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:
73
node_modules/csso/cjs/clean/Atrule.cjs
generated
vendored
Normal file
73
node_modules/csso/cjs/clean/Atrule.cjs
generated
vendored
Normal 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
7
node_modules/csso/cjs/clean/Comment.cjs
generated
vendored
Normal 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
18
node_modules/csso/cjs/clean/Declaration.cjs
generated
vendored
Normal 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
13
node_modules/csso/cjs/clean/Raw.cjs
generated
vendored
Normal 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
104
node_modules/csso/cjs/clean/Rule.cjs
generated
vendored
Normal 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
23
node_modules/csso/cjs/clean/TypeSelector.cjs
generated
vendored
Normal 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
7
node_modules/csso/cjs/clean/WhiteSpace.cjs
generated
vendored
Normal 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
32
node_modules/csso/cjs/clean/index.cjs
generated
vendored
Normal 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
12
node_modules/csso/cjs/clean/utils.cjs
generated
vendored
Normal 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
200
node_modules/csso/cjs/compress.cjs
generated
vendored
Executable 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
127
node_modules/csso/cjs/index.cjs
generated
vendored
Executable 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
13
node_modules/csso/cjs/replace/Atrule.cjs
generated
vendored
Normal 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
32
node_modules/csso/cjs/replace/AttributeSelector.cjs
generated
vendored
Normal 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
67
node_modules/csso/cjs/replace/Dimension.cjs
generated
vendored
Normal 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
45
node_modules/csso/cjs/replace/Number.cjs
generated
vendored
Normal 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
41
node_modules/csso/cjs/replace/Percentage.cjs
generated
vendored
Normal 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: Don’t 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
8
node_modules/csso/cjs/replace/Url.cjs
generated
vendored
Normal 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
29
node_modules/csso/cjs/replace/Value.cjs
generated
vendored
Normal 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
25
node_modules/csso/cjs/replace/atrule/keyframes.cjs
generated
vendored
Normal 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
504
node_modules/csso/cjs/replace/color.cjs
generated
vendored
Normal 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
36
node_modules/csso/cjs/replace/index.cjs
generated
vendored
Normal 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
54
node_modules/csso/cjs/replace/property/background.cjs
generated
vendored
Normal 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
20
node_modules/csso/cjs/replace/property/border.cjs
generated
vendored
Normal 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
26
node_modules/csso/cjs/replace/property/font-weight.cjs
generated
vendored
Normal 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
34
node_modules/csso/cjs/replace/property/font.cjs
generated
vendored
Normal 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
109
node_modules/csso/cjs/restructure/1-mergeAtrule.cjs
generated
vendored
Executable 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
51
node_modules/csso/cjs/restructure/2-initialMergeRuleset.cjs
generated
vendored
Executable 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
46
node_modules/csso/cjs/restructure/3-disjoinRuleset.cjs
generated
vendored
Executable 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
429
node_modules/csso/cjs/restructure/4-restructShorthand.cjs
generated
vendored
Executable 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
307
node_modules/csso/cjs/restructure/6-restructBlock.cjs
generated
vendored
Executable 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
90
node_modules/csso/cjs/restructure/7-mergeRuleset.cjs
generated
vendored
Executable 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
175
node_modules/csso/cjs/restructure/8-restructRuleset.cjs
generated
vendored
Executable 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
39
node_modules/csso/cjs/restructure/index.cjs
generated
vendored
Executable 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;
|
||||
34
node_modules/csso/cjs/restructure/prepare/createDeclarationIndexer.cjs
generated
vendored
Normal file
34
node_modules/csso/cjs/restructure/prepare/createDeclarationIndexer.cjs
generated
vendored
Normal 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
45
node_modules/csso/cjs/restructure/prepare/index.cjs
generated
vendored
Normal 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;
|
||||
101
node_modules/csso/cjs/restructure/prepare/processSelector.cjs
generated
vendored
Normal file
101
node_modules/csso/cjs/restructure/prepare/processSelector.cjs
generated
vendored
Normal 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;
|
||||
133
node_modules/csso/cjs/restructure/prepare/specificity.cjs
generated
vendored
Normal file
133
node_modules/csso/cjs/restructure/prepare/specificity.cjs
generated
vendored
Normal 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 selector’s specificity
|
||||
// https://www.w3.org/TR/selectors-4/#specificity-rules
|
||||
function specificity(simpleSelector) {
|
||||
let A = 0;
|
||||
let B = 0;
|
||||
let C = 0;
|
||||
|
||||
// A selector’s 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
151
node_modules/csso/cjs/restructure/utils.cjs
generated
vendored
Executable 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
60
node_modules/csso/cjs/syntax.cjs
generated
vendored
Executable 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
75
node_modules/csso/cjs/usage.cjs
generated
vendored
Executable 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
14
node_modules/csso/cjs/utils.cjs
generated
vendored
Executable 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
5
node_modules/csso/cjs/version.cjs
generated
vendored
Executable file
@@ -0,0 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
const { version } = require('../package.json');
|
||||
|
||||
exports.version = version;
|
||||
Reference in New Issue
Block a user