├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .npmignore ├── .stylelintrc ├── .travis.yml ├── LICENSE ├── README.md ├── lib ├── clearAtRule.js ├── clearDecl.js ├── clearRule.js ├── index.js ├── unprefix.js ├── unprefixBreakInside.js ├── unprefixFlexDirection.js ├── unprefixGradient.js ├── unprefixMsGrid.js ├── unprefixParam.js ├── unprefixSelector.js └── util.js ├── package.json └── test ├── fixtures ├── 3d-transform.css ├── 3d-transform.out.css ├── advanced-filter.css ├── advanced-filter.out.css ├── appearance.css ├── appearance.out.css ├── background-clip.css ├── background-clip.out.css ├── background-size.css ├── background-size.out.css ├── border-image.css ├── border-image.out.css ├── border-radius.css ├── border-radius.less ├── border-radius.out.css ├── border-radius.out.less ├── box-shadow.css ├── box-shadow.out.css ├── cascade.css ├── cascade.out.css ├── check-down.css ├── check-down.out.css ├── comments.css ├── comments.out.css ├── cross-fade.css ├── cross-fade.out.css ├── custom-prefix.css ├── custom-prefix.out.css ├── disabled.css ├── disabled.out.css ├── double.css ├── double.out.css ├── element.css ├── element.out.css ├── example.css ├── example.out.css ├── filter.css ├── filter.out.css ├── flex-rewrite.css ├── flex-rewrite.out.css ├── flexbox.css ├── flexbox.out.css ├── fullscreen.css ├── fullscreen.out.css ├── gradient-fix.css ├── gradient-fix.out.css ├── gradient.css ├── gradient.out.css ├── grid.css ├── grid.out.css ├── image-rendering.css ├── image-rendering.out.css ├── image-set.css ├── image-set.out.css ├── intrinsic.css ├── intrinsic.out.css ├── keyframes.css ├── keyframes.out.css ├── logical.css ├── logical.out.css ├── mask-border.css ├── mask-border.out.css ├── mistakes.css ├── mistakes.out.css ├── multicolumn.css ├── multicolumn.out.css ├── nogrid.out.css ├── notes.css ├── notes.out.css ├── pie.css ├── pie.out.css ├── placeholder.css ├── placeholder.out.css ├── resolution.css ├── resolution.out.css ├── selectors.css ├── selectors.out.css ├── style.css ├── style.out.css ├── supports.css ├── supports.out.css ├── syntax.css ├── syntax.out.css ├── text-emphasis-position.css ├── text-emphasis-position.out.css ├── transition.css ├── transition.out.css ├── trim.css ├── trim.out.css ├── uncascade.css ├── uncascade.out.css ├── uppercase.css ├── uppercase.out.css ├── value-hack.css ├── value-hack.out.css ├── values.css ├── values.out.css ├── vendor-hack.css ├── vendor-hack.out.css ├── viewport.css ├── viewport.out.css ├── writing-mode.css └── writing-mode.out.css └── index.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | end_of_line = lf 9 | indent_style = tab 10 | indent_size = 2 11 | insert_final_newline = true 12 | tab_width = 4 13 | trim_trailing_whitespace = true 14 | block_comment_start = /* 15 | block_comment = * 16 | block_comment_end = */ 17 | 18 | [*.{cmd,bat}] 19 | end_of_line = crlf 20 | 21 | [{package.json,*.yml}] 22 | indent_style = space 23 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "sourceType": "script", 4 | "impliedStrict": false 5 | }, 6 | "env": { 7 | "es6": true, 8 | "node": true 9 | }, 10 | "extends": [ 11 | "standard" 12 | ], 13 | "root": true, 14 | "rules": { 15 | "comma-dangle": [ 16 | "error", 17 | { 18 | "arrays": "always-multiline", 19 | "objects": "always-multiline", 20 | "imports": "always-multiline", 21 | "exports": "always-multiline", 22 | "functions": "never" 23 | } 24 | ], 25 | "indent": [ 26 | "error", 27 | "tab", 28 | { 29 | "SwitchCase": 1 30 | } 31 | ], 32 | "no-tabs": [ 33 | "off" 34 | ], 35 | "no-var": [ 36 | "error" 37 | ], 38 | "prefer-arrow-callback": [ 39 | "error" 40 | ], 41 | "prefer-const": [ 42 | "error" 43 | ], 44 | "quotes": [ 45 | "error", 46 | "double" 47 | ], 48 | "semi": [ 49 | "error", 50 | "always", 51 | { 52 | "omitLastInOneLineBlock": false 53 | } 54 | ], 55 | "strict": [ 56 | "error", 57 | "safe" 58 | ] 59 | }, 60 | "overrides": [ 61 | { 62 | "files": [ 63 | "test/**/*" 64 | ], 65 | "env": { 66 | "mocha": true 67 | }, 68 | "rules": { 69 | "no-template-curly-in-string": "off" 70 | } 71 | } 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/node 2 | 3 | ### Node ### 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | *.pid.lock 16 | 17 | # Directory for instrumented libs generated by jscoverage/JSCover 18 | lib-cov 19 | 20 | # Coverage directory used by tools like istanbul 21 | coverage 22 | 23 | # nyc test coverage 24 | .nyc_output 25 | 26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 27 | .grunt 28 | 29 | # Bower dependency directory (https://bower.io/) 30 | bower_components 31 | 32 | # node-waf configuration 33 | .lock-wscript 34 | 35 | # Compiled binary addons (http://nodejs.org/api/addons.html) 36 | build/Release 37 | 38 | # Dependency directories 39 | node_modules/ 40 | jspm_packages/ 41 | 42 | # Typescript v1 declaration files 43 | typings/ 44 | 45 | # Optional npm cache directory 46 | .npm 47 | 48 | # Optional eslint cache 49 | .eslintcache 50 | 51 | # Optional REPL history 52 | .node_repl_history 53 | 54 | # Output of 'npm pack' 55 | *.tgz 56 | 57 | # Yarn Integrity file 58 | .yarn-integrity 59 | 60 | # dotenv environment variables file 61 | .env 62 | 63 | 64 | 65 | # End of https://www.gitignore.io/api/node 66 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.pid 3 | *.seed 4 | *.tgz 5 | .circleci 6 | .editorconfig 7 | .babelrc 8 | .eslintrc* 9 | .gitignore 10 | .grunt 11 | .lock-wscript 12 | .node_repl_history 13 | .nyc_output 14 | .stylelintrc* 15 | .travis.yml 16 | .vscode 17 | appveyor.yml 18 | coverage 19 | gulpfile.js 20 | lib-cov 21 | logs 22 | node_modules 23 | npm-debug.log* 24 | pids 25 | test 26 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "indentation": "tab", 4 | "property-no-vendor-prefix": true, 5 | "value-no-vendor-prefix": true, 6 | "selector-no-vendor-prefix": true, 7 | "media-feature-name-no-vendor-prefix": true, 8 | "at-rule-no-vendor-prefix": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: false 3 | language: node_js 4 | node_js: 5 | - "stable" 6 | - "--lts" 7 | 8 | after_script: 9 | - npm run report-coverage 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 刘祺 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [postcss](https://github.com/postcss/postcss)-unprefix 2 | ===== 3 | 4 | Unprefixes vendor prefixes in legacy CSS. 5 | 6 | [![NPM version](https://img.shields.io/npm/v/postcss-unprefix.svg?style=flat-square)](https://www.npmjs.com/package/postcss-unprefix) 7 | [![Travis](https://img.shields.io/travis/gucong3000/postcss-unprefix.svg)](https://travis-ci.org/gucong3000/postcss-unprefix) 8 | [![Codecov](https://img.shields.io/codecov/c/github/gucong3000/postcss-unprefix.svg)](https://codecov.io/gh/gucong3000/postcss-unprefix) 9 | [![David](https://img.shields.io/david/gucong3000/postcss-unprefix.svg)](https://david-dm.org/gucong3000/postcss-unprefix) 10 | 11 | Though, please use [`autoprefixer`](https://github.com/postcss/autoprefixer) as part of your build process to ensure proper browser support. 12 | 13 | ![Gif Deom](http://ww3.sinaimg.cn/bmiddle/534b48acgw1et7jyprmj3g20b40ciaes.gif) 14 | 15 | ## Installation 16 | 17 | ```bash 18 | npm install --save postcss-unprefix 19 | ``` 20 | 21 | ## Usage 22 | 23 | ```javascript 24 | var postcss = require("gulp-html-postcss"); 25 | var unprefix = require("postcss-unprefix"); 26 | var autoprefixer = require("autoprefixer"); 27 | 28 | gulp.task("clear-css", function () { 29 | var processors = [ 30 | unprefix, 31 | autoprefixer, 32 | ]; 33 | return gulp.src("./src/**/*.css") 34 | .pipe(postcss(processors)) 35 | .pipe(gulp.dest('./dest')); 36 | }); 37 | ``` 38 | 39 | #### Input 40 | 41 | ```css 42 | .flex { 43 | display: -webkit-flex; 44 | display: -moz-flex; 45 | -webkit-flex: 1; 46 | } 47 | ``` 48 | 49 | #### Output 50 | 51 | ```css 52 | .flex { 53 | display: flex; 54 | flex: 1; 55 | } 56 | ``` 57 | -------------------------------------------------------------------------------- /lib/clearAtRule.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const rePrefix = require("./util").rePrefix; 3 | const unprefixParam = require("./unprefixParam"); 4 | 5 | function clearAtRule (atRule) { 6 | const parent = atRule.parent; 7 | const nameMatch = rePrefix.exec(atRule.name); 8 | const name = nameMatch ? nameMatch[1] : atRule.name; 9 | let params = unprefixParam(atRule.params, name); 10 | if (!nameMatch && !params) { 11 | return; 12 | } 13 | 14 | params = params || atRule.params; 15 | const paramsValue = params.valueOf(); 16 | 17 | const prefixedAtRule = []; 18 | let unprefixed; 19 | 20 | parent.walkAtRules(new RegExp("^(?:-\\w+-)?" + name + "$", "i"), (atRule) => { 21 | if (atRule.parent !== parent) { 22 | return; 23 | } 24 | const atRuleFixedParams = unprefixParam(atRule.params, name); 25 | if ((atRuleFixedParams || atRule.params).valueOf() !== paramsValue) { 26 | return; 27 | } 28 | 29 | if (atRule.name[0] === "-" || atRuleFixedParams) { 30 | prefixedAtRule.push(atRule); 31 | } else { 32 | unprefixed = atRule; 33 | } 34 | }); 35 | 36 | if (!unprefixed) { 37 | unprefixed = prefixedAtRule.pop(); 38 | unprefixed.name = name; 39 | unprefixed.params = params.toString(); 40 | } 41 | prefixedAtRule.forEach((atRule) => { 42 | atRule.remove(); 43 | }); 44 | } 45 | 46 | module.exports = clearAtRule; 47 | -------------------------------------------------------------------------------- /lib/clearDecl.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const postcss = require("postcss"); 3 | const unprefixDecl = require("./unprefix").decl; 4 | const util = require("./util"); 5 | function walkDecl (decl) { 6 | if (util.rePrefix.test(decl.prop) || /(^|,|\s)-\w+-.+/i.test(decl.value)) { 7 | clearDecl(decl); 8 | } 9 | } 10 | 11 | function clearDecl (decl) { 12 | const rule = decl.parent; 13 | const prop = postcss.vendor.unprefixed(decl.prop); 14 | let unprefixed; 15 | let lastUnprefixed; 16 | 17 | const prefixedDecls = util.getDecls(rule, new RegExp("^-\\w+-" + prop + "$", "i")); 18 | 19 | util.getDecls(rule, unprefixDecl(decl).prop || prop).forEach((decl) => { 20 | lastUnprefixed = unprefixDecl(decl); 21 | if (lastUnprefixed.value) { 22 | prefixedDecls.push(decl); 23 | } else { 24 | unprefixed = decl; 25 | } 26 | }); 27 | 28 | if (!unprefixed) { 29 | const lastDecl = prefixedDecls.pop(); 30 | (lastUnprefixed || unprefixDecl(lastDecl)).replace(); 31 | } 32 | 33 | prefixedDecls.forEach((decl) => { 34 | decl.remove(); 35 | }); 36 | } 37 | 38 | module.exports = walkDecl; 39 | -------------------------------------------------------------------------------- /lib/clearRule.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const unprefixSelector = require("./unprefixSelector"); 3 | 4 | function clearRule (rule) { 5 | let selector = unprefixSelector(rule.selector); 6 | if (!selector.fixed) { 7 | return; 8 | } 9 | const prefixedDecls = []; 10 | let unprefixed; 11 | selector = selector.toString(); 12 | const parent = rule.parent; 13 | parent.walkRules((rule) => { 14 | if (rule.parent !== parent) { 15 | return; 16 | } 17 | if (rule.selector === selector) { 18 | unprefixed = rule; 19 | } else if (unprefixSelector(rule.selector).toString() === selector) { 20 | prefixedDecls.push(rule); 21 | } 22 | }); 23 | if (!unprefixed) { 24 | prefixedDecls.pop().selector = selector; 25 | } 26 | prefixedDecls.forEach((decl) => { 27 | decl.remove(); 28 | }); 29 | } 30 | 31 | module.exports = clearRule; 32 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const postcss = require("postcss"); 3 | const clearDecl = require("./clearDecl"); 4 | const clearAtRule = require("./clearAtRule"); 5 | const clearRule = require("./clearRule"); 6 | 7 | module.exports = postcss.plugin("postcss-unprefix", () => { 8 | return function (css) { 9 | css.walkAtRules(clearAtRule); 10 | css.walkRules(clearRule); 11 | css.walkDecls(clearDecl); 12 | }; 13 | }); 14 | -------------------------------------------------------------------------------- /lib/unprefix.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const postcss = require("postcss"); 4 | const autoprefixer = require("autoprefixer"); 5 | const util = require("./util"); 6 | const unprefixFlexDirection = require("./unprefixFlexDirection"); 7 | const unprefixBreakInside = require("./unprefixBreakInside"); 8 | const unprefixGradient = require("./unprefixGradient"); 9 | const unprefixMsGrid = require("./unprefixMsGrid"); 10 | const properties = require("known-css-properties").all; 11 | function valMap (reg, prop, valMapData) { 12 | return function valMap (decl) { 13 | if (reg.test(decl.prop)) { 14 | const value = postcss.vendor.unprefixed(decl.value); 15 | return { 16 | prop: prop, 17 | value: valMapData[value] || value, 18 | }; 19 | } 20 | }; 21 | } 22 | 23 | function decl2result (decl) { 24 | const result = unprefixDecl(decl); 25 | if (!result.prop) { 26 | result.prop = decl.prop; 27 | } 28 | if (!result.value) { 29 | result.value = decl.value; 30 | } 31 | return result; 32 | } 33 | 34 | function brotherFirst (reg, brotherProp) { 35 | return function brotherFirst (decl) { 36 | if (reg.test(decl.prop)) { 37 | const brother = getBrotherDecl(decl, brotherProp); 38 | if (brother) { 39 | return decl2result(brother); 40 | } 41 | } 42 | }; 43 | } 44 | 45 | function getBrotherDecl (decl, prop) { 46 | const result = util.getDecls(decl.parent, prop); 47 | return result.length && result[result.length - 1]; 48 | } 49 | 50 | const ALIGN_CONTENT = { 51 | "start": "flex-start", 52 | "end": "flex-end", 53 | "justify": "space-between", 54 | "distribute": "space-around", 55 | }; 56 | 57 | const RE_BOX_DIRECTION = /^(?:-\w+-)?(?:flex)?box-direction$/i; 58 | const RE_BOX_ORIENT = /^(?:-\w+-)?(?:flex)?box-orient$/i; 59 | const RE_FLEX_FLOW = /^(?:-\w+-)?flex-flow$/i; 60 | 61 | const declUnprefixers = [ 62 | brotherFirst(/^(?:-\w+-)?box-ordinal-group$/i, /^(?:-\w+-)?order$/i), 63 | brotherFirst(/^(?:-\w+-)?box-flex$/i, /^(?:-\w+-)?flex-grow$/i), 64 | brotherFirst(/^(?:-\w+-)?box-flex$/i, /^(?:-\w+-)?flex$/i), 65 | brotherFirst(RE_BOX_ORIENT, RE_FLEX_FLOW), 66 | brotherFirst(RE_BOX_DIRECTION, RE_FLEX_FLOW), 67 | valMap(/^(?:(?:-\w+-)?(?:flex)?box|-ms-flex)-pack$/i, "justify-content", ALIGN_CONTENT), 68 | valMap(/^(?:(?:-\w+-)?(?:flex)?box|-ms-flex)-line-pack$/i, "align-content", ALIGN_CONTENT), 69 | valMap(/^(?:(?:-\w+-)?(?:flex)?box|-ms-flex)-item-align$/i, "align-self", ALIGN_CONTENT), 70 | valMap(/^(?:(?:-\w+-)?(?:flex)?box|-ms-flex)-align$/i, "align-items", ALIGN_CONTENT), 71 | unprefixFlexDirection, 72 | unprefixBreakInside, 73 | unprefixMsGrid, 74 | function writingMode (decl) { 75 | const prop = /^(?:-\w+-)?(writing-mode)/i.exec(decl.prop); 76 | if (prop) { 77 | const value = decl.value.toLowerCase(); 78 | return { 79 | prop: "writing-mode", 80 | value: { 81 | "lr-tb": "horizontal-tb", 82 | "tb-rl": "vertical-rl", 83 | "tb-lr": "vertical-lr", 84 | }[value] || value, 85 | }; 86 | } 87 | }, 88 | function display (decl) { 89 | const display = /^(-\w+-)?display$/i.exec(decl.prop); 90 | if (display) { 91 | let value; 92 | if ((value = /^(?:-\w+-)?(inline-)?(?:flex)?box$/i.exec(decl.value))) { 93 | value = (value[1] || "") + "flex"; 94 | } else if ((value = util.rePrefix.exec(decl.value))) { 95 | value = value[1]; 96 | } else if (display[1]) { 97 | value = decl.value; 98 | } else { 99 | return; 100 | } 101 | 102 | return { 103 | prop: "display", 104 | value: value.toLowerCase(), 105 | }; 106 | } 107 | }, 108 | function imageRendering (decl) { 109 | let value; 110 | if (/^(?:-\w+-)?image-rendering$/i.test(decl.prop)) { 111 | if (/^-\w+-optimize-contrast$/i.test(decl.value)) { 112 | value = "crisp-edges"; 113 | } else if ((value = util.rePrefix.exec(decl.value))) { 114 | value = value[1]; 115 | } else { 116 | return; 117 | } 118 | } else if (/^-ms-interpolation-mode$/i.test(decl.prop) && /^nearest-neighbor$/i.test(decl.value)) { 119 | value = "pixelated"; 120 | } else { 121 | return; 122 | } 123 | return { 124 | prop: "image-rendering", 125 | value: value, 126 | }; 127 | }, 128 | function borderRadius (decl) { 129 | const prop = /^(?:-\w+-)?border-radius-(top|bottom)(left|right)$/i.exec(decl.prop); 130 | if (prop) { 131 | return { 132 | prop: "border-" + prop[1].toLowerCase() + "-" + prop[2].toLowerCase() + "-radius", 133 | value: decl.value, 134 | }; 135 | } 136 | }, 137 | function unprefixFirst (decl) { 138 | let prop = util.rePrefix.exec(decl.prop); 139 | while (prop) { 140 | const brother = getBrotherDecl(decl, prop[1]); 141 | if (brother) { 142 | return decl2result(brother); 143 | } else { 144 | prop = /^(.+?)-\w+$/.exec(prop[1]); 145 | } 146 | } 147 | }, 148 | ]; 149 | 150 | const PROP_NAME_MAP = { 151 | "border-radius-bottomleft": "border-bottom-left-radius", 152 | "border-radius-bottomright": "border-bottom-right-radius", 153 | "border-radius-topleft": "border-top-left-radius", 154 | "border-radius-topright": "border-top-right-radius", 155 | 156 | "border-after": "border-block-end", 157 | "border-before": "border-block-start", 158 | "border-end": "border-inline-end", 159 | "border-start": "border-inline-start", 160 | 161 | "margin-after": "margin-block-end", 162 | "margin-before": "margin-block-start", 163 | "margin-end": "margin-inline-end", 164 | "margin-start": "margin-inline-start", 165 | 166 | "padding-after": "padding-block-end", 167 | "padding-before": "padding-block-start", 168 | "padding-end": "padding-inline-end", 169 | "padding-start": "padding-inline-start", 170 | 171 | "mask-box-image": "mask-border", 172 | "mask-box-image-outset": "mask-border-outset", 173 | "mask-box-image-repeat": "mask-border-repeat", 174 | "mask-box-image-slice": "mask-border-slice", 175 | "mask-box-image-source": "mask-border-source", 176 | "mask-box-image-width": "mask-border-width", 177 | 178 | "box-ordinal-group": "order", 179 | "box-align": "align-items", 180 | "box-pack": "justify-content", 181 | "box-flex": "flex", 182 | "flex-preferred-size": "flex-basis", 183 | "flex-negative": "flex-shrink", 184 | "flex-positive": "flex-grow", 185 | "flex-order": "order", 186 | }; 187 | 188 | const PREFIXED_VALUE_NAME_NAME = { 189 | "-moz-available": "stretch", 190 | }; 191 | 192 | const unprefixValue = util.valueUnprefixer([ 193 | unprefixGradient, 194 | function unprefixPropInValue (node, prop) { 195 | if (/^(?:-\w+-)?transition(?:-property)?$/.test(prop) && node.type === "word") { 196 | const prefixed = unprefixProp(node.value); 197 | if (prefixed) { 198 | node.value = prefixed; 199 | return node; 200 | } 201 | } 202 | }, 203 | function autoUnprefix (node, prop) { 204 | const value = node.value.toLowerCase(); 205 | const unprefixed = PREFIXED_VALUE_NAME_NAME[value] || postcss.vendor.unprefixed(value); 206 | const data = autoprefixer.data.prefixes[unprefixed]; 207 | 208 | if (data && (!data.props || data.props.some((propName) => { 209 | return propName === "*" || propName === prop; 210 | }))) { 211 | node.value = unprefixed; 212 | return node; 213 | } 214 | }, 215 | ]); 216 | 217 | function unprefixProp (prop) { 218 | prop = util.rePrefix.exec(prop); 219 | 220 | if (!prop) { 221 | return; 222 | } 223 | 224 | prop = prop[1].toLowerCase(); 225 | 226 | if (PROP_NAME_MAP[prop]) { 227 | return PROP_NAME_MAP[prop]; 228 | } 229 | 230 | if (properties.indexOf(prop) >= 0) { 231 | return prop; 232 | } 233 | } 234 | 235 | function unprefix (decl) { 236 | let result; 237 | if (declUnprefixers.some((unprefixer) => { 238 | result = unprefixer(decl); 239 | return result; 240 | })) { 241 | return result; 242 | } 243 | result = {}; 244 | result.prop = unprefixProp(decl.prop); 245 | result.value = unprefixValue(decl.value, result.prop || decl.prop); 246 | return result; 247 | } 248 | 249 | function unprefixDecl (decl) { 250 | const result = unprefix(decl); 251 | result.replace = function () { 252 | if (result.prop && decl.prop.toLowerCase() !== result.prop) { 253 | decl.prop = result.prop; 254 | } 255 | if (result.value && decl.value.toLowerCase() !== result.value) { 256 | decl.value = result.value; 257 | } 258 | }; 259 | return result; 260 | } 261 | 262 | module.exports = { 263 | decl: unprefixDecl, 264 | value: unprefixValue, 265 | prop: unprefixProp, 266 | }; 267 | -------------------------------------------------------------------------------- /lib/unprefixBreakInside.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const util = require("./util"); 3 | 4 | function unprefixFlexDirection (decl) { 5 | const prop = /^(?:-\w+-)?(page|column)-break-(after|before|inside)/i.exec(decl.prop); 6 | if (prop) { 7 | const box = prop[2].toLowerCase(); 8 | util.getDecls(decl.parent, "page-break-" + box).forEach((decl) => { 9 | decl.remove(); 10 | }); 11 | 12 | let value = decl.value.toLowerCase(); 13 | if (value === "avoid") { 14 | value += "-" + prop[1].toLowerCase(); 15 | } 16 | 17 | return { 18 | prop: "break-" + box, 19 | value: value, 20 | }; 21 | } 22 | } 23 | module.exports = unprefixFlexDirection; 24 | -------------------------------------------------------------------------------- /lib/unprefixFlexDirection.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const util = require("./util"); 3 | 4 | const BOX_DIRECTION = { 5 | "lr": "row", 6 | "rl": "row-reverse", 7 | "tb": "column", 8 | "bt": "column-reverse", 9 | }; 10 | 11 | const BOX_ORIENT = { 12 | horizontal: "row", 13 | vertical: "column", 14 | }; 15 | 16 | const RE_BOX_DIRECTION = /^(?:-\w+-)?(?:flex)?box-direction$/i; 17 | const RE_BOX_ORIENT = /^(?:-\w+-)?(?:flex)?box-orient$/i; 18 | 19 | function boxDirection (decl) { 20 | let boxDirection = decl.value.toLowerCase(); 21 | if (BOX_DIRECTION[boxDirection]) { 22 | return BOX_DIRECTION[boxDirection]; 23 | } else if (boxDirection === "reverse") { 24 | boxDirection = "-" + boxDirection; 25 | } else { 26 | boxDirection = ""; 27 | } 28 | let boxOrient = "row"; 29 | 30 | util.getDecls(decl.parent, RE_BOX_ORIENT).forEach((decl) => { 31 | boxOrient = BOX_ORIENT[decl.value.toLowerCase()] || boxOrient; 32 | decl.remove(); 33 | }); 34 | 35 | return boxOrient + boxDirection; 36 | } 37 | 38 | function boxOrient (decl) { 39 | const boxOrient = BOX_ORIENT[decl.value.toLowerCase()] || "row"; 40 | let boxDirection = ""; 41 | 42 | util.getDecls(decl.parent, RE_BOX_DIRECTION).forEach((decl) => { 43 | const value = decl.value.toLowerCase(); 44 | if (value === "reverse") { 45 | boxDirection = "-" + value; 46 | } else if (value === "normal") { 47 | boxDirection = value; 48 | } 49 | decl.remove(); 50 | }); 51 | return boxOrient + boxDirection; 52 | } 53 | 54 | function unprefixFlexDirection (decl) { 55 | let value; 56 | if (RE_BOX_DIRECTION.test(decl.prop)) { 57 | value = boxDirection(decl); 58 | } else if (RE_BOX_ORIENT.test(decl.prop)) { 59 | value = boxOrient(decl); 60 | } else { 61 | return; 62 | } 63 | return value && { 64 | prop: "flex-direction", 65 | value: value, 66 | }; 67 | } 68 | 69 | module.exports = unprefixFlexDirection; 70 | -------------------------------------------------------------------------------- /lib/unprefixGradient.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const valueParser = require("postcss-value-parser"); 3 | const util = require("./util"); 4 | 5 | // 老式方向关键字转换 6 | const directionMap = { 7 | "top": "bottom", 8 | "bottom": "top", 9 | "left": "right", 10 | "right": "left", 11 | }; 12 | 13 | // 需要转换的旧关键字 14 | const keyWordMap = { 15 | cover: "farthest-corner", 16 | contain: "closest-side", 17 | }; 18 | 19 | // 各种角度单位与deg之间的换算关系 https://developer.mozilla.org/zh-CN/docs/Web/CSS/angle 20 | const angleUnitMap = { 21 | grad: 400, 22 | rad: 2 * Math.PI, 23 | turn: 1, 24 | }; 25 | 26 | // 角度转为关键字 27 | const degMap = { 28 | 0: "top", 29 | 90: "right", 30 | 180: "bottom", 31 | 270: "left", 32 | }; 33 | 34 | /** 35 | * 将字符串转为数字与其单位 36 | * @param {String} string 含有数字的字符串 37 | * @returns {Float} num 解析好的数字 38 | * @returns {Float} unit 原有的单位 39 | */ 40 | function parseNum (string) { 41 | let unit; 42 | const num = parseFloat(string.replace(/(\D+)$/, (s) => { 43 | unit = s; 44 | return ""; 45 | })); 46 | if (!isNaN(num)) { 47 | return { 48 | num: num, 49 | unit: unit || "", 50 | }; 51 | } 52 | } 53 | 54 | /** 55 | * 将字符串转为px为单位长度数值 56 | * @param {string} str 含有长度信息的字符串 57 | * @return {number} 换算成像素的数值 58 | */ 59 | function parseLength (str) { 60 | return /(?:\d*\.)?\d+%?$/.test(str) ? parseFloat(str) : util.length2px(str); 61 | } 62 | 63 | /** 64 | * 将字符串转为长度与其单位 65 | * @param {String} string 含有数字的字符串 66 | * @returns {Float} deg 换算成度的数字 67 | * @returns {Float} num 解析好的数字 68 | * @returns {Float} unit 原有的单位 69 | */ 70 | function parseAngle (string) { 71 | const value = parseNum(string); 72 | if (value) { 73 | if (value.num === 0 || !value.unit || value.unit === "deg") { 74 | // 没有角度单位,或数值为0,或角度单位为度,则无需换算 75 | value.deg = value.num; 76 | } else if (angleUnitMap[value.unit]) { 77 | // 不同角度单位间的换算 78 | value.deg = value.num * 360 / angleUnitMap[value.unit]; 79 | } else { 80 | return; 81 | } 82 | // 修正为w3c语法的角度。0°为上方而非右方 83 | value.deg = require("normalize-range").wrap(0, 360, 90 - value.deg); 84 | return value; 85 | } 86 | } 87 | 88 | /** 89 | * 将解析后的数字对象转换为字符串 90 | * @param {Object} angleObj 数字对象 91 | * @param {Object} angleObj.deg 以度为单位的角度 92 | * @param {Object} angleObj.unit 希望使用的单位 93 | * @return {String} 按格式输出的字符串 94 | */ 95 | function angle2String (angleObj) { 96 | let deg = angleObj.deg; 97 | if (angleObj.unit && angleObj.unit !== "deg") { 98 | // 单位不为度是,需要换算 99 | deg = (deg * angleUnitMap[angleObj.unit] / 360); 100 | } 101 | 102 | // 修正浮点数精度 103 | deg = parseFloat(deg.toFixed(4)); 104 | if (deg === 0) { 105 | // 结果等于0时,直接转换为字符串输出,不要单位 106 | deg = "0"; 107 | } else { 108 | // 结果不为0时,补上单位 109 | deg += angleObj.unit || "deg"; 110 | } 111 | return deg; 112 | } 113 | 114 | /** 115 | * 分析css参数中的坐标信息 116 | * @param {String[]} args 包含坐标信息的两个字符串组成的数组 117 | * @returns {Int} x [x轴坐标] 118 | * @returns {Int} y [y轴坐标] 119 | */ 120 | function normalizePos (args) { 121 | const point = {}; 122 | args.forEach((arg, i) => { 123 | if (arg === "top") { 124 | point.y = 0; 125 | } else if (arg === "right") { 126 | point.x = 100; 127 | } else if (arg === "bottom") { 128 | point.y = 100; 129 | } else if (arg === "left") { 130 | point.x = 0; 131 | } else { 132 | // 将长度单位转换为坐标 133 | point[i ? "y" : "x"] = parseLength(arg); 134 | } 135 | }); 136 | return point; 137 | } 138 | 139 | /** 140 | * 将长度字符串转换为以px为单位的字符串 141 | * @param {String} val 表示长度的css表达式字符串 142 | * @return {String} 以px为单位的数字字符串 143 | */ 144 | function px (val) { 145 | try { 146 | val = parseFloat(parseLength(val).toFixed(4)); 147 | if (val === 0) { 148 | return "0"; 149 | } else { 150 | return val + "px"; 151 | } 152 | } catch (ex) { 153 | return val; 154 | } 155 | } 156 | 157 | /** 158 | * `-webkit-gradient(linear, `根据参数位置与尺寸,返回修正顺序与语法的这两个参数 159 | * @param {Array} args -webkit-gradient的参数,去除第一个参数type和所有color-stop 160 | * @return {Array} `[ '90px', 'at', '0px', '150px' ]` 161 | */ 162 | function fixOldRadialGradient (args) { 163 | let position = args[0]; 164 | if (position && position[0] && position[1]) { 165 | // 第一个参数为坐标,则将这个参数中的值的单位转换为px 166 | position = position.map(px); 167 | // 在坐标参数最前面添加`at`关键字 168 | position.unshift("at"); 169 | 170 | const size = args[3] && args[3][0]; 171 | if (size != null) { 172 | // 将尺寸信息加入结果集 173 | position.unshift(px(size)); 174 | } 175 | // 返回结果 176 | return position; 177 | } 178 | } 179 | 180 | /** 181 | * `-webkit-gradient(linear, `根据传入的参数计算角度,返回角度参摄 182 | * @param {Array} args -webkit-gradient的参数,去除第一个参数type和所有color-stop 183 | * @return {String|undefined} 角度值表达式,当角度正好180°时,返回undefined 184 | */ 185 | function fixOldLinearGradient (args) { 186 | let angle; 187 | // 从args[0]中获取起始点信息 188 | const start = normalizePos(args[0]); 189 | // 从args[1]中获取终止点信息 190 | const end = normalizePos(args[1]); 191 | 192 | // 根据起始点和终止点计算角度 193 | angle = 180 - Math.atan2(end.x - start.x, end.y - start.y) * (180 / Math.PI); 194 | // 将角度进行坐标系变换 195 | angle = require("normalize-range").wrap(0, 360, angle); 196 | // 如果角度不等于180°,将其转换为字符串后返回 197 | if (angle !== 180) { 198 | angle = angle2String({ 199 | deg: angle, 200 | }); 201 | return angle; 202 | } 203 | } 204 | 205 | /** 206 | * `-webkit-gradient`转`radial-gradient`或`linear-gradient` 207 | * @param {Array} args 修正前的参数 208 | * @param {Node} gradient 原始的node对象 209 | * @return {Array} 修正后的参数 210 | */ 211 | function fixOldGradient (args, gradient) { 212 | const type = args[0][0]; 213 | let colorStops = []; 214 | let from; 215 | let to; 216 | 217 | // 将参数中的`color-stop`,`from`,`to`三种信息剔除出args并单独存放,剩下的存起来 218 | args = args.slice(1).filter((arg) => { 219 | const fnName = arg.value; 220 | if (fnName === "from") { 221 | from = arg; 222 | } else if (fnName === "to") { 223 | to = arg; 224 | } else if (fnName === "color-stop") { 225 | colorStops.push(arg); 226 | } else { 227 | return true; 228 | } 229 | return false; 230 | }); 231 | 232 | if (from) { 233 | // 将from信息放入colorStops头部 234 | colorStops.unshift(from); 235 | } 236 | if (to) { 237 | // 将from信息放入colorStops尾部 238 | colorStops.push(to); 239 | } 240 | 241 | // 将数组colorStops中的元素都转换为标准形式 242 | colorStops = colorStops.map((colorStop, i) => { 243 | // 获取colorStop的参数 244 | colorStop = colorStop.nodes; 245 | // 如果不知一个参数 246 | if (colorStop.length > 1) { 247 | // 计算位置信息的浏览器默认值 248 | const posVal = i * 100 / (colorStops.length - 1); 249 | colorStop = colorStop.filter((val) => { 250 | // 如果位置信息与浏览器默认值相同,去除它 251 | return parseFloat(val) !== posVal; 252 | }); 253 | 254 | if (colorStop.length > 1) { 255 | // 参数重新排列,位置信息放在后面,以便符合新语法 256 | colorStop.sort((word) => { 257 | return isNaN(parseFloat(word)) ? -1 : 1; 258 | }); 259 | } 260 | } 261 | return colorStop; 262 | }); 263 | 264 | if (type === "radial") { 265 | // 按照圆形渐变语法处理剩下的参数 266 | args = fixOldRadialGradient(args); 267 | } else { 268 | // 按照线性渐变语法处理剩下的参数 269 | args = fixOldLinearGradient(args); 270 | } 271 | 272 | if (args && args.length) { 273 | // 将`fixOldRadialGradient`或`fixOldLinearGradient`的返回结果插入colorStops 274 | colorStops.unshift(args); 275 | } 276 | // 将css属性名名称转换为标准的 277 | gradient.value = type + "-gradient"; 278 | return colorStops; 279 | } 280 | 281 | /** 282 | * 修正`linear-gradient`的参数 283 | * @param {Array} args linear-gradient的所有参数 284 | * @return {Array} 修正后的参数 285 | */ 286 | function fixLinearGradient (args) { 287 | const angle = parseAngle(args[0][0]); 288 | 289 | if (angle) { 290 | // 如果第一参数是角度,修正角度 291 | const deg = Math.round(angle.deg); 292 | if (deg === 180) { 293 | // 180°正是浏览器默认值,所以抛弃,减少生成的css的体积 294 | args.shift(); 295 | } else { 296 | if (degMap[deg]) { 297 | // 如果角度是0、90、180、270等特殊值,将第一参变为方位信息 298 | args[0] = ["to", degMap[deg]]; 299 | } else { 300 | // 其他角度值,直接转换第一参即可 301 | args[0] = angle2String(angle); 302 | } 303 | } 304 | } else { 305 | let position; 306 | // 遍历第一参中的值, 307 | args[0].forEach((arg, i) => { 308 | if (directionMap[arg]) { 309 | // 将top、left、bottom、right取反义词,并记录position 310 | args[0][i] = directionMap[arg]; 311 | position = args[0]; 312 | } 313 | }); 314 | if (position) { 315 | if (position.length === 1 && position[0] === "bottom") { 316 | // `to bottom`正是浏览器默认值,所以抛弃,减少生成的css的体积 317 | args.shift(); 318 | } else { 319 | // 将方位信息最前面添加一个"to"二级参数 320 | position.unshift("to"); 321 | } 322 | } 323 | } 324 | 325 | return args; 326 | } 327 | 328 | /** 329 | * 圆形渐变处理 330 | * @param {Array} args linear-gradient的所有参数 331 | * @return {Array} 修正后的参数 332 | */ 333 | function fixRadialGradient (args) { 334 | let firstArg = []; 335 | let position; 336 | 337 | // 分析所有参数,将坐标参数和关键字剔除出args并单独保存 338 | args = args.filter((subArg) => { 339 | let hasKeyWord; 340 | subArg.forEach((word, i) => { 341 | if (keyWordMap[word]) { 342 | // 查找需要转换的关键字 343 | subArg[i] = keyWordMap[word]; 344 | hasKeyWord = true; 345 | } else if (/^(?:circle|ellipse|\w+-\w+)$/.test(word)) { 346 | // 查找是否有其他的关键字 347 | hasKeyWord = true; 348 | } 349 | }); 350 | if (hasKeyWord) { 351 | // subArg中如果有关键字,将它存入firstArg 352 | firstArg = firstArg.concat(subArg); 353 | return false; 354 | } else if (subArg.every((word) => { 355 | return word === "center" || directionMap[word] || parseNum(word); 356 | })) { 357 | // 如果subArg是坐标信息将它存入position 358 | position = subArg; 359 | return false; 360 | } 361 | return true; 362 | }); 363 | 364 | if (position) { 365 | // 在坐标参数最前面添加`at`关键字 366 | position.unshift("at"); 367 | firstArg = firstArg.concat(position); 368 | } 369 | 370 | if (firstArg.length) { 371 | // 如果收集到了firstArg,将其加入args的最前面 372 | args.unshift(firstArg); 373 | } 374 | 375 | return args; 376 | } 377 | 378 | /** 379 | * `radial-gradient`或`linear-gradient`去前缀并转换语法 380 | * @param {Node} gradient `postcss-value-parser`插件转换后的-webkit-gradient 381 | * @param {String} type `radial`或`linear` 382 | * @return {Array} 修正后的参数 383 | */ 384 | function fixGradient (gradient, type) { 385 | if (/^radial$/i.test(type)) { 386 | // 圆形渐变处理 387 | return fixRadialGradient(gradient); 388 | } else { 389 | // 线性渐变处理 390 | return fixLinearGradient(gradient); 391 | } 392 | } 393 | 394 | /** 395 | * 将语法树中的function节点转换为便于处理的形式 396 | * 返回值二维数组 397 | * @param {Node} node 语法树节点,type必须为function 398 | * @return {Array} 二维数组 399 | */ 400 | function parseFunction (node) { 401 | const args = []; 402 | let index = 0; 403 | node.nodes.forEach((subNode) => { 404 | if (subNode.type === "div" && subNode.value === ",") { 405 | // 遇到`,`下标自加1 406 | index++; 407 | return; 408 | } else if (subNode.type === "function") { 409 | // 将参数中的`color-stop`,`from`,`to`三种function特殊处理 410 | if ((subNode.value === "from" || subNode.value === "to" || subNode.value === "color-stop")) { 411 | let colorStop = subNode.nodes.filter((colorStopInfo) => { 412 | // colorStop的子节点,除function和word外,都丢去 413 | return colorStopInfo.type === "function" || colorStopInfo.type === "word"; 414 | }).map((colorStopInfo) => { 415 | // colorStop的子节点,转换为字符串 416 | return valueParser.stringify(colorStopInfo); 417 | }); 418 | 419 | // 组装新的对象传递出去 420 | colorStop = { 421 | nodes: colorStop, 422 | type: "function", 423 | value: subNode.value, 424 | }; 425 | 426 | // 不使用第三个数组维度,而是将其存在最上面的维度上 427 | args[index] = colorStop; 428 | return args[index]; 429 | } 430 | } else if (subNode.type !== "word") { 431 | return; 432 | } 433 | 434 | if (!args[index]) { 435 | // 如果未初始化该数组维度,对其初始化 436 | args[index] = []; 437 | } 438 | // 未特殊处理的function,还有普通的word,将其转字符串 439 | args[index].push(valueParser.stringify(subNode)); 440 | }); 441 | // 返回转换后的数组 442 | return args; 443 | } 444 | 445 | // 将二维数组降维,并转换为字符串 446 | function stringifyArg (arg) { 447 | if (Array.isArray(arg)) { 448 | // 递归方式处理数组的更高维度 449 | return arg.map(stringifyArg).join(" "); 450 | } else { 451 | return String(arg); 452 | } 453 | } 454 | 455 | /** 456 | * 将二维数组作为参数,重写type为function的语法树节点,type会变为word 457 | * @param {Node} gradient 语法树节点 458 | * @param {Node} args 修正后的参数 459 | */ 460 | function stringifyGradient (gradient, args) { 461 | // 将参数还原成节点 462 | gradient.value = gradient.value + "(" + args.map(stringifyArg).join(", ") + ")"; 463 | gradient.type = "word"; 464 | delete gradient.nodes; 465 | } 466 | 467 | module.exports = function (node) { 468 | if (node.type !== "function") { 469 | return; 470 | } 471 | const gradient = /^-\w+-((?:\w+-)?(\w+)-gradient)$/i.exec(node.value); 472 | if (gradient) { 473 | node.value = gradient[1].toLocaleLowerCase(); 474 | stringifyGradient(node, fixGradient(parseFunction(node), gradient[2])); 475 | } else if (/^-\w+-gradient$/i.test(node.value)) { 476 | // 修复老式webkit语法的gradient 477 | stringifyGradient(node, fixOldGradient(parseFunction(node), node)); 478 | } else { 479 | return; 480 | } 481 | return node; 482 | }; 483 | -------------------------------------------------------------------------------- /lib/unprefixMsGrid.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const util = require("./util"); 3 | 4 | function unprefixMsGrid (decl) { 5 | let prop = /^-ms-grid-(\w+)(?:-(.+))?$/i.exec(decl.prop); 6 | if (!prop) { 7 | return; 8 | } 9 | const aspect = prop[1].toLowerCase(); 10 | prop = prop[2] && prop[2].toLowerCase(); 11 | let value = decl.value.toLowerCase(); 12 | if (!prop) { 13 | if (/s$/i.test(aspect)) { 14 | return { 15 | prop: "grid-template-" + aspect, 16 | value: value, 17 | }; 18 | } else { 19 | prop = "start"; 20 | } 21 | } else if (prop === "span") { 22 | prop = "end"; 23 | value = "span " + value; 24 | } else if (prop === "align") { 25 | return { 26 | prop: "align-self", 27 | value: value.replace(/^(start|end)$/i, "flex-$1"), 28 | }; 29 | } else { 30 | return; 31 | } 32 | 33 | prop = ["grid", aspect, prop].join("-"); 34 | 35 | util.getDecls(decl.parent, ["grid", aspect].join("-")).forEach((parentDecl) => { 36 | prop = parentDecl.prop; 37 | value = parentDecl.value; 38 | }); 39 | 40 | return { 41 | prop: prop, 42 | value: value, 43 | }; 44 | } 45 | 46 | module.exports = unprefixMsGrid; 47 | -------------------------------------------------------------------------------- /lib/unprefixParam.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const util = require("./util"); 3 | const unprefix = require("./unprefix"); 4 | const removeExtraParens = util.removeExtra(/\(\s*(\(.+?\))\s*\)/gm); 5 | const removeExtraDecls = util.removeExtra(/(\(.+?\))\s*or\s*\1/igm); 6 | 7 | function unprefixSupports (params) { 8 | let fixed; 9 | params = params.replace(/\(\s*((?:-\w+-)?\w+(?:-\w+)*)\s*:\s*(.+?)\s*\)/igm, (s, prop, value) => { 10 | const result = unprefix.decl({ 11 | prop: prop, 12 | value: value, 13 | }); 14 | if (result.prop || result.value) { 15 | fixed = true; 16 | } 17 | return "(" + (result.prop || prop) + ": " + (result.value || value) + ")"; 18 | }); 19 | if (!fixed) { 20 | return; 21 | } 22 | params = removeExtraParens(removeExtraDecls(params)); 23 | return { 24 | toString: function () { 25 | return params; 26 | }, 27 | valueOf: function () { 28 | return params.replace(/\s+/gm, " "); 29 | }, 30 | }; 31 | } 32 | 33 | function unprefixMedia (params) { 34 | const rule = {}; 35 | const devicePixelRatio = {}; 36 | let fixed; 37 | 38 | let mediaType = ""; 39 | 40 | params = params.replace(/^\w+(?:\s+\w+)*\s*/, (prefix) => { 41 | mediaType = prefix; 42 | return ""; 43 | }).split(/\s*,\s*/).filter((param) => { 44 | param = /^\(\s*(\S+)\s*(?::\s*(.+?)\s*)?\)$/.exec(param); 45 | if (!param) { 46 | return true; 47 | } 48 | const prop = /^(?:-\w+-)?((?:\w+-)*?)device-pixel-ratio$/i.exec(param[1]); 49 | if (prop) { 50 | const key = prop[1].toLowerCase() + "resolution"; 51 | if (!rule[key]) { 52 | rule[key] = null; 53 | } 54 | devicePixelRatio[key] = param[2]; 55 | fixed = true; 56 | } else { 57 | rule[param[1].toLowerCase()] = param[2]; 58 | } 59 | }); 60 | 61 | if (!fixed) { 62 | return; 63 | } 64 | 65 | for (const prop in devicePixelRatio) { 66 | if (rule[prop]) { 67 | continue; 68 | } 69 | let value = devicePixelRatio[prop]; 70 | try { 71 | // eslint-disable-next-line no-eval 72 | value = eval.call(0, value); 73 | } catch (ex) { 74 | rule[prop] = value; 75 | continue; 76 | } 77 | rule[prop] = value + "dppx"; 78 | } 79 | 80 | return { 81 | toString: function () { 82 | return mediaType + params.concat(Object.keys(rule).map((prop) => { 83 | if (rule[prop]) { 84 | return "(" + prop + ": " + rule[prop] + ")"; 85 | } else { 86 | return "(" + prop + ")"; 87 | } 88 | })).join(", "); 89 | }, 90 | valueOf: function () { 91 | return mediaType + params.concat(Object.keys(rule).sort().map((prop) => { 92 | let value = rule[prop]; 93 | if (/\d+dppx$/i.test(value)) { 94 | value = parseFloat(value) * 96 + "dpi"; 95 | } else { 96 | value = util.length2px(value, value); 97 | } 98 | 99 | return "(" + prop + ": " + value + ")"; 100 | })).join(", "); 101 | }, 102 | }; 103 | } 104 | 105 | module.exports = function (params, name) { 106 | if (/^media$/i.test(name)) { 107 | return unprefixMedia(params.toLowerCase()); 108 | } 109 | if (/^supports$/i.test(name)) { 110 | return unprefixSupports(params.toLowerCase()); 111 | } 112 | }; 113 | -------------------------------------------------------------------------------- /lib/unprefixSelector.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const util = require("./util"); 3 | const removeExtraSelector = util.removeExtra(/(.+?)(?:\s*,\s*\1)+/gm); 4 | const pseudoClasses = require("pseudo-classes")(); 5 | const pseudoElements = require("pseudo-elements")(); 6 | const parser = require("postcss-selector-parser"); 7 | const PSEUDO_MAP = { 8 | "input-placeholder": "placeholder", 9 | "full-screen": "fullscreen", 10 | }; 11 | 12 | function unprefixSelector (selector) { 13 | let fixed; 14 | selector = parser((selectors) => { 15 | selectors.walkPseudos((pseudo) => { 16 | let value = /^(?::+)-\w+-(\w+(-\w+)*)$/.exec(pseudo.value); 17 | if (!value) { 18 | return; 19 | } 20 | let start; 21 | value = value[1].toLowerCase(); 22 | value = PSEUDO_MAP[value] || value; 23 | if (pseudoClasses.indexOf(value) >= 0) { 24 | start = ":"; 25 | } else if (pseudoElements.indexOf(value) >= 0) { 26 | start = "::"; 27 | } else { 28 | return pseudo; 29 | } 30 | pseudo.value = start + value; 31 | fixed = true; 32 | }); 33 | }).processSync(selector); 34 | 35 | return { 36 | fixed: fixed || false, 37 | toString: function () { 38 | return removeExtraSelector(selector.toString()); 39 | }, 40 | }; 41 | } 42 | 43 | module.exports = unprefixSelector; 44 | -------------------------------------------------------------------------------- /lib/util.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const rePrefix = /^-\w+-(\w+(?:-\w+)*)$/i; 3 | const valueParser = require("postcss-value-parser"); 4 | const removeExtraValue = removeExtra(/\b([a-z]+?\w+(?:-\w+)*(?:\s+[^,]+)?)(?:\s*,\s*(?:-\w+-)?\1)+/igm); 5 | 6 | function valueUnprefixer (valueUnprefixers) { 7 | function unprefixValueNode (value, prop) { 8 | let fixed; 9 | value.nodes.forEach((node) => { 10 | if (node.type === "div") { 11 | return false; 12 | } 13 | if (rePrefix.test(node.value)) { 14 | fixed = valueUnprefixers.some((unprefixer) => { 15 | return unprefixer(node, prop); 16 | }) || fixed; 17 | } else if (node.nodes) { 18 | fixed = unprefixValueNode(node, prop) || fixed; 19 | } 20 | }); 21 | return fixed || false; 22 | } 23 | 24 | function unprefixValue (value, prop) { 25 | value = valueParser(value); 26 | 27 | if (unprefixValueNode(value, prop.toLowerCase())) { 28 | return removeExtraValue(valueParser.stringify(value)); 29 | } 30 | } 31 | 32 | return unprefixValue; 33 | } 34 | 35 | // 各种长度单位与deg之间的换算关系 https://developer.mozilla.org/zh-CN/docs/Web/CSS/length 36 | const lengthUnitMap = { 37 | "in": 96, 38 | ch: 6, 39 | cm: 37.79527559055118, 40 | em: 12, 41 | ex: 5.4376, 42 | mm: 3.7795275590551185, 43 | pc: 16, 44 | pt: 1.3333333333333333, 45 | q: 0.9448818897637796, 46 | rem: 16, 47 | vh: 960, 48 | vm: 640, 49 | vmax: 960, 50 | vmin: 640, 51 | vw: 640, 52 | px: 1, 53 | }; 54 | 55 | function length2px (length, failback) { 56 | length = length && /^((?:\d*\.)?\d+)([a-z]+?)$/i.exec(length); 57 | let unit; 58 | let value; 59 | 60 | if (!length || !(unit = lengthUnitMap[length[2].toLowerCase()]) || isNaN(value = parseFloat(length[1]))) { 61 | return failback; 62 | } 63 | return parseFloat((value * unit).toFixed(8)); 64 | } 65 | 66 | function getDecls (parent, prop) { 67 | const result = []; 68 | const unprefix = []; 69 | if (!parent) { 70 | return result; 71 | } 72 | 73 | if (typeof prop === "string") { 74 | prop = new RegExp("^" + prop + "$", "i"); 75 | } 76 | parent.walkDecls(prop, (decl) => { 77 | if (decl.parent !== parent) { 78 | return; 79 | } 80 | if (decl.prop[0] === "-") { 81 | result.push(decl); 82 | } else { 83 | unprefix.push(decl); 84 | } 85 | }); 86 | return result.concat(unprefix); 87 | } 88 | 89 | function removeExtra (regexp) { 90 | function removeExtra (string) { 91 | let fixed; 92 | string = string.replace(regexp, (s, content) => { 93 | fixed = true; 94 | return content; 95 | }); 96 | if (fixed) { 97 | string = removeExtra(string); 98 | } 99 | return string; 100 | } 101 | return removeExtra; 102 | } 103 | 104 | module.exports = { 105 | rePrefix: rePrefix, 106 | removeExtra: removeExtra, 107 | length2px: length2px, 108 | valueUnprefixer: valueUnprefixer, 109 | getDecls: getDecls, 110 | }; 111 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "gucong3000", 3 | "bugs": { 4 | "url": "https://github.com/gucong3000/postcss-unprefix/issues" 5 | }, 6 | "peerDependencies": { 7 | "postcss": ">=5.0.0" 8 | }, 9 | "dependencies": { 10 | "autoprefixer": "^9.4.3", 11 | "known-css-properties": "^0.11.0", 12 | "normalize-range": "^0.1.2", 13 | "postcss-selector-parser": "^5.0.0", 14 | "postcss-value-parser": "^3.3.1", 15 | "pseudo-classes": "^1.0.0", 16 | "pseudo-elements": "^1.1.0" 17 | }, 18 | "description": "Unprefixes vendor prefixes in legacy CSS.", 19 | "devDependencies": { 20 | "codecov": "^3.1.0", 21 | "eslint": "^5.11.1", 22 | "eslint-config-standard": "^12.0.0", 23 | "eslint-plugin-import": "^2.14.0", 24 | "eslint-plugin-node": "^8.0.0", 25 | "eslint-plugin-promise": "^4.0.1", 26 | "eslint-plugin-standard": "^4.0.0", 27 | "mocha": "^5.2.0", 28 | "nyc": "^13.1.0", 29 | "postcss": "^7.0.7", 30 | "postcss-less": "^3.1.0", 31 | "postcss-reporter": "^6.0.1", 32 | "stylelint": "^9.9.0" 33 | }, 34 | "homepage": "https://github.com/gucong3000/postcss-unprefix#readme", 35 | "keywords": [ 36 | "postcss", 37 | "prefix", 38 | "unprefix", 39 | "clear", 40 | "clean", 41 | "remove" 42 | ], 43 | "license": "MIT", 44 | "main": "./lib/index", 45 | "name": "postcss-unprefix", 46 | "nyc": { 47 | "lines": 100, 48 | "statements": 100, 49 | "functions": 100, 50 | "branches": 100, 51 | "reporter": [ 52 | "lcov", 53 | "text" 54 | ], 55 | "cache": true, 56 | "all": true, 57 | "check-coverage": true 58 | }, 59 | "repository": { 60 | "type": "git", 61 | "url": "git+https://github.com/gucong3000/postcss-unprefix.git" 62 | }, 63 | "scripts": { 64 | "report-coverage": "codecov", 65 | "pretest": "eslint lib test", 66 | "test": "nyc mocha --no-timeouts" 67 | }, 68 | "version": "2.1.4" 69 | } 70 | -------------------------------------------------------------------------------- /test/fixtures/3d-transform.css: -------------------------------------------------------------------------------- 1 | a { 2 | -o-transition: -o-transform 1s; 3 | transition: transform 1s; 4 | transition: transform 1s, -o-transform 1s; 5 | transform: rotateX(45deg); 6 | } 7 | 8 | b { 9 | -ms-transform: translateX(45deg); 10 | -o-transform: translateX(45deg); 11 | transform: translateX(45deg); 12 | } 13 | 14 | em { 15 | -ms-transform: rotate(45deg); 16 | -o-transform: rotateZ(45deg); 17 | transform: rotateZ(45deg); 18 | } 19 | 20 | @-o-keyframes anim { 21 | from { 22 | -o-transform: rotate(90deg); 23 | transform: rotate(90deg); 24 | } 25 | } 26 | 27 | @keyframes anim { 28 | from { 29 | -o-transform: rotate(90deg); 30 | transform: rotate(90deg); 31 | } 32 | } 33 | 34 | a { 35 | -o-transition: transform 1s, -o-transform 1s; 36 | } 37 | 38 | b { 39 | -ms-transform: translateX(45deg); 40 | -o-transform: translateX(45deg); 41 | } 42 | 43 | em { 44 | -ms-transform: rotate(45deg); 45 | -o-transform: rotate(45deg); 46 | } 47 | -------------------------------------------------------------------------------- /test/fixtures/3d-transform.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | transition: transform 1s; 3 | transform: rotateX(45deg); 4 | } 5 | 6 | b { 7 | transform: translateX(45deg); 8 | } 9 | 10 | em { 11 | transform: rotateZ(45deg); 12 | } 13 | 14 | @keyframes anim { 15 | from { 16 | transform: rotate(90deg); 17 | } 18 | } 19 | 20 | a { 21 | transition: transform 1s; 22 | } 23 | 24 | b { 25 | transform: translateX(45deg); 26 | } 27 | 28 | em { 29 | transform: rotate(45deg); 30 | } 31 | -------------------------------------------------------------------------------- /test/fixtures/advanced-filter.css: -------------------------------------------------------------------------------- 1 | div { 2 | -webkit-backdrop-filter: blur(2px); 3 | backdrop-filter: blur(2px); 4 | } 5 | 6 | div { 7 | background: -webkit-filter(url('image.jpg'), blur(2px)); 8 | background: filter(url('image.jpg'), blur(2px)); 9 | } 10 | 11 | div { 12 | background: url(image.jpg), -webkit-filter(url('image.jpg'), blur(2px)); 13 | background: url(image.jpg), filter(url('image.jpg'), blur(2px)); 14 | } 15 | 16 | div { 17 | -webkit-backdrop-filter: blur(2px); 18 | } 19 | 20 | div { 21 | background: -webkit-filter(url('image.jpg'), blur(2px)); 22 | } 23 | 24 | div { 25 | background: url(image.jpg), -webkit-filter(url('image.jpg'), blur(2px)); 26 | } -------------------------------------------------------------------------------- /test/fixtures/advanced-filter.out.css: -------------------------------------------------------------------------------- 1 | div { 2 | backdrop-filter: blur(2px); 3 | } 4 | 5 | div { 6 | background: filter(url('image.jpg'), blur(2px)); 7 | } 8 | 9 | div { 10 | background: url(image.jpg), filter(url('image.jpg'), blur(2px)); 11 | } 12 | 13 | div { 14 | backdrop-filter: blur(2px); 15 | } 16 | 17 | div { 18 | background: filter(url('image.jpg'), blur(2px)); 19 | } 20 | 21 | div { 22 | background: url(image.jpg), filter(url('image.jpg'), blur(2px)); 23 | } -------------------------------------------------------------------------------- /test/fixtures/appearance.css: -------------------------------------------------------------------------------- 1 | a { 2 | -webkit-appearance: none; 3 | -moz-appearance: none; 4 | appearance: none; 5 | } 6 | 7 | b { 8 | -webkit-appearance: auto; 9 | -moz-appearance: auto; 10 | appearance: auto; 11 | } 12 | 13 | a { 14 | -webkit-appearance: none; 15 | -moz-appearance: none; 16 | } 17 | 18 | b { 19 | -webkit-appearance: auto; 20 | -moz-appearance: auto; 21 | } 22 | -------------------------------------------------------------------------------- /test/fixtures/appearance.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | appearance: none; 3 | } 4 | 5 | b { 6 | appearance: auto; 7 | } 8 | 9 | a { 10 | appearance: none; 11 | } 12 | 13 | b { 14 | appearance: auto; 15 | } 16 | -------------------------------------------------------------------------------- /test/fixtures/background-clip.css: -------------------------------------------------------------------------------- 1 | a { 2 | -webkit-background-clip: text; 3 | background-clip: text; 4 | } 5 | 6 | b { 7 | background-clip: content-box; 8 | } 9 | 10 | a { 11 | -webkit-background-clip: text; 12 | -moz-background-clip: text; 13 | } 14 | 15 | b { 16 | -webkit-background-clip: content-box; 17 | } 18 | -------------------------------------------------------------------------------- /test/fixtures/background-clip.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | background-clip: text; 3 | } 4 | 5 | b { 6 | background-clip: content-box; 7 | } 8 | 9 | a { 10 | background-clip: text; 11 | } 12 | 13 | b { 14 | background-clip: content-box; 15 | } 16 | -------------------------------------------------------------------------------- /test/fixtures/background-size.css: -------------------------------------------------------------------------------- 1 | a { 2 | -webkit-background-size: 20px 20px; 3 | -moz-background-size: 20px; 4 | background-size: 20px; 5 | } 6 | 7 | b { 8 | -webkit-background-size: contain; 9 | -moz-background-size: contain; 10 | background-size: contain; 11 | } 12 | 13 | b { 14 | -webkit-background-size: contain; 15 | -moz-background-size: contain; 16 | } 17 | -------------------------------------------------------------------------------- /test/fixtures/background-size.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | background-size: 20px; 3 | } 4 | 5 | b { 6 | background-size: contain; 7 | } 8 | 9 | b { 10 | background-size: contain; 11 | } 12 | -------------------------------------------------------------------------------- /test/fixtures/border-image.css: -------------------------------------------------------------------------------- 1 | a { 2 | -o-border-image: -o-linear-gradient(black, white) 20% stretch stretch; 3 | border-image: -webkit-linear-gradient(black, white) 20% fill stretch stretch; 4 | border-image: linear-gradient(black, white) 20% fill stretch stretch; 5 | } 6 | 7 | a { 8 | -o-border-image: -o-linear-gradient(black, white) 20% stretch stretch; 9 | } -------------------------------------------------------------------------------- /test/fixtures/border-image.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | border-image: linear-gradient(black, white) 20% fill stretch stretch; 3 | } 4 | 5 | a { 6 | border-image: linear-gradient(black, white) 20% stretch stretch; 7 | } -------------------------------------------------------------------------------- /test/fixtures/border-radius.css: -------------------------------------------------------------------------------- 1 | a { 2 | -webkit-border-radius: 5px; 3 | -moz-border-radius: 5px; 4 | border-radius: 5px; 5 | -webkit-border-top-left-radius: 3px; 6 | -moz-border-radius-topleft: 3px; 7 | border-top-left-radius: 3px; 8 | -webkit-border-bottom-right-radius: 3px; 9 | -moz-border-radius-bottomright: 3px; 10 | border-bottom-right-radius: 3px; 11 | } 12 | 13 | b { 14 | -moz-border-radius-topleft: 3px; 15 | -moz-border-radius-bottomright: 3px; 16 | -moz-border-radius: 5px; 17 | } 18 | 19 | c { 20 | -moz-border-radius: 5px; 21 | -moz-border-radius-topleft: 3px; 22 | -moz-border-radius-bottomright: 3px; 23 | } 24 | -------------------------------------------------------------------------------- /test/fixtures/border-radius.less: -------------------------------------------------------------------------------- 1 | a { 2 | -webkit-border-radius: 5px; 3 | -webkit-border-top-left-radius: 3px; 4 | -webkit-border-bottom-right-radius: 3px; 5 | b { 6 | -moz-border-radius: 5px; 7 | border-radius: 5px; 8 | -moz-border-radius-topleft: 3px; 9 | border-top-left-radius: 3px; 10 | -moz-border-radius-bottomright: 3px; 11 | border-bottom-right-radius: 3px; 12 | } 13 | } 14 | 15 | b { 16 | -moz-border-radius-topleft: 3px; 17 | -moz-border-radius-bottomright: 3px; 18 | -moz-border-radius: 5px; 19 | } 20 | 21 | c { 22 | -moz-border-radius: 5px; 23 | -moz-border-radius-topleft: 3px; 24 | -moz-border-radius-bottomright: 3px; 25 | } 26 | -------------------------------------------------------------------------------- /test/fixtures/border-radius.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | border-radius: 5px; 3 | border-top-left-radius: 3px; 4 | border-bottom-right-radius: 3px; 5 | } 6 | 7 | b { 8 | border-top-left-radius: 3px; 9 | border-bottom-right-radius: 3px; 10 | border-radius: 5px; 11 | } 12 | 13 | c { 14 | border-radius: 5px; 15 | border-top-left-radius: 3px; 16 | border-bottom-right-radius: 3px; 17 | } 18 | -------------------------------------------------------------------------------- /test/fixtures/border-radius.out.less: -------------------------------------------------------------------------------- 1 | a { 2 | border-radius: 5px; 3 | border-top-left-radius: 3px; 4 | border-bottom-right-radius: 3px; 5 | b { 6 | border-radius: 5px; 7 | border-top-left-radius: 3px; 8 | border-bottom-right-radius: 3px; 9 | } 10 | } 11 | 12 | b { 13 | border-top-left-radius: 3px; 14 | border-bottom-right-radius: 3px; 15 | border-radius: 5px; 16 | } 17 | 18 | c { 19 | border-radius: 5px; 20 | border-top-left-radius: 3px; 21 | border-bottom-right-radius: 3px; 22 | } 23 | -------------------------------------------------------------------------------- /test/fixtures/box-shadow.css: -------------------------------------------------------------------------------- 1 | a { 2 | -webkit-box-shadow: -1px -1px 1px rgba(0, 0, 0, 0.2) inset; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/box-shadow.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | box-shadow: -1px -1px 1px rgba(0, 0, 0, 0.2) inset; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/cascade.css: -------------------------------------------------------------------------------- 1 | a { 2 | -webkit-box-orient: horizontal; 3 | -webkit-box-direction: normal; 4 | -webkit-flex-direction: row; 5 | -moz-box-orient: horizontal; 6 | -moz-box-direction: normal; 7 | -ms-flex-direction: row; 8 | flex-direction: row; 9 | -webkit-mask: none; 10 | mask: none; 11 | } 12 | 13 | b { 14 | -webkit-mask: none; 15 | mask: none; 16 | } 17 | 18 | a { 19 | -webkit-flex-direction: row; 20 | -moz-box-orient: horizontal; 21 | -moz-box-direction: normal; 22 | -ms-flex-direction: row; 23 | -webkit-mask: none; 24 | } 25 | -------------------------------------------------------------------------------- /test/fixtures/cascade.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | flex-direction: row; 3 | mask: none; 4 | } 5 | 6 | b { 7 | mask: none; 8 | } 9 | 10 | a { 11 | flex-direction: row; 12 | mask: none; 13 | } 14 | -------------------------------------------------------------------------------- /test/fixtures/check-down.css: -------------------------------------------------------------------------------- 1 | * { 2 | -webkit-transition: all 1s; 3 | transition: all 1s; 4 | -o-transition: all 1s; 5 | } 6 | 7 | * { 8 | -webkit-transition: all 1s; 9 | -o-transition: all 1s; 10 | } -------------------------------------------------------------------------------- /test/fixtures/check-down.out.css: -------------------------------------------------------------------------------- 1 | * { 2 | transition: all 1s; 3 | } 4 | 5 | * { 6 | transition: all 1s; 7 | } -------------------------------------------------------------------------------- /test/fixtures/comments.css: -------------------------------------------------------------------------------- 1 | a { 2 | /* transition */ 3 | -webkit-transition: all 1s; 4 | -o-transition: all 1s; 5 | transition: all 1s; 6 | height: -webkit-calc(100% - 10px); 7 | height: calc(100% - 10px); 8 | } 9 | 10 | /* placeholder */ 11 | ::-webkit-input-placeholder { 12 | } 13 | 14 | ::placeholder { 15 | } 16 | 17 | a { 18 | /* transition */ 19 | -webkit-transition: all 1s; 20 | -o-transition: all 1s; 21 | } 22 | -------------------------------------------------------------------------------- /test/fixtures/comments.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | /* transition */ 3 | transition: all 1s; 4 | height: calc(100% - 10px); 5 | } 6 | 7 | /* placeholder */ 8 | 9 | ::placeholder { 10 | } 11 | 12 | a { 13 | /* transition */ 14 | transition: all 1s; 15 | } 16 | -------------------------------------------------------------------------------- /test/fixtures/cross-fade.css: -------------------------------------------------------------------------------- 1 | a { 2 | background-image: -webkit-cross-fade(url(foo.png), url(bar.png), 20%); 3 | background-image: cross-fade(20% url(foo.png), url(bar.png)); 4 | } 5 | 6 | b { 7 | background-image: -webkit-cross-fade(url(foo.png), url(bar.png), 0.5); 8 | background-image: cross-fade(url(foo.png), url(bar.png)); 9 | } 10 | 11 | h1 { 12 | background-image: -webkit-cross-fade(url(foo.png), url(bar.png), 10.823%); 13 | background-image: cross-fade(10.823% url(foo.png), url(bar.png)); 14 | } 15 | 16 | h2 { 17 | background-image: -webkit-cross-fade(url(foo.png), url(bar.png), 0.59); 18 | background-image: cross-fade(0.59 url(foo.png), url(bar.png)); 19 | } 20 | 21 | h3 { 22 | background-image: -webkit-cross-fade(url(foo.png), url(bar.png), .59); 23 | background-image: cross-fade(.59 url(foo.png), url(bar.png)); 24 | } 25 | 26 | .foo { 27 | background-image: -webkit-cross-fade(linear-gradient(white, black), radial-gradient(circle closest-corner, white, black), .59); 28 | background-image: cross-fade(.59 linear-gradient(white, black), radial-gradient(circle closest-corner, white, black)); 29 | } 30 | -------------------------------------------------------------------------------- /test/fixtures/cross-fade.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | background-image: cross-fade(20% url(foo.png), url(bar.png)); 3 | } 4 | 5 | b { 6 | background-image: cross-fade(url(foo.png), url(bar.png)); 7 | } 8 | 9 | h1 { 10 | background-image: cross-fade(10.823% url(foo.png), url(bar.png)); 11 | } 12 | 13 | h2 { 14 | background-image: cross-fade(0.59 url(foo.png), url(bar.png)); 15 | } 16 | 17 | h3 { 18 | background-image: cross-fade(.59 url(foo.png), url(bar.png)); 19 | } 20 | 21 | .foo { 22 | background-image: cross-fade(.59 linear-gradient(white, black), radial-gradient(circle closest-corner, white, black)); 23 | } 24 | -------------------------------------------------------------------------------- /test/fixtures/custom-prefix.css: -------------------------------------------------------------------------------- 1 | a { 2 | -evil-up: -webkit-calc(10px + 1); 3 | -evil-up: calc(10px + 1); 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/custom-prefix.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | -evil-up: calc(10px + 1); 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/disabled.css: -------------------------------------------------------------------------------- 1 | a { 2 | border-radius: 4px; 3 | -webkit-mask: none; 4 | mask: none; 5 | } 6 | 7 | b { 8 | /* autoprefixer: off */ 9 | -webkit-border-radius: 4px; 10 | border-radius: 4px; 11 | mask: none; 12 | } 13 | 14 | .loud { 15 | /* ! autoprefixer: off */ 16 | -webkit-border-radius: 4px; 17 | border-radius: 4px; 18 | mask: none; 19 | } 20 | 21 | .case { 22 | /* autoprefixer:OFF */ 23 | -webkit-border-radius: 4px; 24 | border-radius: 4px; 25 | mask: none; 26 | } 27 | 28 | @support (transition: 1s) { 29 | /* autoprefixer: off */ 30 | :fullscreen { 31 | -webkit-border-radius: 4px; 32 | border-radius: 4px; 33 | mask: none; 34 | } 35 | 36 | ::-webkit-input-placeholder { 37 | /*autoprefixer: on*/ 38 | border-radius: 4px; 39 | -webkit-mask: none; 40 | mask: none; 41 | } 42 | 43 | ::placeholder { 44 | /* autoprefixer: on */ 45 | border-radius: 4px; 46 | -webkit-mask: none; 47 | mask: none; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /test/fixtures/disabled.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | border-radius: 4px; 3 | mask: none; 4 | } 5 | 6 | b { 7 | /* autoprefixer: off */ 8 | border-radius: 4px; 9 | mask: none; 10 | } 11 | 12 | .loud { 13 | /* ! autoprefixer: off */ 14 | border-radius: 4px; 15 | mask: none; 16 | } 17 | 18 | .case { 19 | /* autoprefixer:OFF */ 20 | border-radius: 4px; 21 | mask: none; 22 | } 23 | 24 | @support (transition: 1s) { 25 | /* autoprefixer: off */ 26 | :fullscreen { 27 | border-radius: 4px; 28 | mask: none; 29 | } 30 | 31 | ::placeholder { 32 | /* autoprefixer: on */ 33 | border-radius: 4px; 34 | mask: none; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /test/fixtures/double.css: -------------------------------------------------------------------------------- 1 | a { 2 | -webkit-flex-basis: 8.33333%; 3 | -ms-flex-preferred-size: 8.33333%; 4 | flex-basis: 8.33333%; 5 | -webkit-flex-basis: -webkit-calc(100% / 12 * 1); 6 | -ms-flex-preferred-size: calc(100% / 12 * 1); 7 | flex-basis: calc(100% / 12 * 1); 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/double.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | flex-basis: 8.33333%; 3 | flex-basis: calc(100% / 12 * 1); 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/element.css: -------------------------------------------------------------------------------- 1 | div { 2 | background: -moz-element(#id); 3 | background: element(#id); 4 | } 5 | 6 | div { 7 | background: url(image.jpg), -moz-element(#id); 8 | background: url(image.jpg), element(#id); 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/element.out.css: -------------------------------------------------------------------------------- 1 | div { 2 | background: element(#id); 3 | } 4 | 5 | div { 6 | background: url(image.jpg), element(#id); 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/example.css: -------------------------------------------------------------------------------- 1 | :-webkit-full-screen a { 2 | display: -webkit-box; 3 | display: flex; 4 | } 5 | 6 | :-moz-full-screen a { 7 | display: flex; 8 | } 9 | 10 | :-ms-fullscreen a { 11 | display: -ms-flexbox; 12 | display: flex; 13 | } 14 | 15 | :fullscreen a { 16 | display: -webkit-box; 17 | display: -ms-flexbox; 18 | display: flex; 19 | } 20 | -------------------------------------------------------------------------------- /test/fixtures/example.out.css: -------------------------------------------------------------------------------- 1 | :fullscreen a { 2 | display: flex; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/filter.css: -------------------------------------------------------------------------------- 1 | a { 2 | -webkit-filter: blur(10px); 3 | -webkit-transition: -webkit-filter 2s; 4 | transition: -webkit-filter 2s; 5 | transition: filter 2s, -webkit-filter 2s; 6 | } 7 | 8 | a { 9 | -webkit-filter: blur(10px); 10 | filter: blur(10px); 11 | -webkit-transition: -webkit-filter 2s; 12 | transition: -webkit-filter 2s; 13 | transition: filter 2s; 14 | transition: filter 2s, -webkit-filter 2s; 15 | } 16 | 17 | div { 18 | filter: progid:DXImageTransform.Microsoft.Alpha(opacity=50); 19 | } 20 | 21 | b { 22 | filter: alpha(opacity=100); 23 | } 24 | 25 | em { 26 | filter: Alpha(opacity=100); 27 | } 28 | 29 | b { 30 | filter: progid:DXImageTransform.Microsoft.Alpha(opacity=100); 31 | } 32 | -------------------------------------------------------------------------------- /test/fixtures/filter.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | filter: blur(10px); 3 | transition: filter 2s; 4 | } 5 | 6 | a { 7 | filter: blur(10px); 8 | transition: filter 2s; 9 | } 10 | 11 | div { 12 | filter: progid:DXImageTransform.Microsoft.Alpha(opacity=50); 13 | } 14 | 15 | b { 16 | filter: alpha(opacity=100); 17 | } 18 | 19 | em { 20 | filter: Alpha(opacity=100); 21 | } 22 | 23 | b { 24 | filter: progid:DXImageTransform.Microsoft.Alpha(opacity=100); 25 | } 26 | -------------------------------------------------------------------------------- /test/fixtures/flex-rewrite.css: -------------------------------------------------------------------------------- 1 | .a { 2 | -webkit-box-flex: 0; 3 | -webkit-flex-grow: 0; 4 | -moz-box-flex: 0; 5 | -ms-flex-positive: 0; 6 | flex-grow: 0; 7 | } 8 | 9 | .a { 10 | -webkit-box-flex: 0; 11 | -webkit-flex-grow: 0; 12 | -moz-box-flex: 0; 13 | -ms-flex-positive: 0; 14 | } 15 | -------------------------------------------------------------------------------- /test/fixtures/flex-rewrite.out.css: -------------------------------------------------------------------------------- 1 | .a { 2 | flex-grow: 0; 3 | } 4 | 5 | .a { 6 | flex-grow: 0; 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/flexbox.css: -------------------------------------------------------------------------------- 1 | a { 2 | -js-display: flex; 3 | display: -webkit-box; 4 | display: -webkit-flex; 5 | display: -moz-box; 6 | display: -ms-flexbox; 7 | display: flex; 8 | -webkit-box-orient: horizontal; 9 | -webkit-box-direction: normal; 10 | -webkit-flex-flow: row; 11 | -moz-box-orient: horizontal; 12 | -moz-box-direction: normal; 13 | -ms-flex-flow: row; 14 | flex-flow: row; 15 | -webkit-box-ordinal-group: 1; 16 | -webkit-order: 0; 17 | -moz-box-ordinal-group: 1; 18 | -ms-flex-order: 0; 19 | order: 0; 20 | -webkit-box-flex: 0; 21 | -webkit-flex: 0 1 2; 22 | -moz-box-flex: 0; 23 | -ms-flex: 0 1 2; 24 | flex: 0 1 2; 25 | } 26 | 27 | .inline { 28 | display: -webkit-inline-box; 29 | display: -webkit-inline-flex; 30 | display: -moz-inline-box; 31 | display: -ms-inline-flexbox; 32 | display: inline-flex; 33 | -webkit-align-self: auto; 34 | -ms-flex-item-align: auto; 35 | align-self: auto; 36 | -webkit-align-content: stretch; 37 | -ms-flex-line-pack: stretch; 38 | align-content: stretch; 39 | -webkit-box-flex: 1; 40 | -webkit-flex: auto; 41 | -moz-box-flex: 1; 42 | -ms-flex: auto; 43 | flex: auto; 44 | } 45 | 46 | .a { 47 | display: -webkit-box; 48 | display: -webkit-flex; 49 | display: -moz-box; 50 | display: -ms-flexbox; 51 | display: flex; 52 | -webkit-box-orient: horizontal; 53 | -webkit-box-direction: normal; 54 | -webkit-flex-direction: row; 55 | -moz-box-orient: horizontal; 56 | -moz-box-direction: normal; 57 | -ms-flex-direction: row; 58 | flex-direction: row; 59 | -webkit-box-pack: start; 60 | -webkit-justify-content: flex-start; 61 | -moz-box-pack: start; 62 | -ms-flex-pack: start; 63 | justify-content: flex-start; 64 | -webkit-box-align: start; 65 | -webkit-align-items: flex-start; 66 | -moz-box-align: start; 67 | -ms-flex-align: start; 68 | align-items: flex-start; 69 | -webkit-flex-wrap: nowrap; 70 | -ms-flex-wrap: nowrap; 71 | flex-wrap: nowrap; 72 | -webkit-align-content: flex-start; 73 | -ms-flex-line-pack: start; 74 | align-content: flex-start; 75 | -webkit-align-self: flex-start; 76 | -ms-flex-item-align: start; 77 | align-self: flex-start; 78 | -webkit-box-flex: 0; 79 | -webkit-flex: none; 80 | -moz-box-flex: 0; 81 | -ms-flex: none; 82 | flex: none; 83 | } 84 | 85 | .b { 86 | display: -webkit-box; 87 | display: -webkit-flex; 88 | display: -moz-box; 89 | display: -ms-flexbox; 90 | display: flex; 91 | -webkit-box-orient: horizontal; 92 | -webkit-box-direction: reverse; 93 | -webkit-flex-direction: row-reverse; 94 | -moz-box-orient: horizontal; 95 | -moz-box-direction: reverse; 96 | -ms-flex-direction: row-reverse; 97 | flex-direction: row-reverse; 98 | -webkit-box-pack: end; 99 | -webkit-justify-content: flex-end; 100 | -moz-box-pack: end; 101 | -ms-flex-pack: end; 102 | justify-content: flex-end; 103 | -webkit-box-align: end; 104 | -webkit-align-items: flex-end; 105 | -moz-box-align: end; 106 | -ms-flex-align: end; 107 | align-items: flex-end; 108 | -webkit-flex-wrap: wrap; 109 | -ms-flex-wrap: wrap; 110 | flex-wrap: wrap; 111 | -webkit-align-content: flex-end; 112 | -ms-flex-line-pack: end; 113 | align-content: flex-end; 114 | -webkit-align-self: flex-end; 115 | -ms-flex-item-align: end; 116 | align-self: flex-end; 117 | -webkit-flex-shrink: 1; 118 | -ms-flex-negative: 1; 119 | flex-shrink: 1; 120 | } 121 | 122 | .c { 123 | display: -webkit-box; 124 | display: -webkit-flex; 125 | display: -moz-box; 126 | display: -ms-flexbox; 127 | display: flex; 128 | -webkit-box-orient: vertical; 129 | -webkit-box-direction: normal; 130 | -webkit-flex-direction: column; 131 | -moz-box-orient: vertical; 132 | -moz-box-direction: normal; 133 | -ms-flex-direction: column; 134 | flex-direction: column; 135 | -webkit-box-pack: center; 136 | -webkit-justify-content: center; 137 | -moz-box-pack: center; 138 | -ms-flex-pack: center; 139 | justify-content: center; 140 | -webkit-box-align: center; 141 | -webkit-align-items: center; 142 | -moz-box-align: center; 143 | -ms-flex-align: center; 144 | align-items: center; 145 | -webkit-flex-wrap: reverse-wrap; 146 | -ms-flex-wrap: reverse-wrap; 147 | flex-wrap: reverse-wrap; 148 | -webkit-align-content: center; 149 | -ms-flex-line-pack: center; 150 | align-content: center; 151 | -webkit-align-self: center; 152 | -ms-flex-item-align: center; 153 | align-self: center; 154 | -webkit-flex-basis: auto; 155 | -ms-flex-preferred-size: auto; 156 | flex-basis: auto; 157 | } 158 | 159 | .e { 160 | display: -webkit-box; 161 | display: -webkit-flex; 162 | display: -moz-box; 163 | display: -ms-flexbox; 164 | display: flex; 165 | -webkit-box-orient: vertical; 166 | -webkit-box-direction: reverse; 167 | -webkit-flex-direction: column-reverse; 168 | -moz-box-orient: vertical; 169 | -moz-box-direction: reverse; 170 | -ms-flex-direction: column-reverse; 171 | flex-direction: column-reverse; 172 | -webkit-box-pack: justify; 173 | -webkit-justify-content: space-between; 174 | -moz-box-pack: justify; 175 | -ms-flex-pack: justify; 176 | justify-content: space-between; 177 | -webkit-box-align: baseline; 178 | -webkit-align-items: baseline; 179 | -moz-box-align: baseline; 180 | -ms-flex-align: baseline; 181 | align-items: baseline; 182 | -webkit-align-content: space-between; 183 | -ms-flex-line-pack: justify; 184 | align-content: space-between; 185 | -webkit-align-self: baseline; 186 | -ms-flex-item-align: baseline; 187 | align-self: baseline; 188 | } 189 | 190 | .f { 191 | display: -webkit-box; 192 | display: -webkit-flex; 193 | display: -moz-box; 194 | display: -ms-flexbox; 195 | display: flex; 196 | -webkit-justify-content: space-around; 197 | -ms-flex-pack: distribute; 198 | justify-content: space-around; 199 | -webkit-box-align: stretch; 200 | -webkit-align-items: stretch; 201 | -moz-box-align: stretch; 202 | -ms-flex-align: stretch; 203 | align-items: stretch; 204 | -webkit-align-content: space-around; 205 | -ms-flex-line-pack: distribute; 206 | align-content: space-around; 207 | -webkit-align-self: stretch; 208 | -ms-flex-item-align: stretch; 209 | align-self: stretch; 210 | } 211 | 212 | .g { 213 | display: -webkit-box; 214 | display: -webkit-flex; 215 | display: -moz-box; 216 | display: -ms-flexbox; 217 | display: flex; 218 | -webkit-box-flex: -webkit-calc(1em + 1px); 219 | -webkit-flex: -webkit-calc(1em + 1px) 0 0; 220 | -moz-box-flex: calc(1em + 1px); 221 | -ms-flex: calc(1em + 1px) 0 0px; 222 | flex: calc(1em + 1px) 0 0; 223 | } 224 | 225 | .h { 226 | -webkit-box-orient: vertical; 227 | -webkit-box-direction: normal; 228 | -webkit-flex-flow: column wrap; 229 | -moz-box-orient: vertical; 230 | -moz-box-direction: normal; 231 | -ms-flex-flow: column wrap; 232 | flex-flow: column wrap; 233 | } 234 | 235 | .i { 236 | -webkit-flex-flow: nowrap; 237 | -ms-flex-flow: nowrap; 238 | flex-flow: nowrap; 239 | } 240 | 241 | .inherit { 242 | -webkit-box-ordinal-group: inherit; 243 | -webkit-order: inherit; 244 | -moz-box-ordinal-group: inherit; 245 | -ms-flex-order: inherit; 246 | order: inherit; 247 | } 248 | 249 | a { 250 | -js-display: flex; 251 | display: -webkit-box; 252 | display: -webkit-flex; 253 | display: -moz-box; 254 | display: -ms-flexbox; 255 | -webkit-flex-flow: row; 256 | -ms-flex-flow: row; 257 | -webkit-box-ordinal-group: 1; 258 | -webkit-order: 0; 259 | -moz-box-ordinal-group: 1; 260 | -ms-flex-order: 0; 261 | -moz-box-flex: 0; 262 | -ms-flex: 0 1 2; 263 | -webkit-transition: -webkit-box-flex 200ms, -webkit-flex 200ms; 264 | } 265 | 266 | .inline { 267 | -webkit-align-self: auto; 268 | -ms-flex-item-align: auto; 269 | -webkit-align-content: stretch; 270 | -ms-flex-line-pack: stretch; 271 | -moz-box-flex: 1; 272 | -ms-flex: auto; 273 | } 274 | 275 | .a { 276 | -webkit-flex-direction: row; 277 | -moz-box-orient: horizontal; 278 | -moz-box-direction: normal; 279 | -ms-flex-direction: row; 280 | -webkit-justify-content: flex-start; 281 | -moz-box-pack: start; 282 | -ms-flex-pack: start; 283 | -webkit-align-items: flex-start; 284 | -moz-box-align: start; 285 | -ms-flex-align: start; 286 | -webkit-flex-wrap: nowrap; 287 | -ms-flex-wrap: nowrap; 288 | -webkit-align-content: flex-start; 289 | -ms-flex-line-pack: start; 290 | -webkit-align-self: flex-start; 291 | -ms-flex-item-align: start; 292 | -moz-box-flex: 0; 293 | -ms-flex: none; 294 | } 295 | 296 | .b { 297 | -webkit-flex-direction: row-reverse; 298 | -moz-box-orient: horizontal; 299 | -moz-box-direction: reverse; 300 | -ms-flex-direction: row-reverse; 301 | -webkit-justify-content: flex-end; 302 | -moz-box-pack: end; 303 | -ms-flex-pack: end; 304 | -webkit-align-items: flex-end; 305 | -moz-box-align: end; 306 | -ms-flex-align: end; 307 | -webkit-flex-wrap: wrap; 308 | -ms-flex-wrap: wrap; 309 | -webkit-align-content: flex-end; 310 | -ms-flex-line-pack: end; 311 | -webkit-align-self: flex-end; 312 | -ms-flex-item-align: end; 313 | -webkit-flex-shrink: 1; 314 | -ms-flex-negative: 1; 315 | } 316 | 317 | .c { 318 | -webkit-flex-direction: column; 319 | -moz-box-orient: vertical; 320 | -moz-box-direction: normal; 321 | -ms-flex-direction: column; 322 | -webkit-box-pack: center; 323 | -webkit-justify-content: center; 324 | -moz-box-pack: center; 325 | -ms-flex-pack: center; 326 | -webkit-box-align: center; 327 | -webkit-align-items: center; 328 | -moz-box-align: center; 329 | -ms-flex-align: center; 330 | -webkit-flex-wrap: reverse-wrap; 331 | -ms-flex-wrap: reverse-wrap; 332 | -webkit-align-content: center; 333 | -ms-flex-line-pack: center; 334 | -webkit-align-self: center; 335 | -ms-flex-item-align: center; 336 | -webkit-flex-basis: auto; 337 | -ms-flex-preferred-size: auto; 338 | } 339 | 340 | .e { 341 | -webkit-flex-direction: column-reverse; 342 | -moz-box-orient: vertical; 343 | -moz-box-direction: reverse; 344 | -ms-flex-direction: column-reverse; 345 | -webkit-justify-content: space-between; 346 | -moz-box-pack: justify; 347 | -ms-flex-pack: justify; 348 | -webkit-box-align: baseline; 349 | -webkit-align-items: baseline; 350 | -moz-box-align: baseline; 351 | -ms-flex-align: baseline; 352 | -webkit-align-content: space-between; 353 | -ms-flex-line-pack: justify; 354 | -webkit-align-self: baseline; 355 | -ms-flex-item-align: baseline; 356 | } 357 | 358 | .f { 359 | -webkit-justify-content: space-around; 360 | -ms-flex-pack: distribute; 361 | -webkit-box-align: stretch; 362 | -webkit-align-items: stretch; 363 | -moz-box-align: stretch; 364 | -ms-flex-align: stretch; 365 | -webkit-align-content: space-around; 366 | -ms-flex-line-pack: distribute; 367 | -webkit-align-self: stretch; 368 | -ms-flex-item-align: stretch; 369 | } 370 | 371 | .g { 372 | -moz-box-flex: calc(1em + 1px); 373 | -ms-flex: calc(1em + 1px) 0 0; 374 | } 375 | 376 | .h { 377 | -moz-box-direction: reverse; 378 | } 379 | 380 | .i { 381 | -moz-box-direction: normal; 382 | } 383 | 384 | .j { 385 | -moz-box-direction: error; 386 | } 387 | 388 | .k { 389 | -ms-box-direction: bt; 390 | -moz-box-orient: row; 391 | } 392 | 393 | 394 | .l { 395 | -ms-box-direction: bt; 396 | -moz-box-orient: column; 397 | } 398 | 399 | .m { 400 | -ms-box-direction: normal; 401 | -moz-box-orient: row; 402 | } 403 | 404 | 405 | .n { 406 | -ms-box-direction: normal; 407 | -moz-box-orient: column; 408 | } 409 | 410 | .o { 411 | -moz-box-orient: vertical; 412 | } 413 | 414 | .p { 415 | -moz-box-orient: vertical; 416 | -ms-box-direction: error; 417 | } 418 | -------------------------------------------------------------------------------- /test/fixtures/flexbox.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | display: flex; 3 | flex-flow: row; 4 | order: 0; 5 | flex: 0 1 2; 6 | } 7 | 8 | .inline { 9 | display: inline-flex; 10 | align-self: auto; 11 | align-content: stretch; 12 | flex: auto; 13 | } 14 | 15 | .a { 16 | display: flex; 17 | flex-direction: row; 18 | justify-content: flex-start; 19 | align-items: flex-start; 20 | flex-wrap: nowrap; 21 | align-content: flex-start; 22 | align-self: flex-start; 23 | flex: none; 24 | } 25 | 26 | .b { 27 | display: flex; 28 | flex-direction: row-reverse; 29 | justify-content: flex-end; 30 | align-items: flex-end; 31 | flex-wrap: wrap; 32 | align-content: flex-end; 33 | align-self: flex-end; 34 | flex-shrink: 1; 35 | } 36 | 37 | .c { 38 | display: flex; 39 | flex-direction: column; 40 | justify-content: center; 41 | align-items: center; 42 | flex-wrap: reverse-wrap; 43 | align-content: center; 44 | align-self: center; 45 | flex-basis: auto; 46 | } 47 | 48 | .e { 49 | display: flex; 50 | flex-direction: column-reverse; 51 | justify-content: space-between; 52 | align-items: baseline; 53 | align-content: space-between; 54 | align-self: baseline; 55 | } 56 | 57 | .f { 58 | display: flex; 59 | justify-content: space-around; 60 | align-items: stretch; 61 | align-content: space-around; 62 | align-self: stretch; 63 | } 64 | 65 | .g { 66 | display: flex; 67 | flex: calc(1em + 1px) 0 0; 68 | } 69 | 70 | .h { 71 | flex-flow: column wrap; 72 | } 73 | 74 | .i { 75 | flex-flow: nowrap; 76 | } 77 | 78 | .inherit { 79 | order: inherit; 80 | } 81 | 82 | a { 83 | display: flex; 84 | flex-flow: row; 85 | order: 0; 86 | flex: 0 1 2; 87 | transition: flex 200ms; 88 | } 89 | 90 | .inline { 91 | align-self: auto; 92 | align-content: stretch; 93 | flex: auto; 94 | } 95 | 96 | .a { 97 | flex-direction: row; 98 | justify-content: flex-start; 99 | align-items: flex-start; 100 | flex-wrap: nowrap; 101 | align-content: flex-start; 102 | align-self: flex-start; 103 | flex: none; 104 | } 105 | 106 | .b { 107 | flex-direction: row-reverse; 108 | justify-content: flex-end; 109 | align-items: flex-end; 110 | flex-wrap: wrap; 111 | align-content: flex-end; 112 | align-self: flex-end; 113 | flex-shrink: 1; 114 | } 115 | 116 | .c { 117 | flex-direction: column; 118 | justify-content: center; 119 | align-items: center; 120 | flex-wrap: reverse-wrap; 121 | align-content: center; 122 | align-self: center; 123 | flex-basis: auto; 124 | } 125 | 126 | .e { 127 | flex-direction: column-reverse; 128 | justify-content: space-between; 129 | align-items: baseline; 130 | align-content: space-between; 131 | align-self: baseline; 132 | } 133 | 134 | .f { 135 | justify-content: space-around; 136 | align-items: stretch; 137 | align-content: space-around; 138 | align-self: stretch; 139 | } 140 | 141 | .g { 142 | flex: calc(1em + 1px) 0 0; 143 | } 144 | 145 | .h { 146 | flex-direction: row-reverse; 147 | } 148 | 149 | .i { 150 | flex-direction: row; 151 | } 152 | 153 | .j { 154 | flex-direction: row; 155 | } 156 | 157 | .k { 158 | flex-direction: column-reverse; 159 | } 160 | 161 | 162 | .l { 163 | flex-direction: column-reverse; 164 | } 165 | 166 | .m { 167 | flex-direction: row; 168 | } 169 | 170 | 171 | .n { 172 | flex-direction: row; 173 | } 174 | 175 | .o { 176 | flex-direction: column; 177 | } 178 | 179 | .p { 180 | flex-direction: column; 181 | } 182 | -------------------------------------------------------------------------------- /test/fixtures/fullscreen.css: -------------------------------------------------------------------------------- 1 | :-webkit-full-screen { 2 | background: black; 3 | } 4 | 5 | :fullscreen { 6 | background: black; 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/fullscreen.out.css: -------------------------------------------------------------------------------- 1 | :fullscreen { 2 | background: black; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/gradient-fix.css: -------------------------------------------------------------------------------- 1 | .test { 2 | background-image: -webkit-linear-gradient(yellow 50%, red 50%); 3 | background-image: -webkit-linear-gradient(red 50%); 4 | background-image: -o-linear-gradient(red 50%); 5 | background-image: linear-gradient(to, red 50%); 6 | } 7 | -------------------------------------------------------------------------------- /test/fixtures/gradient-fix.out.css: -------------------------------------------------------------------------------- 1 | .test { 2 | background-image: linear-gradient(to, red 50%); 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/gradient.css: -------------------------------------------------------------------------------- 1 | a { 2 | background: -webkit-linear-gradient(99.5deg, white, black), -webkit-linear-gradient(220deg, black, white), -webkit-linear-gradient(45deg, black, white); 3 | background: -o-linear-gradient(99.5deg, white, black), -o-linear-gradient(220deg, black, white), -o-linear-gradient(45deg, black, white); 4 | background: linear-gradient(350.5deg, white, black), linear-gradient(-130deg, black, white), linear-gradient(45deg, black, white); 5 | } 6 | 7 | b { 8 | 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)); 9 | background-image: -webkit-linear-gradient(rgba(0, 0, 0, 1), white), -webkit-linear-gradient(white, black); 10 | background-image: -o-linear-gradient(rgba(0, 0, 0, 1), white), -o-linear-gradient(white, black); 11 | background-image: linear-gradient(rgba(0, 0, 0, 1), white), linear-gradient(white, black); 12 | } 13 | 14 | strong { 15 | background: -webkit-linear-gradient(bottom, transparent, rgba(0, 0, 0, 0.8) 20px, #000 30px, #000) no-repeat; 16 | background: -o-linear-gradient(bottom, transparent, rgba(0, 0, 0, 0.8) 20px, #000 30px, #000) no-repeat; 17 | background: linear-gradient(to top, transparent, rgba(0, 0, 0, 0.8) 20px, #000 30px, #000) no-repeat; 18 | } 19 | 20 | div { 21 | background-image: -webkit-radial-gradient(right, white, black), -webkit-repeating-linear-gradient(top left, black, white), -webkit-repeating-radial-gradient(bottom, aqua, red); 22 | background-image: -o-radial-gradient(right, white, black), -o-repeating-linear-gradient(top left, black, white), -o-repeating-radial-gradient(bottom, aqua, red); 23 | background-image: radial-gradient(to left, white, black), repeating-linear-gradient(to bottom right, black, white), repeating-radial-gradient(to top, aqua, red); 24 | } 25 | 26 | .radial { 27 | background: -webkit-radial-gradient(ellipse farthest-corner, black, white); 28 | background: -o-radial-gradient(ellipse farthest-corner, black, white); 29 | background: radial-gradient(ellipse farthest-corner, black, white); 30 | } 31 | 32 | .simple1 { 33 | background: -webkit-gradient(linear, left top, left bottom, from(black), to(white)); 34 | background: -webkit-linear-gradient(black, white); 35 | background: -o-linear-gradient(black, white); 36 | background: linear-gradient(black, white); 37 | } 38 | 39 | .simple2 { 40 | background: -webkit-gradient(linear, right top, left top, from(black), color-stop(50%, rgba(0, 0, 0, 0.5)), to(white)); 41 | background: -webkit-linear-gradient(right, black 0%, rgba(0, 0, 0, 0.5)50%, white 100%); 42 | background: -o-linear-gradient(right, black 0%, rgba(0, 0, 0, 0.5)50%, white 100%); 43 | background: linear-gradient(to left, black 0%, rgba(0, 0, 0, 0.5)50%, white 100%); 44 | } 45 | 46 | .simple3 { 47 | background: -webkit-gradient(linear, right top, left top, color-stop(50%, black), to(white)); 48 | background: -webkit-linear-gradient(right, black 50%, white 100%); 49 | background: -o-linear-gradient(right, black 50%, white 100%); 50 | background: linear-gradient(to left, black 50%, white 100%); 51 | } 52 | 53 | .simple4 { 54 | background: -webkit-gradient(linear, left bottom, right top, from(black), to(white)); 55 | background: -webkit-linear-gradient(left bottom, black, white); 56 | background: -o-linear-gradient(left bottom, black, white); 57 | background: linear-gradient(to right top, black, white); 58 | } 59 | 60 | .direction { 61 | background: -webkit-gradient(linear, left top, right bottom, from(black), color-stop(rgba(0, 0, 0, 0.5)), to(white)); 62 | background: -webkit-linear-gradient(top left, black, rgba(0, 0, 0, 0.5), white); 63 | background: -o-linear-gradient(top left, black, rgba(0, 0, 0, 0.5), white); 64 | background: linear-gradient(top left, black, rgba(0, 0, 0, 0.5), white); 65 | } 66 | 67 | .silent { 68 | background: -webkit-linear-gradient(top left, black, white); 69 | } 70 | 71 | .radial { 72 | background: -webkit-radial-gradient(0 50%, farthest-side, white, black); 73 | background: -o-radial-gradient(0 50%, farthest-side, white, black); 74 | background: radial-gradient(farthest-side at 0 50%, white, black); 75 | } 76 | 77 | .second { 78 | background: red -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); 79 | background: red -webkit-linear-gradient(red, blue); 80 | background: red -o-linear-gradient(red, blue); 81 | background: red linear-gradient(red, blue); 82 | background: url('logo.png'), -webkit-gradient(linear, left top, left bottom, from(#fff), to(#000)); 83 | background: url('logo.png'), -webkit-linear-gradient(#fff, #000); 84 | background: url('logo.png'), -o-linear-gradient(#fff, #000); 85 | background: url('logo.png'), linear-gradient(#fff, #000); 86 | } 87 | 88 | .px { 89 | background: -webkit-linear-gradient(black 0, white 100px); 90 | background: -o-linear-gradient(black 0, white 100px); 91 | background: linear-gradient(black 0, white 100px); 92 | } 93 | 94 | .list { 95 | list-style-image: -webkit-gradient(linear, left top, left bottom, from(white), to(black)); 96 | list-style-image: -webkit-linear-gradient(white, black); 97 | list-style-image: linear-gradient(white, black); 98 | } 99 | 100 | .mask { 101 | -webkit-mask: -webkit-gradient(linear, left top, left bottom, from(white), to(black)); 102 | -webkit-mask: -webkit-linear-gradient(white, black); 103 | mask: -webkit-gradient(linear, left top, left bottom, from(white), to(black)); 104 | mask: linear-gradient(white, black); 105 | } 106 | 107 | .newline { 108 | background-image: -webkit-gradient(linear, left top, left bottom, from(white), to(black)), -webkit-gradient(linear, left top, left bottom, from(black), to(white)); 109 | background-image: -webkit-linear-gradient(white, black), -webkit-linear-gradient(black, white); 110 | background-image: -o-linear-gradient(white, black), -o-linear-gradient(black, white); 111 | background-image: linear-gradient(white, black), linear-gradient(black, white); 112 | } 113 | 114 | .convert { 115 | background: -webkit-gradient(linear, right top, left top, from(white), to(black)); 116 | background: -webkit-linear-gradient(right, white, black); 117 | background: -o-linear-gradient(right, white, black); 118 | background: linear-gradient(270deg, white, black); 119 | } 120 | 121 | .rad { 122 | background: -webkit-linear-gradient(32.704deg, white, black); 123 | background: -o-linear-gradient(32.704deg, white, black); 124 | background: linear-gradient(1rad, white, black); 125 | } 126 | 127 | .turn { 128 | background: -webkit-linear-gradient(342deg, white, black); 129 | background: -o-linear-gradient(342deg, white, black); 130 | background: linear-gradient(0.3turn, white, black); 131 | } 132 | 133 | .norm { 134 | background: -webkit-linear-gradient(0, white, black); 135 | background: -o-linear-gradient(11111deg, white, black); 136 | } 137 | 138 | .left1 { 139 | background: -webkit-linear-gradient(0.4deg, white, black); 140 | } 141 | 142 | .left2 { 143 | background: -webkit-linear-gradient(0.1grad, white, black); 144 | } 145 | 146 | .left3 { 147 | background: -webkit-linear-gradient(0, white, black); 148 | } 149 | 150 | .left4 { 151 | background: -webkit-linear-gradient(0.1turn, white, black); 152 | } 153 | 154 | .old-simple1 { 155 | background: -webkit-gradient(linear, 0 0, 100% 100%, from(black), to(white)); 156 | } 157 | 158 | .old-simple2 { 159 | background: -webkit-gradient(linear, right top, left top, from(black), color-stop(50%, rgba(0, 0, 0, .5)), to(white)); 160 | } 161 | 162 | .old-simple3 { 163 | background: -webkit-gradient(linear, right top, left top, color-stop(50%, black), to(white)); 164 | } 165 | 166 | .old-simple4 { 167 | background: -webkit-gradient(linear, left bottom, right top, from(black), to(white)); 168 | } 169 | 170 | .old-direction { 171 | background: -webkit-gradient(linear, left top, right bottom, from(black), color-stop(50%, rgba(0, 0, 0, .5)), to(white)); 172 | } 173 | 174 | .old-second { 175 | background: red -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); 176 | } 177 | 178 | .old-list { 179 | list-style-image: -webkit-gradient(linear, left top, left bottom, from(white), to(black)); 180 | } 181 | 182 | .old-mask { 183 | -webkit-mask: -webkit-gradient(linear, left top, left bottom, from(white), to(black)); 184 | } 185 | 186 | .old-newline { 187 | background-image: -webkit-gradient(linear, left top, left bottom, from(white), to(black)), -webkit-gradient(linear, left top, left bottom, from(black), to(white)); 188 | } 189 | 190 | .old-convert { 191 | background: -webkit-gradient(linear, right top, left top, from(white), to(black)); 192 | } 193 | 194 | .old-rad { 195 | background: -webkit-gradient(linear, left top, left bottom, from(white), to(black)); 196 | } 197 | 198 | .old-norm { 199 | background: -webkit-gradient(linear, right top, left top, from(white), to(black)); 200 | } 201 | 202 | .radia-test { 203 | background-image: -webkit-gradient(radial, 45 45, 10, 52 50, 30, from(#a7d30c), to(rgba(1, 159, 98, 0)), color-stop(90%, #019f62)), -webkit-gradient(radial, 105 105, 20, 112 120, 50, from(#ff5f98), to(rgba(255, 1, 136, 0)), color-stop(75%, #ff0188)), -webkit-gradient(radial, 95 15, 15, 102 20, 40, from(#00c9ff), to(rgba(0, 201, 255, 0)), color-stop(80%, #00b5e2)), -webkit-gradient(radial, 0 150, 50, 0 140, 90, from(#f4f201), to(rgba(228, 199, 0, 0)), color-stop(80%, #e4c700)); 204 | } 205 | 206 | .cov-1 { 207 | background: -webkit-gradient(linear, left bottom, left top, color-stop(white, 0)); 208 | -webkit-mask: -webkit-radial-gradient(white, black); 209 | } 210 | 211 | .cov-2 { 212 | background: -webkit-linear-gradient(0err, white, black); 213 | -webkit-mask: -webkit-linear-gradient(1err, white, black); 214 | } 215 | 216 | .cov-3 { 217 | background: -webkit-linear-gradient(270deg, white, black); 218 | } 219 | 220 | .cov-3 { 221 | background: -webkit-linear-gradient(top, white, black); 222 | } 223 | 224 | .cov-4 { 225 | background: -webkit-gradient(radial, 0 150, 50, 0 140, err, from(#f4f201), to(rgba(228, 199, 0, 0)), color-stop(80%, #e4c700)); 226 | } 227 | 228 | .cov-5 { 229 | background: -webkit-gradient(radial, 0 150, 50, 0 140, 5err, from(#f4f201), to(rgba(228, 199, 0, 0)), color-stop(80%, #e4c700)); 230 | } 231 | 232 | .cov-6 { 233 | background: -webkit-gradient(radial, 0 150, from(#f4f201), to(rgba(228, 199, 0, 0)), color-stop(80%, #e4c700)); 234 | } 235 | 236 | .cov-7 { 237 | background: -webkit-gradient(radial, from(#f4f201), to(rgba(228, 199, 0, 0)), color-stop(80%, #e4c700)); 238 | } 239 | 240 | .cov-8 { 241 | background: -webkit-radial-gradient(0 50%, contain, white, black); 242 | } 243 | -------------------------------------------------------------------------------- /test/fixtures/gradient.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | background: linear-gradient(350.5deg, white, black), linear-gradient(-130deg, black, white), linear-gradient(45deg, black, white); 3 | } 4 | 5 | b { 6 | background-image: linear-gradient(rgba(0, 0, 0, 1), white), linear-gradient(white, black); 7 | } 8 | 9 | strong { 10 | background: linear-gradient(to top, transparent, rgba(0, 0, 0, 0.8) 20px, #000 30px, #000) no-repeat; 11 | } 12 | 13 | div { 14 | background-image: radial-gradient(to left, white, black), repeating-linear-gradient(to bottom right, black, white), repeating-radial-gradient(to top, aqua, red); 15 | } 16 | 17 | .radial { 18 | background: radial-gradient(ellipse farthest-corner, black, white); 19 | } 20 | 21 | .simple1 { 22 | background: linear-gradient(black, white); 23 | } 24 | 25 | .simple2 { 26 | background: linear-gradient(to left, black 0%, rgba(0, 0, 0, 0.5)50%, white 100%); 27 | } 28 | 29 | .simple3 { 30 | background: linear-gradient(to left, black 50%, white 100%); 31 | } 32 | 33 | .simple4 { 34 | background: linear-gradient(to right top, black, white); 35 | } 36 | 37 | .direction { 38 | background: linear-gradient(top left, black, rgba(0, 0, 0, 0.5), white); 39 | } 40 | 41 | .silent { 42 | background: linear-gradient(to bottom right, black, white); 43 | } 44 | 45 | .radial { 46 | background: radial-gradient(farthest-side at 0 50%, white, black); 47 | } 48 | 49 | .second { 50 | background: red linear-gradient(red, blue); 51 | background: url('logo.png'), linear-gradient(#fff, #000); 52 | } 53 | 54 | .px { 55 | background: linear-gradient(black 0, white 100px); 56 | } 57 | 58 | .list { 59 | list-style-image: linear-gradient(white, black); 60 | } 61 | 62 | .mask { 63 | mask: linear-gradient(white, black); 64 | } 65 | 66 | .newline { 67 | background-image: linear-gradient(white, black), linear-gradient(black, white); 68 | } 69 | 70 | .convert { 71 | background: linear-gradient(270deg, white, black); 72 | } 73 | 74 | .rad { 75 | background: linear-gradient(1rad, white, black); 76 | } 77 | 78 | .turn { 79 | background: linear-gradient(0.3turn, white, black); 80 | } 81 | 82 | .norm { 83 | background: linear-gradient(139deg, white, black); 84 | } 85 | 86 | .left1 { 87 | background: linear-gradient(to right, white, black); 88 | } 89 | 90 | .left2 { 91 | background: linear-gradient(to right, white, black); 92 | } 93 | 94 | .left3 { 95 | background: linear-gradient(to right, white, black); 96 | } 97 | 98 | .left4 { 99 | background: linear-gradient(0.15turn, white, black); 100 | } 101 | 102 | .old-simple1 { 103 | background: linear-gradient(135deg, black, white); 104 | } 105 | 106 | .old-simple2 { 107 | background: linear-gradient(270deg, black, rgba(0, 0, 0, .5), white); 108 | } 109 | 110 | .old-simple3 { 111 | background: linear-gradient(270deg, black 50%, white); 112 | } 113 | 114 | .old-simple4 { 115 | background: linear-gradient(45deg, black, white); 116 | } 117 | 118 | .old-direction { 119 | background: linear-gradient(135deg, black, rgba(0, 0, 0, .5), white); 120 | } 121 | 122 | .old-second { 123 | background: red linear-gradient(red, blue); 124 | } 125 | 126 | .old-list { 127 | list-style-image: linear-gradient(white, black); 128 | } 129 | 130 | .old-mask { 131 | mask: linear-gradient(white, black); 132 | } 133 | 134 | .old-newline { 135 | background-image: linear-gradient(white, black), linear-gradient(black, white); 136 | } 137 | 138 | .old-convert { 139 | background: linear-gradient(270deg, white, black); 140 | } 141 | 142 | .old-rad { 143 | background: linear-gradient(white, black); 144 | } 145 | 146 | .old-norm { 147 | background: linear-gradient(270deg, white, black); 148 | } 149 | 150 | .radia-test { 151 | background-image: radial-gradient(30px at 45px 45px, #a7d30c, #019f62 90%, rgba(1, 159, 98, 0)), radial-gradient(50px at 105px 105px, #ff5f98, #ff0188 75%, rgba(255, 1, 136, 0)), radial-gradient(40px at 95px 15px, #00c9ff, #00b5e2 80%, rgba(0, 201, 255, 0)), radial-gradient(90px at 0 150px, #f4f201, #e4c700 80%, rgba(228, 199, 0, 0)); 152 | } 153 | 154 | .cov-1 { 155 | background: linear-gradient(0, white 0); 156 | mask: radial-gradient(white, black); 157 | } 158 | 159 | .cov-2 { 160 | background: linear-gradient(to right, white, black); 161 | mask: linear-gradient(1err, white, black); 162 | } 163 | 164 | .cov-3 { 165 | background: linear-gradient(white, black); 166 | } 167 | 168 | .cov-3 { 169 | background: linear-gradient(white, black); 170 | } 171 | 172 | .cov-4 { 173 | background: radial-gradient(err at 0 150px, #f4f201, #e4c700 80%, rgba(228, 199, 0, 0)); 174 | } 175 | 176 | .cov-5 { 177 | background: radial-gradient(5err at 0 150px, #f4f201, #e4c700 80%, rgba(228, 199, 0, 0)); 178 | } 179 | 180 | .cov-6 { 181 | background: radial-gradient(at 0 150px, #f4f201, #e4c700 80%, rgba(228, 199, 0, 0)); 182 | } 183 | 184 | .cov-7 { 185 | background: radial-gradient(#f4f201, #e4c700 80%, rgba(228, 199, 0, 0)); 186 | } 187 | 188 | .cov-8 { 189 | background: radial-gradient(closest-side at 0 50%, white, black); 190 | } 191 | -------------------------------------------------------------------------------- /test/fixtures/grid.css: -------------------------------------------------------------------------------- 1 | .a { 2 | display: -ms-grid; 3 | display: grid; 4 | -ms-grid-columns: auto 1fr; 5 | grid-template-columns: auto 1fr; 6 | -ms-grid-column-align: stretch; 7 | justify-items: stretch; 8 | -ms-grid-row-align: stretch; 9 | align-self: stretch; 10 | -ms-grid-column: 1; 11 | grid-column-start: 1; 12 | grid-column-end: span 3; 13 | } 14 | 15 | .b { 16 | display: -ms-inline-grid; 17 | display: inline-grid; 18 | -ms-grid-rows: 10px (250px 10px)[4] 20px; 19 | grid-template-rows: 10px repeat(4, 250px 10px) 20px; 20 | -ms-grid-row-align: stretch; 21 | align-self: stretch; 22 | -ms-grid-row: 1; 23 | grid-row-start: 1; 24 | grid-row-end: span 3; 25 | } 26 | 27 | .c { 28 | -ms-grid-column: 1; 29 | grid-column: 1 / span 3; 30 | } 31 | 32 | .webkit { 33 | grid: subgrid; 34 | grid-template-areas: "head head" "nav main" "foot ...."; 35 | } 36 | 37 | .unknown { 38 | -webkit-align-self: start; 39 | -ms-flex-item-align: start; 40 | -ms-grid-row-align: start; 41 | align-self: start; 42 | } 43 | 44 | .flex { 45 | -webkit-align-self: flex-end; 46 | -ms-flex-item-align: end; 47 | align-self: flex-end; 48 | } 49 | 50 | @supports ((display: -ms-grid) or (display: grid)) { 51 | .foo { 52 | display: -ms-grid; 53 | display: grid; 54 | } 55 | } 56 | 57 | .a { 58 | -webkit-grid-template-columns: auto 1fr; 59 | -ms-grid-columns: auto 1fr; 60 | -ms-grid-column-align: stretch; 61 | -ms-grid-row-align: stretch; 62 | -webkit-grid-column-start: 1; 63 | -ms-grid-column: 1; 64 | -webkit-grid-column-end: span 3; 65 | -ms-grid-column-span: 3; 66 | } 67 | 68 | .b { 69 | -webkit-grid-template-rows: 10px repeat(4, 250px 10px) 20px; 70 | -ms-grid-rows: 10px (250px 10px)[4] 20px; 71 | -ms-grid-row-align: stretch; 72 | -webkit-grid-row-start: 1; 73 | -ms-grid-row: 1; 74 | -webkit-grid-row-end: span 3; 75 | -ms-grid-row-span: 3; 76 | } 77 | 78 | .c { 79 | -webkit-grid-column: 1 / span 3; 80 | -ms-grid-column-span: 3; 81 | -ms-grid-column: 1; 82 | } 83 | 84 | .webkit { 85 | -webkit-grid: subgrid; 86 | grid-template-areas: "head head" "nav main" "foot ...."; 87 | } 88 | 89 | .unknown { 90 | -webkit-align-items: start; 91 | -ms-flex-align: start; 92 | -ms-grid-row-align: start; 93 | -ms-grid-row-unknown: unknown; 94 | } 95 | -------------------------------------------------------------------------------- /test/fixtures/grid.out.css: -------------------------------------------------------------------------------- 1 | .a { 2 | display: grid; 3 | grid-template-columns: auto 1fr; 4 | justify-items: stretch; 5 | align-self: stretch; 6 | grid-column-start: 1; 7 | grid-column-end: span 3; 8 | } 9 | 10 | .b { 11 | display: inline-grid; 12 | grid-template-rows: 10px repeat(4, 250px 10px) 20px; 13 | align-self: stretch; 14 | grid-row-start: 1; 15 | grid-row-end: span 3; 16 | } 17 | 18 | .c { 19 | grid-column: 1 / span 3; 20 | } 21 | 22 | .webkit { 23 | grid: subgrid; 24 | grid-template-areas: "head head" "nav main" "foot ...."; 25 | } 26 | 27 | .unknown { 28 | align-self: start; 29 | } 30 | 31 | .flex { 32 | align-self: flex-end; 33 | } 34 | 35 | @supports (display: grid) { 36 | .foo { 37 | display: grid; 38 | } 39 | } 40 | 41 | .a { 42 | grid-template-columns: auto 1fr; 43 | align-self: stretch; 44 | grid-column-start: 1; 45 | grid-column-end: span 3; 46 | } 47 | 48 | .b { 49 | grid-template-rows: 10px repeat(4, 250px 10px) 20px; 50 | align-self: stretch; 51 | grid-row-start: 1; 52 | grid-row-end: span 3; 53 | } 54 | 55 | .c { 56 | grid-column-end: span 3; 57 | grid-column-start: 1; 58 | } 59 | 60 | .webkit { 61 | grid: subgrid; 62 | grid-template-areas: "head head" "nav main" "foot ...."; 63 | } 64 | 65 | .unknown { 66 | align-items: start; 67 | align-self: flex-start; 68 | -ms-grid-row-unknown: unknown; 69 | } 70 | -------------------------------------------------------------------------------- /test/fixtures/image-rendering.css: -------------------------------------------------------------------------------- 1 | img { 2 | image-rendering: crisp-edges; 3 | } 4 | 5 | img.other { 6 | -ms-interpolation-mode: nearest-neighbor; 7 | image-rendering: -webkit-optimize-contrast; 8 | image-rendering: -moz-crisp-edges; 9 | image-rendering: pixelated; 10 | } 11 | 12 | img.already { 13 | -ms-interpolation-mode: nearest-neighbor; 14 | display: block; 15 | image-rendering: crisp-edges; 16 | image-rendering: -webkit-optimize-contrast; 17 | image-rendering: -moz-crisp-edges; 18 | image-rendering: pixelated; 19 | } 20 | -------------------------------------------------------------------------------- /test/fixtures/image-rendering.out.css: -------------------------------------------------------------------------------- 1 | img { 2 | image-rendering: crisp-edges; 3 | } 4 | 5 | img.other { 6 | image-rendering: pixelated; 7 | } 8 | 9 | img.already { 10 | display: block; 11 | image-rendering: crisp-edges; 12 | image-rendering: pixelated; 13 | } 14 | -------------------------------------------------------------------------------- /test/fixtures/image-set.css: -------------------------------------------------------------------------------- 1 | a { 2 | background-image: -webkit-image-set(url(foo@1x.png) 1x, url(foo@2x.png) 2x); 3 | background-image: image-set(url(foo@1x.png) 1x, url(foo@2x.png) 2x); 4 | } 5 | 6 | h1 { 7 | background-image: -webkit-image-set(url('foo@1x.png') 1x, url("foo@2x.png") 2x); 8 | background-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x); 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/image-set.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | background-image: image-set(url(foo@1x.png) 1x, url(foo@2x.png) 2x); 3 | } 4 | 5 | h1 { 6 | background-image: image-set('foo@1x.png' 1x, "foo@2x.png" 2x); 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/intrinsic.css: -------------------------------------------------------------------------------- 1 | a { 2 | width: -webkit-fill-available; 3 | width: -moz-available; 4 | width: stretch; 5 | } 6 | 7 | b { 8 | height: -webkit-max-content; 9 | height: -moz-max-content; 10 | height: max-content; 11 | } 12 | 13 | p { 14 | block-size: -webkit-min-content; 15 | block-size: -moz-min-content; 16 | block-size: min-content; 17 | min-inline-size: -webkit-fit-content; 18 | min-inline-size: -moz-fit-content; 19 | min-inline-size: fit-content; 20 | } 21 | 22 | .outdated { 23 | width: -webkit-fill-available; 24 | width: -moz-available; 25 | width: fill; 26 | } 27 | 28 | .old { 29 | width: -webkit-fill-available; 30 | width: -moz-available; 31 | width: fill-available; 32 | } 33 | -------------------------------------------------------------------------------- /test/fixtures/intrinsic.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | width: stretch; 3 | } 4 | 5 | b { 6 | height: max-content; 7 | } 8 | 9 | p { 10 | block-size: min-content; 11 | min-inline-size: fit-content; 12 | } 13 | 14 | .outdated { 15 | width: fill; 16 | } 17 | 18 | .old { 19 | width: fill-available; 20 | } 21 | -------------------------------------------------------------------------------- /test/fixtures/keyframes.css: -------------------------------------------------------------------------------- 1 | @-webkit-keyframes anim { 2 | from { 3 | top: -webkit-calc(10% + 10px); 4 | top: calc(10% + 10px); 5 | -webkit-transform: rotate(10deg); 6 | transform: rotate(10deg); 7 | } 8 | 9 | 50% { 10 | top: 0; 11 | display: -webkit-box; 12 | display: -webkit-flex; 13 | display: flex; 14 | } 15 | 16 | to { 17 | top: -webkit-calc(10%); 18 | top: calc(10%); 19 | -webkit-transform: rotate(0); 20 | transform: rotate(0); 21 | } 22 | } 23 | 24 | @-o-keyframes anim { 25 | from { 26 | top: calc(10% + 10px); 27 | -o-transform: rotate(10deg); 28 | transform: rotate(10deg); 29 | } 30 | 31 | 50% { 32 | top: 0; 33 | display: flex; 34 | } 35 | 36 | to { 37 | top: calc(10%); 38 | -o-transform: rotate(0); 39 | transform: rotate(0); 40 | } 41 | } 42 | 43 | @keyframes anim { 44 | from { 45 | top: -webkit-calc(10% + 10px); 46 | top: calc(10% + 10px); 47 | -webkit-transform: rotate(10deg); 48 | -o-transform: rotate(10deg); 49 | transform: rotate(10deg); 50 | } 51 | 52 | 50% { 53 | top: 0; 54 | display: -webkit-box; 55 | display: -webkit-flex; 56 | display: flex; 57 | } 58 | 59 | to { 60 | top: -webkit-calc(10%); 61 | top: calc(10%); 62 | -webkit-transform: rotate(0); 63 | -o-transform: rotate(0); 64 | transform: rotate(0); 65 | } 66 | } 67 | 68 | @media screen { 69 | @-webkit-keyframes inside { 70 | } 71 | 72 | @-o-keyframes inside { 73 | } 74 | 75 | @keyframes inside { 76 | } 77 | } 78 | 79 | @-webkit-keyframes spaces { 80 | from { 81 | color: black; 82 | } 83 | 84 | to { 85 | color: white; 86 | } 87 | } 88 | 89 | @-o-keyframes spaces { 90 | from { 91 | color: black; 92 | } 93 | 94 | to { 95 | color: white; 96 | } 97 | } 98 | 99 | @keyframes spaces { 100 | from { 101 | color: black; 102 | } 103 | 104 | to { 105 | color: white; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /test/fixtures/keyframes.out.css: -------------------------------------------------------------------------------- 1 | @keyframes anim { 2 | from { 3 | top: calc(10% + 10px); 4 | transform: rotate(10deg); 5 | } 6 | 7 | 50% { 8 | top: 0; 9 | display: flex; 10 | } 11 | 12 | to { 13 | top: calc(10%); 14 | transform: rotate(0); 15 | } 16 | } 17 | 18 | @media screen { 19 | 20 | @keyframes inside { 21 | } 22 | } 23 | 24 | @keyframes spaces { 25 | from { 26 | color: black; 27 | } 28 | 29 | to { 30 | color: white; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/fixtures/logical.css: -------------------------------------------------------------------------------- 1 | a { 2 | -webkit-margin-before: 1px; 3 | margin-block-start: 1px; 4 | -webkit-margin-start: 1px; 5 | -moz-margin-start: 1px; 6 | margin-inline-start: 1px; 7 | -webkit-padding-end: 1px; 8 | -moz-padding-end: 1px; 9 | padding-inline-end: 1px; 10 | } 11 | 12 | .border { 13 | -webkit-border-after: 1px; 14 | border-block-end: 1px; 15 | -webkit-border-end: 1px; 16 | -moz-border-end: 1px; 17 | border-inline-end: 1px; 18 | } 19 | 20 | a { 21 | -webkit-margin-before: 1px; 22 | -webkit-margin-start: 1px; 23 | -moz-margin-start: 1px; 24 | -webkit-padding-end: 1px; 25 | -moz-padding-end: 1px; 26 | } 27 | 28 | .border { 29 | -webkit-border-after: 1px; 30 | -webkit-border-end: 1px; 31 | -moz-border-end: 1px; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /test/fixtures/logical.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | margin-block-start: 1px; 3 | margin-inline-start: 1px; 4 | padding-inline-end: 1px; 5 | } 6 | 7 | .border { 8 | border-block-end: 1px; 9 | border-inline-end: 1px; 10 | } 11 | 12 | a { 13 | margin-block-start: 1px; 14 | margin-inline-start: 1px; 15 | padding-inline-end: 1px; 16 | } 17 | 18 | .border { 19 | border-block-end: 1px; 20 | border-inline-end: 1px; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /test/fixtures/mask-border.css: -------------------------------------------------------------------------------- 1 | a { 2 | -webkit-mask-box-image-source: url(image.png); 3 | mask-border-source: url(image.png); 4 | -webkit-mask-box-image-slice: 50% fill; 5 | mask-border-slice: 50% fill; 6 | -webkit-mask-box-image-width: auto 1 50%; 7 | mask-border-width: auto 1 50%; 8 | -webkit-mask-box-image-outset: 0 1 2; 9 | mask-border-outset: 0 1 2; 10 | -webkit-mask-box-image-repeat: repeat space; 11 | mask-border-repeat: repeat space; 12 | -webkit-mask-box-image: url(#foo) 1 fill; 13 | mask-border: url(#foo) 1 fill; 14 | } 15 | 16 | a { 17 | -webkit-mask-box-image-source: url(image.png); 18 | -webkit-mask-box-image-slice: 50% fill; 19 | -webkit-mask-box-image-width: auto 1 50%; 20 | -webkit-mask-box-image-outset: 0 1 2; 21 | -webkit-mask-box-image-repeat: repeat space; 22 | -webkit-mask-box-image: url(#foo) 1 fill; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /test/fixtures/mask-border.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | mask-border-source: url(image.png); 3 | mask-border-slice: 50% fill; 4 | mask-border-width: auto 1 50%; 5 | mask-border-outset: 0 1 2; 6 | mask-border-repeat: repeat space; 7 | mask-border: url(#foo) 1 fill; 8 | } 9 | 10 | a { 11 | mask-border-source: url(image.png); 12 | mask-border-slice: 50% fill; 13 | mask-border-width: auto 1 50%; 14 | mask-border-outset: 0 1 2; 15 | mask-border-repeat: repeat space; 16 | mask-border: url(#foo) 1 fill; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /test/fixtures/mistakes.css: -------------------------------------------------------------------------------- 1 | a { 2 | transition: all 1s; 3 | border-radius: 5px; 4 | background: linear-gradient(white, black); 5 | } 6 | 7 | a { 8 | -ms-transition: all 1s; 9 | -ms-border-radius: 5px; 10 | background: -ms-linear-gradient(white, black); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /test/fixtures/mistakes.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | transition: all 1s; 3 | border-radius: 5px; 4 | background: linear-gradient(white, black); 5 | } 6 | 7 | a { 8 | transition: all 1s; 9 | border-radius: 5px; 10 | background: linear-gradient(white, black); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /test/fixtures/multicolumn.css: -------------------------------------------------------------------------------- 1 | .a { 2 | -webkit-column-break-inside: auto; 3 | page-break-inside: auto; 4 | break-inside: auto; 5 | -webkit-column-break-before: auto; 6 | page-break-before: auto; 7 | break-before: auto; 8 | -webkit-column-break-after: auto; 9 | page-break-after: auto; 10 | break-after: auto; 11 | } 12 | 13 | .b { 14 | -webkit-column-break-inside: avoid; 15 | page-break-inside: avoid; 16 | break-inside: avoid; 17 | } 18 | 19 | .c { 20 | -webkit-column-break-inside: avoid; 21 | page-break-inside: avoid; 22 | break-inside: avoid-column; 23 | } 24 | 25 | .d { 26 | page-break-inside: avoid; 27 | break-inside: avoid-page; 28 | } 29 | 30 | .e { 31 | break-inside: avoid-region; 32 | } 33 | 34 | .a { 35 | -webkit-column-break-inside: auto; 36 | -webkit-column-break-before: auto; 37 | -webkit-column-break-after: auto; 38 | } 39 | 40 | .b { 41 | -webkit-column-break-inside: avoid; 42 | } 43 | 44 | .c { 45 | -webkit-column-break-inside: avoid; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /test/fixtures/multicolumn.out.css: -------------------------------------------------------------------------------- 1 | .a { 2 | break-inside: auto; 3 | break-before: auto; 4 | break-after: auto; 5 | } 6 | 7 | .b { 8 | break-inside: avoid; 9 | } 10 | 11 | .c { 12 | break-inside: avoid-column; 13 | } 14 | 15 | .d { 16 | page-break-inside: avoid; 17 | break-inside: avoid-page; 18 | } 19 | 20 | .e { 21 | break-inside: avoid-region; 22 | } 23 | 24 | .a { 25 | break-inside: auto; 26 | break-before: auto; 27 | break-after: auto; 28 | } 29 | 30 | .b { 31 | break-inside: avoid-column; 32 | } 33 | 34 | .c { 35 | break-inside: avoid-column; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /test/fixtures/nogrid.out.css: -------------------------------------------------------------------------------- 1 | .nosupport { 2 | grid-row-end: 3; 3 | grid-row: 1 / 3; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/notes.css: -------------------------------------------------------------------------------- 1 | a { 2 | display: -webkit-flex; 3 | display: flex; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/notes.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | display: flex; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/pie.css: -------------------------------------------------------------------------------- 1 | a { 2 | -pie-background: linear-gradient(white, black); 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/pie.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | background: linear-gradient(white, black); 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/placeholder.css: -------------------------------------------------------------------------------- 1 | ::-webkit-input-placeholder { 2 | color: #999; 3 | } 4 | 5 | :-moz-placeholder { 6 | color: #999; 7 | } 8 | 9 | ::-moz-placeholder { 10 | color: #999; 11 | } 12 | 13 | :-ms-input-placeholder { 14 | color: #999; 15 | } 16 | 17 | ::placeholder { 18 | color: #999; 19 | } 20 | 21 | :placeholder-shown { 22 | background: #eee; 23 | } 24 | -------------------------------------------------------------------------------- /test/fixtures/placeholder.out.css: -------------------------------------------------------------------------------- 1 | ::placeholder { 2 | color: #999; 3 | } 4 | 5 | :placeholder-shown { 6 | background: #eee; 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/resolution.css: -------------------------------------------------------------------------------- 1 | @media (-webkit-min-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 2dppx), (min-resolution: 192dpi) { 2 | } 3 | 4 | @media (-webkit-min-device-pixel-ratio: 2.5), (-o-min-device-pixel-ratio: 5/2), (min-resolution: 2.5dppx) { 5 | } 6 | 7 | @media (-webkit-min-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2), (min-resolution: 144dpi) { 8 | } 9 | 10 | @media all and (-webkit-min-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2) { 11 | } 12 | 13 | @media all and (-webkit-min-device-pixel-ratio: 3) { 14 | } 15 | 16 | @media all and (-o-min-device-pixel-ratio: 3) { 17 | } 18 | 19 | @media (-webkit-transform-3d) { 20 | } 21 | 22 | @media (min-resolution: 2.5dppx), (-o-device-pixel-ratio: 5/2),(-o-min-device-pixel-ratio: 5/2), (-webkit-transform-3d) { 23 | } 24 | 25 | @media all and (-o-min-device-pixel-ratio: error) { 26 | } 27 | 28 | @media (-o-min-device-pixel-ratio: 5/2), (-webkit-transform-3d) { 29 | } 30 | 31 | @media (-o-min-device-pixel-ratio: 5/2), (max-width: 1cm) { 32 | } 33 | 34 | @media (-o-min-device-pixel-ratio: 5/2), (max-width: 10mm) { 35 | } 36 | 37 | -------------------------------------------------------------------------------- /test/fixtures/resolution.out.css: -------------------------------------------------------------------------------- 1 | @media (min-resolution: 192dpi) { 2 | } 3 | 4 | @media (min-resolution: 2.5dppx) { 5 | } 6 | 7 | @media (min-resolution: 144dpi) { 8 | } 9 | 10 | @media all and (min-resolution: 1.5dppx) { 11 | } 12 | 13 | @media all and (min-resolution: 3dppx) { 14 | } 15 | 16 | @media (-webkit-transform-3d) { 17 | } 18 | 19 | @media (min-resolution: 2.5dppx), (resolution: 2.5dppx), (-webkit-transform-3d) { 20 | } 21 | 22 | @media all and (min-resolution: error) { 23 | } 24 | 25 | @media (min-resolution: 2.5dppx), (-webkit-transform-3d) { 26 | } 27 | 28 | @media (min-resolution: 2.5dppx), (max-width: 1cm) { 29 | } 30 | 31 | -------------------------------------------------------------------------------- /test/fixtures/selectors.css: -------------------------------------------------------------------------------- 1 | [href=':fullscreen'] { 2 | } 3 | 4 | :-webkit-full-screen a { 5 | box-sizing: border-box; 6 | } 7 | 8 | :-moz-full-screen a { 9 | -moz-box-sizing: border-box; 10 | box-sizing: border-box; 11 | } 12 | 13 | :fullscreen a { 14 | -moz-box-sizing: border-box; 15 | box-sizing: border-box; 16 | } 17 | 18 | :-webkit-full-screen a { 19 | color: black; 20 | } 21 | 22 | :-moz-full-screen a { 23 | color: black; 24 | } 25 | 26 | :fullscreen a { 27 | color: black; 28 | } 29 | 30 | :-moz-full-screen a { 31 | transform: translate3d(0, 0, 0); 32 | } 33 | 34 | @media all { 35 | :-moz-full-screen a { 36 | color: black; 37 | } 38 | } 39 | 40 | p::-moz-selection { 41 | color: white; 42 | background: black; 43 | } 44 | 45 | input:-moz-placeholder, input::placeholder { 46 | color: pink; 47 | } 48 | 49 | a[data-foo=":-webkit-full-screen"] { 50 | 51 | } 52 | 53 | .class::-webkit-scrollbar { 54 | } 55 | -------------------------------------------------------------------------------- /test/fixtures/selectors.out.css: -------------------------------------------------------------------------------- 1 | [href=':fullscreen'] { 2 | } 3 | 4 | :fullscreen a { 5 | box-sizing: border-box; 6 | } 7 | 8 | :fullscreen a { 9 | color: black; 10 | } 11 | 12 | @media all { 13 | :fullscreen a { 14 | color: black; 15 | } 16 | } 17 | 18 | p::selection { 19 | color: white; 20 | background: black; 21 | } 22 | 23 | input::placeholder { 24 | color: pink; 25 | } 26 | 27 | a[data-foo=":-webkit-full-screen"] { 28 | 29 | } 30 | 31 | .class::-webkit-scrollbar { 32 | } 33 | -------------------------------------------------------------------------------- /test/fixtures/style.css: -------------------------------------------------------------------------------- 1 | a { 2 | color: black; 3 | display: -webkit-flex; 4 | display: flex; 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/style.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | color: black; 3 | display: flex; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/supports.css: -------------------------------------------------------------------------------- 1 | @supports ((cursor: -webkit-grab) or (cursor: grab)) or 2 | not ((-webkit-mask: none) or (mask: none)) and 3 | (color: black) { 4 | a { 5 | color: black; 6 | } 7 | } 8 | 9 | @supports (cursor: -webkit-grab) or (cursor: grab) or 10 | not ((-webkit-mask: none) or (mask: none)) and 11 | (color: black) { 12 | a { 13 | color: black; 14 | } 15 | } 16 | 17 | @supports not ((display: -webkit-flex) or (display: flex)) { 18 | a { 19 | color: #000; 20 | } 21 | } 22 | 23 | @supports (((-webkit-perspective: 1px) or (perspective: 1px)) and (not (-webkit-overflow-scrolling: touch))) { 24 | a { 25 | color: #000; 26 | } 27 | } 28 | 29 | @supports ((-webkit-animation-name: test) or (animation-name: test)) and (((-webkit-animation-timing-function: steps(4, end)) or (animation-timing-function: steps(4, end))) or ((-webkit-animation-timing-function: step-end) or (animation-timing-function: step-end))) { 30 | -webkit-animation-name: test; 31 | animation-name: test; 32 | } 33 | 34 | @supports (transition: color 1s) { 35 | -webkit-transition: color 1s; 36 | transition: color 1s; 37 | } 38 | -------------------------------------------------------------------------------- /test/fixtures/supports.out.css: -------------------------------------------------------------------------------- 1 | @supports (cursor: grab) or 2 | not (mask: none) and 3 | (color: black) { 4 | a { 5 | color: black; 6 | } 7 | } 8 | 9 | @supports not (display: flex) { 10 | a { 11 | color: #000; 12 | } 13 | } 14 | 15 | @supports (perspective: 1px) and (not (-webkit-overflow-scrolling: touch)) { 16 | a { 17 | color: #000; 18 | } 19 | } 20 | 21 | @supports (animation-name: test) and (animation-timing-function: steps(4, end) or (animation-timing-function: step-end)) { 22 | animation-name: test; 23 | } 24 | 25 | @supports (transition: color 1s) { 26 | transition: color 1s; 27 | } 28 | -------------------------------------------------------------------------------- /test/fixtures/syntax.css: -------------------------------------------------------------------------------- 1 | @page { 2 | margin: .5cm; 3 | } 4 | 5 | /* comment */ 6 | 7 | @-moz-document url-prefix() { 8 | a { 9 | color: black; 10 | } 11 | } 12 | 13 | @-moz-document url(http://www.w3.org/), url-prefix(http: //www.w3.org/Style/), domain(mozilla.org), regexp('https:.*') { 14 | /* 该条CSS规则会应用在下面的网页: 15 | * URL为"http://www.w3.org/"的页面. 16 | * 任何URL以"http://www.w3.org/Style/"开头的网页 17 | * 任何主机名为"mozilla.org"或者主机名以".mozilla.org"结尾的网页 18 | * 任何URL以"https:"开头的网页 */ 19 | 20 | /* make the above-mentioned pages really ugly */ 21 | body { 22 | color: purple; 23 | background: yellow; 24 | } 25 | } 26 | 27 | @document url(http://www.w3.org/), url-prefix(http: //www.w3.org/Style/), domain(mozilla.org), regexp('https:.*') { 28 | /* 该条CSS规则会应用在下面的网页: 29 | * URL为"http://www.w3.org/"的页面. 30 | * 任何URL以"http://www.w3.org/Style/"开头的网页 31 | * 任何主机名为"mozilla.org"或者主机名以".mozilla.org"结尾的网页 32 | * 任何URL以"https:"开头的网页 */ 33 | 34 | /* make the above-mentioned pages really ugly */ 35 | body { 36 | color: purple; 37 | background: yellow; 38 | } 39 | } 40 | 41 | a { 42 | /* c */ 43 | color: white; 44 | padding: 0 1px 2px; 45 | } 46 | -------------------------------------------------------------------------------- /test/fixtures/syntax.out.css: -------------------------------------------------------------------------------- 1 | @page { 2 | margin: .5cm; 3 | } 4 | 5 | /* comment */ 6 | 7 | @document url-prefix() { 8 | a { 9 | color: black; 10 | } 11 | } 12 | 13 | @document url(http://www.w3.org/), url-prefix(http: //www.w3.org/Style/), domain(mozilla.org), regexp('https:.*') { 14 | /* 该条CSS规则会应用在下面的网页: 15 | * URL为"http://www.w3.org/"的页面. 16 | * 任何URL以"http://www.w3.org/Style/"开头的网页 17 | * 任何主机名为"mozilla.org"或者主机名以".mozilla.org"结尾的网页 18 | * 任何URL以"https:"开头的网页 */ 19 | 20 | /* make the above-mentioned pages really ugly */ 21 | body { 22 | color: purple; 23 | background: yellow; 24 | } 25 | } 26 | 27 | a { 28 | /* c */ 29 | color: white; 30 | padding: 0 1px 2px; 31 | } 32 | -------------------------------------------------------------------------------- /test/fixtures/text-emphasis-position.css: -------------------------------------------------------------------------------- 1 | a { 2 | -webkit-text-emphasis-position: over; 3 | text-emphasis-position: over left; 4 | } 5 | 6 | em { 7 | -webkit-text-emphasis-position: under; 8 | text-emphasis-position: under right; 9 | } 10 | 11 | .reverse { 12 | -webkit-text-emphasis-position: over; 13 | text-emphasis-position: left over; 14 | } 15 | 16 | .wrong { 17 | -webkit-text-emphasis-position: over; 18 | text-emphasis-position: over; 19 | } 20 | 21 | a { 22 | -webkit-text-emphasis-position: over; 23 | } 24 | 25 | em { 26 | -webkit-text-emphasis-position: under; 27 | } 28 | 29 | .reverse { 30 | -webkit-text-emphasis-position: over; 31 | } 32 | 33 | .wrong { 34 | -webkit-text-emphasis-position: over; 35 | } 36 | -------------------------------------------------------------------------------- /test/fixtures/text-emphasis-position.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | text-emphasis-position: over left; 3 | } 4 | 5 | em { 6 | text-emphasis-position: under right; 7 | } 8 | 9 | .reverse { 10 | text-emphasis-position: left over; 11 | } 12 | 13 | .wrong { 14 | text-emphasis-position: over; 15 | } 16 | 17 | a { 18 | text-emphasis-position: over; 19 | } 20 | 21 | em { 22 | text-emphasis-position: under; 23 | } 24 | 25 | .reverse { 26 | text-emphasis-position: over; 27 | } 28 | 29 | .wrong { 30 | text-emphasis-position: over; 31 | } 32 | -------------------------------------------------------------------------------- /test/fixtures/transition.css: -------------------------------------------------------------------------------- 1 | a { 2 | -webkit-transition: color 200ms, -webkit-transform 200ms; 3 | transition: color 200ms, -webkit-transform 200ms; 4 | -o-transition: color 200ms, -o-transform 200ms; 5 | transition: color 200ms, transform 200ms; 6 | transition: color 200ms, transform 200ms, -webkit-transform 200ms, -o-transform 200ms; 7 | -webkit-transform: rotate(10deg); 8 | -o-transform: rotate(10deg); 9 | transform: rotate(10deg); 10 | } 11 | 12 | div { 13 | -webkit-transition-property: -webkit-filter; 14 | transition-property: -webkit-filter; 15 | -o-transition-property: filter; 16 | transition-property: filter; 17 | transition-property: filter, -webkit-filter; 18 | -webkit-animation-name: rotating; 19 | -o-animation-name: rotating; 20 | animation-name: rotating; 21 | } 22 | 23 | .good { 24 | -webkit-transition-property: -webkit-filter; 25 | transition-property: -webkit-filter; 26 | -o-transition-property: filter; 27 | transition-property: filter; 28 | transition-property: filter, -webkit-filter; 29 | -webkit-transition-duration: 1s; 30 | -o-transition-duration: 1s; 31 | transition-duration: 1s; 32 | } 33 | 34 | .good2 { 35 | -webkit-transition-property: color, -webkit-filter; 36 | transition-property: color, -webkit-filter; 37 | -o-transition-property: color, filter; 38 | transition-property: color, filter; 39 | transition-property: color, filter, -webkit-filter; 40 | -webkit-transition-timing-function: cubic-bezier(0.55, 0, 0.1, 1); 41 | -o-transition-timing-function: cubic-bezier(0.55, 0, 0.1, 1); 42 | transition-timing-function: cubic-bezier(0.55, 0, 0.1, 1); 43 | } 44 | 45 | .bad { 46 | /* safe with different node types */ 47 | -webkit-transition-property: color, -webkit-filter; 48 | transition-property: color, -webkit-filter; 49 | -o-transition-property: color, filter; 50 | transition-property: color, filter; 51 | transition-property: color, filter, -webkit-filter; 52 | -webkit-transition-duration: 1s, 2s; 53 | -o-transition-duration: 1s, 2s; 54 | transition-duration: 1s, 2s; 55 | } 56 | 57 | .revert { 58 | -webkit-transition: 200ms -webkit-transform; 59 | transition: 200ms -webkit-transform; 60 | -o-transition: 200ms -o-transform; 61 | transition: 200ms transform; 62 | transition: 200ms transform, 200ms -webkit-transform, 200ms -o-transform; 63 | } 64 | 65 | a { 66 | -webkit-transition: color 200ms, -webkit-transform 200ms; 67 | -o-transition: color 200ms, transform 200ms, -o-transform 200ms; 68 | -webkit-transform: rotate(10deg); 69 | -o-transform: rotate(10deg); 70 | } 71 | 72 | div { 73 | -webkit-transition-property: -webkit-filter; 74 | -o-transition-property: filter; 75 | -webkit-animation-name: rotating; 76 | -o-animation-name: rotating; 77 | } 78 | 79 | .good { 80 | -webkit-transition-property: -webkit-filter; 81 | -o-transition-property: filter; 82 | -webkit-transition-duration: 1s; 83 | -o-transition-duration: 1s; 84 | } 85 | 86 | .good2 { 87 | -webkit-transition-property: color, -webkit-filter; 88 | -o-transition-property: color, filter; 89 | -webkit-transition-timing-function: cubic-bezier(.55, 0, .1, 1); 90 | -o-transition-timing-function: cubic-bezier(.55, 0, .1, 1); 91 | } 92 | 93 | .bad { 94 | /* safe with different node types */ 95 | -webkit-transition-property: color, -webkit-filter; 96 | -o-transition-property: color, filter, -js-coverage; 97 | -webkit-transition-duration: 1s, 2s; 98 | -o-transition-duration: 1s, 2s; 99 | } 100 | 101 | -------------------------------------------------------------------------------- /test/fixtures/transition.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | transition: color 200ms, transform 200ms; 3 | transform: rotate(10deg); 4 | } 5 | 6 | div { 7 | transition-property: filter; 8 | animation-name: rotating; 9 | } 10 | 11 | .good { 12 | transition-property: filter; 13 | transition-duration: 1s; 14 | } 15 | 16 | .good2 { 17 | transition-property: color, filter; 18 | transition-timing-function: cubic-bezier(0.55, 0, 0.1, 1); 19 | } 20 | 21 | .bad { 22 | /* safe with different node types */ 23 | transition-property: color, filter; 24 | transition-duration: 1s, 2s; 25 | } 26 | 27 | .revert { 28 | transition: 200ms transform; 29 | } 30 | 31 | a { 32 | transition: color 200ms, transform 200ms; 33 | transform: rotate(10deg); 34 | } 35 | 36 | div { 37 | transition-property: filter; 38 | animation-name: rotating; 39 | } 40 | 41 | .good { 42 | transition-property: filter; 43 | transition-duration: 1s; 44 | } 45 | 46 | .good2 { 47 | transition-property: color, filter; 48 | transition-timing-function: cubic-bezier(.55, 0, .1, 1); 49 | } 50 | 51 | .bad { 52 | /* safe with different node types */ 53 | transition-property: color, filter, -js-coverage; 54 | transition-duration: 1s, 2s; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /test/fixtures/trim.css: -------------------------------------------------------------------------------- 1 | a { 2 | background: -webkit-linear-gradient(top, #f00 0%, #fff 100%); 3 | background: linear-gradient(to bottom, #f00 0%, #fff 100%); 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/trim.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | background: linear-gradient(to bottom, #f00 0%, #fff 100%); 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/uncascade.css: -------------------------------------------------------------------------------- 1 | a { 2 | -moz-transition: 1s; 3 | transition: 1s; 4 | } 5 | 6 | a { 7 | -moz-transition: 1s; 8 | transition: 1s; 9 | } 10 | 11 | a { 12 | border-radius: 4px; 13 | } 14 | -------------------------------------------------------------------------------- /test/fixtures/uncascade.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | transition: 1s; 3 | } 4 | 5 | a { 6 | transition: 1s; 7 | } 8 | 9 | a { 10 | border-radius: 4px; 11 | } 12 | -------------------------------------------------------------------------------- /test/fixtures/uppercase.css: -------------------------------------------------------------------------------- 1 | a { 2 | dIsPlAy: -webkit-flex; 3 | } 4 | 5 | a { 6 | DISPLAY: -webkit-flex; 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/uppercase.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | dIsPlAy: flex; 3 | } 4 | 5 | a { 6 | DISPLAY: flex; 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/value-hack.css: -------------------------------------------------------------------------------- 1 | .not-hack { 2 | width: calc(30% + 1px); 3 | display: flex; 4 | transition: filter 1s; 5 | } 6 | 7 | .not-hack2 { 8 | transition: filter 1s; 9 | } 10 | 11 | .hack { 12 | width: -webkit-calc(30% + 1px); 13 | display: -webkit-box; 14 | } 15 | -------------------------------------------------------------------------------- /test/fixtures/value-hack.out.css: -------------------------------------------------------------------------------- 1 | .not-hack { 2 | width: calc(30% + 1px); 3 | display: flex; 4 | transition: filter 1s; 5 | } 6 | 7 | .not-hack2 { 8 | transition: filter 1s; 9 | } 10 | 11 | .hack { 12 | width: calc(30% + 1px); 13 | display: flex; 14 | } 15 | -------------------------------------------------------------------------------- /test/fixtures/values.css: -------------------------------------------------------------------------------- 1 | a { 2 | margin: -webkit-calc(5% + 5px) -webkit-calc(10% + 10px); 3 | margin: calc(5% + 5px) calc(10% + 10px); 4 | background: -webkit-linear-gradient(black, white), -webkit-radial-gradient(white, black); 5 | background: -o-linear-gradient(black, white), -o-radial-gradient(white, black); 6 | background: linear-gradient(black, white), radial-gradient(white, black); 7 | content: " linear-gradient(black, white) "; 8 | } 9 | 10 | b { 11 | margin: -webkit-calc(5% + 5px) -webkit-calc(10% + 10px); 12 | background: -webkit-linear-gradient(black, white), -webkit-radial-gradient(white, black); 13 | } 14 | -------------------------------------------------------------------------------- /test/fixtures/values.out.css: -------------------------------------------------------------------------------- 1 | a { 2 | margin: calc(5% + 5px) calc(10% + 10px); 3 | background: linear-gradient(black, white), radial-gradient(white, black); 4 | content: " linear-gradient(black, white) "; 5 | } 6 | 7 | b { 8 | margin: calc(5% + 5px) calc(10% + 10px); 9 | background: linear-gradient(black, white), radial-gradient(white, black); 10 | } 11 | -------------------------------------------------------------------------------- /test/fixtures/vendor-hack.css: -------------------------------------------------------------------------------- 1 | .a { 2 | transform: scale(.9999); 3 | } 4 | 5 | .b { 6 | -moz-transform: scale(.9999); 7 | } 8 | 9 | .c { 10 | transform: scale(1); 11 | -moz-transform: scale(2); 12 | } 13 | 14 | .b { 15 | -moz-transform: scale(.9999); 16 | } 17 | 18 | .c { 19 | -moz-transform: scale(2); 20 | } 21 | -------------------------------------------------------------------------------- /test/fixtures/vendor-hack.out.css: -------------------------------------------------------------------------------- 1 | .a { 2 | transform: scale(.9999); 3 | } 4 | 5 | .b { 6 | transform: scale(.9999); 7 | } 8 | 9 | .c { 10 | transform: scale(1); 11 | } 12 | 13 | .b { 14 | transform: scale(.9999); 15 | } 16 | 17 | .c { 18 | transform: scale(2); 19 | } 20 | -------------------------------------------------------------------------------- /test/fixtures/viewport.css: -------------------------------------------------------------------------------- 1 | @-ms-viewport { 2 | width: device-width; 3 | } 4 | 5 | @viewport { 6 | width: device-width; 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/viewport.out.css: -------------------------------------------------------------------------------- 1 | @viewport { 2 | width: device-width; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/writing-mode.css: -------------------------------------------------------------------------------- 1 | .one { 2 | -webkit-writing-mode: horizontal-tb; 3 | -ms-writing-mode: lr-tb; 4 | writing-mode: horizontal-tb; 5 | } 6 | 7 | .two { 8 | -webkit-writing-mode: vertical-rl; 9 | -ms-writing-mode: tb-rl; 10 | writing-mode: vertical-rl; 11 | } 12 | 13 | .three { 14 | -webkit-writing-mode: vertical-lr; 15 | -ms-writing-mode: tb-lr; 16 | writing-mode: vertical-lr; 17 | } 18 | 19 | .one { 20 | -webkit-writing-mode: horizontal-tb; 21 | -ms-writing-mode: lr-tb; 22 | } 23 | 24 | .two { 25 | -webkit-writing-mode: vertical-rl; 26 | -ms-writing-mode: tb-rl; 27 | } 28 | 29 | .three { 30 | -webkit-writing-mode: vertical-lr; 31 | -ms-writing-mode: tb-lr; 32 | } 33 | -------------------------------------------------------------------------------- /test/fixtures/writing-mode.out.css: -------------------------------------------------------------------------------- 1 | .one { 2 | writing-mode: horizontal-tb; 3 | } 4 | 5 | .two { 6 | writing-mode: vertical-rl; 7 | } 8 | 9 | .three { 10 | writing-mode: vertical-lr; 11 | } 12 | 13 | .one { 14 | writing-mode: horizontal-tb; 15 | } 16 | 17 | .two { 18 | writing-mode: vertical-rl; 19 | } 20 | 21 | .three { 22 | writing-mode: vertical-lr; 23 | } 24 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const fs = require("fs"); 3 | const assert = require("assert"); 4 | const stylelint = Array.prototype.includes && require("stylelint"); 5 | const reporter = require("postcss-reporter"); 6 | const unprefix = require(".."); 7 | 8 | function process (css, postcssOpts, opts) { 9 | const postcss = require("postcss"); 10 | const processors = [ 11 | unprefix(opts), 12 | stylelint && stylelint, 13 | reporter(), 14 | ].filter(Boolean); 15 | return postcss(processors).process(css, postcssOpts); 16 | } 17 | 18 | let files = fs.readdirSync("./test/fixtures"); 19 | 20 | files = files.filter((filename) => { 21 | return /\.(?:c|le|sc)ss$/.test(filename) && !/\.\w+\.\w+$/.test(filename); 22 | }); 23 | describe("fixtures", () => { 24 | // files = ["values.css"] 25 | 26 | files.forEach((filename) => { 27 | const testName = filename.replace(/\.\w+$/, ""); 28 | const inputFile = "./test/fixtures/" + filename; 29 | const outputFile = inputFile.replace(/\.(\w+)$/, ".out.$1"); 30 | const syntax = RegExp.$1.toLowerCase(); 31 | const input = fs.readFileSync(inputFile).toString(); 32 | let output = ""; 33 | try { 34 | output = fs.readFileSync(outputFile).toString(); 35 | } catch (ex) { 36 | // 37 | } 38 | 39 | if (input === output) { 40 | console.error(inputFile); 41 | } 42 | 43 | it(testName, () => { 44 | let real; 45 | return process(input, { 46 | from: inputFile, 47 | syntax: syntax === "css" ? null : require("postcss-" + syntax), 48 | }).then((result) => { 49 | real = result.css; 50 | assert.strictEqual(output, real); 51 | assert.strictEqual(result.messages.length, 0); 52 | }).catch(ex => { 53 | if (real) { 54 | fs.writeFileSync(inputFile.replace(/\.(\w+)$/, ".out.$1"), real); 55 | } 56 | throw ex; 57 | }); 58 | }); 59 | }); 60 | }); 61 | --------------------------------------------------------------------------------