/
dom-parser.ts
63 lines (54 loc) · 1.58 KB
/
dom-parser.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import { CTOR_KEY } from "../constructor-lock.ts";
import { nodesFromString } from "../deserialize.ts";
import { DocumentType, HTMLDocument } from "./document.ts";
import type { Element } from "./element.ts";
export type DOMParserMimeType =
| "text/html"
| "text/xml"
| "application/xml"
| "application/xhtml+xml"
| "image/svg+xml";
export class DOMParser {
parseFromString(
source: string,
mimeType: DOMParserMimeType,
): HTMLDocument | null {
if (mimeType !== "text/html") {
throw new Error(`DOMParser: "${mimeType}" unimplemented`); // TODO
}
const doc = new HTMLDocument(CTOR_KEY);
const fakeDoc = nodesFromString(source);
let htmlNode: Element | null = null;
let hasDoctype = false;
for (const child of [...fakeDoc.childNodes]) {
doc.appendChild(child);
if (child instanceof DocumentType) {
hasDoctype = true;
} else if (child.nodeName === "HTML") {
htmlNode = <Element> child;
}
}
if (!hasDoctype) {
const docType = new DocumentType("html", "", "", CTOR_KEY);
// doc.insertBefore(docType, doc.firstChild);
if (doc.childNodes.length === 0) {
doc.appendChild(docType);
} else {
doc.insertBefore(docType, doc.childNodes[0]);
}
}
if (htmlNode) {
for (const child of htmlNode.childNodes) {
switch ((<Element> child).tagName) {
case "HEAD":
doc.head = <Element> child;
break;
case "BODY":
doc.body = <Element> child;
break;
}
}
}
return doc;
}
}