-
Notifications
You must be signed in to change notification settings - Fork 51
Expand file tree
/
Copy pathdocument.js
More file actions
133 lines (111 loc) · 3.28 KB
/
document.js
File metadata and controls
133 lines (111 loc) · 3.28 KB
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import { DOCUMENT_NODE } from 'domconstants/constants';
import { setParentNode } from './utils.js';
import { childNodes, documentElement, nodeName, ownerDocument, __chunks__ } from './symbols.js';
import Attribute from './attribute.js';
import Comment from './comment.js';
import DocumentFragment from './document-fragment.js';
import DocumentType from './document-type.js';
import Element from './element.js';
import Event from './event.js';
import SVGElement from './svg-element.js';
import Parent from './parent.js';
import Range from './range.js';
import Text from './text.js';
import TreeWalker from './tree-walker.js';
const doctype = Symbol('doctype');
const head = Symbol('head');
const body = Symbol('body');
const defaultView = Object.create(globalThis, {
Event: { value: Event },
});
/** @typedef {import("./attribute.js").Attribute} Attribute */
export default class Document extends Parent {
constructor(type = 'html') {
super(DOCUMENT_NODE, null)[nodeName] = '#document';
this[documentElement] = null;
this[doctype] = null;
this[head] = null;
this[body] = null;
this[__chunks__] = false;
if (type === 'html') {
const html = (this[documentElement] = new Element(type, this));
this[childNodes] = [
(this[doctype] = new DocumentType(type, this)),
html
].map(setParentNode, this)
html[childNodes] = [
(this[head] = new Element('head', this)),
(this[body] = new Element('body', this)),
].map(setParentNode, html);
}
}
/** @type {globalThis} */
get defaultView() {
return defaultView;
}
/** @type {import("./document-type.js").default?} */
get doctype() {
return this[doctype];
}
/** @type {import("./element.js").default?} */
get documentElement() {
return this[documentElement];
}
/** @type {import("./element.js").default?} */
get head() {
return this[head];
}
/** @type {import("./element.js").default?} */
get body() {
return this[body];
}
/** @type {Attribute} */
createAttribute(name) {
const attribute = new Attribute(name);
attribute[ownerDocument] = this;
return attribute;
}
/** @type {import("./comment.js").default} */
createComment(data) {
return new Comment(data, this);
}
/** @type {import("./document-fragment.js").default} */
createDocumentFragment() {
return new DocumentFragment(this);
}
/** @type {import("./element.js").default} */
createElement(name, options = null) {
const element = new Element(name, this);
if (options?.is) element.setAttribute('is', options.is);
return element;
}
/** @type {import("./svg-element.js").default} */
createElementNS(_, name) {
return new SVGElement(name, this);
}
/** @type {globalThis.Range} */
createRange() {
return new Range;
}
/** @type {import("./text.js").default} */
createTextNode(data) {
return new Text(data, this);
}
/** @type {globalThis.TreeWalker} */
createTreeWalker(parent, accept) {
return new TreeWalker(parent, accept);
}
/**
* Same as `document.importNode`
* @template T
* @param {T} externalNode
* @param {boolean} deep
* @returns {T}
*/
importNode(externalNode, deep = false) {
return externalNode.cloneNode(deep);
}
toString() {
return this[childNodes].join('');
}
}