fix(build): ignore escaped `:` when splitting selector in `postcssIsolateStyles` (#4830)

pull/4814/merge
Alex 2 months ago committed by GitHub
parent 5d41785ff7
commit a629b03f0e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,44 @@
import {
postcssIsolateStyles,
splitSelectorPseudo
} from 'node/postcss/isolateStyles'
// helper to run plugin transform on selector
function apply(
prefixPlugin: ReturnType<typeof postcssIsolateStyles>,
selector: string
) {
// `prepare` is available on the runtime plugin but missing from the types, thus cast to `any`
const { Rule } = (prefixPlugin as any).prepare({
root: { source: { input: { file: 'foo/base.css' } } }
})
const rule = { selectors: [selector] }
Rule(rule, { result: {} })
return rule.selectors[0]
}
describe('node/postcss/isolateStyles', () => {
const plugin = postcssIsolateStyles()
test('splitSelectorPseudo skips escaped colon', () => {
const input = '.foo\\:bar'
const [selector, pseudo] = splitSelectorPseudo(input)
expect(selector).toBe(input)
expect(pseudo).toBe('')
})
test('splitSelectorPseudo splits on pseudo selectors', () => {
const input = '.button:hover'
const [selector, pseudo] = splitSelectorPseudo(input)
expect(selector).toBe('.button')
expect(pseudo).toBe(':hover')
})
it('postcssIsolateStyles inserts :not(...) in the right place', () => {
const input = '.disabled\\:opacity-50:disabled'
const result = apply(plugin, input)
expect(result).toBe(
'.disabled\\:opacity-50:not(:where(.vp-raw, .vp-raw *)):disabled'
)
})
})

@ -7,9 +7,15 @@ export function postcssIsolateStyles(
prefix: ':not(:where(.vp-raw, .vp-raw *))', prefix: ':not(:where(.vp-raw, .vp-raw *))',
includeFiles: [/base\.css/], includeFiles: [/base\.css/],
transform(prefix, _selector) { transform(prefix, _selector) {
const [selector, pseudo = ''] = _selector.split(/(:\S*)$/) // split selector from its pseudo part if the trailing colon is not escaped
const [selector, pseudo] = splitSelectorPseudo(_selector)
return selector + prefix + pseudo return selector + prefix + pseudo
}, },
...options ...options
}) })
} }
export function splitSelectorPseudo(selector: string): [string, string] {
const [base, pseudo = ''] = selector.split(/(?<!\\)(:\S*)$/)
return [base, pseudo]
}

Loading…
Cancel
Save