single-file-core 1.6.6 → 1.6.8
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/index.js
CHANGED
|
@@ -146,7 +146,8 @@ const STAGES = [{
|
|
|
146
146
|
}, {
|
|
147
147
|
sequential: [
|
|
148
148
|
{ option: "removeAlternativeImages", action: "removeAlternativeImages" },
|
|
149
|
-
{ action: "groupDuplicateFonts" }
|
|
149
|
+
{ action: "groupDuplicateFonts" },
|
|
150
|
+
{ action: "groupDuplicateImages" }
|
|
150
151
|
],
|
|
151
152
|
parallel: [
|
|
152
153
|
{ option: "removeAlternativeFonts", action: "removeAlternativeFonts" },
|
|
@@ -434,9 +435,11 @@ const SCRIPT_OPTIONS = "data-single-file-options";
|
|
|
434
435
|
const JAVASCRIPT_URI_PROTOCOL = "javascript:";
|
|
435
436
|
const DISABLED_SCRIPT_URI = "javascript:void(0)";
|
|
436
437
|
const SCRIPT_URI_ATTRIBUTE_NAMES = ["href", "src", "action", "formaction", "data"];
|
|
438
|
+
const SVG_NAMESPACE_URI = "http://www.w3.org/2000/svg";
|
|
437
439
|
const UTF8_CHARSET = "utf-8";
|
|
438
440
|
const TAINTED_CANVAS_WARNING_MESSAGE = "SingleFile: canvas elements tainted by a cross-origin resource, dropped from the page:";
|
|
439
441
|
const EMPTY_RESOURCE = "data:,";
|
|
442
|
+
const ORDER_DEPENDENT_RULE = /@(layer|import)\b/i;
|
|
440
443
|
|
|
441
444
|
class Processor {
|
|
442
445
|
constructor(options, processorHelper, batchRequest) {
|
|
@@ -1274,23 +1277,32 @@ class Processor {
|
|
|
1274
1277
|
}
|
|
1275
1278
|
|
|
1276
1279
|
async resolveStylesheetsURLs() {
|
|
1277
|
-
const
|
|
1280
|
+
const styleElementGroups = new Map();
|
|
1278
1281
|
this.options.inlineStylesheets = new Map();
|
|
1279
1282
|
this.options.inlineStylesheetsRefs = new Map();
|
|
1280
1283
|
this.doc.querySelectorAll("style").forEach(styleElement => {
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
if (
|
|
1284
|
-
|
|
1285
|
-
styleElement,
|
|
1286
|
-
content: styleElement.textContent
|
|
1287
|
-
});
|
|
1288
|
-
stylesContents.push(styleElement.textContent);
|
|
1289
|
-
} else {
|
|
1290
|
-
this.options.inlineStylesheetsRefs.set(styleElement, indexContent);
|
|
1284
|
+
const content = styleElement.textContent;
|
|
1285
|
+
if (content) {
|
|
1286
|
+
if (!styleElementGroups.has(content)) {
|
|
1287
|
+
styleElementGroups.set(content, []);
|
|
1291
1288
|
}
|
|
1289
|
+
styleElementGroups.get(content).push(styleElement);
|
|
1292
1290
|
}
|
|
1293
1291
|
});
|
|
1292
|
+
let indexContent = 0;
|
|
1293
|
+
styleElementGroups.forEach((styleElements, content) => {
|
|
1294
|
+
const masterIndex = ORDER_DEPENDENT_RULE.test(content) ? 0 : styleElements.length - 1;
|
|
1295
|
+
this.options.inlineStylesheets.set(indexContent, {
|
|
1296
|
+
styleElement: styleElements[masterIndex],
|
|
1297
|
+
content
|
|
1298
|
+
});
|
|
1299
|
+
styleElements.forEach((styleElement, index) => {
|
|
1300
|
+
if (index != masterIndex) {
|
|
1301
|
+
this.options.inlineStylesheetsRefs.set(styleElement, indexContent);
|
|
1302
|
+
}
|
|
1303
|
+
});
|
|
1304
|
+
indexContent++;
|
|
1305
|
+
});
|
|
1294
1306
|
await Promise.all(Array.from(this.doc.querySelectorAll("style, link[rel*=stylesheet]:not([disabled])")).map(async element => {
|
|
1295
1307
|
const options = Object.assign({}, this.options, { charset: this.charset });
|
|
1296
1308
|
let mediaText;
|
|
@@ -1556,6 +1568,10 @@ class Processor {
|
|
|
1556
1568
|
this.processorHelper.groupDuplicateFonts(this.stylesheets, this.resources.fonts, this.options);
|
|
1557
1569
|
}
|
|
1558
1570
|
|
|
1571
|
+
groupDuplicateImages() {
|
|
1572
|
+
this.processorHelper.groupDuplicateImages(this.doc, this.stylesheets, this.styles, this.resources.images);
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1559
1575
|
async removeAlternativeFonts() {
|
|
1560
1576
|
await this.processorHelper.removeAlternativeFonts(this.doc, this.stylesheets, this.resources.fonts, this.options.fontTests);
|
|
1561
1577
|
}
|
|
@@ -1747,13 +1763,15 @@ function isScriptURI(value) {
|
|
|
1747
1763
|
}
|
|
1748
1764
|
|
|
1749
1765
|
function getOnEventAttributeNames(doc) {
|
|
1750
|
-
const
|
|
1766
|
+
const elements = [doc.body || doc.createElement("div"), doc.createElementNS(SVG_NAMESPACE_URI, "animate")];
|
|
1751
1767
|
const attributeNames = [];
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1768
|
+
elements.forEach(element => {
|
|
1769
|
+
for (const propertyName in element) {
|
|
1770
|
+
if (propertyName.startsWith("on")) {
|
|
1771
|
+
attributeNames.push(propertyName);
|
|
1772
|
+
}
|
|
1755
1773
|
}
|
|
1756
|
-
}
|
|
1774
|
+
});
|
|
1757
1775
|
return attributeNames;
|
|
1758
1776
|
}
|
|
1759
1777
|
|
package/core/infobar.js
CHANGED
|
@@ -157,7 +157,7 @@ const INFOBAR_ANIMATIONS_STYLES = `
|
|
|
157
157
|
animation-iteration-count: 2;
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
.infobar
|
|
160
|
+
.infobar::after {
|
|
161
161
|
content: "";
|
|
162
162
|
position: absolute;
|
|
163
163
|
inset: -2px;
|
|
@@ -170,6 +170,12 @@ const INFOBAR_ANIMATIONS_STYLES = `
|
|
|
170
170
|
animation-timing-function: ease-out;
|
|
171
171
|
animation-delay: 2s;
|
|
172
172
|
animation-iteration-count: 3;
|
|
173
|
+
transition: visibility 0s 999999s;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.infobar:focus-within::after, .infobar.infobar-focus::after {
|
|
177
|
+
visibility: hidden;
|
|
178
|
+
transition-delay: 0s;
|
|
173
179
|
}
|
|
174
180
|
|
|
175
181
|
@keyframes flash {
|
|
@@ -194,7 +200,7 @@ const INFOBAR_ANIMATIONS_STYLES = `
|
|
|
194
200
|
|
|
195
201
|
@media (prefers-reduced-motion: reduce) {
|
|
196
202
|
.infobar,
|
|
197
|
-
.infobar
|
|
203
|
+
.infobar::after {
|
|
198
204
|
animation-name: none;
|
|
199
205
|
}
|
|
200
206
|
}
|
|
@@ -486,6 +486,9 @@ class ProcessorHelperCommon {
|
|
|
486
486
|
groupDuplicateFonts() {
|
|
487
487
|
}
|
|
488
488
|
|
|
489
|
+
groupDuplicateImages() {
|
|
490
|
+
}
|
|
491
|
+
|
|
489
492
|
getFontsDetails(doc, cssRules, sheetIndex, mediaFontsDetails) {
|
|
490
493
|
let mediaIndex = 0, supportsIndex = 0, layerIndex = 0;
|
|
491
494
|
cssRules.forEach(ruleData => {
|
|
@@ -127,33 +127,40 @@ function getProcessorHelperClass(utilInstance) {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
replaceStylesheets(doc, stylesheets, options) {
|
|
130
|
-
doc.querySelectorAll("style")
|
|
130
|
+
const styleElements = Array.from(doc.querySelectorAll("style"));
|
|
131
|
+
styleElements.forEach(element => {
|
|
132
|
+
const stylesheetInfo = stylesheets.get(element);
|
|
133
|
+
if (stylesheetInfo && !options.inlineStylesheetsRefs.has(element)) {
|
|
134
|
+
element.textContent = this.generateStylesheetContent(stylesheetInfo.stylesheet, options);
|
|
135
|
+
options.inlineStylesheets.forEach(({ styleElement }, index) => {
|
|
136
|
+
if (styleElement === element) {
|
|
137
|
+
options.inlineStylesheets.set(index, {
|
|
138
|
+
styleElement,
|
|
139
|
+
content: element.textContent
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
styleElements.forEach(element => {
|
|
131
146
|
const stylesheetInfo = stylesheets.get(element);
|
|
132
147
|
if (stylesheetInfo) {
|
|
133
148
|
stylesheets.delete(element);
|
|
134
149
|
const stylesheetRefIndex = options.inlineStylesheetsRefs.get(element);
|
|
135
|
-
if (stylesheetRefIndex
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
options.inlineStylesheets.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
150
|
+
if (stylesheetRefIndex !== undefined) {
|
|
151
|
+
if (options.groupDuplicateStylesheets) {
|
|
152
|
+
if (!doc.querySelector("style[" + DUPLICATE_STYLESHEET_ATTRIBUTE_NAME + "=\"" + stylesheetRefIndex + "\"]")) {
|
|
153
|
+
const styleElement = doc.createElement("style");
|
|
154
|
+
styleElement.textContent = options.inlineStylesheets.get(stylesheetRefIndex).content;
|
|
155
|
+
styleElement.setAttribute("media", "not all");
|
|
156
|
+
styleElement.setAttribute(DUPLICATE_STYLESHEET_ATTRIBUTE_NAME, stylesheetRefIndex);
|
|
157
|
+
doc.head.appendChild(styleElement);
|
|
143
158
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
styleElement.textContent = options.inlineStylesheets.get(stylesheetRefIndex).content;
|
|
149
|
-
styleElement.setAttribute("media", "not all");
|
|
150
|
-
styleElement.setAttribute(DUPLICATE_STYLESHEET_ATTRIBUTE_NAME, stylesheetRefIndex);
|
|
151
|
-
doc.head.appendChild(styleElement);
|
|
159
|
+
element.textContent = "/* */";
|
|
160
|
+
element.setAttribute("onload", "this.textContent=document.querySelector('style[" + DUPLICATE_STYLESHEET_ATTRIBUTE_NAME + "=\"" + stylesheetRefIndex + "\"]')?.textContent;this.removeAttribute('onload')");
|
|
161
|
+
} else {
|
|
162
|
+
element.textContent = options.inlineStylesheets.get(stylesheetRefIndex).content;
|
|
152
163
|
}
|
|
153
|
-
element.textContent = "/* */";
|
|
154
|
-
element.setAttribute("onload", "this.textContent=document.querySelector('style[" + DUPLICATE_STYLESHEET_ATTRIBUTE_NAME + "=\"" + stylesheetRefIndex + "\"]')?.textContent;this.removeAttribute('onload')");
|
|
155
|
-
} else {
|
|
156
|
-
element.textContent = options.inlineStylesheets.get(stylesheetRefIndex).content;
|
|
157
164
|
}
|
|
158
165
|
if (stylesheetInfo.mediaText) {
|
|
159
166
|
element.media = stylesheetInfo.mediaText;
|
|
@@ -38,6 +38,9 @@ const LOCAL_SOURCE = "local(";
|
|
|
38
38
|
const FONT_MAX_LOAD_DELAY = 5000;
|
|
39
39
|
const SCRIPT_EXTENSION = ".js";
|
|
40
40
|
const LINK_OWN_ATTRIBUTE_NAMES = ["rel", "type", "href", "media"];
|
|
41
|
+
const SRCSET_ATTRIBUTE_NAME = "srcset";
|
|
42
|
+
const IMAGE_ATTRIBUTE_NAMES = ["src", "href", "data", "poster", "background", "xlink:href", SRCSET_ATTRIBUTE_NAME];
|
|
43
|
+
const IMAGE_ATTRIBUTE_SELECTOR = "[src], [href], [data], [poster], [background], [srcset], image, feImage";
|
|
41
44
|
|
|
42
45
|
let util;
|
|
43
46
|
|
|
@@ -103,36 +106,49 @@ function getProcessorHelperClass(utilInstance) {
|
|
|
103
106
|
const entries = Array.from(stylesheets).reverse();
|
|
104
107
|
const linkElements = new Map();
|
|
105
108
|
const sharedStyleElements = new Map();
|
|
109
|
+
const emptyStylesheetRefIndexes = new Set();
|
|
106
110
|
Array.from(new Set(options.inlineStylesheetsRefs.values())).forEach(stylesheetRefIndex => {
|
|
107
|
-
const linkElement = doc.createElement("link");
|
|
108
|
-
linkElement.setAttribute("rel", "stylesheet");
|
|
109
|
-
linkElement.setAttribute("type", "text/css");
|
|
110
|
-
const name = "stylesheet_" + resources.stylesheets.size + ".css";
|
|
111
|
-
linkElement.setAttribute("href", name);
|
|
112
111
|
const { styleElement, content } = options.inlineStylesheets.get(stylesheetRefIndex);
|
|
113
112
|
const sharedEntry = entries.find(([key]) => key.element == styleElement);
|
|
114
113
|
const stylesheet = sharedEntry
|
|
115
114
|
? sharedEntry[1].stylesheet
|
|
116
115
|
: cssTree.parse(content, { context: "stylesheet", parseCustomProperty: true });
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
if (isEmptyStylesheet(stylesheet)) {
|
|
117
|
+
emptyStylesheetRefIndexes.add(stylesheetRefIndex);
|
|
118
|
+
} else {
|
|
119
|
+
const linkElement = doc.createElement("link");
|
|
120
|
+
linkElement.setAttribute("rel", "stylesheet");
|
|
121
|
+
linkElement.setAttribute("type", "text/css");
|
|
122
|
+
const name = "stylesheet_" + resources.stylesheets.size + ".css";
|
|
123
|
+
linkElement.setAttribute("href", name);
|
|
124
|
+
resources.stylesheets.set(resources.stylesheets.size, { name, stylesheet });
|
|
125
|
+
linkElements.set(stylesheetRefIndex, linkElement);
|
|
126
|
+
}
|
|
119
127
|
sharedStyleElements.set(styleElement, stylesheetRefIndex);
|
|
120
128
|
});
|
|
121
129
|
for (const [key, stylesheetInfo] of entries) {
|
|
122
130
|
if (key.urlNode) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
key.urlNode.type = "Url";
|
|
126
|
-
key.urlNode.value = "-sf-url-original(" + JSON.stringify(stylesheetInfo.url) + ") " + name;
|
|
131
|
+
if (isEmptyStylesheet(stylesheetInfo.stylesheet) && !key.importDeclaresLayer) {
|
|
132
|
+
removeImportRule(key.importParent, key.importNode);
|
|
127
133
|
} else {
|
|
128
|
-
|
|
134
|
+
const name = "stylesheet_" + resources.stylesheets.size + ".css";
|
|
135
|
+
if (!isDataURL(stylesheetInfo.url) && options.saveOriginalURLs) {
|
|
136
|
+
key.urlNode.type = "Url";
|
|
137
|
+
key.urlNode.value = "-sf-url-original(" + JSON.stringify(stylesheetInfo.url) + ") " + name;
|
|
138
|
+
} else {
|
|
139
|
+
key.urlNode.value = name;
|
|
140
|
+
}
|
|
141
|
+
resources.stylesheets.set(resources.stylesheets.size, { name, stylesheet: stylesheetInfo.stylesheet, url: stylesheetInfo.url });
|
|
129
142
|
}
|
|
130
|
-
resources.stylesheets.set(resources.stylesheets.size, { name, stylesheet: stylesheetInfo.stylesheet, url: stylesheetInfo.url });
|
|
131
143
|
} else if (key.element.tagName.toUpperCase() == "LINK") {
|
|
132
144
|
const linkElement = key.element;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
145
|
+
if (isEmptyStylesheet(stylesheetInfo.stylesheet)) {
|
|
146
|
+
linkElement.remove();
|
|
147
|
+
} else {
|
|
148
|
+
const name = "stylesheet_" + resources.stylesheets.size + ".css";
|
|
149
|
+
linkElement.setAttribute("href", name);
|
|
150
|
+
resources.stylesheets.set(resources.stylesheets.size, { name, stylesheet: stylesheetInfo.stylesheet, url: stylesheetInfo.url });
|
|
151
|
+
}
|
|
136
152
|
} else {
|
|
137
153
|
const styleElement = key.element;
|
|
138
154
|
const stylesheetRefIndex = options.inlineStylesheetsRefs.has(styleElement)
|
|
@@ -140,6 +156,8 @@ function getProcessorHelperClass(utilInstance) {
|
|
|
140
156
|
: sharedStyleElements.get(styleElement);
|
|
141
157
|
if (stylesheetRefIndex === undefined) {
|
|
142
158
|
styleElement.textContent = this.generateStylesheetContent(stylesheetInfo.stylesheet, options);
|
|
159
|
+
} else if (emptyStylesheetRefIndexes.has(stylesheetRefIndex)) {
|
|
160
|
+
styleElement.remove();
|
|
143
161
|
} else {
|
|
144
162
|
const linkElement = linkElements.get(stylesheetRefIndex).cloneNode(true);
|
|
145
163
|
Array.from(styleElement.attributes).forEach(({ name, value }) => {
|
|
@@ -200,7 +218,8 @@ function getProcessorHelperClass(utilInstance) {
|
|
|
200
218
|
layerName,
|
|
201
219
|
supportsCondition
|
|
202
220
|
};
|
|
203
|
-
|
|
221
|
+
const importDeclaresLayer = Boolean(cssTree.find(node, node => node.type == "Layer" || ((node.type == "Identifier" || node.type == "Function") && node.name.toLowerCase() == "layer")));
|
|
222
|
+
stylesheets.set({ urlNode, importNode: node, importParent: stylesheet, importDeclaresLayer }, stylesheetInfo);
|
|
204
223
|
const requestedURL = resourceURL;
|
|
205
224
|
const content = await this.getStylesheetContent(resourceURL, options);
|
|
206
225
|
stylesheetInfo.url = resourceURL = content.resourceURL;
|
|
@@ -260,7 +279,7 @@ function getProcessorHelperClass(utilInstance) {
|
|
|
260
279
|
} else {
|
|
261
280
|
frameElement.setAttribute("src", name + "index.html");
|
|
262
281
|
}
|
|
263
|
-
resources.frames.set(frameWindowId, { name, content: pageData.content, resources: pageData.resources, url: frameData.url });
|
|
282
|
+
resources.frames.set(frameWindowId, { name, content: pageData.content, resources: pageData.resources, url: frameData.url, title: pageData.title });
|
|
264
283
|
}
|
|
265
284
|
|
|
266
285
|
async processFont(resourceURL, urlNode, originalResourceURL, baseURI, options, resources, batchRequest) {
|
|
@@ -294,12 +313,54 @@ function getProcessorHelperClass(utilInstance) {
|
|
|
294
313
|
if (canonicalNames.size) {
|
|
295
314
|
stylesheets.forEach(stylesheetInfo => {
|
|
296
315
|
if (stylesheetInfo.stylesheet) {
|
|
297
|
-
getUrlFunctions(stylesheetInfo.stylesheet).forEach(urlNode =>
|
|
316
|
+
getUrlFunctions(stylesheetInfo.stylesheet).forEach(urlNode => replaceResourceName(urlNode, canonicalNames));
|
|
298
317
|
}
|
|
299
318
|
});
|
|
300
319
|
}
|
|
301
320
|
}
|
|
302
321
|
|
|
322
|
+
groupDuplicateImages(doc, stylesheets, styles, images) {
|
|
323
|
+
const canonicalNames = new Map();
|
|
324
|
+
const resourcesBySize = new Map();
|
|
325
|
+
[...images]
|
|
326
|
+
.filter(([, resource]) => resource.content && resource.content.length)
|
|
327
|
+
.sort(([indexResource], [otherIndexResource]) => indexResource - otherIndexResource)
|
|
328
|
+
.forEach(([indexResource, resource]) => {
|
|
329
|
+
const sameSizeResources = resourcesBySize.get(resource.content.length) || [];
|
|
330
|
+
const original = sameSizeResources.find(previousResource => testSameContent(previousResource.content, resource.content));
|
|
331
|
+
if (original) {
|
|
332
|
+
canonicalNames.set(resource.name, original.name);
|
|
333
|
+
images.delete(indexResource);
|
|
334
|
+
} else {
|
|
335
|
+
sameSizeResources.push(resource);
|
|
336
|
+
resourcesBySize.set(resource.content.length, sameSizeResources);
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
if (canonicalNames.size) {
|
|
340
|
+
stylesheets.forEach(stylesheetInfo => {
|
|
341
|
+
if (stylesheetInfo.stylesheet) {
|
|
342
|
+
getUrlFunctions(stylesheetInfo.stylesheet).forEach(urlNode => replaceResourceName(urlNode, canonicalNames));
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
styles.forEach(declarationList => getUrlFunctions(declarationList).forEach(urlNode => replaceResourceName(urlNode, canonicalNames)));
|
|
346
|
+
doc.querySelectorAll(IMAGE_ATTRIBUTE_SELECTOR).forEach(element => {
|
|
347
|
+
IMAGE_ATTRIBUTE_NAMES.forEach(attributeName => {
|
|
348
|
+
const value = element.getAttribute(attributeName);
|
|
349
|
+
if (value !== null) {
|
|
350
|
+
if (canonicalNames.has(value)) {
|
|
351
|
+
element.setAttribute(attributeName, canonicalNames.get(value));
|
|
352
|
+
} else if (attributeName == SRCSET_ATTRIBUTE_NAME) {
|
|
353
|
+
const srcset = util.parseSrcset(value);
|
|
354
|
+
if (srcset.some(srcsetValue => canonicalNames.has(srcsetValue.url))) {
|
|
355
|
+
element.setAttribute(attributeName, serializeSrcset(srcset.map(srcsetValue => Object.assign({}, srcsetValue, { url: canonicalNames.get(srcsetValue.url) || srcsetValue.url }))));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
303
364
|
async processStyle(ruleData, options, resources, batchRequest) {
|
|
304
365
|
const urls = getUrlFunctions(ruleData);
|
|
305
366
|
await Promise.all(urls.map(async urlNode => {
|
|
@@ -594,6 +655,26 @@ function getProcessorHelperClass(utilInstance) {
|
|
|
594
655
|
};
|
|
595
656
|
}
|
|
596
657
|
|
|
658
|
+
function isEmptyStylesheet(stylesheet) {
|
|
659
|
+
return !stylesheet || !stylesheet.children || !stylesheet.children.size;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
function removeImportRule(parentStylesheet, importNode) {
|
|
663
|
+
let importItem, importList;
|
|
664
|
+
cssTree.walk(parentStylesheet, {
|
|
665
|
+
visit: "Atrule",
|
|
666
|
+
enter(node, item, list) {
|
|
667
|
+
if (node === importNode) {
|
|
668
|
+
importItem = item;
|
|
669
|
+
importList = list;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
});
|
|
673
|
+
if (importItem) {
|
|
674
|
+
importList.remove(importItem);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
597
678
|
function testSameContent(content, otherContent) {
|
|
598
679
|
if (content.length != otherContent.length) {
|
|
599
680
|
return false;
|
|
@@ -606,7 +687,7 @@ function testSameContent(content, otherContent) {
|
|
|
606
687
|
return true;
|
|
607
688
|
}
|
|
608
689
|
|
|
609
|
-
function
|
|
690
|
+
function replaceResourceName(urlNode, canonicalNames) {
|
|
610
691
|
canonicalNames.forEach((canonicalName, name) => {
|
|
611
692
|
if (urlNode.value == name) {
|
|
612
693
|
urlNode.value = canonicalName;
|
|
@@ -58,6 +58,7 @@ const PARSE_CSS_ERROR_MESSAGE = "Failed to parse CSS";
|
|
|
58
58
|
const QSA_ERROR_MESSAGE = "Failed to match selector";
|
|
59
59
|
const PRELUDE_SEPARATOR = ",";
|
|
60
60
|
const NESTING_SELECTOR = "&";
|
|
61
|
+
const SCOPE_PSEUDO_CLASS = ":scope";
|
|
61
62
|
const VENDOR_PREFIX = "-";
|
|
62
63
|
const CUSTOM_PROPERTY_PREFIX = "--";
|
|
63
64
|
const LAYER_NAME_SEPARATOR = ".";
|
|
@@ -388,7 +389,7 @@ function minifyStylesheetRule(ruleData, cssRule, stylesheets, processingContext,
|
|
|
388
389
|
|
|
389
390
|
function processSelectors(ruleData, processingContext, docContext) {
|
|
390
391
|
const removedSelectors = [];
|
|
391
|
-
const { ancestorsSelectors } = processingContext;
|
|
392
|
+
const { ancestorsSelectors, scopeStack } = processingContext;
|
|
392
393
|
for (let selector = ruleData.prelude.children.head, selectorIndex = 0; selector; selector = selector.next, selectorIndex++) {
|
|
393
394
|
const {
|
|
394
395
|
startsWithCombinator,
|
|
@@ -400,7 +401,8 @@ function processSelectors(ruleData, processingContext, docContext) {
|
|
|
400
401
|
}
|
|
401
402
|
registerSelector(selector, ruleData, processingContext, docContext);
|
|
402
403
|
if (!startsWithCombinator || !ancestorsSelectors || !ancestorsSelectors.length) {
|
|
403
|
-
const
|
|
404
|
+
const relativeToScope = startsWithCombinator && Boolean(scopeStack && scopeStack.length);
|
|
405
|
+
const matchedElements = matchElements(selector, ancestorsSelectors, scopeStack, docContext, relativeToScope);
|
|
404
406
|
if (matchedElements.length) {
|
|
405
407
|
if (!hasUnqueryableSelector) {
|
|
406
408
|
updateMatchingSelectors(matchedElements, selector, docContext);
|
|
@@ -580,8 +582,11 @@ function getConditionalStackForSelector(selector, docContext) {
|
|
|
580
582
|
return conditionalStack;
|
|
581
583
|
}
|
|
582
584
|
|
|
583
|
-
function matchElements(selector, ancestorsSelectors, scopeStack, docContext) {
|
|
584
|
-
|
|
585
|
+
function matchElements(selector, ancestorsSelectors, scopeStack, docContext, relativeToScope) {
|
|
586
|
+
let selectorText = createSelectorText(selector, ancestorsSelectors, docContext);
|
|
587
|
+
if (relativeToScope) {
|
|
588
|
+
selectorText = SCOPE_PSEUDO_CLASS + selectorText;
|
|
589
|
+
}
|
|
585
590
|
const cacheKey = createScopeCacheKey(selectorText, scopeStack);
|
|
586
591
|
const cachedNodes = docContext.matchedSelectors.get(cacheKey);
|
|
587
592
|
if (cachedNodes) {
|