single-file-core 1.6.11 → 1.6.12
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/core/helper.js +232 -26
- package/core/index.js +28 -1
- package/core/util.js +11 -2
- package/modules/html-serializer.js +5 -5
- package/package.json +1 -1
- package/single-file-bootstrap.js +2 -0
package/core/helper.js
CHANGED
|
@@ -94,6 +94,13 @@ const EMPTY_RESOURCE = "data:,";
|
|
|
94
94
|
const POSTER_CONTENT_TYPES = ["image/webp", "image/jpeg"];
|
|
95
95
|
const POSTER_QUALITY = 0.8;
|
|
96
96
|
const NESTING_TRACK_ID_ATTRIBUTE_NAME = "data-sf-nesting-track-id";
|
|
97
|
+
const NESTING_START_MARKER = NESTING_TRACK_ID_ATTRIBUTE_NAME + "-start ";
|
|
98
|
+
const NESTING_END_MARKER = NESTING_TRACK_ID_ATTRIBUTE_NAME + "-end ";
|
|
99
|
+
const NESTING_RECREATED_ATTRIBUTE_NAME = NESTING_TRACK_ID_ATTRIBUTE_NAME + "-recreated";
|
|
100
|
+
const NESTING_SHADOW_ROOT_TRACK_ID_PREFIX = "s";
|
|
101
|
+
const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
|
|
102
|
+
const RAW_TEXT_TAG_NAMES = ["SCRIPT", "STYLE", "TEXTAREA", "TITLE", "XMP", "IFRAME", "NOEMBED", "NOFRAMES", "PLAINTEXT", "NOSCRIPT"];
|
|
103
|
+
const COMMENT_NODE_FILTER = 128;
|
|
97
104
|
const DEPRECATED_OPTION_NAMES = {
|
|
98
105
|
loadDeferredImages: "loadDeferredContent",
|
|
99
106
|
loadDeferredImagesMaxIdleTime: "loadDeferredContentMaxIdleTime",
|
|
@@ -141,6 +148,8 @@ export {
|
|
|
141
148
|
parseDocContent,
|
|
142
149
|
markInvalidNesting,
|
|
143
150
|
fixInvalidNesting,
|
|
151
|
+
removeNestingMarkers,
|
|
152
|
+
getNestingMarkerData,
|
|
144
153
|
normalizeOptions,
|
|
145
154
|
ON_BEFORE_CAPTURE_EVENT_NAME,
|
|
146
155
|
ON_AFTER_CAPTURE_EVENT_NAME,
|
|
@@ -171,6 +180,9 @@ export {
|
|
|
171
180
|
MESSAGE_PREFIX,
|
|
172
181
|
NO_SCRIPT_PROPERTY_NAME,
|
|
173
182
|
NESTING_TRACK_ID_ATTRIBUTE_NAME,
|
|
183
|
+
NESTING_START_MARKER,
|
|
184
|
+
NESTING_END_MARKER,
|
|
185
|
+
NESTING_RECREATED_ATTRIBUTE_NAME,
|
|
174
186
|
getPosterDataURI
|
|
175
187
|
};
|
|
176
188
|
|
|
@@ -311,6 +323,7 @@ function preProcessDoc(doc, win, options) {
|
|
|
311
323
|
markedElements: []
|
|
312
324
|
};
|
|
313
325
|
}
|
|
326
|
+
setNestingMarkersData(doc);
|
|
314
327
|
let referrer = "";
|
|
315
328
|
if (doc.referrer) {
|
|
316
329
|
try {
|
|
@@ -343,18 +356,30 @@ function markInvalidNesting(doc) {
|
|
|
343
356
|
if (!doc.body) {
|
|
344
357
|
return;
|
|
345
358
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
359
|
+
removeNestingMarkers(doc);
|
|
360
|
+
markInvalidNestingInRoot(doc, doc.body, "", () => serialize(doc));
|
|
361
|
+
getShadowRoots(doc.body).forEach((shadowRoot, indexShadowRoot) =>
|
|
362
|
+
markInvalidNestingInRoot(doc, shadowRoot, NESTING_SHADOW_ROOT_TRACK_ID_PREFIX + indexShadowRoot, () => shadowRoot.innerHTML));
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function markInvalidNestingInRoot(doc, root, rootTrackId, getContent) {
|
|
366
|
+
if (rootTrackId) {
|
|
367
|
+
Array.from(root.children).forEach((child, indexChild) => addTrackIds(child, indexChild, rootTrackId));
|
|
368
|
+
} else {
|
|
369
|
+
addTrackIds(root);
|
|
370
|
+
}
|
|
371
|
+
const verificationDoc = parseDocContent(getContent());
|
|
372
|
+
const markedMap = buildTrackIdMap(root);
|
|
373
|
+
const normalizedMap = buildTrackIdMap(verificationDoc.documentElement);
|
|
350
374
|
const trackIds = new Set();
|
|
375
|
+
const droppedElements = [];
|
|
351
376
|
Object.keys(markedMap).forEach(id => {
|
|
352
377
|
if (id in normalizedMap) {
|
|
353
378
|
const markedParent = markedMap[id].parentElement?.getAttribute(NESTING_TRACK_ID_ATTRIBUTE_NAME) || null;
|
|
354
379
|
const normalizedParent = normalizedMap[id]?.parentElement?.getAttribute(NESTING_TRACK_ID_ATTRIBUTE_NAME) || null;
|
|
355
380
|
if (markedParent !== normalizedParent) {
|
|
356
381
|
let current = markedMap[id];
|
|
357
|
-
while (current && current !==
|
|
382
|
+
while (current && current !== root) {
|
|
358
383
|
const currentId = current.getAttribute(NESTING_TRACK_ID_ATTRIBUTE_NAME);
|
|
359
384
|
if (currentId) {
|
|
360
385
|
trackIds.add(currentId);
|
|
@@ -362,9 +387,22 @@ function markInvalidNesting(doc) {
|
|
|
362
387
|
current = current.parentElement;
|
|
363
388
|
}
|
|
364
389
|
}
|
|
390
|
+
} else if (testDroppedElement(markedMap[id])) {
|
|
391
|
+
trackIds.add(id);
|
|
392
|
+
droppedElements.push(markedMap[id]);
|
|
365
393
|
}
|
|
366
394
|
});
|
|
367
|
-
|
|
395
|
+
droppedElements.forEach(element => {
|
|
396
|
+
const id = element.getAttribute(NESTING_TRACK_ID_ATTRIBUTE_NAME);
|
|
397
|
+
element.prepend(doc.createComment(NESTING_START_MARKER + id));
|
|
398
|
+
element.append(doc.createComment(NESTING_END_MARKER + id));
|
|
399
|
+
});
|
|
400
|
+
setNestingMarkersData(root);
|
|
401
|
+
if (rootTrackId) {
|
|
402
|
+
Array.from(root.children).forEach(child => cleanupTrackIds(child, trackIds));
|
|
403
|
+
} else {
|
|
404
|
+
cleanupTrackIds(root, trackIds);
|
|
405
|
+
}
|
|
368
406
|
|
|
369
407
|
function addTrackIds(element, index = 0, parentTrackId = "") {
|
|
370
408
|
const trackId = parentTrackId ? `${parentTrackId}.${index + 1}` : `${index + 1}`;
|
|
@@ -375,9 +413,13 @@ function markInvalidNesting(doc) {
|
|
|
375
413
|
Array.from(element.children).forEach((child, indexChild) => addTrackIds(child, indexChild, trackId));
|
|
376
414
|
}
|
|
377
415
|
|
|
378
|
-
function buildTrackIdMap(
|
|
416
|
+
function buildTrackIdMap(root) {
|
|
379
417
|
const trackIds = {};
|
|
380
|
-
|
|
418
|
+
if (root.getAttribute) {
|
|
419
|
+
traverse(root);
|
|
420
|
+
} else {
|
|
421
|
+
Array.from(root.children).forEach(traverse);
|
|
422
|
+
}
|
|
381
423
|
return trackIds;
|
|
382
424
|
|
|
383
425
|
function traverse(element) {
|
|
@@ -391,6 +433,21 @@ function markInvalidNesting(doc) {
|
|
|
391
433
|
}
|
|
392
434
|
}
|
|
393
435
|
|
|
436
|
+
function testDroppedElement(element) {
|
|
437
|
+
if (element.namespaceURI != HTML_NAMESPACE) {
|
|
438
|
+
return false;
|
|
439
|
+
}
|
|
440
|
+
let ancestor = element.parentElement;
|
|
441
|
+
while (ancestor) {
|
|
442
|
+
const tagName = ancestor.tagName.toUpperCase();
|
|
443
|
+
if (tagName == "TEMPLATE" || RAW_TEXT_TAG_NAMES.includes(tagName)) {
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
446
|
+
ancestor = ancestor.parentElement;
|
|
447
|
+
}
|
|
448
|
+
return true;
|
|
449
|
+
}
|
|
450
|
+
|
|
394
451
|
function cleanupTrackIds(element, toKeep) {
|
|
395
452
|
const id = element.getAttribute(NESTING_TRACK_ID_ATTRIBUTE_NAME);
|
|
396
453
|
if (id && !toKeep.has(id)) {
|
|
@@ -400,33 +457,180 @@ function markInvalidNesting(doc) {
|
|
|
400
457
|
}
|
|
401
458
|
}
|
|
402
459
|
|
|
403
|
-
function
|
|
404
|
-
|
|
460
|
+
function getShadowRoots(element, shadowRoots = []) {
|
|
461
|
+
Array.from(element.children).forEach(child => {
|
|
462
|
+
if (child.namespaceURI == HTML_NAMESPACE && !child.classList.contains(SINGLE_FILE_UI_ELEMENT_CLASS) && child.tagName.toLowerCase() != INFOBAR_TAGNAME) {
|
|
463
|
+
const shadowRoot = getShadowRoot(child);
|
|
464
|
+
if (shadowRoot) {
|
|
465
|
+
shadowRoots.push(shadowRoot);
|
|
466
|
+
getShadowRoots(shadowRoot, shadowRoots);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
getShadowRoots(child, shadowRoots);
|
|
470
|
+
});
|
|
471
|
+
return shadowRoots;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
function getNestingMarkerData(element) {
|
|
475
|
+
return encodeURIComponent(JSON.stringify({
|
|
476
|
+
tag: element.localName,
|
|
477
|
+
attributes: Array.from(element.attributes)
|
|
478
|
+
.filter(attribute => attribute.name != NESTING_RECREATED_ATTRIBUTE_NAME)
|
|
479
|
+
.map(attribute => [attribute.name, attribute.value])
|
|
480
|
+
}));
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
function setNestingMarkersData(root) {
|
|
484
|
+
const walker = (root.ownerDocument || root).createTreeWalker(root, COMMENT_NODE_FILTER);
|
|
485
|
+
while (walker.nextNode()) {
|
|
486
|
+
const comment = walker.currentNode;
|
|
487
|
+
if (comment.data.startsWith(NESTING_START_MARKER)) {
|
|
488
|
+
const id = comment.data.substring(NESTING_START_MARKER.length).split(" ")[0];
|
|
489
|
+
comment.data = NESTING_START_MARKER + id + " " + getNestingMarkerData(comment.parentNode);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
function removeNestingMarkers(doc) {
|
|
495
|
+
if (doc.body) {
|
|
496
|
+
[doc, ...getShadowRoots(doc.body)].forEach(root => {
|
|
497
|
+
const comments = [];
|
|
498
|
+
const walker = doc.createTreeWalker(root, COMMENT_NODE_FILTER);
|
|
499
|
+
while (walker.nextNode()) {
|
|
500
|
+
if (walker.currentNode.data.startsWith(NESTING_START_MARKER) || walker.currentNode.data.startsWith(NESTING_END_MARKER)) {
|
|
501
|
+
comments.push(walker.currentNode);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
comments.forEach(comment => comment.remove());
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
function fixInvalidNesting(document, NESTING_TRACK_ID_ATTRIBUTE_NAME, preventCleanup = false, options = {}) {
|
|
510
|
+
const START_MARKER = NESTING_TRACK_ID_ATTRIBUTE_NAME + "-start ";
|
|
511
|
+
const END_MARKER = NESTING_TRACK_ID_ATTRIBUTE_NAME + "-end ";
|
|
512
|
+
const RECREATED_ATTRIBUTE_NAME = NESTING_TRACK_ID_ATTRIBUTE_NAME + "-recreated";
|
|
405
513
|
if (document.currentScript) {
|
|
406
514
|
document.currentScript.remove();
|
|
407
515
|
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
516
|
+
const roots = [];
|
|
517
|
+
if (options.rootElement) {
|
|
518
|
+
roots.push(options.rootElement);
|
|
519
|
+
} else if (document.body) {
|
|
520
|
+
addRoots(document.body);
|
|
521
|
+
}
|
|
522
|
+
roots.forEach(root => {
|
|
523
|
+
recreateElements(root);
|
|
524
|
+
if (!options.recreateOnly) {
|
|
525
|
+
moveElements(root);
|
|
418
526
|
}
|
|
419
527
|
});
|
|
420
528
|
if (!preventCleanup) {
|
|
421
|
-
|
|
529
|
+
roots.forEach(root => {
|
|
530
|
+
const elements = Array.from(root.querySelectorAll("[" + NESTING_TRACK_ID_ATTRIBUTE_NAME + "]"));
|
|
531
|
+
if (root.getAttribute && root.getAttribute(NESTING_TRACK_ID_ATTRIBUTE_NAME)) {
|
|
532
|
+
elements.push(root);
|
|
533
|
+
}
|
|
534
|
+
elements.forEach(element => element.removeAttribute(NESTING_TRACK_ID_ATTRIBUTE_NAME));
|
|
535
|
+
});
|
|
422
536
|
}
|
|
423
537
|
|
|
424
|
-
function
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
538
|
+
function addRoots(root) {
|
|
539
|
+
roots.push(root);
|
|
540
|
+
root.querySelectorAll("*").forEach(element => {
|
|
541
|
+
if (element.shadowRoot) {
|
|
542
|
+
addRoots(element.shadowRoot);
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
function recreateElements(root) {
|
|
548
|
+
const startComments = [];
|
|
549
|
+
const walker = document.createTreeWalker(root, 128);
|
|
550
|
+
while (walker.nextNode()) {
|
|
551
|
+
if (walker.currentNode.data.startsWith(START_MARKER)) {
|
|
552
|
+
startComments.push(walker.currentNode);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
startComments.forEach(startComment => {
|
|
556
|
+
const separatorIndex = startComment.data.indexOf(" ", START_MARKER.length);
|
|
557
|
+
let endComment, data;
|
|
558
|
+
if (separatorIndex != -1) {
|
|
559
|
+
const id = startComment.data.substring(START_MARKER.length, separatorIndex);
|
|
560
|
+
endComment = startComment.nextSibling;
|
|
561
|
+
while (endComment && !(endComment.nodeType == 8 && endComment.data == END_MARKER + id)) {
|
|
562
|
+
endComment = endComment.nextSibling;
|
|
563
|
+
}
|
|
564
|
+
try {
|
|
565
|
+
data = globalThis.JSON.parse(decodeURIComponent(startComment.data.substring(separatorIndex + 1)));
|
|
566
|
+
} catch {
|
|
567
|
+
/* ignored */
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
if (endComment && data) {
|
|
571
|
+
const element = document.createElement(data.tag);
|
|
572
|
+
data.attributes.forEach(([name, value]) => {
|
|
573
|
+
try {
|
|
574
|
+
element.setAttribute(name, value);
|
|
575
|
+
} catch {
|
|
576
|
+
/* ignored */
|
|
577
|
+
}
|
|
578
|
+
});
|
|
579
|
+
if (preventCleanup) {
|
|
580
|
+
element.setAttribute(RECREATED_ATTRIBUTE_NAME, "");
|
|
581
|
+
}
|
|
582
|
+
startComment.before(element);
|
|
583
|
+
while (startComment.nextSibling != endComment) {
|
|
584
|
+
element.appendChild(startComment.nextSibling);
|
|
585
|
+
}
|
|
586
|
+
startComment.remove();
|
|
587
|
+
endComment.remove();
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
function moveElements(root) {
|
|
593
|
+
const trackIds = {};
|
|
594
|
+
const elements = [];
|
|
595
|
+
if (root.getAttribute) {
|
|
596
|
+
buildTrackIdMap(root);
|
|
597
|
+
} else {
|
|
598
|
+
Array.from(root.children).forEach(buildTrackIdMap);
|
|
599
|
+
}
|
|
600
|
+
elements.forEach(element => {
|
|
601
|
+
const id = element.getAttribute(NESTING_TRACK_ID_ATTRIBUTE_NAME);
|
|
602
|
+
const originalElement = trackIds[id];
|
|
603
|
+
if (originalElement != element) {
|
|
604
|
+
if (!preventCleanup) {
|
|
605
|
+
if (originalElement.contains(element)) {
|
|
606
|
+
element.replaceWith(...element.childNodes);
|
|
607
|
+
} else {
|
|
608
|
+
originalElement.append(...element.childNodes);
|
|
609
|
+
element.remove();
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
} else {
|
|
613
|
+
const idParts = id.split(".");
|
|
614
|
+
if (idParts.length > 1) {
|
|
615
|
+
const parentId = idParts.slice(0, -1).join(".");
|
|
616
|
+
const expectedParent = trackIds[parentId];
|
|
617
|
+
if (expectedParent && element.parentElement !== expectedParent && !element.contains(expectedParent)) {
|
|
618
|
+
expectedParent.appendChild(element);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
function buildTrackIdMap(element) {
|
|
625
|
+
const id = element.getAttribute(NESTING_TRACK_ID_ATTRIBUTE_NAME);
|
|
626
|
+
if (id) {
|
|
627
|
+
if (!(id in trackIds)) {
|
|
628
|
+
trackIds[id] = element;
|
|
629
|
+
}
|
|
630
|
+
elements.push(element);
|
|
631
|
+
}
|
|
632
|
+
Array.from(element.children).forEach(buildTrackIdMap);
|
|
428
633
|
}
|
|
429
|
-
Array.from(element.children).forEach(buildTrackIdMap);
|
|
430
634
|
}
|
|
431
635
|
}
|
|
432
636
|
|
|
@@ -509,6 +713,7 @@ function getElementsInfo(win, doc, element, options, data = { usedFonts: new Map
|
|
|
509
713
|
// ignored
|
|
510
714
|
}
|
|
511
715
|
getElementsInfo(win, doc, shadowRoot, options, data, adoptedStyleSheetsCache, elementHidden);
|
|
716
|
+
setNestingMarkersData(shadowRoot);
|
|
512
717
|
shadowRootInfo.content = shadowRoot.innerHTML;
|
|
513
718
|
shadowRootInfo.mode = shadowRoot.mode;
|
|
514
719
|
shadowRootInfo.delegateFocus = shadowRoot.delegatesFocus;
|
|
@@ -852,6 +1057,7 @@ function testHiddenElement(element, computedStyle) {
|
|
|
852
1057
|
}
|
|
853
1058
|
|
|
854
1059
|
function postProcessDoc(doc, markedElements, invalidElements) {
|
|
1060
|
+
removeNestingMarkers(doc);
|
|
855
1061
|
doc.querySelectorAll("[" + DISABLED_NOSCRIPT_ATTRIBUTE_NAME + "]").forEach(element => {
|
|
856
1062
|
element.textContent = element.getAttribute(DISABLED_NOSCRIPT_ATTRIBUTE_NAME);
|
|
857
1063
|
element.removeAttribute(DISABLED_NOSCRIPT_ATTRIBUTE_NAME);
|
package/core/index.js
CHANGED
|
@@ -212,6 +212,9 @@ class Runner {
|
|
|
212
212
|
this.options.frames = [];
|
|
213
213
|
}
|
|
214
214
|
this.options.content = this.options.content || (rootDocDefined ? util.serialize(this.options.doc) : null);
|
|
215
|
+
if (rootDocDefined) {
|
|
216
|
+
util.removeNestingMarkers(this.options.doc);
|
|
217
|
+
}
|
|
215
218
|
this.onprogress = options.onprogress || (() => { });
|
|
216
219
|
}
|
|
217
220
|
|
|
@@ -498,6 +501,7 @@ class Processor {
|
|
|
498
501
|
pageContent = content.data || "";
|
|
499
502
|
}
|
|
500
503
|
this.doc = util.parseDocContent(pageContent, this.baseURI);
|
|
504
|
+
util.fixInvalidNesting(this.doc, true, { recreateOnly: true });
|
|
501
505
|
removeInsertedParagraphs(this.doc);
|
|
502
506
|
this.nestingPositions = getNestingPositions(this.doc);
|
|
503
507
|
util.fixInvalidNesting(this.doc);
|
|
@@ -609,7 +613,8 @@ class Processor {
|
|
|
609
613
|
size = util.getContentSize(this.doc.documentElement.outerHTML);
|
|
610
614
|
}
|
|
611
615
|
restoreNestingPositions(this.nestingPositions);
|
|
612
|
-
|
|
616
|
+
const collapsedElementCount = collapseRecreatedElements(this.doc);
|
|
617
|
+
if (collapsedElementCount || this.doc.querySelector(`[${util.NESTING_TRACK_ID_ATTRIBUTE_NAME}]`)) {
|
|
613
618
|
const scriptElement = this.doc.createElement("script");
|
|
614
619
|
scriptElement.textContent = `(${util.getFixInvalidNestingSource()})(document, "${util.NESTING_TRACK_ID_ATTRIBUTE_NAME}");`;
|
|
615
620
|
this.doc.body.appendChild(scriptElement);
|
|
@@ -1442,6 +1447,7 @@ class Processor {
|
|
|
1442
1447
|
insertShadowRootContents() {
|
|
1443
1448
|
const doc = this.doc;
|
|
1444
1449
|
const options = this.options;
|
|
1450
|
+
const nestingPositions = this.nestingPositions || [];
|
|
1445
1451
|
if (options.shadowRoots && options.shadowRoots.length) {
|
|
1446
1452
|
processElement(this.doc);
|
|
1447
1453
|
}
|
|
@@ -1482,6 +1488,13 @@ class Processor {
|
|
|
1482
1488
|
if (shadowDoc.body) {
|
|
1483
1489
|
shadowDoc.body.childNodes.forEach(node => templateElement.appendChild(shadowDoc.importNode(node, true)));
|
|
1484
1490
|
}
|
|
1491
|
+
util.fixInvalidNesting(doc, true, { rootElement: templateElement, recreateOnly: true });
|
|
1492
|
+
removeInsertedParagraphs(templateElement);
|
|
1493
|
+
nestingPositions.push(...getNestingPositions(templateElement));
|
|
1494
|
+
util.fixInvalidNesting(doc, true, { rootElement: templateElement });
|
|
1495
|
+
if (templateElement.querySelector(`[${util.NESTING_TRACK_ID_ATTRIBUTE_NAME}]`)) {
|
|
1496
|
+
templateElement.setAttribute(SHADOWROOT_ATTRIBUTE_NAME, "open");
|
|
1497
|
+
}
|
|
1485
1498
|
processElement(templateElement);
|
|
1486
1499
|
if (element.firstChild) {
|
|
1487
1500
|
element.insertBefore(templateElement, element.firstChild);
|
|
@@ -1822,6 +1835,20 @@ function restoreNestingPositions(positions) {
|
|
|
1822
1835
|
}
|
|
1823
1836
|
}
|
|
1824
1837
|
|
|
1838
|
+
function collapseRecreatedElements(doc) {
|
|
1839
|
+
const elements = Array.from(doc.querySelectorAll(`[${util.NESTING_RECREATED_ATTRIBUTE_NAME}]`)).reverse();
|
|
1840
|
+
elements.forEach(element => {
|
|
1841
|
+
const id = element.getAttribute(util.NESTING_TRACK_ID_ATTRIBUTE_NAME);
|
|
1842
|
+
element.before(doc.createComment(util.NESTING_START_MARKER + id + " " + util.getNestingMarkerData(element)));
|
|
1843
|
+
while (element.firstChild) {
|
|
1844
|
+
element.before(element.firstChild);
|
|
1845
|
+
}
|
|
1846
|
+
element.before(doc.createComment(util.NESTING_END_MARKER + id));
|
|
1847
|
+
element.remove();
|
|
1848
|
+
});
|
|
1849
|
+
return elements.length;
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1825
1852
|
function removeInsertedParagraphs(doc) {
|
|
1826
1853
|
const trackedElements = new Map();
|
|
1827
1854
|
doc.querySelectorAll(`[${util.NESTING_TRACK_ID_ATTRIBUTE_NAME}]`).forEach(element =>
|
package/core/util.js
CHANGED
|
@@ -128,8 +128,14 @@ function getInstance(utilOptions) {
|
|
|
128
128
|
return doc;
|
|
129
129
|
}
|
|
130
130
|
},
|
|
131
|
-
fixInvalidNesting(doc, preventCleanup = true) {
|
|
132
|
-
helper.fixInvalidNesting(doc, helper.NESTING_TRACK_ID_ATTRIBUTE_NAME, preventCleanup);
|
|
131
|
+
fixInvalidNesting(doc, preventCleanup = true, options) {
|
|
132
|
+
helper.fixInvalidNesting(doc, helper.NESTING_TRACK_ID_ATTRIBUTE_NAME, preventCleanup, options);
|
|
133
|
+
},
|
|
134
|
+
removeNestingMarkers(doc) {
|
|
135
|
+
helper.removeNestingMarkers(doc);
|
|
136
|
+
},
|
|
137
|
+
getNestingMarkerData(element) {
|
|
138
|
+
return helper.getNestingMarkerData(element);
|
|
133
139
|
},
|
|
134
140
|
markInvalidNesting(doc) {
|
|
135
141
|
helper.markInvalidNesting(doc, helper.NESTING_TRACK_ID_ATTRIBUTE_NAME);
|
|
@@ -226,6 +232,9 @@ function getInstance(utilOptions) {
|
|
|
226
232
|
WAIT_FOR_USERSCRIPT_PROPERTY_NAME: helper.WAIT_FOR_USERSCRIPT_PROPERTY_NAME,
|
|
227
233
|
NO_SCRIPT_PROPERTY_NAME: helper.NO_SCRIPT_PROPERTY_NAME,
|
|
228
234
|
NESTING_TRACK_ID_ATTRIBUTE_NAME: helper.NESTING_TRACK_ID_ATTRIBUTE_NAME,
|
|
235
|
+
NESTING_START_MARKER: helper.NESTING_START_MARKER,
|
|
236
|
+
NESTING_END_MARKER: helper.NESTING_END_MARKER,
|
|
237
|
+
NESTING_RECREATED_ATTRIBUTE_NAME: helper.NESTING_RECREATED_ATTRIBUTE_NAME,
|
|
229
238
|
getPosterDataURI: helper.getPosterDataURI
|
|
230
239
|
};
|
|
231
240
|
|
|
@@ -77,13 +77,13 @@ function process(doc, compressHTML) {
|
|
|
77
77
|
return docTypeString + serialize(doc.documentElement, compressHTML);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
function serialize(node, compressHTML
|
|
80
|
+
function serialize(node, compressHTML) {
|
|
81
81
|
if (node.nodeType == Node_TEXT_NODE) {
|
|
82
82
|
return serializeTextNode(node);
|
|
83
83
|
} else if (node.nodeType == Node_COMMENT_NODE) {
|
|
84
84
|
return serializeCommentNode(node);
|
|
85
85
|
} else if (node.nodeType == Node_ELEMENT_NODE) {
|
|
86
|
-
return serializeElement(node, compressHTML
|
|
86
|
+
return serializeElement(node, compressHTML);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -107,7 +107,7 @@ function serializeCommentNode(commentNode) {
|
|
|
107
107
|
return "<!--" + commentNode.textContent + "-->";
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
function serializeElement(element, compressHTML
|
|
110
|
+
function serializeElement(element, compressHTML) {
|
|
111
111
|
const tagName = getTagName(element);
|
|
112
112
|
const omittedStartTag = compressHTML && OMITTED_START_TAGS.find(omittedStartTag => tagName == getTagName(omittedStartTag) && omittedStartTag.accept(element));
|
|
113
113
|
let content = "";
|
|
@@ -119,10 +119,10 @@ function serializeElement(element, compressHTML, isSVG) {
|
|
|
119
119
|
if (tagName == "TEMPLATE" && !element.childNodes.length) {
|
|
120
120
|
content += element.innerHTML;
|
|
121
121
|
} else {
|
|
122
|
-
Array.from(element.childNodes).forEach(childNode => content += serialize(childNode, compressHTML
|
|
122
|
+
Array.from(element.childNodes).forEach(childNode => content += serialize(childNode, compressHTML));
|
|
123
123
|
}
|
|
124
124
|
const omittedEndTag = compressHTML && OMITTED_END_TAGS.find(omittedEndTag => tagName == getTagName(omittedEndTag) && omittedEndTag.accept(element.nextSibling, element));
|
|
125
|
-
if (
|
|
125
|
+
if (!omittedEndTag && !VOID_TAG_NAMES.includes(tagName)) {
|
|
126
126
|
content += "</" + tagName.toLowerCase() + ">";
|
|
127
127
|
}
|
|
128
128
|
return content;
|
package/package.json
CHANGED
package/single-file-bootstrap.js
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
WAIT_FOR_USERSCRIPT_PROPERTY_NAME,
|
|
32
32
|
preProcessDoc,
|
|
33
33
|
postProcessDoc,
|
|
34
|
+
markInvalidNesting,
|
|
34
35
|
getShadowRoot
|
|
35
36
|
} from "./core/helper.js";
|
|
36
37
|
|
|
@@ -46,6 +47,7 @@ const helper = {
|
|
|
46
47
|
serialize(doc, compressHTML) {
|
|
47
48
|
return serializer.process(doc, compressHTML);
|
|
48
49
|
},
|
|
50
|
+
markInvalidNesting,
|
|
49
51
|
getShadowRoot
|
|
50
52
|
};
|
|
51
53
|
|