@e-mc/document 0.3.2 → 0.4.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/asset.js +11 -11
- package/index.js +1291 -1291
- package/package.json +4 -4
- package/parse/dom.js +256 -256
- package/parse/index.js +1452 -1452
- package/transform/index.js +321 -321
- package/util.js +203 -200
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e-mc/document",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Document constructor for E-mc.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"license": "BSD 3-Clause",
|
|
21
21
|
"homepage": "https://github.com/anpham6/e-mc#readme",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@e-mc/core": "0.
|
|
24
|
-
"@e-mc/db": "0.
|
|
25
|
-
"@e-mc/types": "0.
|
|
23
|
+
"@e-mc/core": "0.4.0",
|
|
24
|
+
"@e-mc/db": "0.4.0",
|
|
25
|
+
"@e-mc/types": "0.4.0",
|
|
26
26
|
"chalk": "4.1.2",
|
|
27
27
|
"htmlparser2": "^8.0.1",
|
|
28
28
|
"js-yaml": "^4.1.0",
|
package/parse/dom.js
CHANGED
|
@@ -1,256 +1,256 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.IGNORE_FLAG = exports.HtmlElement = exports.DomWriter = void 0;
|
|
4
|
-
const htmlparser2 = require("htmlparser2");
|
|
5
|
-
const domhandler = require("domhandler");
|
|
6
|
-
const domutils = require("domutils");
|
|
7
|
-
const types_1 = require("../../types");
|
|
8
|
-
const util_1 = require("../util");
|
|
9
|
-
const index_1 = require("./index");
|
|
10
|
-
Object.defineProperty(exports, "IGNORE_FLAG", { enumerable: true, get: function () { return index_1.IGNORE_FLAG; } });
|
|
11
|
-
const Parser = htmlparser2.Parser;
|
|
12
|
-
const DomHandler = domhandler.DomHandler;
|
|
13
|
-
const TAG_VOID = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
|
|
14
|
-
const REGEXP_VOID = TAG_VOID.map(tagName => new RegExp(`(\\s*)</${tagName}\\s*>` + index_1.XmlWriter.PATTERN_TRAILINGSPACE, 'gi'));
|
|
15
|
-
const REGEXP_TAGNAME = new RegExp(`^${index_1.XmlWriter.PATTERN_TAGNAME}$`);
|
|
16
|
-
const PARSER_OPTIONS = Object.freeze({ xmlMode: false, decodeEntities: false });
|
|
17
|
-
class DomWriter extends index_1.XmlWriter {
|
|
18
|
-
static hasInnerXml(tagName) {
|
|
19
|
-
return !TAG_VOID.includes(tagName);
|
|
20
|
-
}
|
|
21
|
-
static normalize(source, newline, ignoreChar = '', escapeEntities) {
|
|
22
|
-
let ignoreTagGroup;
|
|
23
|
-
if ((0, types_1.isObject)(newline)) {
|
|
24
|
-
({ newline, ignoreChar = '', ignoreTagGroup, escapeEntities } = newline);
|
|
25
|
-
}
|
|
26
|
-
for (const tag of REGEXP_VOID) {
|
|
27
|
-
source = source.replace(tag, (...capture) => index_1.XmlWriter.getNewlineString(capture[1], capture[2], newline));
|
|
28
|
-
}
|
|
29
|
-
const tagGroup = [];
|
|
30
|
-
if (ignoreTagGroup) {
|
|
31
|
-
for (let i = 0, length = ignoreTagGroup.length; i < length; i += 2) {
|
|
32
|
-
const start = ignoreTagGroup[i];
|
|
33
|
-
if (start[0] === '<') {
|
|
34
|
-
tagGroup.push(new RegExp('^' + (0, types_1.escapePattern)(start)));
|
|
35
|
-
}
|
|
36
|
-
const end = ignoreTagGroup[i + 1];
|
|
37
|
-
if (end?.[end.length - 1] === '>') {
|
|
38
|
-
tagGroup.push(new RegExp((0, types_1.escapePattern)(start) + '$'));
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
const pattern = new RegExp(`<(?:!--[\\S\\s]*?--|([^\\s<>/${ignoreChar}]+)(${index_1.XmlWriter.PATTERN_TAGOPEN}*?)(\\s*\\/?\\s*)|\\/([^\\s>]+)(\\s*))>`, 'g');
|
|
43
|
-
let match;
|
|
44
|
-
while (match = pattern.exec(source)) {
|
|
45
|
-
let tag;
|
|
46
|
-
if (match[1]) {
|
|
47
|
-
if (!REGEXP_TAGNAME.test(match[1])) {
|
|
48
|
-
if (match[0][1] === '!') {
|
|
49
|
-
if (match[1].toUpperCase() === '!DOCTYPE') {
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
tag = '<!--' + match[1].substring(1) + match[2] + '-->';
|
|
53
|
-
}
|
|
54
|
-
else if (tagGroup.length === 0 || !tagGroup.some(item => item.test(match[0]))) {
|
|
55
|
-
tag = index_1.XmlWriter.escapeXmlString(match[0]);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
const trailing = match[match.length - 3];
|
|
60
|
-
if (escapeEntities) {
|
|
61
|
-
const outerTag = '<' + match[1] + match[2] + '>';
|
|
62
|
-
tag = index_1.XmlWriter.escapeAttributes(outerTag);
|
|
63
|
-
if (!trailing && tag === outerTag) {
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
else if (trailing) {
|
|
68
|
-
tag = '<' + match[1] + match[2] + '>';
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
else if (match[7]) {
|
|
73
|
-
if (!REGEXP_TAGNAME.test(match[7])) {
|
|
74
|
-
tag = `<!--${match[7]}-->`;
|
|
75
|
-
}
|
|
76
|
-
else if (match[8]) {
|
|
77
|
-
tag = `</${match[8]}>`;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
if (tag) {
|
|
81
|
-
source = source.substring(0, match.index) + tag + source.substring(match.index + match[0].length);
|
|
82
|
-
pattern.lastIndex += tag.length - match[0].length;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
pattern.lastIndex = 0;
|
|
86
|
-
return source;
|
|
87
|
-
}
|
|
88
|
-
static getDocumentElement(source, parser) {
|
|
89
|
-
const result = { element: null, error: null };
|
|
90
|
-
new Parser(new DomHandler((err, dom) => {
|
|
91
|
-
if (!err) {
|
|
92
|
-
result.element = domutils.findOne(elem => elem.tagName === "html" /* VALUES.ROOT */, dom);
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
result.error = err;
|
|
96
|
-
}
|
|
97
|
-
}, { withStartIndices: true, withEndIndices: true }), { decodeEntities: false, ...parser, xmlMode: false }).end(source);
|
|
98
|
-
return result;
|
|
99
|
-
}
|
|
100
|
-
static getElementsByTagName(tagName, nodes, recurse, limit) {
|
|
101
|
-
return domutils.getElementsByTagName(tagName, nodes, recurse, limit);
|
|
102
|
-
}
|
|
103
|
-
constructor(documentName, source, elements, options, escapeEntities, parser) {
|
|
104
|
-
let normalize, stripComments, ignoreTagGroup;
|
|
105
|
-
if ((0, types_1.isObject)(options)) {
|
|
106
|
-
({ normalize, escapeEntities, stripComments, ignoreTagGroup, parser } = options);
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
options = { normalize: options, escapeEntities, parser };
|
|
110
|
-
}
|
|
111
|
-
parser || (parser = { ...PARSER_OPTIONS });
|
|
112
|
-
super(documentName, source, elements, { parser });
|
|
113
|
-
this.documentElement = null;
|
|
114
|
-
this.ignoreTagName = "title|style|script" /* VALUES.IGNORE_TAGNAME */;
|
|
115
|
-
this.rootName = "html" /* VALUES.ROOT */;
|
|
116
|
-
this.ignoreCaseTagName = true;
|
|
117
|
-
const items = [];
|
|
118
|
-
let outerXml = '', documentElement, offsetMap, startIndex = -1;
|
|
119
|
-
for (const item of elements) {
|
|
120
|
-
if (!item.ignoreCase) {
|
|
121
|
-
item.tagName = item.tagName.toLowerCase();
|
|
122
|
-
item.ignoreCase = true;
|
|
123
|
-
}
|
|
124
|
-
if (item.tagName === "html" /* VALUES.ROOT */) {
|
|
125
|
-
items.push(item);
|
|
126
|
-
if (!documentElement && item.innerXml) {
|
|
127
|
-
documentElement = item;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
const setNewline = (value) => this.newline = (0, util_1.getNewline)(value);
|
|
132
|
-
if (!documentElement) {
|
|
133
|
-
setNewline(source);
|
|
134
|
-
if (normalize) {
|
|
135
|
-
source = DomWriter.normalize(source, { newline: this.newline, ignoreChar: typeof normalize === 'string' ? normalize : '', ignoreTagGroup, escapeEntities });
|
|
136
|
-
}
|
|
137
|
-
else if (escapeEntities) {
|
|
138
|
-
source = index_1.XmlWriter.escapeAttributes(source);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
setNewline(documentElement.innerXml);
|
|
143
|
-
}
|
|
144
|
-
const html = /<html[\s>]/i.exec(source);
|
|
145
|
-
if (html) {
|
|
146
|
-
const endIndex = index_1.XmlWriter.findCloseTag(source, html.index);
|
|
147
|
-
if (endIndex !== -1) {
|
|
148
|
-
startIndex = html.index;
|
|
149
|
-
outerXml = source.substring(startIndex, endIndex + 1);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
if (documentElement) {
|
|
153
|
-
let leading;
|
|
154
|
-
if (startIndex === -1) {
|
|
155
|
-
leading = '<!DOCTYPE html>' + this.newline;
|
|
156
|
-
startIndex = leading.length;
|
|
157
|
-
outerXml = '<html>';
|
|
158
|
-
leading += outerXml;
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
leading = source.substring(0, startIndex + outerXml.length);
|
|
162
|
-
}
|
|
163
|
-
source = documentElement.innerXml;
|
|
164
|
-
if (escapeEntities) {
|
|
165
|
-
source = index_1.XmlWriter.escapeAttributes(source);
|
|
166
|
-
}
|
|
167
|
-
source = leading + this.newline + source + this.newline + '</html>';
|
|
168
|
-
this.documentElement = documentElement;
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
const trailing = items.filter(item => item.textContent);
|
|
172
|
-
if (trailing.length) {
|
|
173
|
-
const match = /<\/body\s*>/i.exec(source);
|
|
174
|
-
if (match) {
|
|
175
|
-
const textContent = trailing.reduce((a, b) => a + b.textContent, '');
|
|
176
|
-
offsetMap = index_1.XmlWriter.getTagOffset(textContent, { ignoreCase: this.ignoreCaseTagName, ignoreTagName: this.ignoreTagName, parser: this.parser });
|
|
177
|
-
source = source.substring(0, match.index) + textContent + source.substring(match.index);
|
|
178
|
-
trailing.forEach(item => delete item.textContent);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
if (stripComments) {
|
|
183
|
-
source = DomWriter.getCommentsAndCDATA(source, '', true, true);
|
|
184
|
-
}
|
|
185
|
-
this.source = source;
|
|
186
|
-
this.initOpts = options;
|
|
187
|
-
if (outerXml) {
|
|
188
|
-
const endIndex = startIndex + outerXml.length - 1;
|
|
189
|
-
for (const item of items) {
|
|
190
|
-
item.startIndex = startIndex;
|
|
191
|
-
item.endIndex = endIndex;
|
|
192
|
-
item.outerXml = outerXml;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
this.init(offsetMap);
|
|
196
|
-
}
|
|
197
|
-
save() {
|
|
198
|
-
if (this.modified && this.documentElement) {
|
|
199
|
-
let innerXml;
|
|
200
|
-
for (const item of this.elements) {
|
|
201
|
-
if (item.tagName === "html" /* VALUES.ROOT */) {
|
|
202
|
-
if (!innerXml && index_1.XmlWriter.isIndex(item.endIndex)) {
|
|
203
|
-
innerXml = this.source.substring(item.endIndex + 1, this.source.length - 7).trim();
|
|
204
|
-
}
|
|
205
|
-
item.innerXml = innerXml;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
return super.save();
|
|
210
|
-
}
|
|
211
|
-
close() {
|
|
212
|
-
if (this.documentElement || this._appendCount > 0) {
|
|
213
|
-
this.source = this.source.replace(new RegExp(this.patternId, 'g'), '');
|
|
214
|
-
}
|
|
215
|
-
return super.close();
|
|
216
|
-
}
|
|
217
|
-
newElement(node) {
|
|
218
|
-
return new HtmlElement(this.documentName, node);
|
|
219
|
-
}
|
|
220
|
-
get nameOfId() {
|
|
221
|
-
return index_1.XmlWriter.getNameOfId(this.documentName);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
exports.DomWriter = DomWriter;
|
|
225
|
-
class HtmlElement extends index_1.XmlElement {
|
|
226
|
-
constructor(documentName, node, attributes, options = {}) {
|
|
227
|
-
options.parser || (options.parser = { ...PARSER_OPTIONS });
|
|
228
|
-
super(documentName, node, attributes, { ...options, tagVoid: TAG_VOID.includes(node.tagName) });
|
|
229
|
-
this.TAG_VOID = TAG_VOID;
|
|
230
|
-
}
|
|
231
|
-
getTagOffset(source) {
|
|
232
|
-
switch (this.node.append?.tagName || this.tagName) {
|
|
233
|
-
case 'html':
|
|
234
|
-
case 'title':
|
|
235
|
-
case 'style':
|
|
236
|
-
case 'script':
|
|
237
|
-
return;
|
|
238
|
-
default:
|
|
239
|
-
return super.getTagOffset(source, { ignoreCase: this.ignoreCase, ignoreTagName: "title|style|script" /* VALUES.IGNORE_TAGNAME */, parser: this.parser });
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
findIndexOf(source) {
|
|
243
|
-
const { element } = index_1.XmlWriter.findElement(source, this.node, { document: this.documentName, id: this.id, locatorAttr: 'id', parser: this.parser });
|
|
244
|
-
if (element) {
|
|
245
|
-
return { startIndex: element.startIndex, endIndex: element.endIndex };
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
get outerXml() {
|
|
249
|
-
const [tagName, items, innerXml] = this.getOuterContent();
|
|
250
|
-
return '<' + tagName + HtmlElement.writeAttributes(items) + '>' + (DomWriter.hasInnerXml(tagName) && tagName !== "html" /* VALUES.ROOT */ ? (tagName === 'title' ? index_1.XmlWriter.escapeXmlString(innerXml) : innerXml) + `</${tagName}>` : '');
|
|
251
|
-
}
|
|
252
|
-
get nameOfId() {
|
|
253
|
-
return index_1.XmlWriter.getNameOfId(this.documentName);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
exports.HtmlElement = HtmlElement;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IGNORE_FLAG = exports.HtmlElement = exports.DomWriter = void 0;
|
|
4
|
+
const htmlparser2 = require("htmlparser2");
|
|
5
|
+
const domhandler = require("domhandler");
|
|
6
|
+
const domutils = require("domutils");
|
|
7
|
+
const types_1 = require("../../types");
|
|
8
|
+
const util_1 = require("../util");
|
|
9
|
+
const index_1 = require("./index");
|
|
10
|
+
Object.defineProperty(exports, "IGNORE_FLAG", { enumerable: true, get: function () { return index_1.IGNORE_FLAG; } });
|
|
11
|
+
const Parser = htmlparser2.Parser;
|
|
12
|
+
const DomHandler = domhandler.DomHandler;
|
|
13
|
+
const TAG_VOID = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
|
|
14
|
+
const REGEXP_VOID = TAG_VOID.map(tagName => new RegExp(`(\\s*)</${tagName}\\s*>` + index_1.XmlWriter.PATTERN_TRAILINGSPACE, 'gi'));
|
|
15
|
+
const REGEXP_TAGNAME = new RegExp(`^${index_1.XmlWriter.PATTERN_TAGNAME}$`);
|
|
16
|
+
const PARSER_OPTIONS = Object.freeze({ xmlMode: false, decodeEntities: false });
|
|
17
|
+
class DomWriter extends index_1.XmlWriter {
|
|
18
|
+
static hasInnerXml(tagName) {
|
|
19
|
+
return !TAG_VOID.includes(tagName);
|
|
20
|
+
}
|
|
21
|
+
static normalize(source, newline, ignoreChar = '', escapeEntities) {
|
|
22
|
+
let ignoreTagGroup;
|
|
23
|
+
if ((0, types_1.isObject)(newline)) {
|
|
24
|
+
({ newline, ignoreChar = '', ignoreTagGroup, escapeEntities } = newline);
|
|
25
|
+
}
|
|
26
|
+
for (const tag of REGEXP_VOID) {
|
|
27
|
+
source = source.replace(tag, (...capture) => index_1.XmlWriter.getNewlineString(capture[1], capture[2], newline));
|
|
28
|
+
}
|
|
29
|
+
const tagGroup = [];
|
|
30
|
+
if (ignoreTagGroup) {
|
|
31
|
+
for (let i = 0, length = ignoreTagGroup.length; i < length; i += 2) {
|
|
32
|
+
const start = ignoreTagGroup[i];
|
|
33
|
+
if (start[0] === '<') {
|
|
34
|
+
tagGroup.push(new RegExp('^' + (0, types_1.escapePattern)(start)));
|
|
35
|
+
}
|
|
36
|
+
const end = ignoreTagGroup[i + 1];
|
|
37
|
+
if (end?.[end.length - 1] === '>') {
|
|
38
|
+
tagGroup.push(new RegExp((0, types_1.escapePattern)(start) + '$'));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const pattern = new RegExp(`<(?:!--[\\S\\s]*?--|([^\\s<>/${ignoreChar}]+)(${index_1.XmlWriter.PATTERN_TAGOPEN}*?)(\\s*\\/?\\s*)|\\/([^\\s>]+)(\\s*))>`, 'g');
|
|
43
|
+
let match;
|
|
44
|
+
while (match = pattern.exec(source)) {
|
|
45
|
+
let tag;
|
|
46
|
+
if (match[1]) {
|
|
47
|
+
if (!REGEXP_TAGNAME.test(match[1])) {
|
|
48
|
+
if (match[0][1] === '!') {
|
|
49
|
+
if (match[1].toUpperCase() === '!DOCTYPE') {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
tag = '<!--' + match[1].substring(1) + match[2] + '-->';
|
|
53
|
+
}
|
|
54
|
+
else if (tagGroup.length === 0 || !tagGroup.some(item => item.test(match[0]))) {
|
|
55
|
+
tag = index_1.XmlWriter.escapeXmlString(match[0]);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
const trailing = match[match.length - 3];
|
|
60
|
+
if (escapeEntities) {
|
|
61
|
+
const outerTag = '<' + match[1] + match[2] + '>';
|
|
62
|
+
tag = index_1.XmlWriter.escapeAttributes(outerTag);
|
|
63
|
+
if (!trailing && tag === outerTag) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if (trailing) {
|
|
68
|
+
tag = '<' + match[1] + match[2] + '>';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else if (match[7]) {
|
|
73
|
+
if (!REGEXP_TAGNAME.test(match[7])) {
|
|
74
|
+
tag = `<!--${match[7]}-->`;
|
|
75
|
+
}
|
|
76
|
+
else if (match[8]) {
|
|
77
|
+
tag = `</${match[8]}>`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (tag) {
|
|
81
|
+
source = source.substring(0, match.index) + tag + source.substring(match.index + match[0].length);
|
|
82
|
+
pattern.lastIndex += tag.length - match[0].length;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
pattern.lastIndex = 0;
|
|
86
|
+
return source;
|
|
87
|
+
}
|
|
88
|
+
static getDocumentElement(source, parser) {
|
|
89
|
+
const result = { element: null, error: null };
|
|
90
|
+
new Parser(new DomHandler((err, dom) => {
|
|
91
|
+
if (!err) {
|
|
92
|
+
result.element = domutils.findOne(elem => elem.tagName === "html" /* VALUES.ROOT */, dom);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
result.error = err;
|
|
96
|
+
}
|
|
97
|
+
}, { withStartIndices: true, withEndIndices: true }), { decodeEntities: false, ...parser, xmlMode: false }).end(source);
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
static getElementsByTagName(tagName, nodes, recurse, limit) {
|
|
101
|
+
return domutils.getElementsByTagName(tagName, nodes, recurse, limit);
|
|
102
|
+
}
|
|
103
|
+
constructor(documentName, source, elements, options, escapeEntities, parser) {
|
|
104
|
+
let normalize, stripComments, ignoreTagGroup;
|
|
105
|
+
if ((0, types_1.isObject)(options)) {
|
|
106
|
+
({ normalize, escapeEntities, stripComments, ignoreTagGroup, parser } = options);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
options = { normalize: options, escapeEntities, parser };
|
|
110
|
+
}
|
|
111
|
+
parser || (parser = { ...PARSER_OPTIONS });
|
|
112
|
+
super(documentName, source, elements, { parser });
|
|
113
|
+
this.documentElement = null;
|
|
114
|
+
this.ignoreTagName = "title|style|script" /* VALUES.IGNORE_TAGNAME */;
|
|
115
|
+
this.rootName = "html" /* VALUES.ROOT */;
|
|
116
|
+
this.ignoreCaseTagName = true;
|
|
117
|
+
const items = [];
|
|
118
|
+
let outerXml = '', documentElement, offsetMap, startIndex = -1;
|
|
119
|
+
for (const item of elements) {
|
|
120
|
+
if (!item.ignoreCase) {
|
|
121
|
+
item.tagName = item.tagName.toLowerCase();
|
|
122
|
+
item.ignoreCase = true;
|
|
123
|
+
}
|
|
124
|
+
if (item.tagName === "html" /* VALUES.ROOT */) {
|
|
125
|
+
items.push(item);
|
|
126
|
+
if (!documentElement && item.innerXml) {
|
|
127
|
+
documentElement = item;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const setNewline = (value) => this.newline = (0, util_1.getNewline)(value);
|
|
132
|
+
if (!documentElement) {
|
|
133
|
+
setNewline(source);
|
|
134
|
+
if (normalize) {
|
|
135
|
+
source = DomWriter.normalize(source, { newline: this.newline, ignoreChar: typeof normalize === 'string' ? normalize : '', ignoreTagGroup, escapeEntities });
|
|
136
|
+
}
|
|
137
|
+
else if (escapeEntities) {
|
|
138
|
+
source = index_1.XmlWriter.escapeAttributes(source);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
setNewline(documentElement.innerXml);
|
|
143
|
+
}
|
|
144
|
+
const html = /<html[\s>]/i.exec(source);
|
|
145
|
+
if (html) {
|
|
146
|
+
const endIndex = index_1.XmlWriter.findCloseTag(source, html.index);
|
|
147
|
+
if (endIndex !== -1) {
|
|
148
|
+
startIndex = html.index;
|
|
149
|
+
outerXml = source.substring(startIndex, endIndex + 1);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (documentElement) {
|
|
153
|
+
let leading;
|
|
154
|
+
if (startIndex === -1) {
|
|
155
|
+
leading = '<!DOCTYPE html>' + this.newline;
|
|
156
|
+
startIndex = leading.length;
|
|
157
|
+
outerXml = '<html>';
|
|
158
|
+
leading += outerXml;
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
leading = source.substring(0, startIndex + outerXml.length);
|
|
162
|
+
}
|
|
163
|
+
source = documentElement.innerXml;
|
|
164
|
+
if (escapeEntities) {
|
|
165
|
+
source = index_1.XmlWriter.escapeAttributes(source);
|
|
166
|
+
}
|
|
167
|
+
source = leading + this.newline + source + this.newline + '</html>';
|
|
168
|
+
this.documentElement = documentElement;
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
const trailing = items.filter(item => item.textContent);
|
|
172
|
+
if (trailing.length) {
|
|
173
|
+
const match = /<\/body\s*>/i.exec(source);
|
|
174
|
+
if (match) {
|
|
175
|
+
const textContent = trailing.reduce((a, b) => a + b.textContent, '');
|
|
176
|
+
offsetMap = index_1.XmlWriter.getTagOffset(textContent, { ignoreCase: this.ignoreCaseTagName, ignoreTagName: this.ignoreTagName, parser: this.parser });
|
|
177
|
+
source = source.substring(0, match.index) + textContent + source.substring(match.index);
|
|
178
|
+
trailing.forEach(item => delete item.textContent);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (stripComments) {
|
|
183
|
+
source = DomWriter.getCommentsAndCDATA(source, '', true, true);
|
|
184
|
+
}
|
|
185
|
+
this.source = source;
|
|
186
|
+
this.initOpts = options;
|
|
187
|
+
if (outerXml) {
|
|
188
|
+
const endIndex = startIndex + outerXml.length - 1;
|
|
189
|
+
for (const item of items) {
|
|
190
|
+
item.startIndex = startIndex;
|
|
191
|
+
item.endIndex = endIndex;
|
|
192
|
+
item.outerXml = outerXml;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
this.init(offsetMap);
|
|
196
|
+
}
|
|
197
|
+
save() {
|
|
198
|
+
if (this.modified && this.documentElement) {
|
|
199
|
+
let innerXml;
|
|
200
|
+
for (const item of this.elements) {
|
|
201
|
+
if (item.tagName === "html" /* VALUES.ROOT */) {
|
|
202
|
+
if (!innerXml && index_1.XmlWriter.isIndex(item.endIndex)) {
|
|
203
|
+
innerXml = this.source.substring(item.endIndex + 1, this.source.length - 7).trim();
|
|
204
|
+
}
|
|
205
|
+
item.innerXml = innerXml;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return super.save();
|
|
210
|
+
}
|
|
211
|
+
close() {
|
|
212
|
+
if (this.documentElement || this._appendCount > 0) {
|
|
213
|
+
this.source = this.source.replace(new RegExp(this.patternId, 'g'), '');
|
|
214
|
+
}
|
|
215
|
+
return super.close();
|
|
216
|
+
}
|
|
217
|
+
newElement(node) {
|
|
218
|
+
return new HtmlElement(this.documentName, node);
|
|
219
|
+
}
|
|
220
|
+
get nameOfId() {
|
|
221
|
+
return index_1.XmlWriter.getNameOfId(this.documentName);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
exports.DomWriter = DomWriter;
|
|
225
|
+
class HtmlElement extends index_1.XmlElement {
|
|
226
|
+
constructor(documentName, node, attributes, options = {}) {
|
|
227
|
+
options.parser || (options.parser = { ...PARSER_OPTIONS });
|
|
228
|
+
super(documentName, node, attributes, { ...options, tagVoid: TAG_VOID.includes(node.tagName) });
|
|
229
|
+
this.TAG_VOID = TAG_VOID;
|
|
230
|
+
}
|
|
231
|
+
getTagOffset(source) {
|
|
232
|
+
switch (this.node.append?.tagName || this.tagName) {
|
|
233
|
+
case 'html':
|
|
234
|
+
case 'title':
|
|
235
|
+
case 'style':
|
|
236
|
+
case 'script':
|
|
237
|
+
return;
|
|
238
|
+
default:
|
|
239
|
+
return super.getTagOffset(source, { ignoreCase: this.ignoreCase, ignoreTagName: "title|style|script" /* VALUES.IGNORE_TAGNAME */, parser: this.parser });
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
findIndexOf(source) {
|
|
243
|
+
const { element } = index_1.XmlWriter.findElement(source, this.node, { document: this.documentName, id: this.id, locatorAttr: 'id', parser: this.parser });
|
|
244
|
+
if (element) {
|
|
245
|
+
return { startIndex: element.startIndex, endIndex: element.endIndex };
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
get outerXml() {
|
|
249
|
+
const [tagName, items, innerXml] = this.getOuterContent();
|
|
250
|
+
return '<' + tagName + HtmlElement.writeAttributes(items) + '>' + (DomWriter.hasInnerXml(tagName) && tagName !== "html" /* VALUES.ROOT */ ? (tagName === 'title' ? index_1.XmlWriter.escapeXmlString(innerXml) : innerXml) + `</${tagName}>` : '');
|
|
251
|
+
}
|
|
252
|
+
get nameOfId() {
|
|
253
|
+
return index_1.XmlWriter.getNameOfId(this.documentName);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
exports.HtmlElement = HtmlElement;
|