From 58442218e2cac6b19e363db25006b5b38d0b45bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=A5=BA?= Date: Tue, 25 Apr 2017 19:16:24 +0800 Subject: [PATCH 1/7] add support for `property-no-vendor-prefix` & `value-no-vendor-prefix` --- .eslintrc.json | 7 + .gitignore | 2 + .npmignore | 2 + .travis.yml | 2 +- bin/cli.js | 2 +- lib/formatAtRules.js | 12 +- lib/formatDecls.js | 43 +- lib/formatSelectors.js | 12 +- lib/formatShorthand.js | 32 +- lib/formatValues.js | 3 +- lib/gradient.js | 514 ++++++++++++++++++ lib/unprefixer.js | 255 +++++++++ lib/util.js | 46 +- package.json | 21 + test/stylelint/no-vendor-prefix/.stylelintrc | 6 + .../no-vendor-prefix/no-vendor-prefix.css | 275 ++++++++++ .../no-vendor-prefix/no-vendor-prefix.out.css | 105 ++++ .../property-no-vendor-prefix/.stylelintrc | 5 + .../property-no-vendor-prefix.css | 315 +++++++++++ .../property-no-vendor-prefix.out.css | 170 ++++++ .../value-no-vendor-prefix/.stylelintrc | 5 + .../value-no-vendor-prefix.css | 146 +++++ .../value-no-vendor-prefix.out.css | 138 +++++ 23 files changed, 2083 insertions(+), 35 deletions(-) create mode 100644 lib/gradient.js create mode 100644 lib/unprefixer.js create mode 100644 test/stylelint/no-vendor-prefix/.stylelintrc create mode 100644 test/stylelint/no-vendor-prefix/no-vendor-prefix.css create mode 100644 test/stylelint/no-vendor-prefix/no-vendor-prefix.out.css create mode 100644 test/stylelint/property-no-vendor-prefix/.stylelintrc create mode 100644 test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.css create mode 100644 test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css create mode 100644 test/stylelint/value-no-vendor-prefix/.stylelintrc create mode 100644 test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.css create mode 100644 test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css diff --git a/.eslintrc.json b/.eslintrc.json index e68b2a4..c492bab 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,7 +5,14 @@ "es6": true }, "rules": { + "comma-spacing": [ + "error" + ], "no-console": 0, + "quotes": [ + "error", + "single" + ], "space-before-function-paren": [2, "always"], "semi": [2, "never"], "eqeqeq": [2, "allow-null"], diff --git a/.gitignore b/.gitignore index 93f1361..4d2f777 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ node_modules npm-debug.log +.nyc_output/ +coverage/ diff --git a/.npmignore b/.npmignore index c2615d3..e5d0f3e 100644 --- a/.npmignore +++ b/.npmignore @@ -4,3 +4,5 @@ test .eslintrc.json .travis.yml CHANGELOG.md +.nyc_output +coverage diff --git a/.travis.yml b/.travis.yml index 6e56405..8ebbf33 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,4 +5,4 @@ node_js: - "6" script: - npm run lint - - npm test + - npm test-cov diff --git a/bin/cli.js b/bin/cli.js index be8536b..c47fd29 100644 --- a/bin/cli.js +++ b/bin/cli.js @@ -110,7 +110,7 @@ if (argv.r) { function processMultipleFiles (files) { files = files.filter(isCss).sort() if(!files.length){ - console.error("Files glob patterns specified did not match any css files.") + console.error('Files glob patterns specified did not match any css files.') return } diff --git a/lib/formatAtRules.js b/lib/formatAtRules.js index 859980b..ef7409c 100644 --- a/lib/formatAtRules.js +++ b/lib/formatAtRules.js @@ -98,7 +98,7 @@ function formatAtRules (root, params) { } if (atrule.name === 'mixin') { - atrule.params = atrule.params.replace(/(^[\w|-]+)\s*\(/, "$1(") + atrule.params = atrule.params.replace(/(^[\w|-]+)\s*\(/, '$1(') formatDecls(atrule, indentation, indentWidth, stylelint) } @@ -106,7 +106,7 @@ function formatAtRules (root, params) { atrule.name === 'debug' || atrule.name === 'warn' || atrule.name === 'error' ) { - atrule.params = atrule.params.replace(/\s+/g, " ") + atrule.params = atrule.params.replace(/\s+/g, ' ') atrule.raws.before = '\n' + indentation atrule.raws.between = '' } @@ -123,7 +123,7 @@ function formatAtRules (root, params) { } if (atrule.name === 'include') { - atrule.params = atrule.params.replace(/(^[\w|-]+)\s*\(/, "$1(") + atrule.params = atrule.params.replace(/(^[\w|-]+)\s*\(/, '$1(') atrule.params = atrule.params.replace(/\)\s*{/g, ') ') if (!hasLineBreaksBefore) { atrule.raws.before = '\n' + indentation @@ -215,7 +215,7 @@ function formatAtRules (root, params) { function isAfterComment (prev) { return ( prev - && prev.type === "comment" + && prev.type === 'comment' ) } @@ -228,7 +228,7 @@ function isFirstNested (prev, atrule, isNested) { function isBlocklessGroup (prev, atrule) { return ( - prev && prev.type === "atrule" + prev && prev.type === 'atrule' && !hasBlock(prev) && !hasBlock(atrule) ) @@ -238,7 +238,7 @@ function isBlocklessAfterSameNameBlockless (prev, atrule) { return ( !hasBlock(atrule) && prev && !hasBlock(prev) - && prev.type === "atrule" + && prev.type === 'atrule' && prev.name === atrule.name ) } diff --git a/lib/formatDecls.js b/lib/formatDecls.js index dd18178..7315048 100644 --- a/lib/formatDecls.js +++ b/lib/formatDecls.js @@ -1,17 +1,56 @@ var formatValues = require('./formatValues') var hasDecls = require('./hasDecls') +var unprefixer = require('./unprefixer') var hasEmptyLine = require('stylelint/lib/utils/hasEmptyLine') var isStandardSyntaxDeclaration = require('stylelint/lib/utils/isStandardSyntaxDeclaration') var isCustomProperty = require('stylelint/lib/utils/isCustomProperty') var util = require('./util') var getProperty = util.getProperty var getOptions = util.getOptions -var isSingleLineString = require("stylelint/lib/utils/isSingleLineString") +var isSingleLineString = require('stylelint/lib/utils/isSingleLineString') +var postcss = require('postcss') function formatDecls (rule, indent, indentWidth, stylelint) { + function clearPrefixedDecl (decl) { + var prop = postcss.vendor.unprefixed(decl.prop) + var prefixedDecls = [] + var unprefixed + var lastUnprefixed + + rule.walkDecls(new RegExp('^-\\w+-' + prop + '$'), function (decl) { + prefixedDecls.push(decl) + }) + + rule.walkDecls(unprefixer(decl).prop || prop, function (decl) { + lastUnprefixed = unprefixer(decl) + if(lastUnprefixed.value) { + prefixedDecls.push(decl) + } else { + unprefixed = decl + } + }) + + if (!unprefixed) { + var lastDecl = prefixedDecls.pop(); + (lastUnprefixed || unprefixer(lastDecl)).replace() + } + + prefixedDecls.forEach(function (decl) { + decl.remove() + }) + } const isSingleLine = isSingleLineString(rule) if (hasDecls(rule)) { + var propNoVendorPrefix = getProperty(stylelint, 'property-no-vendor-prefix') + var valueNoVendorPrefix = getProperty(stylelint, 'value-no-vendor-prefix') rule.walkDecls(function (decl) { + if ((propNoVendorPrefix && /^-\w+-(.+)$/.test(decl.prop)) || (valueNoVendorPrefix && /(^|,|\s)-\w+-.+/.test(decl.value))) { + clearPrefixedDecl(decl) + if(!decl.parent) { + return + } + } + var isSassVal = /^\$/.test(decl.prop) var isIEHack = (/(\*|_)$/).test(decl.raws.before) if (decl.prop && !isCustomProperty(decl.prop) && !isSassVal) { @@ -71,7 +110,7 @@ function declarationEmptyLineBefore (stylelint, decl, indent, indentWidth, isSin var exceptOptions = getOptions(stylelint, 'declaration-empty-line-before', 'except') || [] var ignoreOptions = getOptions(stylelint, 'declaration-empty-line-before', 'ignore') || [] - var expectEmptyLineBefore = declarationEmptyLineBeforeRule === "always" + var expectEmptyLineBefore = declarationEmptyLineBeforeRule === 'always' if (ignoreOptions.indexOf('after-comment') !== -1 && prev && prev.type === 'comment') { ignore = true diff --git a/lib/formatSelectors.js b/lib/formatSelectors.js index 87642d3..1f3a97e 100644 --- a/lib/formatSelectors.js +++ b/lib/formatSelectors.js @@ -6,11 +6,11 @@ function formatSelectors (rule, indentation, stylelint) { rule.selectors.forEach(function (selector, i) { // don't add extra spaces to :nth-child(5n+1) etc. if (!hasPlusInsideParens(selector) && !isAttrSelector(selector)) { - selector = selector.replace(/\s*([+~>])\s*/g, " $1 ") + selector = selector.replace(/\s*([+~>])\s*/g, ' $1 ') } if (isAttrSelector(selector)) { - selector = selector.replace(/\[\s*(\S+)\s*\]/g, "[$1]") + selector = selector.replace(/\[\s*(\S+)\s*\]/g, '[$1]') } selector = selectorCombinatorSpaceBefore(stylelint, selector) @@ -46,18 +46,18 @@ function formatSelectors (rule, indentation, stylelint) { function selectorCombinatorSpaceBefore (stylelint, selector) { switch (getProperty(stylelint, 'selector-combinator-space-before')) { case 'never': - return selector.replace(/\s+(?=[+~>])/g, "") + return selector.replace(/\s+(?=[+~>])/g, '') default: - return selector.replace(/^\s*([+~>])/g, " $1") + return selector.replace(/^\s*([+~>])/g, ' $1') } } function selectorCombinatorSpaceAfter (stylelint, selector) { switch (getProperty(stylelint, 'selector-combinator-space-after')) { case 'never': - return selector.replace(/([+~>])\s*/g, "$1") + return selector.replace(/([+~>])\s*/g, '$1') default: - return selector.replace(/^\s*([+~>])\s*/g, "$1 ") + return selector.replace(/^\s*([+~>])\s*/g, '$1 ') } } diff --git a/lib/formatShorthand.js b/lib/formatShorthand.js index 0b36aa4..a0f6a39 100644 --- a/lib/formatShorthand.js +++ b/lib/formatShorthand.js @@ -1,27 +1,27 @@ var valueParser = require('postcss-value-parser') var getProperty = require('./util').getProperty -var ignoredCharacters = ["+", "-", "*", "/", "(", ")", "$", "@", "--", "var("] +var ignoredCharacters = ['+', '-', '*', '/', '(', ')', '$', '@', '--', 'var('] var ignoredShorthandProperties = [ - "background", - "font", - "border", - "border-top", - "border-bottom", - "border-left", - "border-right", - "list-style", - "transition", + 'background', + 'font', + 'border', + 'border-top', + 'border-bottom', + 'border-left', + 'border-right', + 'list-style', + 'transition', ] var shorthandableProperties = [ - "margin", - "padding", - "border-width", - "border-style", - "border-color", - "border-radius", + 'margin', + 'padding', + 'border-width', + 'border-style', + 'border-color', + 'border-radius', ] function condense (top, right, bottom, left) { diff --git a/lib/formatValues.js b/lib/formatValues.js index c23ace3..9d9eb43 100644 --- a/lib/formatValues.js +++ b/lib/formatValues.js @@ -68,11 +68,10 @@ function formatvalues (decl, stylelint) { decl.value = formatTransforms(decl.value) if (decl.important) { - decl.raws.important = " !important" + decl.raws.important = ' !important' } return decl } - module.exports = formatvalues diff --git a/lib/gradient.js b/lib/gradient.js new file mode 100644 index 0000000..87b0de2 --- /dev/null +++ b/lib/gradient.js @@ -0,0 +1,514 @@ +'use strict' + +var postcss = require('postcss') +var valueParser = require('postcss-value-parser') + +// 老式方向关键字转换 +var directionMap = { + 'top': 'bottom', + 'bottom': 'top', + 'left': 'right', + 'right': 'left', +} + +// 需要转换的旧关键字 +var keyWordMap = { + cover: 'farthest-corner', + contain: 'closest-side', +} + +// 各种角度单位与deg之间的换算关系 https://developer.mozilla.org/zh-CN/docs/Web/CSS/angle +var angleUnitMap = { + grad: 400, + rad: 2 * Math.PI, + turn: 1, +} + +// 各种长度单位与deg之间的换算关系 https://developer.mozilla.org/en-US/docs/Web/CSS/length +var lengthUnitMap = { + '%': 1, + 'in': 96, + ch: 6, + cm: 37.79527559055118, + em: 12, + ex: 5.4376, + mm: 3.7795275590551185, + pc: 16, + pt: 1.3333333333333333, + q: 0.9448818897637796, + rem: 16, + vh: 960, + vm: 640, + vmax: 960, + vmin: 640, + vw: 640, +} + +// 角度转为关键字 +var degMap = { + 0: 'top', + 90: 'right', + 180: 'bottom', + 270: 'left', +} + +/** + * 将字符串转为数字与其单位 + * @param {String} string 含有数字的字符串 + * @returns {Float} num 解析好的数字 + * @returns {Float} unit 原有的单位 + */ +function parseNum (string) { + var unit + var num = parseFloat(string.replace(/(\D+)$/, function (s) { + unit = s + return '' + })) + if (!isNaN(num)) { + return { + num: num, + unit: unit || '', + } + } +} + +/** + * 将字符串转为px为单位长度数值 + * @param {String} string 含有长度信息的字符串 + * @return {Float} 换算成像素的数值 + */ +function parseLength (string) { + var value = parseNum(string) + if (value) { + if (value.num === 0 || !value.unit || value.unit === 'px') { + // 没有长度单位,或数值为0,或长度单位为像素,则无需换算 + return value.num + } else if (lengthUnitMap[value.unit]) { + // 不同长度单位间的换算 + return value.num * lengthUnitMap[value.unit] + } + } +} + +/** + * 将字符串转为长度与其单位 + * @param {String} string 含有数字的字符串 + * @returns {Float} deg 换算成度的数字 + * @returns {Float} num 解析好的数字 + * @returns {Float} unit 原有的单位 + */ +function parseAngle (string) { + var value = parseNum(string) + if (value) { + if (value.num === 0 || !value.unit || value.unit === 'deg') { + // 没有角度单位,或数值为0,或角度单位为度,则无需换算 + value.deg = value.num + } else if (angleUnitMap[value.unit]) { + // 不同角度单位间的换算 + value.deg = value.num * 360 / angleUnitMap[value.unit] + } else { + return + } + // 修正为w3c语法的角度。0°为上方而非右方 + value.deg = require('normalize-range').wrap(0, 360, 90 - value.deg) + return value + } +} + +/** + * 将解析后的数字对象转换为字符串 + * @param {Object} angleObj 数字对象 + * @param {Object} angleObj.deg 以度为单位的角度 + * @param {Object} angleObj.unit 希望使用的单位 + * @return {String} 按格式输出的字符串 + */ +function angle2String (angleObj) { + var deg = angleObj.deg + if (angleObj.unit && angleObj.unit !== 'deg') { + // 单位不为度是,需要换算 + deg = (deg * angleUnitMap[angleObj.unit] / 360) + } + + // 修正浮点数精度 + deg = parseFloat(deg.toFixed(4)) + if (deg === 0) { + // 结果等于0时,直接转换为字符串输出,不要单位 + deg = '0' + } else { + // 结果不为0时,补上单位 + deg += angleObj.unit || 'deg' + } + return deg +} + +/** + * 分析css参数中的坐标信息 + * @param {String[]} args 包含坐标信息的两个字符串组成的数组 + * @returns {Int} x [x轴坐标] + * @returns {Int} y [y轴坐标] + */ +function normalizePos (args) { + var point = {} + args.forEach(function (arg, i) { + if (arg === 'top') { + point.y = 0 + } else if (arg === 'right') { + point.x = 100 + } else if (arg === 'bottom') { + point.y = 100 + } else if (arg === 'left') { + point.x = 0 + } else { + // 将长度单位转换为坐标 + point[i ? 'y' : 'x'] = parseLength(arg) + } + }) + return point +} + +/** + * 将长度字符串转换为以px为单位的字符串 + * @param {String} val 表示长度的css表达式字符串 + * @return {String} 以px为单位的数字字符串 + */ +function px (val) { + try { + val = parseFloat(parseLength(val).toFixed(4)) + if (val === 0) { + return '0' + } else { + return val + 'px' + } + } catch (ex) { + return val + } +} + +/** + * `-webkit-gradient(linear, `根据参数位置与尺寸,返回修正顺序与语法的这两个参数 + * @param {Array} args -webkit-gradient的参数,去除第一个参数type和所有color-stop + * @return {Array} `[ '90px', 'at', '0px', '150px' ]` + */ +function fixOldRadialGradient (args) { + var position = args[0] + if (position && position[0] && position[1]) { + // 第一个参数为坐标,则将这个参数中的值的单位转换为px + position = position.map(px) + // 在坐标参数最前面添加`at`关键字 + position.unshift('at') + + var size = args[3] && args[3][0] + if (size != null) { + // 将尺寸信息加入结果集 + position.unshift(px(size)) + } + // 返回结果 + return position + } +} + +/** + * `-webkit-gradient(linear, `根据传入的参数计算角度,返回角度参摄 + * @param {Array} args -webkit-gradient的参数,去除第一个参数type和所有color-stop + * @return {String|undefined} 角度值表达式,当角度正好180°时,返回undefined + */ +function fixOldLinearGradient (args) { + var angle + // 从args[0]中获取起始点信息 + var start = normalizePos(args[0]) + // 从args[1]中获取终止点信息 + var end = normalizePos(args[1]) + + + // 根据起始点和终止点计算角度 + angle = 180 - Math.atan2(end.x - start.x, end.y - start.y) * (180 / Math.PI) + // 将角度进行坐标系变换 + angle = require('normalize-range').wrap(0, 360, angle) + // 如果角度不等于180°,将其转换为字符串后返回 + if (angle !== 180) { + angle = angle2String({ + deg: angle, + }) + return angle + } +} + +/** + * `-webkit-gradient`转`radial-gradient`或`linear-gradient` + * @param {Array} args 修正前的参数 + * @param {Node} gradient 原始的node对象 + * @return {Array} 修正后的参数 + */ +function fixOldGradient (args, gradient) { + var type = args[0][0] + var colorStops = [] + var from + var to + + // 将参数中的`color-stop`,`from`,`to`三种信息剔除出args并单独存放,剩下的存起来 + args = args.slice(1).filter(function (arg) { + var fnName = arg.value + if (fnName === 'from') { + from = arg + } else if (fnName === 'to') { + to = arg + } else if (fnName === 'color-stop') { + colorStops.push(arg) + } else { + return true + } + return false + }) + + if (from) { + // 将from信息放入colorStops头部 + colorStops.unshift(from) + } + if (to) { + // 将from信息放入colorStops尾部 + colorStops.push(to) + } + + // 将数组colorStops中的元素都转换为标准形式 + colorStops = colorStops.map(function parseColorStop (colorStop, i) { + // 获取colorStop的参数 + colorStop = colorStop.nodes + // 如果不知一个参数 + if (colorStop.length > 1) { + // 计算位置信息的浏览器默认值 + var posVal = i * 100 / (colorStops.length - 1) + colorStop = colorStop.filter(function (val) { + // 如果位置信息与浏览器默认值相同,去除它 + return parseFloat(val) !== posVal + }) + + if (colorStop.length > 1) { + // 参数重新排列,位置信息放在后面,以便符合新语法 + colorStop.sort(function (word) { + return isNaN(parseFloat(word)) ? -1 : 1 + }) + } + } + return colorStop + }) + + if (type === 'radial') { + // 按照圆形渐变语法处理剩下的参数 + args = fixOldRadialGradient(args) + } else { + // 按照线性渐变语法处理剩下的参数 + args = fixOldLinearGradient(args) + } + + if (args && args.length) { + // 将`fixOldRadialGradient`或`fixOldLinearGradient`的返回结果插入colorStops + colorStops.unshift(args) + } + // 将css属性名名称转换为标准的 + gradient.value = type + '-gradient' + return colorStops +} + +/** + * 修正`linear-gradient`的参数 + * @param {Array} args linear-gradient的所有参数 + * @return {Array} 修正后的参数 + */ +function fixLinearGradient (args) { + var angle = parseAngle(args[0][0]) + + if (angle) { + // 如果第一参数是角度,修正角度 + var deg = Math.round(angle.deg) + if (deg === 180) { + // 180°正是浏览器默认值,所以抛弃,减少生成的css的体积 + args.shift() + } else { + if (degMap[deg]) { + // 如果角度是0、90、180、270等特殊值,将第一参变为方位信息 + args[0] = ['to', degMap[deg]] + } else { + // 其他角度值,直接转换第一参即可 + args[0] = angle2String(angle) + } + } + } else { + var position + // 遍历第一参中的值, + args[0].forEach(function (arg, i) { + if (directionMap[arg]) { + // 将top、left、bottom、right取反义词,并记录position + args[0][i] = directionMap[arg] + position = args[0] + } + }) + if (position) { + if (position.length === 1 && position[0] === 'bottom') { + // `to bottom`正是浏览器默认值,所以抛弃,减少生成的css的体积 + args.shift() + } else { + // 将方位信息最前面添加一个"to"二级参数 + position.unshift('to') + } + } + } + + return args +} + +/** + * 圆形渐变处理 + * @param {Array} args linear-gradient的所有参数 + * @return {Array} 修正后的参数 + */ +function fixRadialGradient (args) { + + var firstArg = [] + var position + + // 分析所有参数,将坐标参数和关键字剔除出args并单独保存 + args = args.filter(function (subArg) { + var hasKeyWord + subArg.forEach(function (word, i) { + if (keyWordMap[word]) { + // 查找需要转换的关键字 + subArg[i] = keyWordMap[word] + hasKeyWord = true + } else if (/^(?:circle|ellipse|\w+-\w+)$/.test(word)) { + // 查找是否有其他的关键字 + hasKeyWord = true + } + }) + if (hasKeyWord) { + // subArg中如果有关键字,将它存入firstArg + firstArg = firstArg.concat(subArg) + return false + } else if (subArg.every(function (word) { + return word === 'center' || directionMap[word] || parseNum(word) + })) { + // 如果subArg是坐标信息将它存入position + position = subArg + return false + } + return true + }) + + if (position) { + // 在坐标参数最前面添加`at`关键字 + position.unshift('at') + firstArg = firstArg.concat(position) + } + + if (firstArg.length) { + // 如果收集到了firstArg,将其加入args的最前面 + args.unshift(firstArg) + } + + return args +} + +/** + * `radial-gradient`或`linear-gradient`去前缀并转换语法 + * @param {Node} gradient `postcss-value-parser`插件转换后的-webkit-gradient + * @param {String} type `radial`或`linear` + * @return {Array} 修正后的参数 + */ +function fixGradient (gradient, type) { + if (type === 'radial') { + // 圆形渐变处理 + return fixRadialGradient(gradient) + } else { + // 线性渐变处理 + return fixLinearGradient(gradient) + } +} + +/** + * 将语法树中的function节点转换为便于处理的形式 + * 返回值二维数组 + * @param {Node} node 语法树节点,type必须为function + * @return {Array} 二维数组 + */ +function parseFunction (node) { + var args = [] + var index = 0 + node.nodes.forEach(function (subNode) { + if (subNode.type === 'div' && subNode.value === ',') { + // 遇到`,`下标自加1 + index++ + return + } else if (subNode.type === 'function') { + // 将参数中的`color-stop`,`from`,`to`三种function特殊处理 + if ((subNode.value === 'from' || subNode.value === 'to' || subNode.value === 'color-stop')) { + var colorStop = subNode.nodes.filter(function (colorStopInfo) { + // colorStop的子节点,除function和word外,都丢去 + return colorStopInfo.type === 'function' || colorStopInfo.type === 'word' + }).map(function (colorStopInfo) { + // colorStop的子节点,转换为字符串 + return valueParser.stringify(colorStopInfo) + }) + + // 组装新的对象传递出去 + colorStop = { + nodes: colorStop, + type: 'function', + value: subNode.value, + } + + // 不使用第三个数组维度,而是将其存在最上面的维度上 + return args[index] = colorStop + } + } else if (subNode.type !== 'word') { + return + } + + if (!args[index]) { + // 如果未初始化该数组维度,对其初始化 + args[index] = [] + } + // 未特殊处理的function,还有普通的word,将其转字符串 + args[index].push(valueParser.stringify(subNode)) + }) + // 返回转换后的数组 + return args +} + +// 将二维数组降维,并转换为字符串 +function stringifyArg (arg) { + if (Array.isArray(arg)) { + // 递归方式处理数组的更高维度 + return arg.map(stringifyArg).join(' ') + } else { + return String(arg) + } +} + +/** + * 将二维数组作为参数,重写type为function的语法树节点,type会变为word + * @param {Node} gradient 语法树节点 + * @param {Node} args 修正后的参数 + */ +function stringifyGradient (gradient, args) { + // 将参数还原成节点 + gradient.value = gradient.value + '(' + args.map(stringifyArg).join(', ') + ')' + gradient.type = 'word' + delete gradient.nodes +} + +module.exports = function (node) { + if (node.type === 'function') { + if (/^-\w+-gradient$/.test(node.value)) { + // 修复老式webkit语法的gradient + stringifyGradient(node, fixOldGradient(parseFunction(node), node)) + } else if (/^-\w+-(?:\w+-)?(\w+)-gradient$/.test(node.value)) { + var type = RegExp.$1 + // 修复gradient的前缀 + node.value = postcss.vendor.unprefixed(node.value) + // 修复gradient的值 + stringifyGradient(node, fixGradient(parseFunction(node), type)) + } else { + return + } + return node + } +} diff --git a/lib/unprefixer.js b/lib/unprefixer.js new file mode 100644 index 0000000..7e06257 --- /dev/null +++ b/lib/unprefixer.js @@ -0,0 +1,255 @@ +'use strict' + +const postcss = require('postcss') +const autoprefixer = require('autoprefixer') +const valueParser = require('postcss-value-parser') + +function valMap (reg, prop, valMap) { + return function (decl) { + if (reg.test(decl.prop)) { + var value = postcss.vendor.unprefixed(decl.value) + if(valMap[value]) { + return { + prop: prop, + value: valMap[value], + } + } + } + } +} + +function getBrotherDecl (decl, prop){ + var result + decl.parent.walkDecls(new RegExp('^(?:-\\w+-)?' + prop + '$'), function (decl){ + result = decl + }) + return result +} + +const declUnprefixers = [ + function alignItems (decl) { + if (/^(?:-\w+-)?(?:flex|box|flexbox)-align$/.test(decl.prop) ) { + return { + prop: 'align-items', + value: decl.value.replace(/^(?:-\w+-)?(start|end)$/, 'flex-$1') + } + } + }, + function breakInside (decl) { + if (/^(?:-\w+-)?(\w+)-break-(\w+)/.test(decl.prop)) { + return { + prop: 'break-' + RegExp.$2, + value: decl.value === 'avoid' ? RegExp.$1 + '-avoid' : decl.value, + } + } + }, + function display (decl) { + if (/^(?:-\w+-)?display$/.test(decl.prop) && /^(?:-\w+-)?(inline-)?(?:flex|box|flexbox)$/.test(decl.value)) { + return { + prop: 'display', + value: RegExp.$1 + 'flex' + } + } + }, + valMap(/^(?:-\w+-)?(?:flex|box|flexbox)-direction$/, 'flex-direction', { + 'lr': 'row', + 'rl': 'row-reverse', + 'tb': 'column', + 'bt': 'column-reverse' + }), + valMap(/^(?:-\w+-)?(?:flex|box|flexbox)-pack$/, 'justify-content', { + 'start': 'flex-start', + 'end': 'flex-end', + 'justify': 'space-between' + }), + function interpolationMode (decl) { + if (/^-ms-interpolation-mode$/.test(decl.prop) && /^nearest-neighbor$/.test(decl.value)) { + return { + prop: 'image-rendering', + value: 'pixelated', + } + } + }, + function flexFlow (decl) { + var flexFlow + if (/^(?:-\w+-)?(?:flex|box|flexbox)-(?:orient|direction)$/.test(decl.prop) && (flexFlow = getBrotherDecl(decl, 'flex-flow'))) { + return { + prop: flexFlow.prop, + value: flexFlow.value, + } + } + }, + function boxOrient (decl) { + if (/^(?:-\w+-)?(?:flex|box|flexbox)-orient$/.test(decl.prop)) { + var boxOrient = { + horizontal: 'row', + vertical: 'column', + }[decl.value.toLowerCase()] + + if(!boxOrient) { + return + } + var boxDirection = getBrotherDecl(decl, 'box-direction') + if (boxDirection && boxDirection.value === 'reverse') { + boxDirection = '-reverse' + } else { + boxDirection = '' + } + return { + prop: 'flex-direction', + value: boxOrient + boxDirection + } + } + }, + function boxDirection (decl) { + if (/^(?:-\w+-)?(?:flex|box|flexbox)-direction$/.test(decl.prop)) { + var boxDirection = decl.value.toLowerCase() + if (boxDirection === 'reverse') { + boxDirection = '-reverse' + } else if(boxDirection === 'normal') { + boxDirection = '' + } else { + return + } + + var boxOrient = getBrotherDecl(decl, 'box-orient') + if (boxOrient && boxOrient.value === 'vertical') { + boxOrient = 'column' + } else { + boxOrient = 'row' + } + + return { + prop: 'flex-direction', + value: boxOrient + boxDirection + } + } + }, +] + +const PREFIXED_PROP_NAME_MAP = { + '-ms-flex-positive': 'flex-grow', + '-ms-grid-column-align': 'grid-row-align', + '-ms-grid-column-span': 'grid-column', + '-ms-grid-columns': 'grid-template-columns', + '-ms-grid-row-span': 'grid-row-end', + '-ms-grid-rows': 'grid-template-rows', + '-ms-flex-item-align': 'align-self', + '-ms-flex-pack': 'justify-content', + '-ms-flex-line-pack': 'align-content', + '-ms-flex-preferred-size': 'flex-basis', + '-ms-flex-negative': 'flex-shrink' +} + +const PROP_NAME_MAP = { + 'border-radius-bottomleft': 'border-bottom-left-radius', + 'border-radius-bottomright': 'border-bottom-right-radius', + 'border-radius-topleft': 'border-top-left-radius', + 'border-radius-topright': 'border-top-right-radius', + + 'border-after': 'border-block-end', + 'border-before': 'border-block-start', + 'border-end': 'border-inline-end', + 'border-start': 'border-inline-start', + + 'margin-after': 'margin-block-end', + 'margin-before': 'margin-block-start', + 'margin-end': 'margin-inline-end', + 'margin-start': 'margin-inline-start', + + 'padding-after': 'padding-block-end', + 'padding-before': 'padding-block-start', + 'padding-end': 'padding-inline-end', + 'padding-start': 'padding-inline-start', + + 'mask-box-image': 'mask-border', + 'mask-box-image-outset': 'mask-border-outset', + 'mask-box-image-repeat': 'mask-border-repeat', + 'mask-box-image-slice': 'mask-border-slice', + 'mask-box-image-source': 'mask-border-source', + 'mask-box-image-width': 'mask-border-width', + + 'box-align': 'align-items', + 'box-pack': 'justify-content', + 'box-ordinal-group': 'order', + 'flex-order': 'order', + 'box-flex': 'flex', +} + +const valueUnprefixers = [ + function unprefixPropInValue (node) { + var prefixed = unprefixProp(node.value) + if(prefixed) { + node.value = prefixed + return prefixed + } + }, + function imageRendering (node, prop) { + if(/^(?:-\w+-)?image-rendering/.test(prop) && /^-\w+-/.test(node.value)) { + if(/^-\w+-optimize-contrast$/.test(node.value)) { + node.value = 'crisp-edges' + } else { + node.value = postcss.vendor.unprefixed(node.value) + } + return node + } + }, + require('./gradient'), +] + +function unprefixProp (prop) { + if(PREFIXED_PROP_NAME_MAP[prop]){ + return PREFIXED_PROP_NAME_MAP[prop] + } + prop = postcss.vendor.unprefixed(prop) + if(autoprefixer.data.prefixes[prop]) { + return prop + } + if(PROP_NAME_MAP[prop]){ + return PROP_NAME_MAP[prop] + } +} + +function unprefixValue (value, prop) { + var fixed + value = valueParser(value) + value.nodes.forEach(function (node) { + if(node.type !== 'div' && /^-\w+-/.test(node.value) && valueUnprefixers.some(function (unprefixer) { + return unprefixer(node, prop) + })) { + fixed = true + } + }) + if(fixed){ + return valueParser.stringify(value).replace(/(.+?)(\s*,\s*\1)+/g, '$1') + } +} + +function unprefixdecl (decl) { + var result + if (declUnprefixers.some(function (unprefixer) { + result = unprefixer(decl) + return result + })) { + return result + } + result = {} + result.prop = unprefixProp(decl.prop) + result.value = unprefixValue(decl.value, decl.prop) + return result +} + +function unprefix (decl) { + var result = unprefixdecl (decl) + result.replace = function (){ + if(result.prop) { + decl.prop = result.prop + } + if(result.value) { + decl.value = result.value + } + } + return result +} + +module.exports = unprefix diff --git a/lib/util.js b/lib/util.js index 489b504..04d60c1 100644 --- a/lib/util.js +++ b/lib/util.js @@ -55,11 +55,55 @@ function getOptions (stylelint, prop, option) { return stylelintProperty } +var propNameMap = { + 'border-radius-bottomleft': 'border-bottom-left-radius', + 'border-radius-bottomright': 'border-bottom-right-radius', + 'border-radius-topleft': 'border-top-left-radius', + 'border-radius-topright': 'border-top-right-radius', + 'border-after': 'border-block-end', + 'border-before': 'border-block-start', + 'border-end': 'border-inline-end', + 'border-start': 'border-inline-start', + + 'margin-after': 'margin-block-end', + 'margin-before': 'margin-block-start', + 'margin-end': 'margin-inline-end', + 'margin-start': 'margin-inline-start', + + 'padding-after': 'padding-block-end', + 'padding-before': 'padding-block-start', + 'padding-end': 'padding-inline-end', + 'padding-start': 'padding-inline-start', + + 'mask-box-image': 'mask-border', + 'mask-box-image-outset': 'mask-border-outset', + 'mask-box-image-repeat': 'mask-border-repeat', + 'mask-box-image-slice': 'mask-border-slice', + 'mask-box-image-source': 'mask-border-source', + 'mask-box-image-width': 'mask-border-width', + + 'box-align': 'align-items', + 'box-pack': 'justify-content', + 'box-ordinal-group': 'order', + 'flex-order': 'order', + 'box-flex': 'flex', +} + +function unprefixProp (prop) { + prop = prop.replace(/^-\w+-/, '') + return propNameMap[prop] || prop +} + +function unprefixDecl () { + +} module.exports = { inAtRule: inAtRule, getNestedRulesNum: getNestedRulesNum, isEmptyObject: isEmptyObject, getProperty: getProperty, - getOptions: getOptions + getOptions: getOptions, + unprefixProp: unprefixProp, + unprefixDecl: unprefixDecl, } diff --git a/package.json b/package.json index 3515e5f..0dc4007 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,28 @@ "main": "index.js", "scripts": { "test": "tape test/*.js | faucet && npm run lint", + "test-cov": "nyc npm test", "lint": "eslint -c .eslintrc.json index.js lib bin" }, + "nyc": { + "lines": 97, + "statements": 97, + "functions": 98, + "branches": 96, + "include": [ + "lib/**/*.js" + ], + "exclude": [ + "dist/**/*.spec.js" + ], + "reporter": [ + "lcov", + "text" + ], + "cache": true, + "all": true, + "check-coverage": true + }, "bin": { "stylefmt": "bin/cli.js" }, @@ -49,6 +69,7 @@ "eslint": "^3.11.1", "faucet": "0.0.1", "klaw": "^1.3.1", + "nyc": "^10.2.0", "tape": "^4.6.2" } } diff --git a/test/stylelint/no-vendor-prefix/.stylelintrc b/test/stylelint/no-vendor-prefix/.stylelintrc new file mode 100644 index 0000000..3c0a393 --- /dev/null +++ b/test/stylelint/no-vendor-prefix/.stylelintrc @@ -0,0 +1,6 @@ +{ + "rules": { + "property-no-vendor-prefix": true, + "value-no-vendor-prefix": true + } +} diff --git a/test/stylelint/no-vendor-prefix/no-vendor-prefix.css b/test/stylelint/no-vendor-prefix/no-vendor-prefix.css new file mode 100644 index 0000000..8fdcb77 --- /dev/null +++ b/test/stylelint/no-vendor-prefix/no-vendor-prefix.css @@ -0,0 +1,275 @@ +a { + -js-display: flex; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-flow: row; + -moz-box-orient: horizontal; + -moz-box-direction: normal; + -ms-flex-flow: row; + flex-flow: row; + -webkit-box-ordinal-group: 1; + -webkit-order: 0; + -moz-box-ordinal-group: 1; + -ms-flex-order: 0; + order: 0; + -webkit-box-flex: 0; + -webkit-flex: 0 1 2; + -moz-box-flex: 0; + -ms-flex: 0 1 2; + flex: 0 1 2; + -webkit-transition: -webkit-box-flex 200ms, -webkit-flex 200ms; + transition: -webkit-box-flex 200ms, -webkit-flex 200ms; + transition: flex 200ms; + transition: flex 200ms, -webkit-box-flex 200ms, -webkit-flex 200ms, -moz-box-flex 200ms, -ms-flex 200ms; +} + +.inline { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -moz-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-align-self: auto; + -ms-flex-item-align: auto; + align-self: auto; + -webkit-align-content: stretch; + -ms-flex-line-pack: stretch; + align-content: stretch; + -webkit-box-flex: 1; + -webkit-flex: auto; + -moz-box-flex: 1; + -ms-flex: auto; + flex: auto; +} + +.inline-box { + display: -webkit-inline-box; +} + +.inline-flex { + display: -webkit-inline-flex; +} + +.inline-flexbox { + display: -ms-inline-flexbox; +} + +.a { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -moz-box-orient: horizontal; + -moz-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -moz-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + -webkit-box-align: start; + -webkit-align-items: flex-start; + -moz-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-align-content: flex-start; + -ms-flex-line-pack: start; + align-content: flex-start; + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; + -webkit-box-flex: 0; + -webkit-flex: none; + -moz-box-flex: 0; + -ms-flex: none; + flex: none; +} + +.display_flex { + display: -webkit-flex; +} + +.display_box { + display: -moz-box; +} + +.display_flexbox { + display: -ms-flexbox; +} + +.b { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: reverse; + -webkit-flex-direction: row-reverse; + -moz-box-orient: horizontal; + -moz-box-direction: reverse; + -ms-flex-direction: row-reverse; + flex-direction: row-reverse; + -webkit-box-pack: end; + -webkit-justify-content: flex-end; + -moz-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + -webkit-box-align: end; + -webkit-align-items: flex-end; + -moz-box-align: end; + -ms-flex-align: end; + align-items: flex-end; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-align-content: flex-end; + -ms-flex-line-pack: end; + align-content: flex-end; + -webkit-align-self: flex-end; + -ms-flex-item-align: end; + align-self: flex-end; + -webkit-flex-shrink: 1; + -ms-flex-negative: 1; + flex-shrink: 1; +} + +.c { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -moz-box-orient: vertical; + -moz-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -webkit-justify-content: center; + -moz-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -webkit-align-items: center; + -moz-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: reverse-wrap; + -ms-flex-wrap: reverse-wrap; + flex-wrap: reverse-wrap; + -webkit-align-content: center; + -ms-flex-line-pack: center; + align-content: center; + -webkit-align-self: center; + -ms-flex-item-align: center; + align-self: center; + -webkit-flex-basis: auto; + -ms-flex-preferred-size: auto; + flex-basis: auto; +} + +.e { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: reverse; + -webkit-flex-direction: column-reverse; + -moz-box-orient: vertical; + -moz-box-direction: reverse; + -ms-flex-direction: column-reverse; + flex-direction: column-reverse; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -moz-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: baseline; + -webkit-align-items: baseline; + -moz-box-align: baseline; + -ms-flex-align: baseline; + align-items: baseline; + -webkit-align-content: space-between; + -ms-flex-line-pack: justify; + align-content: space-between; + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; +} + +.f { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-justify-content: space-around; + -ms-flex-pack: distribute; + justify-content: space-around; + -webkit-box-align: stretch; + -webkit-align-items: stretch; + -moz-box-align: stretch; + -ms-flex-align: stretch; + align-items: stretch; + -webkit-align-content: space-around; + -ms-flex-line-pack: distribute; + align-content: space-around; + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; + align-self: stretch; +} + +.g { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: -webkit-calc(1em + 1px); + -webkit-flex: -webkit-calc(1em + 1px) 0 0; + -moz-box-flex: calc(1em + 1px); + -ms-flex: calc(1em + 1px) 0 0px; + flex: calc(1em + 1px) 0 0; +} + +.h { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-flow: column wrap; + -moz-box-orient: vertical; + -moz-box-direction: normal; + -ms-flex-flow: column wrap; + flex-flow: column wrap; +} + +.i { + -webkit-flex-flow: nowrap; + -ms-flex-flow: nowrap; + flex-flow: nowrap; +} + +.inherit { + -webkit-box-ordinal-group: inherit; + -webkit-order: inherit; + -moz-box-ordinal-group: inherit; + -ms-flex-order: inherit; + order: inherit; +} diff --git a/test/stylelint/no-vendor-prefix/no-vendor-prefix.out.css b/test/stylelint/no-vendor-prefix/no-vendor-prefix.out.css new file mode 100644 index 0000000..b9bcb88 --- /dev/null +++ b/test/stylelint/no-vendor-prefix/no-vendor-prefix.out.css @@ -0,0 +1,105 @@ +a { + display: flex; + flex-flow: row; + order: 0; + flex: 0 1 2; + transition: flex 200ms; +} + +.inline { + display: inline-flex; + align-self: auto; + align-content: stretch; + flex: auto; +} + +.inline-box { + display: inline-flex; +} + +.inline-flex { + display: inline-flex; +} + +.inline-flexbox { + display: inline-flex; +} + +.a { + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: flex-start; + flex-wrap: nowrap; + align-content: flex-start; + align-self: flex-start; + flex: none; +} + +.display_flex { + display: flex; +} + +.display_box { + display: flex; +} + +.display_flexbox { + display: flex; +} + +.b { + display: flex; + flex-direction: row-reverse; + justify-content: flex-end; + align-items: flex-end; + flex-wrap: wrap; + align-content: flex-end; + align-self: flex-end; + flex-shrink: 1; +} + +.c { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + flex-wrap: reverse-wrap; + align-content: center; + align-self: center; + flex-basis: auto; +} + +.e { + display: flex; + flex-direction: column-reverse; + justify-content: space-between; + align-items: baseline; + align-content: space-between; + align-self: baseline; +} + +.f { + display: flex; + justify-content: space-around; + align-items: stretch; + align-content: space-around; + align-self: stretch; +} + +.g { + display: flex; + flex: calc(1em + 1px) 0 0; +} + +.h { + flex-flow: column wrap; +} + +.i { + flex-flow: nowrap; +} + +.inherit { + order: inherit; +} diff --git a/test/stylelint/property-no-vendor-prefix/.stylelintrc b/test/stylelint/property-no-vendor-prefix/.stylelintrc new file mode 100644 index 0000000..15b926f --- /dev/null +++ b/test/stylelint/property-no-vendor-prefix/.stylelintrc @@ -0,0 +1,5 @@ +{ + "rules": { + "property-no-vendor-prefix": true + } +} diff --git a/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.css b/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.css new file mode 100644 index 0000000..e7730e8 --- /dev/null +++ b/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.css @@ -0,0 +1,315 @@ +.class { + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +h1 { + font: bold 20px/1.5 georgia, simsun, sans-serif; +} + +.box { + display: -webkit-box; + display: -moz-box; + display: -ms-box; + width: 600px; + height: 180px; + margin: 0; + padding: 0; + list-style: none; +} + +a { + -js-display: flex; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-flow: row; + -moz-box-orient: horizontal; + -moz-box-direction: normal; + -ms-flex-flow: row; + flex-flow: row; + -webkit-box-ordinal-group: 1; + -webkit-order: 0; + -moz-box-ordinal-group: 1; + -ms-flex-order: 0; + order: 0; + -webkit-box-flex: 0; + -webkit-flex: 0 1 2; + -moz-box-flex: 0; + -ms-flex: 0 1 2; + flex: 0 1 2; + -webkit-transition: -webkit-box-flex 200ms, -webkit-flex 200ms; + transition: -webkit-box-flex 200ms, -webkit-flex 200ms; + transition: flex 200ms; + transition: flex 200ms, -webkit-box-flex 200ms, -webkit-flex 200ms, -moz-box-flex 200ms, -ms-flex 200ms; +} +.inline { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -moz-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-align-self: auto; + -ms-flex-item-align: auto; + align-self: auto; + -webkit-align-content: stretch; + -ms-flex-line-pack: stretch; + align-content: stretch; + -webkit-box-flex: 1; + -webkit-flex: auto; + -moz-box-flex: 1; + -ms-flex: auto; + flex: auto; +} + +.a { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -moz-box-orient: horizontal; + -moz-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -moz-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + -webkit-box-align: start; + -webkit-align-items: flex-start; + -moz-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-align-content: flex-start; + -ms-flex-line-pack: start; + align-content: flex-start; + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; + -webkit-box-flex: 0; + -webkit-flex: none; + -moz-box-flex: 0; + -ms-flex: none; + flex: none; +} +.b { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: reverse; + -webkit-flex-direction: row-reverse; + -moz-box-orient: horizontal; + -moz-box-direction: reverse; + -ms-flex-direction: row-reverse; + flex-direction: row-reverse; + -webkit-box-pack: end; + -webkit-justify-content: flex-end; + -moz-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + -webkit-box-align: end; + -webkit-align-items: flex-end; + -moz-box-align: end; + -ms-flex-align: end; + align-items: flex-end; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-align-content: flex-end; + -ms-flex-line-pack: end; + align-content: flex-end; + -webkit-align-self: flex-end; + -ms-flex-item-align: end; + align-self: flex-end; + -webkit-flex-shrink: 1; + -ms-flex-negative: 1; + flex-shrink: 1; +} +.c { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -moz-box-orient: vertical; + -moz-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -webkit-justify-content: center; + -moz-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -webkit-align-items: center; + -moz-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: reverse-wrap; + -ms-flex-wrap: reverse-wrap; + flex-wrap: reverse-wrap; + -webkit-align-content: center; + -ms-flex-line-pack: center; + align-content: center; + -webkit-align-self: center; + -ms-flex-item-align: center; + align-self: center; + -webkit-flex-basis: auto; + -ms-flex-preferred-size: auto; + flex-basis: auto; +} +.e { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: reverse; + -webkit-flex-direction: column-reverse; + -moz-box-orient: vertical; + -moz-box-direction: reverse; + -ms-flex-direction: column-reverse; + flex-direction: column-reverse; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -moz-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: baseline; + -webkit-align-items: baseline; + -moz-box-align: baseline; + -ms-flex-align: baseline; + align-items: baseline; + -webkit-align-content: space-between; + -ms-flex-line-pack: justify; + align-content: space-between; + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; +} +.f { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-justify-content: space-around; + -ms-flex-pack: distribute; + justify-content: space-around; + -webkit-box-align: stretch; + -webkit-align-items: stretch; + -moz-box-align: stretch; + -ms-flex-align: stretch; + align-items: stretch; + -webkit-align-content: space-around; + -ms-flex-line-pack: distribute; + align-content: space-around; + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; + align-self: stretch; +} +.g { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: -webkit-calc(1em + 1px); + -webkit-flex: -webkit-calc(1em + 1px) 0 0; + -moz-box-flex: calc(1em + 1px); + -ms-flex: calc(1em + 1px) 0 0px; + flex: calc(1em + 1px) 0 0; +} +.h { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-flow: column wrap; + -moz-box-orient: vertical; + -moz-box-direction: normal; + -ms-flex-flow: column wrap; + flex-flow: column wrap; +} +.i { + -webkit-flex-flow: nowrap; + -ms-flex-flow: nowrap; + flex-flow: nowrap; +} +.inherit { + -webkit-box-ordinal-group: inherit; + -webkit-order: inherit; + -moz-box-ordinal-group: inherit; + -ms-flex-order: inherit; + order: inherit; +} + +.a { + -webkit-column-break-inside: auto; + page-break-inside: auto; + break-inside: auto; + -webkit-column-break-before: auto; + page-break-before: auto; + break-before: auto; + -webkit-column-break-after: auto; + page-break-after: auto; + break-after: auto; +} + +.b { + -webkit-column-break-inside: avoid; + page-break-inside: avoid; + break-inside: avoid; +} + +.c { + -webkit-column-break-inside: avoid; + page-break-inside: avoid; + break-inside: avoid-column; +} + +.d { + page-break-inside: avoid; + break-inside: avoid-page; +} + +.e { + break-inside: avoid-region; +} + +img { + image-rendering: crisp-edges; +} + +img.other { + -ms-interpolation-mode: nearest-neighbor; + image-rendering: -webkit-optimize-contrast; + image-rendering: -moz-crisp-edges; + image-rendering: pixelated; +} + +img.already { + -ms-interpolation-mode: nearest-neighbor; + display: block; + image-rendering: crisp-edges; + image-rendering: -webkit-optimize-contrast; + image-rendering: -moz-crisp-edges; + image-rendering: pixelated; +} diff --git a/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css b/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css new file mode 100644 index 0000000..53e411a --- /dev/null +++ b/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css @@ -0,0 +1,170 @@ +.class { + box-sizing: border-box; +} + +h1 { + font: bold 20px/1.5 georgia, simsun, sans-serif; +} + +.box { + display: -webkit-box; + display: -moz-box; + display: -ms-box; + width: 600px; + height: 180px; + margin: 0; + padding: 0; + list-style: none; +} + +a { + display: flex; + flex-flow: row; + order: 0; + flex: 0 1 2; + transition: flex 200ms; +} + +.inline { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -moz-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + align-self: auto; + align-content: stretch; + flex: auto; +} + +.a { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: flex-start; + flex-wrap: nowrap; + align-content: flex-start; + align-self: flex-start; + flex: none; +} + +.b { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + flex-direction: row-reverse; + justify-content: flex-end; + align-items: flex-end; + flex-wrap: wrap; + align-content: flex-end; + align-self: flex-end; + flex-shrink: 1; +} + +.c { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + flex-wrap: reverse-wrap; + align-content: center; + align-self: center; + flex-basis: auto; +} + +.e { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + flex-direction: column-reverse; + justify-content: space-between; + align-items: baseline; + align-content: space-between; + align-self: baseline; +} + +.f { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + justify-content: space-around; + align-items: stretch; + align-content: space-around; + align-self: stretch; +} + +.g { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + flex: calc(1em + 1px) 0 0; +} + +.h { + flex-flow: column wrap; +} + +.i { + flex-flow: nowrap; +} + +.inherit { + order: inherit; +} + +.a { + page-break-inside: auto; + break-inside: auto; + page-break-before: auto; + break-before: auto; + page-break-after: auto; + break-after: auto; +} + +.b { + page-break-inside: avoid; + break-inside: avoid; +} + +.c { + page-break-inside: avoid; + break-inside: avoid-column; +} + +.d { + page-break-inside: avoid; + break-inside: avoid-page; +} + +.e { + break-inside: avoid-region; +} + +img { + image-rendering: crisp-edges; +} + +img.other { + image-rendering: pixelated; +} + +img.already { + display: block; + image-rendering: crisp-edges; + image-rendering: pixelated; +} diff --git a/test/stylelint/value-no-vendor-prefix/.stylelintrc b/test/stylelint/value-no-vendor-prefix/.stylelintrc new file mode 100644 index 0000000..b4d808c --- /dev/null +++ b/test/stylelint/value-no-vendor-prefix/.stylelintrc @@ -0,0 +1,5 @@ +{ + "rules": { + "value-no-vendor-prefix": true + } +} diff --git a/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.css b/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.css new file mode 100644 index 0000000..01b8233 --- /dev/null +++ b/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.css @@ -0,0 +1,146 @@ +a { + -js-display: flex; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + -webkit-flex-flow: row; + -ms-flex-flow: row; + -webkit-box-ordinal-group: 1; + -webkit-order: 0; + -moz-box-ordinal-group: 1; + -ms-flex-order: 0; + -moz-box-flex: 0; + -ms-flex: 0 1 2; + -webkit-transition: -webkit-box-flex 200ms, -webkit-flex 200ms; +} + +.inline { + -webkit-align-self: auto; + -ms-flex-item-align: auto; + -webkit-align-content: stretch; + -ms-flex-line-pack: stretch; + -moz-box-flex: 1; + -ms-flex: auto; +} + +.a { + -webkit-flex-direction: row; + -moz-box-orient: horizontal; + -moz-box-direction: normal; + -ms-flex-direction: row; + -webkit-justify-content: flex-start; + -moz-box-pack: start; + -ms-flex-pack: start; + -webkit-align-items: flex-start; + -moz-box-align: start; + -ms-flex-align: start; + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + -webkit-align-content: flex-start; + -ms-flex-line-pack: start; + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + -moz-box-flex: 0; + -ms-flex: none; +} + +.b { + -webkit-flex-direction: row-reverse; + -moz-box-orient: horizontal; + -moz-box-direction: reverse; + -ms-flex-direction: row-reverse; + -webkit-justify-content: flex-end; + -moz-box-pack: end; + -ms-flex-pack: end; + -webkit-align-items: flex-end; + -moz-box-align: end; + -ms-flex-align: end; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + -webkit-align-content: flex-end; + -ms-flex-line-pack: end; + -webkit-align-self: flex-end; + -ms-flex-item-align: end; + -webkit-flex-shrink: 1; + -ms-flex-negative: 1; +} + +.c { + -webkit-flex-direction: column; + -moz-box-orient: vertical; + -moz-box-direction: normal; + -ms-flex-direction: column; + -webkit-box-pack: center; + -webkit-justify-content: center; + -moz-box-pack: center; + -ms-flex-pack: center; + -webkit-box-align: center; + -webkit-align-items: center; + -moz-box-align: center; + -ms-flex-align: center; + -webkit-flex-wrap: reverse-wrap; + -ms-flex-wrap: reverse-wrap; + -webkit-align-content: center; + -ms-flex-line-pack: center; + -webkit-align-self: center; + -ms-flex-item-align: center; + -webkit-flex-basis: auto; + -ms-flex-preferred-size: auto; +} + +.e { + -webkit-flex-direction: column-reverse; + -moz-box-orient: vertical; + -moz-box-direction: reverse; + -ms-flex-direction: column-reverse; + -webkit-justify-content: space-between; + -moz-box-pack: justify; + -ms-flex-pack: justify; + -webkit-box-align: baseline; + -webkit-align-items: baseline; + -moz-box-align: baseline; + -ms-flex-align: baseline; + -webkit-align-content: space-between; + -ms-flex-line-pack: justify; + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; +} + +.f { + -webkit-justify-content: space-around; + -ms-flex-pack: distribute; + -webkit-box-align: stretch; + -webkit-align-items: stretch; + -moz-box-align: stretch; + -ms-flex-align: stretch; + -webkit-align-content: space-around; + -ms-flex-line-pack: distribute; + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; +} + +.g { + -moz-box-flex: calc(1em + 1px); + -ms-flex: calc(1em + 1px) 0 0; +} + +img { + image-rendering: crisp-edges; +} + +img.other { + -ms-interpolation-mode: nearest-neighbor; + image-rendering: -webkit-optimize-contrast; + image-rendering: -moz-crisp-edges; + image-rendering: pixelated; +} + +img.already { + -ms-interpolation-mode: nearest-neighbor; + display: block; + image-rendering: crisp-edges; + image-rendering: -webkit-optimize-contrast; + image-rendering: -moz-crisp-edges; + image-rendering: pixelated; +} diff --git a/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css b/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css new file mode 100644 index 0000000..e314a69 --- /dev/null +++ b/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css @@ -0,0 +1,138 @@ +a { + display: flex; + -webkit-flex-flow: row; + -ms-flex-flow: row; + -webkit-box-ordinal-group: 1; + -webkit-order: 0; + -moz-box-ordinal-group: 1; + -ms-flex-order: 0; + -moz-box-flex: 0; + -ms-flex: 0 1 2; + transition: flex 200ms; +} + +.inline { + -webkit-align-self: auto; + -ms-flex-item-align: auto; + -webkit-align-content: stretch; + -ms-flex-line-pack: stretch; + -moz-box-flex: 1; + -ms-flex: auto; +} + +.a { + -webkit-flex-direction: row; + -moz-box-orient: horizontal; + -moz-box-direction: normal; + -ms-flex-direction: row; + -webkit-justify-content: flex-start; + -moz-box-pack: start; + -ms-flex-pack: start; + -webkit-align-items: flex-start; + -moz-box-align: start; + -ms-flex-align: start; + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + -webkit-align-content: flex-start; + -ms-flex-line-pack: start; + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + -moz-box-flex: 0; + -ms-flex: none; +} + +.b { + -webkit-flex-direction: row-reverse; + -moz-box-orient: horizontal; + -moz-box-direction: reverse; + -ms-flex-direction: row-reverse; + -webkit-justify-content: flex-end; + -moz-box-pack: end; + -ms-flex-pack: end; + -webkit-align-items: flex-end; + -moz-box-align: end; + -ms-flex-align: end; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + -webkit-align-content: flex-end; + -ms-flex-line-pack: end; + -webkit-align-self: flex-end; + -ms-flex-item-align: end; + -webkit-flex-shrink: 1; + -ms-flex-negative: 1; +} + +.c { + -webkit-flex-direction: column; + -moz-box-orient: vertical; + -moz-box-direction: normal; + -ms-flex-direction: column; + -webkit-box-pack: center; + -webkit-justify-content: center; + -moz-box-pack: center; + -ms-flex-pack: center; + -webkit-box-align: center; + -webkit-align-items: center; + -moz-box-align: center; + -ms-flex-align: center; + -webkit-flex-wrap: reverse-wrap; + -ms-flex-wrap: reverse-wrap; + -webkit-align-content: center; + -ms-flex-line-pack: center; + -webkit-align-self: center; + -ms-flex-item-align: center; + -webkit-flex-basis: auto; + -ms-flex-preferred-size: auto; +} + +.e { + -webkit-flex-direction: column-reverse; + -moz-box-orient: vertical; + -moz-box-direction: reverse; + -ms-flex-direction: column-reverse; + -webkit-justify-content: space-between; + -moz-box-pack: justify; + -ms-flex-pack: justify; + -webkit-box-align: baseline; + -webkit-align-items: baseline; + -moz-box-align: baseline; + -ms-flex-align: baseline; + -webkit-align-content: space-between; + -ms-flex-line-pack: justify; + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; +} + +.f { + -webkit-justify-content: space-around; + -ms-flex-pack: distribute; + -webkit-box-align: stretch; + -webkit-align-items: stretch; + -moz-box-align: stretch; + -ms-flex-align: stretch; + -webkit-align-content: space-around; + -ms-flex-line-pack: distribute; + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; +} + +.g { + -moz-box-flex: calc(1em + 1px); + -ms-flex: calc(1em + 1px) 0 0; +} + +img { + image-rendering: crisp-edges; +} + +img.other { + -ms-interpolation-mode: nearest-neighbor; + image-rendering: pixelated; +} + +img.already { + -ms-interpolation-mode: nearest-neighbor; + display: block; + image-rendering: crisp-edges; + image-rendering: pixelated; +} From b15308b7a5d52a03b4bd7ba6c0d5e3fda001e5b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=A5=BA?= Date: Tue, 25 Apr 2017 19:29:30 +0800 Subject: [PATCH 2/7] update travis-ci config --- .travis.yml | 3 ++- package.json | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8ebbf33..439f0d9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,9 @@ sudo: false language: node_js node_js: + - "stable" - "4" - "6" script: - npm run lint - - npm test-cov + - npm test diff --git a/package.json b/package.json index 0dc4007..0528570 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,7 @@ "description": "stylefmt is a tool that automatically formats CSS according to stylelint rules", "main": "index.js", "scripts": { - "test": "tape test/*.js | faucet && npm run lint", - "test-cov": "nyc npm test", + "test": "nyc tape test/*.js | faucet && npm run lint", "lint": "eslint -c .eslintrc.json index.js lib bin" }, "nyc": { From 6bbb00a536e45a718fd2d0c91bbc5d71068f52d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=A5=BA?= Date: Wed, 26 Apr 2017 09:59:28 +0800 Subject: [PATCH 3/7] fix ci error --- lib/formatDecls.js | 10 +++++++--- package.json | 1 + .../property-no-vendor-prefix.out.css | 10 ++++++++++ .../value-no-vendor-prefix.out.css | 1 + 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/formatDecls.js b/lib/formatDecls.js index 7315048..fd50ec3 100644 --- a/lib/formatDecls.js +++ b/lib/formatDecls.js @@ -11,6 +11,8 @@ var isSingleLineString = require('stylelint/lib/utils/isSingleLineString') var postcss = require('postcss') function formatDecls (rule, indent, indentWidth, stylelint) { + var propNoVendorPrefix + var valueNoVendorPrefix function clearPrefixedDecl (decl) { var prop = postcss.vendor.unprefixed(decl.prop) var prefixedDecls = [] @@ -36,13 +38,15 @@ function formatDecls (rule, indent, indentWidth, stylelint) { } prefixedDecls.forEach(function (decl) { - decl.remove() + if((propNoVendorPrefix && valueNoVendorPrefix) || (propNoVendorPrefix && decl.prop[0] === '-') || (valueNoVendorPrefix && /(^|,|\s)-\w+-.+/.test(decl.value))){ + decl.remove() + } }) } const isSingleLine = isSingleLineString(rule) if (hasDecls(rule)) { - var propNoVendorPrefix = getProperty(stylelint, 'property-no-vendor-prefix') - var valueNoVendorPrefix = getProperty(stylelint, 'value-no-vendor-prefix') + propNoVendorPrefix = getProperty(stylelint, 'property-no-vendor-prefix') + valueNoVendorPrefix = getProperty(stylelint, 'value-no-vendor-prefix') rule.walkDecls(function (decl) { if ((propNoVendorPrefix && /^-\w+-(.+)$/.test(decl.prop)) || (valueNoVendorPrefix && /(^|,|\s)-\w+-.+/.test(decl.value))) { clearPrefixedDecl(decl) diff --git a/package.json b/package.json index 0528570..e9b2db1 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "author": "Masaaki Morishita", "license": "MIT", "dependencies": { + "autoprefixer": "^6.7.7", "chalk": "^1.1.3", "css-color-list": "0.0.1", "diff": "^3.1.0", diff --git a/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css b/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css index 53e411a..fb8818d 100644 --- a/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css +++ b/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css @@ -18,11 +18,17 @@ h1 { } a { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; display: flex; flex-flow: row; order: 0; flex: 0 1 2; + transition: -webkit-box-flex 200ms, -webkit-flex 200ms; transition: flex 200ms; + transition: flex 200ms, -webkit-box-flex 200ms, -webkit-flex 200ms, -moz-box-flex 200ms, -ms-flex 200ms; } .inline { @@ -160,11 +166,15 @@ img { } img.other { + image-rendering: -webkit-optimize-contrast; + image-rendering: -moz-crisp-edges; image-rendering: pixelated; } img.already { display: block; image-rendering: crisp-edges; + image-rendering: -webkit-optimize-contrast; + image-rendering: -moz-crisp-edges; image-rendering: pixelated; } diff --git a/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css b/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css index e314a69..0750508 100644 --- a/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css +++ b/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css @@ -1,4 +1,5 @@ a { + -js-display: flex; display: flex; -webkit-flex-flow: row; -ms-flex-flow: row; From 7eb6baaf690dc5c29cf4952d76eac50feb00a853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=A5=BA?= Date: Mon, 15 May 2017 13:17:59 +0800 Subject: [PATCH 4/7] save --- .eslintrc.json | 42 +- bin/cli.js | 8 +- index.js | 2 +- lib/formatDecls.js | 6 +- lib/gradient.js | 3 +- lib/params.js | 2 +- lib/unprefixer.js | 137 ++-- lib/util.js | 47 +- package.json | 16 +- .../no-vendor-prefix/no-vendor-prefix.css | 609 +++++++++++------- .../no-vendor-prefix/no-vendor-prefix.out.css | 112 ++++ .../property-no-vendor-prefix.css | 569 +++++++++------- .../property-no-vendor-prefix.out.css | 56 ++ .../value-no-vendor-prefix.css | 267 ++++---- .../value-no-vendor-prefix.out.css | 191 +++--- 15 files changed, 1233 insertions(+), 834 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index c492bab..5faed24 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,21 +1,47 @@ { - "extends": "eslint:recommended", "env": { - "node": true, - "es6": true + "es6": true, + "node": true }, + "extends": "eslint:recommended", "rules": { + "block-spacing": [ + "error", + "always" + ], "comma-spacing": [ "error" ], - "no-console": 0, + "eqeqeq": [ + "error", + "smart" + ], + "keyword-spacing": [ + "error" + ], + "no-console": [ + "error", + { + "allow": [ + "warn", + "error" + ] + } + ], "quotes": [ "error", "single" ], - "space-before-function-paren": [2, "always"], - "semi": [2, "never"], - "eqeqeq": [2, "allow-null"], - "block-spacing": [2, "always"] + "semi": [ + "error", + "never" + ], + "space-before-function-paren": [ + "error", + "always" + ], + "valid-jsdoc": [ + "error" + ] } } diff --git a/bin/cli.js b/bin/cli.js index c47fd29..81a0dfe 100644 --- a/bin/cli.js +++ b/bin/cli.js @@ -1,5 +1,5 @@ #!/usr/bin/env node - +/* eslint no-console: "off" */ var fs = require('fs') var path = require('path') var stdin = require('stdin') @@ -109,7 +109,7 @@ if (argv.r) { function processMultipleFiles (files) { files = files.filter(isCss).sort() - if(!files.length){ + if (!files.length){ console.error('Files glob patterns specified did not match any css files.') return } @@ -144,7 +144,7 @@ function processMultipleFiles (files) { messages = messages.filter(function (file){ return file }) - if(messages.length){ + if (messages.length){ messages = messages.join(', ') + '\n\n' + messages.length } else { messages = 'No' @@ -170,7 +170,7 @@ function handleDiff (file, original, formatted) { if (chalk.supportsColor) { file = chalk.blue(file) - if(diff) { + if (diff) { diff = chalk.gray(diff) } else { var JsDiff = require('diff') diff --git a/index.js b/index.js index 2852657..2f38d8e 100644 --- a/index.js +++ b/index.js @@ -12,7 +12,7 @@ const stylefmt = postcss.plugin('stylefmt', function (options) { var paramer = params(options) return function (root, result) { return paramer(root, result).then(function (params) { - if(params) { + if (params) { formatComments(root, params) formatAtRules(root, params) formatRules(root, params) diff --git a/lib/formatDecls.js b/lib/formatDecls.js index fd50ec3..a103857 100644 --- a/lib/formatDecls.js +++ b/lib/formatDecls.js @@ -25,7 +25,7 @@ function formatDecls (rule, indent, indentWidth, stylelint) { rule.walkDecls(unprefixer(decl).prop || prop, function (decl) { lastUnprefixed = unprefixer(decl) - if(lastUnprefixed.value) { + if (lastUnprefixed.value) { prefixedDecls.push(decl) } else { unprefixed = decl @@ -38,7 +38,7 @@ function formatDecls (rule, indent, indentWidth, stylelint) { } prefixedDecls.forEach(function (decl) { - if((propNoVendorPrefix && valueNoVendorPrefix) || (propNoVendorPrefix && decl.prop[0] === '-') || (valueNoVendorPrefix && /(^|,|\s)-\w+-.+/.test(decl.value))){ + if ((propNoVendorPrefix && valueNoVendorPrefix) || (propNoVendorPrefix && decl.prop[0] === '-') || (valueNoVendorPrefix && /(^|,|\s)-\w+-.+/.test(decl.value))){ decl.remove() } }) @@ -50,7 +50,7 @@ function formatDecls (rule, indent, indentWidth, stylelint) { rule.walkDecls(function (decl) { if ((propNoVendorPrefix && /^-\w+-(.+)$/.test(decl.prop)) || (valueNoVendorPrefix && /(^|,|\s)-\w+-.+/.test(decl.value))) { clearPrefixedDecl(decl) - if(!decl.parent) { + if (!decl.parent) { return } } diff --git a/lib/gradient.js b/lib/gradient.js index 87b0de2..7d2e894 100644 --- a/lib/gradient.js +++ b/lib/gradient.js @@ -24,7 +24,7 @@ var angleUnitMap = { turn: 1, } -// 各种长度单位与deg之间的换算关系 https://developer.mozilla.org/en-US/docs/Web/CSS/length +// 各种长度单位与deg之间的换算关系 https://developer.mozilla.org/zh-CN/docs/Web/CSS/length var lengthUnitMap = { '%': 1, 'in': 96, @@ -487,6 +487,7 @@ function stringifyArg (arg) { * 将二维数组作为参数,重写type为function的语法树节点,type会变为word * @param {Node} gradient 语法树节点 * @param {Node} args 修正后的参数 + * @return {Node} 语法树节点 */ function stringifyGradient (gradient, args) { // 将参数还原成节点 diff --git a/lib/params.js b/lib/params.js index 44d6ff3..c3f514d 100644 --- a/lib/params.js +++ b/lib/params.js @@ -72,7 +72,7 @@ function loadConfig (stylelint, file, options) { throw err } }).then(function (rules) { - if(rules) { + if (rules) { return { indentWidth: getIndentationFromStylelintRules(rules), hasScss: /\.scss$/i.test(file), diff --git a/lib/unprefixer.js b/lib/unprefixer.js index 7e06257..8253e16 100644 --- a/lib/unprefixer.js +++ b/lib/unprefixer.js @@ -4,31 +4,63 @@ const postcss = require('postcss') const autoprefixer = require('autoprefixer') const valueParser = require('postcss-value-parser') -function valMap (reg, prop, valMap) { - return function (decl) { +function valMap (reg, prop, valMapData) { + return function valMap (decl) { if (reg.test(decl.prop)) { var value = postcss.vendor.unprefixed(decl.value) - if(valMap[value]) { + if (valMapData[value]) { return { prop: prop, - value: valMap[value], + value: valMapData[value], } } } } } +function brotherFirst (reg, brotherProp) { + return function brotherFirst (decl) { + if (reg.test(decl.prop)) { + var brother = getBrotherDecl(decl, brotherProp) + if (brother) { + return unprefixDecl(brother) + } + } + } +} + function getBrotherDecl (decl, prop){ var result - decl.parent.walkDecls(new RegExp('^(?:-\\w+-)?' + prop + '$'), function (decl){ + decl.parent.walkDecls(prop, function (decl){ result = decl }) return result } +const RE_BOX_DIRECTION = /^(?:-\w+-)?(?:flex)?box-direction$/i +const RE_BOX_ORIENT = /^(?:-\w+-)?(?:flex)?box-orient$/i +const RE_FLEX_FLOW = /^(?:-\w+-)?flex-flow$/i +const RE_ORDER = /^(?:-\w+-)?order$/i + const declUnprefixers = [ + valMap(/^(?:-\w+-)?(?:flex)?box-direction$/i, 'flex-direction', { + 'lr': 'row', + 'rl': 'row-reverse', + 'tb': 'column', + 'bt': 'column-reverse' + }), + valMap(/^(?:(?:-\w+-)?(?:flex)?box|-ms-flex)-pack$/i, 'justify-content', { + 'start': 'flex-start', + 'end': 'flex-end', + 'justify': 'space-between' + }), + brotherFirst(/^(?:-\w+-)?box-flex$/i, /^(?:-\w+-)?flex$/i), + brotherFirst(/^(?:-\w+-)?box-ordinal-group$/i, RE_ORDER), + brotherFirst(/^-ms-flex-order$/i, RE_ORDER), + brotherFirst(RE_BOX_ORIENT, RE_FLEX_FLOW), + brotherFirst(RE_BOX_DIRECTION, RE_FLEX_FLOW), function alignItems (decl) { - if (/^(?:-\w+-)?(?:flex|box|flexbox)-align$/.test(decl.prop) ) { + if (/^(?:-\w+-)?(?:flex)?box-align$/i.test(decl.prop) || /^-ms-flex-align$/i.test(decl.prop)) { return { prop: 'align-items', value: decl.value.replace(/^(?:-\w+-)?(start|end)$/, 'flex-$1') @@ -36,60 +68,32 @@ const declUnprefixers = [ } }, function breakInside (decl) { - if (/^(?:-\w+-)?(\w+)-break-(\w+)/.test(decl.prop)) { + if (/^(?:-\w+-)?(\w+)-break-(\w+)/i.test(decl.prop)) { return { prop: 'break-' + RegExp.$2, value: decl.value === 'avoid' ? RegExp.$1 + '-avoid' : decl.value, } } }, - function display (decl) { - if (/^(?:-\w+-)?display$/.test(decl.prop) && /^(?:-\w+-)?(inline-)?(?:flex|box|flexbox)$/.test(decl.value)) { - return { - prop: 'display', - value: RegExp.$1 + 'flex' - } - } - }, - valMap(/^(?:-\w+-)?(?:flex|box|flexbox)-direction$/, 'flex-direction', { - 'lr': 'row', - 'rl': 'row-reverse', - 'tb': 'column', - 'bt': 'column-reverse' - }), - valMap(/^(?:-\w+-)?(?:flex|box|flexbox)-pack$/, 'justify-content', { - 'start': 'flex-start', - 'end': 'flex-end', - 'justify': 'space-between' - }), function interpolationMode (decl) { - if (/^-ms-interpolation-mode$/.test(decl.prop) && /^nearest-neighbor$/.test(decl.value)) { + if (/^-ms-interpolation-mode$/i.test(decl.prop) && /^nearest-neighbor$/i.test(decl.value)) { return { prop: 'image-rendering', value: 'pixelated', } } }, - function flexFlow (decl) { - var flexFlow - if (/^(?:-\w+-)?(?:flex|box|flexbox)-(?:orient|direction)$/.test(decl.prop) && (flexFlow = getBrotherDecl(decl, 'flex-flow'))) { - return { - prop: flexFlow.prop, - value: flexFlow.value, - } - } - }, function boxOrient (decl) { - if (/^(?:-\w+-)?(?:flex|box|flexbox)-orient$/.test(decl.prop)) { + if (RE_BOX_ORIENT.test(decl.prop)) { var boxOrient = { horizontal: 'row', vertical: 'column', }[decl.value.toLowerCase()] - if(!boxOrient) { + if (!boxOrient) { return } - var boxDirection = getBrotherDecl(decl, 'box-direction') + var boxDirection = getBrotherDecl(decl, RE_BOX_DIRECTION) if (boxDirection && boxDirection.value === 'reverse') { boxDirection = '-reverse' } else { @@ -102,17 +106,17 @@ const declUnprefixers = [ } }, function boxDirection (decl) { - if (/^(?:-\w+-)?(?:flex|box|flexbox)-direction$/.test(decl.prop)) { + if (RE_BOX_DIRECTION.test(decl.prop)) { var boxDirection = decl.value.toLowerCase() if (boxDirection === 'reverse') { boxDirection = '-reverse' - } else if(boxDirection === 'normal') { + } else if (boxDirection === 'normal') { boxDirection = '' } else { return } - var boxOrient = getBrotherDecl(decl, 'box-orient') + var boxOrient = getBrotherDecl(decl, RE_BOX_ORIENT) if (boxOrient && boxOrient.value === 'vertical') { boxOrient = 'column' } else { @@ -171,22 +175,14 @@ const PROP_NAME_MAP = { 'box-align': 'align-items', 'box-pack': 'justify-content', - 'box-ordinal-group': 'order', - 'flex-order': 'order', - 'box-flex': 'flex', + // 'box-ordinal-group': 'order', + // 'box-flex': 'flex', } const valueUnprefixers = [ - function unprefixPropInValue (node) { - var prefixed = unprefixProp(node.value) - if(prefixed) { - node.value = prefixed - return prefixed - } - }, function imageRendering (node, prop) { - if(/^(?:-\w+-)?image-rendering/.test(prop) && /^-\w+-/.test(node.value)) { - if(/^-\w+-optimize-contrast$/.test(node.value)) { + if (/^(?:-\w+-)?image-rendering/i.test(prop) && /^-\w+-/i.test(node.value)) { + if (/^-\w+-optimize-contrast$/i.test(node.value)) { node.value = 'crisp-edges' } else { node.value = postcss.vendor.unprefixed(node.value) @@ -194,18 +190,33 @@ const valueUnprefixers = [ return node } }, + function displayFlex (node, prop) { + if (/^(?:-\w+-)?display$/i.test(prop) && /^(?:-\w+-)?(inline-)?((?:flex)?(?:box)?)$/i.test(node.value) && RegExp.$2) { + node.value = RegExp.$1 + 'flex' + return node + } + }, require('./gradient'), + function unprefixPropInValue (node, prop) { + if (/^^(?:-\w+-)?transition(?:-property)?$/.test(prop) || node.type === 'function') { + var prefixed = unprefixProp(node.value) + if (prefixed) { + node.value = prefixed + return node + } + } + }, ] function unprefixProp (prop) { - if(PREFIXED_PROP_NAME_MAP[prop]){ + if (PREFIXED_PROP_NAME_MAP[prop]){ return PREFIXED_PROP_NAME_MAP[prop] } prop = postcss.vendor.unprefixed(prop) - if(autoprefixer.data.prefixes[prop]) { + if (autoprefixer.data.prefixes[prop]) { return prop } - if(PROP_NAME_MAP[prop]){ + if (PROP_NAME_MAP[prop]){ return PROP_NAME_MAP[prop] } } @@ -214,18 +225,18 @@ function unprefixValue (value, prop) { var fixed value = valueParser(value) value.nodes.forEach(function (node) { - if(node.type !== 'div' && /^-\w+-/.test(node.value) && valueUnprefixers.some(function (unprefixer) { + if (node.type !== 'div' && /^-\w+-/i.test(node.value) && valueUnprefixers.some(function (unprefixer) { return unprefixer(node, prop) })) { fixed = true } }) - if(fixed){ + if (fixed){ return valueParser.stringify(value).replace(/(.+?)(\s*,\s*\1)+/g, '$1') } } -function unprefixdecl (decl) { +function unprefixDecl (decl) { var result if (declUnprefixers.some(function (unprefixer) { result = unprefixer(decl) @@ -240,12 +251,12 @@ function unprefixdecl (decl) { } function unprefix (decl) { - var result = unprefixdecl (decl) + var result = unprefixDecl (decl) result.replace = function (){ - if(result.prop) { + if (result.prop) { decl.prop = result.prop } - if(result.value) { + if (result.value) { decl.value = result.value } } diff --git a/lib/util.js b/lib/util.js index 04d60c1..acc0501 100644 --- a/lib/util.js +++ b/lib/util.js @@ -55,55 +55,10 @@ function getOptions (stylelint, prop, option) { return stylelintProperty } -var propNameMap = { - 'border-radius-bottomleft': 'border-bottom-left-radius', - 'border-radius-bottomright': 'border-bottom-right-radius', - 'border-radius-topleft': 'border-top-left-radius', - 'border-radius-topright': 'border-top-right-radius', - - 'border-after': 'border-block-end', - 'border-before': 'border-block-start', - 'border-end': 'border-inline-end', - 'border-start': 'border-inline-start', - - 'margin-after': 'margin-block-end', - 'margin-before': 'margin-block-start', - 'margin-end': 'margin-inline-end', - 'margin-start': 'margin-inline-start', - - 'padding-after': 'padding-block-end', - 'padding-before': 'padding-block-start', - 'padding-end': 'padding-inline-end', - 'padding-start': 'padding-inline-start', - - 'mask-box-image': 'mask-border', - 'mask-box-image-outset': 'mask-border-outset', - 'mask-box-image-repeat': 'mask-border-repeat', - 'mask-box-image-slice': 'mask-border-slice', - 'mask-box-image-source': 'mask-border-source', - 'mask-box-image-width': 'mask-border-width', - - 'box-align': 'align-items', - 'box-pack': 'justify-content', - 'box-ordinal-group': 'order', - 'flex-order': 'order', - 'box-flex': 'flex', -} - -function unprefixProp (prop) { - prop = prop.replace(/^-\w+-/, '') - return propNameMap[prop] || prop -} - -function unprefixDecl () { - -} module.exports = { inAtRule: inAtRule, getNestedRulesNum: getNestedRulesNum, isEmptyObject: isEmptyObject, getProperty: getProperty, - getOptions: getOptions, - unprefixProp: unprefixProp, - unprefixDecl: unprefixDecl, + getOptions: getOptions } diff --git a/package.json b/package.json index e9b2db1..0a3d7f3 100644 --- a/package.json +++ b/package.json @@ -4,16 +4,18 @@ "description": "stylefmt is a tool that automatically formats CSS according to stylelint rules", "main": "index.js", "scripts": { - "test": "nyc tape test/*.js | faucet && npm run lint", - "lint": "eslint -c .eslintrc.json index.js lib bin" + "pretest": "eslint -c .eslintrc.json index.js lib bin", + "test": "nyc tape test/*.js | faucet" }, "nyc": { - "lines": 97, - "statements": 97, - "functions": 98, - "branches": 96, + "lines": 80, + "statements": 80, + "functions": 80, + "branches": 80, "include": [ - "lib/**/*.js" + "index.js", + "lib/**/*.js", + "bin/**/*.js" ], "exclude": [ "dist/**/*.spec.js" diff --git a/test/stylelint/no-vendor-prefix/no-vendor-prefix.css b/test/stylelint/no-vendor-prefix/no-vendor-prefix.css index 8fdcb77..f0dbb03 100644 --- a/test/stylelint/no-vendor-prefix/no-vendor-prefix.css +++ b/test/stylelint/no-vendor-prefix/no-vendor-prefix.css @@ -1,275 +1,434 @@ a { - -js-display: flex; - display: -webkit-box; - display: -webkit-flex; - display: -moz-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -webkit-flex-flow: row; - -moz-box-orient: horizontal; - -moz-box-direction: normal; - -ms-flex-flow: row; - flex-flow: row; - -webkit-box-ordinal-group: 1; - -webkit-order: 0; - -moz-box-ordinal-group: 1; - -ms-flex-order: 0; - order: 0; - -webkit-box-flex: 0; - -webkit-flex: 0 1 2; - -moz-box-flex: 0; - -ms-flex: 0 1 2; - flex: 0 1 2; - -webkit-transition: -webkit-box-flex 200ms, -webkit-flex 200ms; - transition: -webkit-box-flex 200ms, -webkit-flex 200ms; - transition: flex 200ms; - transition: flex 200ms, -webkit-box-flex 200ms, -webkit-flex 200ms, -moz-box-flex 200ms, -ms-flex 200ms; + -js-display: flex; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-flow: row; + -moz-box-orient: horizontal; + -moz-box-direction: normal; + -ms-flex-flow: row; + flex-flow: row; + -webkit-box-ordinal-group: 1; + -webkit-order: 0; + -moz-box-ordinal-group: 1; + -ms-flex-order: 0; + order: 0; + -webkit-box-flex: 0; + -webkit-flex: 0 1 2; + -moz-box-flex: 0; + -ms-flex: 0 1 2; + flex: 0 1 2; + -webkit-transition: -webkit-box-flex 200ms, -webkit-flex 200ms; + transition: -webkit-box-flex 200ms, -webkit-flex 200ms; + transition: flex 200ms; + transition: flex 200ms, -webkit-box-flex 200ms, -webkit-flex 200ms, -moz-box-flex 200ms, -ms-flex 200ms; } .inline { - display: -webkit-inline-box; - display: -webkit-inline-flex; - display: -moz-inline-box; - display: -ms-inline-flexbox; - display: inline-flex; - -webkit-align-self: auto; - -ms-flex-item-align: auto; - align-self: auto; - -webkit-align-content: stretch; - -ms-flex-line-pack: stretch; - align-content: stretch; - -webkit-box-flex: 1; - -webkit-flex: auto; - -moz-box-flex: 1; - -ms-flex: auto; - flex: auto; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -moz-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-align-self: auto; + -ms-flex-item-align: auto; + align-self: auto; + -webkit-align-content: stretch; + -ms-flex-line-pack: stretch; + align-content: stretch; + -webkit-box-flex: 1; + -webkit-flex: auto; + -moz-box-flex: 1; + -ms-flex: auto; + flex: auto; } .inline-box { - display: -webkit-inline-box; + display: -webkit-inline-box; } .inline-flex { - display: -webkit-inline-flex; + display: -webkit-inline-flex; } .inline-flexbox { - display: -ms-inline-flexbox; + display: -ms-inline-flexbox; } .a { - display: -webkit-box; - display: -webkit-flex; - display: -moz-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -webkit-flex-direction: row; - -moz-box-orient: horizontal; - -moz-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -moz-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-box-align: start; - -webkit-align-items: flex-start; - -moz-box-align: start; - -ms-flex-align: start; - align-items: flex-start; - -webkit-flex-wrap: nowrap; - -ms-flex-wrap: nowrap; - flex-wrap: nowrap; - -webkit-align-content: flex-start; - -ms-flex-line-pack: start; - align-content: flex-start; - -webkit-align-self: flex-start; - -ms-flex-item-align: start; - align-self: flex-start; - -webkit-box-flex: 0; - -webkit-flex: none; - -moz-box-flex: 0; - -ms-flex: none; - flex: none; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -moz-box-orient: horizontal; + -moz-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -moz-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + -webkit-box-align: start; + -webkit-align-items: flex-start; + -moz-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-align-content: flex-start; + -ms-flex-line-pack: start; + align-content: flex-start; + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; + -webkit-box-flex: 0; + -webkit-flex: none; + -moz-box-flex: 0; + -ms-flex: none; + flex: none; } .display_flex { - display: -webkit-flex; + display: -webkit-flex; } .display_box { - display: -moz-box; + display: -moz-box; } .display_flexbox { - display: -ms-flexbox; + display: -ms-flexbox; } .b { - display: -webkit-box; - display: -webkit-flex; - display: -moz-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: reverse; - -webkit-flex-direction: row-reverse; - -moz-box-orient: horizontal; - -moz-box-direction: reverse; - -ms-flex-direction: row-reverse; - flex-direction: row-reverse; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -moz-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-box-align: end; - -webkit-align-items: flex-end; - -moz-box-align: end; - -ms-flex-align: end; - align-items: flex-end; - -webkit-flex-wrap: wrap; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -webkit-align-content: flex-end; - -ms-flex-line-pack: end; - align-content: flex-end; - -webkit-align-self: flex-end; - -ms-flex-item-align: end; - align-self: flex-end; - -webkit-flex-shrink: 1; - -ms-flex-negative: 1; - flex-shrink: 1; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: reverse; + -webkit-flex-direction: row-reverse; + -moz-box-orient: horizontal; + -moz-box-direction: reverse; + -ms-flex-direction: row-reverse; + flex-direction: row-reverse; + -webkit-box-pack: end; + -webkit-justify-content: flex-end; + -moz-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + -webkit-box-align: end; + -webkit-align-items: flex-end; + -moz-box-align: end; + -ms-flex-align: end; + align-items: flex-end; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-align-content: flex-end; + -ms-flex-line-pack: end; + align-content: flex-end; + -webkit-align-self: flex-end; + -ms-flex-item-align: end; + align-self: flex-end; + -webkit-flex-shrink: 1; + -ms-flex-negative: 1; + flex-shrink: 1; } .c { - display: -webkit-box; - display: -webkit-flex; - display: -moz-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -webkit-flex-direction: column; - -moz-box-orient: vertical; - -moz-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: center; - -webkit-justify-content: center; - -moz-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-box-align: center; - -webkit-align-items: center; - -moz-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-flex-wrap: reverse-wrap; - -ms-flex-wrap: reverse-wrap; - flex-wrap: reverse-wrap; - -webkit-align-content: center; - -ms-flex-line-pack: center; - align-content: center; - -webkit-align-self: center; - -ms-flex-item-align: center; - align-self: center; - -webkit-flex-basis: auto; - -ms-flex-preferred-size: auto; - flex-basis: auto; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -moz-box-orient: vertical; + -moz-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -webkit-justify-content: center; + -moz-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -webkit-align-items: center; + -moz-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: reverse-wrap; + -ms-flex-wrap: reverse-wrap; + flex-wrap: reverse-wrap; + -webkit-align-content: center; + -ms-flex-line-pack: center; + align-content: center; + -webkit-align-self: center; + -ms-flex-item-align: center; + align-self: center; + -webkit-flex-basis: auto; + -ms-flex-preferred-size: auto; + flex-basis: auto; } .e { - display: -webkit-box; - display: -webkit-flex; - display: -moz-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: reverse; - -webkit-flex-direction: column-reverse; - -moz-box-orient: vertical; - -moz-box-direction: reverse; - -ms-flex-direction: column-reverse; - flex-direction: column-reverse; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -moz-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; - -webkit-box-align: baseline; - -webkit-align-items: baseline; - -moz-box-align: baseline; - -ms-flex-align: baseline; - align-items: baseline; - -webkit-align-content: space-between; - -ms-flex-line-pack: justify; - align-content: space-between; - -webkit-align-self: baseline; - -ms-flex-item-align: baseline; - align-self: baseline; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: reverse; + -webkit-flex-direction: column-reverse; + -moz-box-orient: vertical; + -moz-box-direction: reverse; + -ms-flex-direction: column-reverse; + flex-direction: column-reverse; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -moz-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: baseline; + -webkit-align-items: baseline; + -moz-box-align: baseline; + -ms-flex-align: baseline; + align-items: baseline; + -webkit-align-content: space-between; + -ms-flex-line-pack: justify; + align-content: space-between; + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; } .f { - display: -webkit-box; - display: -webkit-flex; - display: -moz-box; - display: -ms-flexbox; - display: flex; - -webkit-justify-content: space-around; - -ms-flex-pack: distribute; - justify-content: space-around; - -webkit-box-align: stretch; - -webkit-align-items: stretch; - -moz-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - -webkit-align-content: space-around; - -ms-flex-line-pack: distribute; - align-content: space-around; - -webkit-align-self: stretch; - -ms-flex-item-align: stretch; - align-self: stretch; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-justify-content: space-around; + -ms-flex-pack: distribute; + justify-content: space-around; + -webkit-box-align: stretch; + -webkit-align-items: stretch; + -moz-box-align: stretch; + -ms-flex-align: stretch; + align-items: stretch; + -webkit-align-content: space-around; + -ms-flex-line-pack: distribute; + align-content: space-around; + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; + align-self: stretch; } .g { - display: -webkit-box; - display: -webkit-flex; - display: -moz-box; - display: -ms-flexbox; - display: flex; - -webkit-box-flex: -webkit-calc(1em + 1px); - -webkit-flex: -webkit-calc(1em + 1px) 0 0; - -moz-box-flex: calc(1em + 1px); - -ms-flex: calc(1em + 1px) 0 0px; - flex: calc(1em + 1px) 0 0; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: -webkit-calc(1em + 1px); + -webkit-flex: -webkit-calc(1em + 1px) 0 0; + -moz-box-flex: calc(1em + 1px); + -ms-flex: calc(1em + 1px) 0 0px; + flex: calc(1em + 1px) 0 0; } .h { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -webkit-flex-flow: column wrap; - -moz-box-orient: vertical; - -moz-box-direction: normal; - -ms-flex-flow: column wrap; - flex-flow: column wrap; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-flow: column wrap; + -moz-box-orient: vertical; + -moz-box-direction: normal; + -ms-flex-flow: column wrap; + flex-flow: column wrap; } .i { - -webkit-flex-flow: nowrap; - -ms-flex-flow: nowrap; - flex-flow: nowrap; + -webkit-flex-flow: nowrap; + -ms-flex-flow: nowrap; + flex-flow: nowrap; } .inherit { - -webkit-box-ordinal-group: inherit; - -webkit-order: inherit; - -moz-box-ordinal-group: inherit; - -ms-flex-order: inherit; - order: inherit; + -webkit-box-ordinal-group: inherit; + -webkit-order: inherit; + -moz-box-ordinal-group: inherit; + -ms-flex-order: inherit; + order: inherit; +} + +a { + background: -webkit-linear-gradient(99.5deg, white, black), -webkit-linear-gradient(220deg, black, white), -webkit-linear-gradient(45deg, black, white); + background: -o-linear-gradient(99.5deg, white, black), -o-linear-gradient(220deg, black, white), -o-linear-gradient(45deg, black, white); + background: linear-gradient(350.5deg, white, black), linear-gradient(-130deg, black, white), linear-gradient(45deg, black, white); +} + +b { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 1)), to(white)), -webkit-gradient(linear, left top, left bottom, from(white), to(black)); + background-image: -webkit-linear-gradient(rgba(0, 0, 0, 1), white), -webkit-linear-gradient(white, black); + background-image: -o-linear-gradient(rgba(0, 0, 0, 1), white), -o-linear-gradient(white, black); + background-image: linear-gradient(rgba(0, 0, 0, 1), white), linear-gradient(white, black); +} + +strong { + background: -webkit-linear-gradient(bottom, transparent, rgba(0, 0, 0, 0.8) 20px, #000 30px, #000) no-repeat; + background: -o-linear-gradient(bottom, transparent, rgba(0, 0, 0, 0.8) 20px, #000 30px, #000) no-repeat; + background: linear-gradient(to top, transparent, rgba(0, 0, 0, 0.8) 20px, #000 30px, #000) no-repeat; +} + +div { + background-image: -webkit-radial-gradient(right, white, black), -webkit-repeating-linear-gradient(top left, black, white), -webkit-repeating-radial-gradient(bottom, aqua, red); + background-image: -o-radial-gradient(right, white, black), -o-repeating-linear-gradient(top left, black, white), -o-repeating-radial-gradient(bottom, aqua, red); + background-image: radial-gradient(to left, white, black), repeating-linear-gradient(to bottom right, black, white), repeating-radial-gradient(to top, aqua, red); +} + +.radial { + background: -webkit-radial-gradient(ellipse farthest-corner, black, white); + background: -o-radial-gradient(ellipse farthest-corner, black, white); + background: radial-gradient(ellipse farthest-corner, black, white); +} + +.simple1 { + background: -webkit-gradient(linear, left top, left bottom, from(black), to(white)); + background: -webkit-linear-gradient(black, white); + background: -o-linear-gradient(black, white); + background: linear-gradient(black, white); +} + +.simple2 { + background: -webkit-gradient(linear, right top, left top, from(black), color-stop(50%, rgba(0, 0, 0, 0.5)), to(white)); + background: -webkit-linear-gradient(right, black 0%, rgba(0, 0, 0, 0.5)50%, white 100%); + background: -o-linear-gradient(right, black 0%, rgba(0, 0, 0, 0.5)50%, white 100%); + background: linear-gradient(to left, black 0%, rgba(0, 0, 0, 0.5)50%, white 100%); +} + +.simple3 { + background: -webkit-gradient(linear, right top, left top, color-stop(50%, black), to(white)); + background: -webkit-linear-gradient(right, black 50%, white 100%); + background: -o-linear-gradient(right, black 50%, white 100%); + background: linear-gradient(to left, black 50%, white 100%); +} + +.simple4 { + background: -webkit-gradient(linear, left bottom, right top, from(black), to(white)); + background: -webkit-linear-gradient(left bottom, black, white); + background: -o-linear-gradient(left bottom, black, white); + background: linear-gradient(to right top, black, white); +} + +.direction { + background: -webkit-gradient(linear, left top, right bottom, from(black), color-stop(rgba(0, 0, 0, 0.5)), to(white)); + background: -webkit-linear-gradient(top left, black, rgba(0, 0, 0, 0.5), white); + background: -o-linear-gradient(top left, black, rgba(0, 0, 0, 0.5), white); + background: linear-gradient(top left, black, rgba(0, 0, 0, 0.5), white); +} + +.silent { + background: -webkit-linear-gradient(top left, black, white); +} + +.radial { + background: -webkit-radial-gradient(0 50%, farthest-side, white, black); + background: -o-radial-gradient(0 50%, farthest-side, white, black); + background: radial-gradient(farthest-side at 0 50%, white, black); +} + +.second { + background: red -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); + background: red -webkit-linear-gradient(red, blue); + background: red -o-linear-gradient(red, blue); + background: red linear-gradient(red, blue); + background: url('logo.png'), -webkit-gradient(linear, left top, left bottom, from(#fff), to(#000)); + background: url('logo.png'), -webkit-linear-gradient(#fff, #000); + background: url('logo.png'), -o-linear-gradient(#fff, #000); + background: url('logo.png'), linear-gradient(#fff, #000); +} + +.px { + background: -webkit-linear-gradient(black 0, white 100px); + background: -o-linear-gradient(black 0, white 100px); + background: linear-gradient(black 0, white 100px); +} + +.list { + list-style-image: -webkit-gradient(linear, left top, left bottom, from(white), to(black)); + list-style-image: -webkit-linear-gradient(white, black); + list-style-image: linear-gradient(white, black); +} + +.mask1 { + -webkit-mask: -webkit-gradient(linear, left top, left bottom, from(white), to(black)); +} + +.mask2 { + -webkit-mask: -webkit-linear-gradient(white, black); +} + +.mask3 { + mask: -webkit-gradient(linear, left top, left bottom, from(white), to(black)); +} + +.newline_old { + background-image: -webkit-gradient(linear, left top, left bottom, from(white), to(black)), -webkit-gradient(linear, left top, left bottom, from(black), to(white)); +} + +.newline { + background-image: -webkit-linear-gradient(white, black), -webkit-linear-gradient(black, white); + background-image: -o-linear-gradient(white, black), -o-linear-gradient(black, white); +} + +.convert_old { + background: -webkit-gradient(linear, right top, left top, from(white), to(black)); +} + +.convert { + background: -webkit-linear-gradient(right, white, black); + background: -o-linear-gradient(right, white, black); +} + +.rad { + background: -webkit-linear-gradient(32.704deg, white, black); + background: -o-linear-gradient(32.704deg, white, black); +} + +.turn { + background: -webkit-linear-gradient(342deg, white, black); + background: -o-linear-gradient(342deg, white, black); +} + +.norm { + background: -webkit-gradient(linear, right top, left top, from(white), to(black)); + background: -webkit-linear-gradient(right, white, black); + background: -o-linear-gradient(right, white, black); +} + +.foo { + --widthA: 100px; + --widthB: -webkit-calc(var(--widthA) / 2); + --widthC: -webkit-calc(var(--widthB) / 2); + --widthB: -moz-calc(var(--widthA) / 2); + --widthC: -moz-calc(var(--widthB) / 2); + width: var(--widthC); +} + +div { + width: -webkit-calc(100% - 1em); + width: -moz-calc(100% - 1em); } diff --git a/test/stylelint/no-vendor-prefix/no-vendor-prefix.out.css b/test/stylelint/no-vendor-prefix/no-vendor-prefix.out.css index b9bcb88..d198721 100644 --- a/test/stylelint/no-vendor-prefix/no-vendor-prefix.out.css +++ b/test/stylelint/no-vendor-prefix/no-vendor-prefix.out.css @@ -103,3 +103,115 @@ a { .inherit { order: inherit; } + +a { + background: linear-gradient(350.5deg, white, black), linear-gradient(-130deg, black, white), linear-gradient(45deg, black, white); +} + +b { + background-image: linear-gradient(rgba(0, 0, 0, 1), white), linear-gradient(white, black); +} + +strong { + background: linear-gradient(to top, transparent, rgba(0, 0, 0, 0.8) 20px, #000 30px, #000) no-repeat; +} + +div { + background-image: radial-gradient(to left, white, black), repeating-linear-gradient(to bottom right, black, white), repeating-radial-gradient(to top, aqua, red); +} + +.radial { + background: radial-gradient(ellipse farthest-corner, black, white); +} + +.simple1 { + background: linear-gradient(black, white); +} + +.simple2 { + background: linear-gradient(to left, black 0%, rgba(0, 0, 0, 0.5)50%, white 100%); +} + +.simple3 { + background: linear-gradient(to left, black 50%, white 100%); +} + +.simple4 { + background: linear-gradient(to right top, black, white); +} + +.direction { + background: linear-gradient(top left, black, rgba(0, 0, 0, 0.5), white); +} + +.silent { + background: linear-gradient(to bottom right, black, white); +} + +.radial { + background: radial-gradient(farthest-side at 0 50%, white, black); +} + +.second { + background: red linear-gradient(red, blue); + background: url('logo.png'), linear-gradient(#fff, #000); +} + +.px { + background: linear-gradient(black 0, white 100px); +} + +.list { + list-style-image: linear-gradient(white, black); +} + +.mask1 { + mask: linear-gradient(white, black); +} + +.mask2 { + mask: linear-gradient(white, black); +} + +.mask3 { + mask: linear-gradient(white, black); +} + +.newline_old { + background-image: linear-gradient(white, black), linear-gradient(black, white); +} + +.newline { + background-image: linear-gradient(white, black), linear-gradient(black, white); +} + +.convert_old { + background: linear-gradient(270deg, white, black); +} + +.convert { + background: linear-gradient(to left, white, black); +} + +.rad { + background: linear-gradient(57.296deg, white, black); +} + +.turn { + background: linear-gradient(108deg, white, black); +} + +.norm { + background: linear-gradient(to left, white, black); +} + +.foo { + --widthA: 100px; + --widthB: calc(var(--widthA) / 2); + --widthC: calc(var(--widthB) / 2); + width: var(--widthC); +} + +div { + width: calc(100% - 1em); +} diff --git a/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.css b/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.css index e7730e8..284a12e 100644 --- a/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.css +++ b/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.css @@ -19,297 +19,370 @@ h1 { } a { - -js-display: flex; - display: -webkit-box; - display: -webkit-flex; - display: -moz-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -webkit-flex-flow: row; - -moz-box-orient: horizontal; - -moz-box-direction: normal; - -ms-flex-flow: row; - flex-flow: row; - -webkit-box-ordinal-group: 1; - -webkit-order: 0; - -moz-box-ordinal-group: 1; - -ms-flex-order: 0; - order: 0; - -webkit-box-flex: 0; - -webkit-flex: 0 1 2; - -moz-box-flex: 0; - -ms-flex: 0 1 2; - flex: 0 1 2; - -webkit-transition: -webkit-box-flex 200ms, -webkit-flex 200ms; - transition: -webkit-box-flex 200ms, -webkit-flex 200ms; - transition: flex 200ms; - transition: flex 200ms, -webkit-box-flex 200ms, -webkit-flex 200ms, -moz-box-flex 200ms, -ms-flex 200ms; + -js-display: flex; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-flow: row; + -moz-box-orient: horizontal; + -moz-box-direction: normal; + -ms-flex-flow: row; + flex-flow: row; + -webkit-box-ordinal-group: 1; + -webkit-order: 0; + -moz-box-ordinal-group: 1; + -ms-flex-order: 0; + order: 0; + -webkit-box-flex: 0; + -webkit-flex: 0 1 2; + -moz-box-flex: 0; + -ms-flex: 0 1 2; + flex: 0 1 2; + -webkit-transition: -webkit-box-flex 200ms, -webkit-flex 200ms; + transition: -webkit-box-flex 200ms, -webkit-flex 200ms; + transition: flex 200ms; + transition: flex 200ms, -webkit-box-flex 200ms, -webkit-flex 200ms, -moz-box-flex 200ms, -ms-flex 200ms; +} + +.flex-direction:row { + -webkit-box-direction: normal; + -webkit-box-orient: horizontal; +} + +.flex-direction:row-reverse { + -webkit-box-direction: reverse; + -webkit-box-orient: horizontal; +} + +.flex-direction:column { + -webkit-box-direction: normal; + -webkit-box-orient: vertical; +} + +.flex-direction:column-reverse { + -webkit-box-direction: reverse; + -webkit-box-orient: vertical; +} + +.flex-direction:row { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; +} + +.flex-direction:row-reverse { + -webkit-box-orient: horizontal; + -webkit-box-direction: reverse; +} + +.flex-direction:column { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; +} + +.flex-direction:column-reverse { + -webkit-box-orient: vertical; + -webkit-box-direction: reverse; +} + +.box-orient:vertical { + -webkit-box-orient: vertical; +} + +.box-orient:horizontal { + -webkit-box-orient: horizontal; +} + +.box-orient { + -webkit-box-orient: error; +} + +.box-direction:normal { + -webkit-box-direction: normal; } + +.box-direction:reverse { + -webkit-box-direction: reverse; +} + +.box-direction { + -webkit-box-direction: error; +} + .inline { - display: -webkit-inline-box; - display: -webkit-inline-flex; - display: -moz-inline-box; - display: -ms-inline-flexbox; - display: inline-flex; - -webkit-align-self: auto; - -ms-flex-item-align: auto; - align-self: auto; - -webkit-align-content: stretch; - -ms-flex-line-pack: stretch; - align-content: stretch; - -webkit-box-flex: 1; - -webkit-flex: auto; - -moz-box-flex: 1; - -ms-flex: auto; - flex: auto; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -moz-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-align-self: auto; + -ms-flex-item-align: auto; + align-self: auto; + -webkit-align-content: stretch; + -ms-flex-line-pack: stretch; + align-content: stretch; + -webkit-box-flex: 1; + -webkit-flex: auto; + -moz-box-flex: 1; + -ms-flex: auto; + flex: auto; } .a { - display: -webkit-box; - display: -webkit-flex; - display: -moz-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -webkit-flex-direction: row; - -moz-box-orient: horizontal; - -moz-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -moz-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-box-align: start; - -webkit-align-items: flex-start; - -moz-box-align: start; - -ms-flex-align: start; - align-items: flex-start; - -webkit-flex-wrap: nowrap; - -ms-flex-wrap: nowrap; - flex-wrap: nowrap; - -webkit-align-content: flex-start; - -ms-flex-line-pack: start; - align-content: flex-start; - -webkit-align-self: flex-start; - -ms-flex-item-align: start; - align-self: flex-start; - -webkit-box-flex: 0; - -webkit-flex: none; - -moz-box-flex: 0; - -ms-flex: none; - flex: none; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -moz-box-orient: horizontal; + -moz-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -moz-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + -webkit-box-align: start; + -webkit-align-items: flex-start; + -moz-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-align-content: flex-start; + -ms-flex-line-pack: start; + align-content: flex-start; + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; + -webkit-box-flex: 0; + -webkit-flex: none; + -moz-box-flex: 0; + -ms-flex: none; + flex: none; } + .b { - display: -webkit-box; - display: -webkit-flex; - display: -moz-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: reverse; - -webkit-flex-direction: row-reverse; - -moz-box-orient: horizontal; - -moz-box-direction: reverse; - -ms-flex-direction: row-reverse; - flex-direction: row-reverse; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -moz-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-box-align: end; - -webkit-align-items: flex-end; - -moz-box-align: end; - -ms-flex-align: end; - align-items: flex-end; - -webkit-flex-wrap: wrap; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -webkit-align-content: flex-end; - -ms-flex-line-pack: end; - align-content: flex-end; - -webkit-align-self: flex-end; - -ms-flex-item-align: end; - align-self: flex-end; - -webkit-flex-shrink: 1; - -ms-flex-negative: 1; - flex-shrink: 1; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: reverse; + -webkit-flex-direction: row-reverse; + -moz-box-orient: horizontal; + -moz-box-direction: reverse; + -ms-flex-direction: row-reverse; + flex-direction: row-reverse; + -webkit-box-pack: end; + -webkit-justify-content: flex-end; + -moz-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + -webkit-box-align: end; + -webkit-align-items: flex-end; + -moz-box-align: end; + -ms-flex-align: end; + align-items: flex-end; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-align-content: flex-end; + -ms-flex-line-pack: end; + align-content: flex-end; + -webkit-align-self: flex-end; + -ms-flex-item-align: end; + align-self: flex-end; + -webkit-flex-shrink: 1; + -ms-flex-negative: 1; + flex-shrink: 1; } + .c { - display: -webkit-box; - display: -webkit-flex; - display: -moz-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -webkit-flex-direction: column; - -moz-box-orient: vertical; - -moz-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: center; - -webkit-justify-content: center; - -moz-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-box-align: center; - -webkit-align-items: center; - -moz-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-flex-wrap: reverse-wrap; - -ms-flex-wrap: reverse-wrap; - flex-wrap: reverse-wrap; - -webkit-align-content: center; - -ms-flex-line-pack: center; - align-content: center; - -webkit-align-self: center; - -ms-flex-item-align: center; - align-self: center; - -webkit-flex-basis: auto; - -ms-flex-preferred-size: auto; - flex-basis: auto; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -moz-box-orient: vertical; + -moz-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -webkit-justify-content: center; + -moz-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -webkit-align-items: center; + -moz-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex-wrap: reverse-wrap; + -ms-flex-wrap: reverse-wrap; + flex-wrap: reverse-wrap; + -webkit-align-content: center; + -ms-flex-line-pack: center; + align-content: center; + -webkit-align-self: center; + -ms-flex-item-align: center; + align-self: center; + -webkit-flex-basis: auto; + -ms-flex-preferred-size: auto; + flex-basis: auto; } + .e { - display: -webkit-box; - display: -webkit-flex; - display: -moz-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: reverse; - -webkit-flex-direction: column-reverse; - -moz-box-orient: vertical; - -moz-box-direction: reverse; - -ms-flex-direction: column-reverse; - flex-direction: column-reverse; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -moz-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; - -webkit-box-align: baseline; - -webkit-align-items: baseline; - -moz-box-align: baseline; - -ms-flex-align: baseline; - align-items: baseline; - -webkit-align-content: space-between; - -ms-flex-line-pack: justify; - align-content: space-between; - -webkit-align-self: baseline; - -ms-flex-item-align: baseline; - align-self: baseline; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: reverse; + -webkit-flex-direction: column-reverse; + -moz-box-orient: vertical; + -moz-box-direction: reverse; + -ms-flex-direction: column-reverse; + flex-direction: column-reverse; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -moz-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: baseline; + -webkit-align-items: baseline; + -moz-box-align: baseline; + -ms-flex-align: baseline; + align-items: baseline; + -webkit-align-content: space-between; + -ms-flex-line-pack: justify; + align-content: space-between; + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; } + .f { - display: -webkit-box; - display: -webkit-flex; - display: -moz-box; - display: -ms-flexbox; - display: flex; - -webkit-justify-content: space-around; - -ms-flex-pack: distribute; - justify-content: space-around; - -webkit-box-align: stretch; - -webkit-align-items: stretch; - -moz-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - -webkit-align-content: space-around; - -ms-flex-line-pack: distribute; - align-content: space-around; - -webkit-align-self: stretch; - -ms-flex-item-align: stretch; - align-self: stretch; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-justify-content: space-around; + -ms-flex-pack: distribute; + justify-content: space-around; + -webkit-box-align: stretch; + -webkit-align-items: stretch; + -moz-box-align: stretch; + -ms-flex-align: stretch; + align-items: stretch; + -webkit-align-content: space-around; + -ms-flex-line-pack: distribute; + align-content: space-around; + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; + align-self: stretch; } + .g { - display: -webkit-box; - display: -webkit-flex; - display: -moz-box; - display: -ms-flexbox; - display: flex; - -webkit-box-flex: -webkit-calc(1em + 1px); - -webkit-flex: -webkit-calc(1em + 1px) 0 0; - -moz-box-flex: calc(1em + 1px); - -ms-flex: calc(1em + 1px) 0 0px; - flex: calc(1em + 1px) 0 0; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: -webkit-calc(1em + 1px); + -webkit-flex: -webkit-calc(1em + 1px) 0 0; + -moz-box-flex: calc(1em + 1px); + -ms-flex: calc(1em + 1px) 0 0px; + flex: calc(1em + 1px) 0 0; } + .h { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -webkit-flex-flow: column wrap; - -moz-box-orient: vertical; - -moz-box-direction: normal; - -ms-flex-flow: column wrap; - flex-flow: column wrap; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-flow: column wrap; + -moz-box-orient: vertical; + -moz-box-direction: normal; + -ms-flex-flow: column wrap; + flex-flow: column wrap; } + .i { - -webkit-flex-flow: nowrap; - -ms-flex-flow: nowrap; - flex-flow: nowrap; + -webkit-flex-flow: nowrap; + -ms-flex-flow: nowrap; + flex-flow: nowrap; } + .inherit { - -webkit-box-ordinal-group: inherit; - -webkit-order: inherit; - -moz-box-ordinal-group: inherit; - -ms-flex-order: inherit; - order: inherit; + -webkit-box-ordinal-group: inherit; + -webkit-order: inherit; + -moz-box-ordinal-group: inherit; + -ms-flex-order: inherit; + order: inherit; } .a { - -webkit-column-break-inside: auto; - page-break-inside: auto; - break-inside: auto; - -webkit-column-break-before: auto; - page-break-before: auto; - break-before: auto; - -webkit-column-break-after: auto; - page-break-after: auto; - break-after: auto; + -webkit-column-break-inside: auto; + page-break-inside: auto; + break-inside: auto; + -webkit-column-break-before: auto; + page-break-before: auto; + break-before: auto; + -webkit-column-break-after: auto; + page-break-after: auto; + break-after: auto; } .b { - -webkit-column-break-inside: avoid; - page-break-inside: avoid; - break-inside: avoid; + -webkit-column-break-inside: avoid; + page-break-inside: avoid; + break-inside: avoid; } .c { - -webkit-column-break-inside: avoid; - page-break-inside: avoid; - break-inside: avoid-column; + -webkit-column-break-inside: avoid; + page-break-inside: avoid; + break-inside: avoid-column; } .d { - page-break-inside: avoid; - break-inside: avoid-page; + page-break-inside: avoid; + break-inside: avoid-page; } .e { - break-inside: avoid-region; + break-inside: avoid-region; } img { - image-rendering: crisp-edges; + image-rendering: crisp-edges; } img.other { - -ms-interpolation-mode: nearest-neighbor; - image-rendering: -webkit-optimize-contrast; - image-rendering: -moz-crisp-edges; - image-rendering: pixelated; + -ms-interpolation-mode: nearest-neighbor; + image-rendering: -webkit-optimize-contrast; + image-rendering: -moz-crisp-edges; + image-rendering: pixelated; } img.already { - -ms-interpolation-mode: nearest-neighbor; - display: block; - image-rendering: crisp-edges; - image-rendering: -webkit-optimize-contrast; - image-rendering: -moz-crisp-edges; - image-rendering: pixelated; + -ms-interpolation-mode: nearest-neighbor; + display: block; + image-rendering: crisp-edges; + image-rendering: -webkit-optimize-contrast; + image-rendering: -moz-crisp-edges; + image-rendering: pixelated; } diff --git a/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css b/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css index fb8818d..2660f05 100644 --- a/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css +++ b/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css @@ -31,6 +31,62 @@ a { transition: flex 200ms, -webkit-box-flex 200ms, -webkit-flex 200ms, -moz-box-flex 200ms, -ms-flex 200ms; } +.flex-direction:row { + flex-direction: row; +} + +.flex-direction:row-reverse { + flex-direction: row-reverse; +} + +.flex-direction:column { + flex-direction: column; +} + +.flex-direction:column-reverse { + flex-direction: column-reverse; +} + +.flex-direction:row { + flex-direction: row; +} + +.flex-direction:row-reverse { + flex-direction: row-reverse; +} + +.flex-direction:column { + flex-direction: column; +} + +.flex-direction:column-reverse { + flex-direction: column-reverse; +} + +.box-orient:vertical { + flex-direction: column; +} + +.box-orient:horizontal { + flex-direction: row; +} + +.box-orient { + -webkit-box-orient: error; +} + +.box-direction:normal { + flex-direction: row; +} + +.box-direction:reverse { + flex-direction: row-reverse; +} + +.box-direction { + -webkit-box-direction: error; +} + .inline { display: -webkit-inline-box; display: -webkit-inline-flex; diff --git a/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.css b/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.css index 01b8233..203c477 100644 --- a/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.css +++ b/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.css @@ -15,132 +15,161 @@ a { -webkit-transition: -webkit-box-flex 200ms, -webkit-flex 200ms; } -.inline { - -webkit-align-self: auto; - -ms-flex-item-align: auto; - -webkit-align-content: stretch; - -ms-flex-line-pack: stretch; - -moz-box-flex: 1; - -ms-flex: auto; -} - -.a { - -webkit-flex-direction: row; - -moz-box-orient: horizontal; - -moz-box-direction: normal; - -ms-flex-direction: row; - -webkit-justify-content: flex-start; - -moz-box-pack: start; - -ms-flex-pack: start; - -webkit-align-items: flex-start; - -moz-box-align: start; - -ms-flex-align: start; - -webkit-flex-wrap: nowrap; - -ms-flex-wrap: nowrap; - -webkit-align-content: flex-start; - -ms-flex-line-pack: start; - -webkit-align-self: flex-start; - -ms-flex-item-align: start; - -moz-box-flex: 0; - -ms-flex: none; -} - -.b { - -webkit-flex-direction: row-reverse; - -moz-box-orient: horizontal; - -moz-box-direction: reverse; - -ms-flex-direction: row-reverse; - -webkit-justify-content: flex-end; - -moz-box-pack: end; - -ms-flex-pack: end; - -webkit-align-items: flex-end; - -moz-box-align: end; - -ms-flex-align: end; - -webkit-flex-wrap: wrap; - -ms-flex-wrap: wrap; - -webkit-align-content: flex-end; - -ms-flex-line-pack: end; - -webkit-align-self: flex-end; - -ms-flex-item-align: end; - -webkit-flex-shrink: 1; - -ms-flex-negative: 1; -} - -.c { - -webkit-flex-direction: column; - -moz-box-orient: vertical; - -moz-box-direction: normal; - -ms-flex-direction: column; - -webkit-box-pack: center; - -webkit-justify-content: center; - -moz-box-pack: center; - -ms-flex-pack: center; - -webkit-box-align: center; - -webkit-align-items: center; - -moz-box-align: center; - -ms-flex-align: center; - -webkit-flex-wrap: reverse-wrap; - -ms-flex-wrap: reverse-wrap; - -webkit-align-content: center; - -ms-flex-line-pack: center; - -webkit-align-self: center; - -ms-flex-item-align: center; - -webkit-flex-basis: auto; - -ms-flex-preferred-size: auto; -} - -.e { - -webkit-flex-direction: column-reverse; - -moz-box-orient: vertical; - -moz-box-direction: reverse; - -ms-flex-direction: column-reverse; - -webkit-justify-content: space-between; - -moz-box-pack: justify; - -ms-flex-pack: justify; - -webkit-box-align: baseline; - -webkit-align-items: baseline; - -moz-box-align: baseline; - -ms-flex-align: baseline; - -webkit-align-content: space-between; - -ms-flex-line-pack: justify; - -webkit-align-self: baseline; - -ms-flex-item-align: baseline; -} - -.f { - -webkit-justify-content: space-around; - -ms-flex-pack: distribute; - -webkit-box-align: stretch; - -webkit-align-items: stretch; - -moz-box-align: stretch; - -ms-flex-align: stretch; - -webkit-align-content: space-around; - -ms-flex-line-pack: distribute; - -webkit-align-self: stretch; - -ms-flex-item-align: stretch; -} - -.g { - -moz-box-flex: calc(1em + 1px); - -ms-flex: calc(1em + 1px) 0 0; +a { + background: -webkit-linear-gradient(99.5deg, white, black), -webkit-linear-gradient(220deg, black, white), -webkit-linear-gradient(45deg, black, white); + background: -o-linear-gradient(99.5deg, white, black), -o-linear-gradient(220deg, black, white), -o-linear-gradient(45deg, black, white); + background: linear-gradient(350.5deg, white, black), linear-gradient(-130deg, black, white), linear-gradient(45deg, black, white); +} + +b { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 1)), to(white)), -webkit-gradient(linear, left top, left bottom, from(white), to(black)); + background-image: -webkit-linear-gradient(rgba(0, 0, 0, 1), white), -webkit-linear-gradient(white, black); + background-image: -o-linear-gradient(rgba(0, 0, 0, 1), white), -o-linear-gradient(white, black); + background-image: linear-gradient(rgba(0, 0, 0, 1), white), linear-gradient(white, black); +} + +strong { + background: -webkit-linear-gradient(bottom, transparent, rgba(0, 0, 0, 0.8) 20px, #000 30px, #000) no-repeat; + background: -o-linear-gradient(bottom, transparent, rgba(0, 0, 0, 0.8) 20px, #000 30px, #000) no-repeat; + background: linear-gradient(to top, transparent, rgba(0, 0, 0, 0.8) 20px, #000 30px, #000) no-repeat; +} + +div { + background-image: -webkit-radial-gradient(right, white, black), -webkit-repeating-linear-gradient(top left, black, white), -webkit-repeating-radial-gradient(bottom, aqua, red); + background-image: -o-radial-gradient(right, white, black), -o-repeating-linear-gradient(top left, black, white), -o-repeating-radial-gradient(bottom, aqua, red); + background-image: radial-gradient(to left, white, black), repeating-linear-gradient(to bottom right, black, white), repeating-radial-gradient(to top, aqua, red); +} + +.radial { + background: -webkit-radial-gradient(ellipse farthest-corner, black, white); + background: -o-radial-gradient(ellipse farthest-corner, black, white); + background: radial-gradient(ellipse farthest-corner, black, white); +} + +.simple1 { + background: -webkit-gradient(linear, left top, left bottom, from(black), to(white)); + background: -webkit-linear-gradient(black, white); + background: -o-linear-gradient(black, white); + background: linear-gradient(black, white); +} + +.simple2 { + background: -webkit-gradient(linear, right top, left top, from(black), color-stop(50%, rgba(0, 0, 0, 0.5)), to(white)); + background: -webkit-linear-gradient(right, black 0%, rgba(0, 0, 0, 0.5)50%, white 100%); + background: -o-linear-gradient(right, black 0%, rgba(0, 0, 0, 0.5)50%, white 100%); + background: linear-gradient(to left, black 0%, rgba(0, 0, 0, 0.5)50%, white 100%); +} + +.simple3 { + background: -webkit-gradient(linear, right top, left top, color-stop(50%, black), to(white)); + background: -webkit-linear-gradient(right, black 50%, white 100%); + background: -o-linear-gradient(right, black 50%, white 100%); + background: linear-gradient(to left, black 50%, white 100%); +} + +.simple4 { + background: -webkit-gradient(linear, left bottom, right top, from(black), to(white)); + background: -webkit-linear-gradient(left bottom, black, white); + background: -o-linear-gradient(left bottom, black, white); + background: linear-gradient(to right top, black, white); +} + +.direction { + background: -webkit-gradient(linear, left top, right bottom, from(black), color-stop(rgba(0, 0, 0, 0.5)), to(white)); + background: -webkit-linear-gradient(top left, black, rgba(0, 0, 0, 0.5), white); + background: -o-linear-gradient(top left, black, rgba(0, 0, 0, 0.5), white); + background: linear-gradient(top left, black, rgba(0, 0, 0, 0.5), white); +} + +.silent { + background: -webkit-linear-gradient(top left, black, white); +} + +.radial { + background: -webkit-radial-gradient(0 50%, farthest-side, white, black); + background: -o-radial-gradient(0 50%, farthest-side, white, black); + background: radial-gradient(farthest-side at 0 50%, white, black); +} + +.second { + background: red -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); + background: red -webkit-linear-gradient(red, blue); + background: red -o-linear-gradient(red, blue); + background: red linear-gradient(red, blue); + background: url('logo.png'), -webkit-gradient(linear, left top, left bottom, from(#fff), to(#000)); + background: url('logo.png'), -webkit-linear-gradient(#fff, #000); + background: url('logo.png'), -o-linear-gradient(#fff, #000); + background: url('logo.png'), linear-gradient(#fff, #000); +} + +.px { + background: -webkit-linear-gradient(black 0, white 100px); + background: -o-linear-gradient(black 0, white 100px); + background: linear-gradient(black 0, white 100px); +} + +.list { + list-style-image: -webkit-gradient(linear, left top, left bottom, from(white), to(black)); + list-style-image: -webkit-linear-gradient(white, black); + list-style-image: linear-gradient(white, black); +} + +.mask { + -webkit-mask: -webkit-gradient(linear, left top, left bottom, from(white), to(black)); + -webkit-mask: -webkit-linear-gradient(white, black); + mask: -webkit-gradient(linear, left top, left bottom, from(white), to(black)); + mask: linear-gradient(white, black); +} + +.newline { + background-image: -webkit-gradient(linear, left top, left bottom, from(white), to(black)), -webkit-gradient(linear, left top, left bottom, from(black), to(white)); + background-image: -webkit-linear-gradient(white, black), -webkit-linear-gradient(black, white); + background-image: -o-linear-gradient(white, black), -o-linear-gradient(black, white); + background-image: linear-gradient(white, black), linear-gradient(black, white); +} + +.convert { + background: -webkit-gradient(linear, right top, left top, from(white), to(black)); + background: -webkit-linear-gradient(right, white, black); + background: -o-linear-gradient(right, white, black); + background: linear-gradient(270deg, white, black); +} + +.rad { + background: -webkit-linear-gradient(32.704deg, white, black); + background: -o-linear-gradient(32.704deg, white, black); + background: linear-gradient(1rad, white, black); +} + +.turn { + background: -webkit-linear-gradient(342deg, white, black); + background: -o-linear-gradient(342deg, white, black); + background: linear-gradient(0.3turn, white, black); +} + +.norm { + background: -webkit-gradient(linear, right top, left top, from(white), to(black)); + background: -webkit-linear-gradient(right, white, black); + background: -o-linear-gradient(right, white, black); + background: linear-gradient(-90deg, white, black); } img { - image-rendering: crisp-edges; + image-rendering: crisp-edges; } img.other { - -ms-interpolation-mode: nearest-neighbor; - image-rendering: -webkit-optimize-contrast; - image-rendering: -moz-crisp-edges; - image-rendering: pixelated; + -ms-interpolation-mode: nearest-neighbor; + image-rendering: -webkit-optimize-contrast; + image-rendering: -moz-crisp-edges; + image-rendering: pixelated; } img.already { - -ms-interpolation-mode: nearest-neighbor; - display: block; - image-rendering: crisp-edges; - image-rendering: -webkit-optimize-contrast; - image-rendering: -moz-crisp-edges; - image-rendering: pixelated; + -ms-interpolation-mode: nearest-neighbor; + display: block; + image-rendering: crisp-edges; + image-rendering: -webkit-optimize-contrast; + image-rendering: -moz-crisp-edges; + image-rendering: pixelated; } diff --git a/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css b/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css index 0750508..978d930 100644 --- a/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css +++ b/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css @@ -12,114 +12,89 @@ a { transition: flex 200ms; } -.inline { - -webkit-align-self: auto; - -ms-flex-item-align: auto; - -webkit-align-content: stretch; - -ms-flex-line-pack: stretch; - -moz-box-flex: 1; - -ms-flex: auto; -} - -.a { - -webkit-flex-direction: row; - -moz-box-orient: horizontal; - -moz-box-direction: normal; - -ms-flex-direction: row; - -webkit-justify-content: flex-start; - -moz-box-pack: start; - -ms-flex-pack: start; - -webkit-align-items: flex-start; - -moz-box-align: start; - -ms-flex-align: start; - -webkit-flex-wrap: nowrap; - -ms-flex-wrap: nowrap; - -webkit-align-content: flex-start; - -ms-flex-line-pack: start; - -webkit-align-self: flex-start; - -ms-flex-item-align: start; - -moz-box-flex: 0; - -ms-flex: none; -} - -.b { - -webkit-flex-direction: row-reverse; - -moz-box-orient: horizontal; - -moz-box-direction: reverse; - -ms-flex-direction: row-reverse; - -webkit-justify-content: flex-end; - -moz-box-pack: end; - -ms-flex-pack: end; - -webkit-align-items: flex-end; - -moz-box-align: end; - -ms-flex-align: end; - -webkit-flex-wrap: wrap; - -ms-flex-wrap: wrap; - -webkit-align-content: flex-end; - -ms-flex-line-pack: end; - -webkit-align-self: flex-end; - -ms-flex-item-align: end; - -webkit-flex-shrink: 1; - -ms-flex-negative: 1; -} - -.c { - -webkit-flex-direction: column; - -moz-box-orient: vertical; - -moz-box-direction: normal; - -ms-flex-direction: column; - -webkit-box-pack: center; - -webkit-justify-content: center; - -moz-box-pack: center; - -ms-flex-pack: center; - -webkit-box-align: center; - -webkit-align-items: center; - -moz-box-align: center; - -ms-flex-align: center; - -webkit-flex-wrap: reverse-wrap; - -ms-flex-wrap: reverse-wrap; - -webkit-align-content: center; - -ms-flex-line-pack: center; - -webkit-align-self: center; - -ms-flex-item-align: center; - -webkit-flex-basis: auto; - -ms-flex-preferred-size: auto; -} - -.e { - -webkit-flex-direction: column-reverse; - -moz-box-orient: vertical; - -moz-box-direction: reverse; - -ms-flex-direction: column-reverse; - -webkit-justify-content: space-between; - -moz-box-pack: justify; - -ms-flex-pack: justify; - -webkit-box-align: baseline; - -webkit-align-items: baseline; - -moz-box-align: baseline; - -ms-flex-align: baseline; - -webkit-align-content: space-between; - -ms-flex-line-pack: justify; - -webkit-align-self: baseline; - -ms-flex-item-align: baseline; -} - -.f { - -webkit-justify-content: space-around; - -ms-flex-pack: distribute; - -webkit-box-align: stretch; - -webkit-align-items: stretch; - -moz-box-align: stretch; - -ms-flex-align: stretch; - -webkit-align-content: space-around; - -ms-flex-line-pack: distribute; - -webkit-align-self: stretch; - -ms-flex-item-align: stretch; -} - -.g { - -moz-box-flex: calc(1em + 1px); - -ms-flex: calc(1em + 1px) 0 0; +a { + background: linear-gradient(350.5deg, white, black), linear-gradient(-130deg, black, white), linear-gradient(45deg, black, white); +} + +b { + background-image: linear-gradient(rgba(0, 0, 0, 1), white), linear-gradient(white, black); +} + +strong { + background: linear-gradient(to top, transparent, rgba(0, 0, 0, 0.8) 20px, #000 30px, #000) no-repeat; +} + +div { + background-image: radial-gradient(to left, white, black), repeating-linear-gradient(to bottom right, black, white), repeating-radial-gradient(to top, aqua, red); +} + +.radial { + background: radial-gradient(ellipse farthest-corner, black, white); +} + +.simple1 { + background: linear-gradient(black, white); +} + +.simple2 { + background: linear-gradient(to left, black 0%, rgba(0, 0, 0, 0.5)50%, white 100%); +} + +.simple3 { + background: linear-gradient(to left, black 50%, white 100%); +} + +.simple4 { + background: linear-gradient(to right top, black, white); +} + +.direction { + background: linear-gradient(top left, black, rgba(0, 0, 0, 0.5), white); +} + +.silent { + background: linear-gradient(to bottom right, black, white); +} + +.radial { + background: radial-gradient(farthest-side at 0 50%, white, black); +} + +.second { + background: red linear-gradient(red, blue); + background: url('logo.png'), linear-gradient(#fff, #000); +} + +.px { + background: linear-gradient(black 0, white 100px); +} + +.list { + list-style-image: linear-gradient(white, black); +} + +.mask { + mask: linear-gradient(white, black); +} + +.newline { + background-image: linear-gradient(white, black), linear-gradient(black, white); +} + +.convert { + background: linear-gradient(270deg, white, black); +} + +.rad { + background: linear-gradient(1rad, white, black); +} + +.turn { + background: linear-gradient(0.3turn, white, black); +} + +.norm { + background: linear-gradient(-90deg, white, black); } img { From ffe94d08d85216c470cd4e8f0e0cba83d3e5fef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=A5=BA?= Date: Tue, 16 May 2017 10:55:53 +0800 Subject: [PATCH 5/7] use `postcss-unprefixer` --- .travis.yml | 2 +- lib/formatAtRules.js | 22 + lib/formatDecls.js | 48 +- lib/formatSelectors.js | 7 + lib/gradient.js | 515 ------------------ lib/unprefixer.js | 266 --------- package.json | 2 +- test/stylelint/no-vendor-prefix/.stylelintrc | 3 + .../no-vendor-prefix/no-vendor-prefix.css | 25 + .../no-vendor-prefix/no-vendor-prefix.out.css | 25 + .../property-no-vendor-prefix.out.css | 27 +- .../value-no-vendor-prefix.out.css | 1 - 12 files changed, 100 insertions(+), 843 deletions(-) delete mode 100644 lib/gradient.js delete mode 100644 lib/unprefixer.js diff --git a/.travis.yml b/.travis.yml index 439f0d9..b094e2c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,8 @@ sudo: false language: node_js node_js: - "stable" - - "4" - "6" + - "4" script: - npm run lint - npm test diff --git a/lib/formatAtRules.js b/lib/formatAtRules.js index ef7409c..86d5688 100644 --- a/lib/formatAtRules.js +++ b/lib/formatAtRules.js @@ -1,3 +1,5 @@ +var postcss = require('postcss') +var unprefixAtRule = require('postcss-unprefix/lib/clearAtRule') var formatAtRuleParams = require('./formatAtRuleParams') var formatDecls = require('./formatDecls') var getIndent = require('./getIndent') @@ -8,11 +10,31 @@ var util = require('./util') var getProperty = util.getProperty var getOptions = util.getOptions +function shouldClear (atrule, stylelint) { + if (postcss.vendor.prefix(atrule.name)) { + return getProperty(stylelint, 'at-rule-no-vendor-prefix') + } else if (atrule.name === 'media') { + return getProperty(stylelint, 'media-feature-name-no-vendor-prefix') && /\(\s*(?:-\w+-)?(?:\w+-)*device-pixel-ratio\b/.test(atrule.params) + } else if (atrule.name === 'supports') { + var propNoVendorPrefix = getProperty(stylelint, 'property-no-vendor-prefix') + var valueNoVendorPrefix = getProperty(stylelint, 'value-no-vendor-prefix') + return (propNoVendorPrefix && valueNoVendorPrefix) + || (propNoVendorPrefix && /\(\s*(?:-\w+){2,}\b/.test(atrule.params)) + || (propNoVendorPrefix && /\(\s*\w+[\w\-]+\s*\:[^()]*[\s,]?-\w+-/.test(atrule.params)) + } +} + function formatAtRules (root, params) { var stylelint = params.stylelint var indentWidth = params.indentWidth root.walkAtRules(function (atrule, index) { + if (shouldClear(atrule, stylelint)) { + unprefixAtRule(atrule) + if (!atrule.parent) { + return + } + } var parentType = atrule.parent.type var sassAtBlockTypes = [ diff --git a/lib/formatDecls.js b/lib/formatDecls.js index a103857..30e5dc4 100644 --- a/lib/formatDecls.js +++ b/lib/formatDecls.js @@ -1,6 +1,7 @@ var formatValues = require('./formatValues') var hasDecls = require('./hasDecls') -var unprefixer = require('./unprefixer') +var postcss = require('postcss') +var unprefixDecl = require('postcss-unprefix/lib/clearDecl') var hasEmptyLine = require('stylelint/lib/utils/hasEmptyLine') var isStandardSyntaxDeclaration = require('stylelint/lib/utils/isStandardSyntaxDeclaration') var isCustomProperty = require('stylelint/lib/utils/isCustomProperty') @@ -8,48 +9,19 @@ var util = require('./util') var getProperty = util.getProperty var getOptions = util.getOptions var isSingleLineString = require('stylelint/lib/utils/isSingleLineString') -var postcss = require('postcss') function formatDecls (rule, indent, indentWidth, stylelint) { - var propNoVendorPrefix - var valueNoVendorPrefix - function clearPrefixedDecl (decl) { - var prop = postcss.vendor.unprefixed(decl.prop) - var prefixedDecls = [] - var unprefixed - var lastUnprefixed - - rule.walkDecls(new RegExp('^-\\w+-' + prop + '$'), function (decl) { - prefixedDecls.push(decl) - }) - - rule.walkDecls(unprefixer(decl).prop || prop, function (decl) { - lastUnprefixed = unprefixer(decl) - if (lastUnprefixed.value) { - prefixedDecls.push(decl) - } else { - unprefixed = decl - } - }) - - if (!unprefixed) { - var lastDecl = prefixedDecls.pop(); - (lastUnprefixed || unprefixer(lastDecl)).replace() - } - - prefixedDecls.forEach(function (decl) { - if ((propNoVendorPrefix && valueNoVendorPrefix) || (propNoVendorPrefix && decl.prop[0] === '-') || (valueNoVendorPrefix && /(^|,|\s)-\w+-.+/.test(decl.value))){ - decl.remove() - } - }) - } const isSingleLine = isSingleLineString(rule) if (hasDecls(rule)) { - propNoVendorPrefix = getProperty(stylelint, 'property-no-vendor-prefix') - valueNoVendorPrefix = getProperty(stylelint, 'value-no-vendor-prefix') + var propNoVendorPrefix = getProperty(stylelint, 'property-no-vendor-prefix') + var valueNoVendorPrefix = getProperty(stylelint, 'value-no-vendor-prefix') + rule.walkDecls(function (decl) { - if ((propNoVendorPrefix && /^-\w+-(.+)$/.test(decl.prop)) || (valueNoVendorPrefix && /(^|,|\s)-\w+-.+/.test(decl.value))) { - clearPrefixedDecl(decl) + if ((propNoVendorPrefix && valueNoVendorPrefix) + || (propNoVendorPrefix && postcss.vendor.prefix(decl.prop)) + || (valueNoVendorPrefix && /(?:^|,|\s)-\w+-/m.test(decl.value))) + { + unprefixDecl(decl) if (!decl.parent) { return } diff --git a/lib/formatSelectors.js b/lib/formatSelectors.js index 1f3a97e..fa1c225 100644 --- a/lib/formatSelectors.js +++ b/lib/formatSelectors.js @@ -1,5 +1,12 @@ +var unprefixRule = require('postcss-unprefix/lib/clearRule') var getProperty = require('./util').getProperty function formatSelectors (rule, indentation, stylelint) { + if (/\:+-\w+-/.test(rule.selector)) { + unprefixRule(rule) + if (!rule.parent) { + return + } + } var tmp = [] var isSingleLine = false diff --git a/lib/gradient.js b/lib/gradient.js deleted file mode 100644 index 7d2e894..0000000 --- a/lib/gradient.js +++ /dev/null @@ -1,515 +0,0 @@ -'use strict' - -var postcss = require('postcss') -var valueParser = require('postcss-value-parser') - -// 老式方向关键字转换 -var directionMap = { - 'top': 'bottom', - 'bottom': 'top', - 'left': 'right', - 'right': 'left', -} - -// 需要转换的旧关键字 -var keyWordMap = { - cover: 'farthest-corner', - contain: 'closest-side', -} - -// 各种角度单位与deg之间的换算关系 https://developer.mozilla.org/zh-CN/docs/Web/CSS/angle -var angleUnitMap = { - grad: 400, - rad: 2 * Math.PI, - turn: 1, -} - -// 各种长度单位与deg之间的换算关系 https://developer.mozilla.org/zh-CN/docs/Web/CSS/length -var lengthUnitMap = { - '%': 1, - 'in': 96, - ch: 6, - cm: 37.79527559055118, - em: 12, - ex: 5.4376, - mm: 3.7795275590551185, - pc: 16, - pt: 1.3333333333333333, - q: 0.9448818897637796, - rem: 16, - vh: 960, - vm: 640, - vmax: 960, - vmin: 640, - vw: 640, -} - -// 角度转为关键字 -var degMap = { - 0: 'top', - 90: 'right', - 180: 'bottom', - 270: 'left', -} - -/** - * 将字符串转为数字与其单位 - * @param {String} string 含有数字的字符串 - * @returns {Float} num 解析好的数字 - * @returns {Float} unit 原有的单位 - */ -function parseNum (string) { - var unit - var num = parseFloat(string.replace(/(\D+)$/, function (s) { - unit = s - return '' - })) - if (!isNaN(num)) { - return { - num: num, - unit: unit || '', - } - } -} - -/** - * 将字符串转为px为单位长度数值 - * @param {String} string 含有长度信息的字符串 - * @return {Float} 换算成像素的数值 - */ -function parseLength (string) { - var value = parseNum(string) - if (value) { - if (value.num === 0 || !value.unit || value.unit === 'px') { - // 没有长度单位,或数值为0,或长度单位为像素,则无需换算 - return value.num - } else if (lengthUnitMap[value.unit]) { - // 不同长度单位间的换算 - return value.num * lengthUnitMap[value.unit] - } - } -} - -/** - * 将字符串转为长度与其单位 - * @param {String} string 含有数字的字符串 - * @returns {Float} deg 换算成度的数字 - * @returns {Float} num 解析好的数字 - * @returns {Float} unit 原有的单位 - */ -function parseAngle (string) { - var value = parseNum(string) - if (value) { - if (value.num === 0 || !value.unit || value.unit === 'deg') { - // 没有角度单位,或数值为0,或角度单位为度,则无需换算 - value.deg = value.num - } else if (angleUnitMap[value.unit]) { - // 不同角度单位间的换算 - value.deg = value.num * 360 / angleUnitMap[value.unit] - } else { - return - } - // 修正为w3c语法的角度。0°为上方而非右方 - value.deg = require('normalize-range').wrap(0, 360, 90 - value.deg) - return value - } -} - -/** - * 将解析后的数字对象转换为字符串 - * @param {Object} angleObj 数字对象 - * @param {Object} angleObj.deg 以度为单位的角度 - * @param {Object} angleObj.unit 希望使用的单位 - * @return {String} 按格式输出的字符串 - */ -function angle2String (angleObj) { - var deg = angleObj.deg - if (angleObj.unit && angleObj.unit !== 'deg') { - // 单位不为度是,需要换算 - deg = (deg * angleUnitMap[angleObj.unit] / 360) - } - - // 修正浮点数精度 - deg = parseFloat(deg.toFixed(4)) - if (deg === 0) { - // 结果等于0时,直接转换为字符串输出,不要单位 - deg = '0' - } else { - // 结果不为0时,补上单位 - deg += angleObj.unit || 'deg' - } - return deg -} - -/** - * 分析css参数中的坐标信息 - * @param {String[]} args 包含坐标信息的两个字符串组成的数组 - * @returns {Int} x [x轴坐标] - * @returns {Int} y [y轴坐标] - */ -function normalizePos (args) { - var point = {} - args.forEach(function (arg, i) { - if (arg === 'top') { - point.y = 0 - } else if (arg === 'right') { - point.x = 100 - } else if (arg === 'bottom') { - point.y = 100 - } else if (arg === 'left') { - point.x = 0 - } else { - // 将长度单位转换为坐标 - point[i ? 'y' : 'x'] = parseLength(arg) - } - }) - return point -} - -/** - * 将长度字符串转换为以px为单位的字符串 - * @param {String} val 表示长度的css表达式字符串 - * @return {String} 以px为单位的数字字符串 - */ -function px (val) { - try { - val = parseFloat(parseLength(val).toFixed(4)) - if (val === 0) { - return '0' - } else { - return val + 'px' - } - } catch (ex) { - return val - } -} - -/** - * `-webkit-gradient(linear, `根据参数位置与尺寸,返回修正顺序与语法的这两个参数 - * @param {Array} args -webkit-gradient的参数,去除第一个参数type和所有color-stop - * @return {Array} `[ '90px', 'at', '0px', '150px' ]` - */ -function fixOldRadialGradient (args) { - var position = args[0] - if (position && position[0] && position[1]) { - // 第一个参数为坐标,则将这个参数中的值的单位转换为px - position = position.map(px) - // 在坐标参数最前面添加`at`关键字 - position.unshift('at') - - var size = args[3] && args[3][0] - if (size != null) { - // 将尺寸信息加入结果集 - position.unshift(px(size)) - } - // 返回结果 - return position - } -} - -/** - * `-webkit-gradient(linear, `根据传入的参数计算角度,返回角度参摄 - * @param {Array} args -webkit-gradient的参数,去除第一个参数type和所有color-stop - * @return {String|undefined} 角度值表达式,当角度正好180°时,返回undefined - */ -function fixOldLinearGradient (args) { - var angle - // 从args[0]中获取起始点信息 - var start = normalizePos(args[0]) - // 从args[1]中获取终止点信息 - var end = normalizePos(args[1]) - - - // 根据起始点和终止点计算角度 - angle = 180 - Math.atan2(end.x - start.x, end.y - start.y) * (180 / Math.PI) - // 将角度进行坐标系变换 - angle = require('normalize-range').wrap(0, 360, angle) - // 如果角度不等于180°,将其转换为字符串后返回 - if (angle !== 180) { - angle = angle2String({ - deg: angle, - }) - return angle - } -} - -/** - * `-webkit-gradient`转`radial-gradient`或`linear-gradient` - * @param {Array} args 修正前的参数 - * @param {Node} gradient 原始的node对象 - * @return {Array} 修正后的参数 - */ -function fixOldGradient (args, gradient) { - var type = args[0][0] - var colorStops = [] - var from - var to - - // 将参数中的`color-stop`,`from`,`to`三种信息剔除出args并单独存放,剩下的存起来 - args = args.slice(1).filter(function (arg) { - var fnName = arg.value - if (fnName === 'from') { - from = arg - } else if (fnName === 'to') { - to = arg - } else if (fnName === 'color-stop') { - colorStops.push(arg) - } else { - return true - } - return false - }) - - if (from) { - // 将from信息放入colorStops头部 - colorStops.unshift(from) - } - if (to) { - // 将from信息放入colorStops尾部 - colorStops.push(to) - } - - // 将数组colorStops中的元素都转换为标准形式 - colorStops = colorStops.map(function parseColorStop (colorStop, i) { - // 获取colorStop的参数 - colorStop = colorStop.nodes - // 如果不知一个参数 - if (colorStop.length > 1) { - // 计算位置信息的浏览器默认值 - var posVal = i * 100 / (colorStops.length - 1) - colorStop = colorStop.filter(function (val) { - // 如果位置信息与浏览器默认值相同,去除它 - return parseFloat(val) !== posVal - }) - - if (colorStop.length > 1) { - // 参数重新排列,位置信息放在后面,以便符合新语法 - colorStop.sort(function (word) { - return isNaN(parseFloat(word)) ? -1 : 1 - }) - } - } - return colorStop - }) - - if (type === 'radial') { - // 按照圆形渐变语法处理剩下的参数 - args = fixOldRadialGradient(args) - } else { - // 按照线性渐变语法处理剩下的参数 - args = fixOldLinearGradient(args) - } - - if (args && args.length) { - // 将`fixOldRadialGradient`或`fixOldLinearGradient`的返回结果插入colorStops - colorStops.unshift(args) - } - // 将css属性名名称转换为标准的 - gradient.value = type + '-gradient' - return colorStops -} - -/** - * 修正`linear-gradient`的参数 - * @param {Array} args linear-gradient的所有参数 - * @return {Array} 修正后的参数 - */ -function fixLinearGradient (args) { - var angle = parseAngle(args[0][0]) - - if (angle) { - // 如果第一参数是角度,修正角度 - var deg = Math.round(angle.deg) - if (deg === 180) { - // 180°正是浏览器默认值,所以抛弃,减少生成的css的体积 - args.shift() - } else { - if (degMap[deg]) { - // 如果角度是0、90、180、270等特殊值,将第一参变为方位信息 - args[0] = ['to', degMap[deg]] - } else { - // 其他角度值,直接转换第一参即可 - args[0] = angle2String(angle) - } - } - } else { - var position - // 遍历第一参中的值, - args[0].forEach(function (arg, i) { - if (directionMap[arg]) { - // 将top、left、bottom、right取反义词,并记录position - args[0][i] = directionMap[arg] - position = args[0] - } - }) - if (position) { - if (position.length === 1 && position[0] === 'bottom') { - // `to bottom`正是浏览器默认值,所以抛弃,减少生成的css的体积 - args.shift() - } else { - // 将方位信息最前面添加一个"to"二级参数 - position.unshift('to') - } - } - } - - return args -} - -/** - * 圆形渐变处理 - * @param {Array} args linear-gradient的所有参数 - * @return {Array} 修正后的参数 - */ -function fixRadialGradient (args) { - - var firstArg = [] - var position - - // 分析所有参数,将坐标参数和关键字剔除出args并单独保存 - args = args.filter(function (subArg) { - var hasKeyWord - subArg.forEach(function (word, i) { - if (keyWordMap[word]) { - // 查找需要转换的关键字 - subArg[i] = keyWordMap[word] - hasKeyWord = true - } else if (/^(?:circle|ellipse|\w+-\w+)$/.test(word)) { - // 查找是否有其他的关键字 - hasKeyWord = true - } - }) - if (hasKeyWord) { - // subArg中如果有关键字,将它存入firstArg - firstArg = firstArg.concat(subArg) - return false - } else if (subArg.every(function (word) { - return word === 'center' || directionMap[word] || parseNum(word) - })) { - // 如果subArg是坐标信息将它存入position - position = subArg - return false - } - return true - }) - - if (position) { - // 在坐标参数最前面添加`at`关键字 - position.unshift('at') - firstArg = firstArg.concat(position) - } - - if (firstArg.length) { - // 如果收集到了firstArg,将其加入args的最前面 - args.unshift(firstArg) - } - - return args -} - -/** - * `radial-gradient`或`linear-gradient`去前缀并转换语法 - * @param {Node} gradient `postcss-value-parser`插件转换后的-webkit-gradient - * @param {String} type `radial`或`linear` - * @return {Array} 修正后的参数 - */ -function fixGradient (gradient, type) { - if (type === 'radial') { - // 圆形渐变处理 - return fixRadialGradient(gradient) - } else { - // 线性渐变处理 - return fixLinearGradient(gradient) - } -} - -/** - * 将语法树中的function节点转换为便于处理的形式 - * 返回值二维数组 - * @param {Node} node 语法树节点,type必须为function - * @return {Array} 二维数组 - */ -function parseFunction (node) { - var args = [] - var index = 0 - node.nodes.forEach(function (subNode) { - if (subNode.type === 'div' && subNode.value === ',') { - // 遇到`,`下标自加1 - index++ - return - } else if (subNode.type === 'function') { - // 将参数中的`color-stop`,`from`,`to`三种function特殊处理 - if ((subNode.value === 'from' || subNode.value === 'to' || subNode.value === 'color-stop')) { - var colorStop = subNode.nodes.filter(function (colorStopInfo) { - // colorStop的子节点,除function和word外,都丢去 - return colorStopInfo.type === 'function' || colorStopInfo.type === 'word' - }).map(function (colorStopInfo) { - // colorStop的子节点,转换为字符串 - return valueParser.stringify(colorStopInfo) - }) - - // 组装新的对象传递出去 - colorStop = { - nodes: colorStop, - type: 'function', - value: subNode.value, - } - - // 不使用第三个数组维度,而是将其存在最上面的维度上 - return args[index] = colorStop - } - } else if (subNode.type !== 'word') { - return - } - - if (!args[index]) { - // 如果未初始化该数组维度,对其初始化 - args[index] = [] - } - // 未特殊处理的function,还有普通的word,将其转字符串 - args[index].push(valueParser.stringify(subNode)) - }) - // 返回转换后的数组 - return args -} - -// 将二维数组降维,并转换为字符串 -function stringifyArg (arg) { - if (Array.isArray(arg)) { - // 递归方式处理数组的更高维度 - return arg.map(stringifyArg).join(' ') - } else { - return String(arg) - } -} - -/** - * 将二维数组作为参数,重写type为function的语法树节点,type会变为word - * @param {Node} gradient 语法树节点 - * @param {Node} args 修正后的参数 - * @return {Node} 语法树节点 - */ -function stringifyGradient (gradient, args) { - // 将参数还原成节点 - gradient.value = gradient.value + '(' + args.map(stringifyArg).join(', ') + ')' - gradient.type = 'word' - delete gradient.nodes -} - -module.exports = function (node) { - if (node.type === 'function') { - if (/^-\w+-gradient$/.test(node.value)) { - // 修复老式webkit语法的gradient - stringifyGradient(node, fixOldGradient(parseFunction(node), node)) - } else if (/^-\w+-(?:\w+-)?(\w+)-gradient$/.test(node.value)) { - var type = RegExp.$1 - // 修复gradient的前缀 - node.value = postcss.vendor.unprefixed(node.value) - // 修复gradient的值 - stringifyGradient(node, fixGradient(parseFunction(node), type)) - } else { - return - } - return node - } -} diff --git a/lib/unprefixer.js b/lib/unprefixer.js deleted file mode 100644 index 8253e16..0000000 --- a/lib/unprefixer.js +++ /dev/null @@ -1,266 +0,0 @@ -'use strict' - -const postcss = require('postcss') -const autoprefixer = require('autoprefixer') -const valueParser = require('postcss-value-parser') - -function valMap (reg, prop, valMapData) { - return function valMap (decl) { - if (reg.test(decl.prop)) { - var value = postcss.vendor.unprefixed(decl.value) - if (valMapData[value]) { - return { - prop: prop, - value: valMapData[value], - } - } - } - } -} - -function brotherFirst (reg, brotherProp) { - return function brotherFirst (decl) { - if (reg.test(decl.prop)) { - var brother = getBrotherDecl(decl, brotherProp) - if (brother) { - return unprefixDecl(brother) - } - } - } -} - -function getBrotherDecl (decl, prop){ - var result - decl.parent.walkDecls(prop, function (decl){ - result = decl - }) - return result -} - -const RE_BOX_DIRECTION = /^(?:-\w+-)?(?:flex)?box-direction$/i -const RE_BOX_ORIENT = /^(?:-\w+-)?(?:flex)?box-orient$/i -const RE_FLEX_FLOW = /^(?:-\w+-)?flex-flow$/i -const RE_ORDER = /^(?:-\w+-)?order$/i - -const declUnprefixers = [ - valMap(/^(?:-\w+-)?(?:flex)?box-direction$/i, 'flex-direction', { - 'lr': 'row', - 'rl': 'row-reverse', - 'tb': 'column', - 'bt': 'column-reverse' - }), - valMap(/^(?:(?:-\w+-)?(?:flex)?box|-ms-flex)-pack$/i, 'justify-content', { - 'start': 'flex-start', - 'end': 'flex-end', - 'justify': 'space-between' - }), - brotherFirst(/^(?:-\w+-)?box-flex$/i, /^(?:-\w+-)?flex$/i), - brotherFirst(/^(?:-\w+-)?box-ordinal-group$/i, RE_ORDER), - brotherFirst(/^-ms-flex-order$/i, RE_ORDER), - brotherFirst(RE_BOX_ORIENT, RE_FLEX_FLOW), - brotherFirst(RE_BOX_DIRECTION, RE_FLEX_FLOW), - function alignItems (decl) { - if (/^(?:-\w+-)?(?:flex)?box-align$/i.test(decl.prop) || /^-ms-flex-align$/i.test(decl.prop)) { - return { - prop: 'align-items', - value: decl.value.replace(/^(?:-\w+-)?(start|end)$/, 'flex-$1') - } - } - }, - function breakInside (decl) { - if (/^(?:-\w+-)?(\w+)-break-(\w+)/i.test(decl.prop)) { - return { - prop: 'break-' + RegExp.$2, - value: decl.value === 'avoid' ? RegExp.$1 + '-avoid' : decl.value, - } - } - }, - function interpolationMode (decl) { - if (/^-ms-interpolation-mode$/i.test(decl.prop) && /^nearest-neighbor$/i.test(decl.value)) { - return { - prop: 'image-rendering', - value: 'pixelated', - } - } - }, - function boxOrient (decl) { - if (RE_BOX_ORIENT.test(decl.prop)) { - var boxOrient = { - horizontal: 'row', - vertical: 'column', - }[decl.value.toLowerCase()] - - if (!boxOrient) { - return - } - var boxDirection = getBrotherDecl(decl, RE_BOX_DIRECTION) - if (boxDirection && boxDirection.value === 'reverse') { - boxDirection = '-reverse' - } else { - boxDirection = '' - } - return { - prop: 'flex-direction', - value: boxOrient + boxDirection - } - } - }, - function boxDirection (decl) { - if (RE_BOX_DIRECTION.test(decl.prop)) { - var boxDirection = decl.value.toLowerCase() - if (boxDirection === 'reverse') { - boxDirection = '-reverse' - } else if (boxDirection === 'normal') { - boxDirection = '' - } else { - return - } - - var boxOrient = getBrotherDecl(decl, RE_BOX_ORIENT) - if (boxOrient && boxOrient.value === 'vertical') { - boxOrient = 'column' - } else { - boxOrient = 'row' - } - - return { - prop: 'flex-direction', - value: boxOrient + boxDirection - } - } - }, -] - -const PREFIXED_PROP_NAME_MAP = { - '-ms-flex-positive': 'flex-grow', - '-ms-grid-column-align': 'grid-row-align', - '-ms-grid-column-span': 'grid-column', - '-ms-grid-columns': 'grid-template-columns', - '-ms-grid-row-span': 'grid-row-end', - '-ms-grid-rows': 'grid-template-rows', - '-ms-flex-item-align': 'align-self', - '-ms-flex-pack': 'justify-content', - '-ms-flex-line-pack': 'align-content', - '-ms-flex-preferred-size': 'flex-basis', - '-ms-flex-negative': 'flex-shrink' -} - -const PROP_NAME_MAP = { - 'border-radius-bottomleft': 'border-bottom-left-radius', - 'border-radius-bottomright': 'border-bottom-right-radius', - 'border-radius-topleft': 'border-top-left-radius', - 'border-radius-topright': 'border-top-right-radius', - - 'border-after': 'border-block-end', - 'border-before': 'border-block-start', - 'border-end': 'border-inline-end', - 'border-start': 'border-inline-start', - - 'margin-after': 'margin-block-end', - 'margin-before': 'margin-block-start', - 'margin-end': 'margin-inline-end', - 'margin-start': 'margin-inline-start', - - 'padding-after': 'padding-block-end', - 'padding-before': 'padding-block-start', - 'padding-end': 'padding-inline-end', - 'padding-start': 'padding-inline-start', - - 'mask-box-image': 'mask-border', - 'mask-box-image-outset': 'mask-border-outset', - 'mask-box-image-repeat': 'mask-border-repeat', - 'mask-box-image-slice': 'mask-border-slice', - 'mask-box-image-source': 'mask-border-source', - 'mask-box-image-width': 'mask-border-width', - - 'box-align': 'align-items', - 'box-pack': 'justify-content', - // 'box-ordinal-group': 'order', - // 'box-flex': 'flex', -} - -const valueUnprefixers = [ - function imageRendering (node, prop) { - if (/^(?:-\w+-)?image-rendering/i.test(prop) && /^-\w+-/i.test(node.value)) { - if (/^-\w+-optimize-contrast$/i.test(node.value)) { - node.value = 'crisp-edges' - } else { - node.value = postcss.vendor.unprefixed(node.value) - } - return node - } - }, - function displayFlex (node, prop) { - if (/^(?:-\w+-)?display$/i.test(prop) && /^(?:-\w+-)?(inline-)?((?:flex)?(?:box)?)$/i.test(node.value) && RegExp.$2) { - node.value = RegExp.$1 + 'flex' - return node - } - }, - require('./gradient'), - function unprefixPropInValue (node, prop) { - if (/^^(?:-\w+-)?transition(?:-property)?$/.test(prop) || node.type === 'function') { - var prefixed = unprefixProp(node.value) - if (prefixed) { - node.value = prefixed - return node - } - } - }, -] - -function unprefixProp (prop) { - if (PREFIXED_PROP_NAME_MAP[prop]){ - return PREFIXED_PROP_NAME_MAP[prop] - } - prop = postcss.vendor.unprefixed(prop) - if (autoprefixer.data.prefixes[prop]) { - return prop - } - if (PROP_NAME_MAP[prop]){ - return PROP_NAME_MAP[prop] - } -} - -function unprefixValue (value, prop) { - var fixed - value = valueParser(value) - value.nodes.forEach(function (node) { - if (node.type !== 'div' && /^-\w+-/i.test(node.value) && valueUnprefixers.some(function (unprefixer) { - return unprefixer(node, prop) - })) { - fixed = true - } - }) - if (fixed){ - return valueParser.stringify(value).replace(/(.+?)(\s*,\s*\1)+/g, '$1') - } -} - -function unprefixDecl (decl) { - var result - if (declUnprefixers.some(function (unprefixer) { - result = unprefixer(decl) - return result - })) { - return result - } - result = {} - result.prop = unprefixProp(decl.prop) - result.value = unprefixValue(decl.value, decl.prop) - return result -} - -function unprefix (decl) { - var result = unprefixDecl (decl) - result.replace = function (){ - if (result.prop) { - decl.prop = result.prop - } - if (result.value) { - decl.value = result.value - } - } - return result -} - -module.exports = unprefix diff --git a/package.json b/package.json index 0a3d7f3..75ba8d9 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,6 @@ "author": "Masaaki Morishita", "license": "MIT", "dependencies": { - "autoprefixer": "^6.7.7", "chalk": "^1.1.3", "css-color-list": "0.0.1", "diff": "^3.1.0", @@ -61,6 +60,7 @@ "postcss": "^5.2.5", "postcss-scss": "^0.4.0", "postcss-sorting": "^2.0.1", + "postcss-unprefix": "^2.1.0", "postcss-value-parser": "^3.3.0", "stdin": "0.0.1", "stylelint": "^7.5.0", diff --git a/test/stylelint/no-vendor-prefix/.stylelintrc b/test/stylelint/no-vendor-prefix/.stylelintrc index 3c0a393..b9792de 100644 --- a/test/stylelint/no-vendor-prefix/.stylelintrc +++ b/test/stylelint/no-vendor-prefix/.stylelintrc @@ -1,6 +1,9 @@ { "rules": { + "at-rule-no-vendor-prefix": true, + "media-feature-name-no-vendor-prefix": true, "property-no-vendor-prefix": true, + "selector-no-vendor-prefix": true, "value-no-vendor-prefix": true } } diff --git a/test/stylelint/no-vendor-prefix/no-vendor-prefix.css b/test/stylelint/no-vendor-prefix/no-vendor-prefix.css index f0dbb03..86e7c43 100644 --- a/test/stylelint/no-vendor-prefix/no-vendor-prefix.css +++ b/test/stylelint/no-vendor-prefix/no-vendor-prefix.css @@ -432,3 +432,28 @@ div { width: -webkit-calc(100% - 1em); width: -moz-calc(100% - 1em); } + +input::-moz-placeholder { +} + +:-webkit-full-screen a { +} + +@media (-webkit-min-device-pixel-ratio: 1) { +} + +@media (min--mox-device-pixel-ratio: 1) { +} + +@media (-o-max-device-pixel-ratio: 1/1) { +} + +@-webkit-keyframes { + 0% { + top: 0; + } +} + +@-ms-viewport { + orientation: landscape; +} diff --git a/test/stylelint/no-vendor-prefix/no-vendor-prefix.out.css b/test/stylelint/no-vendor-prefix/no-vendor-prefix.out.css index d198721..3f84413 100644 --- a/test/stylelint/no-vendor-prefix/no-vendor-prefix.out.css +++ b/test/stylelint/no-vendor-prefix/no-vendor-prefix.out.css @@ -215,3 +215,28 @@ div { div { width: calc(100% - 1em); } + +input::placeholder { +} + +:fullscreen a { +} + +@media (min-resolution: 1dppx) { +} + +@media (min--mox-device-pixel-ratio: 1) { +} + +@media (max-resolution: 1dppx) { +} + +@keyframes { + 0% { + top: 0; + } +} + +@viewport { + orientation: landscape; +} diff --git a/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css b/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css index 2660f05..22c99d3 100644 --- a/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css +++ b/test/stylelint/property-no-vendor-prefix/property-no-vendor-prefix.out.css @@ -18,17 +18,11 @@ h1 { } a { - display: -webkit-box; - display: -webkit-flex; - display: -moz-box; - display: -ms-flexbox; display: flex; flex-flow: row; order: 0; flex: 0 1 2; - transition: -webkit-box-flex 200ms, -webkit-flex 200ms; transition: flex 200ms; - transition: flex 200ms, -webkit-box-flex 200ms, -webkit-flex 200ms, -moz-box-flex 200ms, -ms-flex 200ms; } .flex-direction:row { @@ -40,11 +34,11 @@ a { } .flex-direction:column { - flex-direction: column; + flex-direction: row; } .flex-direction:column-reverse { - flex-direction: column-reverse; + flex-direction: row-reverse; } .flex-direction:row { @@ -52,7 +46,7 @@ a { } .flex-direction:row-reverse { - flex-direction: row-reverse; + flex-direction: row; } .flex-direction:column { @@ -60,7 +54,7 @@ a { } .flex-direction:column-reverse { - flex-direction: column-reverse; + flex-direction: column; } .box-orient:vertical { @@ -72,7 +66,7 @@ a { } .box-orient { - -webkit-box-orient: error; + flex-direction: row; } .box-direction:normal { @@ -84,7 +78,7 @@ a { } .box-direction { - -webkit-box-direction: error; + flex-direction: row; } .inline { @@ -190,21 +184,16 @@ a { } .a { - page-break-inside: auto; break-inside: auto; - page-break-before: auto; break-before: auto; - page-break-after: auto; break-after: auto; } .b { - page-break-inside: avoid; break-inside: avoid; } .c { - page-break-inside: avoid; break-inside: avoid-column; } @@ -222,15 +211,11 @@ img { } img.other { - image-rendering: -webkit-optimize-contrast; - image-rendering: -moz-crisp-edges; image-rendering: pixelated; } img.already { display: block; image-rendering: crisp-edges; - image-rendering: -webkit-optimize-contrast; - image-rendering: -moz-crisp-edges; image-rendering: pixelated; } diff --git a/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css b/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css index 978d930..4b769b8 100644 --- a/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css +++ b/test/stylelint/value-no-vendor-prefix/value-no-vendor-prefix.out.css @@ -1,5 +1,4 @@ a { - -js-display: flex; display: flex; -webkit-flex-flow: row; -ms-flex-flow: row; From c31832a507b10d2c76d43bf4e0d9f106f735dcb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=A5=BA?= Date: Tue, 16 May 2017 11:04:12 +0800 Subject: [PATCH 6/7] update `.travis.yml` --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b094e2c..6e53823 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,3 @@ node_js: - "stable" - "6" - "4" -script: - - npm run lint - - npm test From e9e26d5e799422067dbabe5a5ed57d93f39b3868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=A5=BA?= Date: Sat, 27 May 2017 14:52:49 +0800 Subject: [PATCH 7/7] install nyc & update postcss-unprefixer --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 2f3ee82..fea5d2b 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "postcss": "^6.0.1", "postcss-scss": "^1.0.0", "postcss-sorting": "^2.1.0", - "postcss-unprefix": "^2.1.0", + "postcss-unprefix": "^2.1.1", "postcss-value-parser": "^3.3.0", "stdin": "^0.0.1", "stylelint": "^7.10.1", @@ -71,6 +71,7 @@ "eslint": "^3.19.0", "faucet": "^0.0.1", "klaw": "^1.3.1", + "nyc": "^10.3.2", "tape": "^4.6.3" } }