aboutsummaryrefslogtreecommitdiff
path: root/node_modules/csso/lib/compressor/restructure/6-restructBlock.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/csso/lib/compressor/restructure/6-restructBlock.js')
-rw-r--r--node_modules/csso/lib/compressor/restructure/6-restructBlock.js261
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);
+ });
+};