@weapp-tailwindcss/postcss 2.2.1-next.2 → 2.2.1-next.3
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/dist/compat/color-mix.d.ts +10 -1
- package/dist/compat/tailwindcss-v4.d.ts +5 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +261 -37
- package/dist/index.mjs +261 -38
- package/package.json +5 -2
|
@@ -2,4 +2,13 @@ export interface DynamicColorMixAlphaProtection {
|
|
|
2
2
|
css: string;
|
|
3
3
|
restore: (css: string) => string;
|
|
4
4
|
}
|
|
5
|
-
export
|
|
5
|
+
export interface DynamicColorMixAlphaProtectionOptions {
|
|
6
|
+
customPropertyValues?: ReadonlyMap<string, string> | undefined;
|
|
7
|
+
}
|
|
8
|
+
export interface ModernColorValueNormalization {
|
|
9
|
+
value: string;
|
|
10
|
+
changed: boolean;
|
|
11
|
+
hasUnsupported: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function normalizeModernColorValue(value: string, customPropertyValues?: ReadonlyMap<string, string>): ModernColorValueNormalization;
|
|
14
|
+
export declare function protectDynamicColorMixAlpha(css: string, options?: DynamicColorMixAlphaProtectionOptions): DynamicColorMixAlphaProtection;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import type { AtRule,
|
|
1
|
+
import type { AtRule, Root, Rule } from 'postcss';
|
|
2
|
+
import { Declaration } from 'postcss';
|
|
2
3
|
export declare function isTailwindcssV4(options?: {
|
|
3
4
|
majorVersion?: number;
|
|
4
5
|
}): boolean;
|
|
5
6
|
export declare function testIfRootHostForV4(node: Rule): boolean;
|
|
6
7
|
export declare const cssVarsV4Nodes: Declaration[];
|
|
8
|
+
export declare function collectUsedTailwindcssV4Variables(root: Root): Set<string>;
|
|
9
|
+
export declare function usesTailwindcssV4ContentVariable(root: Root): boolean;
|
|
10
|
+
export declare function createUsedCssVarsV4Nodes(usedProps: ReadonlySet<string>): Declaration[];
|
|
7
11
|
export declare function isTailwindcssV4ModernCheck(atRule: AtRule): boolean;
|
|
8
12
|
export declare function isTailwindcssV4LinearGradientSupports(atRule: AtRule): boolean;
|
|
9
13
|
export declare function isTailwindcssV4DisplayP3Supports(atRule: AtRule): boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { type DynamicColorMixAlphaProtection, protectDynamicColorMixAlpha } from './compat/color-mix';
|
|
1
|
+
export { type DynamicColorMixAlphaProtection, type DynamicColorMixAlphaProtectionOptions, type ModernColorValueNormalization, normalizeModernColorValue, protectDynamicColorMixAlpha, } from './compat/color-mix';
|
|
2
2
|
export * from './handler';
|
|
3
3
|
export { default as postcssHtmlTransform, type IOptions as PostcssHtmlTransformOptions } from './html-transform';
|
|
4
4
|
export { createStylePipeline, type PipelineNodeContext, type PipelineNodeCursor, type PipelineStage, type ResolvedPipelineNode, type StyleProcessingPipeline, } from './pipeline';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_html_transform = require("./html-transform-DuSRw6IH.js");
|
|
3
3
|
require("./types.js");
|
|
4
|
+
let _csstools_css_color_parser = require("@csstools/css-color-parser");
|
|
5
|
+
let _csstools_css_parser_algorithms = require("@csstools/css-parser-algorithms");
|
|
6
|
+
let _csstools_css_tokenizer = require("@csstools/css-tokenizer");
|
|
4
7
|
let postcss = require("postcss");
|
|
5
8
|
postcss = require_html_transform.__toESM(postcss);
|
|
6
9
|
let postcss_value_parser = require("postcss-value-parser");
|
|
@@ -24,9 +27,19 @@ postcss_rule_unit_converter = require_html_transform.__toESM(postcss_rule_unit_c
|
|
|
24
27
|
let _weapp_core_escape = require("@weapp-core/escape");
|
|
25
28
|
//#region src/compat/color-mix.ts
|
|
26
29
|
const COLOR_MIX_NAME = "color-mix";
|
|
27
|
-
const
|
|
30
|
+
const MODERN_COLOR_FUNCTION_NAMES = new Set([
|
|
31
|
+
"oklch",
|
|
32
|
+
"oklab",
|
|
33
|
+
"lch",
|
|
34
|
+
"lab"
|
|
35
|
+
]);
|
|
36
|
+
const PLACEHOLDER_PREFIX = "__weapp_tw_color_mix_";
|
|
28
37
|
const DYNAMIC_ALPHA_RE = /\b(?:var|env)\(|--[\w-]+\b/;
|
|
29
38
|
const INTERNAL_TAILWIND_ALPHA_RE = /var\(\s*--tw-[^)]+-alpha\s*\)/;
|
|
39
|
+
const TRANSPARENT_COLOR_RE = /^transparent$/i;
|
|
40
|
+
const CURRENT_COLOR_RE = /^currentcolor$/i;
|
|
41
|
+
const CSS_WIDE_KEYWORD_RE = /^(?:inherit|initial|unset|revert|revert-layer)$/i;
|
|
42
|
+
const CUSTOM_PROPERTY_RE = /^--[\w-]+$/;
|
|
30
43
|
function splitArguments(nodes) {
|
|
31
44
|
const args = [];
|
|
32
45
|
let current = [];
|
|
@@ -57,15 +70,147 @@ function splitStopSegments(nodes) {
|
|
|
57
70
|
if (current.length > 0) segments.push(current);
|
|
58
71
|
return segments;
|
|
59
72
|
}
|
|
60
|
-
function
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return
|
|
73
|
+
function trimNodes$1(nodes) {
|
|
74
|
+
let start = 0;
|
|
75
|
+
let end = nodes.length;
|
|
76
|
+
while (start < end && nodes[start]?.type === "space") start += 1;
|
|
77
|
+
while (end > start && nodes[end - 1]?.type === "space") end -= 1;
|
|
78
|
+
return nodes.slice(start, end);
|
|
79
|
+
}
|
|
80
|
+
function getParsedColorData(colorSource) {
|
|
81
|
+
try {
|
|
82
|
+
return (0, _csstools_css_color_parser.color)((0, _csstools_css_parser_algorithms.parseComponentValue)((0, _csstools_css_tokenizer.tokenize)({ css: colorSource })));
|
|
83
|
+
} catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function parseAlphaValue(alphaSource) {
|
|
88
|
+
const parsed = Number.parseFloat(alphaSource);
|
|
89
|
+
if (Number.isFinite(parsed)) return alphaSource.trim().endsWith("%") ? parsed / 100 : parsed;
|
|
90
|
+
}
|
|
91
|
+
function resolveVarColor(colorSource, customPropertyValues, depth = 0) {
|
|
92
|
+
if (depth > 5) return;
|
|
93
|
+
const parsed = (0, postcss_value_parser.default)(colorSource.trim());
|
|
94
|
+
const node = parsed.nodes.length === 1 ? parsed.nodes[0] : void 0;
|
|
95
|
+
if (node?.type !== "function" || node.value.toLowerCase() !== "var") return;
|
|
96
|
+
const args = splitArguments(node.nodes);
|
|
97
|
+
const propertyName = postcss_value_parser.default.stringify(trimNodes$1(args[0] ?? [])).trim();
|
|
98
|
+
if (!CUSTOM_PROPERTY_RE.test(propertyName)) return;
|
|
99
|
+
const resolved = customPropertyValues.get(propertyName);
|
|
100
|
+
if (!resolved) {
|
|
101
|
+
const fallback = args[1] ? postcss_value_parser.default.stringify(trimNodes$1(args[1])).trim() : void 0;
|
|
102
|
+
return fallback ? resolveColorData(fallback, customPropertyValues, depth + 1) : void 0;
|
|
103
|
+
}
|
|
104
|
+
return resolveColorData(resolved, customPropertyValues, depth + 1);
|
|
105
|
+
}
|
|
106
|
+
function resolveColorData(colorSource, customPropertyValues, depth = 0) {
|
|
107
|
+
if (typeof colorSource !== "string") return;
|
|
108
|
+
const trimmed = colorSource.trim();
|
|
109
|
+
if (TRANSPARENT_COLOR_RE.test(trimmed)) return getParsedColorData(trimmed) || void 0;
|
|
110
|
+
if (CURRENT_COLOR_RE.test(trimmed) || CSS_WIDE_KEYWORD_RE.test(trimmed)) return;
|
|
111
|
+
const resolvedVar = resolveVarColor(trimmed, customPropertyValues, depth);
|
|
112
|
+
if (resolvedVar) return resolvedVar;
|
|
113
|
+
return getParsedColorData(trimmed) || void 0;
|
|
114
|
+
}
|
|
115
|
+
function normalizeColorFunctionName(colorSource, alpha, customPropertyValues) {
|
|
116
|
+
const resolvedColor = resolveColorData(colorSource, customPropertyValues);
|
|
117
|
+
if (!resolvedColor) return;
|
|
118
|
+
resolvedColor.alpha = alpha;
|
|
119
|
+
return (0, _csstools_css_color_parser.serializeRGB)(resolvedColor).toString();
|
|
120
|
+
}
|
|
121
|
+
function normalizeStandaloneColorFunction(colorSource) {
|
|
122
|
+
const resolvedColor = getParsedColorData(colorSource);
|
|
123
|
+
return resolvedColor ? (0, _csstools_css_color_parser.serializeRGB)(resolvedColor).toString() : void 0;
|
|
124
|
+
}
|
|
125
|
+
function isDisplayP3ColorFunction(colorSource) {
|
|
126
|
+
return /^color\(\s*display-p3\b/i.test(colorSource.trim());
|
|
127
|
+
}
|
|
128
|
+
function hasUnsupportedModernColorFunction(value) {
|
|
129
|
+
const parsed = (0, postcss_value_parser.default)(value);
|
|
130
|
+
let hasUnsupported = false;
|
|
131
|
+
parsed.walk((node) => {
|
|
132
|
+
if (node.type !== "function") return;
|
|
133
|
+
const name = node.value.toLowerCase();
|
|
134
|
+
if (name === COLOR_MIX_NAME || MODERN_COLOR_FUNCTION_NAMES.has(name) || name === "color" && isDisplayP3ColorFunction(postcss_value_parser.default.stringify(node))) {
|
|
135
|
+
hasUnsupported = true;
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
return hasUnsupported;
|
|
140
|
+
}
|
|
141
|
+
function normalizeModernColorValue(value, customPropertyValues = /* @__PURE__ */ new Map()) {
|
|
142
|
+
if (!hasUnsupportedModernColorFunction(value)) return {
|
|
143
|
+
value,
|
|
144
|
+
changed: false,
|
|
145
|
+
hasUnsupported: false
|
|
146
|
+
};
|
|
147
|
+
const parsed = (0, postcss_value_parser.default)(value);
|
|
148
|
+
let changed = false;
|
|
149
|
+
parsed.walk((node) => {
|
|
150
|
+
if (node.type !== "function") return;
|
|
151
|
+
const name = node.value.toLowerCase();
|
|
152
|
+
const source = postcss_value_parser.default.stringify(node);
|
|
153
|
+
let normalized;
|
|
154
|
+
if (MODERN_COLOR_FUNCTION_NAMES.has(name) || name === "color" && isDisplayP3ColorFunction(source)) normalized = normalizeStandaloneColorFunction(source);
|
|
155
|
+
else if (name === COLOR_MIX_NAME) normalized = tryResolveColorMix(node, customPropertyValues)?.value;
|
|
156
|
+
if (!normalized) return;
|
|
157
|
+
const mutableNode = node;
|
|
158
|
+
mutableNode.type = "word";
|
|
159
|
+
mutableNode.value = normalized;
|
|
160
|
+
delete mutableNode.nodes;
|
|
161
|
+
changed = true;
|
|
162
|
+
});
|
|
163
|
+
const nextValue = changed ? parsed.toString() : value;
|
|
164
|
+
return {
|
|
165
|
+
value: nextValue,
|
|
166
|
+
changed,
|
|
167
|
+
hasUnsupported: hasUnsupportedModernColorFunction(nextValue)
|
|
168
|
+
};
|
|
66
169
|
}
|
|
67
|
-
function
|
|
68
|
-
|
|
170
|
+
function createRgbaWithAlpha(colorSource, alphaSource, customPropertyValues) {
|
|
171
|
+
const resolvedColor = resolveColorData(colorSource, customPropertyValues);
|
|
172
|
+
if (!resolvedColor) return;
|
|
173
|
+
const [red, green, blue] = resolvedColor.channels.map((channel) => Math.round(Math.min(1, Math.max(0, channel)) * 255));
|
|
174
|
+
const alpha = alphaSource.trim();
|
|
175
|
+
return `rgba(${red}, ${green}, ${blue}, ${CUSTOM_PROPERTY_RE.test(alpha) ? `var(${alpha})` : alpha})`;
|
|
176
|
+
}
|
|
177
|
+
function tryResolveColorMix(node, customPropertyValues) {
|
|
178
|
+
const args = splitArguments(node.nodes);
|
|
179
|
+
if (args.length < 3) return;
|
|
180
|
+
const colorStopNodes = splitStopSegments(args[1] ?? []);
|
|
181
|
+
if (colorStopNodes.length < 2) return;
|
|
182
|
+
const colorNodes = trimNodes$1(colorStopNodes[0] ?? []);
|
|
183
|
+
const alphaNodes = trimNodes$1(colorStopNodes[1] ?? []);
|
|
184
|
+
const trailingNodes = trimNodes$1(args[2] ?? []);
|
|
185
|
+
if (!colorNodes.length || !alphaNodes.length || postcss_value_parser.default.stringify(trailingNodes).trim().toLowerCase() !== "transparent") return;
|
|
186
|
+
const colorSource = postcss_value_parser.default.stringify(colorNodes).trim();
|
|
187
|
+
const alphaSource = postcss_value_parser.default.stringify(alphaNodes).trim();
|
|
188
|
+
if (!colorSource || !alphaSource || INTERNAL_TAILWIND_ALPHA_RE.test(alphaSource)) return;
|
|
189
|
+
if (CURRENT_COLOR_RE.test(colorSource)) return {
|
|
190
|
+
value: colorSource,
|
|
191
|
+
deferred: false
|
|
192
|
+
};
|
|
193
|
+
if (DYNAMIC_ALPHA_RE.test(alphaSource)) {
|
|
194
|
+
const normalized = createRgbaWithAlpha(colorSource, alphaSource, customPropertyValues);
|
|
195
|
+
return normalized ? {
|
|
196
|
+
value: normalized,
|
|
197
|
+
deferred: true
|
|
198
|
+
} : {
|
|
199
|
+
value: colorSource,
|
|
200
|
+
deferred: true
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
const alpha = parseAlphaValue(alphaSource);
|
|
204
|
+
if (alpha === void 0) return;
|
|
205
|
+
const normalized = normalizeColorFunctionName(colorSource, alpha, customPropertyValues);
|
|
206
|
+
if (normalized) return {
|
|
207
|
+
value: normalized,
|
|
208
|
+
deferred: false
|
|
209
|
+
};
|
|
210
|
+
return {
|
|
211
|
+
value: colorSource,
|
|
212
|
+
deferred: false
|
|
213
|
+
};
|
|
69
214
|
}
|
|
70
215
|
function createPlaceholder(index) {
|
|
71
216
|
return `${PLACEHOLDER_PREFIX}${index}__`;
|
|
@@ -76,40 +221,54 @@ function unwrapProtectedSupports(cssRoot) {
|
|
|
76
221
|
atRule.replaceWith(atRule.nodes);
|
|
77
222
|
});
|
|
78
223
|
}
|
|
79
|
-
function protectDynamicColorMixAlpha(css) {
|
|
224
|
+
function protectDynamicColorMixAlpha(css, options = {}) {
|
|
80
225
|
if (!css.includes(COLOR_MIX_NAME)) return {
|
|
81
226
|
css,
|
|
82
227
|
restore: (value) => value
|
|
83
228
|
};
|
|
84
229
|
const replacements = /* @__PURE__ */ new Map();
|
|
85
230
|
const root = postcss.default.parse(css);
|
|
231
|
+
const customPropertyValues = new Map(options.customPropertyValues);
|
|
232
|
+
let changed = false;
|
|
233
|
+
root.walkDecls((decl) => {
|
|
234
|
+
if (decl.prop.startsWith("--") && !decl.value.includes(COLOR_MIX_NAME)) customPropertyValues.set(decl.prop, decl.value.trim());
|
|
235
|
+
});
|
|
86
236
|
root.walkDecls((decl) => {
|
|
87
237
|
if (!decl.value.includes(COLOR_MIX_NAME)) return;
|
|
88
238
|
const parsed = (0, postcss_value_parser.default)(decl.value);
|
|
89
239
|
let mutated = false;
|
|
90
240
|
parsed.walk((node) => {
|
|
91
241
|
if (node.type !== "function" || node.value.toLowerCase() !== COLOR_MIX_NAME) return;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
242
|
+
const resolved = tryResolveColorMix(node, customPropertyValues);
|
|
243
|
+
if (resolved) {
|
|
244
|
+
if (resolved.deferred) {
|
|
245
|
+
const placeholder = createPlaceholder(replacements.size);
|
|
246
|
+
replacements.set(placeholder, resolved.value);
|
|
247
|
+
const mutableNode = node;
|
|
248
|
+
mutableNode.type = "word";
|
|
249
|
+
mutableNode.value = placeholder;
|
|
250
|
+
delete mutableNode.nodes;
|
|
251
|
+
mutated = true;
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const mutableNode = node;
|
|
255
|
+
mutableNode.type = "word";
|
|
256
|
+
mutableNode.value = resolved.value;
|
|
257
|
+
delete mutableNode.nodes;
|
|
258
|
+
mutated = true;
|
|
259
|
+
}
|
|
100
260
|
});
|
|
101
|
-
if (mutated)
|
|
261
|
+
if (mutated) {
|
|
262
|
+
decl.value = parsed.toString();
|
|
263
|
+
changed = true;
|
|
264
|
+
}
|
|
102
265
|
});
|
|
103
|
-
if (replacements.size
|
|
104
|
-
css,
|
|
105
|
-
restore: (value) => value
|
|
106
|
-
};
|
|
107
|
-
unwrapProtectedSupports(root);
|
|
266
|
+
if (replacements.size > 0) unwrapProtectedSupports(root);
|
|
108
267
|
return {
|
|
109
|
-
css: root.toString(),
|
|
268
|
+
css: changed ? root.toString() : css,
|
|
110
269
|
restore(value) {
|
|
111
270
|
let restored = value;
|
|
112
|
-
for (const [placeholder,
|
|
271
|
+
for (const [placeholder, replacement] of replacements) restored = restored.split(placeholder).join(replacement);
|
|
113
272
|
return restored;
|
|
114
273
|
}
|
|
115
274
|
};
|
|
@@ -141,7 +300,7 @@ function isBaseCarrierSelector(selector) {
|
|
|
141
300
|
function isBaseCarrierRule(rule) {
|
|
142
301
|
return Array.isArray(rule.selectors) && rule.selectors.length > 0 && rule.selectors.every(isBaseCarrierSelector);
|
|
143
302
|
}
|
|
144
|
-
function hasClassSelector(rule) {
|
|
303
|
+
function hasClassSelector$1(rule) {
|
|
145
304
|
return Array.isArray(rule.selectors) && rule.selectors.some((selector) => CLASS_SELECTOR_RE.test(selector));
|
|
146
305
|
}
|
|
147
306
|
function collectRequiredTwVars(value) {
|
|
@@ -171,7 +330,7 @@ function extractUniAppXBaseDefaults(result) {
|
|
|
171
330
|
function injectUniAppXBaseDefaults(result, defaults) {
|
|
172
331
|
if (defaults.size === 0) return;
|
|
173
332
|
result.root.walkRules((rule) => {
|
|
174
|
-
if (!hasClassSelector(rule)) return;
|
|
333
|
+
if (!hasClassSelector$1(rule)) return;
|
|
175
334
|
const declaredProps = /* @__PURE__ */ new Set();
|
|
176
335
|
const requiredProps = /* @__PURE__ */ new Set();
|
|
177
336
|
rule.walkDecls((decl) => {
|
|
@@ -821,6 +980,8 @@ const nodes = [
|
|
|
821
980
|
property("--tw-scroll-snap-strictness", "proximity", "*"),
|
|
822
981
|
property("--tw-space-x-reverse", "0"),
|
|
823
982
|
property("--tw-space-y-reverse", "0"),
|
|
983
|
+
property("--tw-scrollbar-thumb", "#0000", "<color>"),
|
|
984
|
+
property("--tw-scrollbar-track", "#0000", "<color>"),
|
|
824
985
|
property("--tw-border-style", "solid"),
|
|
825
986
|
property("--tw-divide-x-reverse", "0"),
|
|
826
987
|
property("--tw-divide-y-reverse", "0"),
|
|
@@ -945,13 +1106,46 @@ const DISPLAY_P3_VALUE_RE = /color\(\s*display-p3\b/i;
|
|
|
945
1106
|
const COLOR_GAMUT_P3_RE = /\(\s*color-gamut\s*:\s*p3\s*\)/i;
|
|
946
1107
|
const RADIUS_VALUE_RE = /\b([+-]?(?:\d+(?:\.\d+)?|\.\d+)(?:e[+-]?\d+)?)\s*(r?px)\b/gi;
|
|
947
1108
|
const SCIENTIFIC_NOTATION_RE = /e/i;
|
|
1109
|
+
const TW_VAR_FUNCTION_RE = /var\(\s*(--tw-[\w-]+)\b/g;
|
|
1110
|
+
const TW_CONTENT_VAR_RE = /var\(\s*--tw-content\b/;
|
|
948
1111
|
function isTailwindcssV4(options) {
|
|
949
1112
|
return options?.majorVersion === 4;
|
|
950
1113
|
}
|
|
951
1114
|
function testIfRootHostForV4(node) {
|
|
952
1115
|
return node.type === "rule" && node.selector.includes(":root") && node.selector.includes(":host");
|
|
953
1116
|
}
|
|
954
|
-
|
|
1117
|
+
createCssVarNodes(nodes);
|
|
1118
|
+
function collectUsedTailwindcssV4Variables(root) {
|
|
1119
|
+
const props = /* @__PURE__ */ new Set();
|
|
1120
|
+
root.walkDecls((decl) => {
|
|
1121
|
+
if (decl.prop.startsWith("--tw-")) props.add(decl.prop);
|
|
1122
|
+
TW_VAR_FUNCTION_RE.lastIndex = 0;
|
|
1123
|
+
let match = TW_VAR_FUNCTION_RE.exec(decl.value);
|
|
1124
|
+
while (match !== null) {
|
|
1125
|
+
const prop = match[1];
|
|
1126
|
+
if (prop) props.add(prop);
|
|
1127
|
+
match = TW_VAR_FUNCTION_RE.exec(decl.value);
|
|
1128
|
+
}
|
|
1129
|
+
});
|
|
1130
|
+
root.walkAtRules("property", (atRule) => {
|
|
1131
|
+
const prop = atRule.params.trim();
|
|
1132
|
+
if (prop.startsWith("--tw-")) props.add(prop);
|
|
1133
|
+
});
|
|
1134
|
+
return props;
|
|
1135
|
+
}
|
|
1136
|
+
function usesTailwindcssV4ContentVariable(root) {
|
|
1137
|
+
let used = false;
|
|
1138
|
+
root.walkDecls((decl) => {
|
|
1139
|
+
if (TW_CONTENT_VAR_RE.test(decl.value)) used = true;
|
|
1140
|
+
});
|
|
1141
|
+
return used;
|
|
1142
|
+
}
|
|
1143
|
+
function createUsedCssVarsV4Nodes(usedProps) {
|
|
1144
|
+
return nodes.filter((def) => usedProps.has(def.prop)).map((def) => new postcss.Declaration({
|
|
1145
|
+
prop: def.prop,
|
|
1146
|
+
value: def.value
|
|
1147
|
+
}));
|
|
1148
|
+
}
|
|
955
1149
|
function isTailwindcssV4ModernCheck(atRule) {
|
|
956
1150
|
return atRule.name === "supports" && [
|
|
957
1151
|
MODERN_CHECK_WEBKIT_HYPHENS_RE,
|
|
@@ -2091,6 +2285,20 @@ function makePseudoVarRule() {
|
|
|
2091
2285
|
}));
|
|
2092
2286
|
return pseudoVarRule;
|
|
2093
2287
|
}
|
|
2288
|
+
function isEmptyContentInitDeclaration(decl) {
|
|
2289
|
+
return decl.prop === "--tw-content" && (decl.value === "\"\"" || decl.value === "''");
|
|
2290
|
+
}
|
|
2291
|
+
function removeTailwindV4EmptyContentInit(node) {
|
|
2292
|
+
node.walkDecls((decl) => {
|
|
2293
|
+
if (isEmptyContentInitDeclaration(decl)) decl.remove();
|
|
2294
|
+
});
|
|
2295
|
+
}
|
|
2296
|
+
function hasClassSelector(node) {
|
|
2297
|
+
return node.selectors.some((selector) => selector.includes("."));
|
|
2298
|
+
}
|
|
2299
|
+
function isRootThemeScopeRule(node) {
|
|
2300
|
+
return node.selectors.length > 0 && node.selectors.every((selector) => selector === ":root" || selector === ":host" || DEFAULT_ROOT_SELECTORS.includes(selector));
|
|
2301
|
+
}
|
|
2094
2302
|
function remakeCssVarSelector(selectors, options) {
|
|
2095
2303
|
const { cssPreflightRange, cssSelectorReplacement } = options;
|
|
2096
2304
|
if (cssPreflightRange === "all" && !selectors.includes(":not(not)")) selectors.push(":not(not)");
|
|
@@ -2112,6 +2320,7 @@ function resolveUniAppXVariableScopeSelectors(options) {
|
|
|
2112
2320
|
function commonChunkPreflight(node, options) {
|
|
2113
2321
|
const { ctx, cssInjectPreflight, injectAdditionalCssVarScope } = options;
|
|
2114
2322
|
const uniAppXEnabled = isUniAppXEnabled(options);
|
|
2323
|
+
const isTailwindcss4 = isTailwindcssV4(options);
|
|
2115
2324
|
const rootOption = options.cssSelectorReplacement?.root;
|
|
2116
2325
|
const rootSelectors = rootOption === false || rootOption === void 0 ? [] : Array.isArray(rootOption) ? rootOption.filter(Boolean) : [rootOption];
|
|
2117
2326
|
const hasHostSelector = node.selectors.some((selector) => selector.includes(":host"));
|
|
@@ -2121,31 +2330,33 @@ function commonChunkPreflight(node, options) {
|
|
|
2121
2330
|
phase: "pre",
|
|
2122
2331
|
reason: "append-host-selector"
|
|
2123
2332
|
});
|
|
2333
|
+
if (isTailwindcss4 && !usesTailwindcssV4ContentVariable(node.root()) && (!hasClassSelector(node) || isRootThemeScopeRule(node))) removeTailwindV4EmptyContentInit(node);
|
|
2124
2334
|
if (testIfVariablesScope(node) || uniAppXEnabled && node.selectors.includes("*") && hasTwVars(node, 2)) {
|
|
2125
2335
|
ctx?.markVariablesScope(node);
|
|
2126
2336
|
assignRuleSelectors(node, uniAppXEnabled ? resolveUniAppXVariableScopeSelectors(options) : remakeCssVarSelector(node.selectors, options), {
|
|
2127
2337
|
phase: "pre",
|
|
2128
2338
|
reason: "rewrite-variable-scope"
|
|
2129
2339
|
});
|
|
2130
|
-
if (!uniAppXEnabled) node.before(makePseudoVarRule());
|
|
2340
|
+
if (!uniAppXEnabled && !isTailwindcss4) node.before(makePseudoVarRule());
|
|
2131
2341
|
if (typeof cssInjectPreflight === "function") node.append(...cssInjectPreflight());
|
|
2132
2342
|
}
|
|
2133
|
-
const isTailwindcss4 = isTailwindcssV4(options);
|
|
2134
2343
|
if (injectAdditionalCssVarScope && (isTailwindcss4 ? testIfRootHostForV4(node) : testIfTwBackdrop(node))) {
|
|
2344
|
+
const nodes = isTailwindcss4 ? createUsedCssVarsV4Nodes(collectUsedTailwindcssV4Variables(node.root())) : cssVarsV3Nodes;
|
|
2345
|
+
if (nodes.length === 0) return;
|
|
2135
2346
|
const syntheticRule = new postcss.Rule({
|
|
2136
2347
|
selectors: uniAppXEnabled ? resolveUniAppXVariableScopeSelectors(options) : [
|
|
2137
2348
|
"*",
|
|
2138
2349
|
"::after",
|
|
2139
2350
|
"::before"
|
|
2140
2351
|
],
|
|
2141
|
-
nodes
|
|
2352
|
+
nodes
|
|
2142
2353
|
});
|
|
2143
2354
|
if (!uniAppXEnabled) assignRuleSelectors(syntheticRule, remakeCssVarSelector(syntheticRule.selectors, options), {
|
|
2144
2355
|
phase: "pre",
|
|
2145
2356
|
reason: "rewrite-synthetic-variable-scope"
|
|
2146
2357
|
});
|
|
2147
2358
|
node.before(syntheticRule);
|
|
2148
|
-
if (!uniAppXEnabled) node.before(makePseudoVarRule());
|
|
2359
|
+
if (!uniAppXEnabled && !isTailwindcss4) node.before(makePseudoVarRule());
|
|
2149
2360
|
if (typeof cssInjectPreflight === "function") syntheticRule.append(...cssInjectPreflight());
|
|
2150
2361
|
}
|
|
2151
2362
|
}
|
|
@@ -2480,19 +2691,31 @@ function createStyleHandler(options) {
|
|
|
2480
2691
|
const hasUserPlugins = Boolean(cachedOptions.postcssOptions?.plugins && (Array.isArray(cachedOptions.postcssOptions.plugins) ? cachedOptions.postcssOptions.plugins.length > 0 : typeof cachedOptions.postcssOptions.plugins === "object" && Object.keys(cachedOptions.postcssOptions.plugins).length > 0));
|
|
2481
2692
|
const handler = ((rawSource, opt) => {
|
|
2482
2693
|
const resolvedOptions = resolver.resolve(opt);
|
|
2694
|
+
const protectedColorMix = resolvedOptions.majorVersion === 4 ? protectDynamicColorMixAlpha(rawSource) : void 0;
|
|
2695
|
+
const source = protectedColorMix?.css ?? rawSource;
|
|
2483
2696
|
let signal;
|
|
2484
2697
|
if (!hasUserPlugins) try {
|
|
2485
|
-
signal = probeFeatures(
|
|
2698
|
+
signal = probeFeatures(source);
|
|
2486
2699
|
} catch {
|
|
2487
2700
|
signal = void 0;
|
|
2488
2701
|
}
|
|
2489
|
-
const cacheKey = `${getOptionsFingerprint(resolvedOptions)}|${signal ? signalToCacheKey(signal) : ""}|${simpleHash(
|
|
2702
|
+
const cacheKey = `${getOptionsFingerprint(resolvedOptions)}|${signal ? signalToCacheKey(signal) : ""}|${simpleHash(source)}`;
|
|
2490
2703
|
const cachedResult = resultCache.get(cacheKey);
|
|
2491
2704
|
if (cachedResult) return Promise.resolve(cachedResult);
|
|
2492
2705
|
const processor = processorCache.getProcessor(resolvedOptions, signal);
|
|
2493
2706
|
const processOptions = processorCache.getProcessOptions(resolvedOptions);
|
|
2494
|
-
return processor.process(
|
|
2495
|
-
|
|
2707
|
+
return processor.process(source, processOptions).async().then((result) => {
|
|
2708
|
+
let finalResult = applyUniAppXUvueCompatibility(applyUniAppXBaseCompatibility(result, resolvedOptions), resolvedOptions);
|
|
2709
|
+
if (protectedColorMix) {
|
|
2710
|
+
const restoredCss = protectedColorMix.restore(finalResult.css);
|
|
2711
|
+
if (restoredCss !== finalResult.css) {
|
|
2712
|
+
const nextResult = finalResult.root.clone().toResult(finalResult.opts);
|
|
2713
|
+
nextResult.css = restoredCss;
|
|
2714
|
+
nextResult.root = postcss.default.parse(restoredCss, finalResult.opts);
|
|
2715
|
+
nextResult.messages.push(...finalResult.messages);
|
|
2716
|
+
finalResult = nextResult;
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2496
2719
|
resultCache.set(cacheKey, finalResult);
|
|
2497
2720
|
return finalResult;
|
|
2498
2721
|
});
|
|
@@ -2509,5 +2732,6 @@ exports.createInjectPreflight = createInjectPreflight;
|
|
|
2509
2732
|
exports.createStyleHandler = createStyleHandler;
|
|
2510
2733
|
exports.createStylePipeline = createStylePipeline;
|
|
2511
2734
|
exports.internalCssSelectorReplacer = internalCssSelectorReplacer;
|
|
2735
|
+
exports.normalizeModernColorValue = normalizeModernColorValue;
|
|
2512
2736
|
exports.postcssHtmlTransform = require_html_transform.postcssHtmlTransform;
|
|
2513
2737
|
exports.protectDynamicColorMixAlpha = protectDynamicColorMixAlpha;
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import postcssHtmlTransform from "./html-transform.mjs";
|
|
2
2
|
import "./types.mjs";
|
|
3
|
+
import { color, serializeRGB } from "@csstools/css-color-parser";
|
|
4
|
+
import { parseComponentValue } from "@csstools/css-parser-algorithms";
|
|
5
|
+
import { tokenize } from "@csstools/css-tokenizer";
|
|
3
6
|
import postcss, { Declaration, Rule } from "postcss";
|
|
4
7
|
import valueParser from "postcss-value-parser";
|
|
5
8
|
import { defu, defuOverrideArray, regExpTest } from "@weapp-tailwindcss/shared";
|
|
@@ -14,9 +17,19 @@ import postcssUnitConverter, { presets } from "postcss-rule-unit-converter";
|
|
|
14
17
|
import { MappingChars2String, escape } from "@weapp-core/escape";
|
|
15
18
|
//#region src/compat/color-mix.ts
|
|
16
19
|
const COLOR_MIX_NAME = "color-mix";
|
|
17
|
-
const
|
|
20
|
+
const MODERN_COLOR_FUNCTION_NAMES = new Set([
|
|
21
|
+
"oklch",
|
|
22
|
+
"oklab",
|
|
23
|
+
"lch",
|
|
24
|
+
"lab"
|
|
25
|
+
]);
|
|
26
|
+
const PLACEHOLDER_PREFIX = "__weapp_tw_color_mix_";
|
|
18
27
|
const DYNAMIC_ALPHA_RE = /\b(?:var|env)\(|--[\w-]+\b/;
|
|
19
28
|
const INTERNAL_TAILWIND_ALPHA_RE = /var\(\s*--tw-[^)]+-alpha\s*\)/;
|
|
29
|
+
const TRANSPARENT_COLOR_RE = /^transparent$/i;
|
|
30
|
+
const CURRENT_COLOR_RE = /^currentcolor$/i;
|
|
31
|
+
const CSS_WIDE_KEYWORD_RE = /^(?:inherit|initial|unset|revert|revert-layer)$/i;
|
|
32
|
+
const CUSTOM_PROPERTY_RE = /^--[\w-]+$/;
|
|
20
33
|
function splitArguments(nodes) {
|
|
21
34
|
const args = [];
|
|
22
35
|
let current = [];
|
|
@@ -47,15 +60,147 @@ function splitStopSegments(nodes) {
|
|
|
47
60
|
if (current.length > 0) segments.push(current);
|
|
48
61
|
return segments;
|
|
49
62
|
}
|
|
50
|
-
function
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return
|
|
63
|
+
function trimNodes$1(nodes) {
|
|
64
|
+
let start = 0;
|
|
65
|
+
let end = nodes.length;
|
|
66
|
+
while (start < end && nodes[start]?.type === "space") start += 1;
|
|
67
|
+
while (end > start && nodes[end - 1]?.type === "space") end -= 1;
|
|
68
|
+
return nodes.slice(start, end);
|
|
69
|
+
}
|
|
70
|
+
function getParsedColorData(colorSource) {
|
|
71
|
+
try {
|
|
72
|
+
return color(parseComponentValue(tokenize({ css: colorSource })));
|
|
73
|
+
} catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function parseAlphaValue(alphaSource) {
|
|
78
|
+
const parsed = Number.parseFloat(alphaSource);
|
|
79
|
+
if (Number.isFinite(parsed)) return alphaSource.trim().endsWith("%") ? parsed / 100 : parsed;
|
|
80
|
+
}
|
|
81
|
+
function resolveVarColor(colorSource, customPropertyValues, depth = 0) {
|
|
82
|
+
if (depth > 5) return;
|
|
83
|
+
const parsed = valueParser(colorSource.trim());
|
|
84
|
+
const node = parsed.nodes.length === 1 ? parsed.nodes[0] : void 0;
|
|
85
|
+
if (node?.type !== "function" || node.value.toLowerCase() !== "var") return;
|
|
86
|
+
const args = splitArguments(node.nodes);
|
|
87
|
+
const propertyName = valueParser.stringify(trimNodes$1(args[0] ?? [])).trim();
|
|
88
|
+
if (!CUSTOM_PROPERTY_RE.test(propertyName)) return;
|
|
89
|
+
const resolved = customPropertyValues.get(propertyName);
|
|
90
|
+
if (!resolved) {
|
|
91
|
+
const fallback = args[1] ? valueParser.stringify(trimNodes$1(args[1])).trim() : void 0;
|
|
92
|
+
return fallback ? resolveColorData(fallback, customPropertyValues, depth + 1) : void 0;
|
|
93
|
+
}
|
|
94
|
+
return resolveColorData(resolved, customPropertyValues, depth + 1);
|
|
95
|
+
}
|
|
96
|
+
function resolveColorData(colorSource, customPropertyValues, depth = 0) {
|
|
97
|
+
if (typeof colorSource !== "string") return;
|
|
98
|
+
const trimmed = colorSource.trim();
|
|
99
|
+
if (TRANSPARENT_COLOR_RE.test(trimmed)) return getParsedColorData(trimmed) || void 0;
|
|
100
|
+
if (CURRENT_COLOR_RE.test(trimmed) || CSS_WIDE_KEYWORD_RE.test(trimmed)) return;
|
|
101
|
+
const resolvedVar = resolveVarColor(trimmed, customPropertyValues, depth);
|
|
102
|
+
if (resolvedVar) return resolvedVar;
|
|
103
|
+
return getParsedColorData(trimmed) || void 0;
|
|
104
|
+
}
|
|
105
|
+
function normalizeColorFunctionName(colorSource, alpha, customPropertyValues) {
|
|
106
|
+
const resolvedColor = resolveColorData(colorSource, customPropertyValues);
|
|
107
|
+
if (!resolvedColor) return;
|
|
108
|
+
resolvedColor.alpha = alpha;
|
|
109
|
+
return serializeRGB(resolvedColor).toString();
|
|
110
|
+
}
|
|
111
|
+
function normalizeStandaloneColorFunction(colorSource) {
|
|
112
|
+
const resolvedColor = getParsedColorData(colorSource);
|
|
113
|
+
return resolvedColor ? serializeRGB(resolvedColor).toString() : void 0;
|
|
114
|
+
}
|
|
115
|
+
function isDisplayP3ColorFunction(colorSource) {
|
|
116
|
+
return /^color\(\s*display-p3\b/i.test(colorSource.trim());
|
|
117
|
+
}
|
|
118
|
+
function hasUnsupportedModernColorFunction(value) {
|
|
119
|
+
const parsed = valueParser(value);
|
|
120
|
+
let hasUnsupported = false;
|
|
121
|
+
parsed.walk((node) => {
|
|
122
|
+
if (node.type !== "function") return;
|
|
123
|
+
const name = node.value.toLowerCase();
|
|
124
|
+
if (name === COLOR_MIX_NAME || MODERN_COLOR_FUNCTION_NAMES.has(name) || name === "color" && isDisplayP3ColorFunction(valueParser.stringify(node))) {
|
|
125
|
+
hasUnsupported = true;
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return hasUnsupported;
|
|
130
|
+
}
|
|
131
|
+
function normalizeModernColorValue(value, customPropertyValues = /* @__PURE__ */ new Map()) {
|
|
132
|
+
if (!hasUnsupportedModernColorFunction(value)) return {
|
|
133
|
+
value,
|
|
134
|
+
changed: false,
|
|
135
|
+
hasUnsupported: false
|
|
136
|
+
};
|
|
137
|
+
const parsed = valueParser(value);
|
|
138
|
+
let changed = false;
|
|
139
|
+
parsed.walk((node) => {
|
|
140
|
+
if (node.type !== "function") return;
|
|
141
|
+
const name = node.value.toLowerCase();
|
|
142
|
+
const source = valueParser.stringify(node);
|
|
143
|
+
let normalized;
|
|
144
|
+
if (MODERN_COLOR_FUNCTION_NAMES.has(name) || name === "color" && isDisplayP3ColorFunction(source)) normalized = normalizeStandaloneColorFunction(source);
|
|
145
|
+
else if (name === COLOR_MIX_NAME) normalized = tryResolveColorMix(node, customPropertyValues)?.value;
|
|
146
|
+
if (!normalized) return;
|
|
147
|
+
const mutableNode = node;
|
|
148
|
+
mutableNode.type = "word";
|
|
149
|
+
mutableNode.value = normalized;
|
|
150
|
+
delete mutableNode.nodes;
|
|
151
|
+
changed = true;
|
|
152
|
+
});
|
|
153
|
+
const nextValue = changed ? parsed.toString() : value;
|
|
154
|
+
return {
|
|
155
|
+
value: nextValue,
|
|
156
|
+
changed,
|
|
157
|
+
hasUnsupported: hasUnsupportedModernColorFunction(nextValue)
|
|
158
|
+
};
|
|
56
159
|
}
|
|
57
|
-
function
|
|
58
|
-
|
|
160
|
+
function createRgbaWithAlpha(colorSource, alphaSource, customPropertyValues) {
|
|
161
|
+
const resolvedColor = resolveColorData(colorSource, customPropertyValues);
|
|
162
|
+
if (!resolvedColor) return;
|
|
163
|
+
const [red, green, blue] = resolvedColor.channels.map((channel) => Math.round(Math.min(1, Math.max(0, channel)) * 255));
|
|
164
|
+
const alpha = alphaSource.trim();
|
|
165
|
+
return `rgba(${red}, ${green}, ${blue}, ${CUSTOM_PROPERTY_RE.test(alpha) ? `var(${alpha})` : alpha})`;
|
|
166
|
+
}
|
|
167
|
+
function tryResolveColorMix(node, customPropertyValues) {
|
|
168
|
+
const args = splitArguments(node.nodes);
|
|
169
|
+
if (args.length < 3) return;
|
|
170
|
+
const colorStopNodes = splitStopSegments(args[1] ?? []);
|
|
171
|
+
if (colorStopNodes.length < 2) return;
|
|
172
|
+
const colorNodes = trimNodes$1(colorStopNodes[0] ?? []);
|
|
173
|
+
const alphaNodes = trimNodes$1(colorStopNodes[1] ?? []);
|
|
174
|
+
const trailingNodes = trimNodes$1(args[2] ?? []);
|
|
175
|
+
if (!colorNodes.length || !alphaNodes.length || valueParser.stringify(trailingNodes).trim().toLowerCase() !== "transparent") return;
|
|
176
|
+
const colorSource = valueParser.stringify(colorNodes).trim();
|
|
177
|
+
const alphaSource = valueParser.stringify(alphaNodes).trim();
|
|
178
|
+
if (!colorSource || !alphaSource || INTERNAL_TAILWIND_ALPHA_RE.test(alphaSource)) return;
|
|
179
|
+
if (CURRENT_COLOR_RE.test(colorSource)) return {
|
|
180
|
+
value: colorSource,
|
|
181
|
+
deferred: false
|
|
182
|
+
};
|
|
183
|
+
if (DYNAMIC_ALPHA_RE.test(alphaSource)) {
|
|
184
|
+
const normalized = createRgbaWithAlpha(colorSource, alphaSource, customPropertyValues);
|
|
185
|
+
return normalized ? {
|
|
186
|
+
value: normalized,
|
|
187
|
+
deferred: true
|
|
188
|
+
} : {
|
|
189
|
+
value: colorSource,
|
|
190
|
+
deferred: true
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
const alpha = parseAlphaValue(alphaSource);
|
|
194
|
+
if (alpha === void 0) return;
|
|
195
|
+
const normalized = normalizeColorFunctionName(colorSource, alpha, customPropertyValues);
|
|
196
|
+
if (normalized) return {
|
|
197
|
+
value: normalized,
|
|
198
|
+
deferred: false
|
|
199
|
+
};
|
|
200
|
+
return {
|
|
201
|
+
value: colorSource,
|
|
202
|
+
deferred: false
|
|
203
|
+
};
|
|
59
204
|
}
|
|
60
205
|
function createPlaceholder(index) {
|
|
61
206
|
return `${PLACEHOLDER_PREFIX}${index}__`;
|
|
@@ -66,40 +211,54 @@ function unwrapProtectedSupports(cssRoot) {
|
|
|
66
211
|
atRule.replaceWith(atRule.nodes);
|
|
67
212
|
});
|
|
68
213
|
}
|
|
69
|
-
function protectDynamicColorMixAlpha(css) {
|
|
214
|
+
function protectDynamicColorMixAlpha(css, options = {}) {
|
|
70
215
|
if (!css.includes(COLOR_MIX_NAME)) return {
|
|
71
216
|
css,
|
|
72
217
|
restore: (value) => value
|
|
73
218
|
};
|
|
74
219
|
const replacements = /* @__PURE__ */ new Map();
|
|
75
220
|
const root = postcss.parse(css);
|
|
221
|
+
const customPropertyValues = new Map(options.customPropertyValues);
|
|
222
|
+
let changed = false;
|
|
223
|
+
root.walkDecls((decl) => {
|
|
224
|
+
if (decl.prop.startsWith("--") && !decl.value.includes(COLOR_MIX_NAME)) customPropertyValues.set(decl.prop, decl.value.trim());
|
|
225
|
+
});
|
|
76
226
|
root.walkDecls((decl) => {
|
|
77
227
|
if (!decl.value.includes(COLOR_MIX_NAME)) return;
|
|
78
228
|
const parsed = valueParser(decl.value);
|
|
79
229
|
let mutated = false;
|
|
80
230
|
parsed.walk((node) => {
|
|
81
231
|
if (node.type !== "function" || node.value.toLowerCase() !== COLOR_MIX_NAME) return;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
232
|
+
const resolved = tryResolveColorMix(node, customPropertyValues);
|
|
233
|
+
if (resolved) {
|
|
234
|
+
if (resolved.deferred) {
|
|
235
|
+
const placeholder = createPlaceholder(replacements.size);
|
|
236
|
+
replacements.set(placeholder, resolved.value);
|
|
237
|
+
const mutableNode = node;
|
|
238
|
+
mutableNode.type = "word";
|
|
239
|
+
mutableNode.value = placeholder;
|
|
240
|
+
delete mutableNode.nodes;
|
|
241
|
+
mutated = true;
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
const mutableNode = node;
|
|
245
|
+
mutableNode.type = "word";
|
|
246
|
+
mutableNode.value = resolved.value;
|
|
247
|
+
delete mutableNode.nodes;
|
|
248
|
+
mutated = true;
|
|
249
|
+
}
|
|
90
250
|
});
|
|
91
|
-
if (mutated)
|
|
251
|
+
if (mutated) {
|
|
252
|
+
decl.value = parsed.toString();
|
|
253
|
+
changed = true;
|
|
254
|
+
}
|
|
92
255
|
});
|
|
93
|
-
if (replacements.size
|
|
94
|
-
css,
|
|
95
|
-
restore: (value) => value
|
|
96
|
-
};
|
|
97
|
-
unwrapProtectedSupports(root);
|
|
256
|
+
if (replacements.size > 0) unwrapProtectedSupports(root);
|
|
98
257
|
return {
|
|
99
|
-
css: root.toString(),
|
|
258
|
+
css: changed ? root.toString() : css,
|
|
100
259
|
restore(value) {
|
|
101
260
|
let restored = value;
|
|
102
|
-
for (const [placeholder,
|
|
261
|
+
for (const [placeholder, replacement] of replacements) restored = restored.split(placeholder).join(replacement);
|
|
103
262
|
return restored;
|
|
104
263
|
}
|
|
105
264
|
};
|
|
@@ -131,7 +290,7 @@ function isBaseCarrierSelector(selector) {
|
|
|
131
290
|
function isBaseCarrierRule(rule) {
|
|
132
291
|
return Array.isArray(rule.selectors) && rule.selectors.length > 0 && rule.selectors.every(isBaseCarrierSelector);
|
|
133
292
|
}
|
|
134
|
-
function hasClassSelector(rule) {
|
|
293
|
+
function hasClassSelector$1(rule) {
|
|
135
294
|
return Array.isArray(rule.selectors) && rule.selectors.some((selector) => CLASS_SELECTOR_RE.test(selector));
|
|
136
295
|
}
|
|
137
296
|
function collectRequiredTwVars(value) {
|
|
@@ -161,7 +320,7 @@ function extractUniAppXBaseDefaults(result) {
|
|
|
161
320
|
function injectUniAppXBaseDefaults(result, defaults) {
|
|
162
321
|
if (defaults.size === 0) return;
|
|
163
322
|
result.root.walkRules((rule) => {
|
|
164
|
-
if (!hasClassSelector(rule)) return;
|
|
323
|
+
if (!hasClassSelector$1(rule)) return;
|
|
165
324
|
const declaredProps = /* @__PURE__ */ new Set();
|
|
166
325
|
const requiredProps = /* @__PURE__ */ new Set();
|
|
167
326
|
rule.walkDecls((decl) => {
|
|
@@ -811,6 +970,8 @@ const nodes = [
|
|
|
811
970
|
property("--tw-scroll-snap-strictness", "proximity", "*"),
|
|
812
971
|
property("--tw-space-x-reverse", "0"),
|
|
813
972
|
property("--tw-space-y-reverse", "0"),
|
|
973
|
+
property("--tw-scrollbar-thumb", "#0000", "<color>"),
|
|
974
|
+
property("--tw-scrollbar-track", "#0000", "<color>"),
|
|
814
975
|
property("--tw-border-style", "solid"),
|
|
815
976
|
property("--tw-divide-x-reverse", "0"),
|
|
816
977
|
property("--tw-divide-y-reverse", "0"),
|
|
@@ -935,13 +1096,46 @@ const DISPLAY_P3_VALUE_RE = /color\(\s*display-p3\b/i;
|
|
|
935
1096
|
const COLOR_GAMUT_P3_RE = /\(\s*color-gamut\s*:\s*p3\s*\)/i;
|
|
936
1097
|
const RADIUS_VALUE_RE = /\b([+-]?(?:\d+(?:\.\d+)?|\.\d+)(?:e[+-]?\d+)?)\s*(r?px)\b/gi;
|
|
937
1098
|
const SCIENTIFIC_NOTATION_RE = /e/i;
|
|
1099
|
+
const TW_VAR_FUNCTION_RE = /var\(\s*(--tw-[\w-]+)\b/g;
|
|
1100
|
+
const TW_CONTENT_VAR_RE = /var\(\s*--tw-content\b/;
|
|
938
1101
|
function isTailwindcssV4(options) {
|
|
939
1102
|
return options?.majorVersion === 4;
|
|
940
1103
|
}
|
|
941
1104
|
function testIfRootHostForV4(node) {
|
|
942
1105
|
return node.type === "rule" && node.selector.includes(":root") && node.selector.includes(":host");
|
|
943
1106
|
}
|
|
944
|
-
|
|
1107
|
+
createCssVarNodes(nodes);
|
|
1108
|
+
function collectUsedTailwindcssV4Variables(root) {
|
|
1109
|
+
const props = /* @__PURE__ */ new Set();
|
|
1110
|
+
root.walkDecls((decl) => {
|
|
1111
|
+
if (decl.prop.startsWith("--tw-")) props.add(decl.prop);
|
|
1112
|
+
TW_VAR_FUNCTION_RE.lastIndex = 0;
|
|
1113
|
+
let match = TW_VAR_FUNCTION_RE.exec(decl.value);
|
|
1114
|
+
while (match !== null) {
|
|
1115
|
+
const prop = match[1];
|
|
1116
|
+
if (prop) props.add(prop);
|
|
1117
|
+
match = TW_VAR_FUNCTION_RE.exec(decl.value);
|
|
1118
|
+
}
|
|
1119
|
+
});
|
|
1120
|
+
root.walkAtRules("property", (atRule) => {
|
|
1121
|
+
const prop = atRule.params.trim();
|
|
1122
|
+
if (prop.startsWith("--tw-")) props.add(prop);
|
|
1123
|
+
});
|
|
1124
|
+
return props;
|
|
1125
|
+
}
|
|
1126
|
+
function usesTailwindcssV4ContentVariable(root) {
|
|
1127
|
+
let used = false;
|
|
1128
|
+
root.walkDecls((decl) => {
|
|
1129
|
+
if (TW_CONTENT_VAR_RE.test(decl.value)) used = true;
|
|
1130
|
+
});
|
|
1131
|
+
return used;
|
|
1132
|
+
}
|
|
1133
|
+
function createUsedCssVarsV4Nodes(usedProps) {
|
|
1134
|
+
return nodes.filter((def) => usedProps.has(def.prop)).map((def) => new Declaration({
|
|
1135
|
+
prop: def.prop,
|
|
1136
|
+
value: def.value
|
|
1137
|
+
}));
|
|
1138
|
+
}
|
|
945
1139
|
function isTailwindcssV4ModernCheck(atRule) {
|
|
946
1140
|
return atRule.name === "supports" && [
|
|
947
1141
|
MODERN_CHECK_WEBKIT_HYPHENS_RE,
|
|
@@ -2081,6 +2275,20 @@ function makePseudoVarRule() {
|
|
|
2081
2275
|
}));
|
|
2082
2276
|
return pseudoVarRule;
|
|
2083
2277
|
}
|
|
2278
|
+
function isEmptyContentInitDeclaration(decl) {
|
|
2279
|
+
return decl.prop === "--tw-content" && (decl.value === "\"\"" || decl.value === "''");
|
|
2280
|
+
}
|
|
2281
|
+
function removeTailwindV4EmptyContentInit(node) {
|
|
2282
|
+
node.walkDecls((decl) => {
|
|
2283
|
+
if (isEmptyContentInitDeclaration(decl)) decl.remove();
|
|
2284
|
+
});
|
|
2285
|
+
}
|
|
2286
|
+
function hasClassSelector(node) {
|
|
2287
|
+
return node.selectors.some((selector) => selector.includes("."));
|
|
2288
|
+
}
|
|
2289
|
+
function isRootThemeScopeRule(node) {
|
|
2290
|
+
return node.selectors.length > 0 && node.selectors.every((selector) => selector === ":root" || selector === ":host" || DEFAULT_ROOT_SELECTORS.includes(selector));
|
|
2291
|
+
}
|
|
2084
2292
|
function remakeCssVarSelector(selectors, options) {
|
|
2085
2293
|
const { cssPreflightRange, cssSelectorReplacement } = options;
|
|
2086
2294
|
if (cssPreflightRange === "all" && !selectors.includes(":not(not)")) selectors.push(":not(not)");
|
|
@@ -2102,6 +2310,7 @@ function resolveUniAppXVariableScopeSelectors(options) {
|
|
|
2102
2310
|
function commonChunkPreflight(node, options) {
|
|
2103
2311
|
const { ctx, cssInjectPreflight, injectAdditionalCssVarScope } = options;
|
|
2104
2312
|
const uniAppXEnabled = isUniAppXEnabled(options);
|
|
2313
|
+
const isTailwindcss4 = isTailwindcssV4(options);
|
|
2105
2314
|
const rootOption = options.cssSelectorReplacement?.root;
|
|
2106
2315
|
const rootSelectors = rootOption === false || rootOption === void 0 ? [] : Array.isArray(rootOption) ? rootOption.filter(Boolean) : [rootOption];
|
|
2107
2316
|
const hasHostSelector = node.selectors.some((selector) => selector.includes(":host"));
|
|
@@ -2111,31 +2320,33 @@ function commonChunkPreflight(node, options) {
|
|
|
2111
2320
|
phase: "pre",
|
|
2112
2321
|
reason: "append-host-selector"
|
|
2113
2322
|
});
|
|
2323
|
+
if (isTailwindcss4 && !usesTailwindcssV4ContentVariable(node.root()) && (!hasClassSelector(node) || isRootThemeScopeRule(node))) removeTailwindV4EmptyContentInit(node);
|
|
2114
2324
|
if (testIfVariablesScope(node) || uniAppXEnabled && node.selectors.includes("*") && hasTwVars(node, 2)) {
|
|
2115
2325
|
ctx?.markVariablesScope(node);
|
|
2116
2326
|
assignRuleSelectors(node, uniAppXEnabled ? resolveUniAppXVariableScopeSelectors(options) : remakeCssVarSelector(node.selectors, options), {
|
|
2117
2327
|
phase: "pre",
|
|
2118
2328
|
reason: "rewrite-variable-scope"
|
|
2119
2329
|
});
|
|
2120
|
-
if (!uniAppXEnabled) node.before(makePseudoVarRule());
|
|
2330
|
+
if (!uniAppXEnabled && !isTailwindcss4) node.before(makePseudoVarRule());
|
|
2121
2331
|
if (typeof cssInjectPreflight === "function") node.append(...cssInjectPreflight());
|
|
2122
2332
|
}
|
|
2123
|
-
const isTailwindcss4 = isTailwindcssV4(options);
|
|
2124
2333
|
if (injectAdditionalCssVarScope && (isTailwindcss4 ? testIfRootHostForV4(node) : testIfTwBackdrop(node))) {
|
|
2334
|
+
const nodes = isTailwindcss4 ? createUsedCssVarsV4Nodes(collectUsedTailwindcssV4Variables(node.root())) : cssVarsV3Nodes;
|
|
2335
|
+
if (nodes.length === 0) return;
|
|
2125
2336
|
const syntheticRule = new Rule({
|
|
2126
2337
|
selectors: uniAppXEnabled ? resolveUniAppXVariableScopeSelectors(options) : [
|
|
2127
2338
|
"*",
|
|
2128
2339
|
"::after",
|
|
2129
2340
|
"::before"
|
|
2130
2341
|
],
|
|
2131
|
-
nodes
|
|
2342
|
+
nodes
|
|
2132
2343
|
});
|
|
2133
2344
|
if (!uniAppXEnabled) assignRuleSelectors(syntheticRule, remakeCssVarSelector(syntheticRule.selectors, options), {
|
|
2134
2345
|
phase: "pre",
|
|
2135
2346
|
reason: "rewrite-synthetic-variable-scope"
|
|
2136
2347
|
});
|
|
2137
2348
|
node.before(syntheticRule);
|
|
2138
|
-
if (!uniAppXEnabled) node.before(makePseudoVarRule());
|
|
2349
|
+
if (!uniAppXEnabled && !isTailwindcss4) node.before(makePseudoVarRule());
|
|
2139
2350
|
if (typeof cssInjectPreflight === "function") syntheticRule.append(...cssInjectPreflight());
|
|
2140
2351
|
}
|
|
2141
2352
|
}
|
|
@@ -2470,19 +2681,31 @@ function createStyleHandler(options) {
|
|
|
2470
2681
|
const hasUserPlugins = Boolean(cachedOptions.postcssOptions?.plugins && (Array.isArray(cachedOptions.postcssOptions.plugins) ? cachedOptions.postcssOptions.plugins.length > 0 : typeof cachedOptions.postcssOptions.plugins === "object" && Object.keys(cachedOptions.postcssOptions.plugins).length > 0));
|
|
2471
2682
|
const handler = ((rawSource, opt) => {
|
|
2472
2683
|
const resolvedOptions = resolver.resolve(opt);
|
|
2684
|
+
const protectedColorMix = resolvedOptions.majorVersion === 4 ? protectDynamicColorMixAlpha(rawSource) : void 0;
|
|
2685
|
+
const source = protectedColorMix?.css ?? rawSource;
|
|
2473
2686
|
let signal;
|
|
2474
2687
|
if (!hasUserPlugins) try {
|
|
2475
|
-
signal = probeFeatures(
|
|
2688
|
+
signal = probeFeatures(source);
|
|
2476
2689
|
} catch {
|
|
2477
2690
|
signal = void 0;
|
|
2478
2691
|
}
|
|
2479
|
-
const cacheKey = `${getOptionsFingerprint(resolvedOptions)}|${signal ? signalToCacheKey(signal) : ""}|${simpleHash(
|
|
2692
|
+
const cacheKey = `${getOptionsFingerprint(resolvedOptions)}|${signal ? signalToCacheKey(signal) : ""}|${simpleHash(source)}`;
|
|
2480
2693
|
const cachedResult = resultCache.get(cacheKey);
|
|
2481
2694
|
if (cachedResult) return Promise.resolve(cachedResult);
|
|
2482
2695
|
const processor = processorCache.getProcessor(resolvedOptions, signal);
|
|
2483
2696
|
const processOptions = processorCache.getProcessOptions(resolvedOptions);
|
|
2484
|
-
return processor.process(
|
|
2485
|
-
|
|
2697
|
+
return processor.process(source, processOptions).async().then((result) => {
|
|
2698
|
+
let finalResult = applyUniAppXUvueCompatibility(applyUniAppXBaseCompatibility(result, resolvedOptions), resolvedOptions);
|
|
2699
|
+
if (protectedColorMix) {
|
|
2700
|
+
const restoredCss = protectedColorMix.restore(finalResult.css);
|
|
2701
|
+
if (restoredCss !== finalResult.css) {
|
|
2702
|
+
const nextResult = finalResult.root.clone().toResult(finalResult.opts);
|
|
2703
|
+
nextResult.css = restoredCss;
|
|
2704
|
+
nextResult.root = postcss.parse(restoredCss, finalResult.opts);
|
|
2705
|
+
nextResult.messages.push(...finalResult.messages);
|
|
2706
|
+
finalResult = nextResult;
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2486
2709
|
resultCache.set(cacheKey, finalResult);
|
|
2487
2710
|
return finalResult;
|
|
2488
2711
|
});
|
|
@@ -2494,4 +2717,4 @@ function createStyleHandler(options) {
|
|
|
2494
2717
|
return handler;
|
|
2495
2718
|
}
|
|
2496
2719
|
//#endregion
|
|
2497
|
-
export { createFallbackPlaceholderReplacer, createInjectPreflight, createStyleHandler, createStylePipeline, internalCssSelectorReplacer, postcssHtmlTransform, protectDynamicColorMixAlpha };
|
|
2720
|
+
export { createFallbackPlaceholderReplacer, createInjectPreflight, createStyleHandler, createStylePipeline, internalCssSelectorReplacer, normalizeModernColorValue, postcssHtmlTransform, protectDynamicColorMixAlpha };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weapp-tailwindcss/postcss",
|
|
3
|
-
"version": "2.2.1-next.
|
|
3
|
+
"version": "2.2.1-next.3",
|
|
4
4
|
"description": "@weapp-tailwindcss/postcss",
|
|
5
5
|
"author": "ice breaker <1324318532@qq.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -56,11 +56,14 @@
|
|
|
56
56
|
"node": "^20.19.0 || >=22.12.0"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
+
"@csstools/css-color-parser": "^4.1.1",
|
|
60
|
+
"@csstools/css-parser-algorithms": "^4.0.0",
|
|
61
|
+
"@csstools/css-tokenizer": "^4.0.0",
|
|
59
62
|
"@weapp-core/escape": "~7.0.0",
|
|
60
63
|
"@weapp-tailwindcss/postcss-calc": "^1.0.0",
|
|
61
64
|
"autoprefixer": "^10.5.0",
|
|
62
65
|
"lru-cache": "10.4.3",
|
|
63
|
-
"postcss": "^8.5.
|
|
66
|
+
"postcss": "^8.5.15",
|
|
64
67
|
"postcss-preset-env": "^10.6.1",
|
|
65
68
|
"postcss-pxtrans": "^1.0.4",
|
|
66
69
|
"postcss-rem-to-responsive-pixel": "^7.0.4",
|