format: prettify entire project

This commit is contained in:
Rim
2025-04-02 06:50:39 -04:00
parent 86f0782a98
commit 7ccc0be712
1711 changed files with 755867 additions and 235931 deletions

View File

@ -3,32 +3,32 @@
const cssTree = require('css-tree');
class Index {
constructor() {
this.map = new Map();
}
resolve(str) {
let index = this.map.get(str);
constructor() {
this.map = new Map();
}
resolve(str) {
let index = this.map.get(str);
if (index === undefined) {
index = this.map.size + 1;
this.map.set(str, index);
}
return index;
if (index === undefined) {
index = this.map.size + 1;
this.map.set(str, index);
}
return index;
}
}
function createDeclarationIndexer() {
const ids = new Index();
const ids = new Index();
return function markDeclaration(node) {
const id = cssTree.generate(node);
return function markDeclaration(node) {
const id = cssTree.generate(node);
node.id = ids.resolve(id);
node.length = id.length;
node.fingerprint = null;
node.id = ids.resolve(id);
node.length = id.length;
node.fingerprint = null;
return node;
};
return node;
};
}
module.exports = createDeclarationIndexer;

View File

@ -5,41 +5,41 @@ const createDeclarationIndexer = require('./createDeclarationIndexer.cjs');
const processSelector = require('./processSelector.cjs');
function prepare(ast, options) {
const markDeclaration = createDeclarationIndexer();
const markDeclaration = createDeclarationIndexer();
cssTree.walk(ast, {
visit: 'Rule',
enter(node) {
node.block.children.forEach(markDeclaration);
processSelector(node, options.usage);
}
});
cssTree.walk(ast, {
visit: 'Rule',
enter(node) {
node.block.children.forEach(markDeclaration);
processSelector(node, options.usage);
},
});
cssTree.walk(ast, {
visit: 'Atrule',
enter(node) {
if (node.prelude) {
node.prelude.id = null; // pre-init property to avoid multiple hidden class for generate
node.prelude.id = cssTree.generate(node.prelude);
}
cssTree.walk(ast, {
visit: 'Atrule',
enter(node) {
if (node.prelude) {
node.prelude.id = null; // pre-init property to avoid multiple hidden class for generate
node.prelude.id = cssTree.generate(node.prelude);
}
// compare keyframe selectors by its values
// NOTE: still no clarification about problems with keyframes selector grouping (issue #197)
if (cssTree.keyword(node.name).basename === 'keyframes') {
node.block.avoidRulesMerge = true; /* probably we don't need to prevent those merges for @keyframes
// compare keyframe selectors by its values
// NOTE: still no clarification about problems with keyframes selector grouping (issue #197)
if (cssTree.keyword(node.name).basename === 'keyframes') {
node.block.avoidRulesMerge = true; /* probably we don't need to prevent those merges for @keyframes
TODO: need to be checked */
node.block.children.forEach(function(rule) {
rule.prelude.children.forEach(function(simpleselector) {
simpleselector.compareMarker = simpleselector.id;
});
});
}
}
});
node.block.children.forEach(function (rule) {
rule.prelude.children.forEach(function (simpleselector) {
simpleselector.compareMarker = simpleselector.id;
});
});
}
},
});
return {
declaration: markDeclaration
};
return {
declaration: markDeclaration,
};
}
module.exports = prepare;

View File

@ -4,98 +4,100 @@ const cssTree = require('css-tree');
const specificity = require('./specificity.cjs');
const nonFreezePseudoElements = new Set([
'first-letter',
'first-line',
'after',
'before'
'first-letter',
'first-line',
'after',
'before',
]);
const nonFreezePseudoClasses = new Set([
'link',
'visited',
'hover',
'active',
'first-letter',
'first-line',
'after',
'before'
'link',
'visited',
'hover',
'active',
'first-letter',
'first-line',
'after',
'before',
]);
function processSelector(node, usageData) {
const pseudos = new Set();
const pseudos = new Set();
node.prelude.children.forEach(function(simpleSelector) {
let tagName = '*';
let scope = 0;
node.prelude.children.forEach(function (simpleSelector) {
let tagName = '*';
let scope = 0;
simpleSelector.children.forEach(function(node) {
switch (node.type) {
case 'ClassSelector':
if (usageData && usageData.scopes) {
const classScope = usageData.scopes[node.name] || 0;
simpleSelector.children.forEach(function (node) {
switch (node.type) {
case 'ClassSelector':
if (usageData && usageData.scopes) {
const classScope = usageData.scopes[node.name] || 0;
if (scope !== 0 && classScope !== scope) {
throw new Error('Selector can\'t has classes from different scopes: ' + cssTree.generate(simpleSelector));
}
scope = classScope;
}
break;
case 'PseudoClassSelector': {
const name = node.name.toLowerCase();
if (!nonFreezePseudoClasses.has(name)) {
pseudos.add(`:${name}`);
}
break;
}
case 'PseudoElementSelector': {
const name = node.name.toLowerCase();
if (!nonFreezePseudoElements.has(name)) {
pseudos.add(`::${name}`);
}
break;
}
case 'TypeSelector':
tagName = node.name.toLowerCase();
break;
case 'AttributeSelector':
if (node.flags) {
pseudos.add(`[${node.flags.toLowerCase()}]`);
}
break;
case 'Combinator':
tagName = '*';
break;
if (scope !== 0 && classScope !== scope) {
throw new Error(
"Selector can't has classes from different scopes: " +
cssTree.generate(simpleSelector)
);
}
});
simpleSelector.compareMarker = specificity(simpleSelector).toString();
simpleSelector.id = null; // pre-init property to avoid multiple hidden class
simpleSelector.id = cssTree.generate(simpleSelector);
scope = classScope;
}
if (scope) {
simpleSelector.compareMarker += ':' + scope;
break;
case 'PseudoClassSelector': {
const name = node.name.toLowerCase();
if (!nonFreezePseudoClasses.has(name)) {
pseudos.add(`:${name}`);
}
break;
}
if (tagName !== '*') {
simpleSelector.compareMarker += ',' + tagName;
case 'PseudoElementSelector': {
const name = node.name.toLowerCase();
if (!nonFreezePseudoElements.has(name)) {
pseudos.add(`::${name}`);
}
break;
}
case 'TypeSelector':
tagName = node.name.toLowerCase();
break;
case 'AttributeSelector':
if (node.flags) {
pseudos.add(`[${node.flags.toLowerCase()}]`);
}
break;
case 'Combinator':
tagName = '*';
break;
}
});
// add property to all rule nodes to avoid multiple hidden class
node.pseudoSignature = pseudos.size > 0
? [...pseudos].sort().join(',')
: false;
simpleSelector.compareMarker = specificity(simpleSelector).toString();
simpleSelector.id = null; // pre-init property to avoid multiple hidden class
simpleSelector.id = cssTree.generate(simpleSelector);
if (scope) {
simpleSelector.compareMarker += ':' + scope;
}
if (tagName !== '*') {
simpleSelector.compareMarker += ',' + tagName;
}
});
// add property to all rule nodes to avoid multiple hidden class
node.pseudoSignature =
pseudos.size > 0 ? [...pseudos].sort().join(',') : false;
}
module.exports = processSelector;

View File

@ -3,131 +3,131 @@
const cssTree = require('css-tree');
function ensureSelectorList(node) {
if (node.type === 'Raw') {
return cssTree.parse(node.value, { context: 'selectorList' });
}
if (node.type === 'Raw') {
return cssTree.parse(node.value, { context: 'selectorList' });
}
return node;
return node;
}
function maxSpecificity(a, b) {
for (let i = 0; i < 3; i++) {
if (a[i] !== b[i]) {
return a[i] > b[i] ? a : b;
}
for (let i = 0; i < 3; i++) {
if (a[i] !== b[i]) {
return a[i] > b[i] ? a : b;
}
}
return a;
return a;
}
function maxSelectorListSpecificity(selectorList) {
return ensureSelectorList(selectorList).children.reduce(
(result, node) => maxSpecificity(specificity(node), result),
[0, 0, 0]
);
return ensureSelectorList(selectorList).children.reduce(
(result, node) => maxSpecificity(specificity(node), result),
[0, 0, 0]
);
}
// §16. Calculating a selectors specificity
// https://www.w3.org/TR/selectors-4/#specificity-rules
function specificity(simpleSelector) {
let A = 0;
let B = 0;
let C = 0;
let A = 0;
let B = 0;
let C = 0;
// A selectors specificity is calculated for a given element as follows:
simpleSelector.children.forEach((node) => {
switch (node.type) {
// count the number of ID selectors in the selector (= A)
case 'IdSelector':
A++;
break;
// A selectors specificity is calculated for a given element as follows:
simpleSelector.children.forEach((node) => {
switch (node.type) {
// count the number of ID selectors in the selector (= A)
case 'IdSelector':
A++;
break;
// count the number of class selectors, attributes selectors, ...
case 'ClassSelector':
case 'AttributeSelector':
B++;
break;
// count the number of class selectors, attributes selectors, ...
case 'ClassSelector':
case 'AttributeSelector':
B++;
break;
// ... and pseudo-classes in the selector (= B)
case 'PseudoClassSelector':
switch (node.name.toLowerCase()) {
// The specificity of an :is(), :not(), or :has() pseudo-class is replaced
// by the specificity of the most specific complex selector in its selector list argument.
case 'not':
case 'has':
case 'is':
// :matches() is used before it was renamed to :is()
// https://github.com/w3c/csswg-drafts/issues/3258
case 'matches':
// Older browsers support :is() functionality as prefixed pseudo-class :any()
// https://developer.mozilla.org/en-US/docs/Web/CSS/:is
case '-webkit-any':
case '-moz-any': {
const [a, b, c] = maxSelectorListSpecificity(node.children.first);
// ... and pseudo-classes in the selector (= B)
case 'PseudoClassSelector':
switch (node.name.toLowerCase()) {
// The specificity of an :is(), :not(), or :has() pseudo-class is replaced
// by the specificity of the most specific complex selector in its selector list argument.
case 'not':
case 'has':
case 'is':
// :matches() is used before it was renamed to :is()
// https://github.com/w3c/csswg-drafts/issues/3258
case 'matches':
// Older browsers support :is() functionality as prefixed pseudo-class :any()
// https://developer.mozilla.org/en-US/docs/Web/CSS/:is
case '-webkit-any':
case '-moz-any': {
const [a, b, c] = maxSelectorListSpecificity(node.children.first);
A += a;
B += b;
C += c;
A += a;
B += b;
C += c;
break;
}
break;
}
// Analogously, the specificity of an :nth-child() or :nth-last-child() selector
// is the specificity of the pseudo class itself (counting as one pseudo-class selector)
// plus the specificity of the most specific complex selector in its selector list argument (if any).
case 'nth-child':
case 'nth-last-child': {
const arg = node.children.first;
// Analogously, the specificity of an :nth-child() or :nth-last-child() selector
// is the specificity of the pseudo class itself (counting as one pseudo-class selector)
// plus the specificity of the most specific complex selector in its selector list argument (if any).
case 'nth-child':
case 'nth-last-child': {
const arg = node.children.first;
if (arg.type === 'Nth' && arg.selector) {
const [a, b, c] = maxSelectorListSpecificity(arg.selector);
if (arg.type === 'Nth' && arg.selector) {
const [a, b, c] = maxSelectorListSpecificity(arg.selector);
A += a;
B += b + 1;
C += c;
} else {
B++;
}
A += a;
B += b + 1;
C += c;
} else {
B++;
}
break;
}
break;
}
// The specificity of a :where() pseudo-class is replaced by zero.
case 'where':
break;
// The specificity of a :where() pseudo-class is replaced by zero.
case 'where':
break;
// The four Level 2 pseudo-elements (::before, ::after, ::first-line, and ::first-letter) may,
// for legacy reasons, be represented using the <pseudo-class-selector> grammar,
// with only a single ":" character at their start.
// https://www.w3.org/TR/selectors-4/#single-colon-pseudos
case 'before':
case 'after':
case 'first-line':
case 'first-letter':
C++;
break;
// The four Level 2 pseudo-elements (::before, ::after, ::first-line, and ::first-letter) may,
// for legacy reasons, be represented using the <pseudo-class-selector> grammar,
// with only a single ":" character at their start.
// https://www.w3.org/TR/selectors-4/#single-colon-pseudos
case 'before':
case 'after':
case 'first-line':
case 'first-letter':
C++;
break;
default:
B++;
}
break;
// count the number of type selectors ...
case 'TypeSelector':
// ignore the universal selector
if (!node.name.endsWith('*')) {
C++;
}
break;
// ... and pseudo-elements in the selector (= C)
case 'PseudoElementSelector':
C++;
break;
default:
B++;
}
});
break;
return [A, B, C];
// count the number of type selectors ...
case 'TypeSelector':
// ignore the universal selector
if (!node.name.endsWith('*')) {
C++;
}
break;
// ... and pseudo-elements in the selector (= C)
case 'PseudoElementSelector':
C++;
break;
}
});
return [A, B, C];
}
module.exports = specificity;