Fix async lifecycle ordering, add _spa_init boot phase, update to jqhtml _load_only/_load_render_only flags
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
8
node_modules/postcss-merge-rules/package.json
generated
vendored
8
node_modules/postcss-merge-rules/package.json
generated
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "postcss-merge-rules",
|
||||
"version": "7.0.7",
|
||||
"version": "7.0.8",
|
||||
"description": "Merge CSS rules with PostCSS.",
|
||||
"types": "types/index.d.ts",
|
||||
"main": "src/index.js",
|
||||
@@ -24,9 +24,9 @@
|
||||
},
|
||||
"repository": "cssnano/cssnano",
|
||||
"dependencies": {
|
||||
"browserslist": "^4.27.0",
|
||||
"browserslist": "^4.28.1",
|
||||
"caniuse-api": "^3.0.0",
|
||||
"postcss-selector-parser": "^7.1.0",
|
||||
"postcss-selector-parser": "^7.1.1",
|
||||
"cssnano-utils": "^5.0.1"
|
||||
},
|
||||
"bugs": {
|
||||
@@ -39,7 +39,7 @@
|
||||
"@types/caniuse-api": "^3.0.6",
|
||||
"postcss": "^8.5.6",
|
||||
"postcss-simple-vars": "^7.0.1",
|
||||
"postcss-discard-comments": "^7.0.5"
|
||||
"postcss-discard-comments": "^7.0.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"postcss": "^8.4.32"
|
||||
|
||||
305
node_modules/postcss-merge-rules/src/index.js
generated
vendored
305
node_modules/postcss-merge-rules/src/index.js
generated
vendored
@@ -54,20 +54,51 @@ function sameDeclarationsAndOrder(a, b) {
|
||||
return a.every((d, index) => declarationIsEqual(d, b[index]));
|
||||
}
|
||||
|
||||
/**
|
||||
* RuleMeta stores metadata about a `Rule` during the merging process.
|
||||
* It tracks selectors and declarations without re-parsing the AST many times.
|
||||
*
|
||||
* @typedef {Object} RuleMeta
|
||||
* @property {string[]} selectors - Array of selector strings for the rule
|
||||
* @property {import('postcss').Declaration[]} declarations - Array of declaration nodes for the rule
|
||||
* @property {boolean} dirty - Whether the selectors have been modified and need flushing
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {import('postcss').Rule} ruleA
|
||||
* @param {import('postcss').Rule} ruleB
|
||||
* @param {string[]=} browsers
|
||||
* @param {Map<string, boolean>=} compatibilityCache
|
||||
* @param {string[]} browsers
|
||||
* @param {Map<string, boolean>} compatibilityCache
|
||||
* @param {WeakSet<import('postcss').Rule>} ruleCache
|
||||
* @param {WeakMap<import('postcss').Rule, RuleMeta>} ruleMeta
|
||||
* @return {boolean}
|
||||
*/
|
||||
function canMerge(ruleA, ruleB, browsers, compatibilityCache) {
|
||||
const a = ruleA.selectors;
|
||||
const b = ruleB.selectors;
|
||||
function canMerge(
|
||||
ruleA,
|
||||
ruleB,
|
||||
browsers,
|
||||
compatibilityCache,
|
||||
ruleCache,
|
||||
ruleMeta
|
||||
) {
|
||||
const metaA = getMeta(ruleA, ruleMeta);
|
||||
const metaB = getMeta(ruleB, ruleMeta);
|
||||
const a = metaA.selectors;
|
||||
const b = metaB.selectors;
|
||||
|
||||
const selectors = a.concat(b);
|
||||
|
||||
if (!ensureCompatibility(selectors, browsers, compatibilityCache)) {
|
||||
if (ruleCache.has(ruleA) && ruleCache.has(ruleB)) {
|
||||
// Both already validated
|
||||
} else if (ruleCache.has(ruleA)) {
|
||||
if (!ensureCompatibility(b, browsers, compatibilityCache)) {
|
||||
return false;
|
||||
}
|
||||
} else if (ruleCache.has(ruleB)) {
|
||||
if (!ensureCompatibility(a, browsers, compatibilityCache)) {
|
||||
return false;
|
||||
}
|
||||
} else if (!ensureCompatibility(selectors, browsers, compatibilityCache)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -105,6 +136,51 @@ function isRuleOrAtRule(node) {
|
||||
function isDeclaration(node) {
|
||||
return node.type === 'decl';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves or initializes virtual metadata for a PostCSS rule.
|
||||
*
|
||||
* This metadata caches selectors and declarations to avoid expensive AST
|
||||
* re-parsing, especially for the selectors.
|
||||
*
|
||||
* @param {import('postcss').Rule} rule The PostCSS rule to get metadata for.
|
||||
* @param {WeakMap<import('postcss').Rule, RuleMeta>} [ruleMeta] The metadata cache.
|
||||
* @return {RuleMeta} The rule's virtual metadata.
|
||||
*/
|
||||
function getMeta(rule, ruleMeta) {
|
||||
if (ruleMeta && rule) {
|
||||
let meta = ruleMeta.get(rule);
|
||||
if (!meta && rule.nodes) {
|
||||
meta = {
|
||||
selectors: rule.selectors,
|
||||
declarations: rule.nodes.filter(isDeclaration),
|
||||
dirty: false,
|
||||
};
|
||||
ruleMeta.set(rule, meta);
|
||||
}
|
||||
return meta ?? { selectors: [], declarations: [], dirty: false };
|
||||
}
|
||||
return {
|
||||
selectors: rule?.selectors ?? [],
|
||||
declarations: rule?.nodes?.filter(isDeclaration) ?? [],
|
||||
dirty: false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits virtual metadata changes back to the actual PostCSS rule.
|
||||
*
|
||||
* @param {import('postcss').Rule} rule The PostCSS rule to flush.
|
||||
* @param {WeakMap<import('postcss').Rule, RuleMeta>} ruleMeta The metadata cache.
|
||||
*/
|
||||
function flush(rule, ruleMeta) {
|
||||
const meta = ruleMeta.get(rule);
|
||||
if (meta && meta.dirty) {
|
||||
rule.selector = meta.selectors.join(',');
|
||||
meta.dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('postcss').Rule} rule
|
||||
* @return {import('postcss').Declaration[]}
|
||||
@@ -113,9 +189,6 @@ function getDecls(rule) {
|
||||
return rule.nodes.filter(isDeclaration);
|
||||
}
|
||||
|
||||
/** @type {(...rules: import('postcss').Rule[]) => string} */
|
||||
const joinSelectors = (...rules) => rules.map((s) => s.selector).join();
|
||||
|
||||
/**
|
||||
* @param {...import('postcss').Rule} rules
|
||||
* @return {number}
|
||||
@@ -227,10 +300,26 @@ function mergeParents(first, second) {
|
||||
/**
|
||||
* @param {import('postcss').Rule} first
|
||||
* @param {import('postcss').Rule} second
|
||||
* @param {string[]} browsers
|
||||
* @param {Map<string, boolean>} compatibilityCache
|
||||
* @param {WeakSet<import('postcss').Rule>} ruleCache
|
||||
* @param {WeakMap<import('postcss').Rule, RuleMeta>} ruleMeta
|
||||
* @return {import('postcss').Rule} mergedRule
|
||||
*/
|
||||
function partialMerge(first, second) {
|
||||
let intersection = intersect(getDecls(first), getDecls(second));
|
||||
function partialMerge(
|
||||
first,
|
||||
second,
|
||||
browsers,
|
||||
compatibilityCache,
|
||||
ruleCache,
|
||||
ruleMeta
|
||||
) {
|
||||
if (ruleMeta) {
|
||||
flush(first, ruleMeta);
|
||||
}
|
||||
const metaFirst = getMeta(first, ruleMeta);
|
||||
const metaSecond = getMeta(second, ruleMeta);
|
||||
let intersection = intersect(metaFirst.declarations, metaSecond.declarations);
|
||||
if (intersection.length === 0) {
|
||||
return second;
|
||||
}
|
||||
@@ -244,8 +333,22 @@ function partialMerge(first, second) {
|
||||
).next();
|
||||
nextRule = parentSibling && parentSibling.nodes && parentSibling.nodes[0];
|
||||
}
|
||||
if (nextRule && nextRule.type === 'rule' && canMerge(second, nextRule)) {
|
||||
let nextIntersection = intersect(getDecls(second), getDecls(nextRule));
|
||||
if (
|
||||
nextRule?.type === 'rule' &&
|
||||
canMerge(
|
||||
second,
|
||||
nextRule,
|
||||
browsers,
|
||||
compatibilityCache,
|
||||
ruleCache,
|
||||
ruleMeta
|
||||
)
|
||||
) {
|
||||
const metaNext = getMeta(nextRule, ruleMeta);
|
||||
let nextIntersection = intersect(
|
||||
metaSecond.declarations,
|
||||
metaNext.declarations
|
||||
);
|
||||
if (nextIntersection.length > intersection.length) {
|
||||
mergeParents(second, nextRule);
|
||||
first = second;
|
||||
@@ -254,7 +357,11 @@ function partialMerge(first, second) {
|
||||
}
|
||||
}
|
||||
|
||||
const firstDecls = getDecls(first);
|
||||
const metaFirstActual = getMeta(first, ruleMeta);
|
||||
const metaSecondActual = getMeta(second, ruleMeta);
|
||||
let firstDecls = [...metaFirstActual.declarations];
|
||||
let secondDecls = [...metaSecondActual.declarations];
|
||||
|
||||
// Filter out intersections with later conflicts in First
|
||||
intersection = intersection.filter((decl, intersectIndex) => {
|
||||
const indexOfDecl = indexOfDeclaration(firstDecls, decl);
|
||||
@@ -276,7 +383,6 @@ function partialMerge(first, second) {
|
||||
});
|
||||
|
||||
// Filter out intersections with previous conflicts in Second
|
||||
const secondDecls = getDecls(second);
|
||||
intersection = intersection.filter((decl) => {
|
||||
const nextConflictIndex = secondDecls.findIndex((d) =>
|
||||
isConflictingProp(d.prop, decl.prop)
|
||||
@@ -306,15 +412,18 @@ function partialMerge(first, second) {
|
||||
}
|
||||
|
||||
const receivingBlock = second.clone();
|
||||
receivingBlock.selector = joinSelectors(first, second);
|
||||
const firstSelectors = metaFirstActual.selectors;
|
||||
const secondSelectors = metaSecondActual.selectors;
|
||||
|
||||
receivingBlock.selector = [...firstSelectors, ...secondSelectors].join();
|
||||
receivingBlock.nodes = [];
|
||||
|
||||
/** @type {import('postcss').Container<import('postcss').ChildNode>} */ (
|
||||
second.parent
|
||||
).insertBefore(second, receivingBlock);
|
||||
|
||||
const firstClone = first.clone();
|
||||
const secondClone = second.clone();
|
||||
const firstClone = first.clone({ selectors: firstSelectors });
|
||||
const secondClone = second.clone({ selectors: secondSelectors });
|
||||
|
||||
/**
|
||||
* @param {function(import('postcss').Declaration):void} callback
|
||||
@@ -335,6 +444,13 @@ function partialMerge(first, second) {
|
||||
})
|
||||
);
|
||||
secondClone.walkDecls(moveDecl((decl) => decl.remove()));
|
||||
|
||||
// Ensure original rules are flushed for accurate length comparison
|
||||
if (ruleMeta) {
|
||||
flush(first, ruleMeta);
|
||||
flush(second, ruleMeta);
|
||||
}
|
||||
|
||||
const merged = ruleLength(firstClone, receivingBlock, secondClone);
|
||||
const original = ruleLength(first, second);
|
||||
if (merged < original) {
|
||||
@@ -346,8 +462,13 @@ function partialMerge(first, second) {
|
||||
}
|
||||
});
|
||||
if (!secondClone.parent) {
|
||||
ruleCache?.add(receivingBlock);
|
||||
return receivingBlock;
|
||||
}
|
||||
ruleCache?.add(receivingBlock);
|
||||
ruleCache?.add(secondClone);
|
||||
ruleMeta?.delete(first);
|
||||
ruleMeta?.delete(second);
|
||||
return secondClone;
|
||||
} else {
|
||||
receivingBlock.remove();
|
||||
@@ -358,53 +479,101 @@ function partialMerge(first, second) {
|
||||
/**
|
||||
* @param {string[]} browsers
|
||||
* @param {Map<string, boolean>} compatibilityCache
|
||||
* @return {function(import('postcss').Rule)}
|
||||
* @param {WeakSet<import('postcss').Rule>} ruleCache
|
||||
* @param {WeakMap<import('postcss').Rule, RuleMeta>} ruleMeta
|
||||
* @return {{ merger: function(import('postcss').Rule): void, clean: function(): void }}
|
||||
*/
|
||||
function selectorMerger(browsers, compatibilityCache) {
|
||||
function selectorMerger(browsers, compatibilityCache, ruleCache, ruleMeta) {
|
||||
/** @type {import('postcss').Rule | null} */
|
||||
let cache = null;
|
||||
return function (rule) {
|
||||
// Prime the cache with the first rule, or alternately ensure that it is
|
||||
// safe to merge both declarations before continuing
|
||||
if (!cache || !canMerge(rule, cache, browsers, compatibilityCache)) {
|
||||
cache = rule;
|
||||
return;
|
||||
}
|
||||
// Ensure that we don't deduplicate the same rule; this is sometimes
|
||||
// caused by a partial merge
|
||||
if (cache === rule) {
|
||||
cache = rule;
|
||||
return;
|
||||
}
|
||||
|
||||
// Parents merge: check if the rules have same parents, but not same parent nodes
|
||||
mergeParents(cache, rule);
|
||||
|
||||
// Merge when declarations are exactly equal
|
||||
// e.g. h1 { color: red } h2 { color: red }
|
||||
if (sameDeclarationsAndOrder(getDecls(rule), getDecls(cache))) {
|
||||
rule.selector = joinSelectors(cache, rule);
|
||||
cache.remove();
|
||||
cache = rule;
|
||||
return;
|
||||
}
|
||||
// Merge when both selectors are exactly equal
|
||||
// e.g. a { color: blue } a { font-weight: bold }
|
||||
if (cache.selector === rule.selector) {
|
||||
const cached = getDecls(cache);
|
||||
rule.walk((node) => {
|
||||
if (node.type === 'decl' && indexOfDeclaration(cached, node) !== -1) {
|
||||
node.remove();
|
||||
return;
|
||||
return {
|
||||
merger(rule) {
|
||||
// Prime the cache with the first rule, or alternately ensure that it is
|
||||
// safe to merge both declarations before continuing
|
||||
if (
|
||||
!cache ||
|
||||
!canMerge(
|
||||
rule,
|
||||
cache,
|
||||
browsers,
|
||||
compatibilityCache,
|
||||
ruleCache,
|
||||
ruleMeta
|
||||
)
|
||||
) {
|
||||
if (cache) {
|
||||
flush(cache, ruleMeta);
|
||||
}
|
||||
/** @type {import('postcss').Rule} */ (cache).append(node);
|
||||
});
|
||||
rule.remove();
|
||||
return;
|
||||
}
|
||||
// Partial merge: check if the rule contains a subset of the last; if
|
||||
// so create a joined selector with the subset, if smaller.
|
||||
cache = partialMerge(cache, rule);
|
||||
cache = rule;
|
||||
return;
|
||||
}
|
||||
// Ensure that we don't deduplicate the same rule; this is sometimes
|
||||
// caused by a partial merge
|
||||
if (cache === rule) {
|
||||
cache = rule;
|
||||
return;
|
||||
}
|
||||
|
||||
// Parents merge: check if the rules have same parents, but not same parent nodes
|
||||
mergeParents(cache, rule);
|
||||
|
||||
// Merge when declarations are exactly equal
|
||||
// e.g. h1 { color: red } h2 { color: red }
|
||||
if (
|
||||
sameDeclarationsAndOrder(
|
||||
getMeta(rule, ruleMeta).declarations,
|
||||
getMeta(cache, ruleMeta).declarations
|
||||
)
|
||||
) {
|
||||
const metaRule = getMeta(rule, ruleMeta);
|
||||
const metaCache = getMeta(cache, ruleMeta);
|
||||
metaRule.selectors = [...metaCache.selectors, ...metaRule.selectors];
|
||||
metaRule.dirty = true;
|
||||
cache.remove();
|
||||
ruleMeta?.delete(cache);
|
||||
cache = rule;
|
||||
ruleCache?.add(rule);
|
||||
return;
|
||||
}
|
||||
// Merge when both selectors are exactly equal
|
||||
// e.g. a { color: blue } a { font-weight: bold }
|
||||
if (
|
||||
getMeta(cache, ruleMeta).selectors.join(',') ===
|
||||
getMeta(rule, ruleMeta).selectors.join(',')
|
||||
) {
|
||||
const cachedDecls = getMeta(cache, ruleMeta).declarations;
|
||||
rule.walk((node) => {
|
||||
if (
|
||||
node.type === 'decl' &&
|
||||
indexOfDeclaration(cachedDecls, node) !== -1
|
||||
) {
|
||||
node.remove();
|
||||
return;
|
||||
}
|
||||
/** @type {import('postcss').Rule} */ (cache).append(node);
|
||||
});
|
||||
getMeta(cache, ruleMeta).declarations = getDecls(cache);
|
||||
rule.remove();
|
||||
ruleMeta?.delete(rule);
|
||||
return;
|
||||
}
|
||||
// Partial merge: check if the rule contains a subset of the last; if
|
||||
// so create a joined selector with the subset, if smaller.
|
||||
cache = partialMerge(
|
||||
cache,
|
||||
rule,
|
||||
browsers,
|
||||
compatibilityCache,
|
||||
ruleCache,
|
||||
ruleMeta
|
||||
);
|
||||
},
|
||||
// Flushes any remaining rule in the cache to avoid memory leaks.
|
||||
clean() {
|
||||
if (cache) {
|
||||
flush(cache, ruleMeta);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -435,9 +604,21 @@ function pluginCreator(opts = {}) {
|
||||
});
|
||||
|
||||
const compatibilityCache = new Map();
|
||||
|
||||
// Use WeakSet and WeakMap to avoid memory leaks because the keys are objects.
|
||||
const ruleCache = new WeakSet();
|
||||
const ruleMeta = new WeakMap();
|
||||
|
||||
return {
|
||||
OnceExit(css) {
|
||||
css.walkRules(selectorMerger(browsers, compatibilityCache));
|
||||
const { merger, clean } = selectorMerger(
|
||||
browsers,
|
||||
compatibilityCache,
|
||||
ruleCache,
|
||||
ruleMeta
|
||||
);
|
||||
css.walkRules(merger);
|
||||
clean();
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
20
node_modules/postcss-merge-rules/types/index.d.ts
generated
vendored
20
node_modules/postcss-merge-rules/types/index.d.ts
generated
vendored
@@ -11,9 +11,27 @@ export = pluginCreator;
|
||||
*/
|
||||
declare function pluginCreator(opts?: Options): import("postcss").Plugin;
|
||||
declare namespace pluginCreator {
|
||||
export { postcss, AutoprefixerOptions, BrowserslistOptions, Options };
|
||||
export { postcss, RuleMeta, AutoprefixerOptions, BrowserslistOptions, Options };
|
||||
}
|
||||
declare var postcss: true;
|
||||
/**
|
||||
* RuleMeta stores metadata about a `Rule` during the merging process.
|
||||
* It tracks selectors and declarations without re-parsing the AST many times.
|
||||
*/
|
||||
type RuleMeta = {
|
||||
/**
|
||||
* - Array of selector strings for the rule
|
||||
*/
|
||||
selectors: string[];
|
||||
/**
|
||||
* - Array of declaration nodes for the rule
|
||||
*/
|
||||
declarations: import("postcss").Declaration[];
|
||||
/**
|
||||
* - Whether the selectors have been modified and need flushing
|
||||
*/
|
||||
dirty: boolean;
|
||||
};
|
||||
type AutoprefixerOptions = {
|
||||
overrideBrowserslist?: string | string[];
|
||||
};
|
||||
|
||||
2
node_modules/postcss-merge-rules/types/index.d.ts.map
generated
vendored
2
node_modules/postcss-merge-rules/types/index.d.ts.map
generated
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":";AA0ZA;;;;GAIG;AAEH;;;;GAIG;AACH,sCAHW,OAAO,GACN,OAAO,SAAS,EAAE,MAAM,CAyBnC;;;;;2BAjCY;IAAE,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAAE;2BAC5C,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;eACpD,mBAAmB,GAAG,mBAAmB"}
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":";AAmkBA;;;;GAIG;AAEH;;;;GAIG;AACH,sCAHW,OAAO,GACN,OAAO,SAAS,EAAE,MAAM,CAqCnC;;;;;;;;;;;;;eApjBa,MAAM,EAAE;;;;kBACR,OAAO,SAAS,EAAE,WAAW,EAAE;;;;WAC/B,OAAO;;2BAqgBR;IAAE,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAAE;2BAC5C,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;eACpD,mBAAmB,GAAG,mBAAmB"}
|
||||
Reference in New Issue
Block a user