Skip to content

Commit

Permalink
Fix nested tail ampersands (#116)
Browse files Browse the repository at this point in the history
* Add a bunch of (partially failing) tests

* Fix incorrect replacement of deeply nested tail ampersands

* Adjust whitespace in test assertion

I’d prefer the original version, but I understand why it doesn’t work atm and see no non-hackish way to change it
  • Loading branch information
rluba committed Feb 26, 2021
1 parent db5bce7 commit d352092
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 4 deletions.
8 changes: 5 additions & 3 deletions index.js
Expand Up @@ -132,7 +132,7 @@ module.exports = (opts = {}) => {

return {
postcssPlugin: 'postcss-nested',
RuleExit (rule, { Rule }) {
Rule (rule, { Rule }) {
let unwrapped = false
let after = rule
let copyDeclarations = false
Expand All @@ -152,8 +152,6 @@ module.exports = (opts = {}) => {
after.after(child)
after = child
} else if (child.type === 'atrule') {
copyDeclarations = false

if (declarations.length) {
after = pickDeclarations(rule.selector, declarations, after, Rule)
declarations = []
Expand All @@ -172,17 +170,21 @@ module.exports = (opts = {}) => {
after = nodes
child.remove()
} else if (bubble[child.name]) {
copyDeclarations = true
unwrapped = true
atruleChilds(rule, child, true)
after = pickComment(child.prev(), after)
after.after(child)
after = child
} else if (unwrap[child.name]) {
copyDeclarations = true
unwrapped = true
atruleChilds(rule, child, false)
after = pickComment(child.prev(), after)
after.after(child)
after = child
} else if (copyDeclarations) {
declarations.push(child)
}
} else if (child.type === 'decl' && copyDeclarations) {
declarations.push(child)
Expand Down
45 changes: 44 additions & 1 deletion index.test.js
Expand Up @@ -55,7 +55,7 @@ it('unwrap rules inside at-rules', () => {
it('unwraps at-rule', () => {
run(
'a { b { @media screen { width: auto } } }',
'@media screen { a b { width: auto } }'
'@media screen {a b { width: auto } }'
)
})

Expand Down Expand Up @@ -87,6 +87,13 @@ it('unwraps at-rules', () => {
)
})

it('unwraps at-rules with interleaved properties', () => {
run(
'a { a: 1 } a { color: red; @media screen { @supports (a: 1) { a: 1 } } background: green }',
'a { a: 1 } a { color: red; } @media screen { @supports (a: 1) { a { a: 1 } } } a { background: green }'
)
})

it('do not move custom at-rules', () => {
run(
'.one { @mixin test; } .two { @phone { color: black } }',
Expand Down Expand Up @@ -171,6 +178,25 @@ it('replaces ampersands in not selector', () => {
run('.a { &:not(&.no) {} }', '.a:not(.a.no) {}')
})

it('correctly replaces tail ampersands', () => {
run('.a { .b & {} }', '.b .a {}')
})

it('correctly replaces tail ampersands that are nested further down', () => {
run('.a { .b { .c & {} } }', '.c .a .b {}')
})

it('correctly replaces tail ampersands that are nested inside ampersand rules', () => {
run('.a { &:hover { .b { .c & {} } } }', '.c .a:hover .b {}')
})

it('preserves child order when replacing tail ampersands', () => {
run(
'.a { color: red; .first {} @mixinFirst; .b & {} @mixinLast; .last {} }',
'.a { color: red; } .a .first {} .a { @mixinFirst; } .b .a {} .a { @mixinLast; } .a .last {}'
)
})

it('handles :host selector case', () => {
run(':host { &(:focus) {} }', ':host(:focus) {}')
})
Expand All @@ -192,6 +218,23 @@ it('works with other visitors', () => {
expect(out).toEqual('a b{color:red}a .in .deep{color:blue}')
})

it('works with other visitors #2', () => {
let css = 'a { @mixin; b {color:red} }'
let mixinPlugin = () => {
return {
postcssPlugin: 'mixin',
AtRule: {
mixin (node) {
node.replaceWith('.in { .deep {color:blue} }')
}
}
}
}
mixinPlugin.postcss = true
let out = postcss([plugin, mixinPlugin]).process(css, { from: undefined }).css
expect(out).toEqual('a .in .deep {color:blue} a b {color:red}')
})

it('shows clear errors on missed semicolon', () => {
let css = 'a{\n color: black\n @mixin b { }\n}\n'
expect(() => {
Expand Down

0 comments on commit d352092

Please sign in to comment.