@@ -6,47 +6,50 @@ import { sort } from 'fast-sort'
6
6
import { jsStringEscape } from '@ast-core/escape'
7
7
import { parse , ParseResult } from '@babel/parser'
8
8
import traverse from '@babel/traverse'
9
- import { getStringLiteralCalleeName , getTemplateElementCalleeName } from './utils'
10
9
import { escapeStringRegexp } from '@/utils'
11
10
import type { Context } from '@/ctx'
11
+ import { between } from '@/math'
12
12
13
13
interface Options {
14
14
replaceMap : Map < string , string >
15
15
magicString : MagicString
16
16
id : string
17
17
ctx : Context
18
+ markedArray : [ number , number ] [ ]
18
19
}
19
20
20
21
type HandleValueOptions = {
21
22
raw : string
22
23
path : babel . NodePath < babel . types . StringLiteral | babel . types . TemplateElement >
23
24
offset : number
24
25
escape : boolean
25
- preserve : boolean
26
26
} & Options
27
27
28
28
export function handleValue ( options : HandleValueOptions ) {
29
- const { ctx, id, path, magicString, raw, replaceMap, offset = 0 , escape = false , preserve = false } = options
29
+ const { ctx, id, path, magicString, raw, replaceMap, offset = 0 , escape = false , markedArray } = options
30
30
const node = path . node
31
31
let value = raw
32
+ // why 字符串字面量只要开始和结束 在 方法节点内就保留, 另外不可能出现 字符串字面量 开始和结束的下标整个包括 方法体,这是不可能出现的事情
33
+ for ( const [ s , e ] of markedArray ) {
34
+ if ( between ( node . start , s , e ) || between ( node . end , s , e ) ) {
35
+ return
36
+ }
37
+ }
38
+
32
39
const arr = sort ( splitCode ( value ) ) . desc ( ( x ) => x . length )
33
40
34
41
for ( const str of arr ) {
35
42
if ( replaceMap . has ( str ) ) {
36
43
ctx . addToUsedBy ( str , id )
37
- if ( preserve ) {
38
- ctx . addPreserveClass ( str )
39
- }
44
+
40
45
// replace
41
46
const v = replaceMap . get ( str )
42
47
if ( v ) {
43
48
value = value . replaceAll ( str , v )
44
49
}
45
50
}
46
51
}
47
- if ( preserve ) {
48
- return
49
- }
52
+
50
53
if ( typeof node . start === 'number' && typeof node . end === 'number' && value ) {
51
54
const start = node . start + offset
52
55
const end = node . end - offset
@@ -58,11 +61,11 @@ export function handleValue(options: HandleValueOptions) {
58
61
59
62
export const JsPlugin = declare ( ( api , options : Options ) => {
60
63
api . assertVersion ( 7 )
61
- const { magicString, replaceMap, id, ctx } = options
64
+ const { magicString, replaceMap, id, ctx, markedArray } = options
62
65
return {
63
66
visitor : {
64
67
StringLiteral : {
65
- enter ( p ) {
68
+ exit ( p ) {
66
69
const opts : HandleValueOptions = {
67
70
ctx,
68
71
id,
@@ -72,17 +75,14 @@ export const JsPlugin = declare((api, options: Options) => {
72
75
replaceMap,
73
76
offset : 1 ,
74
77
escape : true ,
75
- preserve : false
76
- }
77
- const calleeName = getStringLiteralCalleeName ( p )
78
- if ( calleeName && ctx . isPreserveFunction ( calleeName ) ) {
79
- opts . preserve = true
78
+ markedArray
80
79
}
80
+
81
81
handleValue ( opts )
82
82
}
83
83
} ,
84
84
TemplateElement : {
85
- enter ( p ) {
85
+ exit ( p ) {
86
86
const opts : HandleValueOptions = {
87
87
ctx,
88
88
id,
@@ -92,12 +92,9 @@ export const JsPlugin = declare((api, options: Options) => {
92
92
replaceMap,
93
93
offset : 0 ,
94
94
escape : false ,
95
- preserve : false
96
- }
97
- const calleeName = getTemplateElementCalleeName ( p )
98
- if ( calleeName && ctx . isPreserveFunction ( calleeName ) ) {
99
- opts . preserve = true
95
+ markedArray
100
96
}
97
+
101
98
handleValue ( opts )
102
99
}
103
100
}
@@ -112,27 +109,88 @@ interface IPreProcessJsOptions {
112
109
ctx : Context
113
110
}
114
111
115
- function transformSync ( code : string , plugins : babel . PluginItem [ ] | null | undefined , filename : string | null | undefined ) {
116
- babel . transformSync ( code , {
117
- presets : [
118
- // ['@babel/preset-react', {}],
119
- [
120
- require ( '@babel/preset-typescript' ) ,
121
- {
122
- allExtensions : true ,
123
- isTSX : true
124
- }
125
- ]
126
- ] ,
112
+ function transformSync ( ast : babel . types . Node , code : string , plugins : babel . PluginItem [ ] | null | undefined , filename : string | null | undefined ) {
113
+ babel . transformFromAstSync ( ast , code , {
114
+ presets : loadPresets ( ) ,
127
115
plugins,
128
116
filename
129
117
} )
130
118
}
131
119
120
+ export function loadPresets ( ) {
121
+ return [
122
+ [
123
+ require ( '@babel/preset-typescript' ) ,
124
+ {
125
+ allExtensions : true ,
126
+ isTSX : true
127
+ }
128
+ ]
129
+ ]
130
+ }
131
+
132
132
export function preProcessJs ( options : IPreProcessJsOptions ) {
133
133
const { code, replaceMap, id, ctx } = options
134
134
const magicString = typeof code === 'string' ? new MagicString ( code ) : code
135
+ let ast : ParseResult < babel . types . File >
136
+ try {
137
+ const file = babel . parseSync ( magicString . original , {
138
+ sourceType : 'unambiguous' ,
139
+ presets : loadPresets ( )
140
+ } )
141
+ if ( file ) {
142
+ ast = file
143
+ } else {
144
+ return code
145
+ }
146
+ } catch {
147
+ return code
148
+ }
149
+ const markedArray : [ number , number ] [ ] = [ ]
150
+ traverse ( ast , {
151
+ CallExpression : {
152
+ enter ( p ) {
153
+ const callee = p . get ( 'callee' )
154
+ if ( callee . isIdentifier ( ) && ctx . isPreserveFunction ( callee . node . name ) ) {
155
+ if ( p . node . start && p . node . end ) {
156
+ markedArray . push ( [ p . node . start , p . node . end ] )
157
+ }
158
+
159
+ p . traverse ( {
160
+ StringLiteral : {
161
+ enter ( path ) {
162
+ const node = path . node
163
+ const value = node . value
164
+ const arr = sort ( splitCode ( value ) ) . desc ( ( x ) => x . length )
165
+
166
+ for ( const str of arr ) {
167
+ if ( replaceMap . has ( str ) ) {
168
+ ctx . addPreserveClass ( str )
169
+ }
170
+ }
171
+ }
172
+ } ,
173
+ TemplateElement : {
174
+ enter ( path ) {
175
+ const node = path . node
176
+ const value = node . value . raw
177
+ const arr = sort ( splitCode ( value ) ) . desc ( ( x ) => x . length )
178
+
179
+ for ( const str of arr ) {
180
+ if ( replaceMap . has ( str ) ) {
181
+ ctx . addPreserveClass ( str )
182
+ }
183
+ }
184
+ }
185
+ }
186
+ } )
187
+ }
188
+ }
189
+ }
190
+ } )
191
+
135
192
transformSync (
193
+ ast ,
136
194
magicString . original ,
137
195
[
138
196
[
@@ -141,7 +199,8 @@ export function preProcessJs(options: IPreProcessJsOptions) {
141
199
magicString,
142
200
replaceMap,
143
201
id,
144
- ctx
202
+ ctx,
203
+ markedArray
145
204
}
146
205
]
147
206
] ,
@@ -203,10 +262,8 @@ export function preProcessRawCode(options: IPreProcessRawCodeOptions) {
203
262
continue
204
263
}
205
264
}
206
- // console.log(arr, regex.lastIndex)
207
265
}
208
266
for ( const [ key , value ] of replaceMap ) {
209
- // if (!ctx.isPreserveClass(key)) {
210
267
// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec
211
268
const regex = new RegExp ( escapeStringRegexp ( key ) , 'g' )
212
269
let arr : RegExpExecArray | null = null
@@ -215,7 +272,7 @@ export function preProcessRawCode(options: IPreProcessRawCodeOptions) {
215
272
const end = arr . index + arr [ 0 ] . length
216
273
let shouldUpdate = true
217
274
for ( const [ ps , pe ] of markArr ) {
218
- if ( ( start > ps && start < pe ) || ( end < pe && end > ps ) ) {
275
+ if ( between ( start , ps , pe ) || between ( end , ps , pe ) ) {
219
276
shouldUpdate = false
220
277
break
221
278
}
@@ -228,8 +285,4 @@ export function preProcessRawCode(options: IPreProcessRawCodeOptions) {
228
285
}
229
286
230
287
return magicString . toString ( )
231
- // for (const [key, value] of replaceMap) {
232
- // code = code.replaceAll(key, value)
233
- // }
234
- // return code
235
288
}
0 commit comments