Fix code quality violations and exclude Manifest from checks

Document application modes (development/debug/production)
Add global file drop handler, order column normalization, SPA hash fix
Serve CDN assets via /_vendor/ URLs instead of merging into bundles
Add production minification with license preservation
Improve JSON formatting for debugging and production optimization
Add CDN asset caching with CSS URL inlining for production builds
Add three-mode system (development, debug, production)
Update Manifest CLAUDE.md to reflect helper class architecture
Refactor Manifest.php into helper classes for better organization
Pre-manifest-refactor checkpoint: Add app_mode documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2026-01-14 10:38:22 +00:00
parent bb9046af1b
commit d523f0f600
2355 changed files with 231384 additions and 32223 deletions

73
node_modules/csso/cjs/clean/Atrule.cjs generated vendored Normal file
View File

@@ -0,0 +1,73 @@
'use strict';
const cssTree = require('css-tree');
const utils = require('./utils.cjs');
function cleanAtrule(node, item, list) {
if (node.block) {
// otherwise removed at-rule don't prevent @import for removal
if (this.stylesheet !== null) {
this.stylesheet.firstAtrulesAllowed = false;
}
if (utils.hasNoChildren(node.block)) {
list.remove(item);
return;
}
}
switch (node.name) {
case 'charset':
if (utils.hasNoChildren(node.prelude)) {
list.remove(item);
return;
}
// if there is any rule before @charset -> remove it
if (item.prev) {
list.remove(item);
return;
}
break;
case 'import':
if (this.stylesheet === null || !this.stylesheet.firstAtrulesAllowed) {
list.remove(item);
return;
}
// if there are some rules that not an @import or @charset before @import
// remove it
list.prevUntil(item.prev, function(rule) {
if (rule.type === 'Atrule') {
if (rule.name === 'import' || rule.name === 'charset') {
return;
}
}
this.root.firstAtrulesAllowed = false;
list.remove(item);
return true;
}, this);
break;
default: {
const name = cssTree.keyword(node.name).basename;
if (name === 'keyframes' ||
name === 'media' ||
name === 'supports') {
// drop at-rule with no prelude
if (utils.hasNoChildren(node.prelude) || utils.hasNoChildren(node.block)) {
list.remove(item);
}
}
}
}
}
module.exports = cleanAtrule;

7
node_modules/csso/cjs/clean/Comment.cjs generated vendored Normal file
View File

@@ -0,0 +1,7 @@
'use strict';
function cleanComment(data, item, list) {
list.remove(item);
}
module.exports = cleanComment;

18
node_modules/csso/cjs/clean/Declaration.cjs generated vendored Normal file
View File

@@ -0,0 +1,18 @@
'use strict';
const cssTree = require('css-tree');
function cleanDeclartion(node, item, list) {
if (node.value.children && node.value.children.isEmpty) {
list.remove(item);
return;
}
if (cssTree.property(node.property).custom) {
if (/\S/.test(node.value.value)) {
node.value.value = node.value.value.trim();
}
}
}
module.exports = cleanDeclartion;

13
node_modules/csso/cjs/clean/Raw.cjs generated vendored Normal file
View File

@@ -0,0 +1,13 @@
'use strict';
const utils = require('./utils.cjs');
function cleanRaw(node, item, list) {
// raw in stylesheet or block children
if (utils.isNodeChildrenList(this.stylesheet, list) ||
utils.isNodeChildrenList(this.block, list)) {
list.remove(item);
}
}
module.exports = cleanRaw;

104
node_modules/csso/cjs/clean/Rule.cjs generated vendored Normal file
View File

@@ -0,0 +1,104 @@
'use strict';
const cssTree = require('css-tree');
const utils = require('./utils.cjs');
const { hasOwnProperty } = Object.prototype;
const skipUsageFilteringAtrule = new Set(['keyframes']);
function cleanUnused(selectorList, usageData) {
selectorList.children.forEach((selector, item, list) => {
let shouldRemove = false;
cssTree.walk(selector, function(node) {
// ignore nodes in nested selectors
if (this.selector === null || this.selector === selectorList) {
switch (node.type) {
case 'SelectorList':
// TODO: remove toLowerCase when pseudo selectors will be normalized
// ignore selectors inside :not()
if (this.function === null || this.function.name.toLowerCase() !== 'not') {
if (cleanUnused(node, usageData)) {
shouldRemove = true;
}
}
break;
case 'ClassSelector':
if (usageData.whitelist !== null &&
usageData.whitelist.classes !== null &&
!hasOwnProperty.call(usageData.whitelist.classes, node.name)) {
shouldRemove = true;
}
if (usageData.blacklist !== null &&
usageData.blacklist.classes !== null &&
hasOwnProperty.call(usageData.blacklist.classes, node.name)) {
shouldRemove = true;
}
break;
case 'IdSelector':
if (usageData.whitelist !== null &&
usageData.whitelist.ids !== null &&
!hasOwnProperty.call(usageData.whitelist.ids, node.name)) {
shouldRemove = true;
}
if (usageData.blacklist !== null &&
usageData.blacklist.ids !== null &&
hasOwnProperty.call(usageData.blacklist.ids, node.name)) {
shouldRemove = true;
}
break;
case 'TypeSelector':
// TODO: remove toLowerCase when type selectors will be normalized
// ignore universal selectors
if (node.name.charAt(node.name.length - 1) !== '*') {
if (usageData.whitelist !== null &&
usageData.whitelist.tags !== null &&
!hasOwnProperty.call(usageData.whitelist.tags, node.name.toLowerCase())) {
shouldRemove = true;
}
if (usageData.blacklist !== null &&
usageData.blacklist.tags !== null &&
hasOwnProperty.call(usageData.blacklist.tags, node.name.toLowerCase())) {
shouldRemove = true;
}
}
break;
}
}
});
if (shouldRemove) {
list.remove(item);
}
});
return selectorList.children.isEmpty;
}
function cleanRule(node, item, list, options) {
if (utils.hasNoChildren(node.prelude) || utils.hasNoChildren(node.block)) {
list.remove(item);
return;
}
// avoid usage filtering for some at-rules
if (this.atrule && skipUsageFilteringAtrule.has(cssTree.keyword(this.atrule.name).basename)) {
return;
}
const { usage } = options;
if (usage && (usage.whitelist !== null || usage.blacklist !== null)) {
cleanUnused(node.prelude, usage);
if (utils.hasNoChildren(node.prelude)) {
list.remove(item);
return;
}
}
}
module.exports = cleanRule;

23
node_modules/csso/cjs/clean/TypeSelector.cjs generated vendored Normal file
View File

@@ -0,0 +1,23 @@
'use strict';
// remove useless universal selector
function cleanTypeSelector(node, item, list) {
const name = item.data.name;
// check it's a non-namespaced universal selector
if (name !== '*') {
return;
}
// remove when universal selector before other selectors
const nextType = item.next && item.next.data.type;
if (nextType === 'IdSelector' ||
nextType === 'ClassSelector' ||
nextType === 'AttributeSelector' ||
nextType === 'PseudoClassSelector' ||
nextType === 'PseudoElementSelector') {
list.remove(item);
}
}
module.exports = cleanTypeSelector;

7
node_modules/csso/cjs/clean/WhiteSpace.cjs generated vendored Normal file
View File

@@ -0,0 +1,7 @@
'use strict';
function cleanWhitespace(node, item, list) {
list.remove(item);
}
module.exports = cleanWhitespace;

32
node_modules/csso/cjs/clean/index.cjs generated vendored Normal file
View File

@@ -0,0 +1,32 @@
'use strict';
const cssTree = require('css-tree');
const Atrule = require('./Atrule.cjs');
const Comment = require('./Comment.cjs');
const Declaration = require('./Declaration.cjs');
const Raw = require('./Raw.cjs');
const Rule = require('./Rule.cjs');
const TypeSelector = require('./TypeSelector.cjs');
const WhiteSpace = require('./WhiteSpace.cjs');
const handlers = {
Atrule,
Comment,
Declaration,
Raw,
Rule,
TypeSelector,
WhiteSpace
};
function clean(ast, options) {
cssTree.walk(ast, {
leave(node, item, list) {
if (handlers.hasOwnProperty(node.type)) {
handlers[node.type].call(this, node, item, list, options);
}
}
});
}
module.exports = clean;

12
node_modules/csso/cjs/clean/utils.cjs generated vendored Normal file
View File

@@ -0,0 +1,12 @@
'use strict';
function hasNoChildren(node) {
return !node || !node.children || node.children.isEmpty;
}
function isNodeChildrenList(node, list) {
return node !== null && node.children === list;
}
exports.hasNoChildren = hasNoChildren;
exports.isNodeChildrenList = isNodeChildrenList;

200
node_modules/csso/cjs/compress.cjs generated vendored Executable file
View File

@@ -0,0 +1,200 @@
'use strict';
const cssTree = require('css-tree');
const usage = require('./usage.cjs');
const index = require('./clean/index.cjs');
const index$1 = require('./replace/index.cjs');
const index$2 = require('./restructure/index.cjs');
function readChunk(input, specialComments) {
const children = new cssTree.List();
let nonSpaceTokenInBuffer = false;
let protectedComment;
input.nextUntil(input.head, (node, item, list) => {
if (node.type === 'Comment') {
if (!specialComments || node.value.charAt(0) !== '!') {
list.remove(item);
return;
}
if (nonSpaceTokenInBuffer || protectedComment) {
return true;
}
list.remove(item);
protectedComment = node;
return;
}
if (node.type !== 'WhiteSpace') {
nonSpaceTokenInBuffer = true;
}
children.insert(list.remove(item));
});
return {
comment: protectedComment,
stylesheet: {
type: 'StyleSheet',
loc: null,
children
}
};
}
function compressChunk(ast, firstAtrulesAllowed, num, options) {
options.logger(`Compress block #${num}`, null, true);
let seed = 1;
if (ast.type === 'StyleSheet') {
ast.firstAtrulesAllowed = firstAtrulesAllowed;
ast.id = seed++;
}
cssTree.walk(ast, {
visit: 'Atrule',
enter(node) {
if (node.block !== null) {
node.block.id = seed++;
}
}
});
options.logger('init', ast);
// remove redundant
index(ast, options);
options.logger('clean', ast);
// replace nodes for shortened forms
index$1(ast);
options.logger('replace', ast);
// structure optimisations
if (options.restructuring) {
index$2(ast, options);
}
return ast;
}
function getCommentsOption(options) {
let comments = 'comments' in options ? options.comments : 'exclamation';
if (typeof comments === 'boolean') {
comments = comments ? 'exclamation' : false;
} else if (comments !== 'exclamation' && comments !== 'first-exclamation') {
comments = false;
}
return comments;
}
function getRestructureOption(options) {
if ('restructure' in options) {
return options.restructure;
}
return 'restructuring' in options ? options.restructuring : true;
}
function wrapBlock(block) {
return new cssTree.List().appendData({
type: 'Rule',
loc: null,
prelude: {
type: 'SelectorList',
loc: null,
children: new cssTree.List().appendData({
type: 'Selector',
loc: null,
children: new cssTree.List().appendData({
type: 'TypeSelector',
loc: null,
name: 'x'
})
})
},
block
});
}
function compress(ast, options) {
ast = ast || { type: 'StyleSheet', loc: null, children: new cssTree.List() };
options = options || {};
const compressOptions = {
logger: typeof options.logger === 'function' ? options.logger : function() {},
restructuring: getRestructureOption(options),
forceMediaMerge: Boolean(options.forceMediaMerge),
usage: options.usage ? usage.buildIndex(options.usage) : false
};
const output = new cssTree.List();
let specialComments = getCommentsOption(options);
let firstAtrulesAllowed = true;
let input;
let chunk;
let chunkNum = 1;
let chunkChildren;
if (options.clone) {
ast = cssTree.clone(ast);
}
if (ast.type === 'StyleSheet') {
input = ast.children;
ast.children = output;
} else {
input = wrapBlock(ast);
}
do {
chunk = readChunk(input, Boolean(specialComments));
compressChunk(chunk.stylesheet, firstAtrulesAllowed, chunkNum++, compressOptions);
chunkChildren = chunk.stylesheet.children;
if (chunk.comment) {
// add \n before comment if there is another content in output
if (!output.isEmpty) {
output.insert(cssTree.List.createItem({
type: 'Raw',
value: '\n'
}));
}
output.insert(cssTree.List.createItem(chunk.comment));
// add \n after comment if chunk is not empty
if (!chunkChildren.isEmpty) {
output.insert(cssTree.List.createItem({
type: 'Raw',
value: '\n'
}));
}
}
if (firstAtrulesAllowed && !chunkChildren.isEmpty) {
const lastRule = chunkChildren.last;
if (lastRule.type !== 'Atrule' ||
(lastRule.name !== 'import' && lastRule.name !== 'charset')) {
firstAtrulesAllowed = false;
}
}
if (specialComments !== 'exclamation') {
specialComments = false;
}
output.appendList(chunkChildren);
} while (!input.isEmpty);
return {
ast
};
}
module.exports = compress;

127
node_modules/csso/cjs/index.cjs generated vendored Executable file
View File

@@ -0,0 +1,127 @@
'use strict';
const version = require('./version.cjs');
const syntax = require('./syntax.cjs');
const utils = require('./utils.cjs');
const { parse, generate, compress } = syntax;
function debugOutput(name, options, startTime, data) {
if (options.debug) {
console.error(`## ${name} done in %d ms\n`, Date.now() - startTime);
}
return data;
}
function createDefaultLogger(level) {
let lastDebug;
return function logger(title, ast) {
let line = title;
if (ast) {
line = `[${((Date.now() - lastDebug) / 1000).toFixed(3)}s] ${line}`;
}
if (level > 1 && ast) {
let css = generate(ast);
// when level 2, limit css to 256 symbols
if (level === 2 && css.length > 256) {
css = css.substr(0, 256) + '...';
}
line += `\n ${css}\n`;
}
console.error(line);
lastDebug = Date.now();
};
}
function buildCompressOptions(options) {
options = { ...options };
if (typeof options.logger !== 'function' && options.debug) {
options.logger = createDefaultLogger(options.debug);
}
return options;
}
function runHandler(ast, options, handlers) {
if (!Array.isArray(handlers)) {
handlers = [handlers];
}
handlers.forEach(fn => fn(ast, options));
}
function minify(context, source, options) {
options = options || {};
const filename = options.filename || '<unknown>';
let result;
// parse
const ast = debugOutput('parsing', options, Date.now(),
parse(source, {
context,
filename,
positions: Boolean(options.sourceMap)
})
);
// before compress handlers
if (options.beforeCompress) {
debugOutput('beforeCompress', options, Date.now(),
runHandler(ast, options, options.beforeCompress)
);
}
// compress
const compressResult = debugOutput('compress', options, Date.now(),
compress(ast, buildCompressOptions(options))
);
// after compress handlers
if (options.afterCompress) {
debugOutput('afterCompress', options, Date.now(),
runHandler(compressResult, options, options.afterCompress)
);
}
// generate
if (options.sourceMap) {
result = debugOutput('generate(sourceMap: true)', options, Date.now(), (() => {
const tmp = generate(compressResult.ast, { sourceMap: true });
tmp.map._file = filename; // since other tools can relay on file in source map transform chain
tmp.map.setSourceContent(filename, source);
return tmp;
})());
} else {
result = debugOutput('generate', options, Date.now(), {
css: generate(compressResult.ast),
map: null
});
}
return result;
}
function minifyStylesheet(source, options) {
return minify('stylesheet', source, options);
}
function minifyBlock(source, options) {
return minify('declarationList', source, options);
}
exports.version = version.version;
exports.syntax = syntax;
exports.utils = utils;
exports.minify = minifyStylesheet;
exports.minifyBlock = minifyBlock;

13
node_modules/csso/cjs/replace/Atrule.cjs generated vendored Normal file
View File

@@ -0,0 +1,13 @@
'use strict';
const cssTree = require('css-tree');
const keyframes = require('./atrule/keyframes.cjs');
function Atrule(node) {
// compress @keyframe selectors
if (cssTree.keyword(node.name).basename === 'keyframes') {
keyframes(node);
}
}
module.exports = Atrule;

32
node_modules/csso/cjs/replace/AttributeSelector.cjs generated vendored Normal file
View File

@@ -0,0 +1,32 @@
'use strict';
// Can unquote attribute detection
// Adopted implementation of Mathias Bynens
// https://github.com/mathiasbynens/mothereff.in/blob/master/unquoted-attributes/eff.js
const blockUnquoteRx = /^(-?\d|--)|[\u0000-\u002c\u002e\u002f\u003A-\u0040\u005B-\u005E\u0060\u007B-\u009f]/;
function canUnquote(value) {
if (value === '' || value === '-') {
return false;
}
return !blockUnquoteRx.test(value);
}
function AttributeSelector(node) {
const attrValue = node.value;
if (!attrValue || attrValue.type !== 'String') {
return;
}
if (canUnquote(attrValue.value)) {
node.value = {
type: 'Identifier',
loc: attrValue.loc,
name: attrValue.value
};
}
}
module.exports = AttributeSelector;

67
node_modules/csso/cjs/replace/Dimension.cjs generated vendored Normal file
View File

@@ -0,0 +1,67 @@
'use strict';
const _Number = require('./Number.cjs');
const MATH_FUNCTIONS = new Set([
'calc',
'min',
'max',
'clamp'
]);
const LENGTH_UNIT = new Set([
// absolute length units
'px',
'mm',
'cm',
'in',
'pt',
'pc',
// relative length units
'em',
'ex',
'ch',
'rem',
// viewport-percentage lengths
'vh',
'vw',
'vmin',
'vmax',
'vm'
]);
function compressDimension(node, item) {
const value = _Number.packNumber(node.value);
node.value = value;
if (value === '0' && this.declaration !== null && this.atrulePrelude === null) {
const unit = node.unit.toLowerCase();
// only length values can be compressed
if (!LENGTH_UNIT.has(unit)) {
return;
}
// issue #362: shouldn't remove unit in -ms-flex since it breaks flex in IE10/11
// issue #200: shouldn't remove unit in flex since it breaks flex in IE10/11
if (this.declaration.property === '-ms-flex' ||
this.declaration.property === 'flex') {
return;
}
// issue #222: don't remove units inside calc
if (this.function && MATH_FUNCTIONS.has(this.function.name)) {
return;
}
item.data = {
type: 'Number',
loc: node.loc,
value
};
}
}
module.exports = compressDimension;

45
node_modules/csso/cjs/replace/Number.cjs generated vendored Normal file
View File

@@ -0,0 +1,45 @@
'use strict';
const OMIT_PLUSSIGN = /^(?:\+|(-))?0*(\d*)(?:\.0*|(\.\d*?)0*)?$/;
const KEEP_PLUSSIGN = /^([\+\-])?0*(\d*)(?:\.0*|(\.\d*?)0*)?$/;
const unsafeToRemovePlusSignAfter = new Set([
'Dimension',
'Hash',
'Identifier',
'Number',
'Raw',
'UnicodeRange'
]);
function packNumber(value, item) {
// omit plus sign only if no prev or prev is safe type
const regexp = item && item.prev !== null && unsafeToRemovePlusSignAfter.has(item.prev.data.type)
? KEEP_PLUSSIGN
: OMIT_PLUSSIGN;
// 100 -> '100'
// 00100 -> '100'
// +100 -> '100'
// -100 -> '-100'
// 0.123 -> '.123'
// 0.12300 -> '.123'
// 0.0 -> ''
// 0 -> ''
// -0 -> '-'
value = String(value).replace(regexp, '$1$2$3');
if (value === '' || value === '-') {
value = '0';
}
// FIXME: is it solution simplier?
// value = String(Number(value)).replace(/^(-?)0+\./, '$1.');
return value;
}
function Number(node) {
node.value = packNumber(node.value);
}
exports.Number = Number;
exports.packNumber = packNumber;

41
node_modules/csso/cjs/replace/Percentage.cjs generated vendored Normal file
View File

@@ -0,0 +1,41 @@
'use strict';
const cssTree = require('css-tree');
const _Number = require('./Number.cjs');
const blacklist = new Set([
// see https://github.com/jakubpawlowicz/clean-css/issues/957
'width',
'min-width',
'max-width',
'height',
'min-height',
'max-height',
// issue #410: Dont remove units in flex-basis value for (-ms-)flex shorthand
// issue #362: shouldn't remove unit in -ms-flex since it breaks flex in IE10/11
// issue #200: shouldn't remove unit in flex since it breaks flex in IE10/11
'flex',
'-ms-flex'
]);
function compressPercentage(node, item) {
node.value = _Number.packNumber(node.value);
if (node.value === '0' && this.declaration && !blacklist.has(this.declaration.property)) {
// try to convert a number
item.data = {
type: 'Number',
loc: node.loc,
value: node.value
};
// that's ok only when new value matches on length
if (!cssTree.lexer.matchDeclaration(this.declaration).isType(item.data, 'length')) {
// otherwise rollback changes
item.data = node;
}
}
}
module.exports = compressPercentage;

8
node_modules/csso/cjs/replace/Url.cjs generated vendored Normal file
View File

@@ -0,0 +1,8 @@
'use strict';
function Url(node) {
// convert `\\` to `/`
node.value = node.value.replace(/\\/g, '/');
}
module.exports = Url;

29
node_modules/csso/cjs/replace/Value.cjs generated vendored Normal file
View File

@@ -0,0 +1,29 @@
'use strict';
const cssTree = require('css-tree');
const font = require('./property/font.cjs');
const fontWeight = require('./property/font-weight.cjs');
const background = require('./property/background.cjs');
const border = require('./property/border.cjs');
const handlers = {
'font': font,
'font-weight': fontWeight,
'background': background,
'border': border,
'outline': border
};
function compressValue(node) {
if (!this.declaration) {
return;
}
const property = cssTree.property(this.declaration.property);
if (handlers.hasOwnProperty(property.basename)) {
handlers[property.basename](node);
}
}
module.exports = compressValue;

25
node_modules/csso/cjs/replace/atrule/keyframes.cjs generated vendored Normal file
View File

@@ -0,0 +1,25 @@
'use strict';
function compressKeyframes(node) {
node.block.children.forEach((rule) => {
rule.prelude.children.forEach((simpleselector) => {
simpleselector.children.forEach((data, item) => {
if (data.type === 'Percentage' && data.value === '100') {
item.data = {
type: 'TypeSelector',
loc: data.loc,
name: 'to'
};
} else if (data.type === 'TypeSelector' && data.name === 'from') {
item.data = {
type: 'Percentage',
loc: data.loc,
value: '0'
};
}
});
});
});
}
module.exports = compressKeyframes;

504
node_modules/csso/cjs/replace/color.cjs generated vendored Normal file
View File

@@ -0,0 +1,504 @@
'use strict';
const cssTree = require('css-tree');
const _Number = require('./Number.cjs');
// http://www.w3.org/TR/css3-color/#svg-color
const NAME_TO_HEX = {
'aliceblue': 'f0f8ff',
'antiquewhite': 'faebd7',
'aqua': '0ff',
'aquamarine': '7fffd4',
'azure': 'f0ffff',
'beige': 'f5f5dc',
'bisque': 'ffe4c4',
'black': '000',
'blanchedalmond': 'ffebcd',
'blue': '00f',
'blueviolet': '8a2be2',
'brown': 'a52a2a',
'burlywood': 'deb887',
'cadetblue': '5f9ea0',
'chartreuse': '7fff00',
'chocolate': 'd2691e',
'coral': 'ff7f50',
'cornflowerblue': '6495ed',
'cornsilk': 'fff8dc',
'crimson': 'dc143c',
'cyan': '0ff',
'darkblue': '00008b',
'darkcyan': '008b8b',
'darkgoldenrod': 'b8860b',
'darkgray': 'a9a9a9',
'darkgrey': 'a9a9a9',
'darkgreen': '006400',
'darkkhaki': 'bdb76b',
'darkmagenta': '8b008b',
'darkolivegreen': '556b2f',
'darkorange': 'ff8c00',
'darkorchid': '9932cc',
'darkred': '8b0000',
'darksalmon': 'e9967a',
'darkseagreen': '8fbc8f',
'darkslateblue': '483d8b',
'darkslategray': '2f4f4f',
'darkslategrey': '2f4f4f',
'darkturquoise': '00ced1',
'darkviolet': '9400d3',
'deeppink': 'ff1493',
'deepskyblue': '00bfff',
'dimgray': '696969',
'dimgrey': '696969',
'dodgerblue': '1e90ff',
'firebrick': 'b22222',
'floralwhite': 'fffaf0',
'forestgreen': '228b22',
'fuchsia': 'f0f',
'gainsboro': 'dcdcdc',
'ghostwhite': 'f8f8ff',
'gold': 'ffd700',
'goldenrod': 'daa520',
'gray': '808080',
'grey': '808080',
'green': '008000',
'greenyellow': 'adff2f',
'honeydew': 'f0fff0',
'hotpink': 'ff69b4',
'indianred': 'cd5c5c',
'indigo': '4b0082',
'ivory': 'fffff0',
'khaki': 'f0e68c',
'lavender': 'e6e6fa',
'lavenderblush': 'fff0f5',
'lawngreen': '7cfc00',
'lemonchiffon': 'fffacd',
'lightblue': 'add8e6',
'lightcoral': 'f08080',
'lightcyan': 'e0ffff',
'lightgoldenrodyellow': 'fafad2',
'lightgray': 'd3d3d3',
'lightgrey': 'd3d3d3',
'lightgreen': '90ee90',
'lightpink': 'ffb6c1',
'lightsalmon': 'ffa07a',
'lightseagreen': '20b2aa',
'lightskyblue': '87cefa',
'lightslategray': '789',
'lightslategrey': '789',
'lightsteelblue': 'b0c4de',
'lightyellow': 'ffffe0',
'lime': '0f0',
'limegreen': '32cd32',
'linen': 'faf0e6',
'magenta': 'f0f',
'maroon': '800000',
'mediumaquamarine': '66cdaa',
'mediumblue': '0000cd',
'mediumorchid': 'ba55d3',
'mediumpurple': '9370db',
'mediumseagreen': '3cb371',
'mediumslateblue': '7b68ee',
'mediumspringgreen': '00fa9a',
'mediumturquoise': '48d1cc',
'mediumvioletred': 'c71585',
'midnightblue': '191970',
'mintcream': 'f5fffa',
'mistyrose': 'ffe4e1',
'moccasin': 'ffe4b5',
'navajowhite': 'ffdead',
'navy': '000080',
'oldlace': 'fdf5e6',
'olive': '808000',
'olivedrab': '6b8e23',
'orange': 'ffa500',
'orangered': 'ff4500',
'orchid': 'da70d6',
'palegoldenrod': 'eee8aa',
'palegreen': '98fb98',
'paleturquoise': 'afeeee',
'palevioletred': 'db7093',
'papayawhip': 'ffefd5',
'peachpuff': 'ffdab9',
'peru': 'cd853f',
'pink': 'ffc0cb',
'plum': 'dda0dd',
'powderblue': 'b0e0e6',
'purple': '800080',
'rebeccapurple': '639',
'red': 'f00',
'rosybrown': 'bc8f8f',
'royalblue': '4169e1',
'saddlebrown': '8b4513',
'salmon': 'fa8072',
'sandybrown': 'f4a460',
'seagreen': '2e8b57',
'seashell': 'fff5ee',
'sienna': 'a0522d',
'silver': 'c0c0c0',
'skyblue': '87ceeb',
'slateblue': '6a5acd',
'slategray': '708090',
'slategrey': '708090',
'snow': 'fffafa',
'springgreen': '00ff7f',
'steelblue': '4682b4',
'tan': 'd2b48c',
'teal': '008080',
'thistle': 'd8bfd8',
'tomato': 'ff6347',
'turquoise': '40e0d0',
'violet': 'ee82ee',
'wheat': 'f5deb3',
'white': 'fff',
'whitesmoke': 'f5f5f5',
'yellow': 'ff0',
'yellowgreen': '9acd32'
};
const HEX_TO_NAME = {
'800000': 'maroon',
'800080': 'purple',
'808000': 'olive',
'808080': 'gray',
'00ffff': 'cyan',
'f0ffff': 'azure',
'f5f5dc': 'beige',
'ffe4c4': 'bisque',
'000000': 'black',
'0000ff': 'blue',
'a52a2a': 'brown',
'ff7f50': 'coral',
'ffd700': 'gold',
'008000': 'green',
'4b0082': 'indigo',
'fffff0': 'ivory',
'f0e68c': 'khaki',
'00ff00': 'lime',
'faf0e6': 'linen',
'000080': 'navy',
'ffa500': 'orange',
'da70d6': 'orchid',
'cd853f': 'peru',
'ffc0cb': 'pink',
'dda0dd': 'plum',
'f00': 'red',
'ff0000': 'red',
'fa8072': 'salmon',
'a0522d': 'sienna',
'c0c0c0': 'silver',
'fffafa': 'snow',
'd2b48c': 'tan',
'008080': 'teal',
'ff6347': 'tomato',
'ee82ee': 'violet',
'f5deb3': 'wheat',
'ffffff': 'white',
'ffff00': 'yellow'
};
function hueToRgb(p, q, t) {
if (t < 0) {
t += 1;
}
if (t > 1) {
t -= 1;
}
if (t < 1 / 6) {
return p + (q - p) * 6 * t;
}
if (t < 1 / 2) {
return q;
}
if (t < 2 / 3) {
return p + (q - p) * (2 / 3 - t) * 6;
}
return p;
}
function hslToRgb(h, s, l, a) {
let r;
let g;
let b;
if (s === 0) {
r = g = b = l; // achromatic
} else {
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hueToRgb(p, q, h + 1 / 3);
g = hueToRgb(p, q, h);
b = hueToRgb(p, q, h - 1 / 3);
}
return [
Math.round(r * 255),
Math.round(g * 255),
Math.round(b * 255),
a
];
}
function toHex(value) {
value = value.toString(16);
return value.length === 1 ? '0' + value : value;
}
function parseFunctionArgs(functionArgs, count, rgb) {
let cursor = functionArgs.head;
let args = [];
let wasValue = false;
while (cursor !== null) {
const { type, value } = cursor.data;
switch (type) {
case 'Number':
case 'Percentage':
if (wasValue) {
return;
}
wasValue = true;
args.push({
type,
value: Number(value)
});
break;
case 'Operator':
if (value === ',') {
if (!wasValue) {
return;
}
wasValue = false;
} else if (wasValue || value !== '+') {
return;
}
break;
default:
// something we couldn't understand
return;
}
cursor = cursor.next;
}
if (args.length !== count) {
// invalid arguments count
// TODO: remove those tokens
return;
}
if (args.length === 4) {
if (args[3].type !== 'Number') {
// 4th argument should be a number
// TODO: remove those tokens
return;
}
args[3].type = 'Alpha';
}
if (rgb) {
if (args[0].type !== args[1].type || args[0].type !== args[2].type) {
// invalid color, numbers and percentage shouldn't be mixed
// TODO: remove those tokens
return;
}
} else {
if (args[0].type !== 'Number' ||
args[1].type !== 'Percentage' ||
args[2].type !== 'Percentage') {
// invalid color, for hsl values should be: number, percentage, percentage
// TODO: remove those tokens
return;
}
args[0].type = 'Angle';
}
return args.map(function(arg) {
let value = Math.max(0, arg.value);
switch (arg.type) {
case 'Number':
// fit value to [0..255] range
value = Math.min(value, 255);
break;
case 'Percentage':
// convert 0..100% to value in [0..255] range
value = Math.min(value, 100) / 100;
if (!rgb) {
return value;
}
value = 255 * value;
break;
case 'Angle':
// fit value to (-360..360) range
return (((value % 360) + 360) % 360) / 360;
case 'Alpha':
// fit value to [0..1] range
return Math.min(value, 1);
}
return Math.round(value);
});
}
function compressFunction(node, item) {
let functionName = node.name;
let args;
if (functionName === 'rgba' || functionName === 'hsla') {
args = parseFunctionArgs(node.children, 4, functionName === 'rgba');
if (!args) {
// something went wrong
return;
}
if (functionName === 'hsla') {
args = hslToRgb(...args);
node.name = 'rgba';
}
if (args[3] === 0) {
// try to replace `rgba(x, x, x, 0)` to `transparent`
// always replace `rgba(0, 0, 0, 0)` to `transparent`
// otherwise avoid replacement in gradients since it may break color transition
// http://stackoverflow.com/questions/11829410/css3-gradient-rendering-issues-from-transparent-to-white
const scopeFunctionName = this.function && this.function.name;
if ((args[0] === 0 && args[1] === 0 && args[2] === 0) ||
!/^(?:to|from|color-stop)$|gradient$/i.test(scopeFunctionName)) {
item.data = {
type: 'Identifier',
loc: node.loc,
name: 'transparent'
};
return;
}
}
if (args[3] !== 1) {
// replace argument values for normalized/interpolated
node.children.forEach((node, item, list) => {
if (node.type === 'Operator') {
if (node.value !== ',') {
list.remove(item);
}
return;
}
item.data = {
type: 'Number',
loc: node.loc,
value: _Number.packNumber(args.shift())
};
});
return;
}
// otherwise convert to rgb, i.e. rgba(255, 0, 0, 1) -> rgb(255, 0, 0)
functionName = 'rgb';
}
if (functionName === 'hsl') {
args = args || parseFunctionArgs(node.children, 3, false);
if (!args) {
// something went wrong
return;
}
// convert to rgb
args = hslToRgb(...args);
functionName = 'rgb';
}
if (functionName === 'rgb') {
args = args || parseFunctionArgs(node.children, 3, true);
if (!args) {
// something went wrong
return;
}
item.data = {
type: 'Hash',
loc: node.loc,
value: toHex(args[0]) + toHex(args[1]) + toHex(args[2])
};
compressHex(item.data, item);
}
}
function compressIdent(node, item) {
if (this.declaration === null) {
return;
}
let color = node.name.toLowerCase();
if (NAME_TO_HEX.hasOwnProperty(color) &&
cssTree.lexer.matchDeclaration(this.declaration).isType(node, 'color')) {
const hex = NAME_TO_HEX[color];
if (hex.length + 1 <= color.length) {
// replace for shorter hex value
item.data = {
type: 'Hash',
loc: node.loc,
value: hex
};
} else {
// special case for consistent colors
if (color === 'grey') {
color = 'gray';
}
// just replace value for lower cased name
node.name = color;
}
}
}
function compressHex(node, item) {
let color = node.value.toLowerCase();
// #112233 -> #123
if (color.length === 6 &&
color[0] === color[1] &&
color[2] === color[3] &&
color[4] === color[5]) {
color = color[0] + color[2] + color[4];
}
if (HEX_TO_NAME[color]) {
item.data = {
type: 'Identifier',
loc: node.loc,
name: HEX_TO_NAME[color]
};
} else {
node.value = color;
}
}
exports.compressFunction = compressFunction;
exports.compressHex = compressHex;
exports.compressIdent = compressIdent;

36
node_modules/csso/cjs/replace/index.cjs generated vendored Normal file
View File

@@ -0,0 +1,36 @@
'use strict';
const cssTree = require('css-tree');
const Atrule = require('./Atrule.cjs');
const AttributeSelector = require('./AttributeSelector.cjs');
const Value = require('./Value.cjs');
const Dimension = require('./Dimension.cjs');
const Percentage = require('./Percentage.cjs');
const _Number = require('./Number.cjs');
const Url = require('./Url.cjs');
const color = require('./color.cjs');
const handlers = {
Atrule,
AttributeSelector,
Value,
Dimension,
Percentage,
Number: _Number.Number,
Url,
Hash: color.compressHex,
Identifier: color.compressIdent,
Function: color.compressFunction
};
function replace(ast) {
cssTree.walk(ast, {
leave(node, item, list) {
if (handlers.hasOwnProperty(node.type)) {
handlers[node.type].call(this, node, item, list);
}
}
});
}
module.exports = replace;

54
node_modules/csso/cjs/replace/property/background.cjs generated vendored Normal file
View File

@@ -0,0 +1,54 @@
'use strict';
const cssTree = require('css-tree');
function compressBackground(node) {
function flush() {
if (!buffer.length) {
buffer.unshift(
{
type: 'Number',
loc: null,
value: '0'
},
{
type: 'Number',
loc: null,
value: '0'
}
);
}
newValue.push.apply(newValue, buffer);
buffer = [];
}
let newValue = [];
let buffer = [];
node.children.forEach((node) => {
if (node.type === 'Operator' && node.value === ',') {
flush();
newValue.push(node);
return;
}
// remove defaults
if (node.type === 'Identifier') {
if (node.name === 'transparent' ||
node.name === 'none' ||
node.name === 'repeat' ||
node.name === 'scroll') {
return;
}
}
buffer.push(node);
});
flush();
node.children = new cssTree.List().fromArray(newValue);
}
module.exports = compressBackground;

20
node_modules/csso/cjs/replace/property/border.cjs generated vendored Normal file
View File

@@ -0,0 +1,20 @@
'use strict';
function compressBorder(node) {
node.children.forEach((node, item, list) => {
if (node.type === 'Identifier' && node.name.toLowerCase() === 'none') {
if (list.head === list.tail) {
// replace `none` for zero when `none` is a single term
item.data = {
type: 'Number',
loc: node.loc,
value: '0'
};
} else {
list.remove(item);
}
}
});
}
module.exports = compressBorder;

26
node_modules/csso/cjs/replace/property/font-weight.cjs generated vendored Normal file
View File

@@ -0,0 +1,26 @@
'use strict';
function compressFontWeight(node) {
const value = node.children.head.data;
if (value.type === 'Identifier') {
switch (value.name) {
case 'normal':
node.children.head.data = {
type: 'Number',
loc: value.loc,
value: '400'
};
break;
case 'bold':
node.children.head.data = {
type: 'Number',
loc: value.loc,
value: '700'
};
break;
}
}
}
module.exports = compressFontWeight;

34
node_modules/csso/cjs/replace/property/font.cjs generated vendored Normal file
View File

@@ -0,0 +1,34 @@
'use strict';
function compressFont(node) {
const list = node.children;
list.forEachRight(function(node, item) {
if (node.type === 'Identifier') {
if (node.name === 'bold') {
item.data = {
type: 'Number',
loc: node.loc,
value: '700'
};
} else if (node.name === 'normal') {
const prev = item.prev;
if (prev && prev.data.type === 'Operator' && prev.data.value === '/') {
this.remove(prev);
}
this.remove(item);
}
}
});
if (list.isEmpty) {
list.insert(list.createItem({
type: 'Identifier',
name: 'normal'
}));
}
}
module.exports = compressFont;

109
node_modules/csso/cjs/restructure/1-mergeAtrule.cjs generated vendored Executable file
View File

@@ -0,0 +1,109 @@
'use strict';
const cssTree = require('css-tree');
const { hasOwnProperty } = Object.prototype;
function addRuleToMap(map, item, list, single) {
const node = item.data;
const name = cssTree.keyword(node.name).basename;
const id = node.name.toLowerCase() + '/' + (node.prelude ? node.prelude.id : null);
if (!hasOwnProperty.call(map, name)) {
map[name] = Object.create(null);
}
if (single) {
delete map[name][id];
}
if (!hasOwnProperty.call(map[name], id)) {
map[name][id] = new cssTree.List();
}
map[name][id].append(list.remove(item));
}
function relocateAtrules(ast, options) {
const collected = Object.create(null);
let topInjectPoint = null;
ast.children.forEach(function(node, item, list) {
if (node.type === 'Atrule') {
const name = cssTree.keyword(node.name).basename;
switch (name) {
case 'keyframes':
addRuleToMap(collected, item, list, true);
return;
case 'media':
if (options.forceMediaMerge) {
addRuleToMap(collected, item, list, false);
return;
}
break;
}
if (topInjectPoint === null &&
name !== 'charset' &&
name !== 'import') {
topInjectPoint = item;
}
} else {
if (topInjectPoint === null) {
topInjectPoint = item;
}
}
});
for (const atrule in collected) {
for (const id in collected[atrule]) {
ast.children.insertList(
collected[atrule][id],
atrule === 'media' ? null : topInjectPoint
);
}
}
}
function isMediaRule(node) {
return node.type === 'Atrule' && node.name === 'media';
}
function processAtrule(node, item, list) {
if (!isMediaRule(node)) {
return;
}
const prev = item.prev && item.prev.data;
if (!prev || !isMediaRule(prev)) {
return;
}
// merge @media with same query
if (node.prelude &&
prev.prelude &&
node.prelude.id === prev.prelude.id) {
prev.block.children.appendList(node.block.children);
list.remove(item);
// TODO: use it when we can refer to several points in source
// prev.loc = {
// primary: prev.loc,
// merged: node.loc
// };
}
}
function rejoinAtrule(ast, options) {
relocateAtrules(ast, options);
cssTree.walk(ast, {
visit: 'Atrule',
reverse: true,
enter: processAtrule
});
}
module.exports = rejoinAtrule;

51
node_modules/csso/cjs/restructure/2-initialMergeRuleset.cjs generated vendored Executable file
View File

@@ -0,0 +1,51 @@
'use strict';
const cssTree = require('css-tree');
const utils = require('./utils.cjs');
function processRule(node, item, list) {
const selectors = node.prelude.children;
const declarations = node.block.children;
list.prevUntil(item.prev, function(prev) {
// skip non-ruleset node if safe
if (prev.type !== 'Rule') {
return utils.unsafeToSkipNode.call(selectors, prev);
}
const prevSelectors = prev.prelude.children;
const prevDeclarations = prev.block.children;
// try to join rulesets with equal pseudo signature
if (node.pseudoSignature === prev.pseudoSignature) {
// try to join by selectors
if (utils.isEqualSelectors(prevSelectors, selectors)) {
prevDeclarations.appendList(declarations);
list.remove(item);
return true;
}
// try to join by declarations
if (utils.isEqualDeclarations(declarations, prevDeclarations)) {
utils.addSelectors(prevSelectors, selectors);
list.remove(item);
return true;
}
}
// go to prev ruleset if has no selector similarities
return utils.hasSimilarSelectors(selectors, prevSelectors);
});
}
// NOTE: direction should be left to right, since rulesets merge to left
// ruleset. When direction right to left unmerged rulesets may prevent lookup
// TODO: remove initial merge
function initialMergeRule(ast) {
cssTree.walk(ast, {
visit: 'Rule',
enter: processRule
});
}
module.exports = initialMergeRule;

46
node_modules/csso/cjs/restructure/3-disjoinRuleset.cjs generated vendored Executable file
View File

@@ -0,0 +1,46 @@
'use strict';
const cssTree = require('css-tree');
function processRule(node, item, list) {
const selectors = node.prelude.children;
// generate new rule sets:
// .a, .b { color: red; }
// ->
// .a { color: red; }
// .b { color: red; }
// while there are more than 1 simple selector split for rulesets
while (selectors.head !== selectors.tail) {
const newSelectors = new cssTree.List();
newSelectors.insert(selectors.remove(selectors.head));
list.insert(list.createItem({
type: 'Rule',
loc: node.loc,
prelude: {
type: 'SelectorList',
loc: node.prelude.loc,
children: newSelectors
},
block: {
type: 'Block',
loc: node.block.loc,
children: node.block.children.copy()
},
pseudoSignature: node.pseudoSignature
}), item);
}
}
function disjoinRule(ast) {
cssTree.walk(ast, {
visit: 'Rule',
reverse: true,
enter: processRule
});
}
module.exports = disjoinRule;

429
node_modules/csso/cjs/restructure/4-restructShorthand.cjs generated vendored Executable file
View File

@@ -0,0 +1,429 @@
'use strict';
const cssTree = require('css-tree');
const REPLACE = 1;
const REMOVE = 2;
const TOP = 0;
const RIGHT = 1;
const BOTTOM = 2;
const LEFT = 3;
const SIDES = ['top', 'right', 'bottom', 'left'];
const SIDE = {
'margin-top': 'top',
'margin-right': 'right',
'margin-bottom': 'bottom',
'margin-left': 'left',
'padding-top': 'top',
'padding-right': 'right',
'padding-bottom': 'bottom',
'padding-left': 'left',
'border-top-color': 'top',
'border-right-color': 'right',
'border-bottom-color': 'bottom',
'border-left-color': 'left',
'border-top-width': 'top',
'border-right-width': 'right',
'border-bottom-width': 'bottom',
'border-left-width': 'left',
'border-top-style': 'top',
'border-right-style': 'right',
'border-bottom-style': 'bottom',
'border-left-style': 'left'
};
const MAIN_PROPERTY = {
'margin': 'margin',
'margin-top': 'margin',
'margin-right': 'margin',
'margin-bottom': 'margin',
'margin-left': 'margin',
'padding': 'padding',
'padding-top': 'padding',
'padding-right': 'padding',
'padding-bottom': 'padding',
'padding-left': 'padding',
'border-color': 'border-color',
'border-top-color': 'border-color',
'border-right-color': 'border-color',
'border-bottom-color': 'border-color',
'border-left-color': 'border-color',
'border-width': 'border-width',
'border-top-width': 'border-width',
'border-right-width': 'border-width',
'border-bottom-width': 'border-width',
'border-left-width': 'border-width',
'border-style': 'border-style',
'border-top-style': 'border-style',
'border-right-style': 'border-style',
'border-bottom-style': 'border-style',
'border-left-style': 'border-style'
};
class TRBL {
constructor(name) {
this.name = name;
this.loc = null;
this.iehack = undefined;
this.sides = {
'top': null,
'right': null,
'bottom': null,
'left': null
};
}
getValueSequence(declaration, count) {
const values = [];
let iehack = '';
const hasBadValues = declaration.value.type !== 'Value' || declaration.value.children.some(function(child) {
let special = false;
switch (child.type) {
case 'Identifier':
switch (child.name) {
case '\\0':
case '\\9':
iehack = child.name;
return;
case 'inherit':
case 'initial':
case 'unset':
case 'revert':
special = child.name;
break;
}
break;
case 'Dimension':
switch (child.unit) {
// is not supported until IE11
case 'rem':
// v* units is too buggy across browsers and better
// don't merge values with those units
case 'vw':
case 'vh':
case 'vmin':
case 'vmax':
case 'vm': // IE9 supporting "vm" instead of "vmin".
special = child.unit;
break;
}
break;
case 'Hash': // color
case 'Number':
case 'Percentage':
break;
case 'Function':
if (child.name === 'var') {
return true;
}
special = child.name;
break;
default:
return true; // bad value
}
values.push({
node: child,
special,
important: declaration.important
});
});
if (hasBadValues || values.length > count) {
return false;
}
if (typeof this.iehack === 'string' && this.iehack !== iehack) {
return false;
}
this.iehack = iehack; // move outside
return values;
}
canOverride(side, value) {
const currentValue = this.sides[side];
return !currentValue || (value.important && !currentValue.important);
}
add(name, declaration) {
function attemptToAdd() {
const sides = this.sides;
const side = SIDE[name];
if (side) {
if (side in sides === false) {
return false;
}
const values = this.getValueSequence(declaration, 1);
if (!values || !values.length) {
return false;
}
// can mix only if specials are equal
for (const key in sides) {
if (sides[key] !== null && sides[key].special !== values[0].special) {
return false;
}
}
if (!this.canOverride(side, values[0])) {
return true;
}
sides[side] = values[0];
return true;
} else if (name === this.name) {
const values = this.getValueSequence(declaration, 4);
if (!values || !values.length) {
return false;
}
switch (values.length) {
case 1:
values[RIGHT] = values[TOP];
values[BOTTOM] = values[TOP];
values[LEFT] = values[TOP];
break;
case 2:
values[BOTTOM] = values[TOP];
values[LEFT] = values[RIGHT];
break;
case 3:
values[LEFT] = values[RIGHT];
break;
}
// can mix only if specials are equal
for (let i = 0; i < 4; i++) {
for (const key in sides) {
if (sides[key] !== null && sides[key].special !== values[i].special) {
return false;
}
}
}
for (let i = 0; i < 4; i++) {
if (this.canOverride(SIDES[i], values[i])) {
sides[SIDES[i]] = values[i];
}
}
return true;
}
}
if (!attemptToAdd.call(this)) {
return false;
}
// TODO: use it when we can refer to several points in source
// if (this.loc) {
// this.loc = {
// primary: this.loc,
// merged: declaration.loc
// };
// } else {
// this.loc = declaration.loc;
// }
if (!this.loc) {
this.loc = declaration.loc;
}
return true;
}
isOkToMinimize() {
const top = this.sides.top;
const right = this.sides.right;
const bottom = this.sides.bottom;
const left = this.sides.left;
if (top && right && bottom && left) {
const important =
top.important +
right.important +
bottom.important +
left.important;
return important === 0 || important === 4;
}
return false;
}
getValue() {
const result = new cssTree.List();
const sides = this.sides;
const values = [
sides.top,
sides.right,
sides.bottom,
sides.left
];
const stringValues = [
cssTree.generate(sides.top.node),
cssTree.generate(sides.right.node),
cssTree.generate(sides.bottom.node),
cssTree.generate(sides.left.node)
];
if (stringValues[LEFT] === stringValues[RIGHT]) {
values.pop();
if (stringValues[BOTTOM] === stringValues[TOP]) {
values.pop();
if (stringValues[RIGHT] === stringValues[TOP]) {
values.pop();
}
}
}
for (let i = 0; i < values.length; i++) {
result.appendData(values[i].node);
}
if (this.iehack) {
result.appendData({
type: 'Identifier',
loc: null,
name: this.iehack
});
}
return {
type: 'Value',
loc: null,
children: result
};
}
getDeclaration() {
return {
type: 'Declaration',
loc: this.loc,
important: this.sides.top.important,
property: this.name,
value: this.getValue()
};
}
}
function processRule(rule, shorts, shortDeclarations, lastShortSelector) {
const declarations = rule.block.children;
const selector = rule.prelude.children.first.id;
rule.block.children.forEachRight(function(declaration, item) {
const property = declaration.property;
if (!MAIN_PROPERTY.hasOwnProperty(property)) {
return;
}
const key = MAIN_PROPERTY[property];
let shorthand;
let operation;
if (!lastShortSelector || selector === lastShortSelector) {
if (key in shorts) {
operation = REMOVE;
shorthand = shorts[key];
}
}
if (!shorthand || !shorthand.add(property, declaration)) {
operation = REPLACE;
shorthand = new TRBL(key);
// if can't parse value ignore it and break shorthand children
if (!shorthand.add(property, declaration)) {
lastShortSelector = null;
return;
}
}
shorts[key] = shorthand;
shortDeclarations.push({
operation,
block: declarations,
item,
shorthand
});
lastShortSelector = selector;
});
return lastShortSelector;
}
function processShorthands(shortDeclarations, markDeclaration) {
shortDeclarations.forEach(function(item) {
const shorthand = item.shorthand;
if (!shorthand.isOkToMinimize()) {
return;
}
if (item.operation === REPLACE) {
item.item.data = markDeclaration(shorthand.getDeclaration());
} else {
item.block.remove(item.item);
}
});
}
function restructBlock(ast, indexer) {
const stylesheetMap = {};
const shortDeclarations = [];
cssTree.walk(ast, {
visit: 'Rule',
reverse: true,
enter(node) {
const stylesheet = this.block || this.stylesheet;
const ruleId = (node.pseudoSignature || '') + '|' + node.prelude.children.first.id;
let ruleMap;
let shorts;
if (!stylesheetMap.hasOwnProperty(stylesheet.id)) {
ruleMap = {
lastShortSelector: null
};
stylesheetMap[stylesheet.id] = ruleMap;
} else {
ruleMap = stylesheetMap[stylesheet.id];
}
if (ruleMap.hasOwnProperty(ruleId)) {
shorts = ruleMap[ruleId];
} else {
shorts = {};
ruleMap[ruleId] = shorts;
}
ruleMap.lastShortSelector = processRule.call(this, node, shorts, shortDeclarations, ruleMap.lastShortSelector);
}
});
processShorthands(shortDeclarations, indexer.declaration);
}
module.exports = restructBlock;

307
node_modules/csso/cjs/restructure/6-restructBlock.cjs generated vendored Executable file
View File

@@ -0,0 +1,307 @@
'use strict';
const cssTree = require('css-tree');
let fingerprintId = 1;
const dontRestructure = new Set([
'src' // https://github.com/afelix/csso/issues/50
]);
const DONT_MIX_VALUE = {
// https://developer.mozilla.org/en-US/docs/Web/CSS/display#Browser_compatibility
'display': /table|ruby|flex|-(flex)?box$|grid|contents|run-in/i,
// https://developer.mozilla.org/en/docs/Web/CSS/text-align
'text-align': /^(start|end|match-parent|justify-all)$/i
};
const SAFE_VALUES = {
cursor: [
'auto', 'crosshair', 'default', 'move', 'text', 'wait', 'help',
'n-resize', 'e-resize', 's-resize', 'w-resize',
'ne-resize', 'nw-resize', 'se-resize', 'sw-resize',
'pointer', 'progress', 'not-allowed', 'no-drop', 'vertical-text', 'all-scroll',
'col-resize', 'row-resize'
],
overflow: [
'hidden', 'visible', 'scroll', 'auto'
],
position: [
'static', 'relative', 'absolute', 'fixed'
]
};
const NEEDLESS_TABLE = {
'border-width': ['border'],
'border-style': ['border'],
'border-color': ['border'],
'border-top': ['border'],
'border-right': ['border'],
'border-bottom': ['border'],
'border-left': ['border'],
'border-top-width': ['border-top', 'border-width', 'border'],
'border-right-width': ['border-right', 'border-width', 'border'],
'border-bottom-width': ['border-bottom', 'border-width', 'border'],
'border-left-width': ['border-left', 'border-width', 'border'],
'border-top-style': ['border-top', 'border-style', 'border'],
'border-right-style': ['border-right', 'border-style', 'border'],
'border-bottom-style': ['border-bottom', 'border-style', 'border'],
'border-left-style': ['border-left', 'border-style', 'border'],
'border-top-color': ['border-top', 'border-color', 'border'],
'border-right-color': ['border-right', 'border-color', 'border'],
'border-bottom-color': ['border-bottom', 'border-color', 'border'],
'border-left-color': ['border-left', 'border-color', 'border'],
'margin-top': ['margin'],
'margin-right': ['margin'],
'margin-bottom': ['margin'],
'margin-left': ['margin'],
'padding-top': ['padding'],
'padding-right': ['padding'],
'padding-bottom': ['padding'],
'padding-left': ['padding'],
'font-style': ['font'],
'font-variant': ['font'],
'font-weight': ['font'],
'font-size': ['font'],
'font-family': ['font'],
'list-style-type': ['list-style'],
'list-style-position': ['list-style'],
'list-style-image': ['list-style']
};
function getPropertyFingerprint(propertyName, declaration, fingerprints) {
const realName = cssTree.property(propertyName).basename;
if (realName === 'background') {
return propertyName + ':' + cssTree.generate(declaration.value);
}
const declarationId = declaration.id;
let fingerprint = fingerprints[declarationId];
if (!fingerprint) {
switch (declaration.value.type) {
case 'Value':
const special = {};
let vendorId = '';
let iehack = '';
let raw = false;
declaration.value.children.forEach(function walk(node) {
switch (node.type) {
case 'Value':
case 'Brackets':
case 'Parentheses':
node.children.forEach(walk);
break;
case 'Raw':
raw = true;
break;
case 'Identifier': {
const { name } = node;
if (!vendorId) {
vendorId = cssTree.keyword(name).vendor;
}
if (/\\[09]/.test(name)) {
iehack = RegExp.lastMatch;
}
if (SAFE_VALUES.hasOwnProperty(realName)) {
if (SAFE_VALUES[realName].indexOf(name) === -1) {
special[name] = true;
}
} else if (DONT_MIX_VALUE.hasOwnProperty(realName)) {
if (DONT_MIX_VALUE[realName].test(name)) {
special[name] = true;
}
}
break;
}
case 'Function': {
let { name } = node;
if (!vendorId) {
vendorId = cssTree.keyword(name).vendor;
}
if (name === 'rect') {
// there are 2 forms of rect:
// rect(<top>, <right>, <bottom>, <left>) - standart
// rect(<top> <right> <bottom> <left>) backwards compatible syntax
// only the same form values can be merged
const hasComma = node.children.some((node) =>
node.type === 'Operator' && node.value === ','
);
if (!hasComma) {
name = 'rect-backward';
}
}
special[name + '()'] = true;
// check nested tokens too
node.children.forEach(walk);
break;
}
case 'Dimension': {
const { unit } = node;
if (/\\[09]/.test(unit)) {
iehack = RegExp.lastMatch;
}
switch (unit) {
// is not supported until IE11
case 'rem':
// v* units is too buggy across browsers and better
// don't merge values with those units
case 'vw':
case 'vh':
case 'vmin':
case 'vmax':
case 'vm': // IE9 supporting "vm" instead of "vmin".
special[unit] = true;
break;
}
break;
}
}
});
fingerprint = raw
? '!' + fingerprintId++
: '!' + Object.keys(special).sort() + '|' + iehack + vendorId;
break;
case 'Raw':
fingerprint = '!' + declaration.value.value;
break;
default:
fingerprint = cssTree.generate(declaration.value);
}
fingerprints[declarationId] = fingerprint;
}
return propertyName + fingerprint;
}
function needless(props, declaration, fingerprints) {
const property = cssTree.property(declaration.property);
if (NEEDLESS_TABLE.hasOwnProperty(property.basename)) {
const table = NEEDLESS_TABLE[property.basename];
for (const entry of table) {
const ppre = getPropertyFingerprint(property.prefix + entry, declaration, fingerprints);
const prev = props.hasOwnProperty(ppre) ? props[ppre] : null;
if (prev && (!declaration.important || prev.item.data.important)) {
return prev;
}
}
}
}
function processRule(rule, item, list, props, fingerprints) {
const declarations = rule.block.children;
declarations.forEachRight(function(declaration, declarationItem) {
const { property } = declaration;
const fingerprint = getPropertyFingerprint(property, declaration, fingerprints);
const prev = props[fingerprint];
if (prev && !dontRestructure.has(property)) {
if (declaration.important && !prev.item.data.important) {
props[fingerprint] = {
block: declarations,
item: declarationItem
};
prev.block.remove(prev.item);
// TODO: use it when we can refer to several points in source
// declaration.loc = {
// primary: declaration.loc,
// merged: prev.item.data.loc
// };
} else {
declarations.remove(declarationItem);
// TODO: use it when we can refer to several points in source
// prev.item.data.loc = {
// primary: prev.item.data.loc,
// merged: declaration.loc
// };
}
} else {
const prev = needless(props, declaration, fingerprints);
if (prev) {
declarations.remove(declarationItem);
// TODO: use it when we can refer to several points in source
// prev.item.data.loc = {
// primary: prev.item.data.loc,
// merged: declaration.loc
// };
} else {
declaration.fingerprint = fingerprint;
props[fingerprint] = {
block: declarations,
item: declarationItem
};
}
}
});
if (declarations.isEmpty) {
list.remove(item);
}
}
function restructBlock(ast) {
const stylesheetMap = {};
const fingerprints = Object.create(null);
cssTree.walk(ast, {
visit: 'Rule',
reverse: true,
enter(node, item, list) {
const stylesheet = this.block || this.stylesheet;
const ruleId = (node.pseudoSignature || '') + '|' + node.prelude.children.first.id;
let ruleMap;
let props;
if (!stylesheetMap.hasOwnProperty(stylesheet.id)) {
ruleMap = {};
stylesheetMap[stylesheet.id] = ruleMap;
} else {
ruleMap = stylesheetMap[stylesheet.id];
}
if (ruleMap.hasOwnProperty(ruleId)) {
props = ruleMap[ruleId];
} else {
props = {};
ruleMap[ruleId] = props;
}
processRule.call(this, node, item, list, props, fingerprints);
}
});
}
module.exports = restructBlock;

90
node_modules/csso/cjs/restructure/7-mergeRuleset.cjs generated vendored Executable file
View File

@@ -0,0 +1,90 @@
'use strict';
const cssTree = require('css-tree');
const utils = require('./utils.cjs');
/*
At this step all rules has single simple selector. We try to join by equal
declaration blocks to first rule, e.g.
.a { color: red }
b { ... }
.b { color: red }
->
.a, .b { color: red }
b { ... }
*/
function processRule(node, item, list) {
const selectors = node.prelude.children;
const declarations = node.block.children;
const nodeCompareMarker = selectors.first.compareMarker;
const skippedCompareMarkers = {};
list.nextUntil(item.next, function(next, nextItem) {
// skip non-ruleset node if safe
if (next.type !== 'Rule') {
return utils.unsafeToSkipNode.call(selectors, next);
}
if (node.pseudoSignature !== next.pseudoSignature) {
return true;
}
const nextFirstSelector = next.prelude.children.head;
const nextDeclarations = next.block.children;
const nextCompareMarker = nextFirstSelector.data.compareMarker;
// if next ruleset has same marked as one of skipped then stop joining
if (nextCompareMarker in skippedCompareMarkers) {
return true;
}
// try to join by selectors
if (selectors.head === selectors.tail) {
if (selectors.first.id === nextFirstSelector.data.id) {
declarations.appendList(nextDeclarations);
list.remove(nextItem);
return;
}
}
// try to join by properties
if (utils.isEqualDeclarations(declarations, nextDeclarations)) {
const nextStr = nextFirstSelector.data.id;
selectors.some((data, item) => {
const curStr = data.id;
if (nextStr < curStr) {
selectors.insert(nextFirstSelector, item);
return true;
}
if (!item.next) {
selectors.insert(nextFirstSelector);
return true;
}
});
list.remove(nextItem);
return;
}
// go to next ruleset if current one can be skipped (has no equal specificity nor element selector)
if (nextCompareMarker === nodeCompareMarker) {
return true;
}
skippedCompareMarkers[nextCompareMarker] = true;
});
}
function mergeRule(ast) {
cssTree.walk(ast, {
visit: 'Rule',
enter: processRule
});
}
module.exports = mergeRule;

175
node_modules/csso/cjs/restructure/8-restructRuleset.cjs generated vendored Executable file
View File

@@ -0,0 +1,175 @@
'use strict';
const cssTree = require('css-tree');
const utils = require('./utils.cjs');
function calcSelectorLength(list) {
return list.reduce((res, data) => res + data.id.length + 1, 0) - 1;
}
function calcDeclarationsLength(tokens) {
let length = 0;
for (const token of tokens) {
length += token.length;
}
return (
length + // declarations
tokens.length - 1 // delimeters
);
}
function processRule(node, item, list) {
const avoidRulesMerge = this.block !== null ? this.block.avoidRulesMerge : false;
const selectors = node.prelude.children;
const block = node.block;
const disallowDownMarkers = Object.create(null);
let allowMergeUp = true;
let allowMergeDown = true;
list.prevUntil(item.prev, function(prev, prevItem) {
const prevBlock = prev.block;
const prevType = prev.type;
if (prevType !== 'Rule') {
const unsafe = utils.unsafeToSkipNode.call(selectors, prev);
if (!unsafe && prevType === 'Atrule' && prevBlock) {
cssTree.walk(prevBlock, {
visit: 'Rule',
enter(node) {
node.prelude.children.forEach((data) => {
disallowDownMarkers[data.compareMarker] = true;
});
}
});
}
return unsafe;
}
if (node.pseudoSignature !== prev.pseudoSignature) {
return true;
}
const prevSelectors = prev.prelude.children;
allowMergeDown = !prevSelectors.some((selector) =>
selector.compareMarker in disallowDownMarkers
);
// try prev ruleset if simpleselectors has no equal specifity and element selector
if (!allowMergeDown && !allowMergeUp) {
return true;
}
// try to join by selectors
if (allowMergeUp && utils.isEqualSelectors(prevSelectors, selectors)) {
prevBlock.children.appendList(block.children);
list.remove(item);
return true;
}
// try to join by properties
const diff = utils.compareDeclarations(block.children, prevBlock.children);
// console.log(diff.eq, diff.ne1, diff.ne2);
if (diff.eq.length) {
if (!diff.ne1.length && !diff.ne2.length) {
// equal blocks
if (allowMergeDown) {
utils.addSelectors(selectors, prevSelectors);
list.remove(prevItem);
}
return true;
} else if (!avoidRulesMerge) { /* probably we don't need to prevent those merges for @keyframes
TODO: need to be checked */
if (diff.ne1.length && !diff.ne2.length) {
// prevBlock is subset block
const selectorLength = calcSelectorLength(selectors);
const blockLength = calcDeclarationsLength(diff.eq); // declarations length
if (allowMergeUp && selectorLength < blockLength) {
utils.addSelectors(prevSelectors, selectors);
block.children.fromArray(diff.ne1);
}
} else if (!diff.ne1.length && diff.ne2.length) {
// node is subset of prevBlock
const selectorLength = calcSelectorLength(prevSelectors);
const blockLength = calcDeclarationsLength(diff.eq); // declarations length
if (allowMergeDown && selectorLength < blockLength) {
utils.addSelectors(selectors, prevSelectors);
prevBlock.children.fromArray(diff.ne2);
}
} else {
// diff.ne1.length && diff.ne2.length
// extract equal block
const newSelector = {
type: 'SelectorList',
loc: null,
children: utils.addSelectors(prevSelectors.copy(), selectors)
};
const newBlockLength = calcSelectorLength(newSelector.children) + 2; // selectors length + curly braces length
const blockLength = calcDeclarationsLength(diff.eq); // declarations length
// create new ruleset if declarations length greater than
// ruleset description overhead
if (blockLength >= newBlockLength) {
const newItem = list.createItem({
type: 'Rule',
loc: null,
prelude: newSelector,
block: {
type: 'Block',
loc: null,
children: new cssTree.List().fromArray(diff.eq)
},
pseudoSignature: node.pseudoSignature
});
block.children.fromArray(diff.ne1);
prevBlock.children.fromArray(diff.ne2overrided);
if (allowMergeUp) {
list.insert(newItem, prevItem);
} else {
list.insert(newItem, item);
}
return true;
}
}
}
}
if (allowMergeUp) {
// TODO: disallow up merge only if any property interception only (i.e. diff.ne2overrided.length > 0);
// await property families to find property interception correctly
allowMergeUp = !prevSelectors.some((prevSelector) =>
selectors.some((selector) =>
selector.compareMarker === prevSelector.compareMarker
)
);
}
prevSelectors.forEach((data) => {
disallowDownMarkers[data.compareMarker] = true;
});
});
}
function restructRule(ast) {
cssTree.walk(ast, {
visit: 'Rule',
reverse: true,
enter: processRule
});
}
module.exports = restructRule;

39
node_modules/csso/cjs/restructure/index.cjs generated vendored Executable file
View File

@@ -0,0 +1,39 @@
'use strict';
const index = require('./prepare/index.cjs');
const _1MergeAtrule = require('./1-mergeAtrule.cjs');
const _2InitialMergeRuleset = require('./2-initialMergeRuleset.cjs');
const _3DisjoinRuleset = require('./3-disjoinRuleset.cjs');
const _4RestructShorthand = require('./4-restructShorthand.cjs');
const _6RestructBlock = require('./6-restructBlock.cjs');
const _7MergeRuleset = require('./7-mergeRuleset.cjs');
const _8RestructRuleset = require('./8-restructRuleset.cjs');
function restructure(ast, options) {
// prepare ast for restructing
const indexer = index(ast, options);
options.logger('prepare', ast);
_1MergeAtrule(ast, options);
options.logger('mergeAtrule', ast);
_2InitialMergeRuleset(ast);
options.logger('initialMergeRuleset', ast);
_3DisjoinRuleset(ast);
options.logger('disjoinRuleset', ast);
_4RestructShorthand(ast, indexer);
options.logger('restructShorthand', ast);
_6RestructBlock(ast);
options.logger('restructBlock', ast);
_7MergeRuleset(ast);
options.logger('mergeRuleset', ast);
_8RestructRuleset(ast);
options.logger('restructRuleset', ast);
}
module.exports = restructure;

View File

@@ -0,0 +1,34 @@
'use strict';
const cssTree = require('css-tree');
class Index {
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;
}
}
function createDeclarationIndexer() {
const ids = new Index();
return function markDeclaration(node) {
const id = cssTree.generate(node);
node.id = ids.resolve(id);
node.length = id.length;
node.fingerprint = null;
return node;
};
}
module.exports = createDeclarationIndexer;

45
node_modules/csso/cjs/restructure/prepare/index.cjs generated vendored Normal file
View File

@@ -0,0 +1,45 @@
'use strict';
const cssTree = require('css-tree');
const createDeclarationIndexer = require('./createDeclarationIndexer.cjs');
const processSelector = require('./processSelector.cjs');
function prepare(ast, options) {
const markDeclaration = createDeclarationIndexer();
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);
}
// 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;
});
});
}
}
});
return {
declaration: markDeclaration
};
}
module.exports = prepare;

View File

@@ -0,0 +1,101 @@
'use strict';
const cssTree = require('css-tree');
const specificity = require('./specificity.cjs');
const nonFreezePseudoElements = new Set([
'first-letter',
'first-line',
'after',
'before'
]);
const nonFreezePseudoClasses = new Set([
'link',
'visited',
'hover',
'active',
'first-letter',
'first-line',
'after',
'before'
]);
function processSelector(node, usageData) {
const pseudos = new Set();
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;
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;
}
});
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

@@ -0,0 +1,133 @@
'use strict';
const cssTree = require('css-tree');
function ensureSelectorList(node) {
if (node.type === 'Raw') {
return cssTree.parse(node.value, { context: 'selectorList' });
}
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;
}
}
return a;
}
function maxSelectorListSpecificity(selectorList) {
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;
// 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;
// ... 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;
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;
if (arg.type === 'Nth' && arg.selector) {
const [a, b, c] = maxSelectorListSpecificity(arg.selector);
A += a;
B += b + 1;
C += c;
} else {
B++;
}
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;
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;
}
});
return [A, B, C];
}
module.exports = specificity;

151
node_modules/csso/cjs/restructure/utils.cjs generated vendored Executable file
View File

@@ -0,0 +1,151 @@
'use strict';
const { hasOwnProperty } = Object.prototype;
function isEqualSelectors(a, b) {
let cursor1 = a.head;
let cursor2 = b.head;
while (cursor1 !== null && cursor2 !== null && cursor1.data.id === cursor2.data.id) {
cursor1 = cursor1.next;
cursor2 = cursor2.next;
}
return cursor1 === null && cursor2 === null;
}
function isEqualDeclarations(a, b) {
let cursor1 = a.head;
let cursor2 = b.head;
while (cursor1 !== null && cursor2 !== null && cursor1.data.id === cursor2.data.id) {
cursor1 = cursor1.next;
cursor2 = cursor2.next;
}
return cursor1 === null && cursor2 === null;
}
function compareDeclarations(declarations1, declarations2) {
const result = {
eq: [],
ne1: [],
ne2: [],
ne2overrided: []
};
const fingerprints = Object.create(null);
const declarations2hash = Object.create(null);
for (let cursor = declarations2.head; cursor; cursor = cursor.next) {
declarations2hash[cursor.data.id] = true;
}
for (let cursor = declarations1.head; cursor; cursor = cursor.next) {
const data = cursor.data;
if (data.fingerprint) {
fingerprints[data.fingerprint] = data.important;
}
if (declarations2hash[data.id]) {
declarations2hash[data.id] = false;
result.eq.push(data);
} else {
result.ne1.push(data);
}
}
for (let cursor = declarations2.head; cursor; cursor = cursor.next) {
const data = cursor.data;
if (declarations2hash[data.id]) {
// when declarations1 has an overriding declaration, this is not a difference
// unless no !important is used on prev and !important is used on the following
if (!hasOwnProperty.call(fingerprints, data.fingerprint) ||
(!fingerprints[data.fingerprint] && data.important)) {
result.ne2.push(data);
}
result.ne2overrided.push(data);
}
}
return result;
}
function addSelectors(dest, source) {
source.forEach((sourceData) => {
const newStr = sourceData.id;
let cursor = dest.head;
while (cursor) {
const nextStr = cursor.data.id;
if (nextStr === newStr) {
return;
}
if (nextStr > newStr) {
break;
}
cursor = cursor.next;
}
dest.insert(dest.createItem(sourceData), cursor);
});
return dest;
}
// check if simpleselectors has no equal specificity and element selector
function hasSimilarSelectors(selectors1, selectors2) {
let cursor1 = selectors1.head;
while (cursor1 !== null) {
let cursor2 = selectors2.head;
while (cursor2 !== null) {
if (cursor1.data.compareMarker === cursor2.data.compareMarker) {
return true;
}
cursor2 = cursor2.next;
}
cursor1 = cursor1.next;
}
return false;
}
// test node can't to be skipped
function unsafeToSkipNode(node) {
switch (node.type) {
case 'Rule':
// unsafe skip ruleset with selector similarities
return hasSimilarSelectors(node.prelude.children, this);
case 'Atrule':
// can skip at-rules with blocks
if (node.block) {
// unsafe skip at-rule if block contains something unsafe to skip
return node.block.children.some(unsafeToSkipNode, this);
}
break;
case 'Declaration':
return false;
}
// unsafe by default
return true;
}
exports.addSelectors = addSelectors;
exports.compareDeclarations = compareDeclarations;
exports.hasSimilarSelectors = hasSimilarSelectors;
exports.isEqualDeclarations = isEqualDeclarations;
exports.isEqualSelectors = isEqualSelectors;
exports.unsafeToSkipNode = unsafeToSkipNode;

60
node_modules/csso/cjs/syntax.cjs generated vendored Executable file
View File

@@ -0,0 +1,60 @@
'use strict';
const cssTree = require('css-tree');
const compress = require('./compress.cjs');
const specificity = require('./restructure/prepare/specificity.cjs');
function encodeString(value) {
const stringApostrophe = cssTree.string.encode(value, true);
const stringQuote = cssTree.string.encode(value);
return stringApostrophe.length < stringQuote.length
? stringApostrophe
: stringQuote;
}
const {
lexer,
tokenize,
parse,
generate,
walk,
find,
findLast,
findAll,
fromPlainObject,
toPlainObject
} = cssTree.fork({
node: {
String: {
generate(node) {
this.token(cssTree.tokenTypes.String, encodeString(node.value));
}
},
Url: {
generate(node) {
const encodedUrl = cssTree.url.encode(node.value);
const string = encodeString(node.value);
this.token(cssTree.tokenTypes.Url,
encodedUrl.length <= string.length + 5 /* "url()".length */
? encodedUrl
: 'url(' + string + ')'
);
}
}
}
});
exports.compress = compress;
exports.specificity = specificity;
exports.find = find;
exports.findAll = findAll;
exports.findLast = findLast;
exports.fromPlainObject = fromPlainObject;
exports.generate = generate;
exports.lexer = lexer;
exports.parse = parse;
exports.toPlainObject = toPlainObject;
exports.tokenize = tokenize;
exports.walk = walk;

75
node_modules/csso/cjs/usage.cjs generated vendored Executable file
View File

@@ -0,0 +1,75 @@
'use strict';
const { hasOwnProperty } = Object.prototype;
function buildMap(list, caseInsensitive) {
const map = Object.create(null);
if (!Array.isArray(list)) {
return null;
}
for (let name of list) {
if (caseInsensitive) {
name = name.toLowerCase();
}
map[name] = true;
}
return map;
}
function buildList(data) {
if (!data) {
return null;
}
const tags = buildMap(data.tags, true);
const ids = buildMap(data.ids);
const classes = buildMap(data.classes);
if (tags === null &&
ids === null &&
classes === null) {
return null;
}
return {
tags,
ids,
classes
};
}
function buildIndex(data) {
let scopes = false;
if (data.scopes && Array.isArray(data.scopes)) {
scopes = Object.create(null);
for (let i = 0; i < data.scopes.length; i++) {
const list = data.scopes[i];
if (!list || !Array.isArray(list)) {
throw new Error('Wrong usage format');
}
for (const name of list) {
if (hasOwnProperty.call(scopes, name)) {
throw new Error(`Class can't be used for several scopes: ${name}`);
}
scopes[name] = i + 1;
}
}
}
return {
whitelist: buildList(data),
blacklist: buildList(data.blacklist),
scopes
};
}
exports.buildIndex = buildIndex;

14
node_modules/csso/cjs/utils.cjs generated vendored Executable file
View File

@@ -0,0 +1,14 @@
'use strict';
const processSelector = require('./restructure/prepare/processSelector.cjs');
const utils$1 = require('./restructure/utils.cjs');
exports.processSelector = processSelector;
exports.addSelectors = utils$1.addSelectors;
exports.compareDeclarations = utils$1.compareDeclarations;
exports.hasSimilarSelectors = utils$1.hasSimilarSelectors;
exports.isEqualDeclarations = utils$1.isEqualDeclarations;
exports.isEqualSelectors = utils$1.isEqualSelectors;
exports.unsafeToSkipNode = utils$1.unsafeToSkipNode;

5
node_modules/csso/cjs/version.cjs generated vendored Executable file
View File

@@ -0,0 +1,5 @@
'use strict';
const { version } = require('../package.json');
exports.version = version;