@@ -3,12 +3,12 @@ import {
3
3
VueFile ,
4
4
getDefaultVueLanguagePlugins ,
5
5
replace ,
6
+ getLength ,
6
7
} from "@volar/vue-language-core" ;
8
+ import { capitalize , camelize } from "@vue/shared" ;
7
9
8
10
function pascalCase ( str : string ) {
9
- return str
10
- . replace ( / (?: \b | _ ) [ a - z ] / g, ( c ) => c . toUpperCase ( ) )
11
- . replace ( / [ \W _ ] + / g, "" ) ;
11
+ return capitalize ( camelize ( str ) ) ;
12
12
}
13
13
14
14
const plugin : VueLanguagePlugin = ( ctx ) => {
@@ -88,29 +88,33 @@ const plugin: VueLanguagePlugin = (ctx) => {
88
88
if ( typeof segment === "string" ) {
89
89
newContent . push ( segment ) ;
90
90
} else {
91
- let base = 0 ;
91
+ let base : number | undefined = 0 ;
92
92
// eslint-disable-next-line unicorn/prefer-switch
93
93
if ( segment [ 1 ] === "template" ) {
94
- base = vueFile . sfc . template ! . startTagEnd ;
94
+ base = vueFile . sfc . template ? .startTagEnd ;
95
95
} else if ( segment [ 1 ] === "script" ) {
96
- base = vueFile . sfc . script ! . startTagEnd ;
96
+ base = vueFile . sfc . script ? .startTagEnd ;
97
97
} else if ( segment [ 1 ] === "scriptSetup" ) {
98
- base = vueFile . sfc . scriptSetup ! . startTagEnd ;
98
+ base = vueFile . sfc . scriptSetup ? .startTagEnd ;
99
99
} else if ( segment [ 1 ] ?. startsWith ( "style_" ) ) {
100
100
const index = Number ( segment [ 1 ] . slice ( "style_" . length ) ) ;
101
- base = vueFile . sfc . styles [ index ] ! . startTagEnd ;
101
+ base = vueFile . sfc . styles [ index ] ? .startTagEnd ;
102
102
} else if ( segment [ 1 ] ?. startsWith ( "customBlock_" ) ) {
103
103
const index = Number ( segment [ 1 ] . slice ( "customBlock_" . length ) ) ;
104
- base = vueFile . sfc . customBlocks [ index ] ! . startTagEnd ;
104
+ base = vueFile . sfc . customBlocks [ index ] ?. startTagEnd ;
105
+ }
106
+ if ( base !== undefined ) {
107
+ newContent . push ( [
108
+ segment [ 0 ] ,
109
+ componentBlock . name ,
110
+ typeof segment [ 2 ] === "number"
111
+ ? segment [ 2 ] + base
112
+ : [ segment [ 2 ] [ 0 ] + base , segment [ 2 ] [ 1 ] + base ] ,
113
+ segment [ 3 ] ,
114
+ ] ) ;
115
+ } else {
116
+ newContent . push ( segment [ 0 ] ) ;
105
117
}
106
- newContent . push ( [
107
- segment [ 0 ] ,
108
- componentBlock . name ,
109
- typeof segment [ 2 ] === "number"
110
- ? segment [ 2 ] + base
111
- : [ segment [ 2 ] [ 0 ] + base , segment [ 2 ] [ 1 ] + base ] ,
112
- segment [ 3 ] ,
113
- ] ) ;
114
118
}
115
119
}
116
120
embeddedFile . content = newContent ;
@@ -135,38 +139,56 @@ const plugin: VueLanguagePlugin = (ctx) => {
135
139
`${ fileName } __VLS_NSFC_${ b . name . slice (
136
140
"customBlock_" . length
137
141
) } .vue`
138
- ) } ;\n `
142
+ ) } ;`
139
143
)
140
144
) ;
141
145
146
+ // export components
147
+ embeddedFile . content . push (
148
+ `\nexport { ${ componentBlocks
149
+ . map ( ( b ) => pascalCase ( b . attrs . name as string ) )
150
+ . join ( ", " ) } };\n`
151
+ ) ;
152
+
153
+ const codeLength = getLength ( embeddedFile . content ) ;
154
+
142
155
// register components
143
156
if ( sfc . scriptSetup ) {
144
157
replace (
145
158
embeddedFile . content ,
146
- / s e t u p \( \) { \n r e t u r n { \n / ,
147
- "setup() {" ,
148
- "return {" ,
159
+ new RegExp (
160
+ `const __VLS_internalComponent = \\(await import\\('${ ctx . vueCompilerOptions . lib } '\\)\\)\\.defineComponent\\({\nsetup\\(\\) {\nreturn {\n`
161
+ ) ,
162
+ `const __VLS_internalComponent = (await import('${ ctx . vueCompilerOptions . lib } ')).defineComponent({\nsetup() {\nreturn {\n` ,
149
163
...componentBlocks . map (
150
164
( b ) => `${ pascalCase ( b . attrs . name as string ) } ,\n`
151
165
)
152
166
) ;
153
167
} else {
154
168
replace (
155
169
embeddedFile . content ,
156
- / c o n s t _ _ V L S _ c o m p o n e n t s O p t i o n = { / ,
170
+ " const __VLS_componentsOption = {" ,
157
171
"const __VLS_componentsOption = {\n" ,
158
172
...componentBlocks . map (
159
173
( b ) => `${ pascalCase ( b . attrs . name as string ) } ,\n`
160
174
)
161
175
) ;
162
176
}
163
177
164
- // export components
165
- embeddedFile . content . push (
166
- `\nexport { ${ componentBlocks
167
- . map ( ( b ) => pascalCase ( b . attrs . name as string ) )
168
- . join ( ", " ) } };\n`
169
- ) ;
178
+ // mappings have to be shifted because of the added code when replacing
179
+ const lengthShift = getLength ( embeddedFile . content ) - codeLength ;
180
+ embeddedFile . mirrorBehaviorMappings =
181
+ embeddedFile . mirrorBehaviorMappings . map ( ( mapping ) => ( {
182
+ ...mapping ,
183
+ sourceRange : [
184
+ mapping . sourceRange [ 0 ] + lengthShift ,
185
+ mapping . sourceRange [ 1 ] + lengthShift ,
186
+ ] ,
187
+ generatedRange : [
188
+ mapping . generatedRange [ 0 ] + lengthShift ,
189
+ mapping . generatedRange [ 1 ] + lengthShift ,
190
+ ] ,
191
+ } ) ) ;
170
192
}
171
193
} ,
172
194
} ;
0 commit comments