single-file-core 1.3.7 → 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.
|
@@ -100,19 +100,23 @@ function getProcessorHelperClass(utilInstance) {
|
|
|
100
100
|
} else {
|
|
101
101
|
key.urlNode.value = name;
|
|
102
102
|
}
|
|
103
|
-
resources.stylesheets.set(resources.stylesheets.size, { name,
|
|
103
|
+
resources.stylesheets.set(resources.stylesheets.size, { name, stylesheet: stylesheetInfo.stylesheet });
|
|
104
104
|
} else {
|
|
105
105
|
if (key.element.tagName.toUpperCase() == "LINK") {
|
|
106
106
|
const linkElement = key.element;
|
|
107
107
|
const name = "stylesheet_" + resources.stylesheets.size + ".css";
|
|
108
108
|
linkElement.setAttribute("href", name);
|
|
109
|
-
resources.stylesheets.set(resources.stylesheets.size, { name,
|
|
109
|
+
resources.stylesheets.set(resources.stylesheets.size, { name, stylesheet: stylesheetInfo.stylesheet });
|
|
110
110
|
} else {
|
|
111
111
|
const styleElement = key.element;
|
|
112
112
|
styleElement.textContent = this.generateStylesheetContent(stylesheetInfo.stylesheet, options);
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
|
+
for (const [, stylesheetResource] of resources.stylesheets) {
|
|
117
|
+
stylesheetResource.content = this.generateStylesheetContent(stylesheetResource.stylesheet, options);
|
|
118
|
+
stylesheetResource.stylesheet = null;
|
|
119
|
+
}
|
|
116
120
|
}
|
|
117
121
|
|
|
118
122
|
async resolveImportURLs(stylesheetInfo, baseURI, options, workStylesheet, resources, stylesheets) {
|
|
@@ -138,10 +142,13 @@ function getProcessorHelperClass(utilInstance) {
|
|
|
138
142
|
mediaText = cssTree.generate(mediaQueryListNode);
|
|
139
143
|
}
|
|
140
144
|
const existingStylesheet = Array.from(stylesheets).find(([, stylesheetInfo]) => stylesheetInfo.resourceURL == resourceURL);
|
|
145
|
+
let stylesheet;
|
|
141
146
|
if (existingStylesheet) {
|
|
147
|
+
stylesheet = existingStylesheet[1].stylesheet;
|
|
142
148
|
stylesheets.set({ urlNode }, {
|
|
143
149
|
url: resourceURL,
|
|
144
|
-
stylesheet
|
|
150
|
+
stylesheet,
|
|
151
|
+
scoped
|
|
145
152
|
});
|
|
146
153
|
} else {
|
|
147
154
|
const stylesheetInfo = {
|
|
@@ -152,9 +159,11 @@ function getProcessorHelperClass(utilInstance) {
|
|
|
152
159
|
stylesheetInfo.url = resourceURL = content.resourceURL;
|
|
153
160
|
content.data = getUpdatedResourceContent(resourceURL, options) || content.data;
|
|
154
161
|
stylesheetInfo.stylesheet = cssTree.parse(content.data, { context: "stylesheet", parseCustomProperty: true });
|
|
162
|
+
stylesheet = stylesheetInfo.stylesheet;
|
|
155
163
|
await this.resolveImportURLs(stylesheetInfo, resourceURL, options, workStylesheet, resources, stylesheets);
|
|
156
164
|
stylesheets.set({ urlNode }, stylesheetInfo);
|
|
157
165
|
}
|
|
166
|
+
urlNode.importedChildren = stylesheet.children;
|
|
158
167
|
}
|
|
159
168
|
}
|
|
160
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,
|
|
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,
|
|
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" &&
|
|
142
|
-
filterUnusedFonts(ruleData.
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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 =
|
|
389
|
+
const firstRange = range[0];
|
|
390
390
|
const secondRange = firstRange;
|
|
391
|
-
|
|
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
|
-
|
|
394
|
+
range[0] = transformRange(range[0]);
|
|
394
395
|
}
|
|
395
396
|
}
|
|
396
|
-
if (
|
|
397
|
-
|
|
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
|
|
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
|
-
|
|
414
|
-
range = "0" + range;
|
|
415
|
-
}
|
|
416
|
-
return "\\u{" + range + "}";
|
|
408
|
+
return parseInt(range, 16);
|
|
417
409
|
}
|
|
@@ -40,16 +40,16 @@ class MatchedRules {
|
|
|
40
40
|
doc.body.appendChild(workStyleSheet);
|
|
41
41
|
const workStyleElement = doc.createElement("span");
|
|
42
42
|
doc.body.appendChild(workStyleElement);
|
|
43
|
-
stylesheets.forEach(stylesheetInfo => {
|
|
44
|
-
if (!stylesheetInfo.scoped) {
|
|
43
|
+
stylesheets.forEach((stylesheetInfo, key) => {
|
|
44
|
+
if (!stylesheetInfo.scoped && !key.urlNode) {
|
|
45
45
|
const cssRules = stylesheetInfo.stylesheet.children;
|
|
46
46
|
if (cssRules) {
|
|
47
47
|
if (stylesheetInfo.mediaText && stylesheetInfo.mediaText != MEDIA_ALL) {
|
|
48
48
|
const mediaInfo = createMediaInfo(stylesheetInfo.mediaText);
|
|
49
49
|
this.mediaAllInfo.medias.set("style-" + sheetIndex + "-" + stylesheetInfo.mediaText, mediaInfo);
|
|
50
|
-
getMatchedElementsRules(doc, cssRules, mediaInfo, sheetIndex, styles, matchedElementsCache, workStyleSheet);
|
|
50
|
+
getMatchedElementsRules(doc, cssRules, stylesheets, mediaInfo, sheetIndex, styles, matchedElementsCache, workStyleSheet);
|
|
51
51
|
} else {
|
|
52
|
-
getMatchedElementsRules(doc, cssRules, this.mediaAllInfo, sheetIndex, styles, matchedElementsCache, workStyleSheet);
|
|
52
|
+
getMatchedElementsRules(doc, cssRules, stylesheets, this.mediaAllInfo, sheetIndex, styles, matchedElementsCache, workStyleSheet);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
}
|
|
@@ -88,33 +88,41 @@ function getMediaAllInfo(doc, stylesheets, styles) {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
function createMediaInfo(media) {
|
|
91
|
-
const mediaInfo = {
|
|
91
|
+
const mediaInfo = {
|
|
92
|
+
media: media,
|
|
93
|
+
elements: new Map(),
|
|
94
|
+
medias: new Map(),
|
|
95
|
+
rules: new Map(),
|
|
96
|
+
pseudoRules: new Map()
|
|
97
|
+
};
|
|
92
98
|
if (media == MEDIA_ALL) {
|
|
93
99
|
mediaInfo.matchedStyles = new Map();
|
|
94
100
|
}
|
|
95
101
|
return mediaInfo;
|
|
96
102
|
}
|
|
97
103
|
|
|
98
|
-
function getMatchedElementsRules(doc, cssRules, mediaInfo, sheetIndex, styles, matchedElementsCache, workStylesheet
|
|
99
|
-
|
|
100
|
-
|
|
104
|
+
function getMatchedElementsRules(doc, cssRules, stylesheets, mediaInfo, sheetIndex, styles, matchedElementsCache, workStylesheet, indexes = {
|
|
105
|
+
mediaIndex: 0, ruleIndex: 0
|
|
106
|
+
}) {
|
|
101
107
|
let startTime;
|
|
102
108
|
if (DEBUG && cssRules.length > 1) {
|
|
103
109
|
startTime = Date.now();
|
|
104
110
|
log(" -- STARTED getMatchedElementsRules", " index =", sheetIndex, "rules.length =", cssRules.length);
|
|
105
111
|
}
|
|
106
112
|
cssRules.forEach(ruleData => {
|
|
107
|
-
if (ruleData.
|
|
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);
|
|
115
|
+
} else if (ruleData.block && ruleData.block.children && ruleData.prelude && ruleData.prelude.children) {
|
|
108
116
|
if (ruleData.type == "Atrule" && ruleData.name == "media") {
|
|
109
117
|
const mediaText = cssTree.generate(ruleData.prelude);
|
|
110
118
|
const ruleMediaInfo = createMediaInfo(mediaText);
|
|
111
|
-
mediaInfo.medias.set("rule-" + sheetIndex + "-" + mediaIndex + "-" + mediaText, ruleMediaInfo);
|
|
112
|
-
|
|
113
|
-
|
|
119
|
+
mediaInfo.medias.set("rule-" + sheetIndex + "-" + indexes.mediaIndex + "-" + mediaText, ruleMediaInfo);
|
|
120
|
+
getMatchedElementsRules(doc, ruleData.block.children, stylesheets, ruleMediaInfo, sheetIndex, styles, matchedElementsCache, workStylesheet);
|
|
121
|
+
indexes.mediaIndex++;
|
|
114
122
|
} else if (ruleData.type == "Rule") {
|
|
115
123
|
const selectors = ruleData.prelude.children.toArray();
|
|
116
124
|
const selectorsText = ruleData.prelude.children.toArray().map(selector => cssTree.generate(selector));
|
|
117
|
-
const ruleInfo = { ruleData, mediaInfo, ruleIndex, sheetIndex, matchedSelectors: new Set(), declarations: new Set(), selectors, selectorsText };
|
|
125
|
+
const ruleInfo = { ruleData, mediaInfo, ruleIndex: indexes.ruleIndex, sheetIndex, matchedSelectors: new Set(), declarations: new Set(), selectors, selectorsText };
|
|
118
126
|
if (!invalidSelector(selectorsText.join(","), workStylesheet) || selectorsText.find(selectorText => selectorText.includes("|"))) {
|
|
119
127
|
for (let selector = ruleData.prelude.children.head, selectorIndex = 0; selector; selector = selector.next, selectorIndex++) {
|
|
120
128
|
const selectorText = selectorsText[selectorIndex];
|
|
@@ -122,7 +130,7 @@ function getMatchedElementsRules(doc, cssRules, mediaInfo, sheetIndex, styles, m
|
|
|
122
130
|
getMatchedElementsSelector(doc, selectorInfo, styles, matchedElementsCache);
|
|
123
131
|
}
|
|
124
132
|
}
|
|
125
|
-
ruleIndex++;
|
|
133
|
+
indexes.ruleIndex++;
|
|
126
134
|
}
|
|
127
135
|
}
|
|
128
136
|
});
|
|
@@ -178,7 +186,7 @@ function getFilteredSelector(selector, selectorText) {
|
|
|
178
186
|
let namespaceFound;
|
|
179
187
|
selector = { data: cssTree.parse(cssTree.generate(selector.data), { context: "selector" }) };
|
|
180
188
|
filterNamespace(selector);
|
|
181
|
-
if (namespaceFound)
|
|
189
|
+
if (namespaceFound) {
|
|
182
190
|
selectorText = cssTree.generate(selector.data).trim();
|
|
183
191
|
}
|
|
184
192
|
filterPseudoClasses(selector);
|
|
@@ -32,8 +32,8 @@ export {
|
|
|
32
32
|
function process(stylesheets, styles, mediaAllInfo) {
|
|
33
33
|
const stats = { processed: 0, discarded: 0 };
|
|
34
34
|
let sheetIndex = 0;
|
|
35
|
-
stylesheets.forEach(stylesheetInfo => {
|
|
36
|
-
if (!stylesheetInfo.scoped) {
|
|
35
|
+
stylesheets.forEach((stylesheetInfo, key) => {
|
|
36
|
+
if (!stylesheetInfo.scoped && !key.urlNode) {
|
|
37
37
|
const cssRules = stylesheetInfo.stylesheet.children;
|
|
38
38
|
if (cssRules) {
|
|
39
39
|
stats.processed += cssRules.size;
|
|
@@ -62,8 +62,8 @@ function process(stylesheets, styles, mediaAllInfo) {
|
|
|
62
62
|
return stats;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
function processRules(cssRules, sheetIndex, mediaInfo) {
|
|
66
|
-
let
|
|
65
|
+
function processRules(cssRules, sheetIndex, mediaInfo, indexes = { mediaRuleIndex: 0 }) {
|
|
66
|
+
let startTime;
|
|
67
67
|
if (DEBUG && cssRules.size > 1) {
|
|
68
68
|
startTime = Date.now();
|
|
69
69
|
log(" -- STARTED processRules", "rules.length =", cssRules.size);
|
|
@@ -71,14 +71,13 @@ function processRules(cssRules, sheetIndex, mediaInfo) {
|
|
|
71
71
|
const removedCssRules = [];
|
|
72
72
|
for (let cssRule = cssRules.head; cssRule; cssRule = cssRule.next) {
|
|
73
73
|
const ruleData = cssRule.data;
|
|
74
|
-
if (ruleData.
|
|
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);
|
|
76
|
+
} else if (ruleData.block && ruleData.block.children && ruleData.prelude && ruleData.prelude.children) {
|
|
75
77
|
if (ruleData.type == "Atrule" && ruleData.name == "media") {
|
|
76
78
|
const mediaText = cssTree.generate(ruleData.prelude);
|
|
77
|
-
processRules(ruleData.block.children, sheetIndex, mediaInfo.medias.get("rule-" + sheetIndex + "-" + mediaRuleIndex + "-" + mediaText));
|
|
78
|
-
|
|
79
|
-
removedCssRules.push(cssRule);
|
|
80
|
-
}
|
|
81
|
-
mediaRuleIndex++;
|
|
79
|
+
processRules(ruleData.block.children, sheetIndex, mediaInfo.medias.get("rule-" + sheetIndex + "-" + indexes.mediaRuleIndex + "-" + mediaText));
|
|
80
|
+
indexes.mediaRuleIndex++;
|
|
82
81
|
} else if (ruleData.type == "Rule") {
|
|
83
82
|
const ruleInfo = mediaInfo.rules.get(ruleData);
|
|
84
83
|
const pseudoSelectors = mediaInfo.pseudoRules.get(ruleData);
|