/
index.ts
94 lines (80 loc) · 2.54 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
88
89
90
91
92
93
94
import type { SourceCodeTransformer } from '@unocss/core'
import { toArray } from '@unocss/core'
export type FilterPattern = ReadonlyArray<string | RegExp> | string | RegExp | null
function createFilter(
include: FilterPattern,
exclude: FilterPattern,
): (id: string) => boolean {
const includePattern = toArray(include || [])
const excludePattern = toArray(exclude || [])
return (id: string) => {
if (excludePattern.some(p => id.match(p)))
return false
return includePattern.some(p => id.match(p))
}
}
export interface TransformerAttributifyJsxOptions {
/**
* the list of attributes to ignore
* @default []
*/
blocklist?: (string | RegExp)[]
/**
* Regex of modules to be included from processing
* @default [/\.[jt]sx$/, /\.mdx$/]
*/
include?: FilterPattern
/**
* Regex of modules to exclude from processing
*
* @default []
*/
exclude?: FilterPattern
}
const elementRE = /<!--[\s\S]*?-->|<(\/?)([a-zA-Z][-.:0-9_a-zA-Z]*)((?:\s+[^>]*?(?:(?:'[^']*')|(?:"[^"]*"))?)*)\s*(\/?)>/gs
const attributeRE = /([a-zA-Z()#][\[?a-zA-Z0-9-_:()#%\]?]*)(?:\s*=\s*((?:'[^']*')|(?:"[^"]*")|\S+))?/g
export default function transformerAttributifyJsx(options: TransformerAttributifyJsxOptions = {}): SourceCodeTransformer {
const {
blocklist = [],
} = options
const isBlocked = (matchedRule: string) => {
for (const blockedRule of blocklist) {
if (blockedRule instanceof RegExp) {
if (blockedRule.test(matchedRule))
return true
}
else if (matchedRule === blockedRule) {
return true
}
}
return false
}
const idFilter = createFilter(
options.include || [/\.[jt]sx$/, /\.mdx$/],
options.exclude || [],
)
return {
name: 'transformer-jsx',
enforce: 'pre',
idFilter,
async transform(code, _, { uno }) {
const tasks: Promise<void>[] = []
for (const item of Array.from(code.original.matchAll(elementRE))) {
for (const attr of item[3].matchAll(attributeRE)) {
const matchedRule = attr[0]
if (matchedRule.includes('=') || isBlocked(matchedRule))
continue
tasks.push(uno.parseToken(matchedRule).then((matched) => {
if (matched) {
const tag = item[2]
const startIdx = (item.index || 0) + (attr.index || 0) + tag.length + 1
const endIdx = startIdx + matchedRule.length
code.overwrite(startIdx, endIdx, `${matchedRule}=""`)
}
}))
}
}
await Promise.all(tasks)
},
}
}