diff options
Diffstat (limited to 'node_modules/csso/lib/replace')
| -rw-r--r-- | node_modules/csso/lib/replace/Atrule.js | 9 | ||||
| -rw-r--r-- | node_modules/csso/lib/replace/AttributeSelector.js | 28 | ||||
| -rw-r--r-- | node_modules/csso/lib/replace/Dimension.js | 63 | ||||
| -rw-r--r-- | node_modules/csso/lib/replace/Number.js | 40 | ||||
| -rw-r--r-- | node_modules/csso/lib/replace/Percentage.js | 37 | ||||
| -rw-r--r-- | node_modules/csso/lib/replace/Url.js | 4 | ||||
| -rw-r--r-- | node_modules/csso/lib/replace/Value.js | 26 | ||||
| -rw-r--r-- | node_modules/csso/lib/replace/atrule/keyframes.js | 21 | ||||
| -rw-r--r-- | node_modules/csso/lib/replace/color.js | 498 | ||||
| -rw-r--r-- | node_modules/csso/lib/replace/index.js | 32 | ||||
| -rw-r--r-- | node_modules/csso/lib/replace/property/background.js | 50 | ||||
| -rw-r--r-- | node_modules/csso/lib/replace/property/border.js | 16 | ||||
| -rw-r--r-- | node_modules/csso/lib/replace/property/font-weight.js | 22 | ||||
| -rw-r--r-- | node_modules/csso/lib/replace/property/font.js | 30 |
14 files changed, 876 insertions, 0 deletions
diff --git a/node_modules/csso/lib/replace/Atrule.js b/node_modules/csso/lib/replace/Atrule.js new file mode 100644 index 00000000..98f3248d --- /dev/null +++ b/node_modules/csso/lib/replace/Atrule.js @@ -0,0 +1,9 @@ +import { keyword as resolveKeyword } from 'css-tree'; +import compressKeyframes from './atrule/keyframes.js'; + +export default function(node) { + // compress @keyframe selectors + if (resolveKeyword(node.name).basename === 'keyframes') { + compressKeyframes(node); + } +}; diff --git a/node_modules/csso/lib/replace/AttributeSelector.js b/node_modules/csso/lib/replace/AttributeSelector.js new file mode 100644 index 00000000..3821530c --- /dev/null +++ b/node_modules/csso/lib/replace/AttributeSelector.js @@ -0,0 +1,28 @@ +// 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); +} + +export default function(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 + }; + } +}; diff --git a/node_modules/csso/lib/replace/Dimension.js b/node_modules/csso/lib/replace/Dimension.js new file mode 100644 index 00000000..edb00388 --- /dev/null +++ b/node_modules/csso/lib/replace/Dimension.js @@ -0,0 +1,63 @@ +import { packNumber } from './Number.js'; + +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' +]); + +export default function compressDimension(node, item) { + const value = 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 + }; + } +}; diff --git a/node_modules/csso/lib/replace/Number.js b/node_modules/csso/lib/replace/Number.js new file mode 100644 index 00000000..3420812d --- /dev/null +++ b/node_modules/csso/lib/replace/Number.js @@ -0,0 +1,40 @@ +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' +]); + +export 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; +} + +export function Number(node) { + node.value = packNumber(node.value); +}; diff --git a/node_modules/csso/lib/replace/Percentage.js b/node_modules/csso/lib/replace/Percentage.js new file mode 100644 index 00000000..4a2d70e8 --- /dev/null +++ b/node_modules/csso/lib/replace/Percentage.js @@ -0,0 +1,37 @@ +import { lexer } from 'css-tree'; +import { packNumber } from './Number.js'; + +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' +]); + +export default function compressPercentage(node, item) { + node.value = 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 (!lexer.matchDeclaration(this.declaration).isType(item.data, 'length')) { + // otherwise rollback changes + item.data = node; + } + } +}; diff --git a/node_modules/csso/lib/replace/Url.js b/node_modules/csso/lib/replace/Url.js new file mode 100644 index 00000000..00149218 --- /dev/null +++ b/node_modules/csso/lib/replace/Url.js @@ -0,0 +1,4 @@ +export default function(node) { + // convert `\\` to `/` + node.value = node.value.replace(/\\/g, '/'); +}; diff --git a/node_modules/csso/lib/replace/Value.js b/node_modules/csso/lib/replace/Value.js new file mode 100644 index 00000000..05d1d57b --- /dev/null +++ b/node_modules/csso/lib/replace/Value.js @@ -0,0 +1,26 @@ +import { property as resolveName } from 'css-tree'; +import font from './property/font.js'; +import fontWeight from './property/font-weight.js'; +import background from './property/background.js'; +import border from './property/border.js'; +import outline from './property/border.js'; + +const handlers = { + 'font': font, + 'font-weight': fontWeight, + 'background': background, + 'border': border, + 'outline': outline +}; + +export default function compressValue(node) { + if (!this.declaration) { + return; + } + + const property = resolveName(this.declaration.property); + + if (handlers.hasOwnProperty(property.basename)) { + handlers[property.basename](node); + } +}; diff --git a/node_modules/csso/lib/replace/atrule/keyframes.js b/node_modules/csso/lib/replace/atrule/keyframes.js new file mode 100644 index 00000000..62e6aef7 --- /dev/null +++ b/node_modules/csso/lib/replace/atrule/keyframes.js @@ -0,0 +1,21 @@ +export default function(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' + }; + } + }); + }); + }); +}; diff --git a/node_modules/csso/lib/replace/color.js b/node_modules/csso/lib/replace/color.js new file mode 100644 index 00000000..7f3db13d --- /dev/null +++ b/node_modules/csso/lib/replace/color.js @@ -0,0 +1,498 @@ +import { lexer } from 'css-tree'; +import { packNumber } from './Number.js'; + +// 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); + }); +} + +export 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: 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); + } +} + +export function compressIdent(node, item) { + if (this.declaration === null) { + return; + } + + let color = node.name.toLowerCase(); + + if (NAME_TO_HEX.hasOwnProperty(color) && + 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; + } + } +} + +export 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; + } +} diff --git a/node_modules/csso/lib/replace/index.js b/node_modules/csso/lib/replace/index.js new file mode 100644 index 00000000..de90ee46 --- /dev/null +++ b/node_modules/csso/lib/replace/index.js @@ -0,0 +1,32 @@ +import { walk } from 'css-tree'; +import Atrule from './Atrule.js'; +import AttributeSelector from './AttributeSelector.js'; +import Value from './Value.js'; +import Dimension from './Dimension.js'; +import Percentage from './Percentage.js'; +import { Number } from './Number.js'; +import Url from './Url.js'; +import { compressHex, compressIdent, compressFunction } from './color.js'; + +const handlers = { + Atrule, + AttributeSelector, + Value, + Dimension, + Percentage, + Number, + Url, + Hash: compressHex, + Identifier: compressIdent, + Function: compressFunction +}; + +export default function(ast) { + walk(ast, { + leave(node, item, list) { + if (handlers.hasOwnProperty(node.type)) { + handlers[node.type].call(this, node, item, list); + } + } + }); +}; diff --git a/node_modules/csso/lib/replace/property/background.js b/node_modules/csso/lib/replace/property/background.js new file mode 100644 index 00000000..847a8cff --- /dev/null +++ b/node_modules/csso/lib/replace/property/background.js @@ -0,0 +1,50 @@ +import { List } from 'css-tree'; + +export default 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 List().fromArray(newValue); +}; diff --git a/node_modules/csso/lib/replace/property/border.js b/node_modules/csso/lib/replace/property/border.js new file mode 100644 index 00000000..c470b66f --- /dev/null +++ b/node_modules/csso/lib/replace/property/border.js @@ -0,0 +1,16 @@ +export default 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); + } + } + }); +}; diff --git a/node_modules/csso/lib/replace/property/font-weight.js b/node_modules/csso/lib/replace/property/font-weight.js new file mode 100644 index 00000000..3b901d33 --- /dev/null +++ b/node_modules/csso/lib/replace/property/font-weight.js @@ -0,0 +1,22 @@ +export default 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; + } + } +}; diff --git a/node_modules/csso/lib/replace/property/font.js b/node_modules/csso/lib/replace/property/font.js new file mode 100644 index 00000000..38e903a2 --- /dev/null +++ b/node_modules/csso/lib/replace/property/font.js @@ -0,0 +1,30 @@ +export default 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' + })); + } +}; |
