Skip to content

Commit 8dbb2d1

Browse files
committed
feat: support sourcemap, close #33
1 parent 1498d35 commit 8dbb2d1

File tree

9 files changed

+55
-39
lines changed

9 files changed

+55
-39
lines changed

examples/vue2/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"vite-plugin-vue2": "^1.4.3"
1212
},
1313
"dependencies": {
14-
"vue": "3.0.11",
14+
"vue": "2.6.12",
1515
"vue-template-compiler": "2.6.12"
1616
}
1717
}

examples/vue2/vite.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ const config: UserConfig = {
77
createVuePlugin(),
88
ViteComponents(),
99
],
10+
build: {
11+
sourcemap: true,
12+
},
1013
}
1114

1215
export default config

examples/vue3/vite.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ const config: UserConfig = {
3131
],
3232
}),
3333
],
34+
build: {
35+
sourcemap: true,
36+
},
3437
}
3538

3639
export default config

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"chokidar": "^3.5.1",
3232
"debug": "^4.3.2",
3333
"fast-glob": "^3.2.5",
34+
"magic-string": "^0.25.7",
3435
"minimatch": "^3.0.4"
3536
},
3637
"devDependencies": {

pnpm-lock.yaml

Lines changed: 4 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { Vue2Transformer } from './transforms/vue2'
77

88
function VitePluginComponents(options: Options = {}): Plugin {
99
let ctx: Context
10-
let transformers: Transformer[]
10+
let transformer: Transformer
1111

1212
return {
1313
name: 'vite-plugin-components',
@@ -17,21 +17,16 @@ function VitePluginComponents(options: Options = {}): Plugin {
1717
options.transformer = options.transformer || 'vue2'
1818

1919
ctx = new Context(options, config)
20-
transformers = [
21-
ctx.options.transformer === 'vue2'
22-
? Vue2Transformer(ctx)
23-
: Vue3Transformer(ctx),
24-
]
20+
transformer = ctx.options.transformer === 'vue2'
21+
? Vue2Transformer(ctx)
22+
: Vue3Transformer(ctx)
2523
},
2624
configureServer(server) {
2725
ctx.setServer(server)
2826
},
2927
transform(code, id) {
3028
const { path, query } = parseId(id)
31-
for (const trans of transformers)
32-
code = trans(code, id, path, query)
33-
34-
return code
29+
return transformer(code, id, path, query)
3530
},
3631
}
3732
}

src/transforms/vue2.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Debug from 'debug'
2+
import MagicString from 'magic-string'
23
import { Transformer } from '../types'
34
import { Context } from '../context'
45
import { pascalCase, stringifyComponentImport } from '../utils'
@@ -8,7 +9,7 @@ const debug = Debug('vite-plugin-components:transform:vue2')
89
export function Vue2Transformer(ctx: Context): Transformer {
910
return (code, id, path, query) => {
1011
if (!(path.endsWith('.vue') || ctx.options.customLoaderMatcher(id)))
11-
return code
12+
return null
1213

1314
ctx.searchGlob()
1415

@@ -19,30 +20,36 @@ export function Vue2Transformer(ctx: Context): Transformer {
1920
let no = 0
2021
const componentPaths: string[] = []
2122

22-
let transformed = code.replace(/_c\(['"](.+?)["']([,)])/g, (str, match, append) => {
23-
if (match && !match.startsWith('_')) {
24-
debug(`| ${match}`)
25-
const name = pascalCase(match)
23+
const s = new MagicString(code)
24+
25+
for (const match of code.matchAll(/_c\(['"](.+?)["']([,)])/g)) {
26+
const [full, matchStr, append] = match
27+
28+
if (match.index != null && matchStr && !matchStr.startsWith('_')) {
29+
const start = match.index
30+
const end = start + full.length
31+
debug(`| ${matchStr}`)
32+
const name = pascalCase(matchStr)
2633
componentPaths.push(name)
2734
const component = ctx.findComponent(name, [sfcPath])
2835
if (component) {
2936
const var_name = `__vite_components_${no}`
3037
head.push(stringifyComponentImport({ ...component, name: var_name }, ctx))
3138
no += 1
32-
return `_c(${var_name}${append}`
39+
s.overwrite(start, end, `_c(${var_name}${append}`)
3340
}
3441
}
35-
return str
36-
})
37-
38-
debug(transformed)
42+
}
3943

4044
debug(`^ (${no})`)
4145

4246
ctx.updateUsageMap(sfcPath, componentPaths)
4347

44-
transformed = `${head.join('\n')}\n${transformed}`
48+
s.prepend(`${head.join('\n')}\n`)
4549

46-
return transformed
50+
return {
51+
code: s.toString(),
52+
map: s.generateMap(),
53+
}
4754
}
4855
}

src/transforms/vue3.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Debug from 'debug'
2+
import MagicString from 'magic-string'
23
import { Transformer } from '../types'
34
import { Context } from '../context'
45
import { pascalCase, stringifyComponentImport } from '../utils'
@@ -8,7 +9,7 @@ const debug = Debug('vite-plugin-components:transform:vue3')
89
export function Vue3Transformer(ctx: Context): Transformer {
910
return (code, id, path, query) => {
1011
if (!(path.endsWith('.vue') || ctx.options.customLoaderMatcher(id)))
11-
return code
12+
return null
1213

1314
ctx.searchGlob()
1415

@@ -19,28 +20,35 @@ export function Vue3Transformer(ctx: Context): Transformer {
1920
let no = 0
2021
const componentPaths: string[] = []
2122

22-
let transformed = code.replace(/_resolveComponent\("(.+?)"\)/g, (str, match) => {
23-
if (match && !match.startsWith('_')) {
24-
debug(`| ${match}`)
25-
const name = pascalCase(match)
23+
const s = new MagicString(code)
24+
25+
for (const match of code.matchAll(/_resolveComponent\("(.+?)"\)/g)) {
26+
const matchedName = match[1]
27+
if (match.index != null && matchedName && !matchedName.startsWith('_')) {
28+
const start = match.index
29+
const end = start + match[0].length
30+
debug(`| ${matchedName}`)
31+
const name = pascalCase(matchedName)
2632
componentPaths.push(name)
2733
const component = ctx.findComponent(name, [sfcPath])
2834
if (component) {
2935
const var_name = `__vite_components_${no}`
3036
head.push(stringifyComponentImport({ ...component, name: var_name }, ctx))
3137
no += 1
32-
return var_name
38+
s.overwrite(start, end, var_name)
3339
}
3440
}
35-
return str
36-
})
41+
}
3742

3843
debug(`^ (${no})`)
3944

4045
ctx.updateUsageMap(sfcPath, componentPaths)
4146

42-
transformed = `${head.join('\n')}\n${transformed}`
47+
s.prepend(`${head.join('\n')}\n`)
4348

44-
return transformed
49+
return {
50+
code: s.toString(),
51+
map: s.generateMap(),
52+
}
4553
}
4654
}

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export interface UILibraryOptions {
2020

2121
export type Matcher = (id: string) => boolean | null | undefined
2222

23-
export type Transformer = (code: string, id: string, path: string, query: Record<string, string>) => string
23+
export type Transformer = (code: string, id: string, path: string, query: Record<string, string>) => null | {code: string; map: any}
2424

2525
/**
2626
* Plugin options.

0 commit comments

Comments
 (0)