11import { invalidChars } from '../lib/adaptMiniPrograms'
22import tailwindcss from '../index'
33
4+ /**
5+ * 从 JavaScript 表达式中提取所有字符串字面量并替换
6+ * 支持数组、对象、三元运算符等复杂语法
7+ */
8+ function replaceStringLiterals ( expression , escapeFn ) {
9+ const replacements = [ ]
10+ let i = 0
11+ let inString = false
12+ let stringChar = null
13+ let stringStart = 0
14+ let escaped = false
15+
16+ // 第一步:找到所有字符串字面量的位置
17+ while ( i < expression . length ) {
18+ const char = expression [ i ]
19+
20+ if ( ! inString ) {
21+ // 检查是否是字符串开始(单引号或双引号)
22+ if ( ( char === '"' || char === "'" ) && ! escaped ) {
23+ inString = true
24+ stringChar = char
25+ stringStart = i
26+ escaped = false
27+ } else {
28+ escaped = char === '\\' && ! escaped
29+ }
30+ } else {
31+ // 在字符串内部
32+ if ( char === '\\' && ! escaped ) {
33+ escaped = true
34+ } else if ( char === stringChar && ! escaped ) {
35+ // 字符串结束,记录需要替换的内容
36+ const stringContent = expression . slice ( stringStart + 1 , i )
37+ const escapedContent = escapeFn ( stringContent )
38+ replacements . push ( {
39+ start : stringStart + 1 ,
40+ end : i ,
41+ replacement : escapedContent ,
42+ } )
43+ inString = false
44+ stringChar = null
45+ escaped = false
46+ } else {
47+ escaped = false
48+ }
49+ }
50+
51+ i ++
52+ }
53+
54+ // 第二步:从后向前替换,避免位置偏移
55+ let result = expression
56+ for ( let j = replacements . length - 1 ; j >= 0 ; j -- ) {
57+ const { start, end, replacement } = replacements [ j ]
58+ result = result . slice ( 0 , start ) + replacement + result . slice ( end )
59+ }
60+
61+ return result
62+ }
63+
464export default function modifyClasses ( ) {
565 return {
666 name : 'modify-classes' ,
@@ -20,20 +80,43 @@ export default function modifyClasses() {
2080 return
2181 }
2282
23- const re = new RegExp (
24- `[${ Array . from ( invalidChars )
25- . map ( ( char ) => `\\${ char } ` )
26- . join ( '' ) } ]`,
27- 'g'
28- )
29- // 替换所有 class="..."
30- const transformed = code . replace ( / c l a s s \s * = \s * " ( [ ^ " ] + ) " / g, ( _ , classValue ) => {
31- const newClasses = classValue
83+ // 构建转义正则,转义字符类中需要转义的特殊字符
84+ // 在字符类中,需要转义的字符有: ] \ - ^
85+ const escapedChars = Array . from ( invalidChars )
86+ . map ( ( char ) => {
87+ // 在字符类中,] 和 \ 需要转义
88+ if ( char === ']' || char === '\\' ) {
89+ return `\\${ char } `
90+ }
91+ return char
92+ } )
93+ . join ( '' )
94+ const re = new RegExp ( `[${ escapedChars } ]` , 'g' )
95+
96+ // 转义类名中的特殊字符
97+ const escapeClassName = ( className ) => className . replace ( re , '_' )
98+
99+ // 转义类名字符串中的类名
100+ const escapeClassString = ( classString ) => {
101+ return classString
32102 . split ( / \s + / )
33- . map ( ( cls ) => cls . replace ( re , '_' ) )
103+ . map ( ( cls ) => escapeClassName ( cls ) )
34104 . join ( ' ' )
35- return `class="${ newClasses } "`
105+ }
106+
107+ let transformed = code
108+
109+ // 替换 class="..." (但不匹配 :class)
110+ transformed = transformed . replace ( / ( ^ | [ ^ : ] ) ( \s * ) c l a s s \s * = \s * " ( [ ^ " ] + ) " / g, ( match , before , space , classValue ) => {
111+ return `${ before } ${ space } class="${ escapeClassString ( classValue ) } "`
112+ } )
113+
114+ // 使用 AST 解析 :class 绑定中的 JavaScript 表达式
115+ transformed = transformed . replace ( / : c l a s s \s * = \s * " ( [ ^ " ] + ) " / g, ( match , expression ) => {
116+ const escapedExpression = replaceStringLiterals ( expression , escapeClassString )
117+ return `:class="${ escapedExpression } "`
36118 } )
119+
37120 return transformed
38121 } ,
39122 }
0 commit comments