diff options
| author | ruki <waruqi@gmail.com> | 2018-11-08 00:38:48 +0800 |
|---|---|---|
| committer | ruki <waruqi@gmail.com> | 2018-11-07 21:53:09 +0800 |
| commit | 26105034da4fcce7ac883c899d781f016559310d (patch) | |
| tree | c459a5dc4e3aa0972d9919033ece511ce76dd129 /node_modules/csso/lib/compressor/restructure/6-restructBlock.js | |
| parent | 2c77f00f1a7ecb6c8192f9c16d3b2001b254a107 (diff) | |
| download | xmake-docs-26105034da4fcce7ac883c899d781f016559310d.tar.gz xmake-docs-26105034da4fcce7ac883c899d781f016559310d.zip | |
switch to vuepress
Diffstat (limited to 'node_modules/csso/lib/compressor/restructure/6-restructBlock.js')
| -rw-r--r-- | node_modules/csso/lib/compressor/restructure/6-restructBlock.js | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/node_modules/csso/lib/compressor/restructure/6-restructBlock.js b/node_modules/csso/lib/compressor/restructure/6-restructBlock.js new file mode 100644 index 00000000..4933eed4 --- /dev/null +++ b/node_modules/csso/lib/compressor/restructure/6-restructBlock.js @@ -0,0 +1,261 @@ +var resolveProperty = require('../../utils/names.js').property; +var resolveKeyword = require('../../utils/names.js').keyword; +var walkRulesRight = require('../../utils/walk.js').rulesRight; +var translate = require('../../utils/translate.js'); +var dontRestructure = { + 'src': 1 // https://github.com/afelix/csso/issues/50 +}; + +var 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 +}; + +var CURSOR_SAFE_VALUE = [ + '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' +]; + +var 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) { + var realName = resolveProperty(propertyName).name; + + if (realName === 'background' || + (realName === 'filter' && declaration.value.sequence.first().type === 'Progid')) { + return propertyName + ':' + translate(declaration.value); + } + + var declarationId = declaration.id; + var fingerprint = fingerprints[declarationId]; + + if (!fingerprint) { + var vendorId = ''; + var iehack = ''; + var special = {}; + + declaration.value.sequence.each(function walk(node) { + switch (node.type) { + case 'Argument': + case 'Value': + case 'Braces': + node.sequence.each(walk); + break; + + case 'Identifier': + var name = node.name; + + if (!vendorId) { + vendorId = resolveKeyword(name).vendor; + } + + if (/\\[09]/.test(name)) { + iehack = RegExp.lastMatch; + } + + if (realName === 'cursor') { + if (CURSOR_SAFE_VALUE.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': + var name = node.name; + + if (!vendorId) { + vendorId = resolveKeyword(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 + if (node.arguments.size < 4) { + name = 'rect-backward'; + } + } + + special[name + '()'] = true; + + // check nested tokens too + node.arguments.each(walk); + + break; + + case 'Dimension': + var unit = node.unit; + + 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 = '|' + Object.keys(special).sort() + '|' + iehack + vendorId; + + fingerprints[declarationId] = fingerprint; + } + + return propertyName + fingerprint; +} + +function needless(props, declaration, fingerprints) { + var property = resolveProperty(declaration.property.name); + + if (NEEDLESS_TABLE.hasOwnProperty(property.name)) { + var table = NEEDLESS_TABLE[property.name]; + + for (var i = 0; i < table.length; i++) { + var ppre = getPropertyFingerprint(property.prefix + table[i], declaration, fingerprints); + var prev = props[ppre]; + + if (prev && (!declaration.value.important || prev.item.data.value.important)) { + return prev; + } + } + } +} + +function processRuleset(ruleset, item, list, props, fingerprints) { + var declarations = ruleset.block.declarations; + + declarations.eachRight(function(declaration, declarationItem) { + var property = declaration.property.name; + var fingerprint = getPropertyFingerprint(property, declaration, fingerprints); + var prev = props[fingerprint]; + + if (prev && !dontRestructure.hasOwnProperty(property)) { + if (declaration.value.important && !prev.item.data.value.important) { + props[fingerprint] = { + block: declarations, + item: declarationItem + }; + + prev.block.remove(prev.item); + declaration.info = { + primary: declaration.info, + merged: prev.item.data.info + }; + } else { + declarations.remove(declarationItem); + prev.item.data.info = { + primary: prev.item.data.info, + merged: declaration.info + }; + } + } else { + var prev = needless(props, declaration, fingerprints); + + if (prev) { + declarations.remove(declarationItem); + prev.item.data.info = { + primary: prev.item.data.info, + merged: declaration.info + }; + } else { + declaration.fingerprint = fingerprint; + + props[fingerprint] = { + block: declarations, + item: declarationItem + }; + } + } + }); + + if (declarations.isEmpty()) { + list.remove(item); + } +}; + +module.exports = function restructBlock(ast) { + var stylesheetMap = {}; + var fingerprints = Object.create(null); + + walkRulesRight(ast, function(node, item, list) { + if (node.type !== 'Ruleset') { + return; + } + + var stylesheet = this.stylesheet; + var rulesetId = (node.pseudoSignature || '') + '|' + node.selector.selectors.first().id; + var rulesetMap; + var props; + + if (!stylesheetMap.hasOwnProperty(stylesheet.id)) { + rulesetMap = {}; + stylesheetMap[stylesheet.id] = rulesetMap; + } else { + rulesetMap = stylesheetMap[stylesheet.id]; + } + + if (rulesetMap.hasOwnProperty(rulesetId)) { + props = rulesetMap[rulesetId]; + } else { + props = {}; + rulesetMap[rulesetId] = props; + } + + processRuleset.call(this, node, item, list, props, fingerprints); + }); +}; |
