diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2024-08-30 17:21:18 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2024-08-30 17:21:18 +0800 |
| commit | efbc2ffe6a1ee5ec38a4396305561d6515d0943e (patch) | |
| tree | 2b4c94f18f2c792dfda813050755d5c0273fae22 /node_modules/clean-css/lib/optimizer/level-1/optimize.js | |
| parent | 43acceb75957c880a5ba5a31aae221394a36d5f6 (diff) | |
node fixes, updates
Diffstat (limited to 'node_modules/clean-css/lib/optimizer/level-1/optimize.js')
| -rw-r--r-- | node_modules/clean-css/lib/optimizer/level-1/optimize.js | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/node_modules/clean-css/lib/optimizer/level-1/optimize.js b/node_modules/clean-css/lib/optimizer/level-1/optimize.js new file mode 100644 index 00000000..d0461e06 --- /dev/null +++ b/node_modules/clean-css/lib/optimizer/level-1/optimize.js @@ -0,0 +1,325 @@ +var sortSelectors = require('./sort-selectors'); +var tidyRules = require('./tidy-rules'); +var tidyBlock = require('./tidy-block'); +var tidyAtRule = require('./tidy-at-rule'); + +var Hack = require('../hack'); +var removeUnused = require('../remove-unused'); +var restoreFromOptimizing = require('../restore-from-optimizing'); +var wrapForOptimizing = require('../wrap-for-optimizing').all; + +var configuration = require('../configuration'); +var optimizers = require('./value-optimizers'); + +var OptimizationLevel = require('../../options/optimization-level').OptimizationLevel; + +var Token = require('../../tokenizer/token'); +var Marker = require('../../tokenizer/marker'); + +var formatPosition = require('../../utils/format-position'); + +var serializeRules = require('../../writer/one-time').rules; + +var CHARSET_TOKEN = '@charset'; +var CHARSET_REGEXP = new RegExp('^' + CHARSET_TOKEN, 'i'); + +var DEFAULT_ROUNDING_PRECISION = require('../../options/rounding-precision').DEFAULT; + +var VARIABLE_PROPERTY_NAME_PATTERN = /^--\S+$/; +var PROPERTY_NAME_PATTERN = /^(?:-chrome-|-[\w-]+\w|\w[\w-]+\w|\w{1,})$/; +var IMPORT_PREFIX_PATTERN = /^@import/i; +var URL_PREFIX_PATTERN = /^url\(/i; + +function startsAsUrl(value) { + return URL_PREFIX_PATTERN.test(value); +} + +function isImport(token) { + return IMPORT_PREFIX_PATTERN.test(token[1]); +} + +function isLegacyFilter(property) { + var value; + + if (property.name == 'filter' || property.name == '-ms-filter') { + value = property.value[0][1]; + + return value.indexOf('progid') > -1 + || value.indexOf('alpha') === 0 + || value.indexOf('chroma') === 0; + } + return false; +} + +function noop() {} + +function noopValueOptimizer(_name, value, _options) { return value; } + +function optimizeBody(rule, properties, context) { + var options = context.options; + var valueOptimizers; + var property, name, type, value; + var propertyToken; + var propertyOptimizer; + var serializedRule = serializeRules(rule); + var _properties = wrapForOptimizing(properties); + var pluginValueOptimizers = context.options.plugins.level1Value; + var pluginPropertyOptimizers = context.options.plugins.level1Property; + var isVariable; + var i, l; + + for (i = 0, l = _properties.length; i < l; i++) { + var j, k, m, n; + + property = _properties[i]; + name = property.name; + propertyOptimizer = configuration[name] && configuration[name].propertyOptimizer || noop; + valueOptimizers = configuration[name] && configuration[name].valueOptimizers || [optimizers.whiteSpace]; + isVariable = VARIABLE_PROPERTY_NAME_PATTERN.test(name); + + if (isVariable) { + valueOptimizers = options.variableOptimizers.length > 0 + ? options.variableOptimizers + : [optimizers.whiteSpace]; + } + + if (!isVariable && !PROPERTY_NAME_PATTERN.test(name)) { + propertyToken = property.all[property.position]; + context.warnings.push('Invalid property name \'' + name + '\' at ' + formatPosition(propertyToken[1][2][0]) + '. Ignoring.'); + property.unused = true; + continue; + } + + if (property.value.length === 0) { + propertyToken = property.all[property.position]; + context.warnings.push('Empty property \'' + name + '\' at ' + formatPosition(propertyToken[1][2][0]) + '. Ignoring.'); + property.unused = true; + continue; + } + + if (property.hack && ( + (property.hack[0] == Hack.ASTERISK || property.hack[0] == Hack.UNDERSCORE) + && !options.compatibility.properties.iePrefixHack + || property.hack[0] == Hack.BACKSLASH && !options.compatibility.properties.ieSuffixHack + || property.hack[0] == Hack.BANG && !options.compatibility.properties.ieBangHack)) { + property.unused = true; + continue; + } + + if (!options.compatibility.properties.ieFilters && isLegacyFilter(property)) { + property.unused = true; + continue; + } + + if (property.block) { + optimizeBody(rule, property.value[0][1], context); + continue; + } + + for (j = 0, m = property.value.length; j < m; j++) { + type = property.value[j][0]; + value = property.value[j][1]; + + if (type == Token.PROPERTY_BLOCK) { + property.unused = true; + context.warnings.push('Invalid value token at ' + formatPosition(value[0][1][2][0]) + '. Ignoring.'); + break; + } + + if (startsAsUrl(value) && !context.validator.isUrl(value)) { + property.unused = true; + context.warnings.push('Broken URL \'' + value + '\' at ' + formatPosition(property.value[j][2][0]) + '. Ignoring.'); + break; + } + + for (k = 0, n = valueOptimizers.length; k < n; k++) { + value = valueOptimizers[k](name, value, options); + } + + for (k = 0, n = pluginValueOptimizers.length; k < n; k++) { + value = pluginValueOptimizers[k](name, value, options); + } + + property.value[j][1] = value; + } + + propertyOptimizer(serializedRule, property, options); + + for (j = 0, m = pluginPropertyOptimizers.length; j < m; j++) { + pluginPropertyOptimizers[j](serializedRule, property, options); + } + } + + restoreFromOptimizing(_properties); + removeUnused(_properties); + removeComments(properties, options); +} + +function removeComments(tokens, options) { + var token; + var i; + + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + + if (token[0] != Token.COMMENT) { + continue; + } + + optimizeComment(token, options); + + if (token[1].length === 0) { + tokens.splice(i, 1); + i--; + } + } +} + +function optimizeComment(token, options) { + if (token[1][2] == Marker.EXCLAMATION && (options.level[OptimizationLevel.One].specialComments == 'all' || options.commentsKept < options.level[OptimizationLevel.One].specialComments)) { + options.commentsKept++; + return; + } + + token[1] = []; +} + +function cleanupCharsets(tokens) { + var hasCharset = false; + + for (var i = 0, l = tokens.length; i < l; i++) { + var token = tokens[i]; + + if (token[0] != Token.AT_RULE) { continue; } + + if (!CHARSET_REGEXP.test(token[1])) { continue; } + + if (hasCharset || token[1].indexOf(CHARSET_TOKEN) == -1) { + tokens.splice(i, 1); + i--; + l--; + } else { + hasCharset = true; + tokens.splice(i, 1); + tokens.unshift([Token.AT_RULE, token[1].replace(CHARSET_REGEXP, CHARSET_TOKEN)]); + } + } +} + +function buildUnitRegexp(options) { + var units = ['px', 'em', 'ex', 'cm', 'mm', 'in', 'pt', 'pc', '%']; + var otherUnits = ['ch', 'rem', 'vh', 'vm', 'vmax', 'vmin', 'vw']; + + otherUnits.forEach(function(unit) { + if (options.compatibility.units[unit]) { + units.push(unit); + } + }); + + return new RegExp('(^|\\s|\\(|,)0(?:' + units.join('|') + ')(\\W|$)', 'g'); +} + +function buildPrecisionOptions(roundingPrecision) { + var precisionOptions = { + matcher: null, + units: {} + }; + var optimizable = []; + var unit; + var value; + + for (unit in roundingPrecision) { + value = roundingPrecision[unit]; + + if (value != DEFAULT_ROUNDING_PRECISION) { + precisionOptions.units[unit] = {}; + precisionOptions.units[unit].value = value; + precisionOptions.units[unit].multiplier = 10 ** value; + + optimizable.push(unit); + } + } + + if (optimizable.length > 0) { + precisionOptions.enabled = true; + precisionOptions.decimalPointMatcher = new RegExp('(\\d)\\.($|' + optimizable.join('|') + ')($|\\W)', 'g'); + precisionOptions.zeroMatcher = new RegExp('(\\d*)(\\.\\d+)(' + optimizable.join('|') + ')', 'g'); + } + + return precisionOptions; +} + +function buildVariableOptimizers(options) { + return options.level[OptimizationLevel.One].variableValueOptimizers.map(function(optimizer) { + if (typeof (optimizer) == 'string') { + return optimizers[optimizer] || noopValueOptimizer; + } + + return optimizer; + }); +} + +function level1Optimize(tokens, context) { + var options = context.options; + var levelOptions = options.level[OptimizationLevel.One]; + var ie7Hack = options.compatibility.selectors.ie7Hack; + var adjacentSpace = options.compatibility.selectors.adjacentSpace; + var spaceAfterClosingBrace = options.compatibility.properties.spaceAfterClosingBrace; + var format = options.format; + var mayHaveCharset = false; + var afterRules = false; + + options.unitsRegexp = options.unitsRegexp || buildUnitRegexp(options); + options.precision = options.precision || buildPrecisionOptions(levelOptions.roundingPrecision); + options.commentsKept = options.commentsKept || 0; + options.variableOptimizers = options.variableOptimizers || buildVariableOptimizers(options); + + for (var i = 0, l = tokens.length; i < l; i++) { + var token = tokens[i]; + + switch (token[0]) { + case Token.AT_RULE: + token[1] = isImport(token) && afterRules ? '' : token[1]; + token[1] = levelOptions.tidyAtRules ? tidyAtRule(token[1]) : token[1]; + mayHaveCharset = true; + break; + case Token.AT_RULE_BLOCK: + optimizeBody(token[1], token[2], context); + afterRules = true; + break; + case Token.NESTED_BLOCK: + token[1] = levelOptions.tidyBlockScopes ? tidyBlock(token[1], spaceAfterClosingBrace) : token[1]; + level1Optimize(token[2], context); + afterRules = true; + break; + case Token.COMMENT: + optimizeComment(token, options); + break; + case Token.RULE: + token[1] = levelOptions.tidySelectors + ? tidyRules(token[1], !ie7Hack, adjacentSpace, format, context.warnings) + : token[1]; + token[1] = token[1].length > 1 ? sortSelectors(token[1], levelOptions.selectorsSortingMethod) : token[1]; + optimizeBody(token[1], token[2], context); + afterRules = true; + break; + } + + if (token[0] == Token.COMMENT + && token[1].length === 0 + || levelOptions.removeEmpty + && (token[1].length === 0 || (token[2] && token[2].length === 0))) { + tokens.splice(i, 1); + i--; + l--; + } + } + + if (levelOptions.cleanupCharsets && mayHaveCharset) { + cleanupCharsets(tokens); + } + + return tokens; +} + +module.exports = level1Optimize; |
