Skip to content

Commit 0a3883f

Browse files
committed
refactor(weapp-tailwindcss): utils
1 parent 69a73a2 commit 0a3883f

File tree

5 files changed

+104
-21
lines changed

5 files changed

+104
-21
lines changed

.changeset/zh-context-refactor-tests.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
"weapp-tailwindcss": minor
33
---
44

5-
重构编译上下文模块,将日志、Tailwind 补丁、模板属性转换、处理器构建拆分为独立单元并补充 100% 覆盖率的单元测试,确保模块化结构更清晰且行为可验证。新增 Lightning CSS 版本的样式处理器,覆盖类名转义、选择器兼容、`:hover` 清理与子选择器替换等关键能力,并提供针对性单测。
5+
重构编译上下文模块,将日志、Tailwind 补丁、模板属性转换、处理器构建拆分为独立单元并补充 100% 覆盖率的单元测试,确保模块化结构更清晰且行为可验证。新增 Lightning CSS 版本的样式处理器,覆盖类名转义、选择器兼容、`:hover` 清理与子选择器替换等关键能力,并提供针对性单测。同步优化工具方法:为文件分组逻辑提供固定分组输出,替换已废弃的 `unescape` Unicode 解码实现,并补充对应的单元测试。
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
export function decodeUnicode(s: string) {
2-
return unescape(s.replaceAll(/\\(u[\dA-Fa-f]{4})/g, '%$1'))
1+
const unicodeEscapeRE = /\\u([\dA-Fa-f]{4})/g
2+
3+
export function decodeUnicode(value: string) {
4+
return value.replace(unicodeEscapeRE, (_match, hex) => {
5+
const codePoint = Number.parseInt(hex, 16)
6+
return Number.isNaN(codePoint) ? _match : String.fromCharCode(codePoint)
7+
})
38
}
49

510
export function decodeUnicode2(input: string) {
611
try {
712
return JSON.parse(`"${input}"`)
813
}
914
catch (_error) {
10-
return input
15+
return decodeUnicode(input)
1116
}
1217
}

packages/weapp-tailwindcss/src/utils/index.ts

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,38 @@ export {
1212
removeExt,
1313
}
1414

15+
export type EntryGroup = 'css' | 'html' | 'js' | 'other'
16+
17+
function classifyEntry(filename: string, options: InternalUserDefinedOptions): EntryGroup {
18+
if (options.cssMatcher(filename)) {
19+
return 'css'
20+
}
21+
if (options.htmlMatcher(filename)) {
22+
return 'html'
23+
}
24+
if (options.jsMatcher(filename) || options.wxsMatcher(filename)) {
25+
return 'js'
26+
}
27+
return 'other'
28+
}
29+
30+
function createEmptyGroups<T>(): Record<EntryGroup, [string, T][]> {
31+
return {
32+
css: [],
33+
html: [],
34+
js: [],
35+
other: [],
36+
}
37+
}
38+
1539
export function getGroupedEntries<T>(entries: [string, T][], options: InternalUserDefinedOptions) {
16-
const { cssMatcher, htmlMatcher, jsMatcher, wxsMatcher } = options
17-
const groupedEntries = groupBy(entries, ([file]) => {
18-
if (cssMatcher(file)) {
19-
return 'css'
20-
}
21-
else if (htmlMatcher(file)) {
22-
return 'html'
23-
}
24-
else if (jsMatcher(file) || wxsMatcher(file)) {
25-
return 'js'
26-
}
27-
else {
28-
return 'other'
29-
}
30-
})
31-
return groupedEntries as Record<'css' | 'html' | 'js' | 'other', [string, T][]>
40+
const groups = createEmptyGroups<T>()
41+
for (const entry of entries) {
42+
const [filename] = entry
43+
const group = classifyEntry(filename, options)
44+
groups[group].push(entry)
45+
}
46+
return groups
3247
}
3348

3449
// const MAX_ASCII_CHAR_CODE = 127

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

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import type { InternalUserDefinedOptions } from '@/types'
12
import path from 'node:path'
2-
import { groupBy, regExpTest } from '@/utils'
3+
import { getGroupedEntries, groupBy, regExpTest } from '@/utils'
34
import { switch2relative } from './util'
45

56
function xxx(fn: any) {
@@ -124,4 +125,46 @@ describe('test util', () => {
124125
],
125126
})
126127
})
128+
129+
describe('getGroupedEntries', () => {
130+
const matchers = {
131+
cssMatcher: (file: string) => file.endsWith('.wxss'),
132+
htmlMatcher: (file: string) => file.endsWith('.wxml'),
133+
jsMatcher: (file: string) => file.endsWith('.js'),
134+
wxsMatcher: (file: string) => file.endsWith('.wxs'),
135+
} as Pick<InternalUserDefinedOptions, 'cssMatcher' | 'htmlMatcher' | 'jsMatcher' | 'wxsMatcher'>
136+
137+
const options = matchers as unknown as InternalUserDefinedOptions
138+
139+
it('groups entries by matcher priority', () => {
140+
const entries: [string, number][] = [
141+
['app.wxss', 1],
142+
['index.wxml', 2],
143+
['logic.js', 3],
144+
['helper.wxs', 4],
145+
['README.md', 5],
146+
]
147+
148+
expect(getGroupedEntries(entries, options)).toEqual({
149+
css: [['app.wxss', 1]],
150+
html: [['index.wxml', 2]],
151+
js: [
152+
['logic.js', 3],
153+
['helper.wxs', 4],
154+
],
155+
other: [['README.md', 5]],
156+
})
157+
})
158+
159+
it('returns empty arrays for missing groups', () => {
160+
const entries: [string, number][] = []
161+
162+
expect(getGroupedEntries(entries, options)).toEqual({
163+
css: [],
164+
html: [],
165+
js: [],
166+
other: [],
167+
})
168+
})
169+
})
127170
})
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { decodeUnicode, decodeUnicode2 } from '@/utils/decode'
3+
4+
describe('decode utils', () => {
5+
it('decodes unicode escape sequences', () => {
6+
expect(decodeUnicode('\\u4f60\\u597d')).toBe('你好')
7+
})
8+
9+
it('leaves invalid escapes untouched', () => {
10+
expect(decodeUnicode('\\uZZZZ-test')).toBe('\\uZZZZ-test')
11+
})
12+
13+
it('decodes mixed escape characters via JSON parser fallback', () => {
14+
expect(decodeUnicode2('\\u4f60\\u597d\\nworld')).toBe('你好\nworld')
15+
})
16+
17+
it('falls back gracefully when JSON parsing fails', () => {
18+
expect(decodeUnicode2('\\u4f60\\u597d\\uZZZZ')).toBe('你好\\uZZZZ')
19+
})
20+
})

0 commit comments

Comments
 (0)