@remote-dom/polyfill 0.0.0-preview-20240219211553
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/LICENSE.md +7 -0
- package/README.md +45 -0
- package/build/esm/Attr.mjs +52 -0
- package/build/esm/CharacterData.mjs +27 -0
- package/build/esm/ChildNode.mjs +42 -0
- package/build/esm/Comment.mjs +9 -0
- package/build/esm/CustomElementRegistry.mjs +33 -0
- package/build/esm/CustomEvent.mjs +26 -0
- package/build/esm/Document.mjs +89 -0
- package/build/esm/DocumentFragment.mjs +10 -0
- package/build/esm/Element.mjs +95 -0
- package/build/esm/Event.mjs +108 -0
- package/build/esm/EventTarget.mjs +99 -0
- package/build/esm/HTMLElement.mjs +5 -0
- package/build/esm/HTMLTemplateElement.mjs +24 -0
- package/build/esm/MutationObserver.mjs +5 -0
- package/build/esm/NamedNodeMap.mjs +121 -0
- package/build/esm/Node.mjs +100 -0
- package/build/esm/NodeList.mjs +7 -0
- package/build/esm/ParentNode.mjs +128 -0
- package/build/esm/SVGElement.mjs +17 -0
- package/build/esm/Text.mjs +9 -0
- package/build/esm/Window.mjs +66 -0
- package/build/esm/constants.mjs +39 -0
- package/build/esm/hooks.mjs +3 -0
- package/build/esm/index.mjs +2 -0
- package/build/esm/selectors.mjs +197 -0
- package/build/esm/serialization.mjs +92 -0
- package/build/esm/shared.mjs +55 -0
- package/build/esnext/Attr.esnext +57 -0
- package/build/esnext/CharacterData.esnext +27 -0
- package/build/esnext/ChildNode.esnext +47 -0
- package/build/esnext/Comment.esnext +9 -0
- package/build/esnext/CustomElementRegistry.esnext +34 -0
- package/build/esnext/CustomEvent.esnext +25 -0
- package/build/esnext/Document.esnext +86 -0
- package/build/esnext/DocumentFragment.esnext +10 -0
- package/build/esnext/Element.esnext +99 -0
- package/build/esnext/Event.esnext +109 -0
- package/build/esnext/EventTarget.esnext +99 -0
- package/build/esnext/HTMLElement.esnext +6 -0
- package/build/esnext/HTMLTemplateElement.esnext +26 -0
- package/build/esnext/MutationObserver.esnext +5 -0
- package/build/esnext/NamedNodeMap.esnext +131 -0
- package/build/esnext/Node.esnext +116 -0
- package/build/esnext/NodeList.esnext +7 -0
- package/build/esnext/ParentNode.esnext +138 -0
- package/build/esnext/SVGElement.esnext +17 -0
- package/build/esnext/Text.esnext +9 -0
- package/build/esnext/Window.esnext +59 -0
- package/build/esnext/constants.esnext +37 -0
- package/build/esnext/hooks.esnext +3 -0
- package/build/esnext/index.esnext +2 -0
- package/build/esnext/selectors.esnext +169 -0
- package/build/esnext/serialization.esnext +76 -0
- package/build/esnext/shared.esnext +59 -0
- package/build/tsconfig.tsbuildinfo +1 -0
- package/build/typescript/Attr.d.ts +24 -0
- package/build/typescript/Attr.d.ts.map +1 -0
- package/build/typescript/CharacterData.d.ts +10 -0
- package/build/typescript/CharacterData.d.ts.map +1 -0
- package/build/typescript/ChildNode.d.ts +10 -0
- package/build/typescript/ChildNode.d.ts.map +1 -0
- package/build/typescript/Comment.d.ts +7 -0
- package/build/typescript/Comment.d.ts.map +1 -0
- package/build/typescript/CustomElementRegistry.d.ts +9 -0
- package/build/typescript/CustomElementRegistry.d.ts.map +1 -0
- package/build/typescript/CustomEvent.d.ts +17 -0
- package/build/typescript/CustomEvent.d.ts.map +1 -0
- package/build/typescript/Document.d.ts +27 -0
- package/build/typescript/Document.d.ts.map +1 -0
- package/build/typescript/DocumentFragment.d.ts +8 -0
- package/build/typescript/DocumentFragment.d.ts.map +1 -0
- package/build/typescript/Element.d.ts +32 -0
- package/build/typescript/Element.d.ts.map +1 -0
- package/build/typescript/Event.d.ts +47 -0
- package/build/typescript/Event.d.ts.map +1 -0
- package/build/typescript/EventTarget.d.ts +12 -0
- package/build/typescript/EventTarget.d.ts.map +1 -0
- package/build/typescript/HTMLElement.d.ts +4 -0
- package/build/typescript/HTMLElement.d.ts.map +1 -0
- package/build/typescript/HTMLTemplateElement.d.ts +11 -0
- package/build/typescript/HTMLTemplateElement.d.ts.map +1 -0
- package/build/typescript/MutationObserver.d.ts +3 -0
- package/build/typescript/MutationObserver.d.ts.map +1 -0
- package/build/typescript/NamedNodeMap.d.ts +18 -0
- package/build/typescript/NamedNodeMap.d.ts.map +1 -0
- package/build/typescript/Node.d.ts +37 -0
- package/build/typescript/Node.d.ts.map +1 -0
- package/build/typescript/NodeList.d.ts +4 -0
- package/build/typescript/NodeList.d.ts.map +1 -0
- package/build/typescript/ParentNode.d.ts +18 -0
- package/build/typescript/ParentNode.d.ts.map +1 -0
- package/build/typescript/SVGElement.d.ts +7 -0
- package/build/typescript/SVGElement.d.ts.map +1 -0
- package/build/typescript/Text.d.ts +7 -0
- package/build/typescript/Text.d.ts.map +1 -0
- package/build/typescript/Window.d.ts +45 -0
- package/build/typescript/Window.d.ts.map +1 -0
- package/build/typescript/constants.d.ts +35 -0
- package/build/typescript/constants.d.ts.map +1 -0
- package/build/typescript/hooks.d.ts +13 -0
- package/build/typescript/hooks.d.ts.map +1 -0
- package/build/typescript/index.d.ts +3 -0
- package/build/typescript/index.d.ts.map +1 -0
- package/build/typescript/selectors.d.ts +32 -0
- package/build/typescript/selectors.d.ts.map +1 -0
- package/build/typescript/serialization.d.ts +6 -0
- package/build/typescript/serialization.d.ts.map +1 -0
- package/build/typescript/shared.d.ts +16 -0
- package/build/typescript/shared.d.ts.map +1 -0
- package/package.json +35 -0
- package/rollup.config.js +3 -0
- package/source/Attr.ts +70 -0
- package/source/CharacterData.ts +29 -0
- package/source/ChildNode.ts +45 -0
- package/source/Comment.ts +7 -0
- package/source/CustomElementRegistry.ts +52 -0
- package/source/CustomEvent.ts +30 -0
- package/source/Document.ts +112 -0
- package/source/DocumentFragment.ts +8 -0
- package/source/Element.ts +119 -0
- package/source/Event.ts +142 -0
- package/source/EventTarget.ts +139 -0
- package/source/HTMLElement.ts +3 -0
- package/source/HTMLTemplateElement.ts +28 -0
- package/source/MutationObserver.ts +3 -0
- package/source/NamedNodeMap.ts +156 -0
- package/source/Node.ts +139 -0
- package/source/NodeList.ts +5 -0
- package/source/ParentNode.ts +158 -0
- package/source/SVGElement.ts +16 -0
- package/source/Text.ts +7 -0
- package/source/Window.ts +64 -0
- package/source/constants.ts +37 -0
- package/source/hooks.ts +28 -0
- package/source/index.ts +2 -0
- package/source/selectors.ts +230 -0
- package/source/serialization.ts +110 -0
- package/source/shared.ts +80 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { CHILD, NEXT, PARENT, PREV } from './constants.mjs';
|
|
2
|
+
import { isElementNode } from './shared.mjs';
|
|
3
|
+
|
|
4
|
+
var Combinator = /*#__PURE__*/function (Combinator) {
|
|
5
|
+
Combinator[Combinator["Descendant"] = 0] = "Descendant";
|
|
6
|
+
Combinator[Combinator["Child"] = 1] = "Child";
|
|
7
|
+
Combinator[Combinator["Sibling"] = 2] = "Sibling";
|
|
8
|
+
Combinator[Combinator["Adjacent"] = 3] = "Adjacent";
|
|
9
|
+
Combinator[Combinator["Inner"] = 4] = "Inner";
|
|
10
|
+
return Combinator;
|
|
11
|
+
}(Combinator || {});
|
|
12
|
+
var MatcherType = /*#__PURE__*/function (MatcherType) {
|
|
13
|
+
MatcherType[MatcherType["Unknown"] = 0] = "Unknown";
|
|
14
|
+
MatcherType[MatcherType["Element"] = 1] = "Element";
|
|
15
|
+
MatcherType[MatcherType["Id"] = 2] = "Id";
|
|
16
|
+
MatcherType[MatcherType["Class"] = 3] = "Class";
|
|
17
|
+
MatcherType[MatcherType["Attribute"] = 4] = "Attribute";
|
|
18
|
+
MatcherType[MatcherType["Pseudo"] = 5] = "Pseudo";
|
|
19
|
+
MatcherType[MatcherType["Function"] = 6] = "Function";
|
|
20
|
+
return MatcherType;
|
|
21
|
+
}(MatcherType || {});
|
|
22
|
+
const ELEMENT_SELECTOR_TEST = /[a-z]/;
|
|
23
|
+
function querySelector(within, selector) {
|
|
24
|
+
const parts = parseSelector(selector);
|
|
25
|
+
let result = null;
|
|
26
|
+
const child = within[CHILD];
|
|
27
|
+
if (child && parts[0].matchers.length) {
|
|
28
|
+
walkNodesForSelector(child, parts, node => {
|
|
29
|
+
result = node;
|
|
30
|
+
return false;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
function querySelectorAll(within, selector) {
|
|
36
|
+
const parts = parseSelector(selector);
|
|
37
|
+
const results = [];
|
|
38
|
+
const child = within[CHILD];
|
|
39
|
+
if (child && parts[0].matchers.length) {
|
|
40
|
+
walkNodesForSelector(child, parts, node => {
|
|
41
|
+
results.push(node);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return results;
|
|
45
|
+
}
|
|
46
|
+
function parseSelector(selector) {
|
|
47
|
+
let part = {
|
|
48
|
+
combinator: Combinator.Inner,
|
|
49
|
+
matchers: []
|
|
50
|
+
};
|
|
51
|
+
const parts = [part];
|
|
52
|
+
const tokenizer = /\s*?([>\s+~]?)\s*?(?:(?:\[\s*([^\]=]+)(?:=(['"])(.*?)\3)?\s*\])|([#.]?)([^\s#.[>:]+)|:(\w+)(?:\((.*?)\))?)/gi;
|
|
53
|
+
let token;
|
|
54
|
+
while (token = tokenizer.exec(selector)) {
|
|
55
|
+
// [1]: ancestor/parent/sibling/adjacent
|
|
56
|
+
// [2]: attribute name
|
|
57
|
+
// [4]: attribute value
|
|
58
|
+
// [5]: id/class sigil
|
|
59
|
+
// [6]: id/class name
|
|
60
|
+
// [7]: :pseudo/:function() name
|
|
61
|
+
// [8]: :function(argument) value
|
|
62
|
+
if (token[1]) {
|
|
63
|
+
// Update the combinator on the (now parent) Part:
|
|
64
|
+
if (token[1] === '>') part.combinator = Combinator.Child;else if (token[1] === '+') part.combinator = Combinator.Adjacent;else if (token[1] === '~') part.combinator = Combinator.Sibling;else part.combinator = Combinator.Descendant;
|
|
65
|
+
// Add a new Part for the next selector parts:
|
|
66
|
+
part = {
|
|
67
|
+
combinator: Combinator.Inner,
|
|
68
|
+
matchers: []
|
|
69
|
+
};
|
|
70
|
+
parts.push(part);
|
|
71
|
+
}
|
|
72
|
+
let type = MatcherType.Unknown;
|
|
73
|
+
if (token[2]) {
|
|
74
|
+
type = MatcherType.Attribute;
|
|
75
|
+
} else if (token[5]) {
|
|
76
|
+
type = token[5] === '#' ? MatcherType.Id : MatcherType.Class;
|
|
77
|
+
} else if (token[7]) {
|
|
78
|
+
type = token[8] == null ? MatcherType.Pseudo : MatcherType.Function;
|
|
79
|
+
} else if (token[6] && ELEMENT_SELECTOR_TEST.test(token[6])) {
|
|
80
|
+
type = MatcherType.Element;
|
|
81
|
+
}
|
|
82
|
+
part.matchers.push({
|
|
83
|
+
type,
|
|
84
|
+
name: token[2] || token[6] || token[7],
|
|
85
|
+
value: token[4] ?? token[6] ?? token[8]
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return parts;
|
|
89
|
+
}
|
|
90
|
+
function matchesSelector(element, selector) {
|
|
91
|
+
const parsed = parseSelector(selector);
|
|
92
|
+
let part;
|
|
93
|
+
while (part = parsed.pop()) {
|
|
94
|
+
if (!matchesSelectorPart(element, part)) return false;
|
|
95
|
+
}
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
function walkNodesForSelector(node, parts, callback) {
|
|
99
|
+
if (isElementNode(node)) {
|
|
100
|
+
if (matchesSelectorRecursive(node, parts)) {
|
|
101
|
+
if (callback(node) === false) return false;
|
|
102
|
+
}
|
|
103
|
+
const child = node[CHILD];
|
|
104
|
+
if (child && walkNodesForSelector(child, parts, callback) === false) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const next = node[NEXT];
|
|
109
|
+
if (next && walkNodesForSelector(next, parts, callback) === false) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
function matchesSelectorRecursive(element, parts) {
|
|
115
|
+
const {
|
|
116
|
+
combinator,
|
|
117
|
+
matchers
|
|
118
|
+
} = parts[parts.length - 1];
|
|
119
|
+
if (combinator === Combinator.Inner) {
|
|
120
|
+
if (!matchesSelectorMatcher(element, matchers)) return false;
|
|
121
|
+
const pp = parts.slice(0, -1);
|
|
122
|
+
return pp.length === 0 || matchesSelectorRecursive(element, pp);
|
|
123
|
+
}
|
|
124
|
+
const link = combinator === Combinator.Child || combinator === Combinator.Descendant ? PARENT : PREV;
|
|
125
|
+
let ref = element[link];
|
|
126
|
+
if (!ref || !matchesSelectorMatcher(ref, matchers)) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
if (combinator === Combinator.Descendant || combinator === Combinator.Sibling) {
|
|
130
|
+
while (ref = ref[link]) {
|
|
131
|
+
if (matchesSelectorMatcher(ref, matchers)) {
|
|
132
|
+
const pp = parts.slice(0, -1);
|
|
133
|
+
if (pp.length === 0) return true;
|
|
134
|
+
if (matchesSelectorRecursive(element, pp)) return true;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
function matchesSelectorPart(element, {
|
|
141
|
+
combinator,
|
|
142
|
+
matchers
|
|
143
|
+
}) {
|
|
144
|
+
if (combinator === Combinator.Inner) {
|
|
145
|
+
return matchesSelectorMatcher(element, matchers);
|
|
146
|
+
}
|
|
147
|
+
const link = combinator === Combinator.Child || combinator === Combinator.Descendant ? PARENT : PREV;
|
|
148
|
+
let ref = element[link];
|
|
149
|
+
if (!ref || !matchesSelectorMatcher(ref, matchers)) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
if (combinator === Combinator.Descendant || combinator === Combinator.Sibling) {
|
|
153
|
+
while (ref = ref[link]) {
|
|
154
|
+
if (matchesSelectorMatcher(ref, matchers)) return true;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
function matchesSelectorMatcher(element, matcher) {
|
|
160
|
+
if (!element) return false;
|
|
161
|
+
if (Array.isArray(matcher)) {
|
|
162
|
+
for (const single of matcher) {
|
|
163
|
+
if (matchesSelectorMatcher(element, single) === false) return false;
|
|
164
|
+
}
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
const {
|
|
168
|
+
type,
|
|
169
|
+
name,
|
|
170
|
+
value
|
|
171
|
+
} = matcher;
|
|
172
|
+
switch (type) {
|
|
173
|
+
case MatcherType.Element:
|
|
174
|
+
return element.localName === name;
|
|
175
|
+
case MatcherType.Id:
|
|
176
|
+
return element.getAttribute('id') === name;
|
|
177
|
+
case MatcherType.Class:
|
|
178
|
+
return element.getAttribute('class') === name;
|
|
179
|
+
case MatcherType.Attribute:
|
|
180
|
+
return value == null ? element.hasAttribute(name) : element.getAttribute(name) === value;
|
|
181
|
+
case MatcherType.Pseudo:
|
|
182
|
+
switch (name) {
|
|
183
|
+
default:
|
|
184
|
+
throw Error(`Pseudo :${name} not implemented`);
|
|
185
|
+
}
|
|
186
|
+
case MatcherType.Function:
|
|
187
|
+
switch (name) {
|
|
188
|
+
case 'has':
|
|
189
|
+
return matchesSelector(element, value || '');
|
|
190
|
+
default:
|
|
191
|
+
throw Error(`Function :${name}(${value}) not implemented`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export { parseSelector, querySelector, querySelectorAll };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { CHILD, NEXT, NodeType, DATA, NAME, ATTRIBUTES, VALUE } from './constants.mjs';
|
|
2
|
+
|
|
3
|
+
// const voidElements = {
|
|
4
|
+
// img: true,
|
|
5
|
+
// image: true,
|
|
6
|
+
// };
|
|
7
|
+
// const elementTokenizer =
|
|
8
|
+
// /(?:<([a-z][a-z0-9-:]*)( [^<>'"\n=\s]+=(['"])[^>'"\n]*\3)*\s*(\/?)\s*>|<\/([a-z][a-z0-9-:]*)>|([^&<>]+))/gi;
|
|
9
|
+
// const attributeTokenizer = / ([^<>'"\n=\s]+)=(['"])([^>'"\n]*)\2/g;
|
|
10
|
+
const elementTokenizer = /(?:<([a-z][a-z0-9-:]*)((?:\s[^<>'"=\n\s]+(?:=(['"])[^\n]*?\3|=[^>'"\n\s]*|))*)\s*(\/?)\s*>|<\/([a-z][a-z0-9-:]*)>|<!--(.*?)-->|([^&<>]+))/gi;
|
|
11
|
+
const attributeTokenizer = /\s([^<>'"=\n\s]+)(?:=(['"])([^\n]*?)\2|=([^>'"\n\s]*)|)/g;
|
|
12
|
+
function parseHtml(html, contextNode) {
|
|
13
|
+
const document = contextNode.ownerDocument;
|
|
14
|
+
const root = document.createDocumentFragment();
|
|
15
|
+
const stack = [root];
|
|
16
|
+
let parent = root;
|
|
17
|
+
let token;
|
|
18
|
+
elementTokenizer.lastIndex = 0;
|
|
19
|
+
while (token = elementTokenizer.exec(html)) {
|
|
20
|
+
const tag = token[1];
|
|
21
|
+
if (tag) {
|
|
22
|
+
const node = document.createElement(tag);
|
|
23
|
+
const attrs = token[2];
|
|
24
|
+
attributeTokenizer.lastIndex = 0;
|
|
25
|
+
let t;
|
|
26
|
+
while (t = attributeTokenizer.exec(attrs)) {
|
|
27
|
+
node.setAttribute(t[1], t[3] || t[4] || '');
|
|
28
|
+
}
|
|
29
|
+
parent.append(node);
|
|
30
|
+
// if (voidElements[tag] === true) continue;
|
|
31
|
+
stack.push(parent);
|
|
32
|
+
parent = node;
|
|
33
|
+
} else if (token[5]) {
|
|
34
|
+
parent = stack.pop() || root;
|
|
35
|
+
} else if (token[6]) {
|
|
36
|
+
parent.append(document.createComment(token[6]));
|
|
37
|
+
} else {
|
|
38
|
+
parent.append(token[7]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return root;
|
|
42
|
+
}
|
|
43
|
+
function serializeChildren(parentNode) {
|
|
44
|
+
let out = '';
|
|
45
|
+
let child = parentNode[CHILD];
|
|
46
|
+
while (child) {
|
|
47
|
+
out += serializeNode(child);
|
|
48
|
+
child = child[NEXT];
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
function serializeNode(node) {
|
|
53
|
+
switch (node.nodeType) {
|
|
54
|
+
case NodeType.ELEMENT_NODE:
|
|
55
|
+
{
|
|
56
|
+
const el = node;
|
|
57
|
+
let out = `<${el[NAME]}`;
|
|
58
|
+
let attr = el[ATTRIBUTES]?.[CHILD];
|
|
59
|
+
while (attr) {
|
|
60
|
+
out += ` ${attr[NAME]}`;
|
|
61
|
+
let value = attr[VALUE];
|
|
62
|
+
if (value !== '') {
|
|
63
|
+
value = String(value).replace(/&/g, '&').replace(/"/g, '"');
|
|
64
|
+
out += `="${value}"`;
|
|
65
|
+
}
|
|
66
|
+
attr = attr[NEXT];
|
|
67
|
+
}
|
|
68
|
+
out += '>';
|
|
69
|
+
out += serializeChildren(el);
|
|
70
|
+
// let child = el[CHILD];
|
|
71
|
+
// while (child) {
|
|
72
|
+
// out += serialize(child);
|
|
73
|
+
// child = child[NEXT];
|
|
74
|
+
// }
|
|
75
|
+
out += `</${el[NAME]}>`;
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
case NodeType.TEXT_NODE:
|
|
79
|
+
{
|
|
80
|
+
const text = node;
|
|
81
|
+
return text[DATA].replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
|
|
82
|
+
}
|
|
83
|
+
case NodeType.COMMENT_NODE:
|
|
84
|
+
{
|
|
85
|
+
const text = node;
|
|
86
|
+
return `<!--${text[DATA]}-->`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return '';
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export { parseHtml, serializeChildren, serializeNode };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { DATA, ATTRIBUTES, OWNER_DOCUMENT, NodeType } from './constants.mjs';
|
|
2
|
+
|
|
3
|
+
function isCharacterData(node) {
|
|
4
|
+
return DATA in node;
|
|
5
|
+
}
|
|
6
|
+
function isTextNode(node) {
|
|
7
|
+
return node.nodeType === NodeType.TEXT_NODE;
|
|
8
|
+
}
|
|
9
|
+
function isCommentNode(node) {
|
|
10
|
+
return node.nodeType === NodeType.COMMENT_NODE;
|
|
11
|
+
}
|
|
12
|
+
function isElementNode(node) {
|
|
13
|
+
return node.nodeType === NodeType.ELEMENT_NODE;
|
|
14
|
+
}
|
|
15
|
+
function isDocumentFragmentNode(node) {
|
|
16
|
+
return node.nodeType === NodeType.DOCUMENT_FRAGMENT_NODE;
|
|
17
|
+
}
|
|
18
|
+
function isParentNode(node) {
|
|
19
|
+
return 'appendChild' in node;
|
|
20
|
+
}
|
|
21
|
+
function cloneNode(node, deep, document = node.ownerDocument) {
|
|
22
|
+
if (isTextNode(node)) {
|
|
23
|
+
return document.createTextNode(node.data);
|
|
24
|
+
} else if (isCommentNode(node)) {
|
|
25
|
+
return document.createComment(node.data);
|
|
26
|
+
} else if (isElementNode(node)) {
|
|
27
|
+
const cloned = document.createElement(node.localName);
|
|
28
|
+
if (node[ATTRIBUTES]) {
|
|
29
|
+
for (let i = 0; i < node[ATTRIBUTES].length; i++) {
|
|
30
|
+
const attribute = node[ATTRIBUTES].item(i);
|
|
31
|
+
cloned.setAttributeNS(attribute.namespaceURI, attribute.name, attribute.value);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (deep) {
|
|
35
|
+
for (const child of node.childNodes) {
|
|
36
|
+
cloned.appendChild(cloneNode(child, true, document));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return cloned;
|
|
40
|
+
} else if (isDocumentFragmentNode(node)) {
|
|
41
|
+
const fragment = document.createDocumentFragment();
|
|
42
|
+
if (deep) {
|
|
43
|
+
for (const child of node.childNodes) {
|
|
44
|
+
fragment.appendChild(cloneNode(child, true, document));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return fragment;
|
|
48
|
+
} else {
|
|
49
|
+
const cloned = new node.constructor();
|
|
50
|
+
cloned[OWNER_DOCUMENT] = document;
|
|
51
|
+
return cloned;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { cloneNode, isCharacterData, isCommentNode, isDocumentFragmentNode, isElementNode, isParentNode, isTextNode };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { hooks } from './hooks.esnext';
|
|
2
|
+
import { NodeType, NS, NEXT, VALUE, OWNER_ELEMENT, NAME } from './constants.esnext';
|
|
3
|
+
import { Node } from './Node.esnext';
|
|
4
|
+
|
|
5
|
+
class Attr extends Node {
|
|
6
|
+
nodeType = NodeType.ATTRIBUTE_NODE;
|
|
7
|
+
[NS] = null;
|
|
8
|
+
[NEXT] = null;
|
|
9
|
+
[VALUE];
|
|
10
|
+
[OWNER_ELEMENT] = null;
|
|
11
|
+
isConnected = false;
|
|
12
|
+
constructor(name, value, namespace) {
|
|
13
|
+
super();
|
|
14
|
+
this[NAME] = name;
|
|
15
|
+
this[VALUE] = value;
|
|
16
|
+
if (namespace)
|
|
17
|
+
this[NS] = namespace;
|
|
18
|
+
}
|
|
19
|
+
get nodeName() {
|
|
20
|
+
return this[NAME];
|
|
21
|
+
}
|
|
22
|
+
set nodeName(_readonly) {
|
|
23
|
+
}
|
|
24
|
+
get name() {
|
|
25
|
+
return this[NAME];
|
|
26
|
+
}
|
|
27
|
+
set name(_readonly) {
|
|
28
|
+
}
|
|
29
|
+
get value() {
|
|
30
|
+
return this[VALUE];
|
|
31
|
+
}
|
|
32
|
+
set value(value) {
|
|
33
|
+
const str = String(value);
|
|
34
|
+
this[VALUE] = str;
|
|
35
|
+
const ownerElement = this[OWNER_ELEMENT];
|
|
36
|
+
if (!ownerElement)
|
|
37
|
+
return;
|
|
38
|
+
hooks.setAttribute?.(ownerElement, this[NAME], str, this[NS]);
|
|
39
|
+
}
|
|
40
|
+
get nodeValue() {
|
|
41
|
+
return this.value;
|
|
42
|
+
}
|
|
43
|
+
set nodeValue(value) {
|
|
44
|
+
this.value = value;
|
|
45
|
+
}
|
|
46
|
+
get ownerElement() {
|
|
47
|
+
return this[OWNER_ELEMENT];
|
|
48
|
+
}
|
|
49
|
+
get namespaceURI() {
|
|
50
|
+
return this[NS];
|
|
51
|
+
}
|
|
52
|
+
get specified() {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export { Attr };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { hooks } from './hooks.esnext';
|
|
2
|
+
import { DATA } from './constants.esnext';
|
|
3
|
+
import { ChildNode } from './ChildNode.esnext';
|
|
4
|
+
|
|
5
|
+
class CharacterData extends ChildNode {
|
|
6
|
+
[DATA] = "";
|
|
7
|
+
constructor(data) {
|
|
8
|
+
super();
|
|
9
|
+
this.setData(data);
|
|
10
|
+
}
|
|
11
|
+
setData(data) {
|
|
12
|
+
let str = "";
|
|
13
|
+
if (data != null) {
|
|
14
|
+
str = typeof data === "string" ? data : String(data);
|
|
15
|
+
}
|
|
16
|
+
this[DATA] = str;
|
|
17
|
+
hooks.setText?.(this, str);
|
|
18
|
+
}
|
|
19
|
+
get data() {
|
|
20
|
+
return this[DATA];
|
|
21
|
+
}
|
|
22
|
+
set data(data) {
|
|
23
|
+
this.setData(data);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { CharacterData };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { NEXT } from './constants.esnext';
|
|
2
|
+
import { Node } from './Node.esnext';
|
|
3
|
+
|
|
4
|
+
class ChildNode extends Node {
|
|
5
|
+
remove() {
|
|
6
|
+
const parent = this.parentNode;
|
|
7
|
+
if (!parent)
|
|
8
|
+
return;
|
|
9
|
+
parent.removeChild(this);
|
|
10
|
+
}
|
|
11
|
+
replaceWith(...nodes) {
|
|
12
|
+
const parent = this.parentNode;
|
|
13
|
+
if (!parent)
|
|
14
|
+
return;
|
|
15
|
+
const node = toNode(parent, nodes[0]);
|
|
16
|
+
const next = node[NEXT];
|
|
17
|
+
parent.replaceChild(this, node);
|
|
18
|
+
for (let i = 1; i < nodes.length; i++) {
|
|
19
|
+
parent.insertBefore(toNode(parent, nodes[i]), next);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
before(...nodes) {
|
|
23
|
+
const parent = this.parentNode;
|
|
24
|
+
if (!parent)
|
|
25
|
+
return;
|
|
26
|
+
for (const node of nodes) {
|
|
27
|
+
parent.insertBefore(toNode(parent, node), this);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
after(...nodes) {
|
|
31
|
+
const parent = this.parentNode;
|
|
32
|
+
if (!parent)
|
|
33
|
+
return;
|
|
34
|
+
const next = this[NEXT];
|
|
35
|
+
for (const node of nodes) {
|
|
36
|
+
parent.insertBefore(toNode(parent, node), next);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function toNode(parent, node) {
|
|
41
|
+
if (node instanceof Node)
|
|
42
|
+
return node;
|
|
43
|
+
const ownerDocument = parent.ownerDocument;
|
|
44
|
+
return ownerDocument.createTextNode(String(node));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { ChildNode, toNode };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
class CustomElementRegistryImplementation {
|
|
2
|
+
registry = /* @__PURE__ */ new Map();
|
|
3
|
+
listenersByName = /* @__PURE__ */ new Map();
|
|
4
|
+
define(name, Constructor, _options) {
|
|
5
|
+
this.registry.set(name, Constructor);
|
|
6
|
+
const listeners = this.listenersByName.get(name);
|
|
7
|
+
if (listeners == null)
|
|
8
|
+
return;
|
|
9
|
+
this.listenersByName.delete(name);
|
|
10
|
+
for (const listener of listeners) {
|
|
11
|
+
listener(Constructor);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
get(name) {
|
|
15
|
+
return this.registry.get(name);
|
|
16
|
+
}
|
|
17
|
+
whenDefined(name) {
|
|
18
|
+
const Constructor = this.registry.get(name);
|
|
19
|
+
if (Constructor != null)
|
|
20
|
+
return Promise.resolve(Constructor);
|
|
21
|
+
let listeners = this.listenersByName.get(name);
|
|
22
|
+
if (listeners == null) {
|
|
23
|
+
listeners = [];
|
|
24
|
+
this.listenersByName.set(name, listeners);
|
|
25
|
+
}
|
|
26
|
+
return new Promise((resolve) => {
|
|
27
|
+
listeners.push(resolve);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
upgrade(_root) {
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { CustomElementRegistryImplementation };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Event } from './Event.esnext';
|
|
2
|
+
|
|
3
|
+
class CustomEvent extends Event {
|
|
4
|
+
/**
|
|
5
|
+
* Returns any custom data event was created with. Typically used for synthetic events.
|
|
6
|
+
*
|
|
7
|
+
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/CustomEvent/detail)
|
|
8
|
+
*/
|
|
9
|
+
detail;
|
|
10
|
+
constructor(type, eventInitDict) {
|
|
11
|
+
super(type, eventInitDict);
|
|
12
|
+
this.detail = eventInitDict?.detail;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Returns any custom data event was created with. Typically used for synthetic events.
|
|
16
|
+
*
|
|
17
|
+
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/CustomEvent/detail)
|
|
18
|
+
*/
|
|
19
|
+
initCustomEvent(type, bubbles, cancelable, detail) {
|
|
20
|
+
super.initEvent(type, bubbles, cancelable);
|
|
21
|
+
this.detail = detail;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { CustomEvent };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { OWNER_DOCUMENT, NodeType, NAME, NamespaceURI, NS } from './constants.esnext';
|
|
2
|
+
import { Event } from './Event.esnext';
|
|
3
|
+
import { ParentNode } from './ParentNode.esnext';
|
|
4
|
+
import { Element } from './Element.esnext';
|
|
5
|
+
import { SVGElement } from './SVGElement.esnext';
|
|
6
|
+
import { Text } from './Text.esnext';
|
|
7
|
+
import { Comment } from './Comment.esnext';
|
|
8
|
+
import { DocumentFragment } from './DocumentFragment.esnext';
|
|
9
|
+
import { HTMLTemplateElement } from './HTMLTemplateElement.esnext';
|
|
10
|
+
import { cloneNode, isParentNode } from './shared.esnext';
|
|
11
|
+
|
|
12
|
+
class Document extends ParentNode {
|
|
13
|
+
constructor(defaultView) {
|
|
14
|
+
super();
|
|
15
|
+
this.defaultView = defaultView;
|
|
16
|
+
this[OWNER_DOCUMENT] = this;
|
|
17
|
+
}
|
|
18
|
+
nodeType = NodeType.DOCUMENT_NODE;
|
|
19
|
+
[NAME] = "#document";
|
|
20
|
+
createElement(localName) {
|
|
21
|
+
const lowerName = String(localName).toLowerCase();
|
|
22
|
+
if (lowerName === "template") {
|
|
23
|
+
return createElement(new HTMLTemplateElement(), this, "template");
|
|
24
|
+
}
|
|
25
|
+
const CustomElement = this.defaultView.customElements.get(localName);
|
|
26
|
+
if (CustomElement) {
|
|
27
|
+
return createElement(new CustomElement(), this, localName);
|
|
28
|
+
} else {
|
|
29
|
+
return createElement(new Element(), this, localName);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
createElementNS(localName, namespaceURI) {
|
|
33
|
+
if (namespaceURI === NamespaceURI.SVG) {
|
|
34
|
+
return createElement(new SVGElement(), this, localName);
|
|
35
|
+
}
|
|
36
|
+
return createElement(new Element(), this, localName, namespaceURI);
|
|
37
|
+
}
|
|
38
|
+
createTextNode(data) {
|
|
39
|
+
return createNode(new Text(data), this);
|
|
40
|
+
}
|
|
41
|
+
createComment(data) {
|
|
42
|
+
return createNode(new Comment(data), this);
|
|
43
|
+
}
|
|
44
|
+
createDocumentFragment() {
|
|
45
|
+
return createNode(new DocumentFragment(), this);
|
|
46
|
+
}
|
|
47
|
+
createEvent() {
|
|
48
|
+
return new Event("");
|
|
49
|
+
}
|
|
50
|
+
importNode(node, deep) {
|
|
51
|
+
return cloneNode(node, deep, this);
|
|
52
|
+
}
|
|
53
|
+
adoptNode(node) {
|
|
54
|
+
if (node[OWNER_DOCUMENT] === this)
|
|
55
|
+
return node;
|
|
56
|
+
node.parentNode?.removeChild(node);
|
|
57
|
+
adoptNode(node, this);
|
|
58
|
+
return node;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function createNode(node, ownerDocument) {
|
|
62
|
+
Object.defineProperty(node, OWNER_DOCUMENT, {
|
|
63
|
+
value: ownerDocument,
|
|
64
|
+
writable: true,
|
|
65
|
+
enumerable: false
|
|
66
|
+
});
|
|
67
|
+
return node;
|
|
68
|
+
}
|
|
69
|
+
function createElement(element, ownerDocument, name, namespace) {
|
|
70
|
+
createNode(element, ownerDocument);
|
|
71
|
+
Object.defineProperty(element, NAME, { value: name });
|
|
72
|
+
if (namespace) {
|
|
73
|
+
Object.defineProperty(element, NS, { value: namespace });
|
|
74
|
+
}
|
|
75
|
+
return element;
|
|
76
|
+
}
|
|
77
|
+
function adoptNode(node, document) {
|
|
78
|
+
node[OWNER_DOCUMENT] = document;
|
|
79
|
+
if (isParentNode(node)) {
|
|
80
|
+
for (const child of node.childNodes) {
|
|
81
|
+
adoptNode(child, document);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export { Document, adoptNode, createElement, createNode };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NodeType, NAME, OWNER_DOCUMENT } from './constants.esnext';
|
|
2
|
+
import { ParentNode } from './ParentNode.esnext';
|
|
3
|
+
|
|
4
|
+
class DocumentFragment extends ParentNode {
|
|
5
|
+
nodeType = NodeType.DOCUMENT_FRAGMENT_NODE;
|
|
6
|
+
[NAME] = "#document-fragment";
|
|
7
|
+
[OWNER_DOCUMENT] = window.document;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { DocumentFragment };
|