mirror of https://github.com/vuejs/vitepress
BREAKING CHANGE: `includeFiles` option in `postcssIsolateStyles` now defaults to `[/vp-doc\.css/, /base\.css/]` You can remove explicit `includeFiles` if you were using it just to run it on `vp-doc.css`. To revert back to older behavior pass `includeFiles: [/base\.css/]`. The underlying implementation is changed and `transform` and `exclude` options are no longer supported. Use `postcss-prefix-selector` directly if you've advanced use cases.pull/4910/head
parent
991c780a07
commit
0944777893
File diff suppressed because it is too large
Load Diff
@ -1,21 +1,38 @@
|
|||||||
import postcssPrefixSelector from 'postcss-prefix-selector'
|
import type { Plugin } from 'postcss'
|
||||||
|
import selectorParser from 'postcss-selector-parser'
|
||||||
|
|
||||||
export function postcssIsolateStyles(
|
type Options = {
|
||||||
options: Parameters<typeof postcssPrefixSelector>[0] = {}
|
includeFiles?: RegExp[]
|
||||||
): ReturnType<typeof postcssPrefixSelector> {
|
ignoreFiles?: RegExp[]
|
||||||
return postcssPrefixSelector({
|
prefix?: string
|
||||||
prefix: ':not(:where(.vp-raw, .vp-raw *))',
|
|
||||||
includeFiles: [/base\.css/],
|
|
||||||
transform(prefix, _selector) {
|
|
||||||
// split selector from its pseudo part if the trailing colon is not escaped
|
|
||||||
const [selector, pseudo] = splitSelectorPseudo(_selector)
|
|
||||||
return selector + prefix + pseudo
|
|
||||||
},
|
|
||||||
...options
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function splitSelectorPseudo(selector: string): [string, string] {
|
export function postcssIsolateStyles({
|
||||||
const [base, pseudo = ''] = selector.split(/(?<!\\)(:\S*)$/)
|
includeFiles = [/vp-doc\.css/, /base\.css/],
|
||||||
return [base, pseudo]
|
ignoreFiles,
|
||||||
|
prefix = ':not(:where(.vp-raw, .vp-raw *))'
|
||||||
|
}: Options = {}): Plugin {
|
||||||
|
const prefixNodes = selectorParser().astSync(prefix).first.nodes
|
||||||
|
|
||||||
|
return /* prettier-ignore */ {
|
||||||
|
postcssPlugin: 'postcss-isolate-styles',
|
||||||
|
Once(root) {
|
||||||
|
const file = root.source?.input.file
|
||||||
|
if (file && includeFiles?.length && !includeFiles.some((re) => re.test(file))) return
|
||||||
|
if (file && ignoreFiles?.length && ignoreFiles.some((re) => re.test(file))) return
|
||||||
|
|
||||||
|
root.walkRules((rule) => {
|
||||||
|
if (!rule.selector || rule.selector.includes(prefix)) return
|
||||||
|
if (rule.parent?.type === 'atrule' && /\bkeyframes$/i.test(rule.parent.name)) return
|
||||||
|
|
||||||
|
rule.selector = selectorParser((selectors) => {
|
||||||
|
selectors.each((sel) => {
|
||||||
|
if (!sel.nodes.length) return
|
||||||
|
const insertionIndex = sel.nodes.findLastIndex((n) => n.type !== 'pseudo') + 1
|
||||||
|
sel.nodes.splice(insertionIndex, 0, ...prefixNodes.map((n) => n.clone() as any))
|
||||||
|
})
|
||||||
|
}).processSync(rule.selector)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in new issue