/
index.ts
87 lines (77 loc) · 2.32 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import type { SourceCodeTransformer } from '@unocss/core'
import { escapeRegExp, expandVariantGroup } from '@unocss/core'
export interface CompileClassOptions {
/**
* Trigger string
* @default ':uno:'
*/
trigger?: string
/**
* Prefix for compile class name
* @default 'uno-'
*/
classPrefix?: string
/**
* Hash function
*/
hashFn?: (str: string) => string
/**
* Left unknown classes inside the string
*
* @default true
*/
keepUnknown?: boolean
/**
* The layer name of generated rules
*/
layer?: string
}
export default function transformerCompileClass(options: CompileClassOptions = {}): SourceCodeTransformer {
const {
trigger = ':uno:',
classPrefix = 'uno-',
hashFn = hash,
keepUnknown = true,
} = options
const regex = new RegExp(`(["'\`])${escapeRegExp(trigger)}\\s([^\\1]*?)\\1`, 'g')
return {
name: 'compile-class',
enforce: 'post',
async transform(s, _, { uno }) {
const matches = [...s.original.matchAll(regex)]
if (!matches.length)
return
for (const match of matches) {
let body = expandVariantGroup(match[2].trim())
const start = match.index!
const replacements = []
if (keepUnknown) {
const result = await Promise.all(body.split(/\s+/).filter(Boolean).map(async i => [i, !!await uno.parseToken(i)] as const))
const known = result.filter(([, matched]) => matched).map(([i]) => i)
const unknown = result.filter(([, matched]) => !matched).map(([i]) => i)
replacements.push(...unknown)
body = known.join(' ')
}
if (body) {
const hash = hashFn(body)
const className = `${classPrefix}${hash}`
replacements.unshift(className)
if (options.layer)
uno.config.shortcuts.push([className, body, { layer: options.layer }])
else
uno.config.shortcuts.push([className, body])
}
s.overwrite(start + 1, start + match[0].length - 1, replacements.join(' '))
}
},
}
}
function hash(str: string) {
let i; let l
let hval = 0x811C9DC5
for (i = 0, l = str.length; i < l; i++) {
hval ^= str.charCodeAt(i)
hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24)
}
return (`00000${(hval >>> 0).toString(36)}`).slice(-6)
}