diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ad0157a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,1077 @@
+# Autoprefixer
+
+
+
+[PostCSS] plugin to parse CSS and add vendor prefixes to CSS rules using values
+from [Can I Use]. It is recommended by Google and used in Twitter and Alibaba.
+
+Write your CSS rules without vendor prefixes (in fact, forget about them
+entirely):
+
+```css
+::placeholder {
+ color: gray;
+}
+
+.image {
+ width: stretch;
+}
+```
+
+Autoprefixer will use the data based on current browser popularity and property
+support to apply prefixes for you. You can try the [interactive demo]
+of Autoprefixer.
+
+```css
+::-moz-placeholder {
+ color: gray;
+}
+::placeholder {
+ color: gray;
+}
+
+.image {
+ width: -moz-available;
+ width: -webkit-fill-available;
+ width: stretch;
+}
+```
+
+Twitter account for news and releases: [@autoprefixer].
+
+---
+
+
Autoprefixer is built by Evil Martians, an American design and engineering consultancy for developer tools, AI, and cybersecurity startups.
+
+---
+
+[interactive demo]: https://autoprefixer.github.io/
+[@autoprefixer]: https://twitter.com/autoprefixer
+[Can I Use]: https://caniuse.com/
+[PostCSS]: https://github.com/postcss/postcss
+
+## Contents
+
+- [Contents](#contents)
+- [Browsers](#browsers)
+- [FAQ](#faq)
+ - [Does Autoprefixer polyfill Grid Layout for IE?](#does-autoprefixer-polyfill-grid-layout-for-ie)
+ - [Does it add polyfills?](#does-it-add-polyfills)
+ - [Why doesn’t Autoprefixer add prefixes to `border-radius`?](#why-doesnt-autoprefixer-add-prefixes-to-border-radius)
+ - [Why does Autoprefixer use unprefixed properties in `@-webkit-keyframes`?](#why-does-autoprefixer-use-unprefixed-properties-in--webkit-keyframes)
+ - [How to work with legacy `-webkit-` only code?](#how-to-work-with-legacy--webkit--only-code)
+ - [Does Autoprefixer add `-epub-` prefix?](#does-autoprefixer-add--epub--prefix)
+ - [Why doesn’t Autoprefixer transform generic font-family `system-ui`?](#why-doesnt-autoprefixer-transform-generic-font-family-system-ui)
+- [Usage](#usage)
+ - [Gulp](#gulp)
+ - [Webpack](#webpack)
+ - [CSS-in-JS](#css-in-js)
+ - [CLI](#cli)
+ - [Other Build Tools](#other-build-tools)
+ - [Preprocessors](#preprocessors)
+ - [GUI Tools](#gui-tools)
+ - [JavaScript](#javascript)
+ - [Text Editors and IDE](#text-editors-and-ide)
+- [Warnings](#warnings)
+- [Disabling](#disabling)
+ - [Prefixes](#prefixes)
+ - [Features](#features)
+ - [Control Comments](#control-comments)
+- [Options](#options)
+- [Environment Variables](#environment-variables)
+ - [Using environment variables to support CSS Grid prefixes in Create React App](#using-environment-variables-to-support-css-grid-prefixes-in-create-react-app)
+- [Grid Autoplacement support in IE](#grid-autoplacement-support-in-ie)
+ - [Beware of enabling autoplacement in old projects](#beware-of-enabling-autoplacement-in-old-projects)
+ - [Autoplacement limitations](#autoplacement-limitations)
+ - [Both columns and rows must be defined](#both-columns-and-rows-must-be-defined)
+ - [Repeat auto-fit and auto-fill are not supported](#repeat-auto-fit-and-auto-fill-are-not-supported)
+ - [No manual cell placement or column/row spans allowed inside an autoplacement grid](#no-manual-cell-placement-or-columnrow-spans-allowed-inside-an-autoplacement-grid)
+ - [Do not create `::before` and `::after` pseudo elements](#do-not-create-before-and-after-pseudo-elements)
+ - [When changing the `grid gap` value, columns and rows must be re-declared](#when-changing-the-grid-gap-value-columns-and-rows-must-be-re-declared)
+- [Debug](#debug)
+- [Security Contact](#security-contact)
+- [For Enterprise](#for-enterprise)
+
+## Browsers
+
+Autoprefixer uses [Browserslist], so you can specify the browsers
+you want to target in your project with queries like `> 5%`
+(see [Best Practices]).
+
+The best way to provide browsers is a `.browserslistrc` file in your project
+root, or by adding a `browserslist` key to your `package.json`.
+
+We recommend the use of these options over passing options to Autoprefixer so
+that the config can be shared with other tools such as [babel-preset-env] and
+[Stylelint].
+
+See [Browserslist docs] for queries, browser names, config format, and defaults.
+
+[Browserslist docs]: https://github.com/browserslist/browserslist#queries
+[babel-preset-env]: https://github.com/babel/babel/tree/master/packages/babel-preset-env
+[Best Practices]: https://github.com/browserslist/browserslist#best-practices
+[Browserslist]: https://github.com/browserslist/browserslist
+[Stylelint]: https://stylelint.io/
+
+## FAQ
+
+### Does Autoprefixer polyfill Grid Layout for IE?
+
+Autoprefixer can be used to translate modern CSS Grid syntax into IE 10
+and IE 11 syntax, but this polyfill will not work in 100% of cases.
+This is why it is disabled by default.
+
+First, you need to enable Grid prefixes by using either the `grid: "autoplace"`
+option or the `/* autoprefixer grid: autoplace */` control comment.
+Also you can use environment variable to enable Grid:
+`AUTOPREFIXER_GRID=autoplace npm build`.
+
+Second, you need to test every fix with Grid in IE. It is not an enable and
+forget feature, but it is still very useful.
+Financial Times and Yandex use it in production.
+
+Third, there is only very limited auto placement support. Read the
+[Grid Autoplacement support in IE](#grid-autoplacement-support-in-ie) section
+for more details.
+
+Fourth, if you are not using the autoplacement feature, the best way
+to use Autoprefixer is by using `grid-template` or `grid-template-areas`.
+
+```css
+.page {
+ display: grid;
+ grid-gap: 33px;
+ grid-template:
+ 'head head head' 1fr
+ 'nav main main' minmax(100px, 1fr)
+ 'nav foot foot' 2fr /
+ 1fr 100px 1fr;
+}
+.page__head {
+ grid-area: head;
+}
+.page__nav {
+ grid-area: nav;
+}
+.page__main {
+ grid-area: main;
+}
+.page__footer {
+ grid-area: foot;
+}
+```
+
+See also:
+
+- [The guide about Grids in IE and Autoprefixer].
+- [`postcss-gap-properties`] to use new `gap` property
+ instead of old `grid-gap`.
+- [`postcss-grid-kiss`] has alternate “everything in one property” syntax,
+ which makes using Autoprefixer’s Grid translations safer.
+
+[The guide about Grids in IE and Autoprefixer]: https://css-tricks.com/css-grid-in-ie-css-grid-and-the-new-autoprefixer/
+[`postcss-gap-properties`]: https://github.com/jonathantneal/postcss-gap-properties
+[`postcss-grid-kiss`]: https://github.com/sylvainpolletvillard/postcss-grid-kiss
+
+### Does it add polyfills?
+
+No. Autoprefixer only adds prefixes.
+
+Most new CSS features will require client side JavaScript to handle a new
+behavior correctly.
+
+Depending on what you consider to be a “polyfill”, you can take a look at some
+other tools and libraries. If you are just looking for syntax sugar,
+you might take a look at:
+
+- [postcss-preset-env] is a plugins preset with polyfills and Autoprefixer
+ to write future CSS today.
+- [Oldie], a PostCSS plugin that handles some IE hacks (opacity, rgba, etc).
+- [postcss-flexbugs-fixes], a PostCSS plugin to fix flexbox issues.
+
+[postcss-flexbugs-fixes]: https://github.com/luisrudge/postcss-flexbugs-fixes
+[postcss-preset-env]: https://github.com/jonathantneal/postcss-preset-env
+[Oldie]: https://github.com/jonathantneal/oldie
+
+### Why doesn’t Autoprefixer add prefixes to `border-radius`?
+
+Developers are often surprised by how few prefixes are required today.
+If Autoprefixer doesn’t add prefixes to your CSS, check if they’re still
+required on [Can I Use].
+
+[Can I Use]: https://caniuse.com/
+
+### Why does Autoprefixer use unprefixed properties in `@-webkit-keyframes`?
+
+Browser teams can remove some prefixes before others, so we try to use all
+combinations of prefixed/unprefixed values.
+
+### How to work with legacy `-webkit-` only code?
+
+Autoprefixer needs unprefixed property to add prefixes. So if you only
+wrote `-webkit-gradient` without W3C’s `gradient`,
+Autoprefixer will not add other prefixes.
+
+But [PostCSS] has plugins to convert CSS to unprefixed state.
+Use [postcss-unprefix] before Autoprefixer.
+
+[postcss-unprefix]: https://github.com/gucong3000/postcss-unprefix
+
+### Does Autoprefixer add `-epub-` prefix?
+
+No, Autoprefixer works only with browsers prefixes from Can I Use.
+But you can use [postcss-epub] for prefixing ePub3 properties.
+
+[postcss-epub]: https://github.com/Rycochet/postcss-epub
+
+### Why doesn’t Autoprefixer transform generic font-family `system-ui`?
+
+`system-ui` is technically not a prefix and the transformation is not
+future-proof. You can use [postcss-font-family-system-ui] to transform
+`system-ui` to a practical font-family list.
+
+[postcss-font-family-system-ui]: https://github.com/JLHwung/postcss-font-family-system-ui
+
+## Usage
+
+### Gulp
+
+In Gulp you can use [gulp-postcss] with `autoprefixer` npm package.
+
+```js
+gulp.task('autoprefixer', () => {
+ const autoprefixer = require('autoprefixer')
+ const sourcemaps = require('gulp-sourcemaps')
+ const postcss = require('gulp-postcss')
+
+ return gulp
+ .src('./src/*.css')
+ .pipe(sourcemaps.init())
+ .pipe(postcss([autoprefixer()]))
+ .pipe(sourcemaps.write('.'))
+ .pipe(gulp.dest('./dest'))
+})
+```
+
+With `gulp-postcss` you also can combine Autoprefixer
+with [other PostCSS plugins].
+
+[gulp-postcss]: https://github.com/postcss/gulp-postcss
+[other PostCSS plugins]: https://github.com/postcss/postcss#plugins
+
+### Webpack
+
+In [webpack] you can use [postcss-loader] with `autoprefixer`
+and [other PostCSS plugins].
+
+```js
+module.exports = {
+ module: {
+ rules: [
+ {
+ test: /\.css$/,
+ use: ['style-loader', 'css-loader', 'postcss-loader']
+ }
+ ]
+ }
+}
+```
+
+And create a `postcss.config.js` with:
+
+```js
+module.exports = {
+ plugins: [require('autoprefixer')]
+}
+```
+
+[other PostCSS plugins]: https://github.com/postcss/postcss#plugins
+[postcss-loader]: https://github.com/postcss/postcss-loader
+[webpack]: https://webpack.js.org/
+
+### CSS-in-JS
+
+The best way to use PostCSS with CSS-in-JS is [`astroturf`].
+Add its loader to your `webpack.config.js`:
+
+```js
+module.exports = {
+ module: {
+ rules: [
+ {
+ test: /\.css$/,
+ use: ['style-loader', 'postcss-loader']
+ },
+ {
+ test: /\.jsx?$/,
+ use: ['babel-loader', 'astroturf/loader']
+ }
+ ]
+ }
+}
+```
+
+Then create `postcss.config.js`:
+
+```js
+module.exports = {
+ plugins: [require('autoprefixer')]
+}
+```
+
+[`astroturf`]: https://github.com/4Catalyzer/astroturf
+
+### CLI
+
+You can use the [postcss-cli] to run Autoprefixer from CLI:
+
+```sh
+npm install postcss postcss-cli autoprefixer
+npx postcss *.css --use autoprefixer -d build/
+```
+
+See `postcss -h` for help.
+
+[postcss-cli]: https://github.com/postcss/postcss-cli
+
+### Other Build Tools
+
+- **Grunt:** [grunt-postcss]
+- **Ruby on Rails**: [autoprefixer-rails]
+- **Neutrino**: [neutrino-middleware-postcss]
+- **Jekyll**: add `autoprefixer-rails` and `jekyll-assets` to `Gemfile`
+- **Brunch**: [postcss-brunch]
+- **Broccoli**: [broccoli-postcss]
+- **Middleman**: [middleman-autoprefixer]
+- **Mincer**: add `autoprefixer` npm package and enable it:
+ `environment.enable('autoprefixer')`
+
+[neutrino-middleware-postcss]: https://www.npmjs.com/package/neutrino-middleware-postcss
+[middleman-autoprefixer]: https://github.com/middleman/middleman-autoprefixer
+[autoprefixer-rails]: https://github.com/ai/autoprefixer-rails
+[broccoli-postcss]: https://github.com/jeffjewiss/broccoli-postcss
+[postcss-brunch]: https://github.com/iamvdo/postcss-brunch
+[grunt-postcss]: https://github.com/C-Lodder/grunt-postcss
+
+#### Preprocessors
+
+- **Less**: [less-plugin-autoprefix]
+- **Stylus**: [autoprefixer-stylus]
+- **Compass**: [autoprefixer-rails#compass]
+
+[less-plugin-autoprefix]: https://github.com/less/less-plugin-autoprefix
+[autoprefixer-stylus]: https://github.com/jenius/autoprefixer-stylus
+[autoprefixer-rails#compass]: https://github.com/ai/autoprefixer-rails#compass
+
+#### GUI Tools
+
+- [CodeKit](https://codekitapp.com/help/autoprefixer/)
+- [Prepros](https://prepros.io)
+
+### JavaScript
+
+You can use Autoprefixer with [PostCSS] in your Node.js application
+or if you want to develop an Autoprefixer plugin for a new environment.
+
+```js
+const autoprefixer = require('autoprefixer')
+const postcss = require('postcss')
+
+postcss([autoprefixer])
+ .process(css)
+ .then(result => {
+ result.warnings().forEach(warn => {
+ console.warn(warn.toString())
+ })
+ console.log(result.css)
+ })
+```
+
+There is also a [standalone build] for the browser or for a non-Node.js runtime.
+
+You can use [html-autoprefixer] to process HTML with inlined CSS.
+
+[html-autoprefixer]: https://github.com/RebelMail/html-autoprefixer
+[standalone build]: https://raw.github.com/ai/autoprefixer-rails/master/vendor/autoprefixer.js
+[PostCSS]: https://github.com/postcss/postcss
+
+### Text Editors and IDE
+
+Autoprefixer should be used in assets build tools. Text editor plugins are not
+a good solution, because prefixes decrease code readability and you will need
+to change values in all prefixed properties.
+
+I recommend you to learn how to use build tools like [Parcel].
+They work much better and will open you a whole new world of useful plugins
+and automation.
+
+If you can’t move to a build tool, you can use text editor plugins:
+
+- [Visual Studio Code](https://github.com/mrmlnc/vscode-autoprefixer)
+- [Sublime Text](https://github.com/sindresorhus/sublime-autoprefixer)
+
+[Parcel]: https://parceljs.org/
+
+## Warnings
+
+Autoprefixer uses the [PostCSS warning API] to warn about really important
+problems in your CSS:
+
+- Old direction syntax in gradients.
+- Old unprefixed `display: box` instead of `display: flex`
+ by latest specification version.
+
+You can get warnings from `result.warnings()`:
+
+```js
+result.warnings().forEach(warn => {
+ console.warn(warn.toString())
+})
+```
+
+Every Autoprefixer runner should display these warnings.
+
+[PostCSS warning API]: https://postcss.org/api/#warning
+
+## Disabling
+
+### Prefixes
+
+Autoprefixer was designed to have no interface – it just works.
+If you need some browser specific hack just write a prefixed property
+after the unprefixed one.
+
+```css
+a {
+ transform: scale(0.5);
+ -moz-transform: scale(0.6);
+}
+```
+
+If some prefixes were generated incorrectly, please create an [issue on GitHub].
+
+[issue on GitHub]: https://github.com/postcss/autoprefixer/issues
+
+### Features
+
+You can use these plugin options to control some of Autoprefixer’s features.
+
+- `grid: "autoplace"` will enable `-ms-` prefixes for Grid Layout including some
+ [limited autoplacement support](#grid-autoplacement-support-in-ie).
+- `supports: false` will disable `@supports` parameters prefixing.
+- `flexbox: false` will disable flexbox properties prefixing.
+ Or `flexbox: "no-2009"` will add prefixes only for final and IE
+ versions of specification.
+- `remove: false` will disable cleaning outdated prefixes.
+
+You should set them inside the plugin like so:
+
+```js
+autoprefixer({ grid: 'autoplace' })
+```
+
+### Control Comments
+
+If you do not need Autoprefixer in some part of your CSS,
+you can use control comments to disable Autoprefixer.
+
+```css
+.a {
+ transition: 1s; /* will be prefixed */
+}
+
+.b {
+ /* autoprefixer: off */
+ transition: 1s; /* will not be prefixed */
+}
+
+.c {
+ /* autoprefixer: ignore next */
+ transition: 1s; /* will not be prefixed */
+ mask: url(image.png); /* will be prefixed */
+}
+```
+
+There are three types of control comments:
+
+- `/* autoprefixer: (on|off) */`: enable/disable all Autoprefixer translations for the
+ whole block both _before_ and _after_ the comment.
+- `/* autoprefixer: ignore next */`: disable Autoprefixer only for the next property
+ or next rule selector or at-rule parameters (but not rule/at‑rule body).
+- `/* autoprefixer grid: (autoplace|no-autoplace|off) */`: control how Autoprefixer handles
+ grid translations for the whole block:
+ - `autoplace`: enable grid translations with autoplacement support.
+ - `no-autoplace`: enable grid translations with autoplacement
+ support _disabled_ (alias for deprecated value `on`).
+ - `off`: disable all grid translations.
+
+You can also use comments recursively:
+
+```css
+/* autoprefixer: off */
+@supports (transition: all) {
+ /* autoprefixer: on */
+ a {
+ /* autoprefixer: off */
+ }
+}
+```
+
+Note that comments that disable the whole block should not be featured in the same
+block twice:
+
+```css
+/* How not to use block level control comments */
+
+.do-not-do-this {
+ /* autoprefixer: off */
+ transition: 1s;
+ /* autoprefixer: on */
+ transform: rotate(20deg);
+}
+```
+
+## Options
+
+Function `autoprefixer(options)` returns a new PostCSS plugin.
+See [PostCSS API] for plugin usage documentation.
+
+```js
+autoprefixer({ cascade: false })
+```
+
+Available options are:
+
+- `env` (string): environment for Browserslist.
+- `cascade` (boolean): should Autoprefixer use Visual Cascade,
+ if CSS is uncompressed. Default: `true`
+- `add` (boolean): should Autoprefixer add prefixes. Default is `true`.
+- `remove` (boolean): should Autoprefixer [remove outdated] prefixes.
+ Default is `true`.
+- `supports` (boolean): should Autoprefixer add prefixes for `@supports`
+ parameters. Default is `true`.
+- `flexbox` (boolean|string): should Autoprefixer add prefixes for flexbox
+ properties. With `"no-2009"` value Autoprefixer will add prefixes only
+ for final and IE 10 versions of specification. Default is `true`.
+- `grid` (false|`"autoplace"`|`"no-autoplace"`): should Autoprefixer
+ add IE 10-11 prefixes for Grid Layout properties?
+ - `false` (default): prevent Autoprefixer from outputting
+ CSS Grid translations.
+ - `"autoplace"`: enable Autoprefixer grid translations
+ and _include_ autoplacement support. You can also use
+ `/* autoprefixer grid: autoplace */` in your CSS.
+ - `"no-autoplace"`: enable Autoprefixer grid translations
+ but _exclude_ autoplacement support. You can also use
+ `/* autoprefixer grid: no-autoplace */` in your CSS.
+ (alias for the deprecated `true` value)
+- `stats` (object): custom [usage statistics] for `> 10% in my stats`
+ browsers query.
+- `overrideBrowserslist` (array): list of queries for target browsers.
+ Try to not use it. The best practice is to use `.browserslistrc` config
+ or `browserslist` key in `package.json` to share target browsers
+ with Babel, ESLint and Stylelint. See [Browserslist docs]
+ for available queries and default value.
+- `ignoreUnknownVersions` (boolean): do not raise error on unknown browser
+ version in Browserslist config. Default is `false`.
+
+Plugin object has `info()` method for debugging purpose.
+
+You can use PostCSS processor to process several CSS files
+to increase performance.
+
+[usage statistics]: https://github.com/browserslist/browserslist#custom-usage-data
+[PostCSS API]: https://postcss.org/api/
+
+## Environment Variables
+
+- `AUTOPREFIXER_GRID`: (`autoplace`|`no-autoplace`) should Autoprefixer
+ add IE 10-11 prefixes for Grid Layout properties?
+ - `autoplace`: enable Autoprefixer grid translations
+ and _include_ autoplacement support.
+ - `no-autoplace`: enable Autoprefixer grid translations
+ but _exclude_ autoplacement support.
+
+Environment variables are useful, when you want to change Autoprefixer options but don't have access to config files.
+[Create React App] is a good example of this.
+
+[Create React App]: (https://reactjs.org/docs/create-a-new-react-app.html#create-react-app)
+
+### Using environment variables to support CSS Grid prefixes in Create React App
+
+1. Install the latest version of Autoprefixer and [cross-env](https://www.npmjs.com/package/cross-env):
+
+```
+npm install autoprefixer@latest cross-env --save-dev
+```
+
+2. Under `"browserslist"` > `"development"` in the package.json file, add `"last 1 ie version"`
+
+```
+"browserslist": {
+ "production": [
+ ">0.2%",
+ "not dead",
+ "not op_mini all"
+ ],
+ "development": [
+ "last 1 chrome version",
+ "last 1 firefox version",
+ "last 1 safari version",
+ "last 1 ie version"
+ ]
+}
+```
+
+3. Update `"scripts"` in the package.json file to the following:
+
+```
+"scripts": {
+ "start": "cross-env AUTOPREFIXER_GRID=autoplace react-scripts start",
+ "build": "cross-env AUTOPREFIXER_GRID=autoplace react-scripts build",
+ "test": "cross-env AUTOPREFIXER_GRID=autoplace react-scripts test",
+ "eject": "react-scripts eject"
+},
+```
+
+Replace `autoplace` with `no-autoplace` in the above example if you prefer to disable Autoprefixer Grid autoplacement support.
+
+Now when you run `npm start` you will see CSS Grid prefixes automatically being applied to your output CSS.
+
+See also [Browserslist environment variables] for more examples on how to use environment variables in your project.
+
+[Browserslist environment variables]: https://github.com/browserslist/browserslist#environment-variables
+
+## Grid Autoplacement support in IE
+
+If the `grid` option is set to `"autoplace"`, limited autoplacement support is added to Autoprefixers grid translations. You can also use
+the `/* autoprefixer grid: autoplace */` control comment or
+`AUTOPREFIXER_GRID=autoplace npm build` environment variable.
+
+Autoprefixer will only autoplace grid cells if both `grid-template-rows`
+and `grid-template-columns` has been set. If `grid-template`
+or `grid-template-areas` has been set, Autoprefixer will use area based
+cell placement instead.
+
+Autoprefixer supports autoplacement by using `nth-child` CSS selectors.
+It creates [number of columns] x [number of rows] `nth-child` selectors.
+For this reason Autoplacement is only supported within the explicit grid.
+
+```css
+/* Input CSS */
+
+/* autoprefixer grid: autoplace */
+
+.autoplacement-example {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-template-rows: auto auto;
+ grid-gap: 20px;
+}
+```
+
+```css
+/* Output CSS */
+
+/* autoprefixer grid: autoplace */
+
+.autoplacement-example {
+ display: -ms-grid;
+ display: grid;
+ -ms-grid-columns: 1fr 20px 1fr;
+ grid-template-columns: 1fr 1fr;
+ -ms-grid-rows: auto 20px auto;
+ grid-template-rows: auto auto;
+ grid-gap: 20px;
+}
+
+.autoplacement-example > *:nth-child(1) {
+ -ms-grid-row: 1;
+ -ms-grid-column: 1;
+}
+
+.autoplacement-example > *:nth-child(2) {
+ -ms-grid-row: 1;
+ -ms-grid-column: 3;
+}
+
+.autoplacement-example > *:nth-child(3) {
+ -ms-grid-row: 3;
+ -ms-grid-column: 1;
+}
+
+.autoplacement-example > *:nth-child(4) {
+ -ms-grid-row: 3;
+ -ms-grid-column: 3;
+}
+```
+
+### Beware of enabling autoplacement in old projects
+
+Be careful about enabling autoplacement in any already established projects that have
+previously not used Autoprefixer's grid autoplacement feature before.
+
+If this was your html:
+
+```html
+
+```
+
+The following CSS will not work as expected with the autoplacement feature enabled:
+
+```css
+/* Unsafe CSS when Autoplacement is enabled */
+
+.grid-cell {
+ grid-column: 2;
+ grid-row: 2;
+}
+
+.grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-rows: repeat(3, 1fr);
+}
+```
+
+Swapping the rules around will not fix the issue either:
+
+```css
+/* Also unsafe to use this CSS */
+
+.grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-rows: repeat(3, 1fr);
+}
+
+.grid-cell {
+ grid-column: 2;
+ grid-row: 2;
+}
+```
+
+One way to deal with this issue is to disable autoplacement in the
+grid-declaration rule:
+
+```css
+/* Disable autoplacement to fix the issue */
+
+.grid {
+ /* autoprefixer grid: no-autoplace */
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-rows: repeat(3, 1fr);
+}
+
+.grid-cell {
+ grid-column: 2;
+ grid-row: 2;
+}
+```
+
+The absolute best way to integrate autoplacement into already existing projects
+though is to leave autoplacement turned off by default and then use a control
+comment to enable it when needed. This method is far less likely to cause
+something on the site to break.
+
+```css
+/* Disable autoplacement by default in old projects */
+/* autoprefixer grid: no-autoplace */
+
+/* Old code will function the same way it always has */
+.old-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-rows: repeat(3, 1fr);
+}
+.old-grid-cell {
+ grid-column: 2;
+ grid-row: 2;
+}
+
+/* Enable autoplacement when you want to use it in new code */
+.new-autoplace-friendly-grid {
+ /* autoprefixer grid: autoplace */
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-rows: repeat(3, auto);
+}
+```
+
+Note that the `grid: "no-autoplace"` setting and the
+`/* autoprefixer grid: no-autoplace */` control comment share identical
+functionality to the `grid: true` setting and the `/* autoprefixer grid: on */`
+control comment. There is no need to refactor old code to use `no-autoplace`
+in place of the old `true` and `on` statements.
+
+### Autoplacement limitations
+
+#### Both columns and rows must be defined
+
+Autoplacement only works inside the explicit grid. The columns and rows need to be defined
+so that Autoprefixer knows how many `nth-child` selectors to generate.
+
+```css
+.not-allowed {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+}
+
+.is-allowed {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-rows: repeat(10, auto);
+}
+```
+
+#### Repeat auto-fit and auto-fill are not supported
+
+The `repeat(auto-fit, ...)` and `repeat(auto-fill, ...)` grid functionality relies on
+knowledge from the browser about screen dimensions and the number of available grid
+items for it to work properly. Autoprefixer does not have access to this information
+so unfortunately this little snippet will _never_ be IE friendly.
+
+```css
+.grid {
+ /* This will never be IE friendly */
+ grid-template-columns: repeat(auto-fit, min-max(200px, 1fr));
+}
+```
+
+#### No manual cell placement or column/row spans allowed inside an autoplacement grid
+
+Elements must not be manually placed or given column/row spans inside
+an autoplacement grid. Only the most basic of autoplacement grids are supported.
+Grid cells can still be placed manually outside the the explicit grid though.
+Support for manually placing individual grid cells inside an explicit
+autoplacement grid is planned for a future release.
+
+```css
+.autoplacement-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-rows: repeat(3, auto);
+}
+
+/* Grid cells placed inside the explicit grid
+ will break the layout in IE */
+.not-permitted-grid-cell {
+ grid-column: 1;
+ grid-row: 1;
+}
+
+/* Grid cells placed outside the
+ explicit grid will work in IE */
+.permitted-grid-cell {
+ grid-column: 1 / span 2;
+ grid-row: 4;
+}
+```
+
+If manual cell placement is required, we recommend using `grid-template` or
+`grid-template-areas` instead:
+
+```css
+.page {
+ display: grid;
+ grid-gap: 30px;
+ grid-template:
+ 'head head'
+ 'nav main' minmax(100px, 1fr)
+ 'foot foot' /
+ 200px 1fr;
+}
+.page__head {
+ grid-area: head;
+}
+.page__nav {
+ grid-area: nav;
+}
+.page__main {
+ grid-area: main;
+}
+.page__footer {
+ grid-area: foot;
+}
+```
+
+#### Do not create `::before` and `::after` pseudo elements
+
+Let's say you have this HTML:
+
+```html
+
+```
+
+And you write this CSS:
+
+```css
+.grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-template-rows: auto;
+}
+
+.grid::before {
+ content: 'before';
+}
+
+.grid::after {
+ content: 'after';
+}
+```
+
+This will be the output:
+
+```css
+.grid {
+ display: -ms-grid;
+ display: grid;
+ -ms-grid-columns: 1fr 1fr;
+ grid-template-columns: 1fr 1fr;
+ -ms-grid-rows: auto;
+ grid-template-rows: auto;
+}
+
+.grid > *:nth-child(1) {
+ -ms-grid-row: 1;
+ -ms-grid-column: 1;
+}
+
+.grid > *:nth-child(2) {
+ -ms-grid-row: 1;
+ -ms-grid-column: 2;
+}
+
+.grid::before {
+ content: 'before';
+}
+
+.grid::after {
+ content: 'after';
+}
+```
+
+IE will place `.grid-cell`, `::before` and `::after` in row 1 column 1.
+Modern browsers on the other hand will place `::before` in row 1 column 1,
+`.grid-cell` in row 1 column 2, and `::after` in row 2 column 1.
+
+See this [CodePen](https://codepen.io/daniel-tonon/pen/gBymVw) to see a visualization
+of the issue. View the CodePen in both a modern browser and IE to see the difference.
+
+Note that you can still create `::before` and `::after` elements as long as you manually
+place them outside the explicit grid.
+
+#### When changing the `grid gap` value, columns and rows must be re-declared
+
+If you wish to change the size of a `grid-gap`, you will need to redeclare the grid columns and rows.
+
+```css
+.grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-template-rows: auto;
+ grid-gap: 50px;
+}
+
+/* This will *NOT* work in IE */
+@media (max-width: 600px) {
+ .grid {
+ grid-gap: 20px;
+ }
+}
+
+/* This will *NOT* work in IE */
+.grid.small-gap {
+ grid-gap: 20px;
+}
+```
+
+```css
+.grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-template-rows: auto;
+ grid-gap: 50px;
+}
+
+/* This *WILL* work in IE */
+@media (max-width: 600px) {
+ .grid {
+ grid-template-columns: 1fr 1fr;
+ grid-template-rows: auto;
+ grid-gap: 20px;
+ }
+}
+
+/* This *WILL* work in IE */
+.grid.small-gap {
+ grid-template-columns: 1fr 1fr;
+ grid-template-rows: auto;
+ grid-gap: 20px;
+}
+```
+
+## Debug
+
+Run `npx autoprefixer --info` in your project directory to check
+which browsers are selected and which properties will be prefixed:
+
+```console
+$ npx autoprefixer --info
+Browsers:
+ Edge: 16
+
+These browsers account for 0.26% of all users globally
+
+At-Rules:
+ @viewport: ms
+
+Selectors:
+ ::placeholder: ms
+
+Properties:
+ appearance: webkit
+ flow-from: ms
+ flow-into: ms
+ hyphens: ms
+ overscroll-behavior: ms
+ region-fragment: ms
+ scroll-snap-coordinate: ms
+ scroll-snap-destination: ms
+ scroll-snap-points-x: ms
+ scroll-snap-points-y: ms
+ scroll-snap-type: ms
+ text-size-adjust: ms
+ text-spacing: ms
+ user-select: ms
+```
+
+JS API is also available:
+
+```js
+console.log(autoprefixer().info())
+```
+
+## Security Contact
+
+To report a security vulnerability, please use the [Tidelift security contact].
+Tidelift will coordinate the fix and disclosure.
+
+[Tidelift security contact]: https://tidelift.com/security
+
+## For Enterprise
+
+Available as part of the Tidelift Subscription.
+
+The maintainers of `autoprefixer` and thousands of other packages are working
+with Tidelift to deliver commercial support and maintenance for the open source
+dependencies you use to build your applications. Save time, reduce risk,
+and improve code health, while paying the maintainers of the exact dependencies
+you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-autoprefixer?utm_source=npm-autoprefixer&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
diff --git a/lib/processor.js b/lib/processor.js
new file mode 100644
index 0000000..e884ffb
--- /dev/null
+++ b/lib/processor.js
@@ -0,0 +1,710 @@
+let parser = require('postcss-value-parser')
+
+let Value = require('./value')
+let insertAreas = require('./hacks/grid-utils').insertAreas
+
+const OLD_LINEAR = /(^|[^-])linear-gradient\(\s*(top|left|right|bottom)/i
+const OLD_RADIAL = /(^|[^-])radial-gradient\(\s*\d+(\w*|%)\s+\d+(\w*|%)\s*,/i
+const IGNORE_NEXT = /(!\s*)?autoprefixer:\s*ignore\s+next/i
+const GRID_REGEX = /(!\s*)?autoprefixer\s*grid:\s*(on|off|(no-)?autoplace)/i
+
+const SIZES = [
+ 'width',
+ 'height',
+ 'min-width',
+ 'max-width',
+ 'min-height',
+ 'max-height',
+ 'inline-size',
+ 'min-inline-size',
+ 'max-inline-size',
+ 'block-size',
+ 'min-block-size',
+ 'max-block-size'
+]
+
+function hasGridTemplate(decl) {
+ return decl.parent.some(
+ i => i.prop === 'grid-template' || i.prop === 'grid-template-areas'
+ )
+}
+
+function hasRowsAndColumns(decl) {
+ let hasRows = decl.parent.some(i => i.prop === 'grid-template-rows')
+ let hasColumns = decl.parent.some(i => i.prop === 'grid-template-columns')
+ return hasRows && hasColumns
+}
+
+function insideGrid(decl) {
+ return decl.parent.nodes.some(node => {
+ if (node.type !== 'decl') return false
+ let displayGrid =
+ node.prop === 'display' && /(inline-)?grid/.test(node.value)
+ let gridTemplate = node.prop.startsWith('grid-template')
+ let gridGap = /^grid-([A-z]+-)?gap/.test(node.prop)
+ return displayGrid || gridTemplate || gridGap
+ })
+}
+
+class Processor {
+ constructor(prefixes) {
+ this.prefixes = prefixes
+ }
+
+ /**
+ * Add necessary prefixes
+ */
+ add(css, result) {
+ // At-rules
+ let resolution = this.prefixes.add['@resolution']
+ let keyframes = this.prefixes.add['@keyframes']
+ let viewport = this.prefixes.add['@viewport']
+ let supports = this.prefixes.add['@supports']
+
+ css.walkAtRules(rule => {
+ if (rule.name === 'keyframes') {
+ if (!this.disabled(rule, result)) {
+ return keyframes && keyframes.process(rule)
+ }
+ } else if (rule.name === 'viewport') {
+ if (!this.disabled(rule, result)) {
+ return viewport && viewport.process(rule)
+ }
+ } else if (rule.name === 'supports') {
+ if (
+ this.prefixes.options.supports !== false &&
+ !this.disabled(rule, result)
+ ) {
+ return supports.process(rule)
+ }
+ } else if (rule.name === 'media' && rule.params.includes('-resolution')) {
+ if (!this.disabled(rule, result)) {
+ return resolution && resolution.process(rule)
+ }
+ }
+
+ return undefined
+ })
+
+ // Selectors
+ css.walkRules(rule => {
+ if (this.disabled(rule, result)) return undefined
+
+ return this.prefixes.add.selectors.map(selector => {
+ return selector.process(rule, result)
+ })
+ })
+
+ let gridPrefixes =
+ this.gridStatus(css, result) &&
+ this.prefixes.add['grid-area'] &&
+ this.prefixes.add['grid-area'].prefixes
+
+ css.walkDecls(decl => {
+ if (this.disabledDecl(decl, result)) return undefined
+
+ let parent = decl.parent
+ let prop = decl.prop
+ let value = decl.value
+
+ if (prop === 'color-adjust') {
+ if (parent.every(i => i.prop !== 'print-color-adjust')) {
+ result.warn(
+ 'Replace color-adjust to print-color-adjust. ' +
+ 'The color-adjust shorthand is currently deprecated.',
+ { node: decl }
+ )
+ }
+ } else if (prop === 'grid-row-span') {
+ result.warn(
+ 'grid-row-span is not part of final Grid Layout. Use grid-row.',
+ { node: decl }
+ )
+ return undefined
+ } else if (prop === 'grid-column-span') {
+ result.warn(
+ 'grid-column-span is not part of final Grid Layout. Use grid-column.',
+ { node: decl }
+ )
+ return undefined
+ } else if (prop === 'display' && value === 'box') {
+ result.warn(
+ 'You should write display: flex by final spec ' +
+ 'instead of display: box',
+ { node: decl }
+ )
+ return undefined
+ } else if (prop === 'text-emphasis-position') {
+ if (value === 'under' || value === 'over') {
+ result.warn(
+ 'You should use 2 values for text-emphasis-position ' +
+ 'For example, `under left` instead of just `under`.',
+ { node: decl }
+ )
+ }
+ } else if (prop === 'text-decoration-skip' && value === 'ink') {
+ result.warn(
+ 'Replace text-decoration-skip: ink to ' +
+ 'text-decoration-skip-ink: auto, because spec had been changed',
+ { node: decl }
+ )
+ } else {
+ if (gridPrefixes && this.gridStatus(decl, result)) {
+ if (decl.value === 'subgrid') {
+ result.warn('IE does not support subgrid', { node: decl })
+ }
+ if (/^(align|justify|place)-items$/.test(prop) && insideGrid(decl)) {
+ let fixed = prop.replace('-items', '-self')
+ result.warn(
+ `IE does not support ${prop} on grid containers. ` +
+ `Try using ${fixed} on child elements instead: ` +
+ `${decl.parent.selector} > * { ${fixed}: ${decl.value} }`,
+ { node: decl }
+ )
+ } else if (
+ /^(align|justify|place)-content$/.test(prop) &&
+ insideGrid(decl)
+ ) {
+ result.warn(`IE does not support ${decl.prop} on grid containers`, {
+ node: decl
+ })
+ } else if (prop === 'display' && decl.value === 'contents') {
+ result.warn(
+ 'Please do not use display: contents; ' +
+ 'if you have grid setting enabled',
+ { node: decl }
+ )
+ return undefined
+ } else if (decl.prop === 'grid-gap') {
+ let status = this.gridStatus(decl, result)
+ if (
+ status === 'autoplace' &&
+ !hasRowsAndColumns(decl) &&
+ !hasGridTemplate(decl)
+ ) {
+ result.warn(
+ 'grid-gap only works if grid-template(-areas) is being ' +
+ 'used or both rows and columns have been declared ' +
+ 'and cells have not been manually ' +
+ 'placed inside the explicit grid',
+ { node: decl }
+ )
+ } else if (
+ (status === true || status === 'no-autoplace') &&
+ !hasGridTemplate(decl)
+ ) {
+ result.warn(
+ 'grid-gap only works if grid-template(-areas) is being used',
+ { node: decl }
+ )
+ }
+ } else if (prop === 'grid-auto-columns') {
+ result.warn('grid-auto-columns is not supported by IE', {
+ node: decl
+ })
+ return undefined
+ } else if (prop === 'grid-auto-rows') {
+ result.warn('grid-auto-rows is not supported by IE', { node: decl })
+ return undefined
+ } else if (prop === 'grid-auto-flow') {
+ let hasRows = parent.some(i => i.prop === 'grid-template-rows')
+ let hasCols = parent.some(i => i.prop === 'grid-template-columns')
+
+ if (hasGridTemplate(decl)) {
+ result.warn('grid-auto-flow is not supported by IE', {
+ node: decl
+ })
+ } else if (value.includes('dense')) {
+ result.warn('grid-auto-flow: dense is not supported by IE', {
+ node: decl
+ })
+ } else if (!hasRows && !hasCols) {
+ result.warn(
+ 'grid-auto-flow works only if grid-template-rows and ' +
+ 'grid-template-columns are present in the same rule',
+ { node: decl }
+ )
+ }
+ return undefined
+ } else if (value.includes('auto-fit')) {
+ result.warn('auto-fit value is not supported by IE', {
+ node: decl,
+ word: 'auto-fit'
+ })
+ return undefined
+ } else if (value.includes('auto-fill')) {
+ result.warn('auto-fill value is not supported by IE', {
+ node: decl,
+ word: 'auto-fill'
+ })
+ return undefined
+ } else if (prop.startsWith('grid-template') && value.includes('[')) {
+ result.warn(
+ 'Autoprefixer currently does not support line names. ' +
+ 'Try using grid-template-areas instead.',
+ { node: decl, word: '[' }
+ )
+ }
+ }
+ if (value.includes('radial-gradient')) {
+ if (OLD_RADIAL.test(decl.value)) {
+ result.warn(
+ 'Gradient has outdated direction syntax. ' +
+ 'New syntax is like `closest-side at 0 0` ' +
+ 'instead of `0 0, closest-side`.',
+ { node: decl }
+ )
+ } else {
+ let ast = parser(value)
+
+ for (let i of ast.nodes) {
+ if (i.type === 'function' && i.value === 'radial-gradient') {
+ for (let word of i.nodes) {
+ if (word.type === 'word') {
+ if (word.value === 'cover') {
+ result.warn(
+ 'Gradient has outdated direction syntax. ' +
+ 'Replace `cover` to `farthest-corner`.',
+ { node: decl }
+ )
+ } else if (word.value === 'contain') {
+ result.warn(
+ 'Gradient has outdated direction syntax. ' +
+ 'Replace `contain` to `closest-side`.',
+ { node: decl }
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (value.includes('linear-gradient')) {
+ if (OLD_LINEAR.test(value)) {
+ result.warn(
+ 'Gradient has outdated direction syntax. ' +
+ 'New syntax is like `to left` instead of `right`.',
+ { node: decl }
+ )
+ }
+ }
+ }
+
+ if (SIZES.includes(decl.prop)) {
+ if (!decl.value.includes('-fill-available')) {
+ if (decl.value.includes('fill-available')) {
+ result.warn(
+ 'Replace fill-available to stretch, ' +
+ 'because spec had been changed',
+ { node: decl }
+ )
+ } else if (decl.value.includes('fill')) {
+ let ast = parser(value)
+ if (ast.nodes.some(i => i.type === 'word' && i.value === 'fill')) {
+ result.warn(
+ 'Replace fill to stretch, because spec had been changed',
+ { node: decl }
+ )
+ }
+ }
+ }
+ }
+
+ let prefixer
+
+ if (decl.prop === 'transition' || decl.prop === 'transition-property') {
+ // Transition
+ return this.prefixes.transition.add(decl, result)
+ } else if (decl.prop === 'align-self') {
+ // align-self flexbox or grid
+ let display = this.displayType(decl)
+ if (display !== 'grid' && this.prefixes.options.flexbox !== false) {
+ prefixer = this.prefixes.add['align-self']
+ if (prefixer && prefixer.prefixes) {
+ prefixer.process(decl)
+ }
+ }
+ if (this.gridStatus(decl, result) !== false) {
+ prefixer = this.prefixes.add['grid-row-align']
+ if (prefixer && prefixer.prefixes) {
+ return prefixer.process(decl, result)
+ }
+ }
+ } else if (decl.prop === 'justify-self') {
+ // justify-self flexbox or grid
+ if (this.gridStatus(decl, result) !== false) {
+ prefixer = this.prefixes.add['grid-column-align']
+ if (prefixer && prefixer.prefixes) {
+ return prefixer.process(decl, result)
+ }
+ }
+ } else if (decl.prop === 'place-self') {
+ prefixer = this.prefixes.add['place-self']
+ if (
+ prefixer &&
+ prefixer.prefixes &&
+ this.gridStatus(decl, result) !== false
+ ) {
+ return prefixer.process(decl, result)
+ }
+ } else {
+ // Properties
+ prefixer = this.prefixes.add[decl.prop]
+ if (prefixer && prefixer.prefixes) {
+ return prefixer.process(decl, result)
+ }
+ }
+
+ return undefined
+ })
+
+ // Insert grid-area prefixes. We need to be able to store the different
+ // rules as a data and hack API is not enough for this
+ if (this.gridStatus(css, result)) {
+ insertAreas(css, this.disabled)
+ }
+
+ // Values
+ return css.walkDecls(decl => {
+ if (this.disabledValue(decl, result)) return
+
+ let unprefixed = this.prefixes.unprefixed(decl.prop)
+ let list = this.prefixes.values('add', unprefixed)
+ if (Array.isArray(list)) {
+ for (let value of list) {
+ if (value.process) value.process(decl, result)
+ }
+ }
+ Value.save(this.prefixes, decl)
+ })
+ }
+
+ /**
+ * Check for control comment and global options
+ */
+ disabled(node, result) {
+ if (!node) return false
+
+ if (node._autoprefixerDisabled !== undefined) {
+ return node._autoprefixerDisabled
+ }
+
+ if (node.parent) {
+ let p = node.prev()
+ if (p && p.type === 'comment' && IGNORE_NEXT.test(p.text)) {
+ node._autoprefixerDisabled = true
+ node._autoprefixerSelfDisabled = true
+ return true
+ }
+ }
+
+ let value = null
+ if (node.nodes) {
+ let status
+ node.each(i => {
+ if (i.type !== 'comment') return
+ if (/(!\s*)?autoprefixer:\s*(off|on)/i.test(i.text)) {
+ if (typeof status !== 'undefined') {
+ result.warn(
+ 'Second Autoprefixer control comment ' +
+ 'was ignored. Autoprefixer applies control ' +
+ 'comment to whole block, not to next rules.',
+ { node: i }
+ )
+ } else {
+ status = /on/i.test(i.text)
+ }
+ }
+ })
+
+ if (status !== undefined) {
+ value = !status
+ }
+ }
+ if (!node.nodes || value === null) {
+ if (node.parent) {
+ let isParentDisabled = this.disabled(node.parent, result)
+ if (node.parent._autoprefixerSelfDisabled === true) {
+ value = false
+ } else {
+ value = isParentDisabled
+ }
+ } else {
+ value = false
+ }
+ }
+ node._autoprefixerDisabled = value
+ return value
+ }
+
+ /**
+ * Check for grid/flexbox options.
+ */
+ disabledDecl(node, result) {
+ if (node.type === 'decl' && this.gridStatus(node, result) === false) {
+ if (node.prop.includes('grid') || node.prop === 'justify-items') {
+ return true
+ }
+ }
+ if (node.type === 'decl' && this.prefixes.options.flexbox === false) {
+ let other = ['order', 'justify-content', 'align-items', 'align-content']
+ if (node.prop.includes('flex') || other.includes(node.prop)) {
+ return true
+ }
+ }
+
+ return this.disabled(node, result)
+ }
+
+ /**
+ * Check for grid/flexbox options.
+ */
+ disabledValue(node, result) {
+ if (this.gridStatus(node, result) === false && node.type === 'decl') {
+ if (node.prop === 'display' && node.value.includes('grid')) {
+ return true
+ }
+ }
+ if (this.prefixes.options.flexbox === false && node.type === 'decl') {
+ if (node.prop === 'display' && node.value.includes('flex')) {
+ return true
+ }
+ }
+ if (node.type === 'decl' && node.prop === 'content') {
+ return true
+ }
+
+ return this.disabled(node, result)
+ }
+
+ /**
+ * Is it flebox or grid rule
+ */
+ displayType(decl) {
+ for (let i of decl.parent.nodes) {
+ if (i.prop !== 'display') {
+ continue
+ }
+
+ if (i.value.includes('flex')) {
+ return 'flex'
+ }
+
+ if (i.value.includes('grid')) {
+ return 'grid'
+ }
+ }
+
+ return false
+ }
+
+ /**
+ * Set grid option via control comment
+ */
+ gridStatus(node, result) {
+ if (!node) return false
+
+ if (node._autoprefixerGridStatus !== undefined) {
+ return node._autoprefixerGridStatus
+ }
+
+ let value = null
+ if (node.nodes) {
+ let status
+ node.each(i => {
+ if (i.type !== 'comment') return
+ if (GRID_REGEX.test(i.text)) {
+ let hasAutoplace = /:\s*autoplace/i.test(i.text)
+ let noAutoplace = /no-autoplace/i.test(i.text)
+ if (typeof status !== 'undefined') {
+ result.warn(
+ 'Second Autoprefixer grid control comment was ' +
+ 'ignored. Autoprefixer applies control comments to the whole ' +
+ 'block, not to the next rules.',
+ { node: i }
+ )
+ } else if (hasAutoplace) {
+ status = 'autoplace'
+ } else if (noAutoplace) {
+ status = true
+ } else {
+ status = /on/i.test(i.text)
+ }
+ }
+ })
+
+ if (status !== undefined) {
+ value = status
+ }
+ }
+
+ if (node.type === 'atrule' && node.name === 'supports') {
+ let params = node.params
+ if (params.includes('grid') && params.includes('auto')) {
+ value = false
+ }
+ }
+
+ if (!node.nodes || value === null) {
+ if (node.parent) {
+ let isParentGrid = this.gridStatus(node.parent, result)
+ if (node.parent._autoprefixerSelfDisabled === true) {
+ value = false
+ } else {
+ value = isParentGrid
+ }
+ } else if (typeof this.prefixes.options.grid !== 'undefined') {
+ value = this.prefixes.options.grid
+ } else if (typeof process.env.AUTOPREFIXER_GRID !== 'undefined') {
+ if (process.env.AUTOPREFIXER_GRID === 'autoplace') {
+ value = 'autoplace'
+ } else {
+ value = true
+ }
+ } else {
+ value = false
+ }
+ }
+
+ node._autoprefixerGridStatus = value
+ return value
+ }
+
+ /**
+ * Normalize spaces in cascade declaration group
+ */
+ reduceSpaces(decl) {
+ let stop = false
+ this.prefixes.group(decl).up(() => {
+ stop = true
+ return true
+ })
+ if (stop) {
+ return
+ }
+
+ let parts = decl.raw('before').split('\n')
+ let prevMin = parts[parts.length - 1].length
+ /** @type {number|false} */
+ let diff = false
+
+ this.prefixes.group(decl).down(other => {
+ parts = other.raw('before').split('\n')
+ let last = parts.length - 1
+
+ if (parts[last].length > prevMin) {
+ if (diff === false) {
+ diff = parts[last].length - prevMin
+ }
+
+ parts[last] = parts[last].slice(0, -diff)
+ other.raws.before = parts.join('\n')
+ }
+ })
+ }
+
+ /**
+ * Remove unnecessary pefixes
+ */
+ remove(css, result) {
+ // At-rules
+ let resolution = this.prefixes.remove['@resolution']
+
+ css.walkAtRules((rule, i) => {
+ if (this.prefixes.remove[`@${rule.name}`]) {
+ if (!this.disabled(rule, result)) {
+ rule.parent.removeChild(i)
+ }
+ } else if (
+ rule.name === 'media' &&
+ rule.params.includes('-resolution') &&
+ resolution
+ ) {
+ resolution.clean(rule)
+ }
+ })
+
+ // Selectors
+ css.walkRules((rule, i) => {
+ if (this.disabled(rule, result)) return
+
+ for (let checker of this.prefixes.remove.selectors) {
+ if (checker.check(rule)) {
+ rule.parent.removeChild(i)
+ return
+ }
+ }
+ })
+
+ return css.walkDecls((decl, i) => {
+ if (this.disabled(decl, result)) return
+
+ let rule = decl.parent
+ let unprefixed = this.prefixes.unprefixed(decl.prop)
+
+ // Transition
+ if (decl.prop === 'transition' || decl.prop === 'transition-property') {
+ this.prefixes.transition.remove(decl)
+ }
+
+ // Properties
+ if (
+ this.prefixes.remove[decl.prop] &&
+ this.prefixes.remove[decl.prop].remove
+ ) {
+ let notHack = this.prefixes.group(decl).down(other => {
+ return this.prefixes.normalize(other.prop) === unprefixed
+ })
+
+ if (unprefixed === 'flex-flow') {
+ notHack = true
+ }
+
+ if (decl.prop === '-webkit-box-orient') {
+ let hacks = { 'flex-direction': true, 'flex-flow': true }
+ if (!decl.parent.some(j => hacks[j.prop])) return
+ }
+
+ if (notHack && !this.withHackValue(decl)) {
+ if (decl.raw('before').includes('\n')) {
+ this.reduceSpaces(decl)
+ }
+ rule.removeChild(i)
+ return
+ }
+ }
+
+ // Values
+ for (let checker of this.prefixes.values('remove', unprefixed)) {
+ if (!checker.check) continue
+ if (!checker.check(decl.value)) continue
+
+ unprefixed = checker.unprefixed
+ let notHack = this.prefixes.group(decl).down(other => {
+ return other.value.includes(unprefixed)
+ })
+
+ if (notHack) {
+ rule.removeChild(i)
+ return
+ }
+ }
+ })
+ }
+
+ /**
+ * Some rare old values, which is not in standard
+ */
+ withHackValue(decl) {
+ return (
+ (decl.prop === '-webkit-background-clip' && decl.value === 'text') ||
+ // Do not remove -webkit-box-orient when -webkit-line-clamp is present.
+ // https://github.com/postcss/autoprefixer/issues/1510
+ (decl.prop === '-webkit-box-orient' &&
+ decl.parent.some(d => d.prop === '-webkit-line-clamp'))
+ )
+ }
+}
+
+module.exports = Processor
diff --git a/test/autoprefixer.test.js b/test/autoprefixer.test.js
index e321480..af1da78 100644
--- a/test/autoprefixer.test.js
+++ b/test/autoprefixer.test.js
@@ -1337,20 +1337,6 @@ body > .two {
equal(result.css, output)
})
-test('sets source for grid nodes', () => {
- for (let name of [
- 'grid-template-areas',
- 'grid-media-rules',
- 'grid-autoplacement'
- ]) {
- let result = postcss([prefixer('grid')]).process(read(name), {
- from: name + '.css',
- map: { inline: false }
- })
- equal(result.map.toJSON().sources, [name + '.css'])
- }
-})
-
test('ignores values for CSS3PIE props', () => {
let css = read('pie')
equal(postcss([compiler]).process(css).css, css)