-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
76 lines (65 loc) · 2.19 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
import { Declaration, Root, Rule, AtRule } from 'postcss'
import type { DefaultOptions } from './src/types'
import { defaultOptions } from './src/options'
import {
getTransformValue,
validateFile,
validateMediaQuery,
validateSelector,
validateProp,
validateKeyframesQuery,
} from './src/utils'
const CURRENTIGNORE = 'px-to-clamp-ignore'
const NEXTIGNORE = 'px-to-clamp-ignore-next'
const UNITTOCONVERT = 'px'
const unitReg = new RegExp(
`"[^"]+"|'[^']+'|url\\([^)]+\\)|((?<=^|[^\\w-])-?\\d*\\.?\\d+)${UNITTOCONVERT}\\b`,
'g'
)
const pxToClamp = (opts: Partial<DefaultOptions> = {}) => {
const options: DefaultOptions = Object.assign({}, defaultOptions, opts)
const { replace } = options
let next: Declaration
return {
postcssPlugin: 'postcss-px-to-clamp',
Once(root: Root): void {
if (!validateFile(options, root.source?.input.file?.replace(/\\/g, '/')))
return
root.walkRules((rule: Rule) => {
if (!validateSelector(options, rule.selectors)) return
rule.walkDecls((decl: Declaration) => {
if (decl === next) return
const annotation = decl.prev()
if (annotation?.type === 'comment') {
if (annotation.text === NEXTIGNORE) {
annotation.remove()
return
}
}
const nextAnnotation = decl.next()
if (nextAnnotation?.type === 'comment') {
if (nextAnnotation.text === CURRENTIGNORE) {
nextAnnotation.remove()
return
}
}
if (!~decl.value.indexOf(UNITTOCONVERT)) return
if (!validateProp(options, decl.prop)) return
if (!validateMediaQuery(options, rule.parent as AtRule)) return
if (!validateKeyframesQuery(options, rule.parent as AtRule)) return
if (/^url\(|'|"/.test(decl.value)) return
const value = decl.value.replace(unitReg, (string) =>
getTransformValue(string, decl.prop, options)
)
if (replace) {
decl.value = value
} else {
next = decl.cloneAfter(decl.clone({ value }))
}
})
})
},
}
}
pxToClamp.postcss = true
export = pxToClamp