tailwindcss-patch 9.2.0 → 9.3.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/dist/cli.js +2 -2
- package/dist/cli.mjs +2 -2
- package/dist/commands/cli-runtime.d.mts +1 -1
- package/dist/commands/cli-runtime.d.ts +1 -1
- package/dist/commands/cli-runtime.js +1 -1
- package/dist/commands/cli-runtime.mjs +1 -1
- package/dist/{index.bundle-dp_pw5fq.mjs → index.bundle-CsMNxjyL.mjs} +4 -3
- package/dist/{index.bundle-BQ_yKkd8.js → index.bundle-DSIUuQAH.js} +4 -3
- package/dist/index.d.mts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{validate-D5elFZMj.mjs → validate-B_jsptz9.mjs} +269 -12
- package/dist/{validate-Bu_rkfQF.d.ts → validate-Bqych-z9.d.ts} +17 -1
- package/dist/{validate-CIMnzW8O.d.mts → validate-C8-qsOWo.d.mts} +17 -1
- package/dist/{validate-749MHvAC.js → validate-DzKStQUM.js} +280 -11
- package/package.json +2 -2
- package/src/extraction/candidate-extractor.ts +50 -5
- package/src/options/normalize.ts +5 -0
- package/src/options/types.ts +8 -0
- package/src/runtime/class-collector.ts +2 -0
- package/src/v4/bare-arbitrary-values.ts +326 -0
- package/src/v4/candidates.ts +68 -4
- package/src/v4/engine.ts +15 -3
- package/src/v4/types.ts +6 -0
|
@@ -249,6 +249,10 @@ interface TailwindV4Options {
|
|
|
249
249
|
cssEntries?: string[];
|
|
250
250
|
/** Overrides the content sources scanned by the oxide scanner. */
|
|
251
251
|
sources?: SourceEntry[];
|
|
252
|
+
/** Enables UnoCSS-style bare arbitrary values such as `p-10%` and `p-2.5px`. */
|
|
253
|
+
bareArbitraryValues?: boolean | {
|
|
254
|
+
/** Unit allow-list used when detecting bare arbitrary values. */units?: string[];
|
|
255
|
+
} | undefined;
|
|
252
256
|
}
|
|
253
257
|
/**
|
|
254
258
|
* High-level Tailwind patch configuration shared across versions.
|
|
@@ -326,6 +330,9 @@ interface NormalizedTailwindV4Options {
|
|
|
326
330
|
cssEntries: string[];
|
|
327
331
|
sources: SourceEntry[];
|
|
328
332
|
hasUserDefinedSources: boolean;
|
|
333
|
+
bareArbitraryValues: false | {
|
|
334
|
+
units?: string[];
|
|
335
|
+
} | undefined;
|
|
329
336
|
}
|
|
330
337
|
/**
|
|
331
338
|
* Tailwind configuration ready for consumption by the runtime after normalization.
|
|
@@ -413,6 +420,14 @@ type TailwindcssConfigResult = Awaited<ReturnType<TailwindcssConfigModule['getCo
|
|
|
413
420
|
//#region src/runtime/collector.d.ts
|
|
414
421
|
type TailwindMajorVersion = 2 | 3 | 4;
|
|
415
422
|
//#endregion
|
|
423
|
+
//#region src/v4/bare-arbitrary-values.d.ts
|
|
424
|
+
interface BareArbitraryValueOptions {
|
|
425
|
+
/**
|
|
426
|
+
* 允许作为无方括号任意值的单位列表。
|
|
427
|
+
*/
|
|
428
|
+
units?: string[];
|
|
429
|
+
}
|
|
430
|
+
//#endregion
|
|
416
431
|
//#region src/extraction/candidate-extractor.d.ts
|
|
417
432
|
interface ExtractValidCandidatesOption {
|
|
418
433
|
sources?: SourceEntry[];
|
|
@@ -420,6 +435,7 @@ interface ExtractValidCandidatesOption {
|
|
|
420
435
|
baseFallbacks?: string[];
|
|
421
436
|
css?: string;
|
|
422
437
|
cwd?: string;
|
|
438
|
+
bareArbitraryValues?: boolean | BareArbitraryValueOptions;
|
|
423
439
|
}
|
|
424
440
|
declare function extractRawCandidatesWithPositions(content: string, extension?: string): Promise<{
|
|
425
441
|
rawCandidate: string;
|
|
@@ -682,4 +698,4 @@ declare class ValidateCommandError extends Error {
|
|
|
682
698
|
constructor(summary: ValidateFailureSummary, options?: ErrorOptions);
|
|
683
699
|
}
|
|
684
700
|
//#endregion
|
|
685
|
-
export {
|
|
701
|
+
export { TailwindTokenByFileMap as $, groupTokensByFile as A, NormalizedTailwindCssPatchOptions as B, MIGRATION_REPORT_SCHEMA_VERSION as C, extractRawCandidates as D, extractProjectCandidatesWithPositions as E, CacheStrategy as F, TailwindV4Options as G, TailwindCssPatchOptions as H, ExposeContextOptions as I, PatchCheckStatus as J, ExtractResult as K, ExtendLengthUnitsOptions as L, normalizeOptions as M, ApplyOptions as N, extractRawCandidatesWithPositions as O, CacheOptions as P, TailwindPatchRuntime as Q, ExtractOptions as R, MIGRATION_REPORT_KIND as S, TailwindcssPatcher as T, TailwindV2Options as U, TailwindCssOptions as V, TailwindV3Options as W, PatchStatusEntry as X, PatchName as Y, PatchStatusReport as Z, ConfigFileMigrationEntry as _, ValidateFailureSummary as a, CacheClearOptions as at, RestoreConfigFilesOptions as b, TailwindcssPatchCliMountOptions as c, CacheContextDescriptor as ct, TailwindcssPatchCommandContext as d, CacheReadMeta as dt, TailwindTokenFileKey as et, TailwindcssPatchCommandHandler as f, CacheReadResult as ft, tailwindcssPatchCommands as g, TailwindcssPatchCommandOptions as h, ValidateFailureReason as i, TailwindcssRuntimeContext as it, BareArbitraryValueOptions as j, extractValidCandidates as k, TailwindcssPatchCliOptions as l, CacheContextMetadata as lt, TailwindcssPatchCommandOptionDefinition as m, VALIDATE_FAILURE_REASONS as n, TailwindTokenReport as nt, ValidateJsonFailurePayload as o, CacheClearResult as ot, TailwindcssPatchCommandHandlerMap as p, ILengthUnitsPatchOptions as q, ValidateCommandError as r, TailwindcssClassCache as rt, ValidateJsonSuccessPayload as s, CacheClearScope as st, VALIDATE_EXIT_CODES as t, TailwindTokenLocation as tt, TailwindcssPatchCommand as u, CacheIndexFileV2 as ut, ConfigFileMigrationReport as v, logger as w, RestoreConfigFilesResult as x, MigrateConfigFilesOptions as y, NormalizedCacheOptions as z };
|
|
@@ -23,7 +23,7 @@ _babel_traverse = require_chunk.__toESM(_babel_traverse);
|
|
|
23
23
|
let _babel_parser = require("@babel/parser");
|
|
24
24
|
let tailwindcss_config = require("tailwindcss-config");
|
|
25
25
|
//#region package.json
|
|
26
|
-
var version = "9.
|
|
26
|
+
var version = "9.3.0";
|
|
27
27
|
//#endregion
|
|
28
28
|
//#region src/constants.ts
|
|
29
29
|
const pkgName = "tailwindcss-patch";
|
|
@@ -1342,7 +1342,8 @@ function normalizeTailwindV4Options(v4, fallbackBase) {
|
|
|
1342
1342
|
...v4?.css === void 0 ? {} : { css: v4.css },
|
|
1343
1343
|
cssEntries,
|
|
1344
1344
|
sources,
|
|
1345
|
-
hasUserDefinedSources
|
|
1345
|
+
hasUserDefinedSources,
|
|
1346
|
+
bareArbitraryValues: v4?.bareArbitraryValues === true ? {} : typeof v4?.bareArbitraryValues === "object" && v4.bareArbitraryValues !== null ? { ...v4.bareArbitraryValues } : false
|
|
1346
1347
|
};
|
|
1347
1348
|
}
|
|
1348
1349
|
function normalizeTailwindOptions(tailwind, projectRoot, shouldDefaultResolveFromCwd) {
|
|
@@ -1447,23 +1448,257 @@ async function loadPatchOptionsForWorkspace(cwd, overrides) {
|
|
|
1447
1448
|
return merge(overrides ?? {}, base, { projectRoot: cwd });
|
|
1448
1449
|
}
|
|
1449
1450
|
//#endregion
|
|
1451
|
+
//#region src/v4/bare-arbitrary-values.ts
|
|
1452
|
+
const DEFAULT_BARE_ARBITRARY_VALUE_UNITS = [
|
|
1453
|
+
"%",
|
|
1454
|
+
"px",
|
|
1455
|
+
"rpx",
|
|
1456
|
+
"rem",
|
|
1457
|
+
"em",
|
|
1458
|
+
"vw",
|
|
1459
|
+
"vh",
|
|
1460
|
+
"vmin",
|
|
1461
|
+
"vmax",
|
|
1462
|
+
"dvw",
|
|
1463
|
+
"dvh",
|
|
1464
|
+
"svw",
|
|
1465
|
+
"svh",
|
|
1466
|
+
"lvw",
|
|
1467
|
+
"lvh",
|
|
1468
|
+
"ch",
|
|
1469
|
+
"ex",
|
|
1470
|
+
"lh",
|
|
1471
|
+
"rlh",
|
|
1472
|
+
"fr",
|
|
1473
|
+
"deg",
|
|
1474
|
+
"rad",
|
|
1475
|
+
"turn",
|
|
1476
|
+
"s",
|
|
1477
|
+
"ms"
|
|
1478
|
+
];
|
|
1479
|
+
const NUMBER_RE = /^-?(?:\d+|\d*\.\d+)$/;
|
|
1480
|
+
const FUNCTION_VALUE_RE = /^[a-zA-Z_-][a-zA-Z0-9_-]*\(/;
|
|
1481
|
+
function splitVariantPrefix(candidate) {
|
|
1482
|
+
let depth = 0;
|
|
1483
|
+
let quote;
|
|
1484
|
+
let lastSeparator = -1;
|
|
1485
|
+
for (let index = 0; index < candidate.length; index++) {
|
|
1486
|
+
const character = candidate[index];
|
|
1487
|
+
if (character === "\\") {
|
|
1488
|
+
index++;
|
|
1489
|
+
continue;
|
|
1490
|
+
}
|
|
1491
|
+
if (quote) {
|
|
1492
|
+
if (character === quote) quote = void 0;
|
|
1493
|
+
continue;
|
|
1494
|
+
}
|
|
1495
|
+
if (character === "\"" || character === "'") {
|
|
1496
|
+
quote = character;
|
|
1497
|
+
continue;
|
|
1498
|
+
}
|
|
1499
|
+
if (character === "[" || character === "(" || character === "{") {
|
|
1500
|
+
depth++;
|
|
1501
|
+
continue;
|
|
1502
|
+
}
|
|
1503
|
+
if (character === "]" || character === ")" || character === "}") {
|
|
1504
|
+
depth = Math.max(0, depth - 1);
|
|
1505
|
+
continue;
|
|
1506
|
+
}
|
|
1507
|
+
if (depth === 0 && character === ":") lastSeparator = index;
|
|
1508
|
+
}
|
|
1509
|
+
if (lastSeparator === -1) return {
|
|
1510
|
+
prefix: "",
|
|
1511
|
+
body: candidate
|
|
1512
|
+
};
|
|
1513
|
+
return {
|
|
1514
|
+
prefix: candidate.slice(0, lastSeparator + 1),
|
|
1515
|
+
body: candidate.slice(lastSeparator + 1)
|
|
1516
|
+
};
|
|
1517
|
+
}
|
|
1518
|
+
function isBalancedFunctionValue(value) {
|
|
1519
|
+
let depth = 0;
|
|
1520
|
+
let quote;
|
|
1521
|
+
for (let index = 0; index < value.length; index++) {
|
|
1522
|
+
const character = value[index];
|
|
1523
|
+
if (character === "\\") {
|
|
1524
|
+
index++;
|
|
1525
|
+
continue;
|
|
1526
|
+
}
|
|
1527
|
+
if (quote) {
|
|
1528
|
+
if (character === quote) quote = void 0;
|
|
1529
|
+
continue;
|
|
1530
|
+
}
|
|
1531
|
+
if (character === "\"" || character === "'") {
|
|
1532
|
+
quote = character;
|
|
1533
|
+
continue;
|
|
1534
|
+
}
|
|
1535
|
+
if (character === "(") {
|
|
1536
|
+
depth++;
|
|
1537
|
+
continue;
|
|
1538
|
+
}
|
|
1539
|
+
if (character === ")") {
|
|
1540
|
+
depth--;
|
|
1541
|
+
if (depth < 0) return false;
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
return depth === 0 && quote === void 0;
|
|
1545
|
+
}
|
|
1546
|
+
function isHexColorValue(value) {
|
|
1547
|
+
return /^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6,8})$/.test(value);
|
|
1548
|
+
}
|
|
1549
|
+
function isQuotedValue(value) {
|
|
1550
|
+
const quote = value[0];
|
|
1551
|
+
if (quote !== "\"" && quote !== "'" || value[value.length - 1] !== quote) return false;
|
|
1552
|
+
let escaped = false;
|
|
1553
|
+
for (let index = 1; index < value.length - 1; index++) {
|
|
1554
|
+
const character = value[index];
|
|
1555
|
+
if (escaped) {
|
|
1556
|
+
escaped = false;
|
|
1557
|
+
continue;
|
|
1558
|
+
}
|
|
1559
|
+
if (character === "\\") escaped = true;
|
|
1560
|
+
}
|
|
1561
|
+
return !escaped;
|
|
1562
|
+
}
|
|
1563
|
+
function normalizeBareArbitraryValueOptions(options) {
|
|
1564
|
+
if (options === false || options === void 0 || options === null) return;
|
|
1565
|
+
const units = options === true ? DEFAULT_BARE_ARBITRARY_VALUE_UNITS : options.units ?? DEFAULT_BARE_ARBITRARY_VALUE_UNITS;
|
|
1566
|
+
const normalizedUnits = [...new Set(units.filter((unit) => typeof unit === "string" && unit.length > 0))];
|
|
1567
|
+
if (normalizedUnits.length === 0) return;
|
|
1568
|
+
return { units: normalizedUnits.sort((a, b) => b.length - a.length) };
|
|
1569
|
+
}
|
|
1570
|
+
function resolveValueWithUnit(body, units) {
|
|
1571
|
+
for (const unit of units) {
|
|
1572
|
+
if (!body.endsWith(unit)) continue;
|
|
1573
|
+
const numberPart = body.slice(0, -unit.length);
|
|
1574
|
+
if (NUMBER_RE.test(numberPart)) return `${numberPart}${unit}`;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
function resolveArbitraryValue(body, units) {
|
|
1578
|
+
const withUnit = resolveValueWithUnit(body, units);
|
|
1579
|
+
if (withUnit) return withUnit;
|
|
1580
|
+
if (isHexColorValue(body)) return body;
|
|
1581
|
+
if (isQuotedValue(body)) return body;
|
|
1582
|
+
if (FUNCTION_VALUE_RE.test(body) && body.endsWith(")") && isBalancedFunctionValue(body)) return body;
|
|
1583
|
+
}
|
|
1584
|
+
function resolveUtilityAndValue(body, units) {
|
|
1585
|
+
let depth = 0;
|
|
1586
|
+
let quote;
|
|
1587
|
+
for (let index = 1; index < body.length; index++) {
|
|
1588
|
+
const character = body[index];
|
|
1589
|
+
if (character === "\\") {
|
|
1590
|
+
index++;
|
|
1591
|
+
continue;
|
|
1592
|
+
}
|
|
1593
|
+
if (quote) {
|
|
1594
|
+
if (character === quote) quote = void 0;
|
|
1595
|
+
continue;
|
|
1596
|
+
}
|
|
1597
|
+
if (character === "\"" || character === "'") {
|
|
1598
|
+
quote = character;
|
|
1599
|
+
continue;
|
|
1600
|
+
}
|
|
1601
|
+
if (character === "(" || character === "{") {
|
|
1602
|
+
depth++;
|
|
1603
|
+
continue;
|
|
1604
|
+
}
|
|
1605
|
+
if (character === ")" || character === "}") {
|
|
1606
|
+
depth = Math.max(0, depth - 1);
|
|
1607
|
+
continue;
|
|
1608
|
+
}
|
|
1609
|
+
if (depth > 0 || character !== "-") continue;
|
|
1610
|
+
const utility = body.slice(0, index);
|
|
1611
|
+
const rawValue = body.slice(index + 1);
|
|
1612
|
+
if (!utility || !rawValue) continue;
|
|
1613
|
+
const value = resolveArbitraryValue(rawValue, units);
|
|
1614
|
+
if (value) return {
|
|
1615
|
+
utility,
|
|
1616
|
+
value
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
function resolveBareArbitraryValueCandidate(candidate, options) {
|
|
1621
|
+
const normalizedOptions = normalizeBareArbitraryValueOptions(options);
|
|
1622
|
+
if (!normalizedOptions || !candidate || candidate.includes("[") || candidate.includes("]")) return;
|
|
1623
|
+
const { prefix, body } = splitVariantPrefix(candidate);
|
|
1624
|
+
const important = body.startsWith("!") ? "!" : "";
|
|
1625
|
+
let normalizedBody = important ? body.slice(1) : body;
|
|
1626
|
+
const negative = normalizedBody.startsWith("-") ? "-" : "";
|
|
1627
|
+
if (negative) normalizedBody = normalizedBody.slice(1);
|
|
1628
|
+
const resolved = resolveUtilityAndValue(normalizedBody, normalizedOptions.units);
|
|
1629
|
+
if (!resolved) return;
|
|
1630
|
+
return {
|
|
1631
|
+
candidate,
|
|
1632
|
+
canonicalCandidate: `${prefix}${important}${negative}${resolved.utility}-[${resolved.value}]`
|
|
1633
|
+
};
|
|
1634
|
+
}
|
|
1635
|
+
function escapeCssClassName(value) {
|
|
1636
|
+
let result = "";
|
|
1637
|
+
for (let index = 0; index < value.length; index++) {
|
|
1638
|
+
const codeUnit = value.charCodeAt(index);
|
|
1639
|
+
const character = value.charAt(index);
|
|
1640
|
+
if (codeUnit === 0) {
|
|
1641
|
+
result += "�";
|
|
1642
|
+
continue;
|
|
1643
|
+
}
|
|
1644
|
+
if (codeUnit >= 1 && codeUnit <= 31 || codeUnit === 127 || index === 0 && codeUnit >= 48 && codeUnit <= 57 || index === 1 && codeUnit >= 48 && codeUnit <= 57 && value.charCodeAt(0) === 45) {
|
|
1645
|
+
result += `\\${codeUnit.toString(16)} `;
|
|
1646
|
+
continue;
|
|
1647
|
+
}
|
|
1648
|
+
if (codeUnit >= 128 || codeUnit === 45 || codeUnit === 95 || codeUnit >= 48 && codeUnit <= 57 || codeUnit >= 65 && codeUnit <= 90 || codeUnit >= 97 && codeUnit <= 122) {
|
|
1649
|
+
result += character;
|
|
1650
|
+
continue;
|
|
1651
|
+
}
|
|
1652
|
+
result += `\\${character}`;
|
|
1653
|
+
}
|
|
1654
|
+
return result;
|
|
1655
|
+
}
|
|
1656
|
+
//#endregion
|
|
1450
1657
|
//#region src/v4/candidates.ts
|
|
1451
|
-
function resolveValidTailwindV4Candidates(designSystem, candidates) {
|
|
1658
|
+
function resolveValidTailwindV4Candidates(designSystem, candidates, options) {
|
|
1452
1659
|
const validCandidates = /* @__PURE__ */ new Set();
|
|
1453
1660
|
const parsedCandidates = [];
|
|
1661
|
+
const originalCandidateByCanonical = /* @__PURE__ */ new Map();
|
|
1454
1662
|
for (const candidate of candidates) {
|
|
1455
|
-
if (!candidate
|
|
1456
|
-
|
|
1663
|
+
if (!candidate) continue;
|
|
1664
|
+
const bareArbitrary = resolveBareArbitraryValueCandidate(candidate, options?.bareArbitraryValues);
|
|
1665
|
+
const candidateToCheck = bareArbitrary?.canonicalCandidate ?? candidate;
|
|
1666
|
+
if (parsedCandidates.includes(candidateToCheck)) continue;
|
|
1667
|
+
if (designSystem.parseCandidate(candidateToCheck).length > 0) {
|
|
1668
|
+
parsedCandidates.push(candidateToCheck);
|
|
1669
|
+
if (bareArbitrary) originalCandidateByCanonical.set(candidateToCheck, candidate);
|
|
1670
|
+
}
|
|
1457
1671
|
}
|
|
1458
1672
|
if (parsedCandidates.length === 0) return validCandidates;
|
|
1459
1673
|
const cssByCandidate = designSystem.candidatesToCss(parsedCandidates);
|
|
1460
1674
|
for (let index = 0; index < parsedCandidates.length; index++) {
|
|
1461
1675
|
const candidate = parsedCandidates[index];
|
|
1462
1676
|
const candidateCss = cssByCandidate[index];
|
|
1463
|
-
if (candidate && typeof candidateCss === "string" && candidateCss.trim().length > 0) validCandidates.add(candidate);
|
|
1677
|
+
if (candidate && typeof candidateCss === "string" && candidateCss.trim().length > 0) validCandidates.add(originalCandidateByCanonical.get(candidate) ?? candidate);
|
|
1464
1678
|
}
|
|
1465
1679
|
return validCandidates;
|
|
1466
1680
|
}
|
|
1681
|
+
function createSelectorAliasMap(candidates, options) {
|
|
1682
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
1683
|
+
for (const candidate of candidates) {
|
|
1684
|
+
const bareArbitrary = resolveBareArbitraryValueCandidate(candidate, options);
|
|
1685
|
+
if (!bareArbitrary) continue;
|
|
1686
|
+
aliases.set(escapeCssClassName(bareArbitrary.canonicalCandidate), escapeCssClassName(bareArbitrary.candidate));
|
|
1687
|
+
}
|
|
1688
|
+
return aliases;
|
|
1689
|
+
}
|
|
1690
|
+
function replaceBareArbitraryValueSelectors(css, candidates, options) {
|
|
1691
|
+
const aliases = createSelectorAliasMap(candidates, options);
|
|
1692
|
+
if (aliases.size === 0) return css;
|
|
1693
|
+
let result = css;
|
|
1694
|
+
for (const [canonicalSelector, bareSelector] of aliases) result = result.replaceAll(canonicalSelector, bareSelector);
|
|
1695
|
+
return result;
|
|
1696
|
+
}
|
|
1697
|
+
function canonicalizeBareArbitraryValueCandidates(candidates, options) {
|
|
1698
|
+
return Array.from(candidates, (candidate) => {
|
|
1699
|
+
return resolveBareArbitraryValueCandidate(candidate, options)?.canonicalCandidate ?? candidate;
|
|
1700
|
+
});
|
|
1701
|
+
}
|
|
1467
1702
|
function splitTopLevel(value, separator) {
|
|
1468
1703
|
const result = [];
|
|
1469
1704
|
let start = 0;
|
|
@@ -1709,13 +1944,31 @@ async function compileTailwindV4Source(source) {
|
|
|
1709
1944
|
//#region src/extraction/candidate-extractor.ts
|
|
1710
1945
|
let oxideImportPromise;
|
|
1711
1946
|
const designSystemCandidateCache = /* @__PURE__ */ new Map();
|
|
1947
|
+
function createOxideRuntimeDependencyError(cause) {
|
|
1948
|
+
return new Error([
|
|
1949
|
+
"tailwindcss-patch could not load @tailwindcss/oxide, which is required for source candidate scanning.",
|
|
1950
|
+
"This dependency should be installed automatically by tailwindcss-patch.",
|
|
1951
|
+
"Reinstall dependencies without disabling optional dependencies, or install @tailwindcss/oxide@^4.2.4 manually if your package manager omitted it."
|
|
1952
|
+
].join(" "), { cause });
|
|
1953
|
+
}
|
|
1712
1954
|
async function importOxide() {
|
|
1713
|
-
|
|
1955
|
+
try {
|
|
1956
|
+
return await import("@tailwindcss/oxide");
|
|
1957
|
+
} catch (error) {
|
|
1958
|
+
throw createOxideRuntimeDependencyError(error);
|
|
1959
|
+
}
|
|
1714
1960
|
}
|
|
1715
1961
|
function getOxideModule() {
|
|
1716
1962
|
oxideImportPromise ??= importOxide();
|
|
1963
|
+
oxideImportPromise.catch(() => {
|
|
1964
|
+
oxideImportPromise = void 0;
|
|
1965
|
+
});
|
|
1717
1966
|
return oxideImportPromise;
|
|
1718
1967
|
}
|
|
1968
|
+
function createCandidateCacheKey(designSystemKey, options) {
|
|
1969
|
+
if (options.bareArbitraryValues == null || options.bareArbitraryValues === false) return designSystemKey;
|
|
1970
|
+
return `${designSystemKey}:bare-arbitrary:${JSON.stringify(options.bareArbitraryValues)}`;
|
|
1971
|
+
}
|
|
1719
1972
|
async function extractRawCandidatesWithPositions(content, extension = "html") {
|
|
1720
1973
|
const { Scanner } = await getOxideModule();
|
|
1721
1974
|
return new Scanner({}).getCandidatesWithPositions({
|
|
@@ -1755,8 +2008,9 @@ async function extractValidCandidates(options) {
|
|
|
1755
2008
|
};
|
|
1756
2009
|
const designSystemKey = getTailwindV4DesignSystemCacheKey(source);
|
|
1757
2010
|
const designSystem = await loadTailwindV4DesignSystem(source);
|
|
1758
|
-
const
|
|
1759
|
-
designSystemCandidateCache.
|
|
2011
|
+
const candidateCacheKey = createCandidateCacheKey(designSystemKey, providedOptions);
|
|
2012
|
+
const candidateCache = designSystemCandidateCache.get(candidateCacheKey) ?? /* @__PURE__ */ new Map();
|
|
2013
|
+
designSystemCandidateCache.set(candidateCacheKey, candidateCache);
|
|
1760
2014
|
const candidates = await extractRawCandidates(sources);
|
|
1761
2015
|
const validCandidates = [];
|
|
1762
2016
|
const uncachedCandidates = [];
|
|
@@ -1767,14 +2021,15 @@ async function extractValidCandidates(options) {
|
|
|
1767
2021
|
continue;
|
|
1768
2022
|
}
|
|
1769
2023
|
if (cached === false) continue;
|
|
1770
|
-
|
|
2024
|
+
const bareArbitrary = resolveBareArbitraryValueCandidate(rawCandidate, providedOptions.bareArbitraryValues);
|
|
2025
|
+
if (designSystem.parseCandidate(rawCandidate).length > 0 || bareArbitrary && designSystem.parseCandidate(bareArbitrary.canonicalCandidate).length > 0) {
|
|
1771
2026
|
uncachedCandidates.push(rawCandidate);
|
|
1772
2027
|
continue;
|
|
1773
2028
|
}
|
|
1774
2029
|
candidateCache.set(rawCandidate, false);
|
|
1775
2030
|
}
|
|
1776
2031
|
if (uncachedCandidates.length === 0) return validCandidates;
|
|
1777
|
-
const validUncachedCandidates = resolveValidTailwindV4Candidates(designSystem, uncachedCandidates);
|
|
2032
|
+
const validUncachedCandidates = resolveValidTailwindV4Candidates(designSystem, uncachedCandidates, providedOptions.bareArbitraryValues === void 0 ? void 0 : { bareArbitraryValues: providedOptions.bareArbitraryValues });
|
|
1778
2033
|
for (const candidate of uncachedCandidates) {
|
|
1779
2034
|
const isValid = validUncachedCandidates.has(candidate);
|
|
1780
2035
|
candidateCache.set(candidate, isValid);
|
|
@@ -1982,6 +2237,7 @@ async function collectClassesFromTailwindV4(options) {
|
|
|
1982
2237
|
base: firstBase,
|
|
1983
2238
|
baseFallbacks: designSystemBases.slice(1),
|
|
1984
2239
|
css,
|
|
2240
|
+
...v4Options.bareArbitraryValues === void 0 ? {} : { bareArbitraryValues: v4Options.bareArbitraryValues },
|
|
1985
2241
|
...sources === void 0 ? {} : { sources }
|
|
1986
2242
|
});
|
|
1987
2243
|
for (const candidate of candidates) if (options.filter(candidate)) set.add(candidate);
|
|
@@ -1992,6 +2248,7 @@ async function collectClassesFromTailwindV4(options) {
|
|
|
1992
2248
|
const candidates = await extractValidCandidates({
|
|
1993
2249
|
cwd: options.projectRoot,
|
|
1994
2250
|
base: baseForCss,
|
|
2251
|
+
...v4Options.bareArbitraryValues === void 0 ? {} : { bareArbitraryValues: v4Options.bareArbitraryValues },
|
|
1995
2252
|
...v4Options.css === void 0 ? {} : { css: v4Options.css },
|
|
1996
2253
|
...sources === void 0 ? {} : { sources }
|
|
1997
2254
|
});
|
|
@@ -3599,6 +3856,12 @@ Object.defineProperty(exports, "ValidateCommandError", {
|
|
|
3599
3856
|
return ValidateCommandError;
|
|
3600
3857
|
}
|
|
3601
3858
|
});
|
|
3859
|
+
Object.defineProperty(exports, "canonicalizeBareArbitraryValueCandidates", {
|
|
3860
|
+
enumerable: true,
|
|
3861
|
+
get: function() {
|
|
3862
|
+
return canonicalizeBareArbitraryValueCandidates;
|
|
3863
|
+
}
|
|
3864
|
+
});
|
|
3602
3865
|
Object.defineProperty(exports, "classifyValidateError", {
|
|
3603
3866
|
enumerable: true,
|
|
3604
3867
|
get: function() {
|
|
@@ -3707,6 +3970,12 @@ Object.defineProperty(exports, "normalizeOptions", {
|
|
|
3707
3970
|
return normalizeOptions;
|
|
3708
3971
|
}
|
|
3709
3972
|
});
|
|
3973
|
+
Object.defineProperty(exports, "replaceBareArbitraryValueSelectors", {
|
|
3974
|
+
enumerable: true,
|
|
3975
|
+
get: function() {
|
|
3976
|
+
return replaceBareArbitraryValueSelectors;
|
|
3977
|
+
}
|
|
3978
|
+
});
|
|
3710
3979
|
Object.defineProperty(exports, "resolveValidTailwindV4Candidates", {
|
|
3711
3980
|
enumerable: true,
|
|
3712
3981
|
get: function() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tailwindcss-patch",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.3.0",
|
|
4
4
|
"description": "patch tailwindcss for exposing context and extract classes",
|
|
5
5
|
"author": "ice breaker <1324318532@qq.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"@babel/traverse": "^7.29.0",
|
|
67
67
|
"@babel/types": "^7.29.0",
|
|
68
68
|
"@tailwindcss/node": "^4.2.4",
|
|
69
|
+
"@tailwindcss/oxide": "^4.2.4",
|
|
69
70
|
"cac": "6.7.14",
|
|
70
71
|
"consola": "^3.4.2",
|
|
71
72
|
"fs-extra": "^11.3.4",
|
|
@@ -77,7 +78,6 @@
|
|
|
77
78
|
"@tailwindcss-mangle/config": "7.0.1"
|
|
78
79
|
},
|
|
79
80
|
"devDependencies": {
|
|
80
|
-
"@tailwindcss/oxide": "^4.2.4",
|
|
81
81
|
"@tailwindcss/postcss": "^4.2.4",
|
|
82
82
|
"@tailwindcss/vite": "^4.2.4",
|
|
83
83
|
"tailwindcss": "^4.1.18",
|
|
@@ -8,18 +8,41 @@ import type {
|
|
|
8
8
|
import { promises as fs } from 'node:fs'
|
|
9
9
|
import process from 'node:process'
|
|
10
10
|
import path from 'pathe'
|
|
11
|
+
import {
|
|
12
|
+
type BareArbitraryValueOptions,
|
|
13
|
+
resolveBareArbitraryValueCandidate,
|
|
14
|
+
} from '../v4/bare-arbitrary-values'
|
|
11
15
|
import { resolveValidTailwindV4Candidates } from '../v4/candidates'
|
|
12
16
|
import { getTailwindV4DesignSystemCacheKey, loadTailwindV4DesignSystem } from '../v4/node-adapter'
|
|
13
17
|
|
|
14
18
|
let oxideImportPromise: ReturnType<typeof importOxide> | undefined
|
|
15
19
|
const designSystemCandidateCache = new Map<string, Map<string, boolean>>()
|
|
16
20
|
|
|
21
|
+
function createOxideRuntimeDependencyError(cause: unknown) {
|
|
22
|
+
return new Error(
|
|
23
|
+
[
|
|
24
|
+
'tailwindcss-patch could not load @tailwindcss/oxide, which is required for source candidate scanning.',
|
|
25
|
+
'This dependency should be installed automatically by tailwindcss-patch.',
|
|
26
|
+
'Reinstall dependencies without disabling optional dependencies, or install @tailwindcss/oxide@^4.2.4 manually if your package manager omitted it.',
|
|
27
|
+
].join(' '),
|
|
28
|
+
{ cause },
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
17
32
|
async function importOxide() {
|
|
18
|
-
|
|
33
|
+
try {
|
|
34
|
+
return await import('@tailwindcss/oxide')
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
throw createOxideRuntimeDependencyError(error)
|
|
38
|
+
}
|
|
19
39
|
}
|
|
20
40
|
|
|
21
41
|
function getOxideModule() {
|
|
22
42
|
oxideImportPromise ??= importOxide()
|
|
43
|
+
oxideImportPromise.catch(() => {
|
|
44
|
+
oxideImportPromise = undefined
|
|
45
|
+
})
|
|
23
46
|
return oxideImportPromise
|
|
24
47
|
}
|
|
25
48
|
|
|
@@ -29,6 +52,17 @@ export interface ExtractValidCandidatesOption {
|
|
|
29
52
|
baseFallbacks?: string[]
|
|
30
53
|
css?: string
|
|
31
54
|
cwd?: string
|
|
55
|
+
bareArbitraryValues?: boolean | BareArbitraryValueOptions
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function createCandidateCacheKey(
|
|
59
|
+
designSystemKey: string,
|
|
60
|
+
options: Pick<ExtractValidCandidatesOption, 'bareArbitraryValues'>,
|
|
61
|
+
) {
|
|
62
|
+
if (options.bareArbitraryValues == null || options.bareArbitraryValues === false) {
|
|
63
|
+
return designSystemKey
|
|
64
|
+
}
|
|
65
|
+
return `${designSystemKey}:bare-arbitrary:${JSON.stringify(options.bareArbitraryValues)}`
|
|
32
66
|
}
|
|
33
67
|
|
|
34
68
|
export async function extractRawCandidatesWithPositions(
|
|
@@ -83,8 +117,9 @@ export async function extractValidCandidates(options?: ExtractValidCandidatesOpt
|
|
|
83
117
|
}
|
|
84
118
|
const designSystemKey = getTailwindV4DesignSystemCacheKey(source)
|
|
85
119
|
const designSystem = await loadTailwindV4DesignSystem(source)
|
|
86
|
-
const
|
|
87
|
-
designSystemCandidateCache.
|
|
120
|
+
const candidateCacheKey = createCandidateCacheKey(designSystemKey, providedOptions)
|
|
121
|
+
const candidateCache = designSystemCandidateCache.get(candidateCacheKey) ?? new Map<string, boolean>()
|
|
122
|
+
designSystemCandidateCache.set(candidateCacheKey, candidateCache)
|
|
88
123
|
|
|
89
124
|
const candidates = await extractRawCandidates(sources)
|
|
90
125
|
const validCandidates: string[] = []
|
|
@@ -101,7 +136,11 @@ export async function extractValidCandidates(options?: ExtractValidCandidatesOpt
|
|
|
101
136
|
continue
|
|
102
137
|
}
|
|
103
138
|
|
|
104
|
-
|
|
139
|
+
const bareArbitrary = resolveBareArbitraryValueCandidate(rawCandidate, providedOptions.bareArbitraryValues)
|
|
140
|
+
if (
|
|
141
|
+
designSystem.parseCandidate(rawCandidate).length > 0
|
|
142
|
+
|| (bareArbitrary && designSystem.parseCandidate(bareArbitrary.canonicalCandidate).length > 0)
|
|
143
|
+
) {
|
|
105
144
|
uncachedCandidates.push(rawCandidate)
|
|
106
145
|
continue
|
|
107
146
|
}
|
|
@@ -113,7 +152,13 @@ export async function extractValidCandidates(options?: ExtractValidCandidatesOpt
|
|
|
113
152
|
return validCandidates
|
|
114
153
|
}
|
|
115
154
|
|
|
116
|
-
const validUncachedCandidates = resolveValidTailwindV4Candidates(
|
|
155
|
+
const validUncachedCandidates = resolveValidTailwindV4Candidates(
|
|
156
|
+
designSystem,
|
|
157
|
+
uncachedCandidates,
|
|
158
|
+
providedOptions.bareArbitraryValues === undefined
|
|
159
|
+
? undefined
|
|
160
|
+
: { bareArbitraryValues: providedOptions.bareArbitraryValues },
|
|
161
|
+
)
|
|
117
162
|
|
|
118
163
|
for (const candidate of uncachedCandidates) {
|
|
119
164
|
const isValid = validUncachedCandidates.has(candidate)
|
package/src/options/normalize.ts
CHANGED
|
@@ -170,6 +170,11 @@ function normalizeTailwindV4Options(
|
|
|
170
170
|
cssEntries,
|
|
171
171
|
sources,
|
|
172
172
|
hasUserDefinedSources,
|
|
173
|
+
bareArbitraryValues: v4?.bareArbitraryValues === true
|
|
174
|
+
? {}
|
|
175
|
+
: typeof v4?.bareArbitraryValues === 'object' && v4.bareArbitraryValues !== null
|
|
176
|
+
? { ...v4.bareArbitraryValues }
|
|
177
|
+
: false,
|
|
173
178
|
}
|
|
174
179
|
}
|
|
175
180
|
|
package/src/options/types.ts
CHANGED
|
@@ -101,6 +101,11 @@ export interface TailwindV4Options {
|
|
|
101
101
|
cssEntries?: string[]
|
|
102
102
|
/** Overrides the content sources scanned by the oxide scanner. */
|
|
103
103
|
sources?: SourceEntry[]
|
|
104
|
+
/** Enables UnoCSS-style bare arbitrary values such as `p-10%` and `p-2.5px`. */
|
|
105
|
+
bareArbitraryValues?: boolean | {
|
|
106
|
+
/** Unit allow-list used when detecting bare arbitrary values. */
|
|
107
|
+
units?: string[]
|
|
108
|
+
} | undefined
|
|
104
109
|
}
|
|
105
110
|
|
|
106
111
|
/**
|
|
@@ -185,6 +190,9 @@ export interface NormalizedTailwindV4Options {
|
|
|
185
190
|
cssEntries: string[]
|
|
186
191
|
sources: SourceEntry[]
|
|
187
192
|
hasUserDefinedSources: boolean
|
|
193
|
+
bareArbitraryValues: false | {
|
|
194
|
+
units?: string[]
|
|
195
|
+
} | undefined
|
|
188
196
|
}
|
|
189
197
|
|
|
190
198
|
/**
|
|
@@ -83,6 +83,7 @@ export async function collectClassesFromTailwindV4(
|
|
|
83
83
|
base: firstBase,
|
|
84
84
|
baseFallbacks: designSystemBases.slice(1),
|
|
85
85
|
css,
|
|
86
|
+
...(v4Options.bareArbitraryValues === undefined ? {} : { bareArbitraryValues: v4Options.bareArbitraryValues }),
|
|
86
87
|
...(sources === undefined ? {} : { sources }),
|
|
87
88
|
}
|
|
88
89
|
const candidates = await extractValidCandidates(extractOptions)
|
|
@@ -99,6 +100,7 @@ export async function collectClassesFromTailwindV4(
|
|
|
99
100
|
const extractOptions = {
|
|
100
101
|
cwd: options.projectRoot,
|
|
101
102
|
base: baseForCss,
|
|
103
|
+
...(v4Options.bareArbitraryValues === undefined ? {} : { bareArbitraryValues: v4Options.bareArbitraryValues }),
|
|
102
104
|
...(v4Options.css === undefined ? {} : { css: v4Options.css }),
|
|
103
105
|
...(sources === undefined ? {} : { sources }),
|
|
104
106
|
}
|