Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d8c7d5d

Browse files
committed
feat: support with vitepress
1 parent a774baf commit d8c7d5d

File tree

6 files changed

+130
-79
lines changed

6 files changed

+130
-79
lines changed

.github/workflows/ci.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ jobs:
3939
- uses: actions/checkout@v4
4040

4141
- name: Install pnpm
42-
uses: pnpm/action-setup@v2
42+
uses: pnpm/action-setup@v4
4343

4444
- name: Set node
4545
uses: actions/setup-node@v4
4646
with:
47-
node-version: 16.x
47+
node-version: 18.x
4848
cache: pnpm
4949

5050
- name: Setup
@@ -61,15 +61,15 @@ jobs:
6161

6262
strategy:
6363
matrix:
64-
node: [16.x, 18.x]
64+
node: [18.x]
6565
os: [ubuntu-latest, windows-latest, macos-latest]
6666
fail-fast: false
6767

6868
steps:
6969
- uses: actions/checkout@v4
7070

7171
- name: Install pnpm
72-
uses: pnpm/action-setup@v2
72+
uses: pnpm/action-setup@v4
7373

7474
- name: Set node version to ${{ matrix.node }}
7575
uses: actions/setup-node@v4

README.md

+14
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,20 @@ export default defineConfig({
1616
})
1717
```
1818

19+
In [vitepress](https://vitepress.dev/)
20+
21+
```ts
22+
import vueStyleInTemplate from 'vite-plugin-vue-style-in-template'
23+
24+
export default defineConfig({
25+
plugins: [
26+
vueStyleInTemplate({
27+
include: [/\.vue/, /\.md/],
28+
}),
29+
],
30+
})
31+
```
32+
1933
## Example
2034

2135
transform:

package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@
1919
"exports": {
2020
".": {
2121
"types": "./dist/index.d.ts",
22-
"import": "./dist/index.mjs",
23-
"require": "./dist/index.js"
22+
"import": "./dist/index.js",
23+
"require": "./dist/index.cjs"
2424
},
2525
"./*": "./*"
2626
},
27-
"main": "./dist/index.js",
28-
"module": "./dist/index.mjs",
27+
"main": "./dist/index.cjs",
28+
"module": "./dist/index.js",
2929
"types": "./dist/index.d.ts",
3030
"files": [
3131
"dist",

src/index.ts

+8-71
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,16 @@
11
import type { Plugin } from 'vite'
2-
import { parse } from '@vue/compiler-sfc'
2+
import type { Options } from './type'
3+
import vueStyleInTemplate from './plugin'
34

4-
export default function vitePluginVueStyleInTemplate(): Plugin {
5+
export default function vitePluginVueStyleInTemplate(options: Options = {}): Plugin {
56
return {
67
name: 'vite-plugin-vue-style-in-template',
78
enforce: 'pre',
8-
transform(code: string, id: string) {
9-
// 只处理 .vue 文件
10-
if (!id.endsWith('.vue'))
11-
return null
12-
13-
const { descriptor } = parse(code)
14-
15-
if (!descriptor.template)
16-
return null
17-
18-
const templateContent = descriptor.template.content
19-
const styleRegex = /<style([^>]*)>([\s\S]*?)<\/style>/g
20-
let noScopedStyles = ''
21-
let scopedStyles = ''
22-
23-
const newTemplateContent = templateContent.replace(styleRegex, (_, attributes: string, styleContent: string) => {
24-
if (attributes.includes('scoped')) {
25-
scopedStyles += `${styleContent}\n`
26-
}
27-
else {
28-
noScopedStyles += `${styleContent}\n`
29-
}
30-
return ''
31-
})
32-
33-
if (!noScopedStyles && !scopedStyles)
34-
return null
35-
36-
// 构建新的代码
37-
let newCode = code
38-
39-
// 更新 template 内容
40-
if (descriptor.template) {
41-
newCode = newCode.replace(
42-
descriptor.template.content,
43-
newTemplateContent,
44-
)
45-
}
46-
47-
// 如果已经存在 style 标签
48-
if (descriptor.styles.length > 0) {
49-
descriptor.styles.forEach((style) => {
50-
if (style.attrs.scoped && scopedStyles) {
51-
newCode = newCode.replace(
52-
style.content,
53-
`${style.content}\n${scopedStyles}`,
54-
)
55-
scopedStyles = ''
56-
}
57-
else if (!style.attrs.scoped && noScopedStyles) {
58-
newCode = newCode.replace(
59-
style.content,
60-
`${style.content}\n${noScopedStyles}`,
61-
)
62-
noScopedStyles = ''
63-
}
64-
})
65-
}
66-
67-
if (scopedStyles) {
68-
newCode += `\n<style scoped>\n${scopedStyles}</style>`
69-
}
70-
else if (noScopedStyles) {
71-
newCode += `\n<style>\n${noScopedStyles}</style>`
72-
}
73-
74-
return {
75-
code: newCode,
76-
map: null,
9+
configResolved(config) {
10+
// 将当前插件插入到 vite:vue 之前
11+
const index = config.plugins.findIndex(p => p && p.name === 'vite:vue')
12+
if (index !== -1) {
13+
(config.plugins as Plugin[]).splice(index, 0, vueStyleInTemplate(options))
7714
}
7815
},
7916
}

src/plugin.ts

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import type { Plugin } from 'vite'
2+
import type { Options } from './type'
3+
import { parse } from '@vue/compiler-sfc'
4+
5+
export default function vitePluginVueStyleInTemplate(options: Options): Plugin {
6+
const defaultOptions: Required<Options> = {
7+
include: [/\.vue/],
8+
}
9+
const finalInclude = options.include ?? defaultOptions.include
10+
const verifyInclude = (id: string) => {
11+
for (const item of finalInclude) {
12+
if (typeof item === 'string') {
13+
if (id.includes(item))
14+
return true
15+
}
16+
else if (item.test(id)) {
17+
return true
18+
}
19+
}
20+
return false
21+
}
22+
23+
return {
24+
name: 'vite-plugin-vue-style-in-template',
25+
transform(code: string, id: string) {
26+
// 只处理 .vue 文件
27+
if (!verifyInclude(id))
28+
return null
29+
30+
const { descriptor } = parse(code)
31+
32+
if (!descriptor.template)
33+
return null
34+
35+
const templateContent = descriptor.template.content
36+
const styleRegex = /<style([^>]*)>([\s\S]*?)<\/style>/g
37+
let noScopedStyles = ''
38+
let scopedStyles = ''
39+
40+
const newTemplateContent = templateContent.replace(styleRegex, (_, attributes: string, styleContent: string) => {
41+
if (attributes.includes('scoped')) {
42+
scopedStyles += `${styleContent}\n`
43+
}
44+
else {
45+
noScopedStyles += `${styleContent}\n`
46+
}
47+
return ''
48+
})
49+
50+
if (!noScopedStyles && !scopedStyles)
51+
return null
52+
53+
// 构建新的代码
54+
let newCode = code
55+
56+
// 更新 template 内容
57+
if (descriptor.template) {
58+
newCode = newCode.replace(
59+
descriptor.template.content,
60+
newTemplateContent,
61+
)
62+
}
63+
64+
// 如果已经存在 style 标签
65+
if (descriptor.styles.length > 0) {
66+
descriptor.styles.forEach((style) => {
67+
if (style.attrs.scoped && scopedStyles) {
68+
newCode = newCode.replace(
69+
style.content,
70+
`${style.content}\n${scopedStyles}`,
71+
)
72+
scopedStyles = ''
73+
}
74+
else if (!style.attrs.scoped && noScopedStyles) {
75+
newCode = newCode.replace(
76+
style.content,
77+
`${style.content}\n${noScopedStyles}`,
78+
)
79+
noScopedStyles = ''
80+
}
81+
})
82+
}
83+
84+
if (scopedStyles) {
85+
newCode += `\n<style scoped>\n${scopedStyles}</style>`
86+
}
87+
else if (noScopedStyles) {
88+
newCode += `\n<style>\n${noScopedStyles}</style>`
89+
}
90+
91+
return {
92+
code: newCode,
93+
map: null,
94+
}
95+
},
96+
}
97+
}

src/type.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export interface Options {
2+
include?: (RegExp | string)[]
3+
}

0 commit comments

Comments
 (0)