Skip to content

Commit 1788e26

Browse files
committed
fix: 修复 splitCode 在压缩模板字符串中保留转义空白导致类名匹配遗漏的问题,保证 mp-alipay 等产物的类名替换正常工作。
1 parent 6f2fbfa commit 1788e26

File tree

5 files changed

+75
-2
lines changed

5 files changed

+75
-2
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@weapp-tailwindcss/shared': patch
3+
weapp-tailwindcss: patch
4+
---
5+
6+
修复 splitCode 在压缩模板字符串中保留转义空白导致类名匹配遗漏的问题,保证 mp-alipay 等产物的类名替换正常工作。

packages/shared/src/extractors/split.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ export function isValidSelector(selector = ''): selector is string {
99
// 可选实现:export const splitCode = (code: string) => [...new Set(code.split(/\\?[\s'"`;={}]+/g))].filter(isValidSelector)
1010

1111
export function splitCode(code: string, allowDoubleQuotes = false) {
12+
// 把压缩产物中的转义空白字符(\n \r \t)先还原成空格,避免被粘连到类名上
13+
const normalized = code.includes('\\') ? code.replace(/\\[nrt]/g, ' ') : code
14+
1215
// 参数 onlyWhiteSpace?: boolean
1316
// const regex = onlyWhiteSpace ? /[\s]+/ : /"|[\s]+/
1417
// 默认使用 /\s+/
1518
// 用于处理 Vue 的静态节点
1619
// 示例:|class="
1720
const splitter = allowDoubleQuotes ? /\s+/ : /\s+|"/
18-
return code.split(splitter).filter(element => isValidSelector(element))
21+
return normalized.split(splitter).filter(element => isValidSelector(element))
1922
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { isValidSelector, splitCode } from '@/extractors'
3+
4+
describe('splitCode extractor', () => {
5+
it('splits on whitespace and drops empty selectors', () => {
6+
expect(splitCode(' foo bar ')).toEqual(['foo', 'bar'])
7+
expect(splitCode('" "')).toEqual([])
8+
})
9+
10+
it('normalises escaped whitespace in minified template literals', () => {
11+
const code = 'border-b-[rgba(0,0,0,0.1)]\\ntext-base\\tfont-bold\\rtext-sm'
12+
expect(splitCode(code)).toEqual([
13+
'border-b-[rgba(0,0,0,0.1)]',
14+
'text-base',
15+
'font-bold',
16+
'text-sm',
17+
])
18+
})
19+
20+
it('controls whether double quotes are treated as splitters', () => {
21+
const snippet = 'class="foo bar" data-test="baz"'
22+
expect(splitCode(snippet)).toEqual(['class=', 'foo', 'bar', 'data-test=', 'baz'])
23+
expect(splitCode(snippet, true)).toEqual(['class="foo', 'bar"', 'data-test="baz"'])
24+
})
25+
})
26+
27+
describe('isValidSelector', () => {
28+
it('accepts selectors containing unicode and alphanumeric characters', () => {
29+
expect(isValidSelector('边界')).toBe(true)
30+
expect(isValidSelector('text-sm')).toBe(true)
31+
})
32+
33+
it('rejects empty or punctuation-only inputs', () => {
34+
expect(isValidSelector('')).toBe(false)
35+
expect(isValidSelector(' ')).toBe(false)
36+
expect(isValidSelector('""')).toBe(false)
37+
})
38+
})

packages/shared/test/index.test.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expect, it } from 'vitest'
2-
import { defuOverrideArray, groupBy, isMap, isRegexp, regExpTest, removeExt } from '@/index'
2+
import { defuOverrideArray, groupBy, isMap, isRegexp, noop, regExpTest, removeExt } from '@/index'
33

44
describe('shared utils', () => {
55
it('isRegexp correctly detects regular expressions', () => {
@@ -45,6 +45,8 @@ describe('shared utils', () => {
4545
expect(removeExt('archive.tar.gz')).toBe('archive.tar')
4646
expect(removeExt('noext')).toBe('noext')
4747
expect(removeExt('')).toBe('')
48+
expect(removeExt('file.')).toBe('file')
49+
expect(removeExt('.hidden/file')).toBe('.hidden/file')
4850
})
4951

5052
it('defuOverrideArray replaces array values instead of merging them', () => {
@@ -70,5 +72,26 @@ describe('shared utils', () => {
7072
expect(withFallback.include).toEqual(['**/*.wxml', '**/*.wxss'])
7173
expect(withFallback.nested.matchers).toEqual(['**/*.js'])
7274
expect(withFallback.flag).toBe(true)
75+
76+
const mixedTypes = defuOverrideArray({ include: '**/*.swan' } as any, defaults)
77+
expect(mixedTypes.include).toBe('**/*.swan')
78+
})
79+
80+
it('groupBy validates inputs', () => {
81+
expect(() => groupBy(null as unknown as string[], () => 'a')).toThrowError(/expected an array/i)
82+
expect(() => groupBy([], null as any)).toThrowError(/expected a function/i)
83+
})
84+
85+
it('regExpTest resets regex lastIndex and ignores unsupported entries', () => {
86+
const regex = /foo/g
87+
regex.lastIndex = 12
88+
expect(regExpTest([regex], 'foo')).toBe(true)
89+
expect(regex.lastIndex).not.toBe(12)
90+
91+
expect(regExpTest([123 as any, {} as any], 'foo')).toBe(false)
92+
})
93+
94+
it('noop returns undefined without side effects', () => {
95+
expect(noop()).toBeUndefined()
7396
})
7497
})

packages/weapp-tailwindcss/test/extractors.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ describe('extractorSplit', () => {
3636
const res = extract()
3737
expect(res.length).toBe(6)
3838

39+
code = 'border-b-[rgba(0,0,0,0.1)]\\ntext-base\\tfont-bold'
40+
expect(extract()).toEqual(['border-b-[rgba(0,0,0,0.1)]', 'text-base', 'font-bold'])
41+
3942
code
4043
= '<view class="p-[20px] -mt-2 mb-[-20px]">p-[20px] -mt-2 mb-[-20px] margin的jit 不能这么写 -m-[20px]</view><view class="space-y-[1.6rem]"><view class="w-[300rpx] text-black text-opacity-[0.19]">w-[300rpx] text-black text-opacity-[0.19]</view><view class="min-w-[300rpx] max-h-[100px] text-[20px] leading-[0.9]">min-w-[300rpx] max-h-[100px] text-[20px] leading-[0.9]</view><view class="max-w-[300rpx] min-h-[100px] text-[#dddddd]">max-w-[300rpx] min-h-[100px] text-[#dddddd]</view><view class="flex items-center justify-center h-[100px] w-[100px] rounded-[40px] bg-[#123456] bg-opacity-[0.54] text-[#ffffff]"> Hello</view><view class="border-[10px] border-[#098765] border-solid border-opacity-[0.44]">border-[10px] border-[#098765] border-solid border-opacity-[0.44]</view><view class="grid grid-cols-3 divide-x-[10px] divide-[#010101] divide-solid"><view>1</view><view>2</view><view>3</view></view><view class="w-32 py-2 rounded-md font-semibold text-white bg-pink-500 ring-4 ring-pink-300"> Default </view></view><view class="test">test</view>'
4144
const res0 = extract()

0 commit comments

Comments
 (0)