Skip to content

Commit acc934b

Browse files
authored
refactor(node): Use tagged union for node types (#804)
This makes it straight-forward for users to consume the types. Also adds a CDATA class. BREAKING: Several classes have become abstract, and their constructors have changed.
1 parent 9250dd5 commit acc934b

File tree

3 files changed

+96
-77
lines changed

3 files changed

+96
-77
lines changed

src/index.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { ElementType } from "domelementtype";
22
import {
3-
Node,
3+
ChildNode,
44
Element,
55
DataNode,
66
Text,
77
Comment,
8-
NodeWithChildren,
8+
CDATA,
99
Document,
1010
ProcessingInstruction,
11+
ParentNode,
1112
} from "./node";
1213

1314
export * from "./node";
@@ -51,12 +52,12 @@ interface ParserInterface {
5152
endIndex: number | null;
5253
}
5354

54-
type Callback = (error: Error | null, dom: Node[]) => void;
55+
type Callback = (error: Error | null, dom: ChildNode[]) => void;
5556
type ElementCallback = (element: Element) => void;
5657

5758
export class DomHandler {
5859
/** The elements of the DOM */
59-
public dom: Node[] = [];
60+
public dom: ChildNode[] = [];
6061

6162
/** The root element for the DOM */
6263
public root = new Document(this.dom);
@@ -74,7 +75,7 @@ export class DomHandler {
7475
private done = false;
7576

7677
/** Stack of open tags. */
77-
protected tagStack: NodeWithChildren[] = [this.root];
78+
protected tagStack: ParentNode[] = [this.root];
7879

7980
/** A data node that is still being written to. */
8081
protected lastNode: DataNode | null = null;
@@ -184,7 +185,7 @@ export class DomHandler {
184185

185186
public oncdatastart(): void {
186187
const text = new Text("");
187-
const node = new NodeWithChildren(ElementType.CDATA, [text]);
188+
const node = new CDATA([text]);
188189

189190
this.addNode(node);
190191

@@ -209,10 +210,10 @@ export class DomHandler {
209210
}
210211
}
211212

212-
protected addNode(node: Node): void {
213+
protected addNode(node: ChildNode): void {
213214
const parent = this.tagStack[this.tagStack.length - 1];
214215
const previousSibling = parent.children[parent.children.length - 1] as
215-
| Node
216+
| ChildNode
216217
| undefined;
217218

218219
if (this.options.withStartIndices) {

src/node.spec.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,11 @@ describe("Nodes", () => {
6565
});
6666

6767
it("should throw an error when cloning unsupported types", () => {
68-
const el = new node.Node(ElementType.Doctype);
68+
class Doctype extends node.Node {
69+
type = ElementType.Doctype;
70+
nodeType = NaN;
71+
}
72+
const el = new Doctype();
6973
expect(() => el.cloneNode()).toThrow("Not implemented yet: doctype");
7074
});
7175

@@ -81,6 +85,21 @@ describe("Nodes", () => {
8185
expect(node.isDirective(result)).toBe(false);
8286
expect(node.isDocument(result)).toBe(false);
8387
});
88+
89+
it("should support using tagged types", () => {
90+
// We want to make sure TS is happy about the tagged types.
91+
const parent: node.ParentNode = new node.Document([]);
92+
93+
function setQuirks(el: node.ParentNode): void {
94+
if (el.type === ElementType.Root) {
95+
el["x-mode"] = "no-quirks";
96+
}
97+
}
98+
99+
setQuirks(parent);
100+
101+
expect(parent).toHaveProperty("x-mode", "no-quirks");
102+
});
84103
});
85104

86105
type Options = DomHandlerOptions & ParserOptions;

0 commit comments

Comments
 (0)