single-file-core 1.0.46 → 1.0.48
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/modules/index.js +3 -1
- package/modules/template-formatter.js +2104 -0
- package/package.json +1 -1
- package/processors/hooks/content/content-hooks-frames-web.js +0 -12
- package/single-file-core.js +6 -156
- package/single-file-helper.js +56 -54
- package/single-file-util.js +5 -14
package/package.json
CHANGED
|
@@ -67,9 +67,7 @@
|
|
|
67
67
|
const Event = globalThis.Event;
|
|
68
68
|
const FileReader = globalThis.FileReader;
|
|
69
69
|
const Blob = globalThis.Blob;
|
|
70
|
-
const console = globalThis.console;
|
|
71
70
|
const JSON = globalThis.JSON;
|
|
72
|
-
const warn = (console && console.warn && ((...args) => console.warn(...args))) || (() => { });
|
|
73
71
|
|
|
74
72
|
const observers = new Map();
|
|
75
73
|
const observedElements = new Map();
|
|
@@ -314,12 +312,7 @@
|
|
|
314
312
|
|
|
315
313
|
if (globalThis.FontFace) {
|
|
316
314
|
const FontFace = globalThis.FontFace;
|
|
317
|
-
let warningFontFaceDisplayed;
|
|
318
315
|
globalThis.FontFace = function () {
|
|
319
|
-
if (!warningFontFaceDisplayed) {
|
|
320
|
-
warn("SingleFile is hooking the FontFace constructor, document.fonts.delete and document.fonts.clear to handle dynamically loaded fonts.");
|
|
321
|
-
warningFontFaceDisplayed = true;
|
|
322
|
-
}
|
|
323
316
|
getDetailObject(...arguments).then(detail => dispatchEvent(new CustomEvent(NEW_FONT_FACE_EVENT, { detail })));
|
|
324
317
|
return new FontFace(...arguments);
|
|
325
318
|
};
|
|
@@ -340,12 +333,7 @@
|
|
|
340
333
|
|
|
341
334
|
if (globalThis.IntersectionObserver) {
|
|
342
335
|
const IntersectionObserver = globalThis.IntersectionObserver;
|
|
343
|
-
let warningIntersectionObserverDisplayed;
|
|
344
336
|
globalThis.IntersectionObserver = function () {
|
|
345
|
-
if (!warningIntersectionObserverDisplayed) {
|
|
346
|
-
warn("SingleFile is hooking the IntersectionObserver API to detect and load deferred images.");
|
|
347
|
-
warningIntersectionObserverDisplayed = true;
|
|
348
|
-
}
|
|
349
337
|
const intersectionObserver = new IntersectionObserver(...arguments);
|
|
350
338
|
const observeIntersection = IntersectionObserver.prototype.observe || intersectionObserver.observe;
|
|
351
339
|
const unobserveIntersection = IntersectionObserver.prototype.unobserve || intersectionObserver.unobserve;
|
package/single-file-core.js
CHANGED
|
@@ -100,9 +100,9 @@ const STAGES = [
|
|
|
100
100
|
{ action: "replaceInvalidElements" },
|
|
101
101
|
{ action: "resetCharsetMeta" },
|
|
102
102
|
{ option: "saveFavicon", action: "saveFavicon" },
|
|
103
|
-
{ action: "replaceCanvasElements" },
|
|
104
103
|
{ action: "insertFonts" },
|
|
105
104
|
{ action: "insertShadowRootContents" },
|
|
105
|
+
{ action: "replaceCanvasElements" },
|
|
106
106
|
{ action: "setInputValues" },
|
|
107
107
|
{ option: "moveStylesInHead", action: "moveStylesInHead" },
|
|
108
108
|
{ option: "blockScripts", action: "removeEmbedScripts" },
|
|
@@ -517,21 +517,7 @@ class Processor {
|
|
|
517
517
|
this.stats.set("processed", "HTML bytes", contentSize);
|
|
518
518
|
this.stats.add("discarded", "HTML bytes", size - contentSize);
|
|
519
519
|
}
|
|
520
|
-
|
|
521
|
-
const replacementCharacter = this.options.filenameReplacementCharacter;
|
|
522
|
-
filename = util.getValidFilename(filename, this.options.filenameReplacedCharacters, replacementCharacter);
|
|
523
|
-
if (!this.options.backgroundSave) {
|
|
524
|
-
filename = filename.replace(/\//g, replacementCharacter);
|
|
525
|
-
}
|
|
526
|
-
if (!this.options.keepFilename && ((this.options.filenameMaxLengthUnit == "bytes" && util.getContentSize(filename) > this.options.filenameMaxLength) || filename.length > this.options.filenameMaxLength)) {
|
|
527
|
-
const extensionMatch = filename.match(/(\.[^.]{3,4})$/);
|
|
528
|
-
const extension = extensionMatch && extensionMatch[0] && extensionMatch[0].length > 1 ? extensionMatch[0] : "";
|
|
529
|
-
filename = this.options.filenameMaxLengthUnit == "bytes" ? await util.truncateText(filename, this.options.filenameMaxLength - extension.length) : filename.substring(0, this.options.filenameMaxLength - extension.length);
|
|
530
|
-
filename = filename + "…" + extension;
|
|
531
|
-
}
|
|
532
|
-
if (!filename) {
|
|
533
|
-
filename = "Unnamed page";
|
|
534
|
-
}
|
|
520
|
+
const filename = await util.formatFilename(content, this.options);
|
|
535
521
|
const matchTitle = this.baseURI.match(/([^/]*)\/?(\.html?.*)$/) || this.baseURI.match(/\/\/([^/]*)\/?$/);
|
|
536
522
|
const pageData = {
|
|
537
523
|
stats: this.stats.data,
|
|
@@ -634,6 +620,9 @@ class Processor {
|
|
|
634
620
|
function hideNode(node) {
|
|
635
621
|
if (canHideNode(node)) {
|
|
636
622
|
node.style.setProperty("display", "none", "important");
|
|
623
|
+
node.removeAttribute("src");
|
|
624
|
+
node.removeAttribute("srcset");
|
|
625
|
+
node.removeAttribute("srcdoc");
|
|
637
626
|
Array.from(node.childNodes).forEach(removeNode);
|
|
638
627
|
}
|
|
639
628
|
}
|
|
@@ -1479,7 +1468,7 @@ class Processor {
|
|
|
1479
1468
|
publisher: publisherElement && publisherElement.content ? publisherElement.content.trim() : "",
|
|
1480
1469
|
heading: headingElement && headingElement.textContent ? headingElement.textContent.trim() : ""
|
|
1481
1470
|
};
|
|
1482
|
-
this.options.infobarContent = await
|
|
1471
|
+
this.options.infobarContent = await util.evalTemplate(this.options.infobarTemplate, this.options, null, true);
|
|
1483
1472
|
}
|
|
1484
1473
|
}
|
|
1485
1474
|
|
|
@@ -1493,86 +1482,6 @@ const SINGLE_FILE_VARIABLE_NAME_PREFIX = "--sf-img-";
|
|
|
1493
1482
|
const SINGLE_FILE_VARIABLE_MAX_SIZE = 512 * 1024;
|
|
1494
1483
|
|
|
1495
1484
|
class ProcessorHelper {
|
|
1496
|
-
static async evalTemplate(template = "", options, content, dontReplaceSlash) {
|
|
1497
|
-
const url = util.parseURL(options.saveUrl);
|
|
1498
|
-
template = await evalTemplateVariable(template, "page-title", () => options.title || "No title", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1499
|
-
template = await evalTemplateVariable(template, "page-heading", () => options.info.heading || "No heading", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1500
|
-
template = await evalTemplateVariable(template, "page-language", () => options.info.lang || "No language", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1501
|
-
template = await evalTemplateVariable(template, "page-description", () => options.info.description || "No description", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1502
|
-
template = await evalTemplateVariable(template, "page-author", () => options.info.author || "No author", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1503
|
-
template = await evalTemplateVariable(template, "page-creator", () => options.info.creator || "No creator", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1504
|
-
template = await evalTemplateVariable(template, "page-publisher", () => options.info.publisher || "No publisher", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1505
|
-
await evalDate(options.saveDate);
|
|
1506
|
-
await evalDate(options.visitDate, "visit-");
|
|
1507
|
-
template = await evalTemplateVariable(template, "url-hash", () => url.hash.substring(1) || "No hash", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1508
|
-
template = await evalTemplateVariable(template, "url-host", () => url.host.replace(/\/$/, "") || "No host", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1509
|
-
template = await evalTemplateVariable(template, "url-hostname", () => url.hostname.replace(/\/$/, "") || "No hostname", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1510
|
-
const urlHref = decode(url.href);
|
|
1511
|
-
template = await evalTemplateVariable(template, "url-href", () => urlHref || "No href", dontReplaceSlash === undefined ? true : dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1512
|
-
template = await evalTemplateVariable(template, "url-href-digest-sha-1", urlHref ? async () => util.digest("SHA-1", urlHref) : "No href", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1513
|
-
template = await evalTemplateVariable(template, "url-href-flat", () => decode(url.href) || "No href", false, options.filenameReplacementCharacter);
|
|
1514
|
-
template = await evalTemplateVariable(template, "url-referrer", () => decode(options.referrer) || "No referrer", dontReplaceSlash === undefined ? true : dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1515
|
-
template = await evalTemplateVariable(template, "url-referrer-flat", () => decode(options.referrer) || "No referrer", false, options.filenameReplacementCharacter);
|
|
1516
|
-
template = await evalTemplateVariable(template, "url-password", () => url.password || "No password", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1517
|
-
template = await evalTemplateVariable(template, "url-pathname", () => decode(url.pathname).replace(/^\//, "").replace(/\/$/, "") || "No pathname", dontReplaceSlash === undefined ? true : dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1518
|
-
template = await evalTemplateVariable(template, "url-pathname-flat", () => decode(url.pathname) || "No pathname", false, options.filenameReplacementCharacter);
|
|
1519
|
-
template = await evalTemplateVariable(template, "url-port", () => url.port || "No port", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1520
|
-
template = await evalTemplateVariable(template, "url-protocol", () => url.protocol || "No protocol", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1521
|
-
template = await evalTemplateVariable(template, "url-search", () => url.search.substring(1) || "No search", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1522
|
-
const params = util.getSearchParams(url.search);
|
|
1523
|
-
for (const [name, value] of params) {
|
|
1524
|
-
template = await evalTemplateVariable(template, "url-search-" + name, () => value || "", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1525
|
-
}
|
|
1526
|
-
template = template.replace(/{\s*url-search-[^}\s]*\s*}/gi, "");
|
|
1527
|
-
template = await evalTemplateVariable(template, "url-username", () => url.username || "No username", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1528
|
-
template = await evalTemplateVariable(template, "tab-id", () => String(options.tabId || "No tab id"), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1529
|
-
template = await evalTemplateVariable(template, "tab-index", () => String(options.tabIndex || "No tab index"), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1530
|
-
template = await evalTemplateVariable(template, "url-last-segment", () => decode(getLastSegment(url, options.filenameReplacementCharacter)) || "No last segment", dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1531
|
-
if (content) {
|
|
1532
|
-
template = await evalTemplateVariable(template, "digest-sha-256", async () => util.digest("SHA-256", content), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1533
|
-
template = await evalTemplateVariable(template, "digest-sha-384", async () => util.digest("SHA-384", content), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1534
|
-
template = await evalTemplateVariable(template, "digest-sha-512", async () => util.digest("SHA-512", content), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1535
|
-
}
|
|
1536
|
-
const bookmarkFolder = (options.bookmarkFolders && options.bookmarkFolders.join("/")) || "";
|
|
1537
|
-
template = await evalTemplateVariable(template, "bookmark-pathname", () => bookmarkFolder, dontReplaceSlash === undefined ? true : dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1538
|
-
template = await evalTemplateVariable(template, "bookmark-pathname-flat", () => bookmarkFolder, false, options.filenameReplacementCharacter);
|
|
1539
|
-
template = await evalTemplateVariable(template, "profile-name", () => options.profileName, dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1540
|
-
return template.trim();
|
|
1541
|
-
|
|
1542
|
-
function decode(value) {
|
|
1543
|
-
try {
|
|
1544
|
-
return decodeURI(value);
|
|
1545
|
-
} catch (error) {
|
|
1546
|
-
return value;
|
|
1547
|
-
}
|
|
1548
|
-
}
|
|
1549
|
-
|
|
1550
|
-
async function evalDate(date, prefix = "") {
|
|
1551
|
-
if (date) {
|
|
1552
|
-
template = await evalTemplateVariable(template, prefix + "datetime-iso", () => date.toISOString(), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1553
|
-
template = await evalTemplateVariable(template, prefix + "date-iso", () => date.toISOString().split("T")[0], dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1554
|
-
template = await evalTemplateVariable(template, prefix + "time-iso", () => date.toISOString().split("T")[1].split("Z")[0], dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1555
|
-
template = await evalTemplateVariable(template, prefix + "date-locale", () => date.toLocaleDateString(), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1556
|
-
template = await evalTemplateVariable(template, prefix + "time-locale", () => date.toLocaleTimeString(), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1557
|
-
template = await evalTemplateVariable(template, prefix + "day-locale", () => String(date.getDate()).padStart(2, "0"), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1558
|
-
template = await evalTemplateVariable(template, prefix + "month-locale", () => String(date.getMonth() + 1).padStart(2, "0"), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1559
|
-
template = await evalTemplateVariable(template, prefix + "year-locale", () => String(date.getFullYear()), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1560
|
-
template = await evalTemplateVariable(template, prefix + "datetime-locale", () => date.toLocaleString(), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1561
|
-
template = await evalTemplateVariable(template, prefix + "datetime-utc", () => date.toUTCString(), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1562
|
-
template = await evalTemplateVariable(template, prefix + "day-utc", () => String(date.getUTCDate()).padStart(2, "0"), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1563
|
-
template = await evalTemplateVariable(template, prefix + "month-utc", () => String(date.getUTCMonth() + 1).padStart(2, "0"), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1564
|
-
template = await evalTemplateVariable(template, prefix + "year-utc", () => String(date.getUTCFullYear()), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1565
|
-
template = await evalTemplateVariable(template, prefix + "hours-locale", () => String(date.getHours()).padStart(2, "0"), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1566
|
-
template = await evalTemplateVariable(template, prefix + "minutes-locale", () => String(date.getMinutes()).padStart(2, "0"), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1567
|
-
template = await evalTemplateVariable(template, prefix + "seconds-locale", () => String(date.getSeconds()).padStart(2, "0"), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1568
|
-
template = await evalTemplateVariable(template, prefix + "hours-utc", () => String(date.getUTCHours()).padStart(2, "0"), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1569
|
-
template = await evalTemplateVariable(template, prefix + "minutes-utc", () => String(date.getUTCMinutes()).padStart(2, "0"), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1570
|
-
template = await evalTemplateVariable(template, prefix + "seconds-utc", () => String(date.getUTCSeconds()).padStart(2, "0"), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1571
|
-
template = await evalTemplateVariable(template, prefix + "time-ms", () => String(date.getTime()), dontReplaceSlash, options.filenameReplacementCharacter);
|
|
1572
|
-
}
|
|
1573
|
-
}
|
|
1574
|
-
}
|
|
1575
|
-
|
|
1576
1485
|
static setBackgroundImage(element, url, style) {
|
|
1577
1486
|
element.style.setProperty("background-blend-mode", "normal", "important");
|
|
1578
1487
|
element.style.setProperty("background-clip", "content-box", "important");
|
|
@@ -2102,65 +2011,6 @@ function getOnEventAttributeNames(doc) {
|
|
|
2102
2011
|
return attributeNames;
|
|
2103
2012
|
}
|
|
2104
2013
|
|
|
2105
|
-
async function evalTemplateVariable(template, variableName, valueGetter, dontReplaceSlash, replacementCharacter) {
|
|
2106
|
-
let maxLength, maxCharLength;
|
|
2107
|
-
if (template) {
|
|
2108
|
-
const regExpVariable = "{\\s*" + variableName.replace(/\W|_/g, "[$&]") + "\\s*}";
|
|
2109
|
-
let replaceRegExp = new RegExp(regExpVariable + "\\[\\d+(ch)?\\]", "g");
|
|
2110
|
-
if (template.match(replaceRegExp)) {
|
|
2111
|
-
const matchedLength = template.match(replaceRegExp)[0];
|
|
2112
|
-
if (matchedLength.match(/\[(\d+)\]$/)) {
|
|
2113
|
-
maxLength = Number(matchedLength.match(/\[(\d+)\]$/)[1]);
|
|
2114
|
-
if (isNaN(maxLength) || maxLength <= 0) {
|
|
2115
|
-
maxLength = null;
|
|
2116
|
-
}
|
|
2117
|
-
} else {
|
|
2118
|
-
maxCharLength = Number(matchedLength.match(/\[(\d+)ch\]$/)[1]);
|
|
2119
|
-
if (isNaN(maxCharLength) || maxCharLength <= 0) {
|
|
2120
|
-
maxCharLength = null;
|
|
2121
|
-
}
|
|
2122
|
-
}
|
|
2123
|
-
} else {
|
|
2124
|
-
replaceRegExp = new RegExp(regExpVariable, "g");
|
|
2125
|
-
}
|
|
2126
|
-
if (template.match(replaceRegExp)) {
|
|
2127
|
-
let value = await valueGetter();
|
|
2128
|
-
if (!dontReplaceSlash) {
|
|
2129
|
-
value = value.replace(/\/+/g, replacementCharacter);
|
|
2130
|
-
}
|
|
2131
|
-
if (maxLength) {
|
|
2132
|
-
value = await util.truncateText(value, maxLength);
|
|
2133
|
-
} else if (maxCharLength) {
|
|
2134
|
-
value = value.substring(0, maxCharLength);
|
|
2135
|
-
}
|
|
2136
|
-
return template.replace(replaceRegExp, value);
|
|
2137
|
-
}
|
|
2138
|
-
}
|
|
2139
|
-
return template;
|
|
2140
|
-
}
|
|
2141
|
-
|
|
2142
|
-
function getLastSegment(url, replacementCharacter) {
|
|
2143
|
-
let lastSegmentMatch = url.pathname.match(/\/([^/]+)$/),
|
|
2144
|
-
lastSegment = lastSegmentMatch && lastSegmentMatch[0];
|
|
2145
|
-
if (!lastSegment) {
|
|
2146
|
-
lastSegmentMatch = url.href.match(/([^/]+)\/?$/);
|
|
2147
|
-
lastSegment = lastSegmentMatch && lastSegmentMatch[0];
|
|
2148
|
-
}
|
|
2149
|
-
if (!lastSegment) {
|
|
2150
|
-
lastSegmentMatch = lastSegment.match(/(.*)\.[^.]+$/);
|
|
2151
|
-
lastSegment = lastSegmentMatch && lastSegmentMatch[0];
|
|
2152
|
-
}
|
|
2153
|
-
if (!lastSegment) {
|
|
2154
|
-
lastSegment = url.hostname.replace(/\/+/g, replacementCharacter).replace(/\/$/, "");
|
|
2155
|
-
}
|
|
2156
|
-
lastSegmentMatch = lastSegment.match(/(.*)\.[^.]+$/);
|
|
2157
|
-
if (lastSegmentMatch && lastSegmentMatch[1]) {
|
|
2158
|
-
lastSegment = lastSegmentMatch[1];
|
|
2159
|
-
}
|
|
2160
|
-
lastSegment = lastSegment.replace(/\/$/, "").replace(/^\//, "");
|
|
2161
|
-
return lastSegment;
|
|
2162
|
-
}
|
|
2163
|
-
|
|
2164
2014
|
function getUrlFunctions(declarationList) {
|
|
2165
2015
|
return cssTree.findAll(declarationList, node => node.type == "Url");
|
|
2166
2016
|
}
|
package/single-file-helper.js
CHANGED
|
@@ -183,70 +183,72 @@ function preProcessDoc(doc, win, options) {
|
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
function getElementsInfo(win, doc, element, options, data = { usedFonts: new Map(), canvases: [], images: [], posters: [], videos: [], shadowRoots: [], markedElements: [] }, ascendantHidden) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
if (
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
186
|
+
if (element.childNodes) {
|
|
187
|
+
const elements = Array.from(element.childNodes).filter(node => (node instanceof win.HTMLElement) || (node instanceof win.SVGElement));
|
|
188
|
+
elements.forEach(element => {
|
|
189
|
+
let elementHidden, elementKept, computedStyle;
|
|
190
|
+
if (!options.autoSaveExternalSave && (options.removeHiddenElements || options.removeUnusedFonts || options.compressHTML)) {
|
|
191
|
+
computedStyle = getComputedStyle(win, element);
|
|
192
|
+
if (element instanceof win.HTMLElement) {
|
|
193
|
+
if (options.removeHiddenElements) {
|
|
194
|
+
elementKept = ((ascendantHidden || element.closest("html > head")) && KEPT_TAG_NAMES.includes(element.tagName)) || element.closest("details");
|
|
195
|
+
if (!elementKept) {
|
|
196
|
+
elementHidden = ascendantHidden || testHiddenElement(element, computedStyle);
|
|
197
|
+
if (elementHidden) {
|
|
198
|
+
element.setAttribute(HIDDEN_CONTENT_ATTRIBUTE_NAME, "");
|
|
199
|
+
data.markedElements.push(element);
|
|
200
|
+
}
|
|
199
201
|
}
|
|
200
202
|
}
|
|
201
203
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
204
|
+
if (!elementHidden) {
|
|
205
|
+
if (options.compressHTML && computedStyle) {
|
|
206
|
+
const whiteSpace = computedStyle.getPropertyValue("white-space");
|
|
207
|
+
if (whiteSpace && whiteSpace.startsWith("pre")) {
|
|
208
|
+
element.setAttribute(PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME, "");
|
|
209
|
+
data.markedElements.push(element);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (options.removeUnusedFonts) {
|
|
213
|
+
getUsedFont(computedStyle, options, data.usedFonts);
|
|
214
|
+
getUsedFont(getComputedStyle(win, element, ":first-letter"), options, data.usedFonts);
|
|
215
|
+
getUsedFont(getComputedStyle(win, element, ":before"), options, data.usedFonts);
|
|
216
|
+
getUsedFont(getComputedStyle(win, element, ":after"), options, data.usedFonts);
|
|
209
217
|
}
|
|
210
|
-
}
|
|
211
|
-
if (options.removeUnusedFonts) {
|
|
212
|
-
getUsedFont(computedStyle, options, data.usedFonts);
|
|
213
|
-
getUsedFont(getComputedStyle(win, element, ":first-letter"), options, data.usedFonts);
|
|
214
|
-
getUsedFont(getComputedStyle(win, element, ":before"), options, data.usedFonts);
|
|
215
|
-
getUsedFont(getComputedStyle(win, element, ":after"), options, data.usedFonts);
|
|
216
218
|
}
|
|
217
219
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
220
|
+
getResourcesInfo(win, doc, element, options, data, elementHidden, computedStyle);
|
|
221
|
+
const shadowRoot = !(element instanceof win.SVGElement) && getShadowRoot(element);
|
|
222
|
+
if (shadowRoot && !element.classList.contains(SINGLE_FILE_UI_ELEMENT_CLASS)) {
|
|
223
|
+
const shadowRootInfo = {};
|
|
224
|
+
element.setAttribute(SHADOW_ROOT_ATTRIBUTE_NAME, data.shadowRoots.length);
|
|
225
|
+
data.markedElements.push(element);
|
|
226
|
+
data.shadowRoots.push(shadowRootInfo);
|
|
227
|
+
getElementsInfo(win, doc, shadowRoot, options, data, elementHidden);
|
|
228
|
+
shadowRootInfo.content = shadowRoot.innerHTML;
|
|
229
|
+
shadowRootInfo.mode = shadowRoot.mode;
|
|
230
|
+
try {
|
|
231
|
+
if (shadowRoot.adoptedStyleSheets && shadowRoot.adoptedStyleSheets.length) {
|
|
232
|
+
shadowRootInfo.adoptedStyleSheets = Array.from(shadowRoot.adoptedStyleSheets).map(stylesheet => Array.from(stylesheet.cssRules).map(cssRule => cssRule.cssText).join("\n"));
|
|
233
|
+
}
|
|
234
|
+
} catch (error) {
|
|
235
|
+
// ignored
|
|
232
236
|
}
|
|
233
|
-
} catch (error) {
|
|
234
|
-
// ignored
|
|
235
237
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
238
|
+
getElementsInfo(win, doc, element, options, data, elementHidden);
|
|
239
|
+
if (!options.autoSaveExternalSave && options.removeHiddenElements && ascendantHidden) {
|
|
240
|
+
if (elementKept || element.getAttribute(KEPT_CONTENT_ATTRIBUTE_NAME) == "") {
|
|
241
|
+
if (element.parentElement) {
|
|
242
|
+
element.parentElement.setAttribute(KEPT_CONTENT_ATTRIBUTE_NAME, "");
|
|
243
|
+
data.markedElements.push(element.parentElement);
|
|
244
|
+
}
|
|
245
|
+
} else if (elementHidden) {
|
|
246
|
+
element.setAttribute(REMOVED_CONTENT_ATTRIBUTE_NAME, "");
|
|
247
|
+
data.markedElements.push(element);
|
|
243
248
|
}
|
|
244
|
-
} else if (elementHidden) {
|
|
245
|
-
element.setAttribute(REMOVED_CONTENT_ATTRIBUTE_NAME, "");
|
|
246
|
-
data.markedElements.push(element);
|
|
247
249
|
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
250
252
|
return data;
|
|
251
253
|
}
|
|
252
254
|
|
package/single-file-util.js
CHANGED
|
@@ -115,20 +115,11 @@ function getInstance(utilOptions) {
|
|
|
115
115
|
getContentSize(content) {
|
|
116
116
|
return new Blob([content]).size;
|
|
117
117
|
},
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return
|
|
123
|
-
reader.addEventListener("load", () => {
|
|
124
|
-
if (content.startsWith(reader.result)) {
|
|
125
|
-
resolve(reader.result);
|
|
126
|
-
} else {
|
|
127
|
-
this.truncateText(content, maxSize - 1).then(resolve).catch(reject);
|
|
128
|
-
}
|
|
129
|
-
}, false);
|
|
130
|
-
reader.addEventListener("error", reject, false);
|
|
131
|
-
});
|
|
118
|
+
formatFilename(content, options) {
|
|
119
|
+
return modules.templateFormatter.formatFilename(content, options, this);
|
|
120
|
+
},
|
|
121
|
+
evalTemplate(template, options, content, dontReplaceSlash) {
|
|
122
|
+
return modules.templateFormatter.evalTemplate(template, options, this, content, dontReplaceSlash);
|
|
132
123
|
},
|
|
133
124
|
minifyHTML(doc, options) {
|
|
134
125
|
return modules.htmlMinifier.process(doc, options);
|