single-file-core 1.6.7 → 1.6.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.
- package/core/index.js +8 -5
- package/core/infobar.js +8 -2
- package/modules/css-rules-minifier.js +56 -4
- package/package.json +1 -1
package/core/index.js
CHANGED
|
@@ -435,6 +435,7 @@ const SCRIPT_OPTIONS = "data-single-file-options";
|
|
|
435
435
|
const JAVASCRIPT_URI_PROTOCOL = "javascript:";
|
|
436
436
|
const DISABLED_SCRIPT_URI = "javascript:void(0)";
|
|
437
437
|
const SCRIPT_URI_ATTRIBUTE_NAMES = ["href", "src", "action", "formaction", "data"];
|
|
438
|
+
const SVG_NAMESPACE_URI = "http://www.w3.org/2000/svg";
|
|
438
439
|
const UTF8_CHARSET = "utf-8";
|
|
439
440
|
const TAINTED_CANVAS_WARNING_MESSAGE = "SingleFile: canvas elements tainted by a cross-origin resource, dropped from the page:";
|
|
440
441
|
const EMPTY_RESOURCE = "data:,";
|
|
@@ -1762,13 +1763,15 @@ function isScriptURI(value) {
|
|
|
1762
1763
|
}
|
|
1763
1764
|
|
|
1764
1765
|
function getOnEventAttributeNames(doc) {
|
|
1765
|
-
const
|
|
1766
|
+
const elements = [doc.body || doc.createElement("div"), doc.createElementNS(SVG_NAMESPACE_URI, "animate")];
|
|
1766
1767
|
const attributeNames = [];
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1768
|
+
elements.forEach(element => {
|
|
1769
|
+
for (const propertyName in element) {
|
|
1770
|
+
if (propertyName.startsWith("on")) {
|
|
1771
|
+
attributeNames.push(propertyName);
|
|
1772
|
+
}
|
|
1770
1773
|
}
|
|
1771
|
-
}
|
|
1774
|
+
});
|
|
1772
1775
|
return attributeNames;
|
|
1773
1776
|
}
|
|
1774
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
|
}
|
|
@@ -48,6 +48,7 @@ const IMPORT_NAME = "import";
|
|
|
48
48
|
const FONT_FACE_NAME = "font-face";
|
|
49
49
|
const KEYFRAMES_NAME = "keyframes";
|
|
50
50
|
const COMBINATOR_NAME = "Combinator";
|
|
51
|
+
const TYPE_SELECTOR_TYPE = "TypeSelector";
|
|
51
52
|
const STYLE_ATTRIBUTE_NAME = "style";
|
|
52
53
|
const SELECTOR_LIST_CONTEXT = "selectorList";
|
|
53
54
|
const STYLESHEET_CONTEXT = "stylesheet";
|
|
@@ -58,6 +59,10 @@ const PARSE_CSS_ERROR_MESSAGE = "Failed to parse CSS";
|
|
|
58
59
|
const QSA_ERROR_MESSAGE = "Failed to match selector";
|
|
59
60
|
const PRELUDE_SEPARATOR = ",";
|
|
60
61
|
const NESTING_SELECTOR = "&";
|
|
62
|
+
const SCOPE_PSEUDO_CLASS = ":scope";
|
|
63
|
+
const NAMESPACE_SEPARATOR = "|";
|
|
64
|
+
const SELECTOR_SUPPORTS_PREFIX = "selector(";
|
|
65
|
+
const SELECTOR_SUPPORTS_SUFFIX = ")";
|
|
61
66
|
const VENDOR_PREFIX = "-";
|
|
62
67
|
const CUSTOM_PROPERTY_PREFIX = "--";
|
|
63
68
|
const LAYER_NAME_SEPARATOR = ".";
|
|
@@ -118,6 +123,7 @@ function process(doc, stylesheets) {
|
|
|
118
123
|
layerOrder: new Map(),
|
|
119
124
|
selectorData: new Map(),
|
|
120
125
|
selectorTexts: new Map(),
|
|
126
|
+
supportedSelectors: new Map(),
|
|
121
127
|
preludeTexts: new Map(),
|
|
122
128
|
rulesCounter: 0,
|
|
123
129
|
scopeIdCounter: 0
|
|
@@ -379,6 +385,9 @@ function minifyAtRule(ruleData, cssRule, stylesheets, processingContext, removed
|
|
|
379
385
|
|
|
380
386
|
function minifyStylesheetRule(ruleData, cssRule, stylesheets, processingContext, removedRules, docContext) {
|
|
381
387
|
ruleData.order = docContext.rulesCounter++;
|
|
388
|
+
if (!isPreludeSupported(ruleData.prelude, docContext)) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
382
391
|
const removedSelectors = processSelectors(ruleData, processingContext, docContext);
|
|
383
392
|
const wasDiscarded = removeUnmatchedSelectors(ruleData, removedSelectors, removedRules, cssRule, docContext);
|
|
384
393
|
if (!wasDiscarded && hasChildNodes(ruleData.block)) {
|
|
@@ -388,7 +397,7 @@ function minifyStylesheetRule(ruleData, cssRule, stylesheets, processingContext,
|
|
|
388
397
|
|
|
389
398
|
function processSelectors(ruleData, processingContext, docContext) {
|
|
390
399
|
const removedSelectors = [];
|
|
391
|
-
const { ancestorsSelectors } = processingContext;
|
|
400
|
+
const { ancestorsSelectors, scopeStack } = processingContext;
|
|
392
401
|
for (let selector = ruleData.prelude.children.head, selectorIndex = 0; selector; selector = selector.next, selectorIndex++) {
|
|
393
402
|
const {
|
|
394
403
|
startsWithCombinator,
|
|
@@ -400,7 +409,8 @@ function processSelectors(ruleData, processingContext, docContext) {
|
|
|
400
409
|
}
|
|
401
410
|
registerSelector(selector, ruleData, processingContext, docContext);
|
|
402
411
|
if (!startsWithCombinator || !ancestorsSelectors || !ancestorsSelectors.length) {
|
|
403
|
-
const
|
|
412
|
+
const relativeToScope = startsWithCombinator && Boolean(scopeStack && scopeStack.length);
|
|
413
|
+
const matchedElements = matchElements(selector, ancestorsSelectors, scopeStack, docContext, relativeToScope);
|
|
404
414
|
if (matchedElements.length) {
|
|
405
415
|
if (!hasUnqueryableSelector) {
|
|
406
416
|
updateMatchingSelectors(matchedElements, selector, docContext);
|
|
@@ -453,6 +463,45 @@ function analyzeSelector(selector) {
|
|
|
453
463
|
return { hasUnqueryableSelector, hasNestedUnqueryablePseudoClass, startsWithCombinator };
|
|
454
464
|
}
|
|
455
465
|
|
|
466
|
+
function isPreludeSupported(prelude, docContext) {
|
|
467
|
+
if (!globalThis.CSS || !globalThis.CSS.supports) {
|
|
468
|
+
return true;
|
|
469
|
+
}
|
|
470
|
+
for (let selector = prelude.children.head; selector; selector = selector.next) {
|
|
471
|
+
if (!isSelectorSupported(selector.data, docContext)) {
|
|
472
|
+
return false;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
return true;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function isSelectorSupported(selector, docContext) {
|
|
479
|
+
const selectorNode = cssTree.clone(selector);
|
|
480
|
+
cssTree.walk(selectorNode, {
|
|
481
|
+
visit: TYPE_SELECTOR_TYPE,
|
|
482
|
+
enter(node) {
|
|
483
|
+
if (typeof node.name === "string" && node.name.includes(NAMESPACE_SEPARATOR)) {
|
|
484
|
+
node.name = node.name.substring(node.name.lastIndexOf(NAMESPACE_SEPARATOR) + 1);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
let selectorText = cssTree.generate(selectorNode);
|
|
489
|
+
const firstChild = selectorNode.children && selectorNode.children.head && selectorNode.children.head.data;
|
|
490
|
+
if (firstChild && firstChild.type === COMBINATOR_NAME) {
|
|
491
|
+
selectorText = SCOPE_PSEUDO_CLASS + selectorText;
|
|
492
|
+
}
|
|
493
|
+
if (!docContext.supportedSelectors.has(selectorText)) {
|
|
494
|
+
let supported;
|
|
495
|
+
try {
|
|
496
|
+
supported = globalThis.CSS.supports(SELECTOR_SUPPORTS_PREFIX + selectorText + SELECTOR_SUPPORTS_SUFFIX);
|
|
497
|
+
} catch {
|
|
498
|
+
supported = true;
|
|
499
|
+
}
|
|
500
|
+
docContext.supportedSelectors.set(selectorText, supported);
|
|
501
|
+
}
|
|
502
|
+
return docContext.supportedSelectors.get(selectorText);
|
|
503
|
+
}
|
|
504
|
+
|
|
456
505
|
function updateMatchingSelectors(matchedElements, selector, docContext) {
|
|
457
506
|
matchedElements.forEach(element => {
|
|
458
507
|
docContext.matchedElements.add(element);
|
|
@@ -580,8 +629,11 @@ function getConditionalStackForSelector(selector, docContext) {
|
|
|
580
629
|
return conditionalStack;
|
|
581
630
|
}
|
|
582
631
|
|
|
583
|
-
function matchElements(selector, ancestorsSelectors, scopeStack, docContext) {
|
|
584
|
-
|
|
632
|
+
function matchElements(selector, ancestorsSelectors, scopeStack, docContext, relativeToScope) {
|
|
633
|
+
let selectorText = createSelectorText(selector, ancestorsSelectors, docContext);
|
|
634
|
+
if (relativeToScope) {
|
|
635
|
+
selectorText = SCOPE_PSEUDO_CLASS + selectorText;
|
|
636
|
+
}
|
|
585
637
|
const cacheKey = createScopeCacheKey(selectorText, scopeStack);
|
|
586
638
|
const cachedNodes = docContext.matchedSelectors.get(cacheKey);
|
|
587
639
|
if (cachedNodes) {
|