autoprefixer
Advanced tools
Comparing version 10.4.2 to 10.4.16
@@ -1,2 +0,2 @@ | ||
let unpack = require('caniuse-lite').feature | ||
let unpack = require('caniuse-lite/dist/unpacker/feature') | ||
@@ -71,5 +71,5 @@ function browsersSort(a, b) { | ||
{ | ||
mistakes: ['-khtml-', '-ms-', '-o-'], | ||
browsers, | ||
feature: 'border-radius', | ||
browsers | ||
mistakes: ['-khtml-', '-ms-', '-o-'] | ||
} | ||
@@ -84,5 +84,5 @@ ) | ||
prefix(['box-shadow'], { | ||
mistakes: ['-khtml-'], | ||
browsers, | ||
feature: 'css-boxshadow', | ||
browsers | ||
mistakes: ['-khtml-'] | ||
}) | ||
@@ -109,5 +109,5 @@ ) | ||
{ | ||
mistakes: ['-khtml-', '-ms-'], | ||
browsers, | ||
feature: 'css-animation', | ||
browsers | ||
mistakes: ['-khtml-', '-ms-'] | ||
} | ||
@@ -130,5 +130,5 @@ ) | ||
{ | ||
mistakes: ['-khtml-', '-ms-'], | ||
browsers, | ||
feature: 'css-transitions' | ||
feature: 'css-transitions', | ||
mistakes: ['-khtml-', '-ms-'] | ||
} | ||
@@ -143,4 +143,4 @@ ) | ||
prefix(['transform', 'transform-origin'], { | ||
feature: 'transforms2d', | ||
browsers | ||
browsers, | ||
feature: 'transforms2d' | ||
}) | ||
@@ -154,9 +154,9 @@ ) | ||
prefix(['perspective', 'perspective-origin'], { | ||
feature: 'transforms3d', | ||
browsers | ||
browsers, | ||
feature: 'transforms3d' | ||
}) | ||
return prefix(['transform-style'], { | ||
mistakes: ['-ms-', '-o-'], | ||
browsers, | ||
feature: 'transforms3d' | ||
feature: 'transforms3d', | ||
mistakes: ['-ms-', '-o-'] | ||
}) | ||
@@ -167,5 +167,5 @@ }) | ||
prefix(['backface-visibility'], { | ||
mistakes: ['-ms-', '-o-'], | ||
browsers, | ||
feature: 'transforms3d', | ||
browsers | ||
mistakes: ['-ms-', '-o-'] | ||
}) | ||
@@ -186,2 +186,5 @@ ) | ||
{ | ||
browsers, | ||
feature: 'css-gradients', | ||
mistakes: ['-ms-'], | ||
props: [ | ||
@@ -196,6 +199,3 @@ 'background', | ||
'mask-image' | ||
], | ||
mistakes: ['-ms-'], | ||
feature: 'css-gradients', | ||
browsers | ||
] | ||
} | ||
@@ -221,4 +221,4 @@ ) | ||
{ | ||
feature: 'css-gradients', | ||
browsers | ||
browsers, | ||
feature: 'css-gradients' | ||
} | ||
@@ -233,4 +233,4 @@ ) | ||
prefix(['box-sizing'], { | ||
feature: 'css3-boxsizing', | ||
browsers | ||
browsers, | ||
feature: 'css3-boxsizing' | ||
}) | ||
@@ -244,4 +244,4 @@ ) | ||
prefix(['filter'], { | ||
feature: 'css-filters', | ||
browsers | ||
browsers, | ||
feature: 'css-filters' | ||
}) | ||
@@ -255,2 +255,4 @@ ) | ||
prefix(['filter-function'], { | ||
browsers, | ||
feature: 'css-filter-function', | ||
props: [ | ||
@@ -265,5 +267,3 @@ 'background', | ||
'mask-image' | ||
], | ||
feature: 'css-filter-function', | ||
browsers | ||
] | ||
}) | ||
@@ -273,8 +273,8 @@ ) | ||
// Backdrop-filter | ||
let prefixBackdrop = require('caniuse-lite/data/features/css-backdrop-filter') | ||
let prefixBackdropFilter = require('caniuse-lite/data/features/css-backdrop-filter') | ||
f(prefixBackdrop, { match: /y\sx|y\s#2/ }, browsers => | ||
f(prefixBackdropFilter, { match: /y\sx|y\s#2/ }, browsers => | ||
prefix(['backdrop-filter'], { | ||
feature: 'css-backdrop-filter', | ||
browsers | ||
browsers, | ||
feature: 'css-backdrop-filter' | ||
}) | ||
@@ -288,2 +288,4 @@ ) | ||
prefix(['element'], { | ||
browsers, | ||
feature: 'css-element-function', | ||
props: [ | ||
@@ -298,5 +300,3 @@ 'background', | ||
'mask-image' | ||
], | ||
feature: 'css-element-function', | ||
browsers | ||
] | ||
}) | ||
@@ -323,4 +323,4 @@ ) | ||
{ | ||
feature: 'multicolumn', | ||
browsers | ||
browsers, | ||
feature: 'multicolumn' | ||
} | ||
@@ -331,4 +331,4 @@ ) | ||
prefix(['break-before', 'break-after', 'break-inside'], { | ||
feature: 'multicolumn', | ||
browsers: noff | ||
browsers: noff, | ||
feature: 'multicolumn' | ||
}) | ||
@@ -342,5 +342,5 @@ }) | ||
prefix(['user-select'], { | ||
mistakes: ['-khtml-'], | ||
browsers, | ||
feature: 'user-select-none', | ||
browsers | ||
mistakes: ['-khtml-'] | ||
}) | ||
@@ -361,9 +361,9 @@ ) | ||
prefix(['display-flex', 'inline-flex'], { | ||
props: ['display'], | ||
browsers, | ||
feature: 'flexbox', | ||
browsers | ||
props: ['display'] | ||
}) | ||
prefix(['flex', 'flex-grow', 'flex-shrink', 'flex-basis'], { | ||
feature: 'flexbox', | ||
browsers | ||
browsers, | ||
feature: 'flexbox' | ||
}) | ||
@@ -382,4 +382,4 @@ prefix( | ||
{ | ||
feature: 'flexbox', | ||
browsers | ||
browsers, | ||
feature: 'flexbox' | ||
} | ||
@@ -391,8 +391,8 @@ ) | ||
add(['display-flex', 'inline-flex'], { | ||
feature: 'flexbox', | ||
browsers | ||
browsers, | ||
feature: 'flexbox' | ||
}) | ||
add(['flex', 'flex-grow', 'flex-shrink', 'flex-basis'], { | ||
feature: 'flexbox', | ||
browsers | ||
browsers, | ||
feature: 'flexbox' | ||
}) | ||
@@ -411,4 +411,4 @@ add( | ||
{ | ||
feature: 'flexbox', | ||
browsers | ||
browsers, | ||
feature: 'flexbox' | ||
} | ||
@@ -423,5 +423,5 @@ ) | ||
prefix(['calc'], { | ||
props: ['*'], | ||
browsers, | ||
feature: 'calc', | ||
browsers | ||
props: ['*'] | ||
}) | ||
@@ -435,4 +435,4 @@ ) | ||
prefix(['background-origin', 'background-size'], { | ||
feature: 'background-img-opts', | ||
browsers | ||
browsers, | ||
feature: 'background-img-opts' | ||
}) | ||
@@ -446,4 +446,4 @@ ) | ||
prefix(['background-clip'], { | ||
feature: 'background-clip-text', | ||
browsers | ||
browsers, | ||
feature: 'background-clip-text' | ||
}) | ||
@@ -463,4 +463,4 @@ ) | ||
{ | ||
feature: 'font-feature', | ||
browsers | ||
browsers, | ||
feature: 'font-feature' | ||
} | ||
@@ -475,4 +475,4 @@ ) | ||
prefix(['font-kerning'], { | ||
feature: 'font-kerning', | ||
browsers | ||
browsers, | ||
feature: 'font-kerning' | ||
}) | ||
@@ -486,4 +486,4 @@ ) | ||
prefix(['border-image'], { | ||
feature: 'border-image', | ||
browsers | ||
browsers, | ||
feature: 'border-image' | ||
}) | ||
@@ -497,5 +497,5 @@ ) | ||
prefix(['::selection'], { | ||
selector: true, | ||
browsers, | ||
feature: 'css-selection', | ||
browsers | ||
selector: true | ||
}) | ||
@@ -509,5 +509,5 @@ ) | ||
prefix(['::placeholder'], { | ||
selector: true, | ||
browsers: browsers.concat(['ie 10 old', 'ie 11 old', 'firefox 18 old']), | ||
feature: 'css-placeholder', | ||
browsers: browsers.concat(['ie 10 old', 'ie 11 old', 'firefox 18 old']) | ||
selector: true | ||
}) | ||
@@ -521,5 +521,5 @@ }) | ||
prefix([':placeholder-shown'], { | ||
selector: true, | ||
browsers, | ||
feature: 'css-placeholder-shown', | ||
browsers | ||
selector: true | ||
}) | ||
@@ -533,4 +533,4 @@ }) | ||
prefix(['hyphens'], { | ||
feature: 'css-hyphens', | ||
browsers | ||
browsers, | ||
feature: 'css-hyphens' | ||
}) | ||
@@ -544,13 +544,17 @@ ) | ||
prefix([':fullscreen'], { | ||
selector: true, | ||
browsers, | ||
feature: 'fullscreen', | ||
browsers | ||
selector: true | ||
}) | ||
) | ||
f(prefixFullscreen, { match: /x(\s#2|$)/ }, browsers => | ||
// ::backdrop pseudo-element | ||
// https://caniuse.com/mdn-css_selectors_backdrop | ||
let prefixBackdrop = require('caniuse-lite/data/features/mdn-css-backdrop-pseudo-element') | ||
f(prefixBackdrop, browsers => | ||
prefix(['::backdrop'], { | ||
selector: true, | ||
feature: 'fullscreen', | ||
browsers | ||
browsers, | ||
feature: 'backdrop', | ||
selector: true | ||
}) | ||
@@ -564,5 +568,5 @@ ) | ||
prefix(['::file-selector-button'], { | ||
selector: true, | ||
browsers, | ||
feature: 'file-selector-button', | ||
browsers | ||
selector: true | ||
}) | ||
@@ -576,5 +580,5 @@ ) | ||
prefix([':autofill'], { | ||
selector: true, | ||
browsers, | ||
feature: 'css-autofill', | ||
browsers | ||
selector: true | ||
}) | ||
@@ -588,4 +592,4 @@ ) | ||
prefix(['tab-size'], { | ||
feature: 'css3-tabsize', | ||
browsers | ||
browsers, | ||
feature: 'css3-tabsize' | ||
}) | ||
@@ -620,5 +624,5 @@ ) | ||
prefix(['max-content', 'min-content'], { | ||
props: sizeProps, | ||
browsers, | ||
feature: 'intrinsic-width', | ||
browsers | ||
props: sizeProps | ||
}) | ||
@@ -629,5 +633,5 @@ ) | ||
prefix(['fill', 'fill-available'], { | ||
props: sizeProps, | ||
browsers, | ||
feature: 'intrinsic-width', | ||
browsers | ||
props: sizeProps | ||
}) | ||
@@ -638,5 +642,5 @@ ) | ||
prefix(['fit-content'], { | ||
props: sizeProps, | ||
browsers, | ||
feature: 'intrinsic-width', | ||
browsers | ||
props: sizeProps | ||
}) | ||
@@ -651,5 +655,5 @@ ) | ||
prefix(['stretch'], { | ||
props: sizeProps, | ||
browsers, | ||
feature: 'css-width-stretch', | ||
browsers | ||
props: sizeProps | ||
}) | ||
@@ -663,5 +667,5 @@ ) | ||
prefix(['zoom-in', 'zoom-out'], { | ||
props: ['cursor'], | ||
browsers, | ||
feature: 'css3-cursors-newer', | ||
browsers | ||
props: ['cursor'] | ||
}) | ||
@@ -675,5 +679,5 @@ ) | ||
prefix(['grab', 'grabbing'], { | ||
props: ['cursor'], | ||
browsers, | ||
feature: 'css3-cursors-grab', | ||
browsers | ||
props: ['cursor'] | ||
}) | ||
@@ -687,5 +691,5 @@ ) | ||
prefix(['sticky'], { | ||
props: ['position'], | ||
browsers, | ||
feature: 'css-sticky', | ||
browsers | ||
props: ['position'] | ||
}) | ||
@@ -699,4 +703,4 @@ ) | ||
prefix(['touch-action'], { | ||
feature: 'pointer', | ||
browsers | ||
browsers, | ||
feature: 'pointer' | ||
}) | ||
@@ -708,24 +712,45 @@ ) | ||
f(prefixDecoration, browsers => | ||
prefix( | ||
[ | ||
'text-decoration-style', | ||
'text-decoration-color', | ||
'text-decoration-line', | ||
'text-decoration' | ||
], | ||
{ | ||
feature: 'text-decoration', | ||
browsers | ||
} | ||
) | ||
) | ||
f(prefixDecoration, { match: /x.*#[235]/ }, browsers => | ||
prefix(['text-decoration-skip', 'text-decoration-skip-ink'], { | ||
feature: 'text-decoration', | ||
browsers | ||
browsers, | ||
feature: 'text-decoration' | ||
}) | ||
) | ||
let prefixDecorationShorthand = require('caniuse-lite/data/features/mdn-text-decoration-shorthand') | ||
f(prefixDecorationShorthand, browsers => | ||
prefix(['text-decoration'], { | ||
browsers, | ||
feature: 'text-decoration' | ||
}) | ||
) | ||
let prefixDecorationColor = require('caniuse-lite/data/features/mdn-text-decoration-color') | ||
f(prefixDecorationColor, browsers => | ||
prefix(['text-decoration-color'], { | ||
browsers, | ||
feature: 'text-decoration' | ||
}) | ||
) | ||
let prefixDecorationLine = require('caniuse-lite/data/features/mdn-text-decoration-line') | ||
f(prefixDecorationLine, browsers => | ||
prefix(['text-decoration-line'], { | ||
browsers, | ||
feature: 'text-decoration' | ||
}) | ||
) | ||
let prefixDecorationStyle = require('caniuse-lite/data/features/mdn-text-decoration-style') | ||
f(prefixDecorationStyle, browsers => | ||
prefix(['text-decoration-style'], { | ||
browsers, | ||
feature: 'text-decoration' | ||
}) | ||
) | ||
// Text Size Adjust | ||
@@ -736,4 +761,4 @@ let prefixTextSizeAdjust = require('caniuse-lite/data/features/text-size-adjust') | ||
prefix(['text-size-adjust'], { | ||
feature: 'text-size-adjust', | ||
browsers | ||
browsers, | ||
feature: 'text-size-adjust' | ||
}) | ||
@@ -757,4 +782,4 @@ ) | ||
{ | ||
feature: 'css-masks', | ||
browsers | ||
browsers, | ||
feature: 'css-masks' | ||
} | ||
@@ -773,4 +798,4 @@ ) | ||
{ | ||
feature: 'css-masks', | ||
browsers | ||
browsers, | ||
feature: 'css-masks' | ||
} | ||
@@ -785,4 +810,4 @@ ) | ||
prefix(['clip-path'], { | ||
feature: 'css-clip-path', | ||
browsers | ||
browsers, | ||
feature: 'css-clip-path' | ||
}) | ||
@@ -796,4 +821,4 @@ ) | ||
prefix(['box-decoration-break'], { | ||
feature: 'css-boxdecorationbreak', | ||
browsers | ||
browsers, | ||
feature: 'css-boxdecorationbreak' | ||
}) | ||
@@ -807,4 +832,4 @@ ) | ||
prefix(['object-fit', 'object-position'], { | ||
feature: 'object-fit', | ||
browsers | ||
browsers, | ||
feature: 'object-fit' | ||
}) | ||
@@ -818,4 +843,4 @@ ) | ||
prefix(['shape-margin', 'shape-outside', 'shape-image-threshold'], { | ||
feature: 'css-shapes', | ||
browsers | ||
browsers, | ||
feature: 'css-shapes' | ||
}) | ||
@@ -829,4 +854,4 @@ ) | ||
prefix(['text-overflow'], { | ||
feature: 'text-overflow', | ||
browsers | ||
browsers, | ||
feature: 'text-overflow' | ||
}) | ||
@@ -840,4 +865,4 @@ ) | ||
prefix(['@viewport'], { | ||
feature: 'css-deviceadaptation', | ||
browsers | ||
browsers, | ||
feature: 'css-deviceadaptation' | ||
}) | ||
@@ -851,4 +876,4 @@ ) | ||
prefix(['@resolution'], { | ||
feature: 'css-media-resolution', | ||
browsers | ||
browsers, | ||
feature: 'css-media-resolution' | ||
}) | ||
@@ -862,4 +887,4 @@ ) | ||
prefix(['text-align-last'], { | ||
feature: 'css-text-align-last', | ||
browsers | ||
browsers, | ||
feature: 'css-text-align-last' | ||
}) | ||
@@ -873,5 +898,5 @@ ) | ||
prefix(['pixelated'], { | ||
props: ['image-rendering'], | ||
browsers, | ||
feature: 'css-crisp-edges', | ||
browsers | ||
props: ['image-rendering'] | ||
}) | ||
@@ -882,4 +907,4 @@ ) | ||
prefix(['image-rendering'], { | ||
feature: 'css-crisp-edges', | ||
browsers | ||
browsers, | ||
feature: 'css-crisp-edges' | ||
}) | ||
@@ -902,4 +927,4 @@ ) | ||
{ | ||
feature: 'css-logical-props', | ||
browsers | ||
browsers, | ||
feature: 'css-logical-props' | ||
} | ||
@@ -920,4 +945,4 @@ ) | ||
{ | ||
feature: 'css-logical-props', | ||
browsers | ||
browsers, | ||
feature: 'css-logical-props' | ||
} | ||
@@ -932,4 +957,4 @@ ) | ||
prefix(['appearance'], { | ||
feature: 'css-appearance', | ||
browsers | ||
browsers, | ||
feature: 'css-appearance' | ||
}) | ||
@@ -951,4 +976,4 @@ ) | ||
{ | ||
feature: 'css-snappoints', | ||
browsers | ||
browsers, | ||
feature: 'css-snappoints' | ||
} | ||
@@ -963,4 +988,4 @@ ) | ||
prefix(['flow-into', 'flow-from', 'region-fragment'], { | ||
feature: 'css-regions', | ||
browsers | ||
browsers, | ||
feature: 'css-regions' | ||
}) | ||
@@ -974,2 +999,4 @@ ) | ||
prefix(['image-set'], { | ||
browsers, | ||
feature: 'css-image-set', | ||
props: [ | ||
@@ -985,5 +1012,3 @@ 'background', | ||
'content' | ||
], | ||
feature: 'css-image-set', | ||
browsers | ||
] | ||
}) | ||
@@ -997,4 +1022,4 @@ ) | ||
prefix(['writing-mode'], { | ||
feature: 'css-writing-mode', | ||
browsers | ||
browsers, | ||
feature: 'css-writing-mode' | ||
}) | ||
@@ -1008,2 +1033,4 @@ ) | ||
prefix(['cross-fade'], { | ||
browsers, | ||
feature: 'css-cross-fade', | ||
props: [ | ||
@@ -1018,5 +1045,3 @@ 'background', | ||
'mask-image' | ||
], | ||
feature: 'css-cross-fade', | ||
browsers | ||
] | ||
}) | ||
@@ -1030,5 +1055,5 @@ ) | ||
prefix([':read-only', ':read-write'], { | ||
selector: true, | ||
browsers, | ||
feature: 'css-read-only-write', | ||
browsers | ||
selector: true | ||
}) | ||
@@ -1049,4 +1074,4 @@ ) | ||
{ | ||
feature: 'text-emphasis', | ||
browsers | ||
browsers, | ||
feature: 'text-emphasis' | ||
} | ||
@@ -1061,5 +1086,5 @@ ) | ||
prefix(['display-grid', 'inline-grid'], { | ||
props: ['display'], | ||
browsers, | ||
feature: 'css-grid', | ||
browsers | ||
props: ['display'] | ||
}) | ||
@@ -1082,4 +1107,4 @@ prefix( | ||
{ | ||
feature: 'css-grid', | ||
browsers | ||
browsers, | ||
feature: 'css-grid' | ||
} | ||
@@ -1091,4 +1116,4 @@ ) | ||
prefix(['grid-column-align', 'grid-row-align'], { | ||
feature: 'css-grid', | ||
browsers | ||
browsers, | ||
feature: 'css-grid' | ||
}) | ||
@@ -1102,4 +1127,4 @@ ) | ||
prefix(['text-spacing'], { | ||
feature: 'css-text-spacing', | ||
browsers | ||
browsers, | ||
feature: 'css-text-spacing' | ||
}) | ||
@@ -1113,5 +1138,5 @@ ) | ||
prefix([':any-link'], { | ||
selector: true, | ||
browsers, | ||
feature: 'css-any-link', | ||
browsers | ||
selector: true | ||
}) | ||
@@ -1121,25 +1146,30 @@ ) | ||
// unicode-bidi | ||
let prefixBidi = require('caniuse-lite/data/features/css-unicode-bidi') | ||
f(prefixBidi, browsers => | ||
let bidiIsolate = require('caniuse-lite/data/features/mdn-css-unicode-bidi-isolate') | ||
f(bidiIsolate, browsers => | ||
prefix(['isolate'], { | ||
props: ['unicode-bidi'], | ||
browsers, | ||
feature: 'css-unicode-bidi', | ||
browsers | ||
props: ['unicode-bidi'] | ||
}) | ||
) | ||
f(prefixBidi, { match: /y x|a x #2/ }, browsers => | ||
let bidiPlaintext = require('caniuse-lite/data/features/mdn-css-unicode-bidi-plaintext') | ||
f(bidiPlaintext, browsers => | ||
prefix(['plaintext'], { | ||
props: ['unicode-bidi'], | ||
browsers, | ||
feature: 'css-unicode-bidi', | ||
browsers | ||
props: ['unicode-bidi'] | ||
}) | ||
) | ||
f(prefixBidi, { match: /y x/ }, browsers => | ||
let bidiOverride = require('caniuse-lite/data/features/mdn-css-unicode-bidi-isolate-override') | ||
f(bidiOverride, { match: /y x/ }, browsers => | ||
prefix(['isolate-override'], { | ||
props: ['unicode-bidi'], | ||
browsers, | ||
feature: 'css-unicode-bidi', | ||
browsers | ||
props: ['unicode-bidi'] | ||
}) | ||
@@ -1153,17 +1183,7 @@ ) | ||
prefix(['overscroll-behavior'], { | ||
feature: 'css-overscroll-behavior', | ||
browsers | ||
browsers, | ||
feature: 'css-overscroll-behavior' | ||
}) | ||
) | ||
// color-adjust | ||
let prefixColorAdjust = require('caniuse-lite/data/features/css-color-adjust') | ||
f(prefixColorAdjust, browsers => | ||
prefix(['color-adjust'], { | ||
feature: 'css-color-adjust', | ||
browsers | ||
}) | ||
) | ||
// text-orientation | ||
@@ -1174,5 +1194,15 @@ let prefixTextOrientation = require('caniuse-lite/data/features/css-text-orientation') | ||
prefix(['text-orientation'], { | ||
feature: 'css-text-orientation', | ||
browsers | ||
browsers, | ||
feature: 'css-text-orientation' | ||
}) | ||
) | ||
// print-color-adjust | ||
let prefixPrintAdjust = require('caniuse-lite/data/features/css-print-color-adjust') | ||
f(prefixPrintAdjust, browsers => | ||
prefix(['print-color-adjust', 'color-adjust'], { | ||
browsers, | ||
feature: 'css-print-color-adjust' | ||
}) | ||
) |
let browserslist = require('browserslist') | ||
let { agents } = require('caniuse-lite') | ||
let { agents } = require('caniuse-lite/dist/unpacker/agents') | ||
let pico = require('picocolors') | ||
@@ -99,5 +99,5 @@ | ||
let brwlstOpts = { | ||
env: options.env, | ||
ignoreUnknownVersions: options.ignoreUnknownVersions, | ||
stats: options.stats, | ||
env: options.env | ||
stats: options.stats | ||
} | ||
@@ -118,8 +118,17 @@ | ||
return { | ||
browsers: reqs, | ||
info(opts) { | ||
opts = opts || {} | ||
opts.from = opts.from || process.cwd() | ||
return getInfo(loadPrefixes(opts)) | ||
}, | ||
options, | ||
postcssPlugin: 'autoprefixer', | ||
prepare(result) { | ||
let prefixes = loadPrefixes({ | ||
from: result.opts.from, | ||
env: options.env | ||
env: options.env, | ||
from: result.opts.from | ||
}) | ||
@@ -138,12 +147,3 @@ | ||
} | ||
}, | ||
info(opts) { | ||
opts = opts || {} | ||
opts.from = opts.from || process.cwd() | ||
return getInfo(loadPrefixes(opts)) | ||
}, | ||
options, | ||
browsers: reqs | ||
} | ||
} | ||
@@ -150,0 +150,0 @@ } |
let browserslist = require('browserslist') | ||
let agents = require('caniuse-lite').agents | ||
let { agents } = require('caniuse-lite/dist/unpacker/agents') | ||
@@ -7,2 +7,9 @@ let utils = require('./utils') | ||
class Browsers { | ||
constructor(data, requirements, options, browserslistOpts) { | ||
this.data = data | ||
this.options = options || {} | ||
this.browserslistOpts = browserslistOpts || {} | ||
this.selected = this.parse(requirements) | ||
} | ||
/** | ||
@@ -39,7 +46,7 @@ * Return all prefixes for default browser data | ||
constructor(data, requirements, options, browserslistOpts) { | ||
this.data = data | ||
this.options = options || {} | ||
this.browserslistOpts = browserslistOpts || {} | ||
this.selected = this.parse(requirements) | ||
/** | ||
* Is browser is selected by requirements | ||
*/ | ||
isSelected(browser) { | ||
return this.selected.includes(browser) | ||
} | ||
@@ -72,11 +79,4 @@ | ||
} | ||
/** | ||
* Is browser is selected by requirements | ||
*/ | ||
isSelected(browser) { | ||
return this.selected.includes(browser) | ||
} | ||
} | ||
module.exports = Browsers |
@@ -7,54 +7,66 @@ let Prefixer = require('./prefixer') | ||
/** | ||
* Always true, because we already get prefixer by property name | ||
* Clone and add prefixes for declaration | ||
*/ | ||
check(/* decl */) { | ||
return true | ||
add(decl, prefix, prefixes, result) { | ||
let prefixed = this.prefixed(decl.prop, prefix) | ||
if ( | ||
this.isAlready(decl, prefixed) || | ||
this.otherPrefixes(decl.value, prefix) | ||
) { | ||
return undefined | ||
} | ||
return this.insert(decl, prefix, prefixes, result) | ||
} | ||
/** | ||
* Return prefixed version of property | ||
* Calculate indentation to create visual cascade | ||
*/ | ||
prefixed(prop, prefix) { | ||
return prefix + prop | ||
calcBefore(prefixes, decl, prefix = '') { | ||
let max = this.maxPrefixed(prefixes, decl) | ||
let diff = max - utils.removeNote(prefix).length | ||
let before = decl.raw('before') | ||
if (diff > 0) { | ||
before += Array(diff).fill(' ').join('') | ||
} | ||
return before | ||
} | ||
/** | ||
* Return unprefixed version of property | ||
* Always true, because we already get prefixer by property name | ||
*/ | ||
normalize(prop) { | ||
return prop | ||
check(/* decl */) { | ||
return true | ||
} | ||
/** | ||
* Check `value`, that it contain other prefixes, rather than `prefix` | ||
* Clone and insert new declaration | ||
*/ | ||
otherPrefixes(value, prefix) { | ||
for (let other of Browsers.prefixes()) { | ||
if (other === prefix) { | ||
continue | ||
} | ||
if (value.includes(other)) { | ||
return true | ||
} | ||
insert(decl, prefix, prefixes) { | ||
let cloned = this.set(this.clone(decl), prefix) | ||
if (!cloned) return undefined | ||
let already = decl.parent.some( | ||
i => i.prop === cloned.prop && i.value === cloned.value | ||
) | ||
if (already) { | ||
return undefined | ||
} | ||
return false | ||
} | ||
/** | ||
* Set prefix to declaration | ||
*/ | ||
set(decl, prefix) { | ||
decl.prop = this.prefixed(decl.prop, prefix) | ||
return decl | ||
if (this.needCascade(decl)) { | ||
cloned.raws.before = this.calcBefore(prefixes, decl, prefix) | ||
} | ||
return decl.parent.insertBefore(decl, cloned) | ||
} | ||
/** | ||
* Should we use visual cascade for prefixes | ||
* Did this declaration has this prefix above | ||
*/ | ||
needCascade(decl) { | ||
if (!decl._autoprefixerCascade) { | ||
decl._autoprefixerCascade = | ||
this.all.options.cascade !== false && decl.raw('before').includes('\n') | ||
isAlready(decl, 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 decl._autoprefixerCascade | ||
return already | ||
} | ||
@@ -83,78 +95,46 @@ | ||
/** | ||
* Calculate indentation to create visual cascade | ||
* Should we use visual cascade for prefixes | ||
*/ | ||
calcBefore(prefixes, decl, prefix = '') { | ||
let max = this.maxPrefixed(prefixes, decl) | ||
let diff = max - utils.removeNote(prefix).length | ||
let before = decl.raw('before') | ||
if (diff > 0) { | ||
before += Array(diff).fill(' ').join('') | ||
needCascade(decl) { | ||
if (!decl._autoprefixerCascade) { | ||
decl._autoprefixerCascade = | ||
this.all.options.cascade !== false && decl.raw('before').includes('\n') | ||
} | ||
return before | ||
return decl._autoprefixerCascade | ||
} | ||
/** | ||
* Remove visual cascade | ||
* Return unprefixed version of property | ||
*/ | ||
restoreBefore(decl) { | ||
let lines = decl.raw('before').split('\n') | ||
let min = lines[lines.length - 1] | ||
this.all.group(decl).up(prefixed => { | ||
let array = prefixed.raw('before').split('\n') | ||
let last = array[array.length - 1] | ||
if (last.length < min.length) { | ||
min = last | ||
} | ||
}) | ||
lines[lines.length - 1] = min | ||
decl.raws.before = lines.join('\n') | ||
normalize(prop) { | ||
return prop | ||
} | ||
/** | ||
* Clone and insert new declaration | ||
* Return list of prefixed properties to clean old prefixes | ||
*/ | ||
insert(decl, prefix, prefixes) { | ||
let cloned = this.set(this.clone(decl), prefix) | ||
if (!cloned) return undefined | ||
let already = decl.parent.some( | ||
i => i.prop === cloned.prop && i.value === cloned.value | ||
) | ||
if (already) { | ||
return undefined | ||
} | ||
if (this.needCascade(decl)) { | ||
cloned.raws.before = this.calcBefore(prefixes, decl, prefix) | ||
} | ||
return decl.parent.insertBefore(decl, cloned) | ||
old(prop, prefix) { | ||
return [this.prefixed(prop, prefix)] | ||
} | ||
/** | ||
* Did this declaration has this prefix above | ||
* Check `value`, that it contain other prefixes, rather than `prefix` | ||
*/ | ||
isAlready(decl, prefixed) { | ||
let already = this.all.group(decl).up(i => i.prop === prefixed) | ||
if (!already) { | ||
already = this.all.group(decl).down(i => i.prop === prefixed) | ||
otherPrefixes(value, prefix) { | ||
for (let other of Browsers.prefixes()) { | ||
if (other === prefix) { | ||
continue | ||
} | ||
if (value.includes(other)) { | ||
return value.replace(/var\([^)]+\)/, '').includes(other) | ||
} | ||
} | ||
return already | ||
return false | ||
} | ||
/** | ||
* Clone and add prefixes for declaration | ||
* Return prefixed version of property | ||
*/ | ||
add(decl, prefix, prefixes, result) { | ||
let prefixed = this.prefixed(decl.prop, prefix) | ||
if ( | ||
this.isAlready(decl, prefixed) || | ||
this.otherPrefixes(decl.value, prefix) | ||
) { | ||
return undefined | ||
} | ||
return this.insert(decl, prefix, prefixes, result) | ||
prefixed(prop, prefix) { | ||
return prefix + prop | ||
} | ||
@@ -182,9 +162,29 @@ | ||
/** | ||
* Return list of prefixed properties to clean old prefixes | ||
* Remove visual cascade | ||
*/ | ||
old(prop, prefix) { | ||
return [this.prefixed(prop, prefix)] | ||
restoreBefore(decl) { | ||
let lines = decl.raw('before').split('\n') | ||
let min = lines[lines.length - 1] | ||
this.all.group(decl).up(prefixed => { | ||
let array = prefixed.raw('before').split('\n') | ||
let last = array[array.length - 1] | ||
if (last.length < min.length) { | ||
min = last | ||
} | ||
}) | ||
lines[lines.length - 1] = min | ||
decl.raws.before = lines.join('\n') | ||
} | ||
/** | ||
* Set prefix to declaration | ||
*/ | ||
set(decl, prefix) { | ||
decl.prop = this.prefixed(decl.prop, prefix) | ||
return decl | ||
} | ||
} | ||
module.exports = Declaration |
@@ -6,2 +6,9 @@ let flexSpec = require('./flex-spec') | ||
/** | ||
* Return property name by final spec | ||
*/ | ||
normalize() { | ||
return 'align-content' | ||
} | ||
/** | ||
* Change property name for 2012 spec | ||
@@ -19,9 +26,2 @@ */ | ||
/** | ||
* Return property name by final spec | ||
*/ | ||
normalize() { | ||
return 'align-content' | ||
} | ||
/** | ||
* Change value for 2012 spec and ignore prefix for 2009 | ||
@@ -47,6 +47,6 @@ */ | ||
'flex-start': 'start', | ||
'space-between': 'justify', | ||
'space-around': 'distribute' | ||
'space-around': 'distribute', | ||
'space-between': 'justify' | ||
} | ||
module.exports = AlignContent |
@@ -6,2 +6,9 @@ let flexSpec = require('./flex-spec') | ||
/** | ||
* Return property name by final spec | ||
*/ | ||
normalize() { | ||
return 'align-items' | ||
} | ||
/** | ||
* Change property name for 2009 and 2012 specs | ||
@@ -22,9 +29,2 @@ */ | ||
/** | ||
* Return property name by final spec | ||
*/ | ||
normalize() { | ||
return 'align-items' | ||
} | ||
/** | ||
* Change value for 2009 and 2012 specs | ||
@@ -31,0 +31,0 @@ */ |
@@ -15,2 +15,9 @@ let flexSpec = require('./flex-spec') | ||
/** | ||
* Return property name by final spec | ||
*/ | ||
normalize() { | ||
return 'align-self' | ||
} | ||
/** | ||
* Change property name for 2012 specs | ||
@@ -28,9 +35,2 @@ */ | ||
/** | ||
* Return property name by final spec | ||
*/ | ||
normalize() { | ||
return 'align-self' | ||
} | ||
/** | ||
* Change value for 2012 spec and ignore prefix for 2009 | ||
@@ -37,0 +37,0 @@ */ |
@@ -9,7 +9,3 @@ let Selector = require('../selector') | ||
if (this.prefixes) { | ||
this.prefixes = utils.uniq( | ||
this.prefixes.map(i => { | ||
return '-webkit-' | ||
}) | ||
) | ||
this.prefixes = utils.uniq(this.prefixes.map(() => '-webkit-')) | ||
} | ||
@@ -16,0 +12,0 @@ } |
@@ -5,2 +5,12 @@ let Declaration = require('../declaration') | ||
/** | ||
* Return property name by spec | ||
*/ | ||
normalize(prop) { | ||
if (prop.includes('-before')) { | ||
return prop.replace('-before', '-block-start') | ||
} | ||
return prop.replace('-after', '-block-end') | ||
} | ||
/** | ||
* Use old syntax for -moz- and -webkit- | ||
@@ -14,12 +24,2 @@ */ | ||
} | ||
/** | ||
* Return property name by spec | ||
*/ | ||
normalize(prop) { | ||
if (prop.includes('-before')) { | ||
return prop.replace('-before', '-block-start') | ||
} | ||
return prop.replace('-after', '-block-end') | ||
} | ||
} | ||
@@ -26,0 +26,0 @@ |
@@ -5,2 +5,9 @@ let Declaration = require('../declaration') | ||
/** | ||
* Return unprefixed version of property | ||
*/ | ||
normalize(prop) { | ||
return BorderRadius.toNormal[prop] || prop | ||
} | ||
/** | ||
* Change syntax, when add Mozilla prefix | ||
@@ -14,9 +21,2 @@ */ | ||
} | ||
/** | ||
* Return unprefixed version of property | ||
*/ | ||
normalize(prop) { | ||
return BorderRadius.toNormal[prop] || prop | ||
} | ||
} | ||
@@ -23,0 +23,0 @@ |
@@ -5,6 +5,12 @@ let Declaration = require('../declaration') | ||
/** | ||
* Change name for -webkit- and -moz- prefix | ||
* Don’t prefix some values | ||
*/ | ||
prefixed(prop, prefix) { | ||
return `${prefix}column-${prop}` | ||
insert(decl, prefix, prefixes) { | ||
if (decl.prop !== 'break-inside') { | ||
return super.insert(decl, prefix, prefixes) | ||
} | ||
if (/region/i.test(decl.value) || /page/i.test(decl.value)) { | ||
return undefined | ||
} | ||
return super.insert(decl, prefix, prefixes) | ||
} | ||
@@ -26,2 +32,9 @@ | ||
/** | ||
* Change name for -webkit- and -moz- prefix | ||
*/ | ||
prefixed(prop, prefix) { | ||
return `${prefix}column-${prop}` | ||
} | ||
/** | ||
* Change prefixed value for avoid-column and avoid-page | ||
@@ -38,15 +51,2 @@ */ | ||
} | ||
/** | ||
* Don’t prefix some values | ||
*/ | ||
insert(decl, prefix, prefixes) { | ||
if (decl.prop !== 'break-inside') { | ||
return super.insert(decl, prefix, prefixes) | ||
} | ||
if (/region/i.test(decl.value) || /page/i.test(decl.value)) { | ||
return undefined | ||
} | ||
return super.insert(decl, prefix, prefixes) | ||
} | ||
} | ||
@@ -53,0 +53,0 @@ |
@@ -21,2 +21,11 @@ let flexSpec = require('./flex-spec') | ||
/** | ||
* Change value for old specs | ||
*/ | ||
old(prefix) { | ||
let prefixed = this.prefixed(prefix) | ||
if (!prefixed) return undefined | ||
return new OldValue(this.name, prefixed) | ||
} | ||
/** | ||
* Return value by spec | ||
@@ -53,11 +62,2 @@ */ | ||
} | ||
/** | ||
* Change value for old specs | ||
*/ | ||
old(prefix) { | ||
let prefixed = this.prefixed(prefix) | ||
if (!prefixed) return undefined | ||
return new OldValue(this.name, prefixed) | ||
} | ||
} | ||
@@ -64,0 +64,0 @@ |
@@ -9,7 +9,3 @@ let Selector = require('../selector') | ||
if (this.prefixes) { | ||
this.prefixes = utils.uniq( | ||
this.prefixes.map(i => { | ||
return '-webkit-' | ||
}) | ||
) | ||
this.prefixes = utils.uniq(this.prefixes.map(() => '-webkit-')) | ||
} | ||
@@ -16,0 +12,0 @@ } |
@@ -6,9 +6,2 @@ let flexSpec = require('./flex-spec') | ||
/** | ||
* Return property name by final spec | ||
*/ | ||
normalize() { | ||
return 'flex-direction' | ||
} | ||
/** | ||
* Use two properties for 2009 spec | ||
@@ -58,2 +51,9 @@ */ | ||
/** | ||
* Return property name by final spec | ||
*/ | ||
normalize() { | ||
return 'flex-direction' | ||
} | ||
/** | ||
* Clean two properties for 2009 spec | ||
@@ -60,0 +60,0 @@ */ |
@@ -8,2 +8,9 @@ let list = require('postcss').list | ||
/** | ||
* Return property name by final spec | ||
*/ | ||
normalize() { | ||
return 'flex' | ||
} | ||
/** | ||
* Change property name for 2009 spec | ||
@@ -21,9 +28,2 @@ */ | ||
/** | ||
* Return property name by final spec | ||
*/ | ||
normalize() { | ||
return 'flex' | ||
} | ||
/** | ||
* Spec 2009 supports only first argument | ||
@@ -30,0 +30,0 @@ * Spec 2012 disallows unitless basis |
@@ -12,131 +12,75 @@ let parser = require('postcss-value-parser') | ||
/** | ||
* Change degrees for webkit prefix | ||
* Do not add non-webkit prefixes for list-style and object | ||
*/ | ||
replace(string, prefix) { | ||
let ast = parser(string) | ||
for (let 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') { | ||
let changes = this.oldWebkit(node) | ||
if (!changes) { | ||
return false | ||
} | ||
} else { | ||
node.nodes = this.convertDirection(node.nodes) | ||
node.value = prefix + node.value | ||
} | ||
add(decl, prefix) { | ||
let p = decl.prop | ||
if (p.includes('mask')) { | ||
if (prefix === '-webkit-' || prefix === '-webkit- old') { | ||
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(decl, prefix) | ||
} | ||
} else { | ||
return super.add(decl, prefix) | ||
} | ||
return ast.toString() | ||
return undefined | ||
} | ||
/** | ||
* Replace first token | ||
* Get div token from exists parameters | ||
*/ | ||
replaceFirst(params, ...words) { | ||
let prefix = words.map(i => { | ||
if (i === ' ') { | ||
return { type: 'space', value: i } | ||
cloneDiv(params) { | ||
for (let i of params) { | ||
if (i.type === 'div' && i.value === ',') { | ||
return i | ||
} | ||
return { type: 'word', value: i } | ||
}) | ||
return prefix.concat(params.slice(1)) | ||
} | ||
/** | ||
* Convert angle unit to deg | ||
*/ | ||
normalizeUnit(str, full) { | ||
let num = parseFloat(str) | ||
let deg = (num / full) * 360 | ||
return `${deg}deg` | ||
} | ||
/** | ||
* Normalize angle | ||
*/ | ||
normalize(nodes) { | ||
if (!nodes[0]) return nodes | ||
if (/-?\d+(.\d+)?grad/.test(nodes[0].value)) { | ||
nodes[0].value = this.normalizeUnit(nodes[0].value, 400) | ||
} else if (/-?\d+(.\d+)?rad/.test(nodes[0].value)) { | ||
nodes[0].value = this.normalizeUnit(nodes[0].value, 2 * Math.PI) | ||
} else if (/-?\d+(.\d+)?turn/.test(nodes[0].value)) { | ||
nodes[0].value = this.normalizeUnit(nodes[0].value, 1) | ||
} else if (nodes[0].value.includes('deg')) { | ||
let num = parseFloat(nodes[0].value) | ||
num = range.wrap(0, 360, num) | ||
nodes[0].value = `${num}deg` | ||
} | ||
if (nodes[0].value === '0deg') { | ||
nodes = this.replaceFirst(nodes, 'to', ' ', 'top') | ||
} else if (nodes[0].value === '90deg') { | ||
nodes = this.replaceFirst(nodes, 'to', ' ', 'right') | ||
} else if (nodes[0].value === '180deg') { | ||
nodes = this.replaceFirst(nodes, 'to', ' ', 'bottom') | ||
} else if (nodes[0].value === '270deg') { | ||
nodes = this.replaceFirst(nodes, 'to', ' ', 'left') | ||
} | ||
return nodes | ||
return { after: ' ', type: 'div', value: ',' } | ||
} | ||
/** | ||
* Replace old direction to new | ||
* Change colors syntax to old webkit | ||
*/ | ||
newDirection(params) { | ||
if (params[0].value === 'to') { | ||
return params | ||
} | ||
IS_DIRECTION.lastIndex = 0 // reset search index of global regexp | ||
if (!IS_DIRECTION.test(params[0].value)) { | ||
return params | ||
} | ||
params.unshift( | ||
{ | ||
type: 'word', | ||
value: 'to' | ||
}, | ||
{ | ||
type: 'space', | ||
value: ' ' | ||
colorStops(params) { | ||
let result = [] | ||
for (let i = 0; i < params.length; i++) { | ||
let pos | ||
let param = params[i] | ||
let item | ||
if (i === 0) { | ||
continue | ||
} | ||
) | ||
for (let i = 2; i < params.length; i++) { | ||
if (params[i].type === 'div') { | ||
break | ||
let 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 | ||
} | ||
if (params[i].type === 'word') { | ||
params[i].value = this.revertDirection(params[i].value) | ||
} | ||
} | ||
return params | ||
} | ||
/** | ||
* Look for at word | ||
*/ | ||
isRadial(params) { | ||
let state = 'before' | ||
for (let param of params) { | ||
if (state === 'before' && param.type === 'space') { | ||
state = 'at' | ||
} else if (state === 'at' && param.value === 'at') { | ||
state = 'after' | ||
} else if (state === 'after' && param.type === 'space') { | ||
return true | ||
} else if (param.type === 'div') { | ||
break | ||
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 { | ||
state = 'before' | ||
stop = `color-stop(${color})` | ||
} | ||
let 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 false | ||
return result | ||
} | ||
@@ -161,2 +105,13 @@ | ||
/** | ||
* Add 90 degrees | ||
*/ | ||
fixAngle(params) { | ||
let first = params[0].value | ||
first = parseFloat(first) | ||
first = Math.abs(450 - first) % 360 | ||
first = this.roundFloat(first, 3) | ||
params[0].value = `${first}deg` | ||
} | ||
/** | ||
* Replace `to top left` to `bottom right` | ||
@@ -178,13 +133,2 @@ */ | ||
/** | ||
* Add 90 degrees | ||
*/ | ||
fixAngle(params) { | ||
let first = params[0].value | ||
first = parseFloat(first) | ||
first = Math.abs(450 - first) % 360 | ||
first = this.roundFloat(first, 3) | ||
params[0].value = `${first}deg` | ||
} | ||
/** | ||
* Fix radial direction syntax | ||
@@ -222,14 +166,162 @@ */ | ||
revertDirection(word) { | ||
return Gradient.directions[word.toLowerCase()] || word | ||
/** | ||
* Look for at word | ||
*/ | ||
isRadial(params) { | ||
let state = 'before' | ||
for (let param of params) { | ||
if (state === 'before' && param.type === 'space') { | ||
state = 'at' | ||
} else if (state === 'at' && param.value === 'at') { | ||
state = 'after' | ||
} else if (state === 'after' && param.type === 'space') { | ||
return true | ||
} else if (param.type === 'div') { | ||
break | ||
} else { | ||
state = 'before' | ||
} | ||
} | ||
return false | ||
} | ||
/** | ||
* Round float and save digits under dot | ||
* Replace old direction to new | ||
*/ | ||
roundFloat(float, digits) { | ||
return parseFloat(float.toFixed(digits)) | ||
newDirection(params) { | ||
if (params[0].value === 'to') { | ||
return params | ||
} | ||
IS_DIRECTION.lastIndex = 0 // reset search index of global regexp | ||
if (!IS_DIRECTION.test(params[0].value)) { | ||
return params | ||
} | ||
params.unshift( | ||
{ | ||
type: 'word', | ||
value: 'to' | ||
}, | ||
{ | ||
type: 'space', | ||
value: ' ' | ||
} | ||
) | ||
for (let i = 2; i < params.length; i++) { | ||
if (params[i].type === 'div') { | ||
break | ||
} | ||
if (params[i].type === 'word') { | ||
params[i].value = this.revertDirection(params[i].value) | ||
} | ||
} | ||
return params | ||
} | ||
/** | ||
* Normalize angle | ||
*/ | ||
normalize(nodes, gradientName) { | ||
if (!nodes[0]) return nodes | ||
if (/-?\d+(.\d+)?grad/.test(nodes[0].value)) { | ||
nodes[0].value = this.normalizeUnit(nodes[0].value, 400) | ||
} else if (/-?\d+(.\d+)?rad/.test(nodes[0].value)) { | ||
nodes[0].value = this.normalizeUnit(nodes[0].value, 2 * Math.PI) | ||
} else if (/-?\d+(.\d+)?turn/.test(nodes[0].value)) { | ||
nodes[0].value = this.normalizeUnit(nodes[0].value, 1) | ||
} else if (nodes[0].value.includes('deg')) { | ||
let num = parseFloat(nodes[0].value) | ||
num = range.wrap(0, 360, num) | ||
nodes[0].value = `${num}deg` | ||
} | ||
if ( | ||
gradientName === 'linear-gradient' || | ||
gradientName === 'repeating-linear-gradient' | ||
) { | ||
let direction = nodes[0].value | ||
// Unitless zero for `<angle>` values are allowed in CSS gradients and transforms. | ||
// Spec: https://github.com/w3c/csswg-drafts/commit/602789171429b2231223ab1e5acf8f7f11652eb3 | ||
if (direction === '0deg' || direction === '0') { | ||
nodes = this.replaceFirst(nodes, 'to', ' ', 'top') | ||
} else if (direction === '90deg') { | ||
nodes = this.replaceFirst(nodes, 'to', ' ', 'right') | ||
} else if (direction === '180deg') { | ||
nodes = this.replaceFirst(nodes, 'to', ' ', 'bottom') // default value | ||
} else if (direction === '270deg') { | ||
nodes = this.replaceFirst(nodes, 'to', ' ', 'left') | ||
} | ||
} | ||
return nodes | ||
} | ||
/** | ||
* Convert angle unit to deg | ||
*/ | ||
normalizeUnit(str, full) { | ||
let num = parseFloat(str) | ||
let deg = (num / full) * 360 | ||
return `${deg}deg` | ||
} | ||
/** | ||
* Remove old WebKit gradient too | ||
*/ | ||
old(prefix) { | ||
if (prefix === '-webkit-') { | ||
let type | ||
if (this.name === 'linear-gradient') { | ||
type = 'linear' | ||
} else if (this.name === 'repeating-linear-gradient') { | ||
type = 'repeating-linear' | ||
} else if (this.name === 'repeating-radial-gradient') { | ||
type = 'repeating-radial' | ||
} else { | ||
type = 'radial' | ||
} | ||
let string = '-gradient' | ||
let regexp = utils.regexp( | ||
`-webkit-(${type}-gradient|gradient\\(\\s*${type})`, | ||
false | ||
) | ||
return new OldValue(this.name, prefix + this.name, string, regexp) | ||
} else { | ||
return super.old(prefix) | ||
} | ||
} | ||
/** | ||
* Change direction syntax to old webkit | ||
*/ | ||
oldDirection(params) { | ||
let div = this.cloneDiv(params[0]) | ||
if (params[0][0].value !== 'to') { | ||
return params.unshift([ | ||
{ type: 'word', value: Gradient.oldDirections.bottom }, | ||
div | ||
]) | ||
} else { | ||
let words = [] | ||
for (let node of params[0].slice(2)) { | ||
if (node.type === 'word') { | ||
words.push(node.value.toLowerCase()) | ||
} | ||
} | ||
words = words.join(' ') | ||
let old = Gradient.oldDirections[words] || words | ||
params[0] = [{ type: 'word', value: old }, div] | ||
return params[0] | ||
} | ||
} | ||
/** | ||
* Convert to old webkit syntax | ||
@@ -281,121 +373,48 @@ */ | ||
/** | ||
* Change direction syntax to old webkit | ||
* Change degrees for webkit prefix | ||
*/ | ||
oldDirection(params) { | ||
let div = this.cloneDiv(params[0]) | ||
if (params[0][0].value !== 'to') { | ||
return params.unshift([ | ||
{ type: 'word', value: Gradient.oldDirections.bottom }, | ||
div | ||
]) | ||
} else { | ||
let words = [] | ||
for (let node of params[0].slice(2)) { | ||
if (node.type === 'word') { | ||
words.push(node.value.toLowerCase()) | ||
replace(string, prefix) { | ||
let ast = parser(string) | ||
for (let node of ast.nodes) { | ||
let gradientName = this.name // gradient name | ||
if (node.type === 'function' && node.value === gradientName) { | ||
node.nodes = this.newDirection(node.nodes) | ||
node.nodes = this.normalize(node.nodes, gradientName) | ||
if (prefix === '-webkit- old') { | ||
let changes = this.oldWebkit(node) | ||
if (!changes) { | ||
return false | ||
} | ||
} else { | ||
node.nodes = this.convertDirection(node.nodes) | ||
node.value = prefix + node.value | ||
} | ||
} | ||
words = words.join(' ') | ||
let old = Gradient.oldDirections[words] || words | ||
params[0] = [{ type: 'word', value: old }, div] | ||
return params[0] | ||
} | ||
return ast.toString() | ||
} | ||
/** | ||
* Get div token from exists parameters | ||
* Replace first token | ||
*/ | ||
cloneDiv(params) { | ||
for (let i of params) { | ||
if (i.type === 'div' && i.value === ',') { | ||
return i | ||
replaceFirst(params, ...words) { | ||
let prefix = words.map(i => { | ||
if (i === ' ') { | ||
return { type: 'space', value: i } | ||
} | ||
} | ||
return { type: 'div', value: ',', after: ' ' } | ||
return { type: 'word', value: i } | ||
}) | ||
return prefix.concat(params.slice(1)) | ||
} | ||
/** | ||
* Change colors syntax to old webkit | ||
*/ | ||
colorStops(params) { | ||
let result = [] | ||
for (let i = 0; i < params.length; i++) { | ||
let pos | ||
let param = params[i] | ||
let item | ||
if (i === 0) { | ||
continue | ||
} | ||
let 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 | ||
} | ||
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})` | ||
} | ||
let 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 | ||
revertDirection(word) { | ||
return Gradient.directions[word.toLowerCase()] || word | ||
} | ||
/** | ||
* Remove old WebKit gradient too | ||
* Round float and save digits under dot | ||
*/ | ||
old(prefix) { | ||
if (prefix === '-webkit-') { | ||
let type = this.name === 'linear-gradient' ? 'linear' : 'radial' | ||
let string = '-gradient' | ||
let regexp = utils.regexp( | ||
`-webkit-(${type}-gradient|gradient\\(\\s*${type})`, | ||
false | ||
) | ||
return new OldValue(this.name, prefix + this.name, string, regexp) | ||
} else { | ||
return super.old(prefix) | ||
} | ||
roundFloat(float, digits) { | ||
return parseFloat(float.toFixed(digits)) | ||
} | ||
/** | ||
* Do not add non-webkit prefixes for list-style and object | ||
*/ | ||
add(decl, prefix) { | ||
let p = decl.prop | ||
if (p.includes('mask')) { | ||
if (prefix === '-webkit-' || prefix === '-webkit- old') { | ||
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(decl, prefix) | ||
} | ||
} else { | ||
return super.add(decl, prefix) | ||
} | ||
return undefined | ||
} | ||
} | ||
@@ -411,6 +430,6 @@ | ||
Gradient.directions = { | ||
top: 'bottom', | ||
bottom: 'top', | ||
left: 'right', | ||
bottom: 'top', | ||
right: 'left' | ||
right: 'left', | ||
top: 'bottom' // default value | ||
} | ||
@@ -420,17 +439,17 @@ | ||
Gradient.oldDirections = { | ||
'top': 'left bottom, left top', | ||
'bottom': 'left top, left bottom', | ||
'bottom left': 'right top, left bottom', | ||
'bottom right': 'left top, right bottom', | ||
'left': 'right top, left top', | ||
'bottom': 'left top, left bottom', | ||
'left bottom': 'right top, left bottom', | ||
'left top': 'right bottom, left top', | ||
'right': 'left top, right top', | ||
'top right': 'left bottom, right top', | ||
'right bottom': 'left top, right bottom', | ||
'right top': 'left bottom, right top', | ||
'top': 'left bottom, left 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' | ||
'top right': 'left bottom, right top' | ||
} | ||
module.exports = Gradient |
@@ -12,13 +12,13 @@ let Declaration = require('../declaration') | ||
/** | ||
* Change property name for IE | ||
* Change IE property back | ||
*/ | ||
prefixed(prop, prefix) { | ||
return prefix + 'grid-column-align' | ||
normalize() { | ||
return 'justify-self' | ||
} | ||
/** | ||
* Change IE property back | ||
* Change property name for IE | ||
*/ | ||
normalize() { | ||
return 'justify-self' | ||
prefixed(prop, prefix) { | ||
return prefix + 'grid-column-align' | ||
} | ||
@@ -25,0 +25,0 @@ } |
let Declaration = require('../declaration') | ||
let { isPureNumber } = require('../utils') | ||
@@ -29,4 +30,8 @@ class GridEnd extends Declaration { | ||
if (startDecl) { | ||
let value = Number(decl.value) - Number(startDecl.value) + '' | ||
clonedDecl.value = value | ||
if (isPureNumber(startDecl.value)) { | ||
let value = Number(decl.value) - Number(startDecl.value) + '' | ||
clonedDecl.value = value | ||
} else { | ||
return undefined | ||
} | ||
} else { | ||
@@ -33,0 +38,0 @@ decl.warn( |
@@ -12,13 +12,13 @@ let Declaration = require('../declaration') | ||
/** | ||
* Change property name for IE | ||
* Change IE property back | ||
*/ | ||
prefixed(prop, prefix) { | ||
return prefix + 'grid-row-align' | ||
normalize() { | ||
return 'align-self' | ||
} | ||
/** | ||
* Change IE property back | ||
* Change property name for IE | ||
*/ | ||
normalize() { | ||
return 'align-self' | ||
prefixed(prop, prefix) { | ||
return prefix + 'grid-row-align' | ||
} | ||
@@ -25,0 +25,0 @@ } |
let Declaration = require('../declaration') | ||
let { | ||
prefixTrackProp, | ||
prefixTrackValue, | ||
autoplaceGridItems, | ||
getGridGap, | ||
inheritGridGap | ||
inheritGridGap, | ||
prefixTrackProp, | ||
prefixTrackValue | ||
} = require('./grid-utils') | ||
@@ -12,19 +12,2 @@ let Processor = require('../processor') | ||
class GridRowsColumns extends Declaration { | ||
/** | ||
* Change property name for IE | ||
*/ | ||
prefixed(prop, prefix) { | ||
if (prefix === '-ms-') { | ||
return prefixTrackProp({ prop, prefix }) | ||
} | ||
return super.prefixed(prop, prefix) | ||
} | ||
/** | ||
* Change IE property back | ||
*/ | ||
normalize(prop) { | ||
return prop.replace(/^grid-(rows|columns)/, 'grid-template-$1') | ||
} | ||
insert(decl, prefix, prefixes, result) { | ||
@@ -60,4 +43,4 @@ if (prefix !== '-ms-') return super.insert(decl, prefix, prefixes) | ||
let prefixValue = prefixTrackValue({ | ||
value, | ||
gap: gapValue | ||
gap: gapValue, | ||
value | ||
}) | ||
@@ -69,3 +52,3 @@ | ||
decl.cloneBefore({ | ||
prop: prefixTrackProp({ prop, prefix }), | ||
prop: prefixTrackProp({ prefix, prop }), | ||
value: prefixValue | ||
@@ -119,2 +102,19 @@ }) | ||
} | ||
/** | ||
* Change IE property back | ||
*/ | ||
normalize(prop) { | ||
return prop.replace(/^grid-(rows|columns)/, 'grid-template-$1') | ||
} | ||
/** | ||
* Change property name for IE | ||
*/ | ||
prefixed(prop, prefix) { | ||
if (prefix === '-ms-') { | ||
return prefixTrackProp({ prefix, prop }) | ||
} | ||
return super.prefixed(prop, prefix) | ||
} | ||
} | ||
@@ -121,0 +121,0 @@ |
@@ -9,3 +9,3 @@ let Declaration = require('../declaration') | ||
let value = decl.value | ||
return !value.includes('/') || value.includes('span') | ||
return !value.includes('/') && !value.includes('span') | ||
} | ||
@@ -12,0 +12,0 @@ |
let Declaration = require('../declaration') | ||
let { | ||
getGridGap, | ||
inheritGridGap, | ||
parseGridAreas, | ||
warnMissedAreas, | ||
prefixTrackProp, | ||
prefixTrackValue, | ||
getGridGap, | ||
warnGridGap, | ||
inheritGridGap | ||
warnMissedAreas | ||
} = require('./grid-utils') | ||
@@ -42,4 +42,4 @@ | ||
trackDecl.cloneBefore({ | ||
prop: prefixTrackProp({ prop, prefix }), | ||
value: prefixTrackValue({ value, gap: gap.row }) | ||
prop: prefixTrackProp({ prefix, prop }), | ||
value: prefixTrackValue({ gap: gap.row, value }) | ||
}) | ||
@@ -56,7 +56,7 @@ } else { | ||
prop: '-ms-grid-rows', | ||
raws: {}, | ||
value: prefixTrackValue({ | ||
value: `repeat(${gridRows.length}, auto)`, | ||
gap: gap.row | ||
}), | ||
raws: {} | ||
gap: gap.row, | ||
value: `repeat(${gridRows.length}, auto)` | ||
}) | ||
}) | ||
@@ -67,5 +67,5 @@ } | ||
warnGridGap({ | ||
decl, | ||
gap, | ||
hasColumns, | ||
decl, | ||
result | ||
@@ -75,4 +75,4 @@ }) | ||
let areas = parseGridAreas({ | ||
rows: gridRows, | ||
gap | ||
gap, | ||
rows: gridRows | ||
}) | ||
@@ -79,0 +79,0 @@ |
let Declaration = require('../declaration') | ||
let { | ||
getGridGap, | ||
inheritGridGap, | ||
parseTemplate, | ||
warnMissedAreas, | ||
getGridGap, | ||
warnGridGap, | ||
inheritGridGap | ||
warnMissedAreas | ||
} = require('./grid-utils') | ||
@@ -29,3 +29,3 @@ | ||
let { rows, columns, areas } = parseTemplate({ | ||
let { areas, columns, rows } = parseTemplate({ | ||
decl, | ||
@@ -40,5 +40,5 @@ gap: inheritedGap || gap | ||
warnGridGap({ | ||
decl, | ||
gap, | ||
hasColumns, | ||
decl, | ||
result | ||
@@ -52,4 +52,4 @@ }) | ||
prop: '-ms-grid-rows', | ||
value: rows, | ||
raws: {} | ||
raws: {}, | ||
value: rows | ||
}) | ||
@@ -61,4 +61,4 @@ } | ||
prop: '-ms-grid-columns', | ||
value: columns, | ||
raws: {} | ||
raws: {}, | ||
value: columns | ||
}) | ||
@@ -65,0 +65,0 @@ } |
@@ -93,3 +93,3 @@ let parser = require('postcss-value-parser') | ||
function prefixTrackProp({ prop, prefix }) { | ||
function prefixTrackProp({ prefix, prop }) { | ||
return prefix + prop.replace('template-', '') | ||
@@ -109,5 +109,5 @@ } | ||
{ | ||
count: [], | ||
key: 'count', | ||
size: [], | ||
count: [] | ||
size: [] | ||
} | ||
@@ -137,3 +137,3 @@ ) | ||
function prefixTrackValue({ value, gap }) { | ||
function prefixTrackValue({ gap, value }) { | ||
let result = parser(value).nodes.reduce((nodes, node) => { | ||
@@ -170,3 +170,3 @@ if (node.type === 'function' && node.value === 'repeat') { | ||
function track(start, end) { | ||
return { start, end, span: end - start } | ||
return { end, span: end - start, start } | ||
} | ||
@@ -180,3 +180,3 @@ | ||
function parseGridAreas({ rows, gap }) { | ||
function parseGridAreas({ gap, rows }) { | ||
return rows.reduce((areas, line, rowIndex) => { | ||
@@ -256,6 +256,6 @@ if (gap.row) rowIndex *= 2 | ||
{ | ||
areas: [], | ||
columns: [], | ||
key: 'rows', | ||
columns: [], | ||
rows: [], | ||
areas: [] | ||
rows: [] | ||
} | ||
@@ -266,12 +266,12 @@ ) | ||
areas: parseGridAreas({ | ||
rows: gridTemplate.areas, | ||
gap | ||
gap, | ||
rows: gridTemplate.areas | ||
}), | ||
columns: prefixTrackValue({ | ||
value: gridTemplate.columns.join(' '), | ||
gap: gap.column | ||
gap: gap.column, | ||
value: gridTemplate.columns.join(' ') | ||
}), | ||
rows: prefixTrackValue({ | ||
value: gridTemplate.rows.join(' '), | ||
gap: gap.row | ||
gap: gap.row, | ||
value: gridTemplate.rows.join(' ') | ||
}) | ||
@@ -439,8 +439,8 @@ } | ||
parsed[index].rules.push({ | ||
areas, | ||
duplicateAreaNames, | ||
hasDuplicates: !hasNoDuplicates, | ||
node: rule, | ||
params: media.params, | ||
selectors: rule.selectors, | ||
node: rule, | ||
duplicateAreaNames, | ||
areas | ||
selectors: rule.selectors | ||
}) | ||
@@ -454,9 +454,9 @@ } else { | ||
{ | ||
areas, | ||
duplicateAreaNames: [], | ||
duplicateRules: [], | ||
hasDuplicates: false, | ||
duplicateRules: [], | ||
node: rule, | ||
params: media.params, | ||
selectors: rule.selectors, | ||
node: rule, | ||
duplicateAreaNames: [], | ||
areas | ||
selectors: rule.selectors | ||
} | ||
@@ -1005,3 +1005,3 @@ ] | ||
function warnGridGap({ gap, hasColumns, decl, result }) { | ||
function warnGridGap({ decl, gap, hasColumns, result }) { | ||
let hasBothGaps = gap.row && gap.column | ||
@@ -1092,3 +1092,3 @@ if (!hasColumns && (hasBothGaps || (gap.column && !gap.row))) { | ||
let areas = parseGridAreas({ rows: filledRows, gap }) | ||
let areas = parseGridAreas({ gap, rows: filledRows }) | ||
let keys = Object.keys(areas) | ||
@@ -1095,0 +1095,0 @@ let items = keys.map(i => areas[i]) |
@@ -12,2 +12,9 @@ let Declaration = require('../declaration') | ||
/** | ||
* Return property name by spec | ||
*/ | ||
normalize() { | ||
return 'image-rendering' | ||
} | ||
/** | ||
* Change property name for IE | ||
@@ -23,2 +30,9 @@ */ | ||
/** | ||
* Warn on old value | ||
*/ | ||
process(node, result) { | ||
return super.process(node, result) | ||
} | ||
/** | ||
* Change property and value for IE | ||
@@ -32,16 +46,2 @@ */ | ||
} | ||
/** | ||
* Return property name by spec | ||
*/ | ||
normalize() { | ||
return 'image-rendering' | ||
} | ||
/** | ||
* Warn on old value | ||
*/ | ||
process(node, result) { | ||
return super.process(node, result) | ||
} | ||
} | ||
@@ -48,0 +48,0 @@ |
@@ -5,13 +5,13 @@ let Declaration = require('../declaration') | ||
/** | ||
* Use old syntax for -moz- and -webkit- | ||
* Return property name by spec | ||
*/ | ||
prefixed(prop, prefix) { | ||
return prefix + prop.replace('-inline', '') | ||
normalize(prop) { | ||
return prop.replace(/(margin|padding|border)-(start|end)/, '$1-inline-$2') | ||
} | ||
/** | ||
* Return property name by spec | ||
* Use old syntax for -moz- and -webkit- | ||
*/ | ||
normalize(prop) { | ||
return prop.replace(/(margin|padding|border)-(start|end)/, '$1-inline-$2') | ||
prefixed(prop, prefix) { | ||
return prefix + prop.replace('-inline', '') | ||
} | ||
@@ -18,0 +18,0 @@ } |
@@ -9,5 +9,7 @@ let OldValue = require('../old-value') | ||
class Intrinsic extends Value { | ||
regexp() { | ||
if (!this.regexpCache) this.regexpCache = regexp(this.name) | ||
return this.regexpCache | ||
add(decl, prefix) { | ||
if (decl.prop.includes('grid') && prefix !== '-webkit-') { | ||
return undefined | ||
} | ||
return super.add(decl, prefix) | ||
} | ||
@@ -23,12 +25,2 @@ | ||
replace(string, prefix) { | ||
if (prefix === '-moz-' && this.isStretch()) { | ||
return string.replace(this.regexp(), '$1-moz-available$3') | ||
} | ||
if (prefix === '-webkit-' && this.isStretch()) { | ||
return string.replace(this.regexp(), '$1-webkit-fill-available$3') | ||
} | ||
return super.replace(string, prefix) | ||
} | ||
old(prefix) { | ||
@@ -46,7 +38,15 @@ let prefixed = prefix + this.name | ||
add(decl, prefix) { | ||
if (decl.prop.includes('grid') && prefix !== '-webkit-') { | ||
return undefined | ||
regexp() { | ||
if (!this.regexpCache) this.regexpCache = regexp(this.name) | ||
return this.regexpCache | ||
} | ||
replace(string, prefix) { | ||
if (prefix === '-moz-' && this.isStretch()) { | ||
return string.replace(this.regexp(), '$1-moz-available$3') | ||
} | ||
return super.add(decl, prefix) | ||
if (prefix === '-webkit-' && this.isStretch()) { | ||
return string.replace(this.regexp(), '$1-webkit-fill-available$3') | ||
} | ||
return super.replace(string, prefix) | ||
} | ||
@@ -53,0 +53,0 @@ } |
@@ -6,2 +6,9 @@ let flexSpec = require('./flex-spec') | ||
/** | ||
* Return property name by final spec | ||
*/ | ||
normalize() { | ||
return 'justify-content' | ||
} | ||
/** | ||
* Change property name for 2009 and 2012 specs | ||
@@ -22,9 +29,2 @@ */ | ||
/** | ||
* Return property name by final spec | ||
*/ | ||
normalize() { | ||
return 'justify-content' | ||
} | ||
/** | ||
* Change value for 2009 and 2012 specs | ||
@@ -52,6 +52,6 @@ */ | ||
'flex-start': 'start', | ||
'space-between': 'justify', | ||
'space-around': 'distribute' | ||
'space-around': 'distribute', | ||
'space-between': 'justify' | ||
} | ||
module.exports = JustifyContent |
@@ -76,5 +76,5 @@ let Declaration = require('../declaration') | ||
add: 'source-over', | ||
subtract: 'source-out', | ||
exclude: 'xor', | ||
intersect: 'source-in', | ||
exclude: 'xor' | ||
subtract: 'source-out' | ||
} | ||
@@ -81,0 +81,0 @@ |
@@ -6,2 +6,9 @@ let flexSpec = require('./flex-spec') | ||
/** | ||
* Return property name by final spec | ||
*/ | ||
normalize() { | ||
return 'order' | ||
} | ||
/** | ||
* Change property name for 2009 and 2012 specs | ||
@@ -22,9 +29,2 @@ */ | ||
/** | ||
* Return property name by final spec | ||
*/ | ||
normalize() { | ||
return 'order' | ||
} | ||
/** | ||
* Fix value for 2009 spec | ||
@@ -31,0 +31,0 @@ */ |
@@ -5,13 +5,13 @@ let Declaration = require('../declaration') | ||
/** | ||
* Change property name for IE | ||
* Return property name by spec | ||
*/ | ||
prefixed(prop, prefix) { | ||
return prefix + 'scroll-chaining' | ||
normalize() { | ||
return 'overscroll-behavior' | ||
} | ||
/** | ||
* Return property name by spec | ||
* Change property name for IE | ||
*/ | ||
normalize() { | ||
return 'overscroll-behavior' | ||
prefixed(prop, prefix) { | ||
return prefix + 'scroll-chaining' | ||
} | ||
@@ -18,0 +18,0 @@ |
@@ -6,25 +6,25 @@ let OldValue = require('../old-value') | ||
/** | ||
* Use non-standard name for WebKit and Firefox | ||
* Different name for WebKit and Firefox | ||
*/ | ||
replace(string, prefix) { | ||
old(prefix) { | ||
if (prefix === '-webkit-') { | ||
return string.replace(this.regexp(), '$1-webkit-optimize-contrast') | ||
return new OldValue(this.name, '-webkit-optimize-contrast') | ||
} | ||
if (prefix === '-moz-') { | ||
return string.replace(this.regexp(), '$1-moz-crisp-edges') | ||
return new OldValue(this.name, '-moz-crisp-edges') | ||
} | ||
return super.replace(string, prefix) | ||
return super.old(prefix) | ||
} | ||
/** | ||
* Different name for WebKit and Firefox | ||
* Use non-standard name for WebKit and Firefox | ||
*/ | ||
old(prefix) { | ||
replace(string, prefix) { | ||
if (prefix === '-webkit-') { | ||
return new OldValue(this.name, '-webkit-optimize-contrast') | ||
return string.replace(this.regexp(), '$1-webkit-optimize-contrast') | ||
} | ||
if (prefix === '-moz-') { | ||
return new OldValue(this.name, '-moz-crisp-edges') | ||
return string.replace(this.regexp(), '$1-moz-crisp-edges') | ||
} | ||
return super.old(prefix) | ||
return super.replace(string, prefix) | ||
} | ||
@@ -31,0 +31,0 @@ } |
@@ -5,16 +5,2 @@ let Declaration = require('../declaration') | ||
/** | ||
* Recursively check all parents for @keyframes | ||
*/ | ||
keyframeParents(decl) { | ||
let { parent } = decl | ||
while (parent) { | ||
if (parent.type === 'atrule' && parent.name === 'keyframes') { | ||
return true | ||
} | ||
;({ parent } = parent) | ||
} | ||
return false | ||
} | ||
/** | ||
* Is transform contain 3D commands | ||
@@ -37,13 +23,2 @@ */ | ||
/** | ||
* Replace rotateZ to rotate for IE 9 | ||
*/ | ||
set(decl, prefix) { | ||
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 | ||
@@ -65,2 +40,27 @@ */ | ||
} | ||
/** | ||
* Recursively check all parents for @keyframes | ||
*/ | ||
keyframeParents(decl) { | ||
let { parent } = decl | ||
while (parent) { | ||
if (parent.type === 'atrule' && parent.name === 'keyframes') { | ||
return true | ||
} | ||
;({ parent } = parent) | ||
} | ||
return false | ||
} | ||
/** | ||
* Replace rotateZ to rotate for IE 9 | ||
*/ | ||
set(decl, prefix) { | ||
decl = super.set(decl, prefix) | ||
if (prefix === '-ms-') { | ||
decl.value = decl.value.replace(/rotatez/gi, 'rotate') | ||
} | ||
return decl | ||
} | ||
} | ||
@@ -67,0 +67,0 @@ |
@@ -5,12 +5,2 @@ let Declaration = require('../declaration') | ||
/** | ||
* Change prefixed value for IE | ||
*/ | ||
set(decl, prefix) { | ||
if (prefix === '-ms-' && decl.value === 'contain') { | ||
decl.value = 'element' | ||
} | ||
return super.set(decl, prefix) | ||
} | ||
/** | ||
* Avoid prefixing all in IE | ||
@@ -25,2 +15,12 @@ */ | ||
} | ||
/** | ||
* Change prefixed value for IE | ||
*/ | ||
set(decl, prefix) { | ||
if (prefix === '-ms-' && decl.value === 'contain') { | ||
decl.value = 'element' | ||
} | ||
return super.set(decl, prefix) | ||
} | ||
} | ||
@@ -27,0 +27,0 @@ |
@@ -32,9 +32,9 @@ let Declaration = require('../declaration') | ||
'horizontal-tb': 'lr-tb', | ||
'vertical-rl': 'tb-rl', | ||
'vertical-lr': 'tb-lr' | ||
'vertical-lr': 'tb-lr', | ||
'vertical-rl': 'tb-rl' | ||
}, | ||
rtl: { | ||
'horizontal-tb': 'rl-tb', | ||
'vertical-rl': 'bt-rl', | ||
'vertical-lr': 'bt-lr' | ||
'vertical-lr': 'bt-lr', | ||
'vertical-rl': 'bt-rl' | ||
} | ||
@@ -41,0 +41,0 @@ } |
@@ -8,13 +8,13 @@ let browserslist = require('browserslist') | ||
const NAMES = { | ||
and_chr: 'Chrome for Android', | ||
and_ff: 'Firefox for Android', | ||
and_qq: 'QQ Browser', | ||
and_uc: 'UC for Android', | ||
baidu: 'Baidu Browser', | ||
ie: 'IE', | ||
ie_mob: 'IE Mobile', | ||
ios_saf: 'iOS Safari', | ||
kaios: 'KaiOS Browser', | ||
op_mini: 'Opera Mini', | ||
op_mob: 'Opera Mobile', | ||
and_chr: 'Chrome for Android', | ||
and_ff: 'Firefox for Android', | ||
and_uc: 'UC for Android', | ||
and_qq: 'QQ Browser', | ||
kaios: 'KaiOS Browser', | ||
baidu: 'Baidu Browser', | ||
samsung: 'Samsung Internet' | ||
@@ -21,0 +21,0 @@ } |
@@ -16,2 +16,18 @@ class OldSelector { | ||
/** | ||
* Does rule contain an unnecessary prefixed selector | ||
*/ | ||
check(rule) { | ||
if (!rule.selector.includes(this.prefixed)) { | ||
return false | ||
} | ||
if (!rule.selector.match(this.regexp)) { | ||
return false | ||
} | ||
if (this.isHack(rule)) { | ||
return false | ||
} | ||
return true | ||
} | ||
/** | ||
* Is rule a hack without unprefixed version bottom | ||
@@ -50,20 +66,4 @@ */ | ||
} | ||
/** | ||
* Does rule contain an unnecessary prefixed selector | ||
*/ | ||
check(rule) { | ||
if (!rule.selector.includes(this.prefixed)) { | ||
return false | ||
} | ||
if (!rule.selector.match(this.regexp)) { | ||
return false | ||
} | ||
if (this.isHack(rule)) { | ||
return false | ||
} | ||
return true | ||
} | ||
} | ||
module.exports = OldSelector |
@@ -37,3 +37,20 @@ let Browsers = require('./browsers') | ||
class Prefixer { | ||
constructor(name, prefixes, all) { | ||
this.prefixes = prefixes | ||
this.name = name | ||
this.all = all | ||
} | ||
/** | ||
* Clone node and clean autprefixer custom caches | ||
*/ | ||
static clone(node, overrides) { | ||
let cloned = clone(node) | ||
for (let name in overrides) { | ||
cloned[name] = overrides[name] | ||
} | ||
return cloned | ||
} | ||
/** | ||
* Add hack to selected names | ||
@@ -64,18 +81,8 @@ */ | ||
/** | ||
* Clone node and clean autprefixer custom caches | ||
* Shortcut for Prefixer.clone | ||
*/ | ||
static clone(node, overrides) { | ||
let cloned = clone(node) | ||
for (let name in overrides) { | ||
cloned[name] = overrides[name] | ||
} | ||
return cloned | ||
clone(node, overrides) { | ||
return Prefixer.clone(node, overrides) | ||
} | ||
constructor(name, prefixes, all) { | ||
this.prefixes = prefixes | ||
this.name = name | ||
this.all = all | ||
} | ||
/** | ||
@@ -137,11 +144,4 @@ * Find prefix in node parents | ||
} | ||
/** | ||
* Shortcut for Prefixer.clone | ||
*/ | ||
clone(node, overrides) { | ||
return Prefixer.clone(node, overrides) | ||
} | ||
} | ||
module.exports = Prefixer |
@@ -36,3 +36,2 @@ let vendor = require('./vendor') | ||
let hackBreakProps = require('./hacks/break-props') | ||
let hackColorAdjust = require('./hacks/color-adjust') | ||
let hackWritingMode = require('./hacks/writing-mode') | ||
@@ -57,2 +56,3 @@ let hackBorderImage = require('./hacks/border-image') | ||
let hackGridColumnAlign = require('./hacks/grid-column-align') | ||
let hackPrintColorAdjust = require('./hacks/print-color-adjust') | ||
let hackOverscrollBehavior = require('./hacks/overscroll-behavior') | ||
@@ -97,3 +97,2 @@ let hackGridTemplateAreas = require('./hacks/grid-template-areas') | ||
Declaration.hack(hackBreakProps) | ||
Declaration.hack(hackColorAdjust) | ||
Declaration.hack(hackWritingMode) | ||
@@ -120,2 +119,3 @@ Declaration.hack(hackBorderImage) | ||
Declaration.hack(hackGridTemplateAreas) | ||
Declaration.hack(hackPrintColorAdjust) | ||
Declaration.hack(hackTextEmphasisPosition) | ||
@@ -163,72 +163,73 @@ Declaration.hack(hackTextDecorationSkipInk) | ||
/** | ||
* Select prefixes from data, which is necessary for selected browsers | ||
* Declaration loader with caching | ||
*/ | ||
select(list) { | ||
let selected = { add: {}, remove: {} } | ||
decl(prop) { | ||
if (!declsCache.has(prop)) { | ||
declsCache.set(prop, Declaration.load(prop)) | ||
} | ||
for (let name in list) { | ||
let data = list[name] | ||
let add = data.browsers.map(i => { | ||
let params = i.split(' ') | ||
return { | ||
browser: `${params[0]} ${params[1]}`, | ||
note: params[2] | ||
} | ||
}) | ||
return declsCache.get(prop) | ||
} | ||
let notes = add | ||
.filter(i => i.note) | ||
.map(i => `${this.browsers.prefix(i.browser)} ${i.note}`) | ||
notes = utils.uniq(notes) | ||
/** | ||
* Group declaration by unprefixed property to check them | ||
*/ | ||
group(decl) { | ||
let rule = decl.parent | ||
let index = rule.index(decl) | ||
let { length } = rule.nodes | ||
let unprefixed = this.unprefixed(decl.prop) | ||
add = add | ||
.filter(i => this.browsers.isSelected(i.browser)) | ||
.map(i => { | ||
let prefix = this.browsers.prefix(i.browser) | ||
if (i.note) { | ||
return `${prefix} ${i.note}` | ||
} else { | ||
return prefix | ||
let checker = (step, callback) => { | ||
index += step | ||
while (index >= 0 && index < length) { | ||
let other = rule.nodes[index] | ||
if (other.type === 'decl') { | ||
if (step === -1 && other.prop === unprefixed) { | ||
if (!Browsers.withPrefix(other.value)) { | ||
break | ||
} | ||
} | ||
}) | ||
add = this.sort(utils.uniq(add)) | ||
if (this.options.flexbox === 'no-2009') { | ||
add = add.filter(i => !i.includes('2009')) | ||
} | ||
if (this.unprefixed(other.prop) !== unprefixed) { | ||
break | ||
} else if (callback(other) === true) { | ||
return true | ||
} | ||
let all = data.browsers.map(i => this.browsers.prefix(i)) | ||
if (data.mistakes) { | ||
all = all.concat(data.mistakes) | ||
if (step === +1 && other.prop === unprefixed) { | ||
if (!Browsers.withPrefix(other.value)) { | ||
break | ||
} | ||
} | ||
} | ||
index += step | ||
} | ||
all = all.concat(notes) | ||
all = utils.uniq(all) | ||
return false | ||
} | ||
if (add.length) { | ||
selected.add[name] = add | ||
if (add.length < all.length) { | ||
selected.remove[name] = all.filter(i => !add.includes(i)) | ||
} | ||
} else { | ||
selected.remove[name] = all | ||
return { | ||
down(callback) { | ||
return checker(+1, callback) | ||
}, | ||
up(callback) { | ||
return checker(-1, callback) | ||
} | ||
} | ||
} | ||
return selected | ||
/** | ||
* Normalize prefix for remover | ||
*/ | ||
normalize(prop) { | ||
return this.decl(prop).normalize(prop) | ||
} | ||
/** | ||
* Sort vendor prefixes | ||
* Return prefixed version of property | ||
*/ | ||
sort(prefixes) { | ||
return prefixes.sort((a, b) => { | ||
let aLength = utils.removeNote(a).length | ||
let bLength = utils.removeNote(b).length | ||
if (aLength === bLength) { | ||
return b.length - a.length | ||
} else { | ||
return bLength - aLength | ||
} | ||
}) | ||
prefixed(prop, prefix) { | ||
prop = vendor.unprefixed(prop) | ||
return this.decl(prop).prefixed(prop, prefix) | ||
} | ||
@@ -241,4 +242,4 @@ | ||
let add = { | ||
'selectors': [], | ||
'@supports': new Supports(Prefixes, this) | ||
'@supports': new Supports(Prefixes, this), | ||
'selectors': [] | ||
} | ||
@@ -333,13 +334,75 @@ for (let name in selected.add) { | ||
/** | ||
* Declaration loader with caching | ||
* Select prefixes from data, which is necessary for selected browsers | ||
*/ | ||
decl(prop) { | ||
if (!declsCache.has(prop)) { | ||
declsCache.set(prop, Declaration.load(prop)) | ||
select(list) { | ||
let selected = { add: {}, remove: {} } | ||
for (let name in list) { | ||
let data = list[name] | ||
let add = data.browsers.map(i => { | ||
let params = i.split(' ') | ||
return { | ||
browser: `${params[0]} ${params[1]}`, | ||
note: params[2] | ||
} | ||
}) | ||
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 => { | ||
let 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.includes('2009')) | ||
} | ||
let all = data.browsers.map(i => this.browsers.prefix(i)) | ||
if (data.mistakes) { | ||
all = all.concat(data.mistakes) | ||
} | ||
all = all.concat(notes) | ||
all = utils.uniq(all) | ||
if (add.length) { | ||
selected.add[name] = add | ||
if (add.length < all.length) { | ||
selected.remove[name] = all.filter(i => !add.includes(i)) | ||
} | ||
} else { | ||
selected.remove[name] = all | ||
} | ||
} | ||
return declsCache.get(prop) | ||
return selected | ||
} | ||
/** | ||
* Sort vendor prefixes | ||
*/ | ||
sort(prefixes) { | ||
return prefixes.sort((a, b) => { | ||
let aLength = utils.removeNote(a).length | ||
let bLength = utils.removeNote(b).length | ||
if (aLength === bLength) { | ||
return b.length - a.length | ||
} else { | ||
return bLength - aLength | ||
} | ||
}) | ||
} | ||
/** | ||
* Return unprefixed version of property | ||
@@ -356,17 +419,2 @@ */ | ||
/** | ||
* Normalize prefix for remover | ||
*/ | ||
normalize(prop) { | ||
return this.decl(prop).normalize(prop) | ||
} | ||
/** | ||
* 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 | ||
@@ -386,52 +434,4 @@ */ | ||
} | ||
/** | ||
* Group declaration by unprefixed property to check them | ||
*/ | ||
group(decl) { | ||
let rule = decl.parent | ||
let index = rule.index(decl) | ||
let { length } = rule.nodes | ||
let unprefixed = this.unprefixed(decl.prop) | ||
let checker = (step, callback) => { | ||
index += step | ||
while (index >= 0 && index < length) { | ||
let other = rule.nodes[index] | ||
if (other.type === 'decl') { | ||
if (step === -1 && other.prop === unprefixed) { | ||
if (!Browsers.withPrefix(other.value)) { | ||
break | ||
} | ||
} | ||
if (this.unprefixed(other.prop) !== unprefixed) { | ||
break | ||
} else if (callback(other) === true) { | ||
return true | ||
} | ||
if (step === +1 && other.prop === unprefixed) { | ||
if (!Browsers.withPrefix(other.value)) { | ||
break | ||
} | ||
} | ||
} | ||
index += step | ||
} | ||
return false | ||
} | ||
return { | ||
up(callback) { | ||
return checker(-1, callback) | ||
}, | ||
down(callback) { | ||
return checker(+1, callback) | ||
} | ||
} | ||
} | ||
} | ||
module.exports = Prefixes |
@@ -115,3 +115,11 @@ let parser = require('postcss-value-parser') | ||
if (prop === 'grid-row-span') { | ||
if (prop === 'color-adjust') { | ||
if (parent.every(i => i.prop !== 'print-color-adjust')) { | ||
result.warn( | ||
'Replace color-adjust to print-color-adjust. ' + | ||
'The color-adjust shorthand is currently deprecated.', | ||
{ node: decl } | ||
) | ||
} | ||
} else if (prop === 'grid-row-span') { | ||
result.warn( | ||
@@ -393,137 +401,2 @@ 'grid-row-span is not part of final Grid Layout. Use grid-row.', | ||
/** | ||
* Remove unnecessary pefixes | ||
*/ | ||
remove(css, result) { | ||
// At-rules | ||
let resolution = this.prefixes.remove['@resolution'] | ||
css.walkAtRules((rule, i) => { | ||
if (this.prefixes.remove[`@${rule.name}`]) { | ||
if (!this.disabled(rule, result)) { | ||
rule.parent.removeChild(i) | ||
} | ||
} else if ( | ||
rule.name === 'media' && | ||
rule.params.includes('-resolution') && | ||
resolution | ||
) { | ||
resolution.clean(rule) | ||
} | ||
}) | ||
// Selectors | ||
for (let checker of this.prefixes.remove.selectors) { | ||
css.walkRules((rule, i) => { | ||
if (checker.check(rule)) { | ||
if (!this.disabled(rule, result)) { | ||
rule.parent.removeChild(i) | ||
} | ||
} | ||
}) | ||
} | ||
return css.walkDecls((decl, i) => { | ||
if (this.disabled(decl, result)) return | ||
let rule = decl.parent | ||
let unprefixed = this.prefixes.unprefixed(decl.prop) | ||
// Transition | ||
if (decl.prop === 'transition' || decl.prop === 'transition-property') { | ||
this.prefixes.transition.remove(decl) | ||
} | ||
// 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 | ||
}) | ||
if (unprefixed === 'flex-flow') { | ||
notHack = true | ||
} | ||
if (decl.prop === '-webkit-box-orient') { | ||
let hacks = { 'flex-direction': true, 'flex-flow': true } | ||
if (!decl.parent.some(j => hacks[j.prop])) return | ||
} | ||
if (notHack && !this.withHackValue(decl)) { | ||
if (decl.raw('before').includes('\n')) { | ||
this.reduceSpaces(decl) | ||
} | ||
rule.removeChild(i) | ||
return | ||
} | ||
} | ||
// Values | ||
for (let checker of this.prefixes.values('remove', unprefixed)) { | ||
if (!checker.check) continue | ||
if (!checker.check(decl.value)) continue | ||
unprefixed = checker.unprefixed | ||
let notHack = this.prefixes.group(decl).down(other => { | ||
return other.value.includes(unprefixed) | ||
}) | ||
if (notHack) { | ||
rule.removeChild(i) | ||
return | ||
} | ||
} | ||
}) | ||
} | ||
/** | ||
* Some rare old values, which is not in standard | ||
*/ | ||
withHackValue(decl) { | ||
return decl.prop === '-webkit-background-clip' && decl.value === 'text' | ||
} | ||
/** | ||
* Check for grid/flexbox options. | ||
*/ | ||
disabledValue(node, result) { | ||
if (this.gridStatus(node, result) === false && node.type === 'decl') { | ||
if (node.prop === 'display' && node.value.includes('grid')) { | ||
return true | ||
} | ||
} | ||
if (this.prefixes.options.flexbox === false && node.type === 'decl') { | ||
if (node.prop === 'display' && node.value.includes('flex')) { | ||
return true | ||
} | ||
} | ||
if (node.type === 'decl' && node.prop === 'content') { | ||
return true | ||
} | ||
return this.disabled(node, result) | ||
} | ||
/** | ||
* Check for grid/flexbox options. | ||
*/ | ||
disabledDecl(node, result) { | ||
if (this.gridStatus(node, result) === false && node.type === 'decl') { | ||
if (node.prop.includes('grid') || node.prop === 'justify-items') { | ||
return true | ||
} | ||
} | ||
if (this.prefixes.options.flexbox === false && node.type === 'decl') { | ||
let other = ['order', 'justify-content', 'align-items', 'align-content'] | ||
if (node.prop.includes('flex') || other.includes(node.prop)) { | ||
return true | ||
} | ||
} | ||
return this.disabled(node, result) | ||
} | ||
/** | ||
* Check for control comment and global options | ||
@@ -587,31 +460,39 @@ */ | ||
/** | ||
* Normalize spaces in cascade declaration group | ||
* Check for grid/flexbox options. | ||
*/ | ||
reduceSpaces(decl) { | ||
let stop = false | ||
this.prefixes.group(decl).up(() => { | ||
stop = true | ||
return true | ||
}) | ||
if (stop) { | ||
return | ||
disabledDecl(node, result) { | ||
if (node.type === 'decl' && this.gridStatus(node, result) === false) { | ||
if (node.prop.includes('grid') || node.prop === 'justify-items') { | ||
return true | ||
} | ||
} | ||
if (node.type === 'decl' && this.prefixes.options.flexbox === false) { | ||
let other = ['order', 'justify-content', 'align-items', 'align-content'] | ||
if (node.prop.includes('flex') || other.includes(node.prop)) { | ||
return true | ||
} | ||
} | ||
let parts = decl.raw('before').split('\n') | ||
let prevMin = parts[parts.length - 1].length | ||
let diff = false | ||
return this.disabled(node, result) | ||
} | ||
this.prefixes.group(decl).down(other => { | ||
parts = other.raw('before').split('\n') | ||
let last = parts.length - 1 | ||
/** | ||
* Check for grid/flexbox options. | ||
*/ | ||
disabledValue(node, result) { | ||
if (this.gridStatus(node, result) === false && node.type === 'decl') { | ||
if (node.prop === 'display' && node.value.includes('grid')) { | ||
return true | ||
} | ||
} | ||
if (this.prefixes.options.flexbox === false && node.type === 'decl') { | ||
if (node.prop === 'display' && node.value.includes('flex')) { | ||
return true | ||
} | ||
} | ||
if (node.type === 'decl' && node.prop === 'content') { | ||
return true | ||
} | ||
if (parts[last].length > prevMin) { | ||
if (diff === false) { | ||
diff = parts[last].length - prevMin | ||
} | ||
parts[last] = parts[last].slice(0, -diff) | ||
other.raws.before = parts.join('\n') | ||
} | ||
}) | ||
return this.disabled(node, result) | ||
} | ||
@@ -711,4 +592,132 @@ | ||
} | ||
/** | ||
* Normalize spaces in cascade declaration group | ||
*/ | ||
reduceSpaces(decl) { | ||
let stop = false | ||
this.prefixes.group(decl).up(() => { | ||
stop = true | ||
return true | ||
}) | ||
if (stop) { | ||
return | ||
} | ||
let parts = decl.raw('before').split('\n') | ||
let prevMin = parts[parts.length - 1].length | ||
let diff = false | ||
this.prefixes.group(decl).down(other => { | ||
parts = other.raw('before').split('\n') | ||
let last = parts.length - 1 | ||
if (parts[last].length > prevMin) { | ||
if (diff === false) { | ||
diff = parts[last].length - prevMin | ||
} | ||
parts[last] = parts[last].slice(0, -diff) | ||
other.raws.before = parts.join('\n') | ||
} | ||
}) | ||
} | ||
/** | ||
* Remove unnecessary pefixes | ||
*/ | ||
remove(css, result) { | ||
// At-rules | ||
let resolution = this.prefixes.remove['@resolution'] | ||
css.walkAtRules((rule, i) => { | ||
if (this.prefixes.remove[`@${rule.name}`]) { | ||
if (!this.disabled(rule, result)) { | ||
rule.parent.removeChild(i) | ||
} | ||
} else if ( | ||
rule.name === 'media' && | ||
rule.params.includes('-resolution') && | ||
resolution | ||
) { | ||
resolution.clean(rule) | ||
} | ||
}) | ||
// Selectors | ||
css.walkRules((rule, i) => { | ||
if (this.disabled(rule, result)) return | ||
for (let checker of this.prefixes.remove.selectors) { | ||
if (checker.check(rule)) { | ||
rule.parent.removeChild(i) | ||
return | ||
} | ||
} | ||
}) | ||
return css.walkDecls((decl, i) => { | ||
if (this.disabled(decl, result)) return | ||
let rule = decl.parent | ||
let unprefixed = this.prefixes.unprefixed(decl.prop) | ||
// Transition | ||
if (decl.prop === 'transition' || decl.prop === 'transition-property') { | ||
this.prefixes.transition.remove(decl) | ||
} | ||
// 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 | ||
}) | ||
if (unprefixed === 'flex-flow') { | ||
notHack = true | ||
} | ||
if (decl.prop === '-webkit-box-orient') { | ||
let hacks = { 'flex-direction': true, 'flex-flow': true } | ||
if (!decl.parent.some(j => hacks[j.prop])) return | ||
} | ||
if (notHack && !this.withHackValue(decl)) { | ||
if (decl.raw('before').includes('\n')) { | ||
this.reduceSpaces(decl) | ||
} | ||
rule.removeChild(i) | ||
return | ||
} | ||
} | ||
// Values | ||
for (let checker of this.prefixes.values('remove', unprefixed)) { | ||
if (!checker.check) continue | ||
if (!checker.check(decl.value)) continue | ||
unprefixed = checker.unprefixed | ||
let notHack = this.prefixes.group(decl).down(other => { | ||
return other.value.includes(unprefixed) | ||
}) | ||
if (notHack) { | ||
rule.removeChild(i) | ||
return | ||
} | ||
} | ||
}) | ||
} | ||
/** | ||
* Some rare old values, which is not in standard | ||
*/ | ||
withHackValue(decl) { | ||
return decl.prop === '-webkit-background-clip' && decl.value === 'text' | ||
} | ||
} | ||
module.exports = Processor |
@@ -11,2 +11,19 @@ let FractionJs = require('fraction.js') | ||
/** | ||
* 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')) | ||
} | ||
} | ||
rule.params = utils.editList(rule.params, queries => { | ||
return queries.filter(query => this.bad.every(i => !query.includes(i))) | ||
}) | ||
} | ||
/** | ||
* Return prefixed query name | ||
@@ -44,19 +61,2 @@ */ | ||
/** | ||
* 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')) | ||
} | ||
} | ||
rule.params = utils.editList(rule.params, queries => { | ||
return queries.filter(query => this.bad.every(i => !query.includes(i))) | ||
}) | ||
} | ||
/** | ||
* Add prefixed queries | ||
@@ -63,0 +63,0 @@ */ |
@@ -15,35 +15,69 @@ let { list } = require('postcss') | ||
/** | ||
* Is rule selectors need to be prefixed | ||
* Clone and add prefixes for at-rule | ||
*/ | ||
check(rule) { | ||
if (rule.selector.includes(this.name)) { | ||
return !!rule.selector.match(this.regexp()) | ||
add(rule, prefix) { | ||
let prefixeds = this.prefixeds(rule) | ||
if (this.already(rule, prefixeds, prefix)) { | ||
return | ||
} | ||
return false | ||
let cloned = this.clone(rule, { selector: prefixeds[this.name][prefix] }) | ||
rule.parent.insertBefore(rule, cloned) | ||
} | ||
/** | ||
* Return prefixed version of selector | ||
* Is rule already prefixed before | ||
*/ | ||
prefixed(prefix) { | ||
return this.name.replace(/^(\W*)/, `$1${prefix}`) | ||
already(rule, prefixeds, prefix) { | ||
let index = rule.parent.index(rule) - 1 | ||
while (index >= 0) { | ||
let before = rule.parent.nodes[index] | ||
if (before.type !== 'rule') { | ||
return false | ||
} | ||
let some = false | ||
for (let key in prefixeds[this.name]) { | ||
let prefixed = prefixeds[this.name][key] | ||
if (before.selector === prefixed) { | ||
if (prefix === key) { | ||
return true | ||
} else { | ||
some = true | ||
break | ||
} | ||
} | ||
} | ||
if (!some) { | ||
return false | ||
} | ||
index -= 1 | ||
} | ||
return false | ||
} | ||
/** | ||
* Lazy loadRegExp for name | ||
* Is rule selectors need to be prefixed | ||
*/ | ||
regexp(prefix) { | ||
if (!this.regexpCache.has(prefix)) { | ||
let name = prefix ? this.prefixed(prefix) : this.name | ||
this.regexpCache.set( | ||
prefix, | ||
new RegExp(`(^|[^:"'=])${utils.escapeRegexp(name)}`, 'gi') | ||
) | ||
check(rule) { | ||
if (rule.selector.includes(this.name)) { | ||
return !!rule.selector.match(this.regexp()) | ||
} | ||
return this.regexpCache.get(prefix) | ||
return false | ||
} | ||
/** | ||
* Return function to fast find prefixed selector | ||
*/ | ||
old(prefix) { | ||
return new OldSelector(this, prefix) | ||
} | ||
/** | ||
* All possible prefixes | ||
@@ -56,2 +90,9 @@ */ | ||
/** | ||
* Return prefixed version of selector | ||
*/ | ||
prefixed(prefix) { | ||
return this.name.replace(/^(\W*)/, `$1${prefix}`) | ||
} | ||
/** | ||
* Return all possible selector prefixes | ||
@@ -89,34 +130,14 @@ */ | ||
/** | ||
* Is rule already prefixed before | ||
* Lazy loadRegExp for name | ||
*/ | ||
already(rule, prefixeds, prefix) { | ||
let index = rule.parent.index(rule) - 1 | ||
while (index >= 0) { | ||
let before = rule.parent.nodes[index] | ||
if (before.type !== 'rule') { | ||
return false | ||
} | ||
let some = false | ||
for (let key in prefixeds[this.name]) { | ||
let prefixed = prefixeds[this.name][key] | ||
if (before.selector === prefixed) { | ||
if (prefix === key) { | ||
return true | ||
} else { | ||
some = true | ||
break | ||
} | ||
} | ||
} | ||
if (!some) { | ||
return false | ||
} | ||
index -= 1 | ||
regexp(prefix) { | ||
if (!this.regexpCache.has(prefix)) { | ||
let name = prefix ? this.prefixed(prefix) : this.name | ||
this.regexpCache.set( | ||
prefix, | ||
new RegExp(`(^|[^:"'=])${utils.escapeRegexp(name)}`, 'gi') | ||
) | ||
} | ||
return false | ||
return this.regexpCache.get(prefix) | ||
} | ||
@@ -130,25 +151,4 @@ | ||
} | ||
/** | ||
* Clone and add prefixes for at-rule | ||
*/ | ||
add(rule, prefix) { | ||
let prefixeds = this.prefixeds(rule) | ||
if (this.already(rule, prefixeds, prefix)) { | ||
return | ||
} | ||
let cloned = this.clone(rule, { selector: prefixeds[this.name][prefix] }) | ||
rule.parent.insertBefore(rule, cloned) | ||
} | ||
/** | ||
* Return function to fast find prefixed selector | ||
*/ | ||
old(prefix) { | ||
return new OldSelector(this, prefix) | ||
} | ||
} | ||
module.exports = Selector |
let featureQueries = require('caniuse-lite/data/features/css-featurequeries.js') | ||
let { feature } = require('caniuse-lite') | ||
let feature = require('caniuse-lite/dist/unpacker/feature') | ||
let { parse } = require('postcss') | ||
@@ -30,72 +30,88 @@ | ||
/** | ||
* Return prefixer only with @supports supported browsers | ||
* Add prefixes | ||
*/ | ||
prefixer() { | ||
if (this.prefixerCache) { | ||
return this.prefixerCache | ||
} | ||
add(nodes, all) { | ||
return nodes.map(i => { | ||
if (this.isProp(i)) { | ||
let prefixed = this.prefixed(i[0]) | ||
if (prefixed.length > 1) { | ||
return this.convert(prefixed) | ||
} | ||
let filtered = this.all.browsers.selected.filter(i => { | ||
return supported.includes(i) | ||
return i | ||
} | ||
if (typeof i === 'object') { | ||
return this.add(i, all) | ||
} | ||
return i | ||
}) | ||
let 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 | ||
* Clean brackets with one child | ||
*/ | ||
parse(str) { | ||
let parts = str.split(':') | ||
let prop = parts[0] | ||
let value = parts[1] | ||
if (!value) value = '' | ||
return [prop.trim(), value.trim()] | ||
cleanBrackets(nodes) { | ||
return nodes.map(i => { | ||
if (typeof i !== 'object') { | ||
return i | ||
} | ||
if (i.length === 1 && typeof i[0] === 'object') { | ||
return this.cleanBrackets(i[0]) | ||
} | ||
return this.cleanBrackets(i) | ||
}) | ||
} | ||
/** | ||
* Create virtual rule to process it by prefixer | ||
* Add " or " between properties and convert it to brackets format | ||
*/ | ||
virtual(str) { | ||
let [prop, value] = this.parse(str) | ||
let rule = parse('a{}').first | ||
rule.append({ prop, value, raws: { before: '' } }) | ||
return rule | ||
convert(progress) { | ||
let result = [''] | ||
for (let i of progress) { | ||
result.push([`${i.prop}: ${i.value}`]) | ||
result.push(' or ') | ||
} | ||
result[result.length - 1] = '' | ||
return result | ||
} | ||
/** | ||
* Return array of Declaration with all necessary prefixes | ||
* Check global options | ||
*/ | ||
prefixed(str) { | ||
let rule = this.virtual(str) | ||
if (this.disabled(rule.first)) { | ||
return rule.nodes | ||
disabled(node) { | ||
if (!this.all.options.grid) { | ||
if (node.prop === 'display' && node.value.includes('grid')) { | ||
return true | ||
} | ||
if (node.prop.includes('grid') || node.prop === 'justify-items') { | ||
return true | ||
} | ||
} | ||
let result = { warn: () => null } | ||
let prefixer = this.prefixer().add[rule.first.prop] | ||
prefixer && prefixer.process && prefixer.process(rule.first, result) | ||
for (let decl of rule.nodes) { | ||
for (let value of this.prefixer().values('add', rule.first.prop)) { | ||
value.process(decl) | ||
if (this.all.options.flexbox === false) { | ||
if (node.prop === 'display' && node.value.includes('flex')) { | ||
return true | ||
} | ||
Value.save(this.all, decl) | ||
let other = ['order', 'justify-content', 'align-items', 'align-content'] | ||
if (node.prop.includes('flex') || other.includes(node.prop)) { | ||
return true | ||
} | ||
} | ||
return rule.nodes | ||
return false | ||
} | ||
/** | ||
* Return true if prefixed property has no unprefixed | ||
*/ | ||
isHack(all, unprefixed) { | ||
let check = new RegExp(`(\\(|\\s)${utils.escapeRegexp(unprefixed)}:`) | ||
return !check.test(all) | ||
} | ||
/** | ||
* Return true if brackets node is "not" word | ||
@@ -126,36 +142,98 @@ */ | ||
/** | ||
* Return true if prefixed property has no unprefixed | ||
* Compress value functions into a string nodes | ||
*/ | ||
isHack(all, unprefixed) { | ||
let check = new RegExp(`(\\(|\\s)${utils.escapeRegexp(unprefixed)}:`) | ||
return !check.test(all) | ||
normalize(nodes) { | ||
if (typeof nodes !== 'object') { | ||
return nodes | ||
} | ||
nodes = nodes.filter(i => i !== '') | ||
if (typeof nodes[0] === 'string') { | ||
let firstNode = nodes[0].trim() | ||
if ( | ||
firstNode.includes(':') || | ||
firstNode === 'selector' || | ||
firstNode === 'not selector' | ||
) { | ||
return [brackets.stringify(nodes)] | ||
} | ||
} | ||
return nodes.map(i => this.normalize(i)) | ||
} | ||
/** | ||
* Return true if we need to remove node | ||
* Parse string into declaration property and value | ||
*/ | ||
toRemove(str, all) { | ||
let [prop, value] = this.parse(str) | ||
let unprefixed = this.all.unprefixed(prop) | ||
parse(str) { | ||
let parts = str.split(':') | ||
let prop = parts[0] | ||
let value = parts[1] | ||
if (!value) value = '' | ||
return [prop.trim(), value.trim()] | ||
} | ||
let cleaner = this.all.cleaner() | ||
if ( | ||
cleaner.remove[prop] && | ||
cleaner.remove[prop].remove && | ||
!this.isHack(all, unprefixed) | ||
) { | ||
return true | ||
/** | ||
* Return array of Declaration with all necessary prefixes | ||
*/ | ||
prefixed(str) { | ||
let rule = this.virtual(str) | ||
if (this.disabled(rule.first)) { | ||
return rule.nodes | ||
} | ||
for (let checker of cleaner.values('remove', unprefixed)) { | ||
if (checker.check(value)) { | ||
return true | ||
let result = { warn: () => null } | ||
let prefixer = this.prefixer().add[rule.first.prop] | ||
prefixer && prefixer.process && prefixer.process(rule.first, result) | ||
for (let decl of rule.nodes) { | ||
for (let value of this.prefixer().values('add', rule.first.prop)) { | ||
value.process(decl) | ||
} | ||
Value.save(this.all, decl) | ||
} | ||
return false | ||
return rule.nodes | ||
} | ||
/** | ||
* Return prefixer only with @supports supported browsers | ||
*/ | ||
prefixer() { | ||
if (this.prefixerCache) { | ||
return this.prefixerCache | ||
} | ||
let filtered = this.all.browsers.selected.filter(i => { | ||
return supported.includes(i) | ||
}) | ||
let 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 | ||
} | ||
/** | ||
* 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) | ||
rule.params = brackets.stringify(ast) | ||
} | ||
/** | ||
* Remove all unnecessary prefixes | ||
@@ -190,116 +268,38 @@ */ | ||
/** | ||
* Clean brackets with one child | ||
* Return true if we need to remove node | ||
*/ | ||
cleanBrackets(nodes) { | ||
return nodes.map(i => { | ||
if (typeof i !== 'object') { | ||
return i | ||
} | ||
toRemove(str, all) { | ||
let [prop, value] = this.parse(str) | ||
let unprefixed = this.all.unprefixed(prop) | ||
if (i.length === 1 && typeof i[0] === 'object') { | ||
return this.cleanBrackets(i[0]) | ||
} | ||
let cleaner = this.all.cleaner() | ||
return this.cleanBrackets(i) | ||
}) | ||
} | ||
/** | ||
* Add " or " between properties and convert it to brackets format | ||
*/ | ||
convert(progress) { | ||
let result = [''] | ||
for (let i of progress) { | ||
result.push([`${i.prop}: ${i.value}`]) | ||
result.push(' or ') | ||
if ( | ||
cleaner.remove[prop] && | ||
cleaner.remove[prop].remove && | ||
!this.isHack(all, unprefixed) | ||
) { | ||
return true | ||
} | ||
result[result.length - 1] = '' | ||
return result | ||
} | ||
/** | ||
* Compress value functions into a string nodes | ||
*/ | ||
normalize(nodes) { | ||
if (typeof nodes !== 'object') { | ||
return nodes | ||
} | ||
nodes = nodes.filter(i => i !== '') | ||
if (typeof nodes[0] === 'string') { | ||
let firstNode = nodes[0].trim() | ||
if ( | ||
firstNode.includes(':') || | ||
firstNode === 'selector' || | ||
firstNode === 'not selector' | ||
) { | ||
return [brackets.stringify(nodes)] | ||
for (let checker of cleaner.values('remove', unprefixed)) { | ||
if (checker.check(value)) { | ||
return true | ||
} | ||
} | ||
return nodes.map(i => this.normalize(i)) | ||
} | ||
/** | ||
* Add prefixes | ||
*/ | ||
add(nodes, all) { | ||
return nodes.map(i => { | ||
if (this.isProp(i)) { | ||
let prefixed = this.prefixed(i[0]) | ||
if (prefixed.length > 1) { | ||
return this.convert(prefixed) | ||
} | ||
return i | ||
} | ||
if (typeof i === 'object') { | ||
return this.add(i, all) | ||
} | ||
return i | ||
}) | ||
return false | ||
} | ||
/** | ||
* Add prefixed declaration | ||
* Create virtual rule to process it by prefixer | ||
*/ | ||
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) | ||
rule.params = brackets.stringify(ast) | ||
virtual(str) { | ||
let [prop, value] = this.parse(str) | ||
let rule = parse('a{}').first | ||
rule.append({ prop, raws: { before: '' }, value }) | ||
return rule | ||
} | ||
/** | ||
* Check global options | ||
*/ | ||
disabled(node) { | ||
if (!this.all.options.grid) { | ||
if (node.prop === 'display' && node.value.includes('grid')) { | ||
return true | ||
} | ||
if (node.prop.includes('grid') || node.prop === 'justify-items') { | ||
return true | ||
} | ||
} | ||
if (this.all.options.flexbox === false) { | ||
if (node.prop === 'display' && node.value.includes('flex')) { | ||
return true | ||
} | ||
let other = ['order', 'justify-content', 'align-items', 'align-content'] | ||
if (node.prop.includes('flex') || other.includes(node.prop)) { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
} | ||
module.exports = Supports |
@@ -83,17 +83,2 @@ let { list } = require('postcss') | ||
/** | ||
* Find property name | ||
*/ | ||
findProp(param) { | ||
let prop = param[0].value | ||
if (/^\d/.test(prop)) { | ||
for (let [i, token] of param.entries()) { | ||
if (i !== 0 && token.type === 'word') { | ||
return token.value | ||
} | ||
} | ||
} | ||
return prop | ||
} | ||
/** | ||
* Does we already have this declaration | ||
@@ -106,11 +91,2 @@ */ | ||
/** | ||
* Add declaration if it is not exist | ||
*/ | ||
cloneBefore(decl, prop, value) { | ||
if (!this.already(decl, prop, value)) { | ||
decl.cloneBefore({ prop, value }) | ||
} | ||
} | ||
/** | ||
* Show transition-property warning | ||
@@ -161,75 +137,26 @@ */ | ||
/** | ||
* Process transition and remove all unnecessary properties | ||
* Remove all non-webkit prefixes and unprefixed params if we have prefixed | ||
*/ | ||
remove(decl) { | ||
let params = this.parse(decl.value) | ||
params = params.filter(i => { | ||
let prop = this.prefixes.remove[this.findProp(i)] | ||
return !prop || !prop.remove | ||
}) | ||
let value = this.stringify(params) | ||
cleanFromUnprefixed(params, prefix) { | ||
let remove = params | ||
.map(i => this.findProp(i)) | ||
.filter(i => i.slice(0, prefix.length) === prefix) | ||
.map(i => this.prefixes.unprefixed(i)) | ||
if (decl.value === value) { | ||
return | ||
} | ||
if (params.length === 0) { | ||
decl.remove() | ||
return | ||
} | ||
let double = decl.parent.some(i => { | ||
return i.prop === decl.prop && i.value === value | ||
}) | ||
let smaller = decl.parent.some(i => { | ||
return i !== decl && i.prop === decl.prop && i.value.length > value.length | ||
}) | ||
if (double || smaller) { | ||
decl.remove() | ||
return | ||
} | ||
decl.value = value | ||
} | ||
/** | ||
* Parse properties list to array | ||
*/ | ||
parse(value) { | ||
let ast = parser(value) | ||
let result = [] | ||
let param = [] | ||
for (let node of ast.nodes) { | ||
param.push(node) | ||
if (node.type === 'div' && node.value === ',') { | ||
for (let param of params) { | ||
let prop = this.findProp(param) | ||
let p = vendor.prefix(prop) | ||
if (!remove.includes(prop) && (p === prefix || p === '')) { | ||
result.push(param) | ||
param = [] | ||
} | ||
} | ||
result.push(param) | ||
return result.filter(i => i.length > 0) | ||
return result | ||
} | ||
/** | ||
* Return properties string from array | ||
*/ | ||
stringify(params) { | ||
if (params.length === 0) { | ||
return '' | ||
} | ||
let nodes = [] | ||
for (let param of params) { | ||
if (param[param.length - 1].type !== 'div') { | ||
param.push(this.div(params)) | ||
} | ||
nodes = nodes.concat(param) | ||
} | ||
if (nodes[0].type === 'div') { | ||
nodes = nodes.slice(1) | ||
} | ||
if (nodes[nodes.length - 1].type === 'div') { | ||
nodes = nodes.slice(0, +-2 + 1 || undefined) | ||
} | ||
return parser.stringify({ nodes }) | ||
cleanOtherPrefixes(params, prefix) { | ||
return params.filter(param => { | ||
let current = vendor.prefix(this.findProp(param)) | ||
return current === '' || current === prefix | ||
}) | ||
} | ||
@@ -255,2 +182,28 @@ | ||
/** | ||
* Add declaration if it is not exist | ||
*/ | ||
cloneBefore(decl, prop, value) { | ||
if (!this.already(decl, prop, value)) { | ||
decl.cloneBefore({ prop, value }) | ||
} | ||
} | ||
/** | ||
* Check property for disabled by option | ||
*/ | ||
disabled(prop, prefix) { | ||
let other = ['order', 'justify-content', 'align-self', 'align-content'] | ||
if (prop.includes('flex') || other.includes(prop)) { | ||
if (this.prefixes.options.flexbox === false) { | ||
return true | ||
} | ||
if (this.prefixes.options.flexbox === 'no-2009') { | ||
return prefix.includes('2009') | ||
} | ||
} | ||
return undefined | ||
} | ||
/** | ||
* Find or create separator | ||
@@ -266,47 +219,71 @@ */ | ||
} | ||
return { type: 'div', value: ',', after: ' ' } | ||
return { after: ' ', type: 'div', value: ',' } | ||
} | ||
cleanOtherPrefixes(params, prefix) { | ||
return params.filter(param => { | ||
let current = vendor.prefix(this.findProp(param)) | ||
return current === '' || current === prefix | ||
}) | ||
/** | ||
* Find property name | ||
*/ | ||
findProp(param) { | ||
let prop = param[0].value | ||
if (/^\d/.test(prop)) { | ||
for (let [i, token] of param.entries()) { | ||
if (i !== 0 && token.type === 'word') { | ||
return token.value | ||
} | ||
} | ||
} | ||
return prop | ||
} | ||
/** | ||
* Remove all non-webkit prefixes and unprefixed params if we have prefixed | ||
* Parse properties list to array | ||
*/ | ||
cleanFromUnprefixed(params, prefix) { | ||
let remove = params | ||
.map(i => this.findProp(i)) | ||
.filter(i => i.slice(0, prefix.length) === prefix) | ||
.map(i => this.prefixes.unprefixed(i)) | ||
parse(value) { | ||
let ast = parser(value) | ||
let result = [] | ||
for (let param of params) { | ||
let prop = this.findProp(param) | ||
let p = vendor.prefix(prop) | ||
if (!remove.includes(prop) && (p === prefix || p === '')) { | ||
let param = [] | ||
for (let node of ast.nodes) { | ||
param.push(node) | ||
if (node.type === 'div' && node.value === ',') { | ||
result.push(param) | ||
param = [] | ||
} | ||
} | ||
return result | ||
result.push(param) | ||
return result.filter(i => i.length > 0) | ||
} | ||
/** | ||
* Check property for disabled by option | ||
* Process transition and remove all unnecessary properties | ||
*/ | ||
disabled(prop, prefix) { | ||
let other = ['order', 'justify-content', 'align-self', 'align-content'] | ||
if (prop.includes('flex') || other.includes(prop)) { | ||
if (this.prefixes.options.flexbox === false) { | ||
return true | ||
} | ||
remove(decl) { | ||
let params = this.parse(decl.value) | ||
params = params.filter(i => { | ||
let prop = this.prefixes.remove[this.findProp(i)] | ||
return !prop || !prop.remove | ||
}) | ||
let value = this.stringify(params) | ||
if (this.prefixes.options.flexbox === 'no-2009') { | ||
return prefix.includes('2009') | ||
} | ||
if (decl.value === value) { | ||
return | ||
} | ||
return undefined | ||
if (params.length === 0) { | ||
decl.remove() | ||
return | ||
} | ||
let double = decl.parent.some(i => { | ||
return i.prop === decl.prop && i.value === value | ||
}) | ||
let smaller = decl.parent.some(i => { | ||
return i !== decl && i.prop === decl.prop && i.value.length > value.length | ||
}) | ||
if (double || smaller) { | ||
decl.remove() | ||
return | ||
} | ||
decl.value = value | ||
} | ||
@@ -332,4 +309,27 @@ | ||
} | ||
/** | ||
* Return properties string from array | ||
*/ | ||
stringify(params) { | ||
if (params.length === 0) { | ||
return '' | ||
} | ||
let nodes = [] | ||
for (let param of params) { | ||
if (param[param.length - 1].type !== 'div') { | ||
param.push(this.div(params)) | ||
} | ||
nodes = nodes.concat(param) | ||
} | ||
if (nodes[0].type === 'div') { | ||
nodes = nodes.slice(1) | ||
} | ||
if (nodes[nodes.length - 1].type === 'div') { | ||
nodes = nodes.slice(0, +-2 + 1 || undefined) | ||
} | ||
return parser.stringify({ nodes }) | ||
} | ||
} | ||
module.exports = Transition |
@@ -79,1 +79,16 @@ let { list } = require('postcss') | ||
} | ||
/** | ||
* Return true if a given value only contains numbers. | ||
* @param {*} value | ||
* @returns {boolean} | ||
*/ | ||
module.exports.isPureNumber = function (value) { | ||
if (typeof value === 'number') { | ||
return true | ||
} | ||
if (typeof value === 'string') { | ||
return /^[0-9]+$/.test(value) | ||
} | ||
return false | ||
} |
@@ -62,2 +62,21 @@ let Prefixer = require('./prefixer') | ||
/** | ||
* Save values with next prefixed token | ||
*/ | ||
add(decl, prefix) { | ||
if (!decl._autoprefixerValues) { | ||
decl._autoprefixerValues = {} | ||
} | ||
let value = decl._autoprefixerValues[prefix] || this.value(decl) | ||
let before | ||
do { | ||
before = value | ||
value = this.replace(value, prefix) | ||
if (value === false) return | ||
} while (value !== before) | ||
decl._autoprefixerValues[prefix] = value | ||
} | ||
/** | ||
* Is declaration need to be prefixed | ||
@@ -75,2 +94,9 @@ */ | ||
/** | ||
* Return function to fast find prefixed value | ||
*/ | ||
old(prefix) { | ||
return new OldValue(this.name, prefix + this.name) | ||
} | ||
/** | ||
* Lazy regexp loading | ||
@@ -99,30 +125,4 @@ */ | ||
} | ||
/** | ||
* Save values with next prefixed token | ||
*/ | ||
add(decl, prefix) { | ||
if (!decl._autoprefixerValues) { | ||
decl._autoprefixerValues = {} | ||
} | ||
let value = decl._autoprefixerValues[prefix] || this.value(decl) | ||
let before | ||
do { | ||
before = value | ||
value = this.replace(value, prefix) | ||
if (value === false) return | ||
} while (value !== before) | ||
decl._autoprefixerValues[prefix] = value | ||
} | ||
/** | ||
* Return function to fast find prefixed value | ||
*/ | ||
old(prefix) { | ||
return new OldValue(this.name, prefix + this.name) | ||
} | ||
} | ||
module.exports = Value |
{ | ||
"name": "autoprefixer", | ||
"version": "10.4.2", | ||
"version": "10.4.16", | ||
"description": "Parse CSS and add vendor prefixes to CSS rules using values from the Can I Use website", | ||
@@ -18,6 +18,16 @@ "engines": { | ||
"types": "lib/autoprefixer.d.ts", | ||
"funding": { | ||
"type": "opencollective", | ||
"url": "https://opencollective.com/postcss/" | ||
}, | ||
"funding": [ | ||
{ | ||
"type": "opencollective", | ||
"url": "https://opencollective.com/postcss/" | ||
}, | ||
{ | ||
"type": "tidelift", | ||
"url": "https://tidelift.com/funding/github/npm/autoprefixer" | ||
}, | ||
{ | ||
"type": "github", | ||
"url": "https://github.com/sponsors/ai" | ||
} | ||
], | ||
"author": "Andrey Sitnik <andrey@sitnik.ru>", | ||
@@ -33,5 +43,5 @@ "license": "MIT", | ||
"dependencies": { | ||
"browserslist": "^4.19.1", | ||
"caniuse-lite": "^1.0.30001297", | ||
"fraction.js": "^4.1.2", | ||
"browserslist": "^4.21.10", | ||
"caniuse-lite": "^1.0.30001538", | ||
"fraction.js": "^4.3.6", | ||
"normalize-range": "^0.1.2", | ||
@@ -38,0 +48,0 @@ "picocolors": "^1.0.0", |
# Autoprefixer [![Cult Of Martians][cult-img]][cult] | ||
<img align="right" width="94" height="71" | ||
src="http://postcss.github.io/autoprefixer/logo.svg" | ||
src="https://postcss.github.io/autoprefixer/logo.svg" | ||
title="Autoprefixer logo by Anton Lovchikov"> | ||
@@ -36,5 +36,2 @@ | ||
} | ||
:-ms-input-placeholder { | ||
color: gray; | ||
} | ||
::placeholder { | ||
@@ -64,8 +61,8 @@ color: gray; | ||
[Can I Use]: https://caniuse.com/ | ||
[cult-img]: http://cultofmartians.com/assets/badges/badge.svg | ||
[cult-img]: https://cultofmartians.com/assets/badges/badge.svg | ||
[PostCSS]: https://github.com/postcss/postcss | ||
[cult]: http://cultofmartians.com/tasks/autoprefixer-grid.html | ||
[cult]: https://cultofmartians.com/tasks/autoprefixer-grid.html | ||
## Docs | ||
Read **[full docs](https://github.com/postcss/autoprefixer#readme)** on GitHub. | ||
Read full docs **[here](https://github.com/postcss/autoprefixer#readme)**. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
199002
6999
67
Updatedbrowserslist@^4.21.10
Updatedcaniuse-lite@^1.0.30001538
Updatedfraction.js@^4.3.6