diff --git a/lib/selector.js b/lib/selector.js index 123f38f96..2b8f68c25 100644 --- a/lib/selector.js +++ b/lib/selector.js @@ -1,3 +1,5 @@ +let { list } = require('postcss') + let OldSelector = require('./old-selector') let Prefixer = require('./prefixer') let Browsers = require('./browsers') @@ -53,15 +55,30 @@ class Selector extends Prefixer { */ prefixeds (rule) { if (rule._autoprefixerPrefixeds) { - return rule._autoprefixerPrefixeds + if (rule._autoprefixerPrefixeds[this.name]) { + return rule._autoprefixerPrefixeds + } + } else { + rule._autoprefixerPrefixeds = {} } let prefixeds = {} - for (let prefix of this.possible()) { - prefixeds[prefix] = this.replace(rule.selector, prefix) + if (rule.selector.includes(',')) { + let ruleParts = list.comma(rule.selector) + let toProcess = ruleParts.filter(el => el.includes(this.name)) + + for (let prefix of this.possible()) { + prefixeds[prefix] = toProcess + .map(el => this.replace(el, prefix)) + .join(', ') + } + } else { + for (let prefix of this.possible()) { + prefixeds[prefix] = this.replace(rule.selector, prefix) + } } - rule._autoprefixerPrefixeds = prefixeds + rule._autoprefixerPrefixeds[this.name] = prefixeds return rule._autoprefixerPrefixeds } @@ -79,8 +96,8 @@ class Selector extends Prefixer { } let some = false - for (let key in prefixeds) { - let prefixed = prefixeds[key] + for (let key in prefixeds[this.name]) { + let prefixed = prefixeds[this.name][key] if (before.selector === prefixed) { if (prefix === key) { return true @@ -117,7 +134,7 @@ class Selector extends Prefixer { return } - let cloned = this.clone(rule, { selector: prefixeds[prefix] }) + let cloned = this.clone(rule, { selector: prefixeds[this.name][prefix] }) rule.parent.insertBefore(rule, cloned) } diff --git a/test/autoprefixer.test.js b/test/autoprefixer.test.js index f05096ac0..ee677ea96 100644 --- a/test/autoprefixer.test.js +++ b/test/autoprefixer.test.js @@ -44,6 +44,10 @@ let uncascader = autoprefixer({ let gradienter = autoprefixer({ overrideBrowserslist: ['Chrome 25', 'Opera 12', 'Android 2.3'] }) +let grouping = autoprefixer({ + overrideBrowserslist: ['Chrome 25', 'Firefox > 17', 'IE 10', 'Edge 12'], + grid: 'autoplace' +}) let ffgradienter = autoprefixer({ overrideBrowserslist: ['Chrome 25', 'Opera 12', 'Firefox 6'] }) @@ -90,6 +94,8 @@ function prefixer (name) { return gradienter } else if (name === 'gradient-fix') { return ffgradienter + } else if (name === 'grouping-rule') { + return grouping } else if (name === 'flexbox' || name === 'flex-rewrite') { return flexboxer } else if (name === 'double') { @@ -244,6 +250,7 @@ it('saves declaration style', () => check('style')) it('uses ignore next control comments', () => check('ignore-next')) it('uses block control comments', () => check('disabled')) it('has actual example in docs', () => check('example')) +it('process grouping rules correctly', () => check('grouping-rule')) it('uses control comments to whole scope', () => { let input = read('scope') diff --git a/test/cases/grouping-rule.css b/test/cases/grouping-rule.css new file mode 100644 index 000000000..0a59e477f --- /dev/null +++ b/test/cases/grouping-rule.css @@ -0,0 +1,23 @@ +.grid { + display: grid; +} + +.a, +.b, +.c::selection, +.d:read-only, +.e::placeholder { + color: yellow; +} + +::selection { + color: red; +} + +:read-only { + color: black; +} + +.f:read-write, .g:read-write { + background: #fff; +} diff --git a/test/cases/grouping-rule.out.css b/test/cases/grouping-rule.out.css new file mode 100644 index 000000000..829872bc1 --- /dev/null +++ b/test/cases/grouping-rule.out.css @@ -0,0 +1,64 @@ +.grid { + display: -ms-grid; + display: grid; +} + +.c::-moz-selection { + color: yellow; +} + +.e::-webkit-input-placeholder { + color: yellow; +} + +.e:-moz-placeholder { + color: yellow; +} + +.e::-moz-placeholder { + color: yellow; +} + +.e:-ms-input-placeholder { + color: yellow; +} + +.e::-ms-input-placeholder { + color: yellow; +} + +.d:-moz-read-only { + color: yellow; +} + +.a, +.b, +.c::selection, +.d:read-only, +.e::placeholder { + color: yellow; +} + +::-moz-selection { + color: red; +} + +::selection { + color: red; +} + +:-moz-read-only { + color: black; +} + +:read-only { + color: black; +} + +.f:-moz-read-write, .g:-moz-read-write { + background: #fff; +} + +.f:read-write, .g:read-write { + background: #fff; +} diff --git a/test/selector.test.js b/test/selector.test.js index de590fd9d..afe4109b9 100644 --- a/test/selector.test.js +++ b/test/selector.test.js @@ -28,7 +28,7 @@ describe('regexp()', () => { }) describe('check()', () => { - it('shecks rule selectors', () => { + it('checks rule selectors', () => { let css = parse('body .selection {}, ' + ':::selection {}, body ::selection {}') expect(selector.check(css.nodes[0])).toBeFalsy() @@ -38,13 +38,36 @@ describe('check()', () => { }) describe('prefixeds()', () => { - it('returns all avaiable prefixed selectors', () => { + it('grouping rule gets correct _autoprefixerPrefixeds property', () => { + let css = parse('.c::selection, .d:read-only {}') + let rSel = new Selector(':read-only', ['-moz-']) + selector.prefixeds(css.first) + rSel.prefixeds(css.first) + expect(css.first._autoprefixerPrefixeds).toEqual({ + '::selection': { + '-webkit-': '.c::-webkit-selection', + '-moz-': '.c::-moz-selection', + '-ms-': '.c::-ms-selection', + '-o-': '.c::-o-selection' + }, + ':read-only': { + '-webkit-': '.d:-webkit-read-only', + '-moz-': '.d:-moz-read-only', + '-ms-': '.d:-ms-read-only', + '-o-': '.d:-o-read-only' + } + }) + }) + + it('returns all available prefixed selectors', () => { let css = parse('::selection {}') expect(selector.prefixeds(css.first)).toEqual({ - '-webkit-': '::-webkit-selection', - '-moz-': '::-moz-selection', - '-ms-': '::-ms-selection', - '-o-': '::-o-selection' + '::selection': { + '-webkit-': '::-webkit-selection', + '-moz-': '::-moz-selection', + '-ms-': '::-ms-selection', + '-o-': '::-o-selection' + } }) }) })