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 stylesContents = [];
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
- if (styleElement.textContent) {
1282
- const indexContent = stylesContents.indexOf(styleElement.textContent);
1283
- if (indexContent == -1) {
1284
- this.options.inlineStylesheets.set(stylesContents.length, {
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 element = doc.body || doc.createElement("div");
1766
+ const elements = [doc.body || doc.createElement("div"), doc.createElementNS(SVG_NAMESPACE_URI, "animate")];
1751
1767
  const attributeNames = [];
1752
- for (const propertyName in element) {
1753
- if (propertyName.startsWith("on")) {
1754
- attributeNames.push(propertyName);
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:not(:focus-within):not(.infobar-focus)::after {
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:not(:focus-within):not(.infobar-focus)::after {
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").forEach(element => {
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 === undefined) {
136
- element.textContent = this.generateStylesheetContent(stylesheetInfo.stylesheet, options);
137
- options.inlineStylesheets.forEach(({ styleElement }, index) => {
138
- if (styleElement === element) {
139
- options.inlineStylesheets.set(index, {
140
- styleElement,
141
- content: element.textContent
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
- } else if (options.groupDuplicateStylesheets) {
146
- if (!doc.querySelector("style[" + DUPLICATE_STYLESHEET_ATTRIBUTE_NAME + "=\"" + stylesheetRefIndex + "\"]")) {
147
- const styleElement = doc.createElement("style");
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
- resources.stylesheets.set(resources.stylesheets.size, { name, stylesheet });
118
- linkElements.set(stylesheetRefIndex, linkElement);
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
- const name = "stylesheet_" + resources.stylesheets.size + ".css";
124
- if (!isDataURL(stylesheetInfo.url) && options.saveOriginalURLs) {
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
- key.urlNode.value = name;
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
- const name = "stylesheet_" + resources.stylesheets.size + ".css";
134
- linkElement.setAttribute("href", name);
135
- resources.stylesheets.set(resources.stylesheets.size, { name, stylesheet: stylesheetInfo.stylesheet, url: stylesheetInfo.url });
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
- stylesheets.set({ urlNode }, stylesheetInfo);
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 => replaceFontName(urlNode, canonicalNames));
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 replaceFontName(urlNode, canonicalNames) {
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 matchedElements = matchElements(selector, ancestorsSelectors, processingContext.scopeStack, docContext);
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
- const selectorText = createSelectorText(selector, ancestorsSelectors, docContext);
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "single-file-core",
3
- "version": "1.6.6",
3
+ "version": "1.6.8",
4
4
  "description": "SingleFile Core",
5
5
  "author": "Gildas Lormeau",
6
6
  "license": "AGPL-3.0-or-later",