@unocss/transformer-directives 0.62.3 → 0.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.mjs +123 -62
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -11,9 +11,9 @@ npm i -D @unocss/transformer-directives
|
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
+
import transformerDirectives from '@unocss/transformer-directives'
|
|
14
15
|
// uno.config.ts
|
|
15
16
|
import { defineConfig } from 'unocss'
|
|
16
|
-
import transformerDirectives from '@unocss/transformer-directives'
|
|
17
17
|
|
|
18
18
|
export default defineConfig({
|
|
19
19
|
// ...
|
package/dist/index.mjs
CHANGED
|
@@ -1,62 +1,6 @@
|
|
|
1
1
|
import { expandVariantGroup, notNull, regexScopePlaceholder, toArray, cssIdRE } from '@unocss/core';
|
|
2
|
+
import { transformThemeString, hasThemeFn, hasIconFn } from '@unocss/rule-utils';
|
|
2
3
|
import { generate, parse, clone, List, walk } from 'css-tree';
|
|
3
|
-
import { transformThemeString, hasThemeFn } from '@unocss/rule-utils';
|
|
4
|
-
|
|
5
|
-
const screenRuleRE = /(@screen [^{]+)(.+)/g;
|
|
6
|
-
function handleScreen({ code, uno }, node) {
|
|
7
|
-
let breakpointName = "";
|
|
8
|
-
let prefix = "";
|
|
9
|
-
if (node.name === "screen" && node.prelude?.type === "Raw")
|
|
10
|
-
breakpointName = node.prelude.value.trim();
|
|
11
|
-
if (!breakpointName)
|
|
12
|
-
return;
|
|
13
|
-
const match = breakpointName.match(/^(?:(lt|at)-)?(\w+)$/);
|
|
14
|
-
if (match) {
|
|
15
|
-
prefix = match[1];
|
|
16
|
-
breakpointName = match[2];
|
|
17
|
-
}
|
|
18
|
-
const resolveBreakpoints = () => {
|
|
19
|
-
let breakpoints;
|
|
20
|
-
if (uno.userConfig && uno.userConfig.theme)
|
|
21
|
-
breakpoints = uno.userConfig.theme.breakpoints;
|
|
22
|
-
if (!breakpoints)
|
|
23
|
-
breakpoints = uno.config.theme.breakpoints;
|
|
24
|
-
return breakpoints ? Object.entries(breakpoints).sort((a, b) => Number.parseInt(a[1].replace(/[a-z]+/gi, "")) - Number.parseInt(b[1].replace(/[a-z]+/gi, ""))).map(([point, size]) => ({ point, size })) : void 0;
|
|
25
|
-
};
|
|
26
|
-
const variantEntries = (resolveBreakpoints() ?? []).map(({ point, size }, idx) => [point, size, idx]);
|
|
27
|
-
const generateMediaQuery = (breakpointName2, prefix2) => {
|
|
28
|
-
const [, size, idx] = variantEntries.find((i) => i[0] === breakpointName2);
|
|
29
|
-
if (prefix2) {
|
|
30
|
-
if (prefix2 === "lt")
|
|
31
|
-
return `@media (max-width: ${calcMaxWidthBySize(size)})`;
|
|
32
|
-
else if (prefix2 === "at")
|
|
33
|
-
return `@media (min-width: ${size})${variantEntries[idx + 1] ? ` and (max-width: ${calcMaxWidthBySize(variantEntries[idx + 1][1])})` : ""}`;
|
|
34
|
-
else
|
|
35
|
-
throw new Error(`breakpoint variant not supported: ${prefix2}`);
|
|
36
|
-
}
|
|
37
|
-
return `@media (min-width: ${size})`;
|
|
38
|
-
};
|
|
39
|
-
if (!variantEntries.find((i) => i[0] === breakpointName))
|
|
40
|
-
throw new Error(`breakpoint ${breakpointName} not found`);
|
|
41
|
-
const offset = node.loc.start.offset;
|
|
42
|
-
const str = code.original.slice(offset, node.loc.end.offset);
|
|
43
|
-
const matches = Array.from(str.matchAll(screenRuleRE));
|
|
44
|
-
if (!matches.length)
|
|
45
|
-
return;
|
|
46
|
-
for (const match2 of matches) {
|
|
47
|
-
code.overwrite(
|
|
48
|
-
offset + match2.index,
|
|
49
|
-
offset + match2.index + match2[1].length,
|
|
50
|
-
`${generateMediaQuery(breakpointName, prefix)}`
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
function calcMaxWidthBySize(size) {
|
|
55
|
-
const value = size.match(/^-?\d+\.?\d*/)?.[0] || "";
|
|
56
|
-
const unit = size.slice(value.length);
|
|
57
|
-
const maxWidth = Number.parseFloat(value) - 0.1;
|
|
58
|
-
return Number.isNaN(maxWidth) ? size : `${maxWidth}${unit}`;
|
|
59
|
-
}
|
|
60
4
|
|
|
61
5
|
async function handleApply(ctx, node) {
|
|
62
6
|
const { code, uno, options, filename } = ctx;
|
|
@@ -110,7 +54,7 @@ async function parseApply({ code, uno, applyVariable }, node, childNode) {
|
|
|
110
54
|
context: "rule"
|
|
111
55
|
});
|
|
112
56
|
const prelude = clone(node.prelude);
|
|
113
|
-
prelude.children
|
|
57
|
+
prelude.children?.forEach((child) => {
|
|
114
58
|
const selectorListAst = clone(ruleAST.prelude);
|
|
115
59
|
const classSelectors = new List();
|
|
116
60
|
selectorListAst.children.forEach((selectorAst) => {
|
|
@@ -145,7 +89,58 @@ function removeComments(value) {
|
|
|
145
89
|
return value.replace(/(\/\*(?:.|\n)*?\*\/)|(\/\/.*)/g, "");
|
|
146
90
|
}
|
|
147
91
|
|
|
148
|
-
function
|
|
92
|
+
async function transformIconString(uno, icon, color) {
|
|
93
|
+
const presetIcons = uno.userConfig.presets?.flat()?.findLast((i) => i.name === "@unocss/preset-icons");
|
|
94
|
+
if (!presetIcons) {
|
|
95
|
+
console.warn("@unocss/preset-icons not found, icon() directive will be keep as-is");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const {
|
|
99
|
+
scale = 1,
|
|
100
|
+
prefix = "i-",
|
|
101
|
+
collections: customCollections,
|
|
102
|
+
extraProperties = {},
|
|
103
|
+
customizations = {},
|
|
104
|
+
autoInstall = false,
|
|
105
|
+
collectionsNodeResolvePath,
|
|
106
|
+
unit
|
|
107
|
+
} = presetIcons.options;
|
|
108
|
+
const api = presetIcons.api;
|
|
109
|
+
const loaderOptions = {
|
|
110
|
+
addXmlNs: true,
|
|
111
|
+
scale,
|
|
112
|
+
customCollections,
|
|
113
|
+
autoInstall,
|
|
114
|
+
cwd: collectionsNodeResolvePath,
|
|
115
|
+
// avoid warn from @iconify/loader: we'll warn below if not found
|
|
116
|
+
warn: void 0,
|
|
117
|
+
customizations: {
|
|
118
|
+
...customizations,
|
|
119
|
+
additionalProps: { ...extraProperties },
|
|
120
|
+
trimCustomSvg: true,
|
|
121
|
+
async iconCustomizer(collection, icon2, props) {
|
|
122
|
+
await customizations.iconCustomizer?.(collection, icon2, props);
|
|
123
|
+
if (unit) {
|
|
124
|
+
if (!props.width)
|
|
125
|
+
props.width = `${scale}${unit}`;
|
|
126
|
+
if (!props.height)
|
|
127
|
+
props.height = `${scale}${unit}`;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
const loader = await api.createNodeLoader?.() || (async () => void 0);
|
|
133
|
+
for (const p of toArray(prefix)) {
|
|
134
|
+
if (icon.startsWith(p)) {
|
|
135
|
+
icon = icon.slice(p.length);
|
|
136
|
+
const parsed = await api.parseIconWithLoader(icon, loader, loaderOptions);
|
|
137
|
+
if (parsed)
|
|
138
|
+
return `url("data:image/svg+xml;utf8,${color ? api.encodeSvgForCss(parsed.svg).replace(/currentcolor/gi, color) : api.encodeSvgForCss(parsed.svg)}")`;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async function handleFunction({ code, uno, options }, node) {
|
|
149
144
|
const { throwOnMissing = true } = options;
|
|
150
145
|
switch (node.name) {
|
|
151
146
|
case "theme": {
|
|
@@ -155,9 +150,75 @@ function handleFunction({ code, uno, options }, node) {
|
|
|
155
150
|
const value = transformThemeString(themeStr, uno.config.theme, throwOnMissing);
|
|
156
151
|
if (value)
|
|
157
152
|
code.overwrite(node.loc.start.offset, node.loc.end.offset, value);
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
case "icon": {
|
|
156
|
+
const params = node.children.toArray().filter((i) => i.type === "String").map((i) => i.value);
|
|
157
|
+
if (params.length === 0)
|
|
158
|
+
throw new Error("icon() expects at least one argument");
|
|
159
|
+
const value = await transformIconString(uno, ...params);
|
|
160
|
+
if (value)
|
|
161
|
+
code.overwrite(node.loc.start.offset, node.loc.end.offset, value);
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const screenRuleRE = /(@screen [^{]+)(.+)/g;
|
|
168
|
+
function handleScreen({ code, uno }, node) {
|
|
169
|
+
let breakpointName = "";
|
|
170
|
+
let prefix = "";
|
|
171
|
+
if (node.name === "screen" && node.prelude?.type === "Raw")
|
|
172
|
+
breakpointName = node.prelude.value.trim();
|
|
173
|
+
if (!breakpointName)
|
|
174
|
+
return;
|
|
175
|
+
const match = breakpointName.match(/^(?:(lt|at)-)?(\w+)$/);
|
|
176
|
+
if (match) {
|
|
177
|
+
prefix = match[1];
|
|
178
|
+
breakpointName = match[2];
|
|
179
|
+
}
|
|
180
|
+
const resolveBreakpoints = () => {
|
|
181
|
+
let breakpoints;
|
|
182
|
+
if (uno.userConfig && uno.userConfig.theme)
|
|
183
|
+
breakpoints = uno.userConfig.theme.breakpoints;
|
|
184
|
+
if (!breakpoints)
|
|
185
|
+
breakpoints = uno.config.theme.breakpoints;
|
|
186
|
+
return breakpoints ? Object.entries(breakpoints).sort((a, b) => Number.parseInt(a[1].replace(/[a-z]+/gi, "")) - Number.parseInt(b[1].replace(/[a-z]+/gi, ""))).map(([point, size]) => ({ point, size })) : void 0;
|
|
187
|
+
};
|
|
188
|
+
const variantEntries = (resolveBreakpoints() ?? []).map(({ point, size }, idx) => [point, size, idx]);
|
|
189
|
+
const generateMediaQuery = (breakpointName2, prefix2) => {
|
|
190
|
+
const [, size, idx] = variantEntries.find((i) => i[0] === breakpointName2);
|
|
191
|
+
if (prefix2) {
|
|
192
|
+
if (prefix2 === "lt")
|
|
193
|
+
return `@media (max-width: ${calcMaxWidthBySize(size)})`;
|
|
194
|
+
else if (prefix2 === "at")
|
|
195
|
+
return `@media (min-width: ${size})${variantEntries[idx + 1] ? ` and (max-width: ${calcMaxWidthBySize(variantEntries[idx + 1][1])})` : ""}`;
|
|
196
|
+
else
|
|
197
|
+
throw new Error(`breakpoint variant not supported: ${prefix2}`);
|
|
158
198
|
}
|
|
199
|
+
return `@media (min-width: ${size})`;
|
|
200
|
+
};
|
|
201
|
+
if (!variantEntries.find((i) => i[0] === breakpointName))
|
|
202
|
+
throw new Error(`breakpoint ${breakpointName} not found`);
|
|
203
|
+
const offset = node.loc.start.offset;
|
|
204
|
+
const str = code.original.slice(offset, node.loc.end.offset);
|
|
205
|
+
const matches = Array.from(str.matchAll(screenRuleRE));
|
|
206
|
+
if (!matches.length)
|
|
207
|
+
return;
|
|
208
|
+
for (const match2 of matches) {
|
|
209
|
+
code.overwrite(
|
|
210
|
+
offset + match2.index,
|
|
211
|
+
offset + match2.index + match2[1].length,
|
|
212
|
+
`${generateMediaQuery(breakpointName, prefix)}`
|
|
213
|
+
);
|
|
159
214
|
}
|
|
160
215
|
}
|
|
216
|
+
function calcMaxWidthBySize(size) {
|
|
217
|
+
const value = size.match(/^-?\d+\.?\d*/)?.[0] || "";
|
|
218
|
+
const unit = size.slice(value.length);
|
|
219
|
+
const maxWidth = Number.parseFloat(value) - 0.1;
|
|
220
|
+
return Number.isNaN(maxWidth) ? size : `${maxWidth}${unit}`;
|
|
221
|
+
}
|
|
161
222
|
|
|
162
223
|
async function transformDirectives(code, uno, options, filename, originalCode, offset) {
|
|
163
224
|
let { applyVariable } = options;
|
|
@@ -171,8 +232,8 @@ async function transformDirectives(code, uno, options, filename, originalCode, o
|
|
|
171
232
|
const parseCode = originalCode || code.original;
|
|
172
233
|
const hasApply = parseCode.includes("@apply") || applyVariable.some((s) => parseCode.includes(s));
|
|
173
234
|
const hasScreen = parseCode.includes("@screen");
|
|
174
|
-
const
|
|
175
|
-
if (!hasApply && !
|
|
235
|
+
const hasFn = hasThemeFn(parseCode) || hasIconFn(parseCode);
|
|
236
|
+
if (!hasApply && !hasFn && !hasScreen)
|
|
176
237
|
return;
|
|
177
238
|
const ast = parse(parseCode, {
|
|
178
239
|
parseCustomProperty: true,
|
|
@@ -196,7 +257,7 @@ async function transformDirectives(code, uno, options, filename, originalCode, o
|
|
|
196
257
|
if (hasScreen && node.type === "Atrule")
|
|
197
258
|
handleScreen(ctx, node);
|
|
198
259
|
if (node.type === "Function")
|
|
199
|
-
handleFunction(ctx, node);
|
|
260
|
+
await handleFunction(ctx, node);
|
|
200
261
|
if (hasApply && node.type === "Rule")
|
|
201
262
|
await handleApply(ctx, node);
|
|
202
263
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unocss/transformer-directives",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.63.0",
|
|
5
5
|
"description": "UnoCSS transformer for `@apply` directive",
|
|
6
6
|
"author": "hannoeru <me@hanlee.co>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"dist"
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"css-tree": "^
|
|
36
|
-
"@unocss/core": "0.
|
|
37
|
-
"@unocss/rule-utils": "0.
|
|
35
|
+
"css-tree": "^3.0.0",
|
|
36
|
+
"@unocss/core": "0.63.0",
|
|
37
|
+
"@unocss/rule-utils": "0.63.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"magic-string": "^0.30.11"
|