Commit 7a2150f1 authored by David Sveningsson's avatar David Sveningsson
Browse files

feat(events): rename `tag:open` and `tag:close` to `tag:start` and `tag:end`

Matches specs better. The older names will still be supported but deprecated. In
practice it will probably take a really long time before they are removed.
parent cfbf3dce
......@@ -60,7 +60,7 @@ Emitted when a doctype is encountered. `value` is the doctype (without
```plaintext
attr attr
tag:open | tag:ready tag:open | tag:ready
tag:start | tag:ready tag:start | tag:ready
| | / | | /
v vv v vv
<div class="foobar"> <input class="foobar">
......@@ -68,11 +68,13 @@ tag:open | tag:ready tag:open | tag:ready
</div> \
^ element:ready
|\
| element:ready (tag:close not emitted)
| element:ready (tag:end not emitted)
tag:end
```
### `tag:open`
### `tag:start`
- Deprecated alias: `tag:open`
```typescript
{
......@@ -86,7 +88,9 @@ Emitted when a start tag is parsed: `<div>`.
The element will not have its attribute nor children yet.
Use `tag:ready` (all attributes parsed) or `element:ready` (all children parsed) if you need to wait for element to be ready.
### `tag:close`
### `tag:end`
- Deprecated alias: `tag:close`
```typescript
{
......@@ -122,7 +126,7 @@ The children will not yet be parsed.
```
Emitted when an element is fully constructed (including its children).
It is similar to `tag:close` but will be emitted for `void` elements as well.
It is similar to `tag:end` but will be emitted for `void` elements as well.
`target` will be the element.
......
......@@ -364,15 +364,15 @@ describe("Engine", () => {
const lines = engine.dumpEvents(source);
expect(lines).toHaveLength(12);
expect(lines[0].event).toEqual("dom:load");
expect(lines[1].event).toEqual("tag:open");
expect(lines[1].event).toEqual("tag:start");
expect(lines[2].event).toEqual("attr");
expect(lines[3].event).toEqual("tag:ready");
expect(lines[4].event).toEqual("tag:open");
expect(lines[4].event).toEqual("tag:start");
expect(lines[5].event).toEqual("attr");
expect(lines[6].event).toEqual("tag:ready");
expect(lines[7].event).toEqual("tag:close");
expect(lines[7].event).toEqual("tag:end");
expect(lines[8].event).toEqual("element:ready");
expect(lines[9].event).toEqual("tag:close");
expect(lines[9].event).toEqual("tag:end");
expect(lines[10].event).toEqual("element:ready");
expect(lines[11].event).toEqual("dom:ready");
});
......
import { ConfigData, ResolvedConfig, RuleOptions, Severity } from "../config";
import { Location, Source } from "../context";
import { HtmlElement } from "../dom";
import { ConfigReadyEvent, DirectiveEvent, TagCloseEvent, TagOpenEvent } from "../event";
import { ConfigReadyEvent, DirectiveEvent, TagEndEvent, TagStartEvent } from "../event";
import { InvalidTokenError, Lexer, TokenType } from "../lexer";
import { Parser, ParserError } from "../parser";
import { Report, Reporter } from "../reporter";
......@@ -219,7 +219,7 @@ export class Engine<T extends Parser = Parser> {
}
/* enable rules on node */
parser.on("tag:open", (event: string, data: TagOpenEvent) => {
parser.on("tag:start", (event: string, data: TagStartEvent) => {
data.target.enableRules(rules.map((rule) => rule.name));
});
}
......@@ -230,7 +230,7 @@ export class Engine<T extends Parser = Parser> {
}
/* disable rules on node */
parser.on("tag:open", (event: string, data: TagOpenEvent) => {
parser.on("tag:start", (event: string, data: TagStartEvent) => {
data.target.disableRules(rules.map((rule) => rule.name));
});
}
......@@ -241,7 +241,7 @@ export class Engine<T extends Parser = Parser> {
rule.setEnabled(false);
}
const unregisterOpen = parser.on("tag:open", (event: string, data: TagOpenEvent) => {
const unregisterOpen = parser.on("tag:start", (event: string, data: TagStartEvent) => {
/* wait for a tag to open and find the current block by using its parent */
if (directiveBlock === null) {
directiveBlock = data.target.parent?.unique ?? null;
......@@ -252,7 +252,7 @@ export class Engine<T extends Parser = Parser> {
data.target.disableRules(rules.map((rule) => rule.name));
});
const unregisterClose = parser.on("tag:close", (event: string, data: TagCloseEvent) => {
const unregisterClose = parser.on("tag:end", (event: string, data: TagEndEvent) => {
/* if the directive is the last thing in a block no id would be set */
const lastNode = directiveBlock === null;
......@@ -278,12 +278,12 @@ export class Engine<T extends Parser = Parser> {
/* disable rules directly on the node so it will be recorded for later,
* more specifically when using the domtree to trigger errors */
const unregister = parser.on("tag:open", (event: string, data: TagOpenEvent) => {
const unregister = parser.on("tag:start", (event: string, data: TagStartEvent) => {
data.target.disableRules(rules.map((rule) => rule.name));
});
/* disable directive after next event occurs */
parser.once("tag:ready, tag:close, attr", () => {
parser.once("tag:ready, tag:end, attr", () => {
unregister();
parser.defer(() => {
for (const rule of rules) {
......
......@@ -20,24 +20,27 @@ export interface ConfigReadyEvent extends Event {
}
/**
* Event emitted when opening tags are encountered.
* Event emitted when starting tags are encountered.
*/
export interface TagOpenEvent extends Event {
export interface TagStartEvent extends Event {
/** Event location. */
location: Location;
/** The node being opened. */
/** The node being started. */
target: HtmlElement;
}
/** Deprecated alias for TagStartEvent */
export type TagOpenEvent = TagStartEvent;
/**
* Event emitted when close tags `</..>` are encountered.
* Event emitted when end tags `</..>` are encountered.
*/
export interface TagCloseEvent extends Event {
export interface TagEndEvent extends Event {
/** Event location. */
location: Location;
/** Temporary node for the close tag. Can be null for elements left unclosed
/** Temporary node for the end tag. Can be null for elements left unclosed
* when document ends */
target: HtmlElement | null;
......@@ -45,6 +48,9 @@ export interface TagCloseEvent extends Event {
previous: HtmlElement;
}
/** Deprecated alias for TagEndEvent */
export type TagCloseEvent = TagEndEvent;
/**
* Event emitted when a tag is ready (i.e. all the attributes has been
* parsed). The children of the element will not yet be finished.
......
......@@ -61,10 +61,10 @@ describe("parser", () => {
it("simple element", () => {
expect.assertions(5);
parser.parseHtml("<div></div>");
expect(events.shift()).toEqual({ event: "tag:open", target: "div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "div" });
expect(events.shift()).toEqual({ event: "tag:ready", target: "div" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "div",
previous: "div",
});
......@@ -78,10 +78,10 @@ describe("parser", () => {
it("with numbers", () => {
expect.assertions(5);
parser.parseHtml("<h1></h1>");
expect(events.shift()).toEqual({ event: "tag:open", target: "h1" });
expect(events.shift()).toEqual({ event: "tag:start", target: "h1" });
expect(events.shift()).toEqual({ event: "tag:ready", target: "h1" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "h1",
previous: "h1",
});
......@@ -95,10 +95,10 @@ describe("parser", () => {
it("with dashes", () => {
expect.assertions(5);
parser.parseHtml("<foo-bar></foo-bar>");
expect(events.shift()).toEqual({ event: "tag:open", target: "foo-bar" });
expect(events.shift()).toEqual({ event: "tag:start", target: "foo-bar" });
expect(events.shift()).toEqual({ event: "tag:ready", target: "foo-bar" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "foo-bar",
previous: "foo-bar",
});
......@@ -112,12 +112,12 @@ describe("parser", () => {
it("elements closed on wrong order", () => {
expect.assertions(9);
parser.parseHtml("<div><label></div></label>");
expect(events.shift()).toEqual({ event: "tag:open", target: "div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "div" });
expect(events.shift()).toEqual({ event: "tag:ready", target: "div" });
expect(events.shift()).toEqual({ event: "tag:open", target: "label" });
expect(events.shift()).toEqual({ event: "tag:start", target: "label" });
expect(events.shift()).toEqual({ event: "tag:ready", target: "label" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "div",
previous: "label",
});
......@@ -126,7 +126,7 @@ describe("parser", () => {
target: "label",
});
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "label",
previous: "div",
});
......@@ -140,10 +140,10 @@ describe("parser", () => {
it("self-closing elements", () => {
expect.assertions(5);
parser.parseHtml("<input/>");
expect(events.shift()).toEqual({ event: "tag:open", target: "input" });
expect(events.shift()).toEqual({ event: "tag:start", target: "input" });
expect(events.shift()).toEqual({ event: "tag:ready", target: "input" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "input",
previous: "input",
});
......@@ -157,10 +157,10 @@ describe("parser", () => {
it("void elements", () => {
expect.assertions(5);
parser.parseHtml("<input>");
expect(events.shift()).toEqual({ event: "tag:open", target: "input" });
expect(events.shift()).toEqual({ event: "tag:start", target: "input" });
expect(events.shift()).toEqual({ event: "tag:ready", target: "input" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "input",
previous: "input",
});
......@@ -174,10 +174,10 @@ describe("parser", () => {
it("void elements with close tag", () => {
expect.assertions(6);
parser.parseHtml("<input></input>");
expect(events.shift()).toEqual({ event: "tag:open", target: "input" });
expect(events.shift()).toEqual({ event: "tag:start", target: "input" });
expect(events.shift()).toEqual({ event: "tag:ready", target: "input" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "input",
previous: "input",
});
......@@ -186,7 +186,7 @@ describe("parser", () => {
target: "input",
});
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "input",
previous: "#document",
});
......@@ -228,7 +228,7 @@ describe("parser", () => {
it("with newlines", () => {
expect.assertions(6);
parser.parseHtml('<div\nfoo="bar"></div>');
expect(events.shift()).toEqual({ event: "tag:open", target: "div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "div" });
expect(events.shift()).toEqual({
event: "attr",
key: "foo",
......@@ -242,7 +242,7 @@ describe("parser", () => {
});
expect(events.shift()).toEqual({ event: "tag:ready", target: "div" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "div",
previous: "div",
});
......@@ -256,7 +256,7 @@ describe("parser", () => {
it("with newline after attribute", () => {
expect.assertions(7);
parser.parseHtml('<div foo="bar"\nspam="ham"></div>');
expect(events.shift()).toEqual({ event: "tag:open", target: "div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "div" });
expect(events.shift()).toEqual({
event: "attr",
key: "foo",
......@@ -281,7 +281,7 @@ describe("parser", () => {
});
expect(events.shift()).toEqual({ event: "tag:ready", target: "div" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "div",
previous: "div",
});
......@@ -295,10 +295,10 @@ describe("parser", () => {
it("with xml namespaces", () => {
expect.assertions(5);
parser.parseHtml("<foo:div></foo:div>");
expect(events.shift()).toEqual({ event: "tag:open", target: "foo:div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "foo:div" });
expect(events.shift()).toEqual({ event: "tag:ready", target: "foo:div" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "foo:div",
previous: "foo:div",
});
......@@ -338,7 +338,7 @@ describe("parser", () => {
it("without quotes", () => {
expect.assertions(6);
parser.parseHtml("<div foo=bar></div>");
expect(events.shift()).toEqual({ event: "tag:open", target: "div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "div" });
expect(events.shift()).toEqual({
event: "attr",
key: "foo",
......@@ -352,7 +352,7 @@ describe("parser", () => {
});
expect(events.shift()).toEqual({ event: "tag:ready", target: "div" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "div",
previous: "div",
});
......@@ -366,7 +366,7 @@ describe("parser", () => {
it("with single quotes", () => {
expect.assertions(6);
parser.parseHtml("<div foo='bar'></div>");
expect(events.shift()).toEqual({ event: "tag:open", target: "div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "div" });
expect(events.shift()).toEqual({
event: "attr",
key: "foo",
......@@ -380,7 +380,7 @@ describe("parser", () => {
});
expect(events.shift()).toEqual({ event: "tag:ready", target: "div" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "div",
previous: "div",
});
......@@ -394,7 +394,7 @@ describe("parser", () => {
it("with double quote", () => {
expect.assertions(6);
parser.parseHtml('<div foo="bar"></div>');
expect(events.shift()).toEqual({ event: "tag:open", target: "div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "div" });
expect(events.shift()).toEqual({
event: "attr",
key: "foo",
......@@ -408,7 +408,7 @@ describe("parser", () => {
});
expect(events.shift()).toEqual({ event: "tag:ready", target: "div" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "div",
previous: "div",
});
......@@ -422,7 +422,7 @@ describe("parser", () => {
it("with nested quotes", () => {
expect.assertions(7);
parser.parseHtml("<div foo='\"foo\"' bar=\"'foo'\"></div>");
expect(events.shift()).toEqual({ event: "tag:open", target: "div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "div" });
expect(events.shift()).toEqual({
event: "attr",
key: "foo",
......@@ -447,7 +447,7 @@ describe("parser", () => {
});
expect(events.shift()).toEqual({ event: "tag:ready", target: "div" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "div",
previous: "div",
});
......@@ -461,7 +461,7 @@ describe("parser", () => {
it("without value", () => {
expect.assertions(6);
parser.parseHtml("<div foo></div>");
expect(events.shift()).toEqual({ event: "tag:open", target: "div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "div" });
expect(events.shift()).toEqual({
event: "attr",
key: "foo",
......@@ -472,7 +472,7 @@ describe("parser", () => {
});
expect(events.shift()).toEqual({ event: "tag:ready", target: "div" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "div",
previous: "div",
});
......@@ -486,7 +486,7 @@ describe("parser", () => {
it("with empty value", () => {
expect.assertions(7);
parser.parseHtml("<div foo=\"\" bar=''></div>");
expect(events.shift()).toEqual({ event: "tag:open", target: "div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "div" });
expect(events.shift()).toEqual({
event: "attr",
key: "foo",
......@@ -505,7 +505,7 @@ describe("parser", () => {
});
expect(events.shift()).toEqual({ event: "tag:ready", target: "div" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "div",
previous: "div",
});
......@@ -519,7 +519,7 @@ describe("parser", () => {
it("with dashes", () => {
expect.assertions(6);
parser.parseHtml("<div foo-bar-baz></div>");
expect(events.shift()).toEqual({ event: "tag:open", target: "div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "div" });
expect(events.shift()).toEqual({
event: "attr",
key: "foo-bar-baz",
......@@ -530,7 +530,7 @@ describe("parser", () => {
});
expect(events.shift()).toEqual({ event: "tag:ready", target: "div" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "div",
previous: "div",
});
......@@ -544,7 +544,7 @@ describe("parser", () => {
it("with spaces inside", () => {
expect.assertions(6);
parser.parseHtml('<div class="foo bar baz"></div>');
expect(events.shift()).toEqual({ event: "tag:open", target: "div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "div" });
expect(events.shift()).toEqual({
event: "attr",
key: "class",
......@@ -558,7 +558,7 @@ describe("parser", () => {
});
expect(events.shift()).toEqual({ event: "tag:ready", target: "div" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "div",
previous: "div",
});
......@@ -572,7 +572,7 @@ describe("parser", () => {
it("with uncommon characters", () => {
expect.assertions(6);
parser.parseHtml('<div a2?()!="foo"></div>');
expect(events.shift()).toEqual({ event: "tag:open", target: "div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "div" });
expect(events.shift()).toEqual({
event: "attr",
key: "a2?()!",
......@@ -586,7 +586,7 @@ describe("parser", () => {
});
expect(events.shift()).toEqual({ event: "tag:ready", target: "div" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "div",
previous: "div",
});
......@@ -600,7 +600,7 @@ describe("parser", () => {
it("with multiple attributes", () => {
expect.assertions(7);
parser.parseHtml('<div foo="bar" spam="ham"></div>');
expect(events.shift()).toEqual({ event: "tag:open", target: "div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "div" });
expect(events.shift()).toEqual({
event: "attr",
key: "foo",
......@@ -625,7 +625,7 @@ describe("parser", () => {
});
expect(events.shift()).toEqual({ event: "tag:ready", target: "div" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "div",
previous: "div",
});
......@@ -639,7 +639,7 @@ describe("parser", () => {
it("on self-closing elements", () => {
expect.assertions(6);
parser.parseHtml('<input type="text"/>');
expect(events.shift()).toEqual({ event: "tag:open", target: "input" });
expect(events.shift()).toEqual({ event: "tag:start", target: "input" });
expect(events.shift()).toEqual({
event: "attr",
key: "type",
......@@ -653,7 +653,7 @@ describe("parser", () => {
});
expect(events.shift()).toEqual({ event: "tag:ready", target: "input" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "input",
previous: "input",
});
......@@ -667,7 +667,7 @@ describe("parser", () => {
it("with xml namespaces", () => {
expect.assertions(6);
parser.parseHtml('<div foo:bar="baz"></div>');
expect(events.shift()).toEqual({ event: "tag:open", target: "div" });
expect(events.shift()).toEqual({ event: "tag:start", target: "div" });
expect(events.shift()).toEqual({
event: "attr",
key: "foo:bar",
......@@ -681,7 +681,7 @@ describe("parser", () => {
});
expect(events.shift()).toEqual({ event: "tag:ready", target: "div" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "div",
previous: "div",
});
......@@ -770,14 +770,14 @@ describe("parser", () => {
<li><strong>nested</strong>
<li><input>
</ul>`);
expect(events.shift()).toEqual({ event: "tag:open", target: "ul" });
expect(events.shift()).toEqual({ event: "tag:start", target: "ul" });
expect(events.shift()).toEqual({ event: "tag:ready", target: "ul" });
/* 1: explicitly closed <li> */
expect(events.shift()).toEqual({ event: "tag:open", target: "li" });
expect(events.shift()).toEqual({ event: "tag:start", target: "li" });
expect(events.shift()).toEqual({ event: "tag:ready", target: "li" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "li",
previous: "li",
});
......@@ -787,10 +787,10 @@ describe("parser", () => {
});
/* 2: implicitly closed <li> */
expect(events.shift()).toEqual({ event: "tag:open", target: "li" });
expect(events.shift()).toEqual({ event: "tag:start", target: "li" });
expect(events.shift()).toEqual({ event: "tag:ready", target: "li" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "li",
previous: "li",
});
......@@ -800,12 +800,12 @@ describe("parser", () => {
});
/* 3: implicit with children */
expect(events.shift()).toEqual({ event: "tag:open", target: "li" });
expect(events.shift()).toEqual({ event: "tag:start", target: "li" });
expect(events.shift()).toEqual({ event: "tag:ready", target: "li" });
expect(events.shift()).toEqual({ event: "tag:open", target: "strong" });
expect(events.shift()).toEqual({ event: "tag:start", target: "strong" });
expect(events.shift()).toEqual({ event: "tag:ready", target: "strong" });
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "strong",
previous: "strong",
});
......@@ -814,7 +814,7 @@ describe("parser", () => {
target: "strong",
});
expect(events.shift()).toEqual({
event: "tag:close",
event: "tag:end",
target: "li",
previous: "li",
});
......@@ -824,12 +824,12 @@ describe("parser", () => {
});
/* 3: implicit with void */
expect(events.shift()).toEqual({ event: "tag:open", target: "li" });
expect(events.shift()).toEqual({ event: "tag:start", target: "li" });
expect(events.shift()).toEqual({ event: "tag:ready", target: "li" });
expect(events.shift()).toEqual({ event: "tag:open", target: "input" });