diff --git a/.editorconfig b/.editorconfig index 4e3f2a619..afb1408a1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,5 +8,8 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true +[*.js] +indent_size = 4 + [*.css] indent_size = 4 diff --git a/data/prefixes.js b/data/prefixes.js index a89749f7a..c65dedd05 100644 --- a/data/prefixes.js +++ b/data/prefixes.js @@ -1,31 +1,22 @@ +/* eslint-disable max-len */ + const unpackFeature = require('caniuse-lite').feature; -// Sort browsers -const sort = array => - array.sort((a, b) => { +const browsersSort = (a, b) => { a = a.split(' '); b = b.split(' '); if (a[0] > b[0]) { return 1; } else if (a[0] < b[0]) { return -1; - } else { - const d = parseFloat(a[1]) - parseFloat(b[1]); - if (d > 0) { - return 1; - } else if (d < 0) { - return -1; - } else { - return 0; } - } - }) -; + return Math.sign(parseFloat(a[1]) - parseFloat(b[1])); +}; // Convert Can I Use data const feature = function (data, opts, callback) { if (!callback) { - [callback, opts] = Array.from([opts, { }]); + [callback, opts] = [opts, {}]; } const match = opts.match || /\sx($|\s)/; @@ -41,128 +32,124 @@ const feature = function (data, opts, callback) { } } - return callback(sort(need)); + callback(need.sort(browsersSort)); }; // Add data for all properties -const result = { }; - -const prefix = function (...args) { - const names = args.slice(0, args.length - 1), data = args[args.length - 1]; - return names.map((name) => - (result[name] = { }, - (() => { - const result1 = []; - for (let i in data) { - result1.push(result[name][i] = data[i]); +const result = {}; + +const prefix = function (names, data) { + for (const name of names) { + result[name] = Object.assign({}, data); } - return result1; - })())); }; -const add = function (...args) { - const names = args.slice(0, args.length - 1), data = args[args.length - 1]; - return names.map((name) => - result[name].browsers = sort(result[name].browsers.concat(data.browsers))); +const add = function (names, data) { + for (const name of names) { + result[name].browsers = result[name].browsers + .concat(data.browsers) + .sort(browsersSort); + } }; module.exports = result; // Border Radius feature(unpackFeature(require('caniuse-lite/data/features/border-radius.js')), browsers => - prefix('border-radius', 'border-top-left-radius', 'border-top-right-radius', - 'border-bottom-right-radius', 'border-bottom-left-radius', { + prefix([ + 'border-radius', 'border-top-left-radius', 'border-top-right-radius', + 'border-bottom-right-radius', 'border-bottom-left-radius' + ], { mistakes: ['-khtml-', '-ms-', '-o-'], browsers, feature: 'border-radius' - } - ) + }) ); // Box Shadow feature(unpackFeature(require('caniuse-lite/data/features/css-boxshadow.js')), browsers => - prefix('box-shadow', { + prefix(['box-shadow'], { mistakes: ['-khtml-'], browsers, feature: 'css-boxshadow' - } - ) + }) ); // Animation feature(unpackFeature(require('caniuse-lite/data/features/css-animation.js')), browsers => - prefix('animation', 'animation-name', 'animation-duration', + prefix([ + 'animation', 'animation-name', 'animation-duration', 'animation-delay', 'animation-direction', 'animation-fill-mode', 'animation-iteration-count', 'animation-play-state', - 'animation-timing-function', '@keyframes', { + 'animation-timing-function', '@keyframes' + ], { mistakes: ['-khtml-', '-ms-'], browsers, feature: 'css-animation' - } - ) + }) ); // Transition feature(unpackFeature(require('caniuse-lite/data/features/css-transitions.js')), browsers => - prefix('transition', 'transition-property', 'transition-duration', - 'transition-delay', 'transition-timing-function', { + prefix([ + 'transition', 'transition-property', 'transition-duration', + 'transition-delay', 'transition-timing-function' + ], { mistakes: ['-khtml-', '-ms-'], browsers, feature: 'css-transitions' - } - ) + }) ); // Transform 2D feature(unpackFeature(require('caniuse-lite/data/features/transforms2d.js')), browsers => - prefix('transform', 'transform-origin', { + prefix(['transform', 'transform-origin'], { browsers, feature: 'transforms2d' - } - ) + }) ); // Transform 3D const transforms3d = unpackFeature(require('caniuse-lite/data/features/transforms3d.js')); feature(transforms3d, (browsers) => { - prefix('perspective', 'perspective-origin', { + prefix(['perspective', 'perspective-origin'], { browsers, feature: 'transforms3d' - } - ); - return prefix('transform-style', { + }); + return prefix(['transform-style'], { mistakes: ['-ms-', '-o-'], browsers, feature: 'transforms3d' - } - ); + }); }); feature(transforms3d, { match: /y\sx|y\s#2/ }, browsers => - prefix('backface-visibility', { + prefix(['backface-visibility'], { mistakes: ['-ms-', '-o-'], browsers, feature: 'transforms3d' - } - ) + }) ); // Gradients const gradients = unpackFeature(require('caniuse-lite/data/features/css-gradients.js')); feature(gradients, { match: /y\sx/ }, browsers => - prefix('linear-gradient', 'repeating-linear-gradient', - 'radial-gradient', 'repeating-radial-gradient', { - props: ['background', 'background-image', 'border-image', 'mask', - 'list-style', 'list-style-image', 'content', 'mask-image'], + prefix([ + 'linear-gradient', 'repeating-linear-gradient', + 'radial-gradient', 'repeating-radial-gradient' + ], { + props: [ + 'background', 'background-image', 'border-image', 'mask', + 'list-style', 'list-style-image', 'content', 'mask-image' + ], mistakes: ['-ms-'], browsers, feature: 'css-gradients' - } - ) + }) ); -feature(gradients, { match: /a\sx/ }, (browsers) => { +feature(gradients, { match: /a\sx/ }, browsers => { browsers = browsers.map((i) => { if (/op/.test(i)) { return i; @@ -170,102 +157,103 @@ feature(gradients, { match: /a\sx/ }, (browsers) => { return `${i} old`; } }); - return add('linear-gradient', 'repeating-linear-gradient', - 'radial-gradient', 'repeating-radial-gradient', { + return add([ + 'linear-gradient', 'repeating-linear-gradient', + 'radial-gradient', 'repeating-radial-gradient' + ], { browsers, feature: 'css-gradients' - } - ); + }); }); // Box sizing feature(unpackFeature(require('caniuse-lite/data/features/css3-boxsizing.js')), browsers => - prefix('box-sizing', { + prefix(['box-sizing'], { browsers, feature: 'css3-boxsizing' - } - ) + }) ); // Filter Effects feature(unpackFeature(require('caniuse-lite/data/features/css-filters.js')), browsers => - prefix('filter', { + prefix(['filter'], { browsers, feature: 'css-filters' - } - ) + }) ); // filter() function const filterFunction = unpackFeature(require('caniuse-lite/data/features/css-filter-function.js')); feature(filterFunction, browsers => - prefix('filter-function', { - props: ['background', 'background-image', 'border-image', 'mask', - 'list-style', 'list-style-image', 'content', 'mask-image'], + prefix(['filter-function'], { + props: [ + 'background', 'background-image', 'border-image', 'mask', + 'list-style', 'list-style-image', 'content', 'mask-image' + ], browsers, feature: 'css-filter-function' - } - ) + }) ); // Backdrop-filter const backdropFilter = unpackFeature(require('caniuse-lite/data/features/css-backdrop-filter.js')); feature(backdropFilter, browsers => - prefix('backdrop-filter', { + prefix(['backdrop-filter'], { browsers, feature: 'css-backdrop-filter' - } - ) + }) ); // element() function const elementFunction = unpackFeature(require('caniuse-lite/data/features/css-element-function.js')); feature(elementFunction, browsers => - prefix('element', { - props: ['background', 'background-image', 'border-image', 'mask', - 'list-style', 'list-style-image', 'content', 'mask-image'], + prefix(['element'], { + props: [ + 'background', 'background-image', 'border-image', 'mask', + 'list-style', 'list-style-image', 'content', 'mask-image' + ], browsers, feature: 'css-element-function' - } - ) + }) ); // Multicolumns feature(unpackFeature(require('caniuse-lite/data/features/multicolumn.js')), (browsers) => { - prefix('columns', 'column-width', 'column-gap', - 'column-rule', 'column-rule-color', 'column-rule-width', { + prefix([ + 'columns', 'column-width', 'column-gap', + 'column-rule', 'column-rule-color', 'column-rule-width' + ], { browsers, feature: 'multicolumn' - } - ); + }); - return prefix('column-count', 'column-rule-style', 'column-span', 'column-fill', - 'break-before', 'break-after', 'break-inside', { + return prefix([ + 'column-count', 'column-rule-style', 'column-span', 'column-fill', + 'break-before', 'break-after', 'break-inside' + ], { browsers, feature: 'multicolumn' - } - ); + }); }); // User select const userSelectNone = unpackFeature(require('caniuse-lite/data/features/user-select-none.js')); feature(userSelectNone, browsers => - prefix('user-select', { + prefix(['user-select'], { mistakes: ['-khtml-'], browsers, feature: 'user-select-none' - } - ) + }) ); // Flexible Box Layout const flexbox = unpackFeature(require('caniuse-lite/data/features/flexbox.js')); -feature(flexbox, { match: /a\sx/ }, (browsers) => { +feature(flexbox, { match: /a\sx/ }, browsers => { browsers = browsers.map((i) => { if (/ie|firefox/.test(i)) { return i; @@ -273,107 +261,101 @@ feature(flexbox, { match: /a\sx/ }, (browsers) => { return `${i} 2009`; } }); - prefix('display-flex', 'inline-flex', { + prefix(['display-flex', 'inline-flex'], { props: ['display'], browsers, feature: 'flexbox' - } - ); - prefix('flex', 'flex-grow', 'flex-shrink', 'flex-basis', { + }); + prefix(['flex', 'flex-grow', 'flex-shrink', 'flex-basis'], { browsers, feature: 'flexbox' - } - ); - return prefix('flex-direction', 'flex-wrap', 'flex-flow', 'justify-content', - 'order', 'align-items', 'align-self', 'align-content', { + }); + prefix([ + 'flex-direction', 'flex-wrap', 'flex-flow', 'justify-content', + 'order', 'align-items', 'align-self', 'align-content' + ], { browsers, feature: 'flexbox' - } - ); + }); }); -feature(flexbox, { match: /y\sx/ }, (browsers) => { - add('display-flex', 'inline-flex', { +feature(flexbox, { match: /y\sx/ }, browsers => { + add(['display-flex', 'inline-flex'], { browsers, feature: 'flexbox' - } - ); - add('flex', 'flex-grow', 'flex-shrink', 'flex-basis', { + }); + add(['flex', 'flex-grow', 'flex-shrink', 'flex-basis'], { browsers, feature: 'flexbox' - } - ); - return add('flex-direction', 'flex-wrap', 'flex-flow', 'justify-content', - 'order', 'align-items', 'align-self', 'align-content', { + }); + add([ + 'flex-direction', 'flex-wrap', 'flex-flow', 'justify-content', + 'order', 'align-items', 'align-self', 'align-content' + ], { browsers, feature: 'flexbox' - } - ); + }); }); // calc() unit feature(unpackFeature(require('caniuse-lite/data/features/calc.js')), browsers => - prefix('calc', { + prefix(['calc'], { props: ['*'], browsers, feature: 'calc' - } - ) + }) ); // Background options const bckgrndImgOpts = unpackFeature(require('caniuse-lite/data/features/background-img-opts.js')); feature(bckgrndImgOpts, browsers => - prefix('background-clip', 'background-origin', 'background-size', { + prefix(['background-clip', 'background-origin', 'background-size'], { browsers, feature: 'background-img-opts' - } - ) + }) ); // Font feature settings feature(unpackFeature(require('caniuse-lite/data/features/font-feature.js')), browsers => - prefix('font-feature-settings', 'font-variant-ligatures', - 'font-language-override', { + prefix([ + 'font-feature-settings', 'font-variant-ligatures', + 'font-language-override' + ], { browsers, feature: 'font-feature' - } - ) + }) ); // CSS font-kerning property feature(unpackFeature(require('caniuse-lite/data/features/font-kerning.js')), browsers => - prefix('font-kerning', { + prefix(['font-kerning'], { browsers, feature: 'font-kerning' - } - ) + }) ); // Border image feature(unpackFeature(require('caniuse-lite/data/features/border-image.js')), browsers => - prefix('border-image', { + prefix(['border-image'], { browsers, feature: 'border-image' - } - ) + }) ); // Selection selector feature(unpackFeature(require('caniuse-lite/data/features/css-selection.js')), browsers => - prefix('::selection', { + prefix(['::selection'], { selector: true, browsers, feature: 'css-selection' - } - ) + }) ); // Placeholder selector feature(unpackFeature(require('caniuse-lite/data/features/css-placeholder.js')), (browsers) => { browsers = browsers.map((i) => { - const [name, version] = Array.from(i.split(' ')); + const [name, version] = i.split(' '); if (name === 'firefox' && parseFloat(version) <= 18) { return i + ' old'; } else { @@ -381,412 +363,399 @@ feature(unpackFeature(require('caniuse-lite/data/features/css-placeholder.js')), } }); - return prefix('::placeholder', { + return prefix(['::placeholder'], { selector: true, browsers, feature: 'css-placeholder' - } - ); + }); }); // Hyphenation feature(unpackFeature(require('caniuse-lite/data/features/css-hyphens.js')), browsers => - prefix('hyphens', { + prefix(['hyphens'], { browsers, feature: 'css-hyphens' - } - ) + }) ); // Fullscreen selector const fullscreen = unpackFeature(require('caniuse-lite/data/features/fullscreen.js')); feature(fullscreen, browsers => - prefix(':fullscreen', { + prefix([':fullscreen'], { selector: true, browsers, feature: 'fullscreen' - } - ) + }) ); feature(fullscreen, { match: /x(\s#2|$)/ }, browsers => - prefix('::backdrop', { + prefix(['::backdrop'], { selector: true, browsers, feature: 'fullscreen' - } - ) + }) ); // Tab size feature(unpackFeature(require('caniuse-lite/data/features/css3-tabsize.js')), browsers => - prefix('tab-size', { + prefix(['tab-size'], { browsers, feature: 'css3-tabsize' - } - ) + }) ); // Intrinsic & extrinsic sizing feature(unpackFeature(require('caniuse-lite/data/features/intrinsic-width.js')), browsers => - prefix('max-content', 'min-content', 'fit-content', - 'fill', 'fill-available', 'stretch', { - props: ['width', 'min-width', 'max-width', + prefix([ + 'max-content', 'min-content', 'fit-content', + 'fill', 'fill-available', 'stretch' + ], { + props: [ + 'width', 'min-width', 'max-width', 'height', 'min-height', 'max-height', 'inline-size', 'min-inline-size', 'max-inline-size', - 'block-size', 'min-block-size', 'max-block-size'], + 'block-size', 'min-block-size', 'max-block-size' + ], browsers, feature: 'intrinsic-width' - } - ) + }) ); // Zoom cursors const cursorsNewer = unpackFeature(require('caniuse-lite/data/features/css3-cursors-newer.js')); feature(cursorsNewer, browsers => - prefix('zoom-in', 'zoom-out', { + prefix(['zoom-in', 'zoom-out'], { props: ['cursor'], browsers, feature: 'css3-cursors-newer' - } - ) + }) ); // Grab cursors const cursorsGrab = unpackFeature(require('caniuse-lite/data/features/css3-cursors-grab.js')); feature(cursorsGrab, browsers => - prefix('grab', 'grabbing', { + prefix(['grab', 'grabbing'], { props: ['cursor'], browsers, feature: 'css3-cursors-grab' - } - ) + }) ); // Sticky position feature(unpackFeature(require('caniuse-lite/data/features/css-sticky.js')), browsers => - prefix('sticky', { + prefix(['sticky'], { props: ['position'], browsers, feature: 'css-sticky' - } - ) + }) ); // Pointer Events feature(unpackFeature(require('caniuse-lite/data/features/pointer.js')), browsers => - prefix('touch-action', { + prefix(['touch-action'], { browsers, feature: 'pointer' - } - ) + }) ); // Text decoration const decoration = unpackFeature(require('caniuse-lite/data/features/text-decoration.js')); feature(decoration, browsers => - prefix('text-decoration-style', + prefix([ + 'text-decoration-style', 'text-decoration-color', - 'text-decoration-line', { + 'text-decoration-line' + ], { browsers, feature: 'text-decoration' - } - ) + }) ); feature(decoration, { match: /x.*#[23]/ }, browsers => - prefix('text-decoration-skip', { + prefix(['text-decoration-skip'], { browsers, feature: 'text-decoration' - } - ) + }) ); // Text Size Adjust const textSizeAdjust = unpackFeature(require('caniuse-lite/data/features/text-size-adjust.js')); feature(textSizeAdjust, browsers => - prefix('text-size-adjust', { + prefix(['text-size-adjust'], { browsers, feature: 'text-size-adjust' - } - ) + }) ); // CSS Masks feature(unpackFeature(require('caniuse-lite/data/features/css-masks.js')), (browsers) => { - prefix('mask-clip', 'mask-composite', 'mask-image', + prefix([ + 'mask-clip', 'mask-composite', 'mask-image', 'mask-origin', 'mask-repeat', 'mask-border-repeat', - 'mask-border-source', { + 'mask-border-source' + ], { browsers, feature: 'css-masks' - } - ); - return prefix('mask', 'mask-position', 'mask-size', + }); + return prefix([ + 'mask', 'mask-position', 'mask-size', 'mask-border', 'mask-border-outset', 'mask-border-width', - 'mask-border-slice', { + 'mask-border-slice' + ], { browsers, feature: 'css-masks' - } - ); + }); }); // CSS clip-path property feature(unpackFeature(require('caniuse-lite/data/features/css-clip-path.js')), browsers => - prefix('clip-path', { + prefix(['clip-path'], { browsers, feature: 'css-clip-path' - } - ) + }) ); // Fragmented Borders and Backgrounds const boxdecorbreak = unpackFeature(require('caniuse-lite/data/features/css-boxdecorationbreak.js')); feature(boxdecorbreak, browsers => - prefix('box-decoration-break', { + prefix(['box-decoration-break'], { browsers, feature: 'css-boxdecorationbreak' - } - ) + }) ); // CSS3 object-fit/object-position feature(unpackFeature(require('caniuse-lite/data/features/object-fit.js')), browsers => - prefix('object-fit', - 'object-position', { + prefix(['object-fit', 'object-position'], { browsers, feature: 'object-fit' - } - ) + }) ); // CSS Shapes feature(unpackFeature(require('caniuse-lite/data/features/css-shapes.js')), browsers => - prefix('shape-margin', + prefix([ + 'shape-margin', 'shape-outside', - 'shape-image-threshold', { + 'shape-image-threshold' + ], { browsers, feature: 'css-shapes' - } - ) + }) ); // CSS3 text-overflow feature(unpackFeature(require('caniuse-lite/data/features/text-overflow.js')), browsers => - prefix('text-overflow', { + prefix(['text-overflow'], { browsers, feature: 'text-overflow' - } - ) + }) ); // Viewport at-rule const devdaptation = unpackFeature(require('caniuse-lite/data/features/css-deviceadaptation.js')); feature(devdaptation, browsers => - prefix('@viewport', { + prefix(['@viewport'], { browsers, feature: 'css-deviceadaptation' - } - ) + }) ); // Resolution Media Queries const resolution = unpackFeature(require('caniuse-lite/data/features/css-media-resolution.js')); feature(resolution, { match: /( x($| )|a #3)/ }, browsers => - prefix('@resolution', { + prefix(['@resolution'], { browsers, feature: 'css-media-resolution' - } - ) + }) ); // CSS text-align-last const textAlignLast = unpackFeature(require('caniuse-lite/data/features/css-text-align-last.js')); feature(textAlignLast, browsers => - prefix('text-align-last', { + prefix(['text-align-last'], { browsers, feature: 'css-text-align-last' - } - ) + }) ); // Crisp Edges Image Rendering Algorithm const crispedges = unpackFeature(require('caniuse-lite/data/features/css-crisp-edges.js')); feature(crispedges, { match: /y x|a x #1/ }, browsers => - prefix('pixelated', { + prefix(['pixelated'], { props: ['image-rendering'], browsers, feature: 'css-crisp-edges' - } - ) + }) ); feature(crispedges, { match: /a x #2/ }, browsers => - prefix('image-rendering', { + prefix(['image-rendering'], { browsers, feature: 'css-crisp-edges' - } - ) + }) ); // Logical Properties const logicalProps = unpackFeature(require('caniuse-lite/data/features/css-logical-props.js')); feature(logicalProps, browsers => - prefix('border-inline-start', 'border-inline-end', + prefix([ + 'border-inline-start', 'border-inline-end', 'margin-inline-start', 'margin-inline-end', - 'padding-inline-start', 'padding-inline-end', { + 'padding-inline-start', 'padding-inline-end' + ], { browsers, feature: 'css-logical-props' - } - ) + }) ); feature(logicalProps, { match: /x\s#2/ }, browsers => - prefix('border-block-start', 'border-block-end', + prefix([ + 'border-block-start', 'border-block-end', 'margin-block-start', 'margin-block-end', - 'padding-block-start', 'padding-block-end', { + 'padding-block-start', 'padding-block-end' + ], { browsers, feature: 'css-logical-props' - } - ) + }) ); // CSS appearance feature(unpackFeature(require('caniuse-lite/data/features/css-appearance.js')), browsers => - prefix('appearance', { + prefix(['appearance'], { browsers, feature: 'css-appearance' - } - ) + }) ); // CSS Scroll snap points feature(unpackFeature(require('caniuse-lite/data/features/css-snappoints.js')), browsers => - prefix('scroll-snap-type', + prefix([ + 'scroll-snap-type', 'scroll-snap-coordinate', 'scroll-snap-destination', - 'scroll-snap-points-x', 'scroll-snap-points-y', { + 'scroll-snap-points-x', 'scroll-snap-points-y' + ], { browsers, feature: 'css-snappoints' - } - ) + }) ); // CSS Regions feature(unpackFeature(require('caniuse-lite/data/features/css-regions.js')), browsers => - prefix('flow-into', 'flow-from', - 'region-fragment', { + prefix([ + 'flow-into', 'flow-from', + 'region-fragment' + ], { browsers, feature: 'css-regions' - } - ) + }) ); // CSS image-set feature(unpackFeature(require('caniuse-lite/data/features/css-image-set.js')), browsers => - prefix('image-set', { - props: ['background', 'background-image', 'border-image', 'mask', - 'list-style', 'list-style-image', 'content', 'mask-image'], + prefix(['image-set'], { + props: [ + 'background', 'background-image', 'border-image', 'mask', + 'list-style', 'list-style-image', 'content', 'mask-image' + ], browsers, feature: 'css-image-set' - } - ) + }) ); // Writing Mode const writingMode = unpackFeature(require('caniuse-lite/data/features/css-writing-mode.js')); feature(writingMode, { match: /a|x/ }, browsers => - prefix('writing-mode', { + prefix(['writing-mode'], { browsers, feature: 'css-writing-mode' - } - ) + }) ); // Cross-Fade Function feature(unpackFeature(require('caniuse-lite/data/features/css-cross-fade.js')), browsers => - prefix('cross-fade', { - props: ['background', 'background-image', 'border-image', 'mask', - 'list-style', 'list-style-image', 'content', 'mask-image'], + prefix(['cross-fade'], { + props: [ + 'background', 'background-image', 'border-image', 'mask', + 'list-style', 'list-style-image', 'content', 'mask-image' + ], browsers, feature: 'css-cross-fade' - } - ) + }) ); // Read Only selector const readOnly = unpackFeature(require('caniuse-lite/data/features/css-read-only-write.js')); feature(readOnly, browsers => - prefix(':read-only', ':read-write', { + prefix([':read-only', ':read-write'], { selector: true, browsers, feature: 'css-read-only-write' - } - ) + }) ); // Text Emphasize feature(unpackFeature(require('caniuse-lite/data/features/text-emphasis.js')), browsers => - prefix('text-emphasis', 'text-emphasis-position', - 'text-emphasis-style', 'text-emphasis-color', { + prefix([ + 'text-emphasis', 'text-emphasis-position', + 'text-emphasis-style', 'text-emphasis-color' + ], { browsers, feature: 'text-emphasis' - } - ) + }) ); // CSS Grid Layout const grid = unpackFeature(require('caniuse-lite/data/features/css-grid.js')); feature(grid, (browsers) => { - prefix('display-grid', 'inline-grid', { + prefix(['display-grid', 'inline-grid'], { props: ['display'], browsers, feature: 'css-grid' - } - ); - return prefix('grid-template-columns', 'grid-template-rows', + }); + return prefix([ + 'grid-template-columns', 'grid-template-rows', 'grid-row-start', 'grid-column-start', 'grid-row-end', 'grid-column-end', - 'grid-row', 'grid-column', { + 'grid-row', 'grid-column' + ], { browsers, feature: 'css-grid' - } - ); + }); }); feature(grid, { match: /a x/ }, browsers => - prefix('justify-items', 'grid-row-align', { + prefix(['justify-items', 'grid-row-align'], { browsers, feature: 'css-grid' - } - ) + }) ); // CSS text-spacing const textSpacing = unpackFeature(require('caniuse-lite/data/features/css-text-spacing.js')); feature(textSpacing, browsers => - prefix('text-spacing', { + prefix(['text-spacing'], { browsers, feature: 'css-text-spacing' - } - ) + }) ); // :any-link selector feature(unpackFeature(require('caniuse-lite/data/features/css-any-link.js')), browsers => - prefix(':any-link', { + prefix([':any-link'], { selector: true, browsers, feature: 'css-any-link' - } - ) + }) ); diff --git a/gulpfile.js b/gulpfile.js index 6c1cff00f..4ec22e3e1 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,38 +1,36 @@ -var gulp = require('gulp'); -var path = require('path'); -var fs = require('fs-extra'); +const gulp = require('gulp'); +const path = require('path'); +const fs = require('fs-extra'); -gulp.task('clean', function (done) { - fs.remove(path.join(__dirname, 'autoprefixer.js'), function () { +gulp.task('clean', (done) => { + fs.remove(path.join(__dirname, 'autoprefixer.js'), () => { fs.remove(path.join(__dirname, 'build'), done); }); }); -gulp.task('build:lib', ['clean'], function () { - var babel = require('gulp-babel'); +gulp.task('build:lib', ['clean'], () => { + const babel = require('gulp-babel'); return gulp.src(['{lib,data}/**/*.js']) .pipe(babel()) .pipe(gulp.dest('build/')); }); -gulp.task('build:docs', ['clean'], function () { - var ignore = require('fs').readFileSync('.npmignore').toString() +gulp.task('build:docs', ['clean'], () => { + const ignore = require('fs').readFileSync('.npmignore').toString() .trim().split(/\n+/) .concat(['.npmignore', 'index.js', 'package.json', 'logo.svg']) - .map(function (i) { - return '!' + i; - }); + .map((i) => '!' + i); return gulp.src(['*'].concat(ignore)) .pipe(gulp.dest('build')); }); -gulp.task('build:package', ['clean'], function () { - var editor = require('gulp-json-editor'); +gulp.task('build:package', ['clean'], () => { + const editor = require('gulp-json-editor'); return gulp.src('./package.json') - .pipe(editor(function (json) { + .pipe(editor((json) => { json.main = 'lib/autoprefixer'; json.devDependencies['babel-register'] = json.dependencies['babel-register']; @@ -44,19 +42,19 @@ gulp.task('build:package', ['clean'], function () { gulp.task('build', ['build:lib', 'build:docs', 'build:package']); -gulp.task('standalone', ['build:lib'], function (done) { - var builder = require('browserify')({ +gulp.task('standalone', ['build:lib'], (done) => { + const builder = require('browserify')({ basedir: path.join(__dirname, 'build'), standalone: 'autoprefixer' }); builder.add('./lib/autoprefixer.js'); - builder.bundle(function (error, build) { + builder.bundle((error, build) => { if ( error ) throw error; fs.removeSync(path.join(__dirname, 'build')); - var rails = path.join(__dirname, '..', 'autoprefixer-rails', + const rails = path.join(__dirname, '..', 'autoprefixer-rails', 'vendor', 'autoprefixer.js'); if ( fs.existsSync(rails) ) { fs.writeFileSync(rails, build); @@ -67,21 +65,20 @@ gulp.task('standalone', ['build:lib'], function (done) { }); }); -gulp.task('lint', function () { - var eslint = require('gulp-eslint'); +gulp.task('lint', () => { + const eslint = require('gulp-eslint'); - return gulp.src(['index.js', 'gulpfile.js']) + return gulp.src(['index.js', 'gulpfile.js', 'data/**/.js', 'lib/**/*.js']) .pipe(eslint()) .pipe(eslint.format()) .pipe(eslint.failAfterError()); }); -gulp.task('test', function () { - require('babel-register')(); +gulp.task('test', () => { require('should'); - var mocha = require('gulp-mocha'); - return gulp.src('test/*.js', { read: false }).pipe(mocha()); + const mocha = require('gulp-mocha'); + return gulp.src('test/*.js', { read: false }).pipe(mocha({ compilers: 'js:babel-core/register' })); }); gulp.task('default', ['lint', 'test']); diff --git a/lib/at-rule.js b/lib/at-rule.js index fbbf8ba18..c83479064 100644 --- a/lib/at-rule.js +++ b/lib/at-rule.js @@ -2,33 +2,34 @@ const Prefixer = require('./prefixer'); class AtRule extends Prefixer { - // Clone and add prefixes for at-rule + /** + * Clone and add prefixes for at-rule + */ add(rule, prefix) { const prefixed = prefix + rule.name; - const already = rule.parent.some(i => i.name === prefixed && i.params === rule.params); + const already = rule.parent.some( + i => i.name === prefixed && i.params === rule.params + ); if (already) { - return; + return undefined; } const cloned = this.clone(rule, { name: prefixed }); return rule.parent.insertBefore(rule, cloned); } - // Clone node with prefixes + /** + * Clone node with prefixes + */ process(node) { const parent = this.parentPrefix(node); - return (() => { - const result = []; - for (let prefix of this.prefixes) { - if (parent && parent !== prefix) { - continue; - } - result.push(this.add(node, prefix)); + for (const prefix of this.prefixes) { + if (!parent || parent === prefix) { + this.add(node, prefix); } - return result; - })(); + } } } diff --git a/lib/autoprefixer.js b/lib/autoprefixer.js index be3f68f96..9bb8720f5 100644 --- a/lib/autoprefixer.js +++ b/lib/autoprefixer.js @@ -1,12 +1,13 @@ const browserslist = require('browserslist'); -const postcss = require('postcss'); +const postcss = require('postcss'); const Browsers = require('./browsers'); const Prefixes = require('./prefixes'); -const isPlainObject = obj => Object.prototype.toString.apply(obj) === '[object Object]'; +const isPlainObject = obj => + Object.prototype.toString.apply(obj) === '[object Object]'; -const cache = { }; +const cache = {}; const timeCapsule = function (result, prefixes) { if (prefixes.browsers.selected.length === 0) { @@ -19,53 +20,64 @@ const timeCapsule = function (result, prefixes) { return; } - return result.warn( - 'Greetings, time traveller. ' + - 'We are in the golden age of prefix-less CSS, ' + - 'where Autoprefixer is no longer needed for your stylesheet.'); + result.warn( + 'Greetings, time traveller. ' + + 'We are in the golden age of prefix-less CSS, ' + + 'where Autoprefixer is no longer needed for your stylesheet.' + ); }; module.exports = postcss.plugin('autoprefixer', (...reqs) => { let options; if (reqs.length === 1 && isPlainObject(reqs[0])) { options = reqs[0]; - reqs = undefined; - } else if (reqs.length === 0 || reqs.length === 1 && reqs[0] == null) { reqs = undefined; - } else if (reqs.length <= 2 && (reqs[0] instanceof Array || reqs[0] == null)) { + } else if (reqs.length === 0 || reqs.length === 1 && !reqs[0]) { + reqs = undefined; + } else if (reqs.length <= 2 && (reqs[0] instanceof Array || !reqs[0])) { options = reqs[1]; - reqs = reqs[0]; + reqs = reqs[0]; } else if (typeof reqs[reqs.length - 1] === 'object') { options = reqs.pop(); } if (!options) { - options = { }; + options = {}; } if (options.browser) { - throw new Error('Change `browser` option to `browsers` in Autoprefixer'); + throw new Error( + 'Change `browser` option to `browsers` in Autoprefixer' + ); } - if (options.browsers != null) { + if (options.browsers) { reqs = options.browsers; } const loadPrefixes = function (opts) { - const { stats } = options; - const browsers = new Browsers(module.exports.data.browsers, reqs, opts, stats); - const key = browsers.selected.join(', ') + JSON.stringify(options); - return cache[key] || (cache[key] = new Prefixes(module.exports.data.prefixes, browsers, options)); + const data = module.exports.data; + const browsers = new Browsers(data.browsers, reqs, opts, options.stats); + const key = browsers.selected.join(', ') + JSON.stringify(options); + + if (!cache[key]) { + cache[key] = new Prefixes(data.prefixes, browsers, options); + } + + return cache[key]; }; const plugin = function (css, result) { - const prefixes = loadPrefixes({ from: css.source != null ? css.source.input.file : undefined, env: options.env }); + const prefixes = loadPrefixes({ + from: css.source && css.source.input.file, + env: options.env + }); timeCapsule(result, prefixes); if (options.remove !== false) { prefixes.processor.remove(css); } if (options.add !== false) { - return prefixes.processor.add(css, result); + prefixes.processor.add(css, result); } }; @@ -76,14 +88,20 @@ module.exports = postcss.plugin('autoprefixer', (...reqs) => { return plugin; }); -// Autoprefixer data +/** + * Autoprefixer data + */ module.exports.data = { browsers: require('caniuse-lite').agents, prefixes: require('../data/prefixes') }; -// Autoprefixer default browsers +/** + * Autoprefixer default browsers + */ module.exports.defaults = browserslist.defaults; -// Inspect with default Autoprefixer +/** + * Inspect with default Autoprefixer + */ module.exports.info = () => module.exports().info(); diff --git a/lib/brackets.js b/lib/brackets.js index 8124f3933..8d0da095f 100644 --- a/lib/brackets.js +++ b/lib/brackets.js @@ -1,13 +1,15 @@ const last = array => array[array.length - 1]; -var brackets = { +const brackets = { - // Parse string to nodes tree + /** + * Parse string to nodes tree + */ parse(str) { let current = ['']; - const stack = [current]; + const stack = [current]; - for (let sym of str) { + for (const sym of str) { if (sym === '(') { current = ['']; last(stack).push(current); @@ -26,10 +28,12 @@ var brackets = { return stack[0]; }, - // Generate output string by nodes tree + /** + * Generate output string by nodes tree + */ stringify(ast) { let result = ''; - for (let i of ast) { + for (const i of ast) { if (typeof i === 'object') { result += `(${brackets.stringify(i)})`; } else { diff --git a/lib/browsers.js b/lib/browsers.js index bee4820be..56cf7a0ca 100644 --- a/lib/browsers.js +++ b/lib/browsers.js @@ -4,28 +4,34 @@ const utils = require('./utils'); class Browsers { - // Return all prefixes for default browser data + /** + * Return all prefixes for default browser data + */ static prefixes() { if (this.prefixesCache) { return this.prefixesCache; } const data = require('caniuse-lite').agents; - return this.prefixesCache = utils.uniq((() => { - const result = []; - for (let name in data) { - const i = data[name]; - result.push(`-${i.prefix}-`); - } - return result; - })()) + + this.prefixesCache = []; + for (const name in data) { + this.prefixesCache.push(`-${data[name].prefix}-`); + } + + this.prefixesCache = utils + .uniq(this.prefixesCache) .sort((a, b) => b.length - a.length); + + return this.prefixesCache; } - // Check is value contain any possibe prefix + /** + * Check is value contain any possibe prefix + */ static withPrefix(value) { if (!this.prefixesRegexp) { - this.prefixesRegexp = new RegExp(`${ this.prefixes().join('|') }`); + this.prefixesRegexp = new RegExp(this.prefixes().join('|')); } return this.prefixesRegexp.test(value); @@ -33,47 +39,54 @@ class Browsers { constructor(data, requirements, options, stats) { this.data = data; - this.options = options; + this.options = options || {}; this.stats = stats; this.selected = this.parse(requirements); } - // Return browsers selected by requirements + /** + * Return browsers selected by requirements + */ parse(requirements) { return browserslist(requirements, { stats: this.stats, - path: this.options != null ? this.options.from : undefined, - env: this.options != null ? this.options.env : undefined - } - ); + path: this.options.from, + env: this.options.env + }); } - // Select major browsers versions by criteria + /** + * Select major browsers versions by criteria + */ browsers(criteria) { let selected = []; - for (var browser in this.data) { + for (const browser in this.data) { const data = this.data[browser]; - const versions = criteria(data).map(version => `${browser} ${version}`); + const versions = criteria(data).map( + version => `${browser} ${version}` + ); selected = selected.concat(versions); } return selected; } - // Return prefix for selected browser + /** + * Return prefix for selected browser + */ prefix(browser) { - let prefix; - const [name, version] = Array.from(browser.split(' ')); + const [name, version] = browser.split(' '); const data = this.data[name]; - if (data.prefix_exceptions) { - prefix = data.prefix_exceptions[version]; - } + + let prefix = data.prefix_exceptions && data.prefix_exceptions[version]; if (!prefix) { - ({ prefix } = data); + prefix = data.prefix; } return `-${prefix}-`; } - // Is browser is selected by requirements + /** + * Is browser is selected by requirements + */ isSelected(browser) { return this.selected.indexOf(browser) !== -1; } diff --git a/lib/declaration.js b/lib/declaration.js index 39a26f0cd..954025077 100644 --- a/lib/declaration.js +++ b/lib/declaration.js @@ -1,27 +1,35 @@ const Prefixer = require('./prefixer'); const Browsers = require('./browsers'); -const utils = require('./utils'); +const utils = require('./utils'); class Declaration extends Prefixer { - // Always true, because we already get prefixer by property name - check(decl) { + /** + * Always true, because we already get prefixer by property name + */ + check(/* decl */) { return true; } - // Return prefixed version of property + /** + * Return prefixed version of property + */ prefixed(prop, prefix) { return prefix + prop; } - // Return unprefixed version of property + /** + * Return unprefixed version of property + */ normalize(prop) { return prop; } - // Check `value`, that it contain other prefixes, rather than `prefix` + /** + * Check `value`, that it contain other prefixes, rather than `prefix` + */ otherPrefixes(value, prefix) { - for (let other of Browsers.prefixes()) { + for (const other of Browsers.prefixes()) { if (other === prefix) { continue; } @@ -32,19 +40,29 @@ class Declaration extends Prefixer { return false; } - // Set prefix to declaration + /** + * Set prefix to declaration + */ set(decl, prefix) { decl.prop = this.prefixed(decl.prop, prefix); return decl; } - // Should we use visual cascade for prefixes + /** + * Should we use visual cascade for prefixes + */ needCascade(decl) { - return decl._autoprefixerCascade || (decl._autoprefixerCascade = this.all.options.cascade !== false && - decl.raw('before').indexOf('\n') !== -1); + if (!decl._autoprefixerCascade) { + decl._autoprefixerCascade = + this.all.options.cascade !== false && + decl.raw('before').indexOf('\n') !== -1; + } + return decl._autoprefixerCascade; } - // Return maximum length of possible prefixed property + /** + * Return maximum length of possible prefixed property + */ maxPrefixed(prefixes, decl) { if (decl._autoprefixerMax) { return decl._autoprefixerMax; @@ -54,51 +72,60 @@ class Declaration extends Prefixer { for (let prefix of prefixes) { prefix = utils.removeNote(prefix); if (prefix.length > max) { - max = prefix.length; + max = prefix.length; } } + decl._autoprefixerMax = max; - return decl._autoprefixerMax = max; + return decl._autoprefixerMax; } - // Calculate indentation to create visual cascade + /** + * Calculate indentation to create visual cascade + */ calcBefore(prefixes, decl, prefix = '') { + const max = this.maxPrefixed(prefixes, decl); + const diff = max - utils.removeNote(prefix).length; + let before = decl.raw('before'); - const max = this.maxPrefixed(prefixes, decl); - const diff = max - utils.removeNote(prefix).length; - for (let i = 0, end = diff, asc = end >= 0; asc ? i < end : i > end; asc ? i++ : i--) { - before += ' '; - } + before += Array(diff).fill(' ').join(''); + return before; } - // Remove visual cascade + /** + * Remove visual cascade + */ restoreBefore(decl) { const lines = decl.raw('before').split('\n'); - let min = lines[lines.length - 1]; + let min = lines[lines.length - 1]; this.all.group(decl).up((prefixed) => { const array = prefixed.raw('before').split('\n'); - const last = array[array.length - 1]; + const last = array[array.length - 1]; if (last.length < min.length) { - return min = last; + min = last; } }); lines[lines.length - 1] = min; - return decl.raws.before = lines.join('\n'); + decl.raws.before = lines.join('\n'); } - // Clone and insert new declaration + /** + * Clone and insert new declaration + */ insert(decl, prefix, prefixes) { const cloned = this.set(this.clone(decl), prefix); if (!cloned) { - return; + return undefined; } - const already = decl.parent.some(i => i.prop === cloned.prop && i.value === cloned.value); + const already = decl.parent.some( + i => i.prop === cloned.prop && i.value === cloned.value + ); if (already) { - return; + return undefined; } if (this.needCascade(decl)) { @@ -107,38 +134,47 @@ class Declaration extends Prefixer { return decl.parent.insertBefore(decl, cloned); } - // Did this declaration has this prefix above + /** + * Did this declaration has this prefix above + */ isAlready(decl, prefixed) { - let already = this.all.group(decl).up(i => i.prop === prefixed); + let already = this.all.group(decl).up(i => i.prop === prefixed); if (!already) { already = this.all.group(decl).down(i => i.prop === prefixed); } return already; } - // Clone and add prefixes for declaration + /** + * Clone and add prefixes for declaration + */ add(decl, prefix, prefixes) { const prefixed = this.prefixed(decl.prop, prefix); - if (this.isAlready(decl, prefixed) || this.otherPrefixes(decl.value, prefix)) { - return; + if (this.isAlready(decl, prefixed) || + this.otherPrefixes(decl.value, prefix)) { + return undefined; } return this.insert(decl, prefix, prefixes); } - // Add spaces for visual cascade + /** + * Add spaces for visual cascade + */ process(decl) { if (this.needCascade(decl)) { - const prefixes = super.process(...arguments); - if (prefixes != null ? prefixes.length : undefined) { + const prefixes = super.process(decl); + if (prefixes && prefixes.length) { this.restoreBefore(decl); - return decl.raws.before = this.calcBefore(prefixes, decl); + decl.raws.before = this.calcBefore(prefixes, decl); } } else { - return super.process(...arguments); + super.process(decl); } } - // Return list of prefixed properties to clean old prefixes + /** + * Return list of prefixed properties to clean old prefixes + */ old(prop, prefix) { return [this.prefixed(prop, prefix)]; } diff --git a/lib/hacks/align-content.js b/lib/hacks/align-content.js index 21f708430..efd92d591 100644 --- a/lib/hacks/align-content.js +++ b/lib/hacks/align-content.js @@ -1,4 +1,4 @@ -const flexSpec = require('./flex-spec'); +const flexSpec = require('./flex-spec'); const Declaration = require('../declaration'); class AlignContent extends Declaration { @@ -6,38 +6,45 @@ class AlignContent extends Declaration { this.names = ['align-content', 'flex-line-pack']; this.oldValues = { - 'flex-end': 'end', - 'flex-start': 'start', + 'flex-end': 'end', + 'flex-start': 'start', 'space-between': 'justify', - 'space-around': 'distribute' + 'space-around': 'distribute' }; } - // Change property name for 2012 spec + /** + * Change property name for 2012 spec + */ prefixed(prop, prefix) { let spec; - [spec, prefix] = Array.from(flexSpec(prefix)); + [spec, prefix] = flexSpec(prefix); if (spec === 2012) { return prefix + 'flex-line-pack'; } else { - return super.prefixed(...arguments); + return super.prefixed(prop, prefix); } } - // Return property name by final spec - normalize(prop) { + /** + * Return property name by final spec + */ + normalize() { return 'align-content'; } - // Change value for 2012 spec and ignore prefix for 2009 + /** + * Change value for 2012 spec and ignore prefix for 2009 + */ set(decl, prefix) { const spec = flexSpec(prefix)[0]; if (spec === 2012) { decl.value = AlignContent.oldValues[decl.value] || decl.value; return super.set(decl, prefix); } else if (spec === 'final') { - return super.set(...arguments); + return super.set(decl, prefix); } + return undefined; } } AlignContent.initClass(); diff --git a/lib/hacks/align-items.js b/lib/hacks/align-items.js index 2ff415bb1..c0950f6a8 100644 --- a/lib/hacks/align-items.js +++ b/lib/hacks/align-items.js @@ -1,4 +1,4 @@ -const flexSpec = require('./flex-spec'); +const flexSpec = require('./flex-spec'); const Declaration = require('../declaration'); class AlignItems extends Declaration { @@ -6,38 +6,42 @@ class AlignItems extends Declaration { this.names = ['align-items', 'flex-align', 'box-align']; this.oldValues = { - 'flex-end': 'end', + 'flex-end': 'end', 'flex-start': 'start' }; } - // Change property name for 2009 and 2012 specs + /** + * Change property name for 2009 and 2012 specs + */ prefixed(prop, prefix) { let spec; - [spec, prefix] = Array.from(flexSpec(prefix)); + [spec, prefix] = flexSpec(prefix); if (spec === 2009) { return prefix + 'box-align'; } else if (spec === 2012) { return prefix + 'flex-align'; } else { - return super.prefixed(...arguments); + return super.prefixed(prop, prefix); } } - // Return property name by final spec - normalize(prop) { + /** + * Return property name by final spec + */ + normalize() { return 'align-items'; } - // Change value for 2009 and 2012 specs + /** + * Change value for 2009 and 2012 specs + */ set(decl, prefix) { const spec = flexSpec(prefix)[0]; if (spec === 2009 || spec === 2012) { decl.value = AlignItems.oldValues[decl.value] || decl.value; - return super.set(decl, prefix); - } else { - return super.set(...arguments); } + return super.set(decl, prefix); } } AlignItems.initClass(); diff --git a/lib/hacks/align-self.js b/lib/hacks/align-self.js index 3de1f287d..390bd1b60 100644 --- a/lib/hacks/align-self.js +++ b/lib/hacks/align-self.js @@ -1,4 +1,4 @@ -const flexSpec = require('./flex-spec'); +const flexSpec = require('./flex-spec'); const Declaration = require('../declaration'); class AlignSelf extends Declaration { @@ -6,36 +6,43 @@ class AlignSelf extends Declaration { this.names = ['align-self', 'flex-item-align']; this.oldValues = { - 'flex-end': 'end', + 'flex-end': 'end', 'flex-start': 'start' }; } - // Change property name for 2012 specs + /** + * Change property name for 2012 specs + */ prefixed(prop, prefix) { let spec; - [spec, prefix] = Array.from(flexSpec(prefix)); + [spec, prefix] = flexSpec(prefix); if (spec === 2012) { return prefix + 'flex-item-align'; } else { - return super.prefixed(...arguments); + return super.prefixed(prop, prefix); } } - // Return property name by final spec - normalize(prop) { + /** + * Return property name by final spec + */ + normalize() { return 'align-self'; } - // Change value for 2012 spec and ignore prefix for 2009 + /** + * Change value for 2012 spec and ignore prefix for 2009 + */ set(decl, prefix) { const spec = flexSpec(prefix)[0]; if (spec === 2012) { decl.value = AlignSelf.oldValues[decl.value] || decl.value; return super.set(decl, prefix); } else if (spec === 'final') { - return super.set(...arguments); + return super.set(decl, prefix); } + return undefined; } } AlignSelf.initClass(); diff --git a/lib/hacks/background-size.js b/lib/hacks/background-size.js index bf51d5e25..eca4fe2a3 100644 --- a/lib/hacks/background-size.js +++ b/lib/hacks/background-size.js @@ -5,11 +5,16 @@ class BackgroundSize extends Declaration { this.names = ['background-size']; } - // Duplication parameter for -webkit- browsers + /** + * Duplication parameter for -webkit- browsers + */ set(decl, prefix) { const value = decl.value.toLowerCase(); - if (prefix === '-webkit-' && value.indexOf(' ') === -1 && - value !== 'contain' && value !== 'cover') { + if (prefix === '-webkit-' && + value.indexOf(' ') === -1 && + value !== 'contain' && + value !== 'cover' + ) { decl.value = decl.value + ' ' + decl.value; } return super.set(decl, prefix); diff --git a/lib/hacks/block-logical.js b/lib/hacks/block-logical.js index a76eb04aa..a1dd6db43 100644 --- a/lib/hacks/block-logical.js +++ b/lib/hacks/block-logical.js @@ -2,22 +2,28 @@ const Declaration = require('../declaration'); class BlockLogical extends Declaration { static initClass() { - this.names = ['border-block-start', 'border-block-end', - 'margin-block-start', 'margin-block-end', + this.names = [ + 'border-block-start', 'border-block-end', + 'margin-block-start', 'margin-block-end', 'padding-block-start', 'padding-block-end', - 'border-before', 'border-after', - 'margin-before', 'margin-after', - 'padding-before', 'padding-after']; + 'border-before', 'border-after', + 'margin-before', 'margin-after', + 'padding-before', 'padding-after' + ]; } - // Use old syntax for -moz- and -webkit- + /** + * Use old syntax for -moz- and -webkit- + */ prefixed(prop, prefix) { return prefix + (prop.indexOf('-start') !== -1 ? - prop.replace('-block-start', '-before') : - prop.replace('-block-end', '-after')); + prop.replace('-block-start', '-before') : + prop.replace('-block-end', '-after')); } - // Return property name by spec + /** + * Return property name by spec + */ normalize(prop) { if (prop.indexOf('-before') !== -1) { return prop.replace('-before', '-block-start'); diff --git a/lib/hacks/border-image.js b/lib/hacks/border-image.js index 9294f8d4f..57c3e28fe 100644 --- a/lib/hacks/border-image.js +++ b/lib/hacks/border-image.js @@ -5,7 +5,9 @@ class BorderImage extends Declaration { this.names = ['border-image']; } - // Remove fill parameter for prefixed declarations + /** + * Remove fill parameter for prefixed declarations + */ set(decl, prefix) { decl.value = decl.value.replace(/\s+fill(\s)/, '$1'); return super.set(decl, prefix); diff --git a/lib/hacks/border-radius.js b/lib/hacks/border-radius.js index 1e1023d74..e8b54878c 100644 --- a/lib/hacks/border-radius.js +++ b/lib/hacks/border-radius.js @@ -2,13 +2,13 @@ const Declaration = require('../declaration'); class BorderRadius extends Declaration { static initClass() { - this.names = ['border-radius']; + this.names = ['border-radius']; - this.toMozilla = { }; - this.toNormal = { }; - for (let ver of ['top', 'bottom']) { - for (let hor of ['left', 'right']) { - const normal = `border-${ver}-${hor}-radius`; + this.toMozilla = {}; + this.toNormal = {}; + for (const ver of ['top', 'bottom']) { + for (const hor of ['left', 'right']) { + const normal = `border-${ver}-${hor}-radius`; const mozilla = `border-radius-${ver}${hor}`; this.names.push(normal); @@ -20,16 +20,20 @@ class BorderRadius extends Declaration { } } - // Change syntax, when add Mozilla prefix + /** + * Change syntax, when add Mozilla prefix + */ prefixed(prop, prefix) { if (prefix === '-moz-') { return prefix + (BorderRadius.toMozilla[prop] || prop); } else { - return super.prefixed(...arguments); + return super.prefixed(prop, prefix); } } - // Return unprefixed version of property + /** + * Return unprefixed version of property + */ normalize(prop) { return BorderRadius.toNormal[prop] || prop; } diff --git a/lib/hacks/break-props.js b/lib/hacks/break-props.js index 080f1aa56..524b54117 100644 --- a/lib/hacks/break-props.js +++ b/lib/hacks/break-props.js @@ -2,23 +2,29 @@ const Declaration = require('../declaration'); class BreakProps extends Declaration { static initClass() { - this.names = ['break-inside', 'page-break-inside', 'column-break-inside', + this.names = [ + 'break-inside', 'page-break-inside', 'column-break-inside', 'break-before', 'page-break-before', 'column-break-before', - 'break-after', 'page-break-after', 'column-break-after']; + 'break-after', 'page-break-after', 'column-break-after' + ]; } - // Change name for -webkit- and -moz- prefix + /** + * Change name for -webkit- and -moz- prefix + */ prefixed(prop, prefix) { if (prefix === '-webkit-') { return `-webkit-column-${prop}`; } else if (prefix === '-moz-') { return `page-${prop}`; } else { - return super.prefixed(...arguments); + return super.prefixed(prop, prefix); } } - // Return property name by final spec + /** + * Return property name by final spec + */ normalize(prop) { if (prop.indexOf('inside') !== -1) { return 'break-inside'; @@ -27,27 +33,35 @@ class BreakProps extends Declaration { } else if (prop.indexOf('after') !== -1) { return 'break-after'; } + return undefined; } - // Change prefixed value for avoid-column and avoid-page + /** + * Change prefixed value for avoid-column and avoid-page + */ set(decl, prefix) { const v = decl.value; - if (decl.prop === 'break-inside' && v === 'avoid-column' || v === 'avoid-page') { + if (decl.prop === 'break-inside' && + v === 'avoid-column' || + v === 'avoid-page' + ) { decl.value = 'avoid'; } - return super.set(...arguments); + return super.set(decl, prefix); } - // Don’t prefix some values + /** + * Don’t prefix some values + */ insert(decl, prefix, prefixes) { if (decl.prop !== 'break-inside') { - return super.insert(...arguments); + return super.insert(decl, prefix, prefixes); } else if (decl.value === 'avoid-region') { - return; + return undefined; } else if (decl.value === 'avoid-page' && prefix === '-webkit-') { - return; + return undefined; } else { - return super.insert(...arguments); + return super.insert(decl, prefix, prefixes); } } } diff --git a/lib/hacks/cross-fade.js b/lib/hacks/cross-fade.js index 4b430acd6..e528e6acd 100644 --- a/lib/hacks/cross-fade.js +++ b/lib/hacks/cross-fade.js @@ -1,7 +1,5 @@ -const OldValue = require('../old-value'); -const Value = require('../value'); -const utils = require('../utils'); -const list = require('postcss/lib/list'); +const Value = require('../value'); +const list = require('postcss/lib/list'); class CrossFade extends Value { static initClass() { @@ -10,26 +8,26 @@ class CrossFade extends Value { replace(string, prefix) { return list.space(string) - .map(value => { - if (value.slice(0, +this.name.length + 1 || undefined) !== this.name + '(') { - return value; - } + .map(value => { + if (value.slice(0, +this.name.length + 1) !== this.name + '(') { + return value; + } - const close = value.lastIndexOf(')'); - const after = value.slice(close + 1); - let args = value.slice(this.name.length + 1, +close - 1 + 1 || undefined); + const close = value.lastIndexOf(')'); + const after = value.slice(close + 1); + let args = value.slice(this.name.length + 1, close); - if (prefix === '-webkit-') { - const match = args.match(/\d*.?\d+%?/); - if (match) { - args = args.slice(match[0].length).trim(); - args += `, ${match[0]}`; - } else { - args += ', 0.5'; - } - } - return prefix + this.name + '(' + args + ')' + after; - }).join(' '); + if (prefix === '-webkit-') { + const match = args.match(/\d*.?\d+%?/); + if (match) { + args = args.slice(match[0].length).trim(); + args += `, ${match[0]}`; + } else { + args += ', 0.5'; + } + } + return prefix + this.name + '(' + args + ')' + after; + }).join(' '); } } CrossFade.initClass(); diff --git a/lib/hacks/display-flex.js b/lib/hacks/display-flex.js index 6983447b0..7ebafbca2 100644 --- a/lib/hacks/display-flex.js +++ b/lib/hacks/display-flex.js @@ -1,6 +1,6 @@ const flexSpec = require('./flex-spec'); const OldValue = require('../old-value'); -const Value = require('../value'); +const Value = require('../value'); class DisplayFlex extends Value { static initClass() { @@ -8,52 +8,61 @@ class DisplayFlex extends Value { } constructor(name, prefixes) { - super(...arguments); + super(name, prefixes); if (name === 'display-flex') { this.name = 'flex'; } } - // Faster check for flex value + /** + * Faster check for flex value + */ check(decl) { return decl.prop === 'display' && decl.value === this.name; } - // Return value by spec + /** + * Return value by spec + */ prefixed(prefix) { - let spec; - [spec, prefix] = Array.from(flexSpec(prefix)); - - return prefix + (() => { - if (spec === 2009) { - if (this.name === 'flex') { - return 'box'; - } else { - return 'inline-box'; - } - } else if (spec === 2012) { - if (this.name === 'flex') { - return 'flexbox'; - } else { - return 'inline-flexbox'; - } - } else if (spec === 'final') { - return this.name; + let spec, value; + [spec, prefix] = flexSpec(prefix); + + if (spec === 2009) { + if (this.name === 'flex') { + value = 'box'; + } else { + value = 'inline-box'; + } + } else if (spec === 2012) { + if (this.name === 'flex') { + value = 'flexbox'; + } else { + value = 'inline-flexbox'; } - })(); + } else if (spec === 'final') { + value = this.name; + } + + return prefix + value; } - // Add prefix to value depend on flebox spec version + /** + * Add prefix to value depend on flebox spec version + */ replace(string, prefix) { return this.prefixed(prefix); } - // Change value for old specs + /** + * Change value for old specs + */ old(prefix) { const prefixed = this.prefixed(prefix); if (prefixed) { return new OldValue(this.name, prefixed); } + return undefined; } } DisplayFlex.initClass(); diff --git a/lib/hacks/display-grid.js b/lib/hacks/display-grid.js index 4ed126008..d2124b727 100644 --- a/lib/hacks/display-grid.js +++ b/lib/hacks/display-grid.js @@ -1,6 +1,4 @@ -const flexSpec = require('./flex-spec'); -const OldValue = require('../old-value'); -const Value = require('../value'); +const Value = require('../value'); class DisplayGrid extends Value { static initClass() { @@ -8,13 +6,15 @@ class DisplayGrid extends Value { } constructor(name, prefixes) { - super(...arguments); + super(name, prefixes); if (name === 'display-grid') { this.name = 'grid'; } } - // Faster check for flex value + /** + * Faster check for flex value + */ check(decl) { return decl.prop === 'display' && decl.value === this.name; } diff --git a/lib/hacks/filter-value.js b/lib/hacks/filter-value.js index 96d2ecaba..47c6b14f5 100644 --- a/lib/hacks/filter-value.js +++ b/lib/hacks/filter-value.js @@ -1,13 +1,15 @@ const OldValue = require('../old-value'); -const Value = require('../value'); -const utils = require('../utils'); +const Value = require('../value'); +const utils = require('../utils'); class OldFilterValue extends OldValue { - // Clean -webkit-filter from properties list + /** + * Clean -webkit-filter from properties list + */ clean(decl) { - return decl.value = utils.editList(decl.value, props => { - if (props.every( i => i.indexOf(this.unprefixed) !== 0 )) { + decl.value = utils.editList(decl.value, props => { + if (props.every(i => i.indexOf(this.unprefixed) !== 0)) { return props; } return props.filter(i => i.indexOf(this.prefixed) === -1); @@ -21,26 +23,30 @@ class FilterValue extends Value { } constructor(name, prefixes) { - super(...arguments); + super(name, prefixes); if (name === 'filter-function') { this.name = 'filter'; } } - // Use prefixed and unprefixed filter for WebKit + /** + * Use prefixed and unprefixed filter for WebKit + */ replace(value, prefix) { - if (prefix === '-webkit-' && value.indexOf('filter(') === -1) { + if (prefix === '-webkit-' && value.indexOf('filter(') === -1) { if (value.indexOf('-webkit-filter') === -1) { - return super.replace(...arguments) + ', ' + value; + return super.replace(value, prefix) + ', ' + value; } else { return value; } } else { - return super.replace(...arguments); + return super.replace(value, prefix); } } - // Clean -webkit-filter + /** + * Clean -webkit-filter + */ old(prefix) { return new OldFilterValue(this.name, prefix + this.name); } diff --git a/lib/hacks/filter.js b/lib/hacks/filter.js index df9e491e2..5974c1d69 100644 --- a/lib/hacks/filter.js +++ b/lib/hacks/filter.js @@ -5,12 +5,16 @@ class Filter extends Declaration { this.names = ['filter']; } - // Check is it Internet Explorer filter + /** + * Check is it Internet Explorer filter + */ check(decl) { const v = decl.value; - return v.toLowerCase().indexOf('alpha(') === -1 && - v.indexOf('DXImageTransform.Microsoft') === -1 && - v.indexOf('data:image/svg+xml') === -1; + return ( + v.toLowerCase().indexOf('alpha(') === -1 && + v.indexOf('DXImageTransform.Microsoft') === -1 && + v.indexOf('data:image/svg+xml') === -1 + ); } } Filter.initClass(); diff --git a/lib/hacks/flex-basis.js b/lib/hacks/flex-basis.js index a872a3f61..2553703e7 100644 --- a/lib/hacks/flex-basis.js +++ b/lib/hacks/flex-basis.js @@ -1,4 +1,4 @@ -const flexSpec = require('./flex-spec'); +const flexSpec = require('./flex-spec'); const Declaration = require('../declaration'); class FlexBasis extends Declaration { @@ -6,29 +6,36 @@ class FlexBasis extends Declaration { this.names = ['flex-basis', 'flex-preferred-size']; } - // Return property name by final spec + /** + * Return property name by final spec + */ normalize() { return 'flex-basis'; } - // Return flex property for 2012 spec + /** + * Return flex property for 2012 spec + */ prefixed(prop, prefix) { let spec; - [spec, prefix] = Array.from(flexSpec(prefix)); + [spec, prefix] = flexSpec(prefix); if (spec === 2012) { return prefix + 'flex-preferred-size'; } else { - return super.prefixed(...arguments); + return super.prefixed(prop, prefix); } } - // Ignore 2009 spec and use flex property for 2012 + /** + * Ignore 2009 spec and use flex property for 2012 + */ set(decl, prefix) { let spec; - [spec, prefix] = Array.from(flexSpec(prefix)); + [spec, prefix] = flexSpec(prefix); if (spec === 2012 || spec === 'final') { - return super.set(...arguments); + return super.set(decl, prefix); } + return undefined; } } FlexBasis.initClass(); diff --git a/lib/hacks/flex-direction.js b/lib/hacks/flex-direction.js index 9d6bde9b2..d98e6fea0 100644 --- a/lib/hacks/flex-direction.js +++ b/lib/hacks/flex-direction.js @@ -1,4 +1,4 @@ -const flexSpec = require('./flex-spec'); +const flexSpec = require('./flex-spec'); const Declaration = require('../declaration'); class FlexDirection extends Declaration { @@ -6,29 +6,40 @@ class FlexDirection extends Declaration { this.names = ['flex-direction', 'box-direction', 'box-orient']; } - // Return property name by final spec - normalize(prop) { + /** + * Return property name by final spec + */ + normalize() { return 'flex-direction'; } - // Use two properties for 2009 spec + /** + * Use two properties for 2009 spec + */ insert(decl, prefix, prefixes) { let spec; - [spec, prefix] = Array.from(flexSpec(prefix)); + [spec, prefix] = flexSpec(prefix); if (spec !== 2009) { - return super.insert(...arguments); + return super.insert(decl, prefix, prefixes); } else { - const already = decl.parent.some(i => i.prop === prefix + 'box-orient' || i.prop === prefix + 'box-direction'); + const already = decl.parent.some( + i => i.prop === prefix + 'box-orient' || + i.prop === prefix + 'box-direction' + ); if (already) { - return; + return undefined; } - const { value } = decl; - const orient = value.indexOf('row') !== -1 ? 'horizontal' : 'vertical'; - const dir = value.indexOf('reverse') !== -1 ? 'reverse' : 'normal'; + const value = decl.value; + const orient = value.indexOf('row') !== -1 ? + 'horizontal' : + 'vertical'; + const dir = value.indexOf('reverse') !== -1 ? + 'reverse' : + 'normal'; let cloned = this.clone(decl); - cloned.prop = prefix + 'box-orient'; + cloned.prop = prefix + 'box-orient'; cloned.value = orient; if (this.needCascade(decl)) { cloned.raws.before = this.calcBefore(prefixes, decl, prefix); @@ -36,7 +47,7 @@ class FlexDirection extends Declaration { decl.parent.insertBefore(decl, cloned); cloned = this.clone(decl); - cloned.prop = prefix + 'box-direction'; + cloned.prop = prefix + 'box-direction'; cloned.value = dir; if (this.needCascade(decl)) { cloned.raws.before = this.calcBefore(prefixes, decl, prefix); @@ -45,14 +56,16 @@ class FlexDirection extends Declaration { } } - // Clean two properties for 2009 spec + /** + * Clean two properties for 2009 spec + */ old(prop, prefix) { let spec; - [spec, prefix] = Array.from(flexSpec(prefix)); + [spec, prefix] = flexSpec(prefix); if (spec === 2009) { return [prefix + 'box-orient', prefix + 'box-direction']; } else { - return super.old(...arguments); + return super.old(prop, prefix); } } } diff --git a/lib/hacks/flex-flow.js b/lib/hacks/flex-flow.js index 2c20e9718..f41cae03d 100644 --- a/lib/hacks/flex-flow.js +++ b/lib/hacks/flex-flow.js @@ -1,4 +1,4 @@ -const flexSpec = require('./flex-spec'); +const flexSpec = require('./flex-spec'); const Declaration = require('../declaration'); class FlexFlow extends Declaration { @@ -6,29 +6,40 @@ class FlexFlow extends Declaration { this.names = ['flex-flow', 'box-direction', 'box-orient']; } - // Use two properties for 2009 spec + /** + * Use two properties for 2009 spec + */ insert(decl, prefix, prefixes) { let spec; - [spec, prefix] = Array.from(flexSpec(prefix)); + [spec, prefix] = flexSpec(prefix); if (spec !== 2009) { - return super.insert(...arguments); + return super.insert(decl, prefix, prefixes); } else { - const values = decl.value.split(/\s+/).filter(i => i !== 'wrap' && i !== 'nowrap' && 'wrap-reverse'); + const values = decl.value.split(/\s+/).filter( + i => i !== 'wrap' && i !== 'nowrap' && 'wrap-reverse' + ); if (values.length === 0) { - return; + return undefined; } - const already = decl.parent.some(i => i.prop === prefix + 'box-orient' || i.prop === prefix + 'box-direction'); + const already = decl.parent.some( + i => i.prop === prefix + 'box-orient' || + i.prop === prefix + 'box-direction' + ); if (already) { - return; + return undefined; } const value = values[0]; - const orient = value.indexOf('row') !== -1 ? 'horizontal' : 'vertical'; - const dir = value.indexOf('reverse') !== -1 ? 'reverse' : 'normal'; + const orient = value.indexOf('row') !== -1 ? + 'horizontal' : + 'vertical'; + const dir = value.indexOf('reverse') !== -1 ? + 'reverse' : + 'normal'; let cloned = this.clone(decl); - cloned.prop = prefix + 'box-orient'; + cloned.prop = prefix + 'box-orient'; cloned.value = orient; if (this.needCascade(decl)) { cloned.raws.before = this.calcBefore(prefixes, decl, prefix); @@ -36,7 +47,7 @@ class FlexFlow extends Declaration { decl.parent.insertBefore(decl, cloned); cloned = this.clone(decl); - cloned.prop = prefix + 'box-direction'; + cloned.prop = prefix + 'box-direction'; cloned.value = dir; if (this.needCascade(decl)) { cloned.raws.before = this.calcBefore(prefixes, decl, prefix); diff --git a/lib/hacks/flex-grow.js b/lib/hacks/flex-grow.js index 0e2051e81..d529c3a93 100644 --- a/lib/hacks/flex-grow.js +++ b/lib/hacks/flex-grow.js @@ -1,4 +1,4 @@ -const flexSpec = require('./flex-spec'); +const flexSpec = require('./flex-spec'); const Declaration = require('../declaration'); class Flex extends Declaration { @@ -6,21 +6,25 @@ class Flex extends Declaration { this.names = ['flex-grow', 'flex-positive']; } - // Return property name by final spec + /** + * Return property name by final spec + */ normalize() { return 'flex'; } - // Return flex property for 2009 and 2012 specs + /** + * Return flex property for 2009 and 2012 specs + */ prefixed(prop, prefix) { let spec; - [spec, prefix] = Array.from(flexSpec(prefix)); + [spec, prefix] = flexSpec(prefix); if (spec === 2009) { return prefix + 'box-flex'; } else if (spec === 2012) { return prefix + 'flex-positive'; } else { - return super.prefixed(...arguments); + return super.prefixed(prop, prefix); } } } diff --git a/lib/hacks/flex-shrink.js b/lib/hacks/flex-shrink.js index 96733d5b7..4b71aec3b 100644 --- a/lib/hacks/flex-shrink.js +++ b/lib/hacks/flex-shrink.js @@ -1,4 +1,4 @@ -const flexSpec = require('./flex-spec'); +const flexSpec = require('./flex-spec'); const Declaration = require('../declaration'); class FlexShrink extends Declaration { @@ -6,29 +6,36 @@ class FlexShrink extends Declaration { this.names = ['flex-shrink', 'flex-negative']; } - // Return property name by final spec + /** + * Return property name by final spec + */ normalize() { return 'flex-shrink'; } - // Return flex property for 2012 spec + /** + * Return flex property for 2012 spec + */ prefixed(prop, prefix) { let spec; - [spec, prefix] = Array.from(flexSpec(prefix)); + [spec, prefix] = flexSpec(prefix); if (spec === 2012) { return prefix + 'flex-negative'; } else { - return super.prefixed(...arguments); + return super.prefixed(prop, prefix); } } - // Ignore 2009 spec and use flex property for 2012 + /** + * Ignore 2009 spec and use flex property for 2012 + */ set(decl, prefix) { let spec; - [spec, prefix] = Array.from(flexSpec(prefix)); + [spec, prefix] = flexSpec(prefix); if (spec === 2012 || spec === 'final') { - return super.set(...arguments); + return super.set(decl, prefix); } + return undefined; } } FlexShrink.initClass(); diff --git a/lib/hacks/flex-spec.js b/lib/hacks/flex-spec.js index 49e07cf8c..f9cfe150c 100644 --- a/lib/hacks/flex-spec.js +++ b/lib/hacks/flex-spec.js @@ -1,14 +1,16 @@ -// Return flexbox spec versions by prefix +/** + * Return flexbox spec versions by prefix + */ module.exports = function (prefix) { - const spec = (() => { - if (prefix === '-webkit- 2009' || prefix === '-moz-') { - return 2009; - } else if (prefix === '-ms-') { - return 2012; - } else if (prefix === '-webkit-') { - return 'final'; - } - })(); + let spec; + if (prefix === '-webkit- 2009' || prefix === '-moz-') { + spec = 2009; + } else if (prefix === '-ms-') { + spec = 2012; + } else if (prefix === '-webkit-') { + spec = 'final'; + } + if (prefix === '-webkit- 2009') { prefix = '-webkit-'; } diff --git a/lib/hacks/flex-values.js b/lib/hacks/flex-values.js index 34ade9397..205d303b4 100644 --- a/lib/hacks/flex-values.js +++ b/lib/hacks/flex-values.js @@ -1,22 +1,28 @@ const OldValue = require('../old-value'); -const Value = require('../value'); +const Value = require('../value'); class FlexValues extends Value { static initClass() { this.names = ['flex', 'flex-grow', 'flex-shrink', 'flex-basis']; } - // Return prefixed property name + /** + * Return prefixed property name + */ prefixed(prefix) { return this.all.prefixed(this.name, prefix); } - // Change property name to prefixed property name + /** + * Change property name to prefixed property name + */ replace(string, prefix) { return string.replace(this.regexp(), `$1${this.prefixed(prefix)}$3`); } - // Return function to fast prefixed property name + /** + * Return function to fast prefixed property name + */ old(prefix) { return new OldValue(this.name, this.prefixed(prefix)); } diff --git a/lib/hacks/flex-wrap.js b/lib/hacks/flex-wrap.js index 5df94f7b4..04ee7b524 100644 --- a/lib/hacks/flex-wrap.js +++ b/lib/hacks/flex-wrap.js @@ -1,4 +1,4 @@ -const flexSpec = require('./flex-spec'); +const flexSpec = require('./flex-spec'); const Declaration = require('../declaration'); class FlexWrap extends Declaration { @@ -6,12 +6,15 @@ class FlexWrap extends Declaration { this.names = ['flex-wrap']; } - // Don't add prefix for 2009 spec + /** + * Don't add prefix for 2009 spec + */ set(decl, prefix) { const spec = flexSpec(prefix)[0]; if (spec !== 2009) { - return super.set(...arguments); + return super.set(decl, prefix); } + return undefined; } } FlexWrap.initClass(); diff --git a/lib/hacks/flex.js b/lib/hacks/flex.js index a1580b535..8ac690e95 100644 --- a/lib/hacks/flex.js +++ b/lib/hacks/flex.js @@ -1,4 +1,4 @@ -const flexSpec = require('./flex-spec'); +const flexSpec = require('./flex-spec'); const Declaration = require('../declaration'); const list = require('postcss/lib/list'); @@ -13,24 +13,30 @@ class Flex extends Declaration { }; } - // Change property name for 2009 spec + /** + * Change property name for 2009 spec + */ prefixed(prop, prefix) { let spec; - [spec, prefix] = Array.from(flexSpec(prefix)); + [spec, prefix] = flexSpec(prefix); if (spec === 2009) { return prefix + 'box-flex'; } else { - return super.prefixed(...arguments); + return super.prefixed(prop, prefix); } } - // Return property name by final spec + /** + * Return property name by final spec + */ normalize() { return 'flex'; } - // Spec 2009 supports only first argument - // Spec 2012 disallows unitless basis + /** + * Spec 2009 supports only first argument + * Spec 2012 disallows unitless basis + */ set(decl, prefix) { const spec = flexSpec(prefix)[0]; if (spec === 2009) { @@ -42,10 +48,8 @@ class Flex extends Declaration { if (components.length === 3 && components[2] === '0') { decl.value = components.slice(0, 2).concat('0px').join(' '); } - return super.set(decl, prefix); - } else { - return super.set(...arguments); } + return super.set(decl, prefix); } } Flex.initClass(); diff --git a/lib/hacks/fullscreen.js b/lib/hacks/fullscreen.js index d475909fd..ea5a40402 100644 --- a/lib/hacks/fullscreen.js +++ b/lib/hacks/fullscreen.js @@ -5,14 +5,16 @@ class Fullscreen extends Selector { this.names = [':fullscreen']; } - // Return different selectors depend on prefix + /** + * Return different selectors depend on prefix + */ prefixed(prefix) { if (prefix === '-webkit-') { return ':-webkit-full-screen'; } else if (prefix === '-moz-') { return ':-moz-full-screen'; } else { - return `:${ prefix }fullscreen`; + return `:${prefix}fullscreen`; } } } diff --git a/lib/hacks/gradient.js b/lib/hacks/gradient.js index 327486491..a7cab23c4 100644 --- a/lib/hacks/gradient.js +++ b/lib/hacks/gradient.js @@ -1,55 +1,58 @@ const OldValue = require('../old-value'); -const Value = require('../value'); -const utils = require('../utils'); +const Value = require('../value'); +const utils = require('../utils'); const parser = require('postcss-value-parser'); -const range = require('normalize-range'); -const list = require('postcss/lib/list'); +const range = require('normalize-range'); const isDirection = /top|left|right|bottom/gi; class Gradient extends Value { static initClass() { - this.names = ['linear-gradient', 'repeating-linear-gradient', - 'radial-gradient', 'repeating-radial-gradient']; + this.names = [ + 'linear-gradient', 'repeating-linear-gradient', + 'radial-gradient', 'repeating-radial-gradient' + ]; - // Direction to replace + // Direction to replace this.prototype.directions = { - top: 'bottom', - left: 'right', + top: 'bottom', + left: 'right', bottom: 'top', - right: 'left' + right: 'left' }; - // Direction to replace + // Direction to replace this.prototype.oldDirections = { - 'top': 'left bottom, left top', - 'left': 'right top, left top', + 'top': 'left bottom, left top', + 'left': 'right top, left top', 'bottom': 'left top, left bottom', - 'right': 'left top, right top', + 'right': 'left top, right top', - 'top right': 'left bottom, right top', - 'top left': 'right bottom, left top', - 'right top': 'left bottom, right top', + 'top right': 'left bottom, right top', + 'top left': 'right bottom, left top', + 'right top': 'left bottom, right top', 'right bottom': 'left top, right bottom', 'bottom right': 'left top, right bottom', - 'bottom left': 'right top, left bottom', - 'left top': 'right bottom, left top', - 'left bottom': 'right top, left bottom' + 'bottom left': 'right top, left bottom', + 'left top': 'right bottom, left top', + 'left bottom': 'right top, left bottom' }; } - // Change degrees for webkit prefix + /** + * Change degrees for webkit prefix + */ replace(string, prefix) { const ast = parser(string); - for (let node of ast.nodes) { + for (const node of ast.nodes) { if (node.type === 'function' && node.value === this.name) { node.nodes = this.newDirection(node.nodes); node.nodes = this.normalize(node.nodes); if (prefix === '-webkit- old') { const changes = this.oldWebkit(node); if (!changes) { - return; + return undefined; } } else { node.nodes = this.convertDirection(node.nodes); @@ -60,7 +63,9 @@ class Gradient extends Value { return ast.toString(); } - // Replace first token + /** + * Replace first token + */ replaceFirst(params, ...words) { const prefix = words.map((i) => { if (i === ' ') { @@ -72,14 +77,18 @@ class Gradient extends Value { return prefix.concat(params.slice(1)); } - // Convert angle unit to deg + /** + * Convert angle unit to deg + */ normalizeUnit(str, full) { const num = parseFloat(str); const deg = num / full * 360; - return `${ deg }deg`; + return `${deg}deg`; } - // Normalize angle + /** + * Normalize angle + */ normalize(nodes) { if (!nodes[0]) { return nodes; @@ -110,7 +119,9 @@ class Gradient extends Value { return nodes; } - // Replace old direction to new + /** + * Replace old direction to new + */ newDirection(params) { if (params[0].value === 'to') { return params; @@ -118,8 +129,16 @@ class Gradient extends Value { if (!isDirection.test(params[0].value)) { return params; } - params.unshift({ type: 'word', value: 'to' }, { type: 'space', value: ' ' }); - for (let i = 2, end = params.length, asc = end >= 2; asc ? i < end : i > end; asc ? i++ : i--) { + + params.unshift({ + type: 'word', + value: 'to' + }, { + type: 'space', + value: ' ' + }); + + for (let i = 2; i < params.length; i++) { if (params[i].type === 'div') { break; } @@ -131,7 +150,9 @@ class Gradient extends Value { return params; } - // Change new direction to old + /** + * Change new direction to old + */ convertDirection(params) { if (params.length > 0) { if (params[0].value === 'to') { @@ -145,42 +166,42 @@ class Gradient extends Value { return params; } - // Replace `to top left` to `bottom right` + /** + * Replace `to top left` to `bottom right` + */ fixDirection(params) { params.splice(0, 2); - return (() => { - const result = []; - for (let i = 0, end = params.length, asc = end >= 0; asc ? i < end : i > end; asc ? i++ : i--) { - let item; - if (params[i].type === 'div') { - break; - } - if (params[i].type === 'word') { - item = params[i].value = this.revertDirection(params[i].value); - } - result.push(item); + + for (const param of params) { + if (param.type === 'div') { + break; + } + if (param.type === 'word') { + param.value = this.revertDirection(param.value); } - return result; - })(); + } } - // Add 90 degrees + /** + * Add 90 degrees + */ fixAngle(params) { let first = params[0].value; first = parseFloat(first); first = Math.abs(450 - first) % 360; first = this.roundFloat(first, 3); - return params[0].value = `${first}deg`; + params[0].value = `${first}deg`; } - // Fix radial direction syntax + /** + * Fix radial direction syntax + */ fixRadial(params) { - let i; - const first = params[0]; + const first = params[0]; const second = []; + let i; - for (i = 4, end = params.length, asc = end >= 4; asc ? i < end : i > end; asc ? i++ : i--) { - var asc, end; + for (i = 4; i < params.length; i++) { if (params[i].type === 'div') { break; } else { @@ -188,21 +209,25 @@ class Gradient extends Value { } } - return params.splice(0, i, ...Array.from(second), params[i + 2], first); + params.splice(0, i, ...second, params[i + 2], first); } revertDirection(word) { return this.directions[word.toLowerCase()] || word; } - // Round float and save digits under dot + /** + * Round float and save digits under dot + */ roundFloat(float, digits) { return parseFloat(float.toFixed(digits)); } - // Convert to old webkit syntax + /** + * Convert to old webkit syntax + */ oldWebkit(node) { - const { nodes } = node; + const { nodes } = node; const string = parser.stringify(node.nodes); if (this.name !== 'linear-gradient') { @@ -217,12 +242,12 @@ class Gradient extends Value { if (string.indexOf('-corner') !== -1) { return false; } - if (string.indexOf('-side') !== -1) { + if (string.indexOf('-side') !== -1) { return false; } const params = [[]]; - for (let i of nodes) { + for (const i of nodes) { params[params.length - 1].push(i); if (i.type === 'div' && i.value === ',') { params.push([]); @@ -233,7 +258,7 @@ class Gradient extends Value { this.colorStops(params); node.nodes = []; - for (let param of params) { + for (const param of params) { node.nodes = node.nodes.concat(param); } @@ -243,12 +268,17 @@ class Gradient extends Value { return true; } - // Change direction syntax to old webkit + /** + * Change direction syntax to old webkit + */ oldDirection(params) { const div = this.cloneDiv(params[0]); if (params[0][0].value !== 'to') { - return params.unshift([{ type: 'word', value: this.oldDirections.bottom }, div]); + return params.unshift([ + { type: 'word', value: this.oldDirections.bottom }, + div + ]); } else { let words = []; @@ -259,13 +289,16 @@ class Gradient extends Value { } words = words.join(' '); - const old = this.oldDirections[words] || words; + const old = this.oldDirections[words] || words; - return params[0] = [{ type: 'word', value: old }, div]; + params[0] = [{ type: 'word', value: old }, div]; + return params[0]; } } - // Get div token from exists parameters + /** + * Get div token from exists parameters + */ cloneDiv(params) { for (let i of params) { if (i.type === 'div' && i.value === ',') { @@ -275,72 +308,81 @@ class Gradient extends Value { return { type: 'div', value: ',', after: ' ' }; } - // Change colors syntax to old webkit + /** + * Change colors syntax to old webkit + */ colorStops(params) { - return (() => { - const result = []; - for (let i = 0; i < params.length; i++) { - var pos; - const param = params[i]; - let item; - if (i === 0) { - continue; - } + const result = []; + for (let i = 0; i < params.length; i++) { + let pos; + const param = params[i]; + let item; + if (i === 0) { + continue; + } - const color = parser.stringify(param[0]); - if (param[1] && param[1].type === 'word') { - pos = param[1].value; - } else if (param[2] && param[2].type === 'word') { - pos = param[2].value; - } + const color = parser.stringify(param[0]); + if (param[1] && param[1].type === 'word') { + pos = param[1].value; + } else if (param[2] && param[2].type === 'word') { + pos = param[2].value; + } - const stop = i === 1 && (!pos || pos === '0%') ? - `from(${color})` : - i === params.length - 1 && (!pos || pos === '100%') ? - `to(${color})` : - pos ? - `color-stop(${pos}, ${color})` : - `color-stop(${color})`; - - const div = param[param.length - 1]; - params[i] = [{ type: 'word', value: stop }]; - if (div.type === 'div' && div.value === ',') { - item = params[i].push(div); - } - result.push(item); + let stop; + if (i === 1 && (!pos || pos === '0%')) { + stop = `from(${color})`; + } else if (i === params.length - 1 && (!pos || pos === '100%')) { + stop = `to(${color})`; + } else if (pos) { + stop = `color-stop(${pos}, ${color})`; + } else { + stop = `color-stop(${color})`; } - return result; - })(); + + const div = param[param.length - 1]; + params[i] = [{ type: 'word', value: stop }]; + if (div.type === 'div' && div.value === ',') { + item = params[i].push(div); + } + result.push(item); + } + return result; } - // Remove old WebKit gradient too + /** + * Remove old WebKit gradient too + */ old(prefix) { if (prefix === '-webkit-') { - const type = this.name === 'linear-gradient' ? 'linear' : 'radial'; + const type = this.name === 'linear-gradient' ? 'linear' : 'radial'; const string = '-gradient'; const regexp = utils.regexp( - `-webkit-(${type}-gradient|gradient\\(\\s*${type})`, false); + `-webkit-(${type}-gradient|gradient\\(\\s*${type})`, false + ); return new OldValue(this.name, prefix + this.name, string, regexp); } else { - return super.old(...arguments); + return super.old(prefix); } } - // Do not add non-webkit prefixes for list-style and object + /** + * Do not add non-webkit prefixes for list-style and object + */ add(decl, prefix) { const p = decl.prop; if (p.indexOf('mask') !== -1) { if (prefix === '-webkit-' || prefix === '-webkit- old') { - return super.add(...arguments); + return super.add(decl, prefix); } } else if (p === 'list-style' || p === 'list-style-image' || p === 'content') { if (prefix === '-webkit-' || prefix === '-webkit- old') { - return super.add(...arguments); + return super.add(decl, prefix); } } else { - return super.add(...arguments); + return super.add(decl, prefix); } + return undefined; } } Gradient.initClass(); diff --git a/lib/hacks/grid-end.js b/lib/hacks/grid-end.js index 74c22d3e5..5e3a82ac0 100644 --- a/lib/hacks/grid-end.js +++ b/lib/hacks/grid-end.js @@ -2,21 +2,29 @@ const Declaration = require('../declaration'); class GridEnd extends Declaration { static initClass() { - this.names = ['grid-row-end', 'grid-column-end', - 'grid-row-span', 'grid-column-span']; + this.names = [ + 'grid-row-end', 'grid-column-end', + 'grid-row-span', 'grid-column-span' + ]; } - // Do not add prefix for unsupported value in IE + /** + * Do not add prefix for unsupported value in IE + */ check(decl) { return decl.value.indexOf('span') !== -1; } - // Return a final spec property + /** + * Return a final spec property + */ normalize(prop) { return prop.replace(/(-span|-end)/, ''); } - // Change property name for IE + /** + * Change property name for IE + */ prefixed(prop, prefix) { if (prefix === '-ms-') { return prefix + prop.replace('-end', '-span'); @@ -25,7 +33,9 @@ class GridEnd extends Declaration { } } - // Change repeating syntax for IE + /** + * Change repeating syntax for IE + */ set(decl, prefix) { if (prefix === '-ms-') { decl.value = decl.value.replace(/span\s/i, ''); diff --git a/lib/hacks/grid-row-align.js b/lib/hacks/grid-row-align.js index 45ba5cab2..168e69bff 100644 --- a/lib/hacks/grid-row-align.js +++ b/lib/hacks/grid-row-align.js @@ -5,18 +5,24 @@ class GridRowAlign extends Declaration { this.names = ['grid-row-align']; } - // Do not prefix flexbox values + /** + * Do not prefix flexbox values + */ check(decl) { return decl.value.indexOf('flex-') === -1 && decl.value !== 'baseline'; } - // Change property name for IE + /** + * Change property name for IE + */ prefixed(prop, prefix) { return prefix + 'grid-row-align'; } - // Change IE property back - normalize(prop) { + /** + * Change IE property back + */ + normalize() { return 'align-self'; } } diff --git a/lib/hacks/grid-start.js b/lib/hacks/grid-start.js index 287d64360..332f5b132 100644 --- a/lib/hacks/grid-start.js +++ b/lib/hacks/grid-start.js @@ -2,20 +2,29 @@ const Declaration = require('../declaration'); class GridStart extends Declaration { static initClass() { - this.names = ['grid-row-start', 'grid-column-start', 'grid-row', 'grid-column']; + this.names = [ + 'grid-row-start', 'grid-column-start', 'grid-row', 'grid-column' + ]; } - // Do not add prefix for unsupported value in IE + /** + * Do not add prefix for unsupported value in IE + */ check(decl) { - return decl.value.indexOf('/') === -1 || decl.value.indexOf('span') !== -1; + return decl.value.indexOf('/') === -1 || + decl.value.indexOf('span') !== -1; } - // Return a final spec property + /** + * Return a final spec property + */ normalize(prop) { return prop.replace('-start', ''); } - // Change property name for IE + /** + * Change property name for IE + */ prefixed(prop, prefix) { if (prefix === '-ms-') { return prefix + prop.replace('-start', ''); @@ -24,16 +33,23 @@ class GridStart extends Declaration { } } - // Split one value to two + /** + * Split one value to two + */ insert(decl, prefix, prefixes) { const parts = this.splitValue(decl, prefix); if (parts.length === 2) { - decl.cloneBefore({ prop: `-ms-${decl.prop}-span`, value: parts[1] }); + decl.cloneBefore({ + prop: `-ms-${decl.prop}-span`, + value: parts[1] + }); } return super.insert(decl, prefix, prefixes); } - // Change value for combine property + /** + * Change value for combine property + */ set(decl, prefix) { const parts = this.splitValue(decl, prefix); if (parts.length === 2) { @@ -42,7 +58,9 @@ class GridStart extends Declaration { return super.set(decl, prefix); } - // If property contains start and end + /** + * If property contains start and end + */ splitValue(decl, prefix) { if (prefix === '-ms-' && decl.prop.indexOf('-start') === -1) { const parts = decl.value.split(/\s*\/\s*span\s+/); diff --git a/lib/hacks/grid-template.js b/lib/hacks/grid-template.js index 1e3111e59..687c2f8c8 100644 --- a/lib/hacks/grid-template.js +++ b/lib/hacks/grid-template.js @@ -4,11 +4,15 @@ const Declaration = require('../declaration'); class GridTemplate extends Declaration { static initClass() { - this.names = ['grid-template-rows', 'grid-template-columns', - 'grid-rows', 'grid-columns']; + this.names = [ + 'grid-template-rows', 'grid-template-columns', + 'grid-rows', 'grid-columns' + ]; } - // Change property name for IE + /** + * Change property name for IE + */ prefixed(prop, prefix) { if (prefix === '-ms-') { return prefix + prop.replace('template-', ''); @@ -17,15 +21,19 @@ class GridTemplate extends Declaration { } } - // Change IE property back + /** + * Change IE property back + */ normalize(prop) { return prop.replace(/^grid-(rows|columns)/, 'grid-template-$1'); } - // Recursive part of changeRepeat + /** + * Recursive part of changeRepeat + */ walkRepeat(node) { const fixed = []; - for (let i of node.nodes) { + for (const i of node.nodes) { if (i.nodes) { this.walkRepeat(i); } @@ -36,21 +44,25 @@ class GridTemplate extends Declaration { const count = first.value; i.nodes.shift(); i.value = ''; - fixed.push({ type: 'word', value: `[${ count }]` }); + fixed.push({ type: 'word', value: `[${count}]` }); } } } - return node.nodes = fixed; + node.nodes = fixed; } - // IE repeating syntax + /** + * IE repeating syntax + */ changeRepeat(value) { const ast = parser(value); this.walkRepeat(ast); return ast.toString(); } - // Change repeating syntax for IE + /** + * Change repeating syntax for IE + */ set(decl, prefix) { if (prefix === '-ms-' && decl.value.indexOf('repeat(') !== -1) { decl.value = this.changeRepeat(decl.value); diff --git a/lib/hacks/image-rendering.js b/lib/hacks/image-rendering.js index 23829b8a8..a884c2f56 100644 --- a/lib/hacks/image-rendering.js +++ b/lib/hacks/image-rendering.js @@ -5,39 +5,49 @@ class ImageRendering extends Declaration { this.names = ['image-rendering', 'interpolation-mode']; } - // Add hack only for crisp-edges + /** + * Add hack only for crisp-edges + */ check(decl) { return decl.value === 'pixelated'; } - // Change property name for IE + /** + * Change property name for IE + */ prefixed(prop, prefix) { if (prefix === '-ms-') { return '-ms-interpolation-mode'; } else { - return super.prefixed(...arguments); + return super.prefixed(prop, prefix); } } - // Change property and value for IE + /** + * Change property and value for IE + */ set(decl, prefix) { if (prefix === '-ms-') { - decl.prop = '-ms-interpolation-mode'; + decl.prop = '-ms-interpolation-mode'; decl.value = 'nearest-neighbor'; return decl; } else { - return super.set(...arguments); + return super.set(decl, prefix); } } - // Return property name by spec - normalize(prop) { + /** + * Return property name by spec + */ + normalize() { return 'image-rendering'; } - // Warn on old value + /** + * Warn on old value + */ process(node, result) { - return super.process(...arguments); + return super.process(node, result); } } ImageRendering.initClass(); diff --git a/lib/hacks/image-set.js b/lib/hacks/image-set.js index 7af7bf0db..a16ec7c25 100644 --- a/lib/hacks/image-set.js +++ b/lib/hacks/image-set.js @@ -1,5 +1,3 @@ -const list = require('postcss/lib/list'); - const Value = require('../value'); class ImageSet extends Value { @@ -7,12 +5,15 @@ class ImageSet extends Value { this.names = ['image-set']; } - // Use non-standard name for WebKit and Firefox + /** + * Use non-standard name for WebKit and Firefox + */ replace(string, prefix) { if (prefix === '-webkit-') { - return super.replace(...arguments).replace(/("[^"]+"|'[^']+')(\s+\d+\w)/gi, 'url($1)$2'); + return super.replace(string, prefix) + .replace(/("[^"]+"|'[^']+')(\s+\d+\w)/gi, 'url($1)$2'); } else { - return super.replace(...arguments); + return super.replace(string, prefix); } } } diff --git a/lib/hacks/inline-logical.js b/lib/hacks/inline-logical.js index 79202c942..62bc20922 100644 --- a/lib/hacks/inline-logical.js +++ b/lib/hacks/inline-logical.js @@ -2,22 +2,30 @@ const Declaration = require('../declaration'); class InlineLogical extends Declaration { static initClass() { - this.names = ['border-inline-start', 'border-inline-end', - 'margin-inline-start', 'margin-inline-end', + this.names = [ + 'border-inline-start', 'border-inline-end', + 'margin-inline-start', 'margin-inline-end', 'padding-inline-start', 'padding-inline-end', 'border-start', 'border-end', 'margin-start', 'margin-end', - 'padding-start', 'padding-end']; + 'padding-start', 'padding-end' + ]; } - // Use old syntax for -moz- and -webkit- + /** + * Use old syntax for -moz- and -webkit- + */ prefixed(prop, prefix) { return prefix + prop.replace('-inline', ''); } - // Return property name by spec + /** + * Return property name by spec + */ normalize(prop) { - return prop.replace(/(margin|padding|border)-(start|end)/, '$1-inline-$2'); + return prop.replace( + /(margin|padding|border)-(start|end)/, '$1-inline-$2' + ); } } InlineLogical.initClass(); diff --git a/lib/hacks/justify-content.js b/lib/hacks/justify-content.js index a0c54fd61..33fa06be4 100644 --- a/lib/hacks/justify-content.js +++ b/lib/hacks/justify-content.js @@ -1,4 +1,4 @@ -const flexSpec = require('./flex-spec'); +const flexSpec = require('./flex-spec'); const Declaration = require('../declaration'); class JustifyContent extends Declaration { @@ -6,32 +6,38 @@ class JustifyContent extends Declaration { this.names = ['justify-content', 'flex-pack', 'box-pack']; this.oldValues = { - 'flex-end': 'end', - 'flex-start': 'start', + 'flex-end': 'end', + 'flex-start': 'start', 'space-between': 'justify', - 'space-around': 'distribute' + 'space-around': 'distribute' }; } - // Change property name for 2009 and 2012 specs + /** + * Change property name for 2009 and 2012 specs + */ prefixed(prop, prefix) { let spec; - [spec, prefix] = Array.from(flexSpec(prefix)); + [spec, prefix] = flexSpec(prefix); if (spec === 2009) { return prefix + 'box-pack'; } else if (spec === 2012) { return prefix + 'flex-pack'; } else { - return super.prefixed(...arguments); + return super.prefixed(prop, prefix); } } - // Return property name by final spec - normalize(prop) { + /** + * Return property name by final spec + */ + normalize() { return 'justify-content'; } - // Change value for 2009 and 2012 specs + /** + * Change value for 2009 and 2012 specs + */ set(decl, prefix) { const spec = flexSpec(prefix)[0]; if (spec === 2009 || spec === 2012) { @@ -41,8 +47,9 @@ class JustifyContent extends Declaration { return super.set(decl, prefix); } } else if (spec === 'final') { - return super.set(...arguments); + return super.set(decl, prefix); } + return undefined; } } JustifyContent.initClass(); diff --git a/lib/hacks/justify-items.js b/lib/hacks/justify-items.js index d80d8b157..56bb34aed 100644 --- a/lib/hacks/justify-items.js +++ b/lib/hacks/justify-items.js @@ -5,15 +5,17 @@ class JustifyItems extends Declaration { this.names = ['justify-items', 'grid-column-align']; } - // Change property name for IE + /** + * Change property name for IE + */ prefixed(prop, prefix) { - return prefix + (prefix === '-ms-' ? - 'grid-column-align' : - prop); + return prefix + (prefix === '-ms-' ? 'grid-column-align' : prop); } - // Change IE property back - normalize(prop) { + /** + * Change IE property back + */ + normalize() { return 'justify-items'; } } diff --git a/lib/hacks/mask-border.js b/lib/hacks/mask-border.js index 0deb29cef..276321797 100644 --- a/lib/hacks/mask-border.js +++ b/lib/hacks/mask-border.js @@ -2,25 +2,31 @@ const Declaration = require('../declaration'); class MaskBorder extends Declaration { static initClass() { - this.names = ['mask-border', 'mask-border-source', - 'mask-border-slice', 'mask-border-width', + this.names = [ + 'mask-border', 'mask-border-source', + 'mask-border-slice', 'mask-border-width', 'mask-border-outset', 'mask-border-repeat', - 'mask-box-image', 'mask-box-image-source', - 'mask-box-image-slice', 'mask-box-image-width', - 'mask-box-image-outset', 'mask-box-image-repeat']; + 'mask-box-image', 'mask-box-image-source', + 'mask-box-image-slice', 'mask-box-image-width', + 'mask-box-image-outset', 'mask-box-image-repeat' + ]; } - // Return property name by final spec + /** + * Return property name by final spec + */ normalize() { return this.name.replace('box-image', 'border'); } - // Return flex property for 2012 spec + /** + * Return flex property for 2012 spec + */ prefixed(prop, prefix) { if (prefix === '-webkit-') { - return super.prefixed(...arguments).replace('border', 'box-image'); + return super.prefixed(prop, prefix).replace('border', 'box-image'); } else { - return super.prefixed(...arguments); + return super.prefixed(prop, prefix); } } } diff --git a/lib/hacks/order.js b/lib/hacks/order.js index 24a8a6314..8ee5b5fa3 100644 --- a/lib/hacks/order.js +++ b/lib/hacks/order.js @@ -1,4 +1,4 @@ -const flexSpec = require('./flex-spec'); +const flexSpec = require('./flex-spec'); const Declaration = require('../declaration'); class Order extends Declaration { @@ -6,32 +6,38 @@ class Order extends Declaration { this.names = ['order', 'flex-order', 'box-ordinal-group']; } - // Change property name for 2009 and 2012 specs + /** + * Change property name for 2009 and 2012 specs + */ prefixed(prop, prefix) { let spec; - [spec, prefix] = Array.from(flexSpec(prefix)); + [spec, prefix] = flexSpec(prefix); if (spec === 2009) { return prefix + 'box-ordinal-group'; } else if (spec === 2012) { return prefix + 'flex-order'; } else { - return super.prefixed(...arguments); + return super.prefixed(prop, prefix); } } - // Return property name by final spec - normalize(prop) { + /** + * Return property name by final spec + */ + normalize() { return 'order'; } - // Fix value for 2009 spec + /** + * Fix value for 2009 spec + */ set(decl, prefix) { const spec = flexSpec(prefix)[0]; if (spec === 2009 && /\d/.test(decl.value)) { decl.value = (parseInt(decl.value) + 1).toString(); return super.set(decl, prefix); } else { - return super.set(...arguments); + return super.set(decl, prefix); } } } diff --git a/lib/hacks/pixelated.js b/lib/hacks/pixelated.js index 545af85b7..80c156717 100644 --- a/lib/hacks/pixelated.js +++ b/lib/hacks/pixelated.js @@ -1,30 +1,34 @@ const OldValue = require('../old-value'); -const Value = require('../value'); +const Value = require('../value'); class Pixelated extends Value { static initClass() { this.names = ['pixelated']; } - // Use non-standard name for WebKit and Firefox + /** + * Use non-standard name for WebKit and Firefox + */ replace(string, prefix) { if (prefix === '-webkit-') { return string.replace(this.regexp(), '$1-webkit-optimize-contrast'); } else if (prefix === '-moz-') { return string.replace(this.regexp(), '$1-moz-crisp-edges'); } else { - return super.replace(...arguments); + return super.replace(string, prefix); } } - // Different name for WebKit and Firefox + /** + * Different name for WebKit and Firefox + */ old(prefix) { if (prefix === '-webkit-') { return new OldValue(this.name, '-webkit-optimize-contrast'); } else if (prefix === '-moz-') { return new OldValue(this.name, '-moz-crisp-edges'); } else { - return super.old(...arguments); + return super.old(prefix); } } } diff --git a/lib/hacks/placeholder.js b/lib/hacks/placeholder.js index 062a683ab..3dce27973 100644 --- a/lib/hacks/placeholder.js +++ b/lib/hacks/placeholder.js @@ -5,12 +5,16 @@ class Placeholder extends Selector { this.names = [':placeholder-shown', '::placeholder']; } - // Add old mozilla to possible prefixes + /** + * Add old mozilla to possible prefixes + */ possible() { - return super.possible(...arguments).concat('-moz- old'); + return super.possible().concat('-moz- old'); } - // Return different selectors depend on prefix + /** + * Return different selectors depend on prefix + */ prefixed(prefix) { if (prefix === '-webkit-') { return '::-webkit-input-placeholder'; @@ -19,7 +23,7 @@ class Placeholder extends Selector { } else if (prefix === '-moz- old') { return ':-moz-placeholder'; } else { - return `::${ prefix }placeholder`; + return `::${prefix}placeholder`; } } } diff --git a/lib/hacks/stretch.js b/lib/hacks/stretch.js index 79be2ccae..395b23f7a 100644 --- a/lib/hacks/stretch.js +++ b/lib/hacks/stretch.js @@ -1,30 +1,34 @@ const OldValue = require('../old-value'); -const Value = require('../value'); +const Value = require('../value'); class Stretch extends Value { static initClass() { this.names = ['stretch', 'fill', 'fill-available']; } - // Different prefix for WebKit and Firefox + /** + * Different prefix for WebKit and Firefox + */ replace(string, prefix) { if (prefix === '-moz-') { return string.replace(this.regexp(), '$1-moz-available$3'); } else if (prefix === '-webkit-') { return string.replace(this.regexp(), '$1-webkit-fill-available$3'); } else { - return super.replace(...arguments); + return super.replace(string, prefix); } } - // Different name for WebKit and Firefox + /** + * Different name for WebKit and Firefox + */ old(prefix) { if (prefix === '-moz-') { return new OldValue(this.name, '-moz-available'); } else if (prefix === '-webkit-') { return new OldValue(this.name, '-webkit-fill-available'); } else { - return super.old(...arguments); + return super.old(prefix); } } } diff --git a/lib/hacks/text-emphasis-position.js b/lib/hacks/text-emphasis-position.js index 69d6c6006..b7dafff35 100644 --- a/lib/hacks/text-emphasis-position.js +++ b/lib/hacks/text-emphasis-position.js @@ -10,7 +10,7 @@ class TextEmphasisPosition extends Declaration { decl.value = decl.value.replace(/\s*(right|left)\s*/i, ''); return super.set(decl, prefix); } else { - return super.set(...arguments); + return super.set(decl, prefix); } } } diff --git a/lib/hacks/transform-decl.js b/lib/hacks/transform-decl.js index bffd3e833..ad6f70704 100644 --- a/lib/hacks/transform-decl.js +++ b/lib/hacks/transform-decl.js @@ -4,11 +4,15 @@ class TransformDecl extends Declaration { static initClass() { this.names = ['transform', 'transform-origin']; - this.functions3d = ['matrix3d', 'translate3d', 'translateZ', 'scale3d', 'scaleZ', - 'rotate3d', 'rotateX', 'rotateY', 'perspective']; + this.functions3d = [ + 'matrix3d', 'translate3d', 'translateZ', 'scale3d', 'scaleZ', + 'rotate3d', 'rotateX', 'rotateY', 'perspective' + ]; } - // Recursively check all parents for @keyframes + /** + * Recursively check all parents for @keyframes + */ keyframeParents(decl) { let { parent } = decl; while (parent) { @@ -20,14 +24,16 @@ class TransformDecl extends Declaration { return false; } - // Is transform caontain 3D commands + /** + * Is transform caontain 3D commands + */ contain3d(decl) { if (decl.prop === 'transform-origin') { return false; } for (let func of TransformDecl.functions3d) { - if (decl.value.indexOf(`${ func }(`) !== -1) { + if (decl.value.indexOf(`${func}(`) !== -1) { return true; } } @@ -35,28 +41,33 @@ class TransformDecl extends Declaration { return false; } - // Replace rotateZ to rotate for IE 9 + /** + * Replace rotateZ to rotate for IE 9 + */ set(decl, prefix) { - decl = super.set(...arguments); + decl = super.set(decl, prefix); if (prefix === '-ms-') { decl.value = decl.value.replace(/rotateZ/gi, 'rotate'); } return decl; } - // Don't add prefix for IE in keyframes + /** + * Don't add prefix for IE in keyframes + */ insert(decl, prefix, prefixes) { if (prefix === '-ms-') { if (!this.contain3d(decl) && !this.keyframeParents(decl)) { - return super.insert(...arguments); + return super.insert(decl, prefix, prefixes); } } else if (prefix === '-o-') { if (!this.contain3d(decl)) { - return super.insert(...arguments); + return super.insert(decl, prefix, prefixes); } } else { - return super.insert(...arguments); + return super.insert(decl, prefix, prefixes); } + return undefined; } } TransformDecl.initClass(); diff --git a/lib/hacks/writing-mode.js b/lib/hacks/writing-mode.js index 5978462a1..a7dec313e 100644 --- a/lib/hacks/writing-mode.js +++ b/lib/hacks/writing-mode.js @@ -6,8 +6,8 @@ class WritingMode extends Declaration { this.msValues = { 'horizontal-tb': 'lr-tb', - 'vertical-rl': 'tb-rl', - 'vertical-lr': 'tb-lr' + 'vertical-rl': 'tb-rl', + 'vertical-lr': 'tb-lr' }; } @@ -16,7 +16,7 @@ class WritingMode extends Declaration { decl.value = WritingMode.msValues[decl.value] || decl.value; return super.set(decl, prefix); } else { - return super.set(...arguments); + return super.set(decl, prefix); } } } diff --git a/lib/info.js b/lib/info.js index 894560384..65d009d3b 100644 --- a/lib/info.js +++ b/lib/info.js @@ -2,34 +2,34 @@ const browserslist = require('browserslist'); const capitalize = str => str.slice(0, 1).toUpperCase() + str.slice(1); +/* eslint-disable camelcase */ const names = { - ie: 'IE', - ie_mob: 'IE Mobile', + ie: 'IE', + ie_mob: 'IE Mobile', ios_saf: 'iOS', op_mini: 'Opera Mini', - op_mob: 'Opera Mobile', + op_mob: 'Opera Mobile', and_chr: 'Chrome for Android', - and_ff: 'Firefox for Android', - and_uc: 'UC for Android' + and_ff: 'Firefox for Android', + and_uc: 'UC for Android' }; +/* eslint-enable camelcase */ const prefix = function (name, prefixes) { - let out = ` ${name}: `; - out += prefixes.map( i => i.replace(/^-(.*)-$/g, '$1')).join(', '); + let out = ` ${name}: `; + out += prefixes.map(i => i.replace(/^-(.*)-$/g, '$1')).join(', '); out += '\n'; return out; }; module.exports = function (prefixes) { - let data, name; if (prefixes.browsers.selected.length === 0) { return 'No browsers selected'; } - const versions = []; - for (var browser of prefixes.browsers.selected) { - let version; - [name, version] = Array.from(browser.split(' ')); + const versions = {}; + for (const browser of prefixes.browsers.selected) { + let [name, version] = browser.split(' '); name = names[name] || capitalize(name); if (versions[name]) { @@ -39,19 +39,20 @@ module.exports = function (prefixes) { } } - let out = 'Browsers:\n'; - for (browser in versions) { + let out = 'Browsers:\n'; + for (const browser in versions) { let list = versions[browser]; list = list.sort((a, b) => parseFloat(b) - parseFloat(a)); out += ` ${browser}: ${list.join(', ')}\n`; } + const coverage = browserslist.coverage(prefixes.browsers.selected); - const round = Math.round(coverage * 100) / 100.0; - out += `\nThese browsers account for ${ round }% of all users globally\n`; + const round = Math.round(coverage * 100) / 100.0; + out += `\nThese browsers account for ${round}% of all users globally\n`; let atrules = ''; - for (name in prefixes.add) { - data = prefixes.add[name]; + for (const name in prefixes.add) { + const data = prefixes.add[name]; if (name[0] === '@' && data.prefixes) { atrules += prefix(name, data.prefixes); } @@ -61,7 +62,7 @@ module.exports = function (prefixes) { } let selectors = ''; - for (let selector of prefixes.add.selectors) { + for (const selector of prefixes.add.selectors) { if (selector.prefixes) { selectors += prefix(selector.name, selector.prefixes); } @@ -71,9 +72,9 @@ module.exports = function (prefixes) { } let values = ''; - let props = ''; - for (name in prefixes.add) { - data = prefixes.add[name]; + let props = ''; + for (const name in prefixes.add) { + const data = prefixes.add[name]; if (name[0] !== '@' && data.prefixes) { props += prefix(name, data.prefixes); } @@ -89,7 +90,7 @@ module.exports = function (prefixes) { } } - if (props !== '') { + if (props !== '') { out += `\nProperties:\n${props}`; } if (values !== '') { @@ -98,7 +99,7 @@ module.exports = function (prefixes) { if (atrules === '' && selectors === '' && props === '' && values === '') { out += '\nAwesome! Your browsers don\'t require any vendor prefixes.' + - '\nNow you can remove Autoprefixer from build steps.'; + '\nNow you can remove Autoprefixer from build steps.'; } return out; diff --git a/lib/old-selector.js b/lib/old-selector.js index e6c94e905..05a7a5181 100644 --- a/lib/old-selector.js +++ b/lib/old-selector.js @@ -1,19 +1,20 @@ class OldSelector { - constructor(selector, prefix1) { - this.prefix = prefix1; + constructor(selector, prefix) { + this.prefix = prefix; this.prefixed = selector.prefixed(this.prefix); - this.regexp = selector.regexp(this.prefix); + this.regexp = selector.regexp(this.prefix); - this.prefixeds = []; - for (let prefix of selector.possible()) { - this.prefixeds.push([selector.prefixed(prefix), selector.regexp(prefix)]); - } + this.prefixeds = selector.possible().map( + x => [selector.prefixed(x), selector.regexp(x)] + ); this.unprefixed = selector.name; this.nameRegexp = selector.regexp(); } - // Is rule is hack without unprefixed version bottom + /** + * Is rule is hack without unprefixed version bottom + */ isHack(rule) { let index = rule.parent.index(rule) + 1; const rules = rule.parent.nodes; @@ -24,13 +25,17 @@ class OldSelector { return true; } - if (before.indexOf(this.unprefixed) !== -1 && before.match(this.nameRegexp)) { + if (before.indexOf(this.unprefixed) !== -1 && + before.match(this.nameRegexp) + ) { return false; } let some = false; - for (let [string, regexp] of this.prefixeds) { - if (before.indexOf(string) !== -1 && before.match(regexp)) { + for (const [string, regexp] of this.prefixeds) { + if (before.indexOf(string) !== -1 && + before.match(regexp) + ) { some = true; break; } @@ -46,15 +51,17 @@ class OldSelector { return true; } - // Does rule contain unnecessayr prefixed selector + /** + * Does rule contain unnecessayr prefixed selector + */ check(rule) { - if (rule.selector.indexOf(this.prefixed) === -1) { + if (rule.selector.indexOf(this.prefixed) === -1) { return false; } if (!rule.selector.match(this.regexp)) { return false; } - if (this.isHack(rule)) { + if (this.isHack(rule)) { return false; } return true; diff --git a/lib/old-value.js b/lib/old-value.js index 1430913d3..3df79bfc9 100644 --- a/lib/old-value.js +++ b/lib/old-value.js @@ -4,23 +4,18 @@ class OldValue { constructor(unprefixed, prefixed, string, regexp) { this.unprefixed = unprefixed; this.prefixed = prefixed; - this.string = string; - this.regexp = regexp; - if (!this.regexp) { - this.regexp = utils.regexp(this.prefixed); - } - if (!this.string) { - this.string = this.prefixed; - } + this.string = string || prefixed; + this.regexp = regexp || utils.regexp(prefixed); } - // Check, that value contain old value + /** + * Check, that value contain old value + */ check(value) { if (value.indexOf(this.string) !== -1) { return !!value.match(this.regexp); - } else { - return false; } + return false; } } diff --git a/lib/prefixer.js b/lib/prefixer.js index d62124671..483620946 100644 --- a/lib/prefixer.js +++ b/lib/prefixer.js @@ -1,13 +1,15 @@ const Browsers = require('./browsers'); -const utils = require('./utils'); +const utils = require('./utils'); const vendor = require('postcss/lib/vendor'); -// Recursivly clone objects -var clone = function (obj, parent) { +/** + * Recursivly clone objects + */ +const clone = function (obj, parent) { const cloned = new obj.constructor(); - for (let i of Object.keys(obj || {})) { + for (const i of Object.keys(obj || {})) { let value = obj[i]; if (i === 'parent' && typeof value === 'object') { if (parent) { @@ -18,7 +20,7 @@ var clone = function (obj, parent) { } else if (i === null) { cloned[i] = value; } else if (value instanceof Array) { - cloned[i] = value.map(i => clone(i, cloned)); + cloned[i] = value.map(x => clone(x, cloned)); } else if (i !== '_autoprefixerPrefix' && i !== '_autoprefixerValues') { if (typeof value === 'object' && value !== null) { value = clone(value, cloned); @@ -31,26 +33,34 @@ var clone = function (obj, parent) { }; class Prefixer { - // Add hack to selected names + /** + * Add hack to selected names + */ static hack(klass) { if (!this.hacks) { - this.hacks = { }; + this.hacks = {}; } - return klass.names.map((name) => - this.hacks[name] = klass); + return klass.names.map((name) => { + this.hacks[name] = klass; + return this.hacks[name]; + }); } - // Load hacks for some names + /** + * Load hacks for some names + */ static load(name, prefixes, all) { - const klass = this.hacks != null ? this.hacks[name] : undefined; - if (klass) { - return new klass(name, prefixes, all); + const Klass = this.hacks && this.hacks[name]; + if (Klass) { + return new Klass(name, prefixes, all); } else { return new this(name, prefixes, all); } } - // Clone node and clean autprefixer custom caches + /** + * Clone node and clean autprefixer custom caches + */ static clone(node, overrides) { const cloned = clone(node); for (let name in overrides) { @@ -65,49 +75,56 @@ class Prefixer { this.all = all; } - // Find prefix in node parents + /** + * Find prefix in node parents + */ parentPrefix(node) { - let prefix = node._autoprefixerPrefix != null ? - node._autoprefixerPrefix : + let prefix; - node.type === 'decl' && node.prop[0] === '-' ? - vendor.prefix(node.prop) : - - node.type === 'root' ? - false : - - node.type === 'rule' && - node.selector.indexOf(':-') !== -1 && /:(-\w+-)/.test(node.selector) ? - node.selector.match(/:(-\w+-)/)[1] : + if (node._autoprefixerPrefix) { + prefix = node._autoprefixerPrefix; + } else if (node.type === 'decl' && node.prop[0] === '-') { + prefix = vendor.prefix(node.prop); + } else if (node.type === 'root') { + prefix = false; + } else if ( + node.type === 'rule' && + node.selector.indexOf(':-') !== -1 && + /:(-\w+-)/.test(node.selector) + ) { + prefix = node.selector.match(/:(-\w+-)/)[1]; + } else if (node.type === 'atrule' && node.name[0] === '-') { + prefix = vendor.prefix(node.name); + } else { + prefix = this.parentPrefix(node.parent); + } - node.type === 'atrule' && node.name[0] === '-' ? - vendor.prefix(node.name) : - this.parentPrefix(node.parent); if (Browsers.prefixes().indexOf(prefix) === -1) { prefix = false; } - return node._autoprefixerPrefix = prefix; + + node._autoprefixerPrefix = prefix; + + return node._autoprefixerPrefix; } - // Clone node with prefixes + /** + * Clone node with prefixes + */ process(node) { if (!this.check(node)) { - return; + return undefined; } - const parent = this.parentPrefix(node); - const prefixes = []; + const parent = this.parentPrefix(node); - for (var prefix of this.prefixes) { - if (parent && parent !== utils.removeNote(prefix)) { - continue; - } - prefixes.push(prefix); - } + const prefixes = this.prefixes.filter( + prefix => !parent || parent === utils.removeNote(prefix) + ); const added = []; - for (prefix of prefixes) { + for (const prefix of prefixes) { if (this.add(node, prefix, added.concat([prefix]))) { added.push(prefix); } @@ -116,7 +133,9 @@ class Prefixer { return added; } - // Shortcut for Prefixer.clone + /** + * Shortcut for Prefixer.clone + */ clone(node, overrides) { return Prefixer.clone(node, overrides); } diff --git a/lib/prefixes.js b/lib/prefixes.js index 5acb371aa..0665b04ca 100644 --- a/lib/prefixes.js +++ b/lib/prefixes.js @@ -1,13 +1,13 @@ const Declaration = require('./declaration'); -const Resolution = require('./resolution'); -const Transition = require('./transition'); -const Processor = require('./processor'); -const Supports = require('./supports'); -const Browsers = require('./browsers'); -const Selector = require('./selector'); -const AtRule = require('./at-rule'); -const Value = require('./value'); -const utils = require('./utils'); +const Resolution = require('./resolution'); +const Transition = require('./transition'); +const Processor = require('./processor'); +const Supports = require('./supports'); +const Browsers = require('./browsers'); +const Selector = require('./selector'); +const AtRule = require('./at-rule'); +const Value = require('./value'); +const utils = require('./utils'); const vendor = require('postcss/lib/vendor'); @@ -54,65 +54,74 @@ Value.hack(require('./hacks/display-flex')); Value.hack(require('./hacks/display-grid')); Value.hack(require('./hacks/filter-value')); -const declsCache = { }; +const declsCache = {}; class Prefixes { - constructor(data, browsers, options = { }) { + constructor(data, browsers, options = {}) { this.data = data; this.browsers = browsers; this.options = options; - [this.add, this.remove] = Array.from(this.preprocess(this.select(this.data))); - this.transition = new Transition(this); - this.processor = new Processor(this); + [this.add, this.remove] = this.preprocess(this.select(this.data)); + this.transition = new Transition(this); + this.processor = new Processor(this); } - // Return clone instance to remove all prefixes + /** + * Return clone instance to remove all prefixes + */ cleaner() { - if (!this.cleanerCache) { - if (this.browsers.selected.length) { - const empty = new Browsers(this.browsers.data, []); - this.cleanerCache = new Prefixes(this.data, empty, this.options); - } else { - return this; - } + if (this.cleanerCache) { + return this.cleanerCache; + } + + if (this.browsers.selected.length) { + const empty = new Browsers(this.browsers.data, []); + this.cleanerCache = new Prefixes(this.data, empty, this.options); + } else { + return this; } return this.cleanerCache; } - // Select prefixes from data, which is necessary for selected browsers + /** + * Select prefixes from data, which is necessary for selected browsers + */ select(list) { - const selected = { add: { }, remove: { } }; + const selected = { add: {}, remove: {} }; for (let name in list) { - var prefix; const data = list[name]; - var add = data.browsers.map((i) => { + let add = data.browsers.map(i => { const params = i.split(' '); - return { browser: params[0] + ' ' + params[1], note: params[2] }; + return { + browser: `${params[0]} ${params[1]}`, + note: params[2] + }; }); - let notes = add.filter( i => i.note).map(i => { - return this.browsers.prefix(i.browser) + ' ' + i.note; - }); + let notes = add + .filter(i => i.note) + .map(i => `${this.browsers.prefix(i.browser)} ${i.note}`); notes = utils.uniq(notes); - add = add.filter( i => this.browsers.isSelected(i.browser) ).map(i => { - prefix = this.browsers.prefix(i.browser); - if (i.note) { - return prefix + ' ' + i.note; - } else { - return prefix; - } - }); - + add = add + .filter(i => this.browsers.isSelected(i.browser)) + .map(i => { + const prefix = this.browsers.prefix(i.browser); + if (i.note) { + return `${prefix} ${i.note}`; + } else { + return prefix; + } + }); add = this.sort(utils.uniq(add)); if (this.options.flexbox === 'no-2009') { add = add.filter(i => i.indexOf('2009') === -1); } - let all = data.browsers.map( i => this.browsers.prefix(i) ); + let all = data.browsers.map(i => this.browsers.prefix(i)); if (data.mistakes) { all = all.concat(data.mistakes); } @@ -122,7 +131,9 @@ class Prefixes { if (add.length) { selected.add[name] = add; if (add.length < all.length) { - selected.remove[name] = all.filter(i => add.indexOf(i) === -1); + selected.remove[name] = all.filter( + i => add.indexOf(i) === -1 + ); } } else { selected.remove[name] = all; @@ -132,7 +143,9 @@ class Prefixes { return selected; } - // Sort vendor prefixes + /** + * Sort vendor prefixes + */ sort(prefixes) { return prefixes.sort((a, b) => { const aLength = utils.removeNote(a).length; @@ -146,12 +159,16 @@ class Prefixes { }); } - // Cache prefixes data to fast CSS processing + /** + * Cache prefixes data to fast CSS processing + */ preprocess(selected) { - let prefixes, prop, props, value, values; - const add = { 'selectors': [], '@supports': new Supports(Prefixes, this) }; - for (var name in selected.add) { - prefixes = selected.add[name]; + const add = { + 'selectors': [], + '@supports': new Supports(Prefixes, this) + }; + for (const name in selected.add) { + const prefixes = selected.add[name]; if (name === '@keyframes' || name === '@viewport') { add[name] = new AtRule(name, prefixes, this); @@ -162,18 +179,18 @@ class Prefixes { add.selectors.push(Selector.load(name, prefixes, this)); } else { - ({ props } = this.data[name]); + const props = this.data[name].props; if (props) { - value = Value.load(name, prefixes, this); - for (prop of props) { + const value = Value.load(name, prefixes, this); + for (const prop of props) { if (!add[prop]) { add[prop] = { values: [] }; } add[prop].values.push(value); } } else { - values = (add[name] != null ? add[name].values : undefined) || []; + const values = add[name] && add[name].values || []; add[name] = Declaration.load(name, prefixes, this); add[name].values = values; } @@ -181,18 +198,17 @@ class Prefixes { } const remove = { selectors: [] }; - for (name in selected.remove) { - var prefix, prefixed; - prefixes = selected.remove[name]; + for (const name in selected.remove) { + const prefixes = selected.remove[name]; if (this.data[name].selector) { const selector = Selector.load(name, prefixes); - for (prefix of prefixes) { + for (const prefix of prefixes) { remove.selectors.push(selector.old(prefix)); } } else if (name === '@keyframes' || name === '@viewport') { - for (prefix of prefixes) { - prefixed = `@${prefix}${name.slice(1)}`; + for (const prefix of prefixes) { + const prefixed = `@${prefix}${name.slice(1)}`; remove[prefixed] = { remove: true }; } @@ -200,39 +216,39 @@ class Prefixes { remove[name] = new Resolution(name, prefixes, this); } else { - var old; - ({ props } = this.data[name]); + const props = this.data[name].props; if (props) { - value = Value.load(name, [], this); - for (prefix of prefixes) { - old = value.old(prefix); + const value = Value.load(name, [], this); + for (const prefix of prefixes) { + const old = value.old(prefix); if (old) { - for (prop of props) { + for (const prop of props) { if (!remove[prop]) { - remove[prop] = { }; - } + remove[prop] = {}; + } if (!remove[prop].values) { - remove[prop].values = []; - } + remove[prop].values = []; + } remove[prop].values.push(old); } } } } else { - for (prefix of prefixes) { - prop = vendor.unprefixed(name); + for (const prefix of prefixes) { const olds = this.decl(name).old(name, prefix); if (name === 'align-self') { - const a = add[name] != null ? add[name].prefixes : undefined; + const a = add[name] && add[name].prefixes; if (a) { - if (prefix === '-webkit- 2009' && a.indexOf('-webkit-') !== -1) { - continue; - } else if (prefix === '-webkit-' && a.indexOf('-webkit- 2009') !== -1) { - continue; - } + if (prefix === '-webkit- 2009' && + a.indexOf('-webkit-') !== -1) { + continue; + } else if (prefix === '-webkit-' && + a.indexOf('-webkit- 2009') !== -1) { + continue; + } } } - for (prefixed of olds) { + for (const prefixed of olds) { if (!remove[prefixed]) { remove[prefixed] = {}; } @@ -246,18 +262,23 @@ class Prefixes { return [add, remove]; } - // Declaration loader with caching + /** + * Declaration loader with caching + */ decl(prop) { const decl = declsCache[prop]; if (decl) { return decl; } else { - return declsCache[prop] = Declaration.load(prop); + declsCache[prop] = Declaration.load(prop); + return declsCache[prop]; } } - // Return unprefixed version of property + /** + * Return unprefixed version of property + */ unprefixed(prop) { let value = this.normalize(vendor.unprefixed(prop)); if (value === 'flex-direction') { @@ -266,23 +287,29 @@ class Prefixes { return value; } - // Normalize prefix for remover + /** + * Normalize prefix for remover + */ normalize(prop) { return this.decl(prop).normalize(prop); } - // Return prefixed version of property + /** + * Return prefixed version of property + */ prefixed(prop, prefix) { prop = vendor.unprefixed(prop); return this.decl(prop).prefixed(prop, prefix); } - // Return values, which must be prefixed in selected property + /** + * Return values, which must be prefixed in selected property + */ values(type, prop) { const data = this[type]; - const global = data['*'] != null ? data['*'].values : undefined; - const values = data[prop] != null ? data[prop].values : undefined; + const global = data['*'] && data['*'].values; + const values = data[prop] && data[prop].values; if (global && values) { return utils.uniq(global.concat(values)); @@ -291,11 +318,13 @@ class Prefixes { } } - // Group declaration by unprefixed property to check them + /** + * Group declaration by unprefixed property to check them + */ group(decl) { - const rule = decl.parent; - let index = rule.index(decl); - const { length } = rule.nodes; + const rule = decl.parent; + let index = rule.index(decl); + const { length } = rule.nodes; const unprefixed = this.unprefixed(decl.prop); const checker = (step, callback) => { @@ -312,7 +341,6 @@ class Prefixes { if (this.unprefixed(other.prop) !== unprefixed) { break; - } else if (callback(other) === true) { return true; } diff --git a/lib/processor.js b/lib/processor.js index 0fbb8b881..042fb9f68 100644 --- a/lib/processor.js +++ b/lib/processor.js @@ -1,124 +1,158 @@ -const vendor = require('postcss/lib/vendor'); -const Value = require('./value'); -const utils = require('./utils'); +const Value = require('./value'); -const OLD_DIRECTION = /(^|[^-])(linear|radial)-gradient\(\s*(top|left|right|bottom)/i; +const OLD_DIRECTION = + /(^|[^-])(linear|radial)-gradient\(\s*(top|left|right|bottom)/i; -const SIZES = ['width', 'height', 'min-width', 'max-width', +const SIZES = [ + 'width', 'height', 'min-width', 'max-width', 'min-height', 'max-height', 'inline-size', 'min-inline-size', 'max-inline-size', 'block-size', - 'min-block-size', 'max-block-size']; + 'min-block-size', 'max-block-size' +]; class Processor { constructor(prefixes) { this.prefixes = prefixes; } - // Add necessary prefixes + /** + * Add necessary prefixes + */ add(css, result) { - // At-rules + // At-rules const resolution = this.prefixes.add['@resolution']; - const keyframes = this.prefixes.add['@keyframes']; - const viewport = this.prefixes.add['@viewport']; - const supports = this.prefixes.add['@supports']; + const keyframes = this.prefixes.add['@keyframes']; + const viewport = this.prefixes.add['@viewport']; + const supports = this.prefixes.add['@supports']; css.walkAtRules(rule => { if (rule.name === 'keyframes') { if (!this.disabled(rule)) { - return keyframes != null ? keyframes.process(rule) : undefined; + return keyframes && keyframes.process(rule); } } else if (rule.name === 'viewport') { if (!this.disabled(rule)) { - return viewport != null ? viewport.process(rule) : undefined; + return viewport && viewport.process(rule); } } else if (rule.name === 'supports') { - if (this.prefixes.options.supports !== false && !this.disabled(rule)) { + if (this.prefixes.options.supports !== false && + !this.disabled(rule) + ) { return supports.process(rule); } - } else if (rule.name === 'media' && rule.params.indexOf('-resolution') !== -1) { + } else if (rule.name === 'media' && + rule.params.indexOf('-resolution') !== -1 + ) { if (!this.disabled(rule)) { - return resolution != null ? resolution.process(rule) : undefined; + return resolution && resolution.process(rule); } } + + return undefined; }); - // Selectors + // Selectors css.walkRules(rule => { if (this.disabled(rule)) { - return; + return undefined; } - return this.prefixes.add.selectors.map((selector) => - selector.process(rule, result)); + return this.prefixes.add.selectors.map( + selector => selector.process(rule, result) + ); }); css.walkDecls(decl => { - let prefixer; if (this.disabled(decl)) { - return; + return undefined; } if (decl.prop === 'display' && decl.value === 'box') { - result.warn('You should write display: flex by final spec ' + - 'instead of display: box', { node: decl }); - return; + result.warn( + 'You should write display: flex by final spec ' + + 'instead of display: box', { node: decl } + ); + return undefined; } if (decl.value.indexOf('linear-gradient') !== -1) { if (OLD_DIRECTION.test(decl.value)) { - result.warn('Gradient has outdated direction syntax. ' + - 'New syntax is like `to left` instead of `right`.', - { node: decl }); + result.warn( + 'Gradient has outdated direction syntax. ' + + 'New syntax is like `to left` instead of `right`.', + { node: decl } + ); } } if (decl.prop === 'text-emphasis-position') { if (decl.value === 'under' || decl.value === 'over') { - result.warn('You should use 2 values for text-emphasis-position ' + - 'For example, `under left` instead of just `under`.', - { node: decl }); + result.warn( + 'You should use 2 values for text-emphasis-position ' + + 'For example, `under left` instead of just `under`.', + { node: decl } + ); } } if (SIZES.indexOf(decl.prop) !== -1) { if (decl.value.indexOf('fill-available') !== -1) { - result.warn('Replace fill-available to stretch, ' + - 'because spec had been changed', - { node: decl }); + result.warn( + 'Replace fill-available to stretch, ' + + 'because spec had been changed', + { node: decl } + ); } else if (decl.value.indexOf('fill') !== -1) { - result.warn('Replace fill to stretch, because spec had been changed', - { node: decl }); + result.warn( + 'Replace fill to stretch, because spec had been changed', + { node: decl } + ); } } if (this.prefixes.options.flexbox !== false) { - if (decl.prop === 'grid-row-end' && decl.value.indexOf('span') === -1) { - result.warn('IE supports only grid-row-end with span. ' + - 'You should add grid: false option to Autoprefixer ' + - 'and use some JS grid polyfill for full spec support', - { node: decl }); + if (decl.prop === 'grid-row-end' && + decl.value.indexOf('span') === -1 + ) { + result.warn( + 'IE supports only grid-row-end with span. ' + + 'You should add grid: false option to Autoprefixer ' + + 'and use some JS grid polyfill for full spec support', + { node: decl } + ); } if (decl.prop === 'grid-row') { - if (decl.value.indexOf('/') !== -1 && decl.value.indexOf('span') === -1) { - result.warn('IE supports only grid-row with / and span. ' + + if (decl.value.indexOf('/') !== -1 && + decl.value.indexOf('span') === -1 + ) { + result.warn( + 'IE supports only grid-row with / and span. ' + 'You should add grid: false option to Autoprefixer ' + 'and use some JS grid polyfill for full spec support', - { node: decl }); + { node: decl } + ); } } } - if (decl.prop === 'transition' || decl.prop === 'transition-property') { - // Transition - return this.prefixes.transition.add(decl, result); + let prefixer; + if (decl.prop === 'transition' || + decl.prop === 'transition-property' + ) { + // Transition + return this.prefixes.transition.add(decl, result); } else if (decl.prop === 'align-self') { - // align-self flexbox or grid + // align-self flexbox or grid const display = this.displayType(decl); - if (display !== 'grid' && this.prefixes.options.flexbox !== false) { + if (display !== 'grid' && + this.prefixes.options.flexbox !== false + ) { prefixer = this.prefixes.add['align-self']; if (prefixer && prefixer.prefixes) { prefixer.process(decl); } } - if (display !== 'flex' && this.prefixes.options.grid !== false) { + if (display !== 'flex' && + this.prefixes.options.grid !== false + ) { prefixer = this.prefixes.add['grid-row-align']; if (prefixer && prefixer.prefixes) { return prefixer.process(decl); @@ -126,15 +160,17 @@ class Processor { } } else { - // Properties + // Properties prefixer = this.prefixes.add[decl.prop]; if (prefixer && prefixer.prefixes) { return prefixer.process(decl); } } + + return undefined; }); - // Values + // Values return css.walkDecls(decl => { if (this.disabled(decl)) { return; @@ -144,53 +180,61 @@ class Processor { for (let value of this.prefixes.values('add', unprefixed)) { value.process(decl, result); } - return Value.save(this.prefixes, decl); + Value.save(this.prefixes, decl); }); } - // Remove unnecessary pefixes + /** + * Remove unnecessary pefixes + */ remove(css) { - // At-rules + // At-rules const resolution = this.prefixes.remove['@resolution']; css.walkAtRules((rule, i) => { if (this.prefixes.remove[`@${rule.name}`]) { if (!this.disabled(rule)) { - return rule.parent.removeChild(i); + rule.parent.removeChild(i); } - } else if (rule.name === 'media' && rule.params.indexOf('-resolution') !== -1) { - return resolution != null ? resolution.clean(rule) : undefined; + } else if (rule.name === 'media' && + rule.params.indexOf('-resolution') !== -1 && + resolution + ) { + resolution.clean(rule); } }); - // Selectors - for (var checker of this.prefixes.remove.selectors) { + // Selectors + for (const checker of this.prefixes.remove.selectors) { css.walkRules((rule, i) => { if (checker.check(rule)) { if (!this.disabled(rule)) { - return rule.parent.removeChild(i); + rule.parent.removeChild(i); } } }); } return css.walkDecls((decl, i) => { - let notHack; if (this.disabled(decl)) { return; } - const rule = decl.parent; + const rule = decl.parent; let unprefixed = this.prefixes.unprefixed(decl.prop); - // Transition - if (decl.prop === 'transition' || decl.prop === 'transition-property') { + // Transition + if (decl.prop === 'transition' || + decl.prop === 'transition-property' + ) { this.prefixes.transition.remove(decl); } - // Properties - if (this.prefixes.remove[decl.prop] != null ? this.prefixes.remove[decl.prop].remove : undefined) { - notHack = this.prefixes.group(decl).down(other => { + // Properties + if (this.prefixes.remove[decl.prop] && + this.prefixes.remove[decl.prop].remove + ) { + let notHack = this.prefixes.group(decl).down(other => { return this.prefixes.normalize(other.prop) === unprefixed; }); @@ -207,11 +251,13 @@ class Processor { } } - // Values - for (checker of this.prefixes.values('remove', unprefixed)) { + // Values + for (const checker of this.prefixes.values('remove', unprefixed)) { if (checker.check(decl.value)) { - ({ unprefixed } = checker); - notHack = this.prefixes.group(decl).down(other => other.value.indexOf(unprefixed) !== -1); + unprefixed = checker.unprefixed; + const notHack = this.prefixes.group(decl).down( + other => other.value.indexOf(unprefixed) !== -1 + ); if (notHack) { rule.removeChild(i); @@ -225,39 +271,55 @@ class Processor { }); } - // Some rare old values, which is not in standard + /** + * Some rare old values, which is not in standard + */ withHackValue(decl) { return decl.prop === '-webkit-background-clip' && decl.value === 'text'; } - // Check for control comment and global options + /** + * Check for control comment and global options + */ disabled(node) { if (this.prefixes.options.grid === false && node.type === 'decl') { - if (node.prop === 'display' && node.value.indexOf('grid') !== -1) { + if (node.prop === 'display' && + node.value.indexOf('grid') !== -1 + ) { return true; } - if (node.prop.indexOf('grid') !== -1 || node.prop === 'justify-items') { + if (node.prop.indexOf('grid') !== -1 || + node.prop === 'justify-items' + ) { return true; } } if (this.prefixes.options.flexbox === false && node.type === 'decl') { - if (node.prop === 'display' && node.value.indexOf('flex') !== -1) { + if (node.prop === 'display' && + node.value.indexOf('flex') !== -1 + ) { return true; } - const other = ['order', 'justify-content', 'align-items', 'align-content']; - if (node.prop.indexOf('flex') !== -1 || other.indexOf(node.prop) !== -1) { + const other = [ + 'order', + 'justify-content', + 'align-items', + 'align-content' + ]; + if (node.prop.indexOf('flex') !== -1 || + other.indexOf(node.prop) !== -1 + ) { return true; } } - if (node._autoprefixerDisabled != null) { + if (node._autoprefixerDisabled !== undefined) { return node._autoprefixerDisabled; - } else if (node.nodes) { let status = undefined; - node.each((i) => { + node.each(i => { if (i.type !== 'comment') { - return; + return undefined; } if (/(!\s*)?autoprefixer:\s*off/i.test(i.text)) { status = false; @@ -266,53 +328,66 @@ class Processor { status = true; return false; } + return undefined; }); - return node._autoprefixerDisabled = status != null ? - !status : - node.parent ? - this.disabled(node.parent) : - false; + let result; + if (status !== undefined) { + result = !status; + } else { + result = node.parent ? this.disabled(node.parent) : false; + } + + node._autoprefixerDisabled = result; + return node._autoprefixerDisabled; } else if (node.parent) { - return node._autoprefixerDisabled = this.disabled(node.parent); + node._autoprefixerDisabled = this.disabled(node.parent); + return node._autoprefixerDisabled; } else { - // unknown state + // unknown state return false; } } - // Normalize spaces in cascade declaration group + /** + * Normalize spaces in cascade declaration group + */ reduceSpaces(decl) { let stop = false; - this.prefixes.group(decl).up(other => stop = true); + this.prefixes.group(decl).up(() => { + stop = true; + return true; + }); if (stop) { return; } - let parts = decl.raw('before').split('\n'); + let parts = decl.raw('before').split('\n'); const prevMin = parts[parts.length - 1].length; - let diff = false; + let diff = false; - return this.prefixes.group(decl).down((other) => { + this.prefixes.group(decl).down(other => { parts = other.raw('before').split('\n'); - const last = parts.length - 1; + const last = parts.length - 1; if (parts[last].length > prevMin) { if (diff === false) { diff = parts[last].length - prevMin; } - parts[last] = parts[last].slice(0, -diff); - return other.raws.before = parts.join('\n'); + parts[last] = parts[last].slice(0, -diff); + other.raws.before = parts.join('\n'); } }); } - // Is it flebox or grid rule + /** + * Is it flebox or grid rule + */ displayType(decl) { - for (let i of decl.parent.nodes) { + for (const i of decl.parent.nodes) { if (i.prop === 'display') { if (i.value.indexOf('flex') !== -1) { return 'flex'; diff --git a/lib/resolution.js b/lib/resolution.js index c0b254ca4..410226ca8 100644 --- a/lib/resolution.js +++ b/lib/resolution.js @@ -1,21 +1,26 @@ const Prefixer = require('./prefixer'); -const utils = require('./utils'); +const utils = require('./utils'); const n2f = require('num2fraction'); const regexp = /(min|max)-resolution\s*:\s*\d*\.?\d+(dppx|dpi)/gi; -const split = /(min|max)-resolution(\s*:\s*)(\d*\.?\d+)(dppx|dpi)/i; +const split = /(min|max)-resolution(\s*:\s*)(\d*\.?\d+)(dppx|dpi)/i; class Resolution extends Prefixer { - // Return prefixed query name + /** + * Return prefixed query name + */ prefixName(prefix, name) { - return name = prefix === '-moz-' ? - name + '--moz-device-pixel-ratio' : - prefix + name + '-device-pixel-ratio'; + const newName = prefix === '-moz-' ? + name + '--moz-device-pixel-ratio' : + prefix + name + '-device-pixel-ratio'; + return newName; } - // Return prefixed query + /** + * Return prefixed query + */ prefixQuery(prefix, name, colon, value, units) { if (units === 'dpi') { value = Number(value / 96); @@ -26,41 +31,55 @@ class Resolution extends Prefixer { return this.prefixName(prefix, name) + colon + value; } - // Remove prefixed queries + /** + * Remove prefixed queries + */ clean(rule) { if (!this.bad) { this.bad = []; - for (let prefix of this.prefixes) { - this.bad.push( this.prefixName(prefix, 'min') ); - this.bad.push( this.prefixName(prefix, 'max') ); + for (const prefix of this.prefixes) { + this.bad.push(this.prefixName(prefix, 'min')); + this.bad.push(this.prefixName(prefix, 'max')); } } - return rule.params = utils.editList(rule.params, queries => { - return queries.filter(query => this.bad.every( i => query.indexOf(i) === -1)); + rule.params = utils.editList(rule.params, queries => { + return queries.filter( + query => this.bad.every(i => query.indexOf(i) === -1) + ); }); } - // Add prefixed queries + /** + * Add prefixed queries + */ process(rule) { - const parent = this.parentPrefix(rule); + const parent = this.parentPrefix(rule); const prefixes = parent ? [parent] : this.prefixes; - return rule.params = utils.editList(rule.params, (origin, prefixed) => { + rule.params = utils.editList(rule.params, (origin, prefixed) => { for (let query of origin) { if (query.indexOf('min-resolution') === -1 && - query.indexOf('max-resolution') === -1) { + query.indexOf('max-resolution') === -1) { prefixed.push(query); continue; } - for (var prefix of prefixes) { - if (prefix === '-moz-' && rule.params.indexOf('dpi') !== -1) { + for (const prefix of prefixes) { + if (prefix === '-moz-' && + rule.params.indexOf('dpi') !== -1 + ) { continue; } else { const processed = query.replace(regexp, str => { const parts = str.match(split); - return this.prefixQuery(prefix, parts[1], parts[2], parts[3], parts[4]); + return this.prefixQuery( + prefix, + parts[1], + parts[2], + parts[3], + parts[4] + ); }); prefixed.push(processed); } diff --git a/lib/selector.js b/lib/selector.js index 8dc569c0d..cfe20422a 100644 --- a/lib/selector.js +++ b/lib/selector.js @@ -1,15 +1,17 @@ const OldSelector = require('./old-selector'); -const Prefixer = require('./prefixer'); -const Browsers = require('./browsers'); -const utils = require('./utils'); +const Prefixer = require('./prefixer'); +const Browsers = require('./browsers'); +const utils = require('./utils'); class Selector extends Prefixer { constructor(name, prefixes, all) { super(name, prefixes, all); - this.regexpCache = { }; + this.regexpCache = {}; } - // Is rule selectors need to be prefixed + /** + * Is rule selectors need to be prefixed + */ check(rule) { if (rule.selector.indexOf(this.name) !== -1) { return !!rule.selector.match(this.regexp()); @@ -18,41 +20,54 @@ class Selector extends Prefixer { } } - // Return prefixed version of selector + /** + * Return prefixed version of selector + */ prefixed(prefix) { return this.name.replace(/^([^\w]*)/, `$1${prefix}`); } - // Lazy loadRegExp for name + /** + * Lazy loadRegExp for name + */ regexp(prefix) { if (this.regexpCache[prefix]) { return this.regexpCache[prefix]; } const name = prefix ? this.prefixed(prefix) : this.name; - return this.regexpCache[prefix] = new RegExp(`(^|[^:"'=])${ utils.escapeRegexp(name) }`, 'gi'); + this.regexpCache[prefix] = + new RegExp(`(^|[^:"'=])${utils.escapeRegexp(name)}`, 'gi'); + return this.regexpCache[prefix]; } - // All possible prefixes + /** + * All possible prefixes + */ possible() { return Browsers.prefixes(); } - // Return all possible selector prefixes + /** + * Return all possible selector prefixes + */ prefixeds(rule) { if (rule._autoprefixerPrefixeds) { return rule._autoprefixerPrefixeds; } - const prefixeds = { }; - for (let prefix of this.possible()) { + const prefixeds = {}; + for (const prefix of this.possible()) { prefixeds[prefix] = this.replace(rule.selector, prefix); } - return rule._autoprefixerPrefixeds = prefixeds; + rule._autoprefixerPrefixeds = prefixeds; + return rule._autoprefixerPrefixeds; } - // Is rule already prefixed before + /** + * Is rule already prefixed before + */ already(rule, prefixeds, prefix) { let index = rule.parent.index(rule) - 1; @@ -85,12 +100,16 @@ class Selector extends Prefixer { return false; } - // Replace selectors by prefixed one + /** + * Replace selectors by prefixed one + */ replace(selector, prefix) { return selector.replace(this.regexp(), `$1${this.prefixed(prefix)}`); } - // Clone and add prefixes for at-rule + /** + * Clone and add prefixes for at-rule + */ add(rule, prefix) { const prefixeds = this.prefixeds(rule); @@ -99,10 +118,12 @@ class Selector extends Prefixer { } const cloned = this.clone(rule, { selector: prefixeds[prefix] }); - return rule.parent.insertBefore(rule, cloned); + rule.parent.insertBefore(rule, cloned); } - // Return function to fast find prefixed selector + /** + * Return function to fast find prefixed selector + */ old(prefix) { return new OldSelector(this, prefix); } diff --git a/lib/supports.js b/lib/supports.js index 15dc9fbf5..df801bd19 100644 --- a/lib/supports.js +++ b/lib/supports.js @@ -25,7 +25,9 @@ class Supports { this.all = all; } - // Return prefixer only with @supports supported browsers + /** + * Return prefixer only with @supports supported browsers + */ prefixer() { if (this.prefixerCache) { return this.prefixerCache; @@ -35,28 +37,43 @@ class Supports { return supported.indexOf(i) !== -1; }); - const browsers = new Browsers(this.all.browsers.data, filtered, this.all.options); - return this.prefixerCache = new this.Prefixes(this.all.data, browsers, this.all.options); + const browsers = new Browsers( + this.all.browsers.data, + filtered, + this.all.options + ); + this.prefixerCache = new this.Prefixes( + this.all.data, + browsers, + this.all.options + ); + return this.prefixerCache; } - // Parse string into declaration property and value + /** + * Parse string into declaration property and value + */ parse(str) { - let [prop, value] = Array.from(str.split(':')); + let [prop, value] = str.split(':'); if (!value) { value = ''; } return [prop.trim(), value.trim()]; } - // Create virtual rule to process it by prefixer + /** + * Create virtual rule to process it by prefixer + */ virtual(str) { - const [prop, value] = Array.from(this.parse(str)); + const [prop, value] = this.parse(str); const rule = postcss.parse('a{}').first; rule.append({ prop, value, raws: { before: '' } }); return rule; } - // Return array of Declaration with all necessary prefixes + /** + * Return array of Declaration with all necessary prefixes + */ prefixed(str) { const rule = this.virtual(str); if (this.disabled(rule.first)) { @@ -64,7 +81,7 @@ class Supports { } const prefixer = this.prefixer().add[rule.first.prop]; - __guardMethod__(prefixer, 'process', o => o.process(rule.first)); + prefixer && prefixer.process && prefixer.process(rule.first); for (let decl of rule.nodes) { for (let value of this.prefixer().values('add', rule.first.prop)) { @@ -76,37 +93,56 @@ class Supports { return rule.nodes; } - // Return true if brackets node is "not" word + /** + * Return true if brackets node is "not" word + */ isNot(node) { - return typeof node === 'string' && /not\s*/i.test(node); + return typeof node === 'string' && + /not\s*/i.test(node); } - // Return true if brackets node is "or" word + /** + * Return true if brackets node is "or" word + */ isOr(node) { - return typeof node === 'string' && /\s*or\s*/i.test(node); + return typeof node === 'string' && + /\s*or\s*/i.test(node); } - // Return true if brackets node is (prop: value) + /** + * Return true if brackets node is (prop: value) + */ isProp(node) { - return typeof node === 'object' && node.length === 1 && typeof node[0] === 'string'; + return typeof node === 'object' && + node.length === 1 && + typeof node[0] === 'string'; } - // Return true if prefixed property has no unprefixed + /** + * Return true if prefixed property has no unprefixed + */ isHack(all, unprefixed) { const check = new RegExp(`(\\(|\\s)${utils.escapeRegexp(unprefixed)}:`); return !check.test(all); } - // Return true if we need to remove node + /** + * Return true if we need to remove node + */ toRemove(str, all) { - const [prop, value] = Array.from(this.parse(str)); + const [prop, value] = this.parse(str); const unprefixed = this.all.unprefixed(prop); - if (__guard__(this.all.cleaner().remove[prop], x => x.remove) && !this.isHack(all, unprefixed)) { + const cleaner = this.all.cleaner(); + + if (cleaner.remove[prop] && + cleaner.remove[prop].remove && + !this.isHack(all, unprefixed) + ) { return true; } - for (let checker of this.all.cleaner().values('remove', unprefixed)) { + for (const checker of cleaner.values('remove', unprefixed)) { if (checker.check(value)) { return true; } @@ -115,11 +151,16 @@ class Supports { return false; } - // Remove all unnecessary prefixes + /** + * Remove all unnecessary prefixes + */ remove(nodes, all) { let i = 0; while (i < nodes.length) { - if (!this.isNot(nodes[i - 1]) && this.isProp(nodes[i]) && this.isOr(nodes[i + 1])) { + if (!this.isNot(nodes[i - 1]) && + this.isProp(nodes[i]) && + this.isOr(nodes[i + 1]) + ) { if (this.toRemove(nodes[i][0], all)) { nodes.splice(i, 2); } else { @@ -135,7 +176,9 @@ class Supports { return nodes; } - // Clean brackets with one child + /** + * Clean brackets with one child + */ cleanBrackets(nodes) { return nodes.map(i => { if (typeof i === 'object') { @@ -150,18 +193,22 @@ class Supports { }); } - // Add " or " between properties and convert it to brackets format + /** + * Add " or " between properties and convert it to brackets format + */ convert(progress) { const result = ['']; for (let i of progress) { - result.push([`${ i.prop }: ${ i.value }`]); + result.push([`${i.prop}: ${i.value}`]); result.push(' or '); } result[result.length - 1] = ''; return result; } - // Compress value functions into a string nodes + /** + * Compress value functions into a string nodes + */ normalize(nodes) { if (typeof nodes === 'object') { nodes = nodes.filter(i => i !== ''); @@ -175,7 +222,9 @@ class Supports { } } - // Add prefixes + /** + * Add prefixes + */ add(nodes, all) { return nodes.map(i => { if (this.isProp(i)) { @@ -193,33 +242,50 @@ class Supports { }); } - // Add prefixed declaration + /** + * Add prefixed declaration + */ process(rule) { let ast = brackets.parse(rule.params); ast = this.normalize(ast); ast = this.remove(ast, rule.params); ast = this.add(ast, rule.params); ast = this.cleanBrackets(ast); - return rule.params = brackets.stringify(ast); + rule.params = brackets.stringify(ast); } - // Check global options + /** + * Check global options + */ disabled(node) { if (this.all.options.grid === false) { - if (node.prop === 'display' && node.value.indexOf('grid') !== -1) { + if (node.prop === 'display' && + node.value.indexOf('grid') !== -1 + ) { return true; } - if (node.prop.indexOf('grid') !== -1 || node.prop === 'justify-items') { + if (node.prop.indexOf('grid') !== -1 || + node.prop === 'justify-items' + ) { return true; } } if (this.all.options.flexbox === false) { - if (node.prop === 'display' && node.value.indexOf('flex') !== -1) { + if (node.prop === 'display' && + node.value.indexOf('flex') !== -1 + ) { return true; } - const other = ['order', 'justify-content', 'align-items', 'align-content']; - if (node.prop.indexOf('flex') !== -1 || other.indexOf(node.prop) !== -1) { + const other = [ + 'order', + 'justify-content', + 'align-items', + 'align-content' + ]; + if (node.prop.indexOf('flex') !== -1 || + other.indexOf(node.prop) !== -1 + ) { return true; } } @@ -229,14 +295,3 @@ class Supports { } module.exports = Supports; - -function __guardMethod__(obj, methodName, transform) { - if (typeof obj !== 'undefined' && obj !== null && typeof obj[methodName] === 'function') { - return transform(obj, methodName); - } else { - return undefined; - } -} -function __guard__(value, transform) { - return typeof value !== 'undefined' && value !== null ? transform(value) : undefined; -} diff --git a/lib/transition.js b/lib/transition.js index 1fbe67883..97a899a86 100644 --- a/lib/transition.js +++ b/lib/transition.js @@ -1,25 +1,28 @@ const parser = require('postcss-value-parser'); const vendor = require('postcss/lib/vendor'); -const list = require('postcss/lib/list'); +const list = require('postcss/lib/list'); class Transition { static initClass() { - // Properties to be processed + // Properties to be processed this.prototype.props = ['transition', 'transition-property']; } constructor(prefixes) { this.prefixes = prefixes; } - // Process transition and add prefies for all necessary properties + /** + * Process transition and add prefies for all necessary properties + */ add(decl, result) { let prefix, prop; - const declPrefixes = (this.prefixes.add[decl.prop] != null ? this.prefixes.add[decl.prop].prefixes : undefined) || []; + const declPrefixes = this.prefixes.add[decl.prop] && + this.prefixes.add[decl.prop].prefixes || []; let params = this.parse(decl.value); - const names = params.map(i => this.findProp(i)); - const added = []; + const names = params.map(i => this.findProp(i)); + const added = []; if (names.some(i => i[0] === '-')) { return; @@ -31,13 +34,15 @@ class Transition { continue; } const prefixer = this.prefixes.add[prop]; - if (!(prefixer != null ? prefixer.prefixes : undefined)) { + if (!prefixer || !prefixer.prefixes) { continue; } for (prefix of prefixer.prefixes) { const prefixed = this.prefixes.prefixed(prop, prefix); - if (prefixed !== '-ms-transform' && names.indexOf(prefixed) === -1) { + if (prefixed !== '-ms-transform' && + names.indexOf(prefixed) === -1 + ) { if (!this.disabled(prop, prefix)) { added.push(this.clone(prop, prefixed, param)); } @@ -46,21 +51,27 @@ class Transition { } params = params.concat(added); - const value = this.stringify(params); + const value = this.stringify(params); - const webkitClean = this.stringify(this.cleanFromUnprefixed(params, '-webkit-')); + const webkitClean = this.stringify( + this.cleanFromUnprefixed(params, '-webkit-') + ); if (declPrefixes.indexOf('-webkit-') !== -1) { this.cloneBefore(decl, `-webkit-${decl.prop}`, webkitClean); } this.cloneBefore(decl, decl.prop, webkitClean); if (declPrefixes.indexOf('-o-') !== -1) { - const operaClean = this.stringify(this.cleanFromUnprefixed(params, '-o-')); + const operaClean = this.stringify( + this.cleanFromUnprefixed(params, '-o-') + ); this.cloneBefore(decl, `-o-${decl.prop}`, operaClean); } for (prefix of declPrefixes) { if (prefix !== '-webkit-' && prefix !== '-o-') { - const prefixValue = this.stringify(this.cleanOtherPrefixes(params, prefix)); + const prefixValue = this.stringify( + this.cleanOtherPrefixes(params, prefix) + ); this.cloneBefore(decl, prefix + decl.prop, prefixValue); } } @@ -68,11 +79,13 @@ class Transition { if (value !== decl.value && !this.already(decl, decl.prop, value)) { this.checkForWarning(result, decl); decl.cloneBefore(); - return decl.value = value; + decl.value = value; } } - // Find property name + /** + * Find property name + */ findProp(param) { const prop = param[0].value; if (/^\d/.test(prop)) { @@ -86,48 +99,61 @@ class Transition { return prop; } - // Does we aready have this declaration + /** + * Does we aready have this declaration + */ already(decl, prop, value) { return decl.parent.some(i => i.prop === prop && i.value === value); } - // Add declaration if it is not exist + /** + * Add declaration if it is not exist + */ cloneBefore(decl, prop, value) { if (!this.already(decl, prop, value)) { - return decl.cloneBefore({ prop, value }); + decl.cloneBefore({ prop, value }); } } - // Show transition-property warning + /** + * Show transition-property warning + */ checkForWarning(result, decl) { if (decl.prop === 'transition-property') { - return decl.parent.each((i) => { + decl.parent.each((i) => { if (i.type !== 'decl') { - return; + return undefined; } if (i.prop.indexOf('transition-') !== 0) { - return; + return undefined; } if (i.prop === 'transition-property') { - return; + return undefined; } if (list.comma(i.value).length > 1) { - decl.warn(result, 'Replace transition-property to transition, ' + - 'because Autoprefixer could not support ' + - 'any cases of transition-property ' + - 'and other transition-*'); + decl.warn(result, + 'Replace transition-property to transition, ' + + 'because Autoprefixer could not support ' + + 'any cases of transition-property ' + + 'and other transition-*' + ); } return false; }); } } - // Process transition and remove all unnecessary properties + /** + * Process transition and remove all unnecessary properties + */ remove(decl) { let params = this.parse(decl.value); - params = params.filter(i => !__guard__(this.prefixes.remove[this.findProp(i)], x => x.remove)); - const value = this.stringify(params); + params = params.filter(i => { + const x = this.prefixes.remove[this.findProp(i)]; + return x && x.remove; + }); + const value = this.stringify(params); if (decl.value === value) { return; @@ -138,21 +164,29 @@ class Transition { return; } - const double = decl.parent.some(i => i.prop === decl.prop && i.value === value); - const smaller = decl.parent.some(i => i !== decl && i.prop === decl.prop && i.value.length > value.length); + const double = decl.parent.some( + i => i.prop === decl.prop && i.value === value + ); + const smaller = decl.parent.some( + i => i !== decl && + i.prop === decl.prop && + i.value.length > value.length + ); if (double || smaller) { - return decl.remove(); + decl.remove(); } else { - return decl.value = value; + decl.value = value; } } - // Parse properties list to array + /** + * Parse properties list to array + */ parse(value) { - const ast = parser(value); + const ast = parser(value); const result = []; - let param = []; + let param = []; for (let node of ast.nodes) { param.push(node); if (node.type === 'div' && node.value === ',') { @@ -164,7 +198,9 @@ class Transition { return result.filter(i => i.length > 0); } - // Return properties string from array + /** + * Return properties string from array + */ stringify(params) { if (params.length === 0) { return ''; @@ -185,11 +221,13 @@ class Transition { return parser.stringify({ nodes }); } - // Return new param array with different name + /** + * Return new param array with different name + */ clone(origin, name, param) { - const result = []; + const result = []; let changed = false; - for (let i of param) { + for (const i of param) { if (!changed && i.type === 'word' && i.value === origin) { result.push({ type: 'word', value: name }); changed = true; @@ -200,7 +238,9 @@ class Transition { return result; } - // Find or create seperator + /** + * Find or create seperator + */ div(params) { for (let param of params) { for (let node of param) { @@ -219,16 +259,19 @@ class Transition { }); } - // Remove all non-webkit prefixes and unprefixed params if we have prefixed + /** + * Remove all non-webkit prefixes and unprefixed params if we have prefixed + */ cleanFromUnprefixed(params, prefix) { - const result = []; const remove = params - .map(i => this.findProp(i)) - .filter(i => i.slice(0, prefix.length) === prefix) - .map(i => this.prefixes.unprefixed(i)); - for (let param of params) { + .map(i => this.findProp(i)) + .filter(i => i.slice(0, prefix.length) === prefix) + .map(i => this.prefixes.unprefixed(i)); + + const result = []; + for (const param of params) { const prop = this.findProp(param); - const p = vendor.prefix(prop); + const p = vendor.prefix(prop); if (remove.indexOf(prop) === -1 && (p === prefix || p === '')) { result.push(param); } @@ -236,9 +279,16 @@ class Transition { return result; } - // Check property for disabled by option + /** + * Check property for disabled by option + */ disabled(prop, prefix) { - const other = ['order', 'justify-content', 'align-self', 'align-content']; + const other = [ + 'order', + 'justify-content', + 'align-self', + 'align-content' + ]; if (prop.indexOf('flex') !== -1 || other.indexOf(prop) !== -1) { if (this.prefixes.options.flexbox === false) { return true; @@ -246,12 +296,9 @@ class Transition { return prefix.indexOf('2009') !== -1; } } + return undefined; } } Transition.initClass(); module.exports = Transition; - -function __guard__(value, transform) { - return typeof value !== 'undefined' && value !== null ? transform(value) : undefined; -} diff --git a/lib/utils.js b/lib/utils.js index a5d4ad651..794d07f87 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -2,17 +2,21 @@ const list = require('postcss/lib/list'); module.exports = { - // Throw special error, to tell beniary, that this error is from Autoprefixer. + /** + * Throw special error, to tell beniary, that this error is from Autoprefixer. + */ error(text) { const err = new Error(text); err.autoprefixer = true; throw err; }, - // Return array, that doesn’t contain duplicates. + /** + * Return array, that doesn’t contain duplicates. + */ uniq(array) { const filtered = []; - for (let i of array) { + for (const i of array) { if (filtered.indexOf(i) === -1) { filtered.push(i); } @@ -20,7 +24,9 @@ module.exports = { return filtered; }, - // Return "-webkit-" on "-webkit- old" + /** + * Return "-webkit-" on "-webkit- old" + */ removeNote(string) { if (string.indexOf(' ') === -1) { return string; @@ -29,22 +35,28 @@ module.exports = { } }, - // Escape RegExp symbols + /** + * Escape RegExp symbols + */ escapeRegexp(string) { return string.replace(/[.?*+\^\$\[\]\\(){}|\-]/g, '\\$&'); }, - // Return regexp to check, that CSS string contain word + /** + * Return regexp to check, that CSS string contain word + */ regexp(word, escape = true) { if (escape) { word = this.escapeRegexp(word); } - return new RegExp(`(^|[\\s,(])(${ word }($|[\\s(,]))`, 'gi'); + return new RegExp(`(^|[\\s,(])(${word}($|[\\s(,]))`, 'gi'); }, - // Change comma list + /** + * Change comma list + */ editList(value, callback) { - const origin = list.comma(value); + const origin = list.comma(value); const changed = callback(origin, []); if (origin === changed) { diff --git a/lib/value.js b/lib/value.js index add726d21..0a8499528 100644 --- a/lib/value.js +++ b/lib/value.js @@ -1,50 +1,60 @@ const Prefixer = require('./prefixer'); const OldValue = require('./old-value'); -const utils = require('./utils'); +const utils = require('./utils'); const vendor = require('postcss/lib/vendor'); class Value extends Prefixer { - // Clone decl for each prefixed values + /** + * Clone decl for each prefixed values + */ static save(prefixes, decl) { - const { prop } = decl; - return (() => { - const result = []; - for (let prefix in decl._autoprefixerValues) { - const value = decl._autoprefixerValues[prefix]; - let item; - if (value === decl.value) { - continue; - } + const prop = decl.prop; + const result = []; + + for (let prefix in decl._autoprefixerValues) { + const value = decl._autoprefixerValues[prefix]; + + if (value === decl.value) { + continue; + } + + let item; + const propPrefix = vendor.prefix(prop); - const propPrefix = vendor.prefix(prop); - if (propPrefix === prefix) { - item = decl.value = value; - } else if (propPrefix === '-pie-') { - continue; - } else { - var prefixed = prefixes.prefixed(prop, prefix); - const rule = decl.parent; - if (rule.every( i => i.prop !== prefixed)) { - var trimmed = value.replace(/\s+/, ' '); - const already = rule.some(i => i.prop === decl.prop && i.value.replace(/\s+/, ' ') === trimmed); - - if (!already) { - const cloned = this.clone(decl, { value }); - item = decl.parent.insertBefore(decl, cloned); - } + if (propPrefix === prefix) { + item = decl.value = value; + } else if (propPrefix === '-pie-') { + continue; + } else { + const prefixed = prefixes.prefixed(prop, prefix); + const rule = decl.parent; + if (rule.every(i => i.prop !== prefixed)) { + const trimmed = value.replace(/\s+/, ' '); + const already = rule.some( + i => i.prop === decl.prop && + i.value.replace(/\s+/, ' ') === trimmed + ); + + if (!already) { + const cloned = this.clone(decl, { value }); + item = decl.parent.insertBefore(decl, cloned); } } - result.push(item); } - return result; - })(); + + result.push(item); + } + + return result; } - // Is declaration need to be prefixed + /** + * Is declaration need to be prefixed + */ check(decl) { - const { value } = decl; + const value = decl.value; if (value.indexOf(this.name) !== -1) { return !!value.match(this.regexp()); } else { @@ -52,17 +62,23 @@ class Value extends Prefixer { } } - // Lazy regexp loading + /** + * Lazy regexp loading + */ regexp() { return this.regexpCache || (this.regexpCache = utils.regexp(this.name)); } - // Add prefix to values in string + /** + * Add prefix to values in string + */ replace(string, prefix) { return string.replace(this.regexp(), `$1${prefix}$2`); } - // Get value with comments if it was not changed + /** + * Get value with comments if it was not changed + */ value(decl) { if (decl.raws.value && decl.raws.value.value === decl.value) { return decl.raws.value.raw; @@ -71,19 +87,23 @@ class Value extends Prefixer { } } - // Save values with next prefixed token + /** + * Save values with next prefixed token + */ add(decl, prefix) { if (!decl._autoprefixerValues) { - decl._autoprefixerValues = { }; + decl._autoprefixerValues = {}; } let value = decl._autoprefixerValues[prefix] || this.value(decl); value = this.replace(value, prefix); if (value) { - return decl._autoprefixerValues[prefix] = value; + decl._autoprefixerValues[prefix] = value; } } - // Return function to fast find prefixed value + /** + * Return function to fast find prefixed value + */ old(prefix) { return new OldValue(this.name, prefix + this.name); } diff --git a/package.json b/package.json index 15baf04d8..403dee27c 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,14 @@ "test": "gulp" }, "eslintConfig": { - "extends": "eslint-config-postcss" + "extends": "eslint-config-postcss", + "rules": { + "complexity": "off", + "max-len": [2, 80, { + "ignoreComments": true, + "ignoreStrings": true + }] + } }, "babel": { "presets": [