single-file-core 1.3.8 → 1.3.9

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.
@@ -142,10 +142,13 @@ function getProcessorHelperClass(utilInstance) {
142
142
  mediaText = cssTree.generate(mediaQueryListNode);
143
143
  }
144
144
  const existingStylesheet = Array.from(stylesheets).find(([, stylesheetInfo]) => stylesheetInfo.resourceURL == resourceURL);
145
+ let stylesheet;
145
146
  if (existingStylesheet) {
147
+ stylesheet = existingStylesheet[1].stylesheet;
146
148
  stylesheets.set({ urlNode }, {
147
149
  url: resourceURL,
148
- stylesheet: existingStylesheet[1].stylesheet, scoped
150
+ stylesheet,
151
+ scoped
149
152
  });
150
153
  } else {
151
154
  const stylesheetInfo = {
@@ -156,9 +159,11 @@ function getProcessorHelperClass(utilInstance) {
156
159
  stylesheetInfo.url = resourceURL = content.resourceURL;
157
160
  content.data = getUpdatedResourceContent(resourceURL, options) || content.data;
158
161
  stylesheetInfo.stylesheet = cssTree.parse(content.data, { context: "stylesheet", parseCustomProperty: true });
162
+ stylesheet = stylesheetInfo.stylesheet;
159
163
  await this.resolveImportURLs(stylesheetInfo, resourceURL, options, workStylesheet, resources, stylesheets);
160
164
  stylesheets.set({ urlNode }, stylesheetInfo);
161
165
  }
166
+ urlNode.importedChildren = stylesheet.children;
162
167
  }
163
168
  }
164
169
  }
@@ -100,10 +100,11 @@ function process(doc, stylesheets, styles, options) {
100
100
  }));
101
101
  unusedFonts = fontsInfo.declared.filter(fontInfo => !filteredUsedFonts.has(fontInfo.fontFamily));
102
102
  }
103
+ const docChars = Array.from(new Set(docContent)).map(char => char.charCodeAt(0)).sort((value1, value2) => value1 - value2);
103
104
  stylesheets.forEach(stylesheetInfo => {
104
105
  const cssRules = stylesheetInfo.stylesheet.children;
105
106
  if (cssRules) {
106
- filterUnusedFonts(cssRules, fontsInfo.declared, unusedFonts, filteredUsedFonts, docContent);
107
+ filterUnusedFonts(cssRules, fontsInfo.declared, unusedFonts, filteredUsedFonts, docChars);
107
108
  stats.rules.discarded -= cssRules.size;
108
109
  }
109
110
  });
@@ -134,17 +135,19 @@ function getFontsInfo(cssRules, fontsInfo, options) {
134
135
  });
135
136
  }
136
137
 
137
- function filterUnusedFonts(cssRules, declaredFonts, unusedFonts, filteredUsedFonts, docContent) {
138
+ function filterUnusedFonts(cssRules, declaredFonts, unusedFonts, filteredUsedFonts, docChars) {
138
139
  const removedRules = [];
139
140
  for (let cssRule = cssRules.head; cssRule; cssRule = cssRule.next) {
140
141
  const ruleData = cssRule.data;
141
- if (ruleData.type == "Atrule" && (ruleData.name == "media" || ruleData.name == "supports" || ruleData.name == "layer") && ruleData.block && ruleData.block.children) {
142
- filterUnusedFonts(ruleData.block.children, declaredFonts, unusedFonts, filteredUsedFonts, docContent);
142
+ if (ruleData.type == "Atrule" && ruleData.name == "import" && ruleData.prelude && ruleData.prelude.children && ruleData.prelude.children.head.data.importedChildren) {
143
+ filterUnusedFonts(ruleData.prelude.children.head.data.importedChildren, declaredFonts, unusedFonts, filteredUsedFonts, docChars);
144
+ } else if (ruleData.type == "Atrule" && (ruleData.name == "media" || ruleData.name == "supports" || ruleData.name == "layer") && ruleData.block && ruleData.block.children) {
145
+ filterUnusedFonts(ruleData.block.children, declaredFonts, unusedFonts, filteredUsedFonts, docChars);
143
146
  } else if (ruleData.type == "Atrule" && ruleData.name == "font-face") {
144
147
  const fontFamily = helper.normalizeFontFamily(getDeclarationValue(ruleData.block.children, "font-family"));
145
148
  if (fontFamily) {
146
149
  const unicodeRange = getDeclarationValue(ruleData.block.children, "unicode-range");
147
- if (unusedFonts.find(fontInfo => fontInfo.fontFamily == fontFamily) || !testUnicodeRange(docContent, unicodeRange) || !testUsedFont(ruleData, fontFamily, declaredFonts, filteredUsedFonts)) {
150
+ if (unusedFonts.find(fontInfo => fontInfo.fontFamily == fontFamily) || !testUnicodeRange(docChars, unicodeRange) || !testUsedFont(ruleData, fontFamily, declaredFonts, filteredUsedFonts)) {
148
151
  removedRules.push(cssRule);
149
152
  }
150
153
  }
@@ -373,45 +376,34 @@ function getDeclarationUnescapedValue(declarations, property, workStylesheet) {
373
376
  return "";
374
377
  }
375
378
 
376
- function testUnicodeRange(docContent, unicodeRange) {
379
+ function testUnicodeRange(docCharCodes, unicodeRange) {
377
380
  if (unicodeRange) {
378
381
  const unicodeRanges = unicodeRange.split(REGEXP_COMMA);
379
- let invalid;
380
382
  const result = unicodeRanges.filter(rangeValue => {
381
383
  const range = rangeValue.split(REGEXP_DASH);
382
- let regExpString;
383
384
  if (range.length == 2) {
384
385
  range[0] = transformRange(range[0]);
385
- regExpString = "[" + range[0] + "-" + transformRange("U+" + range[1]) + "]";
386
- }
387
- if (range.length == 1) {
386
+ range[1] = transformRange(range[1]);
387
+ } else if (range.length == 1) {
388
388
  if (range[0].includes("?")) {
389
- const firstRange = transformRange(range[0]);
389
+ const firstRange = range[0];
390
390
  const secondRange = firstRange;
391
- regExpString = "[" + firstRange.replace(REGEXP_QUESTION_MARK, "0") + "-" + secondRange.replace(REGEXP_QUESTION_MARK, "F") + "]";
391
+ range[0] = transformRange(firstRange.replace(REGEXP_QUESTION_MARK, "0"));
392
+ range[1] = transformRange(secondRange.replace(REGEXP_QUESTION_MARK, "F"));
392
393
  } else if (range[0]) {
393
- regExpString = "[" + transformRange(range[0]) + "]";
394
+ range[0] = transformRange(range[0]);
394
395
  }
395
396
  }
396
- if (regExpString) {
397
- try {
398
- return (new RegExp(regExpString, "u")).test(docContent);
399
- } catch (error) {
400
- invalid = true;
401
- return false;
402
- }
397
+ if (!range[0] || docCharCodes.find(charCode => charCode >= range[0] && charCode <= range[1])) {
398
+ return true;
403
399
  }
404
- return true;
405
400
  });
406
- return !invalid && (!unicodeRanges.length || result.length);
401
+ return (!unicodeRanges.length || result.length);
407
402
  }
408
403
  return true;
409
404
  }
410
405
 
411
406
  function transformRange(range) {
412
407
  range = range.replace(REGEXP_STARTS_U_PLUS, "");
413
- while (range.length < 6) {
414
- range = "0" + range;
415
- }
416
- return "\\u{" + range + "}";
408
+ return parseInt(range, 16);
417
409
  }
@@ -110,11 +110,8 @@ function getMatchedElementsRules(doc, cssRules, stylesheets, mediaInfo, sheetInd
110
110
  log(" -- STARTED getMatchedElementsRules", " index =", sheetIndex, "rules.length =", cssRules.length);
111
111
  }
112
112
  cssRules.forEach(ruleData => {
113
- if (ruleData.type == "Atrule" && ruleData.name == "import") {
114
- const stylesheetEntry = Array.from(stylesheets.entries()).find(([key]) => key.urlNode == ruleData.prelude.children.head.data);
115
- const stylesheetInfo = stylesheetEntry[1];
116
- ruleData.importedChildren = stylesheetInfo.stylesheet.children;
117
- getMatchedElementsRules(doc, ruleData.importedChildren, stylesheets, mediaInfo, sheetIndex, styles, matchedElementsCache, workStylesheet, indexes);
113
+ if (ruleData.type == "Atrule" && ruleData.name == "import" && ruleData.prelude && ruleData.prelude.children && ruleData.prelude.children.head.data.importedChildren) {
114
+ getMatchedElementsRules(doc, ruleData.prelude.children.head.data.importedChildren, stylesheets, mediaInfo, sheetIndex, styles, matchedElementsCache, workStylesheet, indexes);
118
115
  } else if (ruleData.block && ruleData.block.children && ruleData.prelude && ruleData.prelude.children) {
119
116
  if (ruleData.type == "Atrule" && ruleData.name == "media") {
120
117
  const mediaText = cssTree.generate(ruleData.prelude);
@@ -71,10 +71,8 @@ function processRules(cssRules, sheetIndex, mediaInfo, indexes = { mediaRuleInde
71
71
  const removedCssRules = [];
72
72
  for (let cssRule = cssRules.head; cssRule; cssRule = cssRule.next) {
73
73
  const ruleData = cssRule.data;
74
- if (ruleData.type == "Atrule" && ruleData.name == "import") {
75
- if (ruleData.importedChildren) {
76
- processRules(ruleData.importedChildren, sheetIndex, mediaInfo, indexes);
77
- }
74
+ if (ruleData.type == "Atrule" && ruleData.name == "import" && ruleData.prelude && ruleData.prelude.children && ruleData.prelude.children.head.data.importedChildren) {
75
+ processRules(ruleData.prelude.children.head.data.importedChildren, sheetIndex, mediaInfo, indexes);
78
76
  } else if (ruleData.block && ruleData.block.children && ruleData.prelude && ruleData.prelude.children) {
79
77
  if (ruleData.type == "Atrule" && ruleData.name == "media") {
80
78
  const mediaText = cssTree.generate(ruleData.prelude);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "single-file-core",
3
- "version": "1.3.8",
3
+ "version": "1.3.9",
4
4
  "description": "SingleFile Core",
5
5
  "author": "Gildas Lormeau",
6
6
  "license": "AGPL-3.0-or-later",