@playdrop/playdrop-cli 0.12.42 → 0.13.0
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/config/client-meta.json +2 -2
- package/dist/apps/index.d.ts +2 -0
- package/dist/apps/index.js +2 -1
- package/dist/apps/loadCheck.d.ts +4 -1
- package/dist/apps/loadCheck.js +40 -10
- package/dist/apps/staticHtml.d.ts +28 -0
- package/dist/apps/staticHtml.js +343 -0
- package/dist/apps/validate.js +2 -1
- package/dist/commands/devServer.js +19 -0
- package/dist/commands/feedback.d.ts +2 -0
- package/dist/commands/feedback.js +44 -2
- package/dist/commands/upload.d.ts +24 -0
- package/dist/commands/upload.js +122 -4
- package/dist/commands/worker/instrument-evidence.js +1 -1
- package/dist/commands/worker/runtime.d.ts +14 -0
- package/dist/commands/worker/runtime.js +97 -8
- package/dist/commands/worker.d.ts +27 -2
- package/dist/commands/worker.js +688 -146
- package/dist/index.js +7 -0
- package/dist/listingPreflight.js +15 -4
- package/node_modules/@playdrop/api-client/dist/client.d.ts +5 -2
- package/node_modules/@playdrop/api-client/dist/client.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/agent-tasks.d.ts +3 -2
- package/node_modules/@playdrop/api-client/dist/domains/agent-tasks.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/agent-tasks.js +13 -2
- package/node_modules/@playdrop/api-client/dist/domains/apps.d.ts +2 -1
- package/node_modules/@playdrop/api-client/dist/domains/apps.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/me.d.ts +2 -1
- package/node_modules/@playdrop/api-client/dist/domains/me.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/me.js +11 -0
- package/node_modules/@playdrop/api-client/dist/index.d.ts +6 -3
- package/node_modules/@playdrop/api-client/dist/index.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/index.js +14 -2
- package/node_modules/@playdrop/config/client-meta.json +2 -2
- package/node_modules/@playdrop/config/dist/src/constants.d.ts +1 -0
- package/node_modules/@playdrop/config/dist/src/constants.d.ts.map +1 -1
- package/node_modules/@playdrop/config/dist/src/constants.js +1 -0
- package/node_modules/@playdrop/config/dist/tsconfig.tsbuildinfo +1 -1
- package/node_modules/@playdrop/types/dist/api.d.ts +195 -4
- package/node_modules/@playdrop/types/dist/api.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/api.js +25 -2
- package/node_modules/entities/decode-codepoint.d.ts +19 -0
- package/node_modules/entities/decode-codepoint.d.ts.map +1 -0
- package/node_modules/entities/decode-codepoint.js +77 -0
- package/node_modules/entities/decode-codepoint.js.map +1 -0
- package/node_modules/entities/decode.d.ts +209 -0
- package/node_modules/entities/decode.d.ts.map +1 -0
- package/node_modules/entities/decode.js +511 -0
- package/node_modules/entities/decode.js.map +1 -0
- package/node_modules/entities/encode.d.ts +22 -0
- package/node_modules/entities/encode.d.ts.map +1 -0
- package/node_modules/entities/encode.js +73 -0
- package/node_modules/entities/encode.js.map +1 -0
- package/node_modules/entities/escape.d.ts +43 -0
- package/node_modules/entities/escape.d.ts.map +1 -0
- package/node_modules/entities/escape.js +121 -0
- package/node_modules/entities/escape.js.map +1 -0
- package/node_modules/entities/generated/decode-data-html.d.ts +2 -0
- package/node_modules/entities/generated/decode-data-html.d.ts.map +1 -0
- package/node_modules/entities/generated/decode-data-html.js +10 -0
- package/node_modules/entities/generated/decode-data-html.js.map +1 -0
- package/node_modules/entities/generated/decode-data-xml.d.ts +2 -0
- package/node_modules/entities/generated/decode-data-xml.d.ts.map +1 -0
- package/node_modules/entities/generated/decode-data-xml.js +10 -0
- package/node_modules/entities/generated/decode-data-xml.js.map +1 -0
- package/node_modules/entities/generated/encode-html.d.ts +8 -0
- package/node_modules/entities/generated/encode-html.d.ts.map +1 -0
- package/node_modules/entities/generated/encode-html.js +13 -0
- package/node_modules/entities/generated/encode-html.js.map +1 -0
- package/node_modules/entities/index.d.ts +96 -0
- package/node_modules/entities/index.d.ts.map +1 -0
- package/node_modules/entities/index.js +131 -0
- package/node_modules/entities/index.js.map +1 -0
- package/node_modules/entities/package.json +3 -0
- package/node_modules/parse5/common/doctype.d.ts +4 -0
- package/node_modules/parse5/common/doctype.js +118 -0
- package/node_modules/parse5/common/error-codes.d.ts +67 -0
- package/node_modules/parse5/common/error-codes.js +66 -0
- package/node_modules/parse5/common/foreign-content.d.ts +9 -0
- package/node_modules/parse5/common/foreign-content.js +237 -0
- package/node_modules/parse5/common/html.d.ts +289 -0
- package/node_modules/parse5/common/html.js +528 -0
- package/node_modules/parse5/common/token.d.ts +84 -0
- package/node_modules/parse5/common/token.js +24 -0
- package/node_modules/parse5/common/unicode.d.ts +42 -0
- package/node_modules/parse5/common/unicode.js +70 -0
- package/node_modules/parse5/index.d.ts +71 -0
- package/node_modules/parse5/index.js +54 -0
- package/node_modules/parse5/package.json +1 -0
- package/node_modules/parse5/parser/formatting-element-list.d.ts +36 -0
- package/node_modules/parse5/parser/formatting-element-list.js +114 -0
- package/node_modules/parse5/parser/index.d.ts +221 -0
- package/node_modules/parse5/parser/index.js +3240 -0
- package/node_modules/parse5/parser/open-element-stack.d.ts +53 -0
- package/node_modules/parse5/parser/open-element-stack.js +328 -0
- package/node_modules/parse5/serializer/index.d.ts +60 -0
- package/node_modules/parse5/serializer/index.js +172 -0
- package/node_modules/parse5/tokenizer/index.d.ts +247 -0
- package/node_modules/parse5/tokenizer/index.js +2714 -0
- package/node_modules/parse5/tokenizer/preprocessor.d.ts +36 -0
- package/node_modules/parse5/tokenizer/preprocessor.js +200 -0
- package/node_modules/parse5/tree-adapters/default.d.ts +84 -0
- package/node_modules/parse5/tree-adapters/default.js +176 -0
- package/node_modules/parse5/tree-adapters/interface.d.ts +255 -0
- package/node_modules/parse5/tree-adapters/interface.js +2 -0
- package/package.json +7 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { TAG_ID as $ } from '../common/html.js';
|
|
2
|
+
import type { TreeAdapter, TreeAdapterTypeMap } from '../tree-adapters/interface.js';
|
|
3
|
+
export interface StackHandler<T extends TreeAdapterTypeMap> {
|
|
4
|
+
onItemPush: (node: T['parentNode'], tid: number, isTop: boolean) => void;
|
|
5
|
+
onItemPop: (node: T['parentNode'], isTop: boolean) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare class OpenElementStack<T extends TreeAdapterTypeMap> {
|
|
8
|
+
private treeAdapter;
|
|
9
|
+
private handler;
|
|
10
|
+
items: T['parentNode'][];
|
|
11
|
+
tagIDs: $[];
|
|
12
|
+
current: T['parentNode'] | undefined;
|
|
13
|
+
stackTop: number;
|
|
14
|
+
tmplCount: number;
|
|
15
|
+
currentTagId: number | undefined;
|
|
16
|
+
get currentTmplContentOrNode(): T['parentNode'];
|
|
17
|
+
constructor(document: T['document'], treeAdapter: TreeAdapter<T>, handler: StackHandler<T>);
|
|
18
|
+
private _indexOf;
|
|
19
|
+
private _isInTemplate;
|
|
20
|
+
private _updateCurrentElement;
|
|
21
|
+
push(element: T['element'], tagID: $): void;
|
|
22
|
+
pop(): void;
|
|
23
|
+
replace(oldElement: T['element'], newElement: T['element']): void;
|
|
24
|
+
insertAfter(referenceElement: T['element'], newElement: T['element'], newElementID: $): void;
|
|
25
|
+
popUntilTagNamePopped(tagName: $): void;
|
|
26
|
+
shortenToLength(idx: number): void;
|
|
27
|
+
popUntilElementPopped(element: T['element']): void;
|
|
28
|
+
private popUntilPopped;
|
|
29
|
+
popUntilNumberedHeaderPopped(): void;
|
|
30
|
+
popUntilTableCellPopped(): void;
|
|
31
|
+
popAllUpToHtmlElement(): void;
|
|
32
|
+
private _indexOfTagNames;
|
|
33
|
+
private clearBackTo;
|
|
34
|
+
clearBackToTableContext(): void;
|
|
35
|
+
clearBackToTableBodyContext(): void;
|
|
36
|
+
clearBackToTableRowContext(): void;
|
|
37
|
+
remove(element: T['element']): void;
|
|
38
|
+
tryPeekProperlyNestedBodyElement(): T['element'] | null;
|
|
39
|
+
contains(element: T['element']): boolean;
|
|
40
|
+
getCommonAncestor(element: T['element']): T['element'] | null;
|
|
41
|
+
isRootHtmlElementCurrent(): boolean;
|
|
42
|
+
private hasInDynamicScope;
|
|
43
|
+
hasInScope(tagName: $): boolean;
|
|
44
|
+
hasInListItemScope(tagName: $): boolean;
|
|
45
|
+
hasInButtonScope(tagName: $): boolean;
|
|
46
|
+
hasNumberedHeaderInScope(): boolean;
|
|
47
|
+
hasInTableScope(tagName: $): boolean;
|
|
48
|
+
hasTableBodyContextInTableScope(): boolean;
|
|
49
|
+
hasInSelectScope(tagName: $): boolean;
|
|
50
|
+
generateImpliedEndTags(): void;
|
|
51
|
+
generateImpliedEndTagsThoroughly(): void;
|
|
52
|
+
generateImpliedEndTagsWithExclusion(exclusionId: $): void;
|
|
53
|
+
}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OpenElementStack = void 0;
|
|
4
|
+
const html_js_1 = require("../common/html.js");
|
|
5
|
+
//Element utils
|
|
6
|
+
const IMPLICIT_END_TAG_REQUIRED = new Set([html_js_1.TAG_ID.DD, html_js_1.TAG_ID.DT, html_js_1.TAG_ID.LI, html_js_1.TAG_ID.OPTGROUP, html_js_1.TAG_ID.OPTION, html_js_1.TAG_ID.P, html_js_1.TAG_ID.RB, html_js_1.TAG_ID.RP, html_js_1.TAG_ID.RT, html_js_1.TAG_ID.RTC]);
|
|
7
|
+
const IMPLICIT_END_TAG_REQUIRED_THOROUGHLY = new Set([
|
|
8
|
+
...IMPLICIT_END_TAG_REQUIRED,
|
|
9
|
+
html_js_1.TAG_ID.CAPTION,
|
|
10
|
+
html_js_1.TAG_ID.COLGROUP,
|
|
11
|
+
html_js_1.TAG_ID.TBODY,
|
|
12
|
+
html_js_1.TAG_ID.TD,
|
|
13
|
+
html_js_1.TAG_ID.TFOOT,
|
|
14
|
+
html_js_1.TAG_ID.TH,
|
|
15
|
+
html_js_1.TAG_ID.THEAD,
|
|
16
|
+
html_js_1.TAG_ID.TR,
|
|
17
|
+
]);
|
|
18
|
+
const SCOPING_ELEMENTS_HTML = new Set([
|
|
19
|
+
html_js_1.TAG_ID.APPLET,
|
|
20
|
+
html_js_1.TAG_ID.CAPTION,
|
|
21
|
+
html_js_1.TAG_ID.HTML,
|
|
22
|
+
html_js_1.TAG_ID.MARQUEE,
|
|
23
|
+
html_js_1.TAG_ID.OBJECT,
|
|
24
|
+
html_js_1.TAG_ID.TABLE,
|
|
25
|
+
html_js_1.TAG_ID.TD,
|
|
26
|
+
html_js_1.TAG_ID.TEMPLATE,
|
|
27
|
+
html_js_1.TAG_ID.TH,
|
|
28
|
+
]);
|
|
29
|
+
const SCOPING_ELEMENTS_HTML_LIST = new Set([...SCOPING_ELEMENTS_HTML, html_js_1.TAG_ID.OL, html_js_1.TAG_ID.UL]);
|
|
30
|
+
const SCOPING_ELEMENTS_HTML_BUTTON = new Set([...SCOPING_ELEMENTS_HTML, html_js_1.TAG_ID.BUTTON]);
|
|
31
|
+
const SCOPING_ELEMENTS_MATHML = new Set([html_js_1.TAG_ID.ANNOTATION_XML, html_js_1.TAG_ID.MI, html_js_1.TAG_ID.MN, html_js_1.TAG_ID.MO, html_js_1.TAG_ID.MS, html_js_1.TAG_ID.MTEXT]);
|
|
32
|
+
const SCOPING_ELEMENTS_SVG = new Set([html_js_1.TAG_ID.DESC, html_js_1.TAG_ID.FOREIGN_OBJECT, html_js_1.TAG_ID.TITLE]);
|
|
33
|
+
const TABLE_ROW_CONTEXT = new Set([html_js_1.TAG_ID.TR, html_js_1.TAG_ID.TEMPLATE, html_js_1.TAG_ID.HTML]);
|
|
34
|
+
const TABLE_BODY_CONTEXT = new Set([html_js_1.TAG_ID.TBODY, html_js_1.TAG_ID.TFOOT, html_js_1.TAG_ID.THEAD, html_js_1.TAG_ID.TEMPLATE, html_js_1.TAG_ID.HTML]);
|
|
35
|
+
const TABLE_CONTEXT = new Set([html_js_1.TAG_ID.TABLE, html_js_1.TAG_ID.TEMPLATE, html_js_1.TAG_ID.HTML]);
|
|
36
|
+
const TABLE_CELLS = new Set([html_js_1.TAG_ID.TD, html_js_1.TAG_ID.TH]);
|
|
37
|
+
//Stack of open elements
|
|
38
|
+
class OpenElementStack {
|
|
39
|
+
get currentTmplContentOrNode() {
|
|
40
|
+
return this._isInTemplate() ? this.treeAdapter.getTemplateContent(this.current) : this.current;
|
|
41
|
+
}
|
|
42
|
+
constructor(document, treeAdapter, handler) {
|
|
43
|
+
this.treeAdapter = treeAdapter;
|
|
44
|
+
this.handler = handler;
|
|
45
|
+
this.items = [];
|
|
46
|
+
this.tagIDs = [];
|
|
47
|
+
this.stackTop = -1;
|
|
48
|
+
this.tmplCount = 0;
|
|
49
|
+
this.currentTagId = html_js_1.TAG_ID.UNKNOWN;
|
|
50
|
+
this.current = document;
|
|
51
|
+
}
|
|
52
|
+
//Index of element
|
|
53
|
+
_indexOf(element) {
|
|
54
|
+
return this.items.lastIndexOf(element, this.stackTop);
|
|
55
|
+
}
|
|
56
|
+
//Update current element
|
|
57
|
+
_isInTemplate() {
|
|
58
|
+
return this.currentTagId === html_js_1.TAG_ID.TEMPLATE && this.treeAdapter.getNamespaceURI(this.current) === html_js_1.NS.HTML;
|
|
59
|
+
}
|
|
60
|
+
_updateCurrentElement() {
|
|
61
|
+
this.current = this.items[this.stackTop];
|
|
62
|
+
this.currentTagId = this.tagIDs[this.stackTop];
|
|
63
|
+
}
|
|
64
|
+
//Mutations
|
|
65
|
+
push(element, tagID) {
|
|
66
|
+
this.stackTop++;
|
|
67
|
+
this.items[this.stackTop] = element;
|
|
68
|
+
this.current = element;
|
|
69
|
+
this.tagIDs[this.stackTop] = tagID;
|
|
70
|
+
this.currentTagId = tagID;
|
|
71
|
+
if (this._isInTemplate()) {
|
|
72
|
+
this.tmplCount++;
|
|
73
|
+
}
|
|
74
|
+
this.handler.onItemPush(element, tagID, true);
|
|
75
|
+
}
|
|
76
|
+
pop() {
|
|
77
|
+
const popped = this.current;
|
|
78
|
+
if (this.tmplCount > 0 && this._isInTemplate()) {
|
|
79
|
+
this.tmplCount--;
|
|
80
|
+
}
|
|
81
|
+
this.stackTop--;
|
|
82
|
+
this._updateCurrentElement();
|
|
83
|
+
this.handler.onItemPop(popped, true);
|
|
84
|
+
}
|
|
85
|
+
replace(oldElement, newElement) {
|
|
86
|
+
const idx = this._indexOf(oldElement);
|
|
87
|
+
this.items[idx] = newElement;
|
|
88
|
+
if (idx === this.stackTop) {
|
|
89
|
+
this.current = newElement;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
insertAfter(referenceElement, newElement, newElementID) {
|
|
93
|
+
const insertionIdx = this._indexOf(referenceElement) + 1;
|
|
94
|
+
this.items.splice(insertionIdx, 0, newElement);
|
|
95
|
+
this.tagIDs.splice(insertionIdx, 0, newElementID);
|
|
96
|
+
this.stackTop++;
|
|
97
|
+
if (insertionIdx === this.stackTop) {
|
|
98
|
+
this._updateCurrentElement();
|
|
99
|
+
}
|
|
100
|
+
if (this.current && this.currentTagId !== undefined) {
|
|
101
|
+
this.handler.onItemPush(this.current, this.currentTagId, insertionIdx === this.stackTop);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
popUntilTagNamePopped(tagName) {
|
|
105
|
+
let targetIdx = this.stackTop + 1;
|
|
106
|
+
do {
|
|
107
|
+
targetIdx = this.tagIDs.lastIndexOf(tagName, targetIdx - 1);
|
|
108
|
+
} while (targetIdx > 0 && this.treeAdapter.getNamespaceURI(this.items[targetIdx]) !== html_js_1.NS.HTML);
|
|
109
|
+
this.shortenToLength(Math.max(targetIdx, 0));
|
|
110
|
+
}
|
|
111
|
+
shortenToLength(idx) {
|
|
112
|
+
while (this.stackTop >= idx) {
|
|
113
|
+
const popped = this.current;
|
|
114
|
+
if (this.tmplCount > 0 && this._isInTemplate()) {
|
|
115
|
+
this.tmplCount -= 1;
|
|
116
|
+
}
|
|
117
|
+
this.stackTop--;
|
|
118
|
+
this._updateCurrentElement();
|
|
119
|
+
this.handler.onItemPop(popped, this.stackTop < idx);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
popUntilElementPopped(element) {
|
|
123
|
+
const idx = this._indexOf(element);
|
|
124
|
+
this.shortenToLength(Math.max(idx, 0));
|
|
125
|
+
}
|
|
126
|
+
popUntilPopped(tagNames, targetNS) {
|
|
127
|
+
const idx = this._indexOfTagNames(tagNames, targetNS);
|
|
128
|
+
this.shortenToLength(Math.max(idx, 0));
|
|
129
|
+
}
|
|
130
|
+
popUntilNumberedHeaderPopped() {
|
|
131
|
+
this.popUntilPopped(html_js_1.NUMBERED_HEADERS, html_js_1.NS.HTML);
|
|
132
|
+
}
|
|
133
|
+
popUntilTableCellPopped() {
|
|
134
|
+
this.popUntilPopped(TABLE_CELLS, html_js_1.NS.HTML);
|
|
135
|
+
}
|
|
136
|
+
popAllUpToHtmlElement() {
|
|
137
|
+
//NOTE: here we assume that the root <html> element is always first in the open element stack, so
|
|
138
|
+
//we perform this fast stack clean up.
|
|
139
|
+
this.tmplCount = 0;
|
|
140
|
+
this.shortenToLength(1);
|
|
141
|
+
}
|
|
142
|
+
_indexOfTagNames(tagNames, namespace) {
|
|
143
|
+
for (let i = this.stackTop; i >= 0; i--) {
|
|
144
|
+
if (tagNames.has(this.tagIDs[i]) && this.treeAdapter.getNamespaceURI(this.items[i]) === namespace) {
|
|
145
|
+
return i;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return -1;
|
|
149
|
+
}
|
|
150
|
+
clearBackTo(tagNames, targetNS) {
|
|
151
|
+
const idx = this._indexOfTagNames(tagNames, targetNS);
|
|
152
|
+
this.shortenToLength(idx + 1);
|
|
153
|
+
}
|
|
154
|
+
clearBackToTableContext() {
|
|
155
|
+
this.clearBackTo(TABLE_CONTEXT, html_js_1.NS.HTML);
|
|
156
|
+
}
|
|
157
|
+
clearBackToTableBodyContext() {
|
|
158
|
+
this.clearBackTo(TABLE_BODY_CONTEXT, html_js_1.NS.HTML);
|
|
159
|
+
}
|
|
160
|
+
clearBackToTableRowContext() {
|
|
161
|
+
this.clearBackTo(TABLE_ROW_CONTEXT, html_js_1.NS.HTML);
|
|
162
|
+
}
|
|
163
|
+
remove(element) {
|
|
164
|
+
const idx = this._indexOf(element);
|
|
165
|
+
if (idx >= 0) {
|
|
166
|
+
if (idx === this.stackTop) {
|
|
167
|
+
this.pop();
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
this.items.splice(idx, 1);
|
|
171
|
+
this.tagIDs.splice(idx, 1);
|
|
172
|
+
this.stackTop--;
|
|
173
|
+
this._updateCurrentElement();
|
|
174
|
+
this.handler.onItemPop(element, false);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
//Search
|
|
179
|
+
tryPeekProperlyNestedBodyElement() {
|
|
180
|
+
//Properly nested <body> element (should be second element in stack).
|
|
181
|
+
return this.stackTop >= 1 && this.tagIDs[1] === html_js_1.TAG_ID.BODY ? this.items[1] : null;
|
|
182
|
+
}
|
|
183
|
+
contains(element) {
|
|
184
|
+
return this._indexOf(element) > -1;
|
|
185
|
+
}
|
|
186
|
+
getCommonAncestor(element) {
|
|
187
|
+
const elementIdx = this._indexOf(element) - 1;
|
|
188
|
+
return elementIdx >= 0 ? this.items[elementIdx] : null;
|
|
189
|
+
}
|
|
190
|
+
isRootHtmlElementCurrent() {
|
|
191
|
+
return this.stackTop === 0 && this.tagIDs[0] === html_js_1.TAG_ID.HTML;
|
|
192
|
+
}
|
|
193
|
+
//Element in scope
|
|
194
|
+
hasInDynamicScope(tagName, htmlScope) {
|
|
195
|
+
for (let i = this.stackTop; i >= 0; i--) {
|
|
196
|
+
const tn = this.tagIDs[i];
|
|
197
|
+
switch (this.treeAdapter.getNamespaceURI(this.items[i])) {
|
|
198
|
+
case html_js_1.NS.HTML: {
|
|
199
|
+
if (tn === tagName)
|
|
200
|
+
return true;
|
|
201
|
+
if (htmlScope.has(tn))
|
|
202
|
+
return false;
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
case html_js_1.NS.SVG: {
|
|
206
|
+
if (SCOPING_ELEMENTS_SVG.has(tn))
|
|
207
|
+
return false;
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
case html_js_1.NS.MATHML: {
|
|
211
|
+
if (SCOPING_ELEMENTS_MATHML.has(tn))
|
|
212
|
+
return false;
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
hasInScope(tagName) {
|
|
220
|
+
return this.hasInDynamicScope(tagName, SCOPING_ELEMENTS_HTML);
|
|
221
|
+
}
|
|
222
|
+
hasInListItemScope(tagName) {
|
|
223
|
+
return this.hasInDynamicScope(tagName, SCOPING_ELEMENTS_HTML_LIST);
|
|
224
|
+
}
|
|
225
|
+
hasInButtonScope(tagName) {
|
|
226
|
+
return this.hasInDynamicScope(tagName, SCOPING_ELEMENTS_HTML_BUTTON);
|
|
227
|
+
}
|
|
228
|
+
hasNumberedHeaderInScope() {
|
|
229
|
+
for (let i = this.stackTop; i >= 0; i--) {
|
|
230
|
+
const tn = this.tagIDs[i];
|
|
231
|
+
switch (this.treeAdapter.getNamespaceURI(this.items[i])) {
|
|
232
|
+
case html_js_1.NS.HTML: {
|
|
233
|
+
if (html_js_1.NUMBERED_HEADERS.has(tn))
|
|
234
|
+
return true;
|
|
235
|
+
if (SCOPING_ELEMENTS_HTML.has(tn))
|
|
236
|
+
return false;
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
case html_js_1.NS.SVG: {
|
|
240
|
+
if (SCOPING_ELEMENTS_SVG.has(tn))
|
|
241
|
+
return false;
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
case html_js_1.NS.MATHML: {
|
|
245
|
+
if (SCOPING_ELEMENTS_MATHML.has(tn))
|
|
246
|
+
return false;
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
hasInTableScope(tagName) {
|
|
254
|
+
for (let i = this.stackTop; i >= 0; i--) {
|
|
255
|
+
if (this.treeAdapter.getNamespaceURI(this.items[i]) !== html_js_1.NS.HTML) {
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
switch (this.tagIDs[i]) {
|
|
259
|
+
case tagName: {
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
case html_js_1.TAG_ID.TABLE:
|
|
263
|
+
case html_js_1.TAG_ID.HTML: {
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
hasTableBodyContextInTableScope() {
|
|
271
|
+
for (let i = this.stackTop; i >= 0; i--) {
|
|
272
|
+
if (this.treeAdapter.getNamespaceURI(this.items[i]) !== html_js_1.NS.HTML) {
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
switch (this.tagIDs[i]) {
|
|
276
|
+
case html_js_1.TAG_ID.TBODY:
|
|
277
|
+
case html_js_1.TAG_ID.THEAD:
|
|
278
|
+
case html_js_1.TAG_ID.TFOOT: {
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
case html_js_1.TAG_ID.TABLE:
|
|
282
|
+
case html_js_1.TAG_ID.HTML: {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
hasInSelectScope(tagName) {
|
|
290
|
+
for (let i = this.stackTop; i >= 0; i--) {
|
|
291
|
+
if (this.treeAdapter.getNamespaceURI(this.items[i]) !== html_js_1.NS.HTML) {
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
switch (this.tagIDs[i]) {
|
|
295
|
+
case tagName: {
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
case html_js_1.TAG_ID.OPTION:
|
|
299
|
+
case html_js_1.TAG_ID.OPTGROUP: {
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
default: {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
//Implied end tags
|
|
310
|
+
generateImpliedEndTags() {
|
|
311
|
+
while (this.currentTagId !== undefined && IMPLICIT_END_TAG_REQUIRED.has(this.currentTagId)) {
|
|
312
|
+
this.pop();
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
generateImpliedEndTagsThoroughly() {
|
|
316
|
+
while (this.currentTagId !== undefined && IMPLICIT_END_TAG_REQUIRED_THOROUGHLY.has(this.currentTagId)) {
|
|
317
|
+
this.pop();
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
generateImpliedEndTagsWithExclusion(exclusionId) {
|
|
321
|
+
while (this.currentTagId !== undefined &&
|
|
322
|
+
this.currentTagId !== exclusionId &&
|
|
323
|
+
IMPLICIT_END_TAG_REQUIRED_THOROUGHLY.has(this.currentTagId)) {
|
|
324
|
+
this.pop();
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
exports.OpenElementStack = OpenElementStack;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { TreeAdapter, TreeAdapterTypeMap } from '../tree-adapters/interface.js';
|
|
2
|
+
import { type DefaultTreeAdapterMap } from '../tree-adapters/default.js';
|
|
3
|
+
export interface SerializerOptions<T extends TreeAdapterTypeMap> {
|
|
4
|
+
/**
|
|
5
|
+
* Specifies input tree format.
|
|
6
|
+
*
|
|
7
|
+
* @default `treeAdapters.default`
|
|
8
|
+
*/
|
|
9
|
+
treeAdapter?: TreeAdapter<T>;
|
|
10
|
+
/**
|
|
11
|
+
* The [scripting flag](https://html.spec.whatwg.org/multipage/parsing.html#scripting-flag). If set
|
|
12
|
+
* to `true`, `noscript` element content will not be escaped.
|
|
13
|
+
*
|
|
14
|
+
* @default `true`
|
|
15
|
+
*/
|
|
16
|
+
scriptingEnabled?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Serializes an AST node to an HTML string.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
*
|
|
23
|
+
* ```js
|
|
24
|
+
* const parse5 = require('parse5');
|
|
25
|
+
*
|
|
26
|
+
* const document = parse5.parse('<!DOCTYPE html><html><head></head><body>Hi there!</body></html>');
|
|
27
|
+
*
|
|
28
|
+
* // Serializes a document.
|
|
29
|
+
* const html = parse5.serialize(document);
|
|
30
|
+
*
|
|
31
|
+
* // Serializes the <html> element content.
|
|
32
|
+
* const str = parse5.serialize(document.childNodes[1]);
|
|
33
|
+
*
|
|
34
|
+
* console.log(str); //> '<head></head><body>Hi there!</body>'
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @param node Node to serialize.
|
|
38
|
+
* @param options Serialization options.
|
|
39
|
+
*/
|
|
40
|
+
export declare function serialize<T extends TreeAdapterTypeMap = DefaultTreeAdapterMap>(node: T['parentNode'], options?: SerializerOptions<T>): string;
|
|
41
|
+
/**
|
|
42
|
+
* Serializes an AST element node to an HTML string, including the element node.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
*
|
|
46
|
+
* ```js
|
|
47
|
+
* const parse5 = require('parse5');
|
|
48
|
+
*
|
|
49
|
+
* const document = parse5.parseFragment('<div>Hello, <b>world</b>!</div>');
|
|
50
|
+
*
|
|
51
|
+
* // Serializes the <div> element.
|
|
52
|
+
* const str = parse5.serializeOuter(document.childNodes[0]);
|
|
53
|
+
*
|
|
54
|
+
* console.log(str); //> '<div>Hello, <b>world</b>!</div>'
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @param node Node to serialize.
|
|
58
|
+
* @param options Serialization options.
|
|
59
|
+
*/
|
|
60
|
+
export declare function serializeOuter<T extends TreeAdapterTypeMap = DefaultTreeAdapterMap>(node: T['node'], options?: SerializerOptions<T>): string;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.serialize = serialize;
|
|
4
|
+
exports.serializeOuter = serializeOuter;
|
|
5
|
+
const html_js_1 = require("../common/html.js");
|
|
6
|
+
const escape_1 = require("entities/escape");
|
|
7
|
+
const default_js_1 = require("../tree-adapters/default.js");
|
|
8
|
+
// Sets
|
|
9
|
+
const VOID_ELEMENTS = new Set([
|
|
10
|
+
html_js_1.TAG_NAMES.AREA,
|
|
11
|
+
html_js_1.TAG_NAMES.BASE,
|
|
12
|
+
html_js_1.TAG_NAMES.BASEFONT,
|
|
13
|
+
html_js_1.TAG_NAMES.BGSOUND,
|
|
14
|
+
html_js_1.TAG_NAMES.BR,
|
|
15
|
+
html_js_1.TAG_NAMES.COL,
|
|
16
|
+
html_js_1.TAG_NAMES.EMBED,
|
|
17
|
+
html_js_1.TAG_NAMES.FRAME,
|
|
18
|
+
html_js_1.TAG_NAMES.HR,
|
|
19
|
+
html_js_1.TAG_NAMES.IMG,
|
|
20
|
+
html_js_1.TAG_NAMES.INPUT,
|
|
21
|
+
html_js_1.TAG_NAMES.KEYGEN,
|
|
22
|
+
html_js_1.TAG_NAMES.LINK,
|
|
23
|
+
html_js_1.TAG_NAMES.META,
|
|
24
|
+
html_js_1.TAG_NAMES.PARAM,
|
|
25
|
+
html_js_1.TAG_NAMES.SOURCE,
|
|
26
|
+
html_js_1.TAG_NAMES.TRACK,
|
|
27
|
+
html_js_1.TAG_NAMES.WBR,
|
|
28
|
+
]);
|
|
29
|
+
function isVoidElement(node, options) {
|
|
30
|
+
return (options.treeAdapter.isElementNode(node) &&
|
|
31
|
+
options.treeAdapter.getNamespaceURI(node) === html_js_1.NS.HTML &&
|
|
32
|
+
VOID_ELEMENTS.has(options.treeAdapter.getTagName(node)));
|
|
33
|
+
}
|
|
34
|
+
const defaultOpts = { treeAdapter: default_js_1.defaultTreeAdapter, scriptingEnabled: true };
|
|
35
|
+
/**
|
|
36
|
+
* Serializes an AST node to an HTML string.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
*
|
|
40
|
+
* ```js
|
|
41
|
+
* const parse5 = require('parse5');
|
|
42
|
+
*
|
|
43
|
+
* const document = parse5.parse('<!DOCTYPE html><html><head></head><body>Hi there!</body></html>');
|
|
44
|
+
*
|
|
45
|
+
* // Serializes a document.
|
|
46
|
+
* const html = parse5.serialize(document);
|
|
47
|
+
*
|
|
48
|
+
* // Serializes the <html> element content.
|
|
49
|
+
* const str = parse5.serialize(document.childNodes[1]);
|
|
50
|
+
*
|
|
51
|
+
* console.log(str); //> '<head></head><body>Hi there!</body>'
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* @param node Node to serialize.
|
|
55
|
+
* @param options Serialization options.
|
|
56
|
+
*/
|
|
57
|
+
function serialize(node, options) {
|
|
58
|
+
const opts = Object.assign(Object.assign({}, defaultOpts), options);
|
|
59
|
+
if (isVoidElement(node, opts)) {
|
|
60
|
+
return '';
|
|
61
|
+
}
|
|
62
|
+
return serializeChildNodes(node, opts);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Serializes an AST element node to an HTML string, including the element node.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
*
|
|
69
|
+
* ```js
|
|
70
|
+
* const parse5 = require('parse5');
|
|
71
|
+
*
|
|
72
|
+
* const document = parse5.parseFragment('<div>Hello, <b>world</b>!</div>');
|
|
73
|
+
*
|
|
74
|
+
* // Serializes the <div> element.
|
|
75
|
+
* const str = parse5.serializeOuter(document.childNodes[0]);
|
|
76
|
+
*
|
|
77
|
+
* console.log(str); //> '<div>Hello, <b>world</b>!</div>'
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* @param node Node to serialize.
|
|
81
|
+
* @param options Serialization options.
|
|
82
|
+
*/
|
|
83
|
+
function serializeOuter(node, options) {
|
|
84
|
+
const opts = Object.assign(Object.assign({}, defaultOpts), options);
|
|
85
|
+
return serializeNode(node, opts);
|
|
86
|
+
}
|
|
87
|
+
function serializeChildNodes(parentNode, options) {
|
|
88
|
+
let html = '';
|
|
89
|
+
// Get container of the child nodes
|
|
90
|
+
const container = options.treeAdapter.isElementNode(parentNode) &&
|
|
91
|
+
options.treeAdapter.getTagName(parentNode) === html_js_1.TAG_NAMES.TEMPLATE &&
|
|
92
|
+
options.treeAdapter.getNamespaceURI(parentNode) === html_js_1.NS.HTML
|
|
93
|
+
? options.treeAdapter.getTemplateContent(parentNode)
|
|
94
|
+
: parentNode;
|
|
95
|
+
const childNodes = options.treeAdapter.getChildNodes(container);
|
|
96
|
+
if (childNodes) {
|
|
97
|
+
for (const currentNode of childNodes) {
|
|
98
|
+
html += serializeNode(currentNode, options);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return html;
|
|
102
|
+
}
|
|
103
|
+
function serializeNode(node, options) {
|
|
104
|
+
if (options.treeAdapter.isElementNode(node)) {
|
|
105
|
+
return serializeElement(node, options);
|
|
106
|
+
}
|
|
107
|
+
if (options.treeAdapter.isTextNode(node)) {
|
|
108
|
+
return serializeTextNode(node, options);
|
|
109
|
+
}
|
|
110
|
+
if (options.treeAdapter.isCommentNode(node)) {
|
|
111
|
+
return serializeCommentNode(node, options);
|
|
112
|
+
}
|
|
113
|
+
if (options.treeAdapter.isDocumentTypeNode(node)) {
|
|
114
|
+
return serializeDocumentTypeNode(node, options);
|
|
115
|
+
}
|
|
116
|
+
// Return an empty string for unknown nodes
|
|
117
|
+
return '';
|
|
118
|
+
}
|
|
119
|
+
function serializeElement(node, options) {
|
|
120
|
+
const tn = options.treeAdapter.getTagName(node);
|
|
121
|
+
return `<${tn}${serializeAttributes(node, options)}>${isVoidElement(node, options) ? '' : `${serializeChildNodes(node, options)}</${tn}>`}`;
|
|
122
|
+
}
|
|
123
|
+
function serializeAttributes(node, { treeAdapter }) {
|
|
124
|
+
let html = '';
|
|
125
|
+
for (const attr of treeAdapter.getAttrList(node)) {
|
|
126
|
+
html += ' ';
|
|
127
|
+
if (attr.namespace) {
|
|
128
|
+
switch (attr.namespace) {
|
|
129
|
+
case html_js_1.NS.XML: {
|
|
130
|
+
html += `xml:${attr.name}`;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case html_js_1.NS.XMLNS: {
|
|
134
|
+
if (attr.name !== 'xmlns') {
|
|
135
|
+
html += 'xmlns:';
|
|
136
|
+
}
|
|
137
|
+
html += attr.name;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
case html_js_1.NS.XLINK: {
|
|
141
|
+
html += `xlink:${attr.name}`;
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
default: {
|
|
145
|
+
html += `${attr.prefix}:${attr.name}`;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
html += attr.name;
|
|
151
|
+
}
|
|
152
|
+
html += `="${(0, escape_1.escapeAttribute)(attr.value)}"`;
|
|
153
|
+
}
|
|
154
|
+
return html;
|
|
155
|
+
}
|
|
156
|
+
function serializeTextNode(node, options) {
|
|
157
|
+
const { treeAdapter } = options;
|
|
158
|
+
const content = treeAdapter.getTextNodeContent(node);
|
|
159
|
+
const parent = treeAdapter.getParentNode(node);
|
|
160
|
+
const parentTn = parent && treeAdapter.isElementNode(parent) && treeAdapter.getTagName(parent);
|
|
161
|
+
return parentTn &&
|
|
162
|
+
treeAdapter.getNamespaceURI(parent) === html_js_1.NS.HTML &&
|
|
163
|
+
(0, html_js_1.hasUnescapedText)(parentTn, options.scriptingEnabled)
|
|
164
|
+
? content
|
|
165
|
+
: (0, escape_1.escapeText)(content);
|
|
166
|
+
}
|
|
167
|
+
function serializeCommentNode(node, { treeAdapter }) {
|
|
168
|
+
return `<!--${treeAdapter.getCommentNodeContent(node)}-->`;
|
|
169
|
+
}
|
|
170
|
+
function serializeDocumentTypeNode(node, { treeAdapter }) {
|
|
171
|
+
return `<!DOCTYPE ${treeAdapter.getDocumentTypeNodeName(node)}>`;
|
|
172
|
+
}
|