tailwindcss-patch 9.2.1 → 9.3.1

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.
@@ -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 { TailwindTokenFileKey as $, groupTokensByFile as A, TailwindCssOptions as B, MIGRATION_REPORT_SCHEMA_VERSION as C, extractRawCandidates as D, extractProjectCandidatesWithPositions as E, ExposeContextOptions as F, ExtractResult as G, TailwindV2Options as H, ExtendLengthUnitsOptions as I, PatchName as J, ILengthUnitsPatchOptions as K, ExtractOptions as L, ApplyOptions as M, CacheOptions as N, extractRawCandidatesWithPositions as O, CacheStrategy as P, TailwindTokenByFileMap as Q, NormalizedCacheOptions as R, MIGRATION_REPORT_KIND as S, TailwindcssPatcher as T, TailwindV3Options as U, TailwindCssPatchOptions as V, TailwindV4Options as W, PatchStatusReport as X, PatchStatusEntry as Y, TailwindPatchRuntime as Z, ConfigFileMigrationEntry as _, ValidateFailureSummary as a, CacheClearResult as at, RestoreConfigFilesOptions as b, TailwindcssPatchCliMountOptions as c, CacheContextMetadata as ct, TailwindcssPatchCommandContext as d, CacheReadResult as dt, TailwindTokenLocation as et, TailwindcssPatchCommandHandler as f, tailwindcssPatchCommands as g, TailwindcssPatchCommandOptions as h, ValidateFailureReason as i, CacheClearOptions as it, normalizeOptions as j, extractValidCandidates as k, TailwindcssPatchCliOptions as l, CacheIndexFileV2 as lt, TailwindcssPatchCommandOptionDefinition as m, VALIDATE_FAILURE_REASONS as n, TailwindcssClassCache as nt, ValidateJsonFailurePayload as o, CacheClearScope as ot, TailwindcssPatchCommandHandlerMap as p, PatchCheckStatus as q, ValidateCommandError as r, TailwindcssRuntimeContext as rt, ValidateJsonSuccessPayload as s, CacheContextDescriptor as st, VALIDATE_EXIT_CODES as t, TailwindTokenReport as tt, TailwindcssPatchCommand as u, CacheReadMeta as ut, ConfigFileMigrationReport as v, logger as w, RestoreConfigFilesResult as x, MigrateConfigFilesOptions as y, NormalizedTailwindCssPatchOptions as z };
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 };
@@ -16,7 +16,7 @@ import _babelTraverse from "@babel/traverse";
16
16
  import { parse, parse as parse$1 } from "@babel/parser";
17
17
  import { loadConfig } from "tailwindcss-config";
18
18
  //#region package.json
19
- var version = "9.2.1";
19
+ var version = "9.3.1";
20
20
  //#endregion
21
21
  //#region src/constants.ts
22
22
  const pkgName = "tailwindcss-patch";
@@ -177,6 +177,8 @@ function cloneEntry(entry) {
177
177
  };
178
178
  }
179
179
  var CacheStore = class {
180
+ options;
181
+ context;
180
182
  driver;
181
183
  lockPath;
182
184
  memoryCache = null;
@@ -1335,7 +1337,8 @@ function normalizeTailwindV4Options(v4, fallbackBase) {
1335
1337
  ...v4?.css === void 0 ? {} : { css: v4.css },
1336
1338
  cssEntries,
1337
1339
  sources,
1338
- hasUserDefinedSources
1340
+ hasUserDefinedSources,
1341
+ bareArbitraryValues: v4?.bareArbitraryValues === true ? {} : typeof v4?.bareArbitraryValues === "object" && v4.bareArbitraryValues !== null ? { ...v4.bareArbitraryValues } : false
1339
1342
  };
1340
1343
  }
1341
1344
  function normalizeTailwindOptions(tailwind, projectRoot, shouldDefaultResolveFromCwd) {
@@ -1399,7 +1402,7 @@ function normalizeOptions(options = {}) {
1399
1402
  };
1400
1403
  }
1401
1404
  //#endregion
1402
- //#region ../../node_modules/.pnpm/tsdown@0.21.10_synckit@0.11.12_typescript@6.0.3/node_modules/tsdown/esm-shims.js
1405
+ //#region ../../node_modules/.pnpm/tsdown@0.22.0_tsx@4.21.0_typescript@6.0.3_unrun@0.2.37_synckit@0.11.12_/node_modules/tsdown/esm-shims.js
1403
1406
  const getFilename = () => fileURLToPath(import.meta.url);
1404
1407
  const getDirname = () => path$1.dirname(getFilename());
1405
1408
  const __dirname = /* @__PURE__ */ getDirname();
@@ -1445,23 +1448,257 @@ async function loadPatchOptionsForWorkspace(cwd, overrides) {
1445
1448
  return merge(overrides ?? {}, base, { projectRoot: cwd });
1446
1449
  }
1447
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
1448
1657
  //#region src/v4/candidates.ts
1449
- function resolveValidTailwindV4Candidates(designSystem, candidates) {
1658
+ function resolveValidTailwindV4Candidates(designSystem, candidates, options) {
1450
1659
  const validCandidates = /* @__PURE__ */ new Set();
1451
1660
  const parsedCandidates = [];
1661
+ const originalCandidateByCanonical = /* @__PURE__ */ new Map();
1452
1662
  for (const candidate of candidates) {
1453
- if (!candidate || parsedCandidates.includes(candidate)) continue;
1454
- if (designSystem.parseCandidate(candidate).length > 0) parsedCandidates.push(candidate);
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
+ }
1455
1671
  }
1456
1672
  if (parsedCandidates.length === 0) return validCandidates;
1457
1673
  const cssByCandidate = designSystem.candidatesToCss(parsedCandidates);
1458
1674
  for (let index = 0; index < parsedCandidates.length; index++) {
1459
1675
  const candidate = parsedCandidates[index];
1460
1676
  const candidateCss = cssByCandidate[index];
1461
- 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);
1462
1678
  }
1463
1679
  return validCandidates;
1464
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
+ }
1465
1702
  function splitTopLevel(value, separator) {
1466
1703
  const result = [];
1467
1704
  let start = 0;
@@ -1728,6 +1965,10 @@ function getOxideModule() {
1728
1965
  });
1729
1966
  return oxideImportPromise;
1730
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
+ }
1731
1972
  async function extractRawCandidatesWithPositions(content, extension = "html") {
1732
1973
  const { Scanner } = await getOxideModule();
1733
1974
  return new Scanner({}).getCandidatesWithPositions({
@@ -1767,8 +2008,9 @@ async function extractValidCandidates(options) {
1767
2008
  };
1768
2009
  const designSystemKey = getTailwindV4DesignSystemCacheKey(source);
1769
2010
  const designSystem = await loadTailwindV4DesignSystem(source);
1770
- const candidateCache = designSystemCandidateCache.get(designSystemKey) ?? /* @__PURE__ */ new Map();
1771
- designSystemCandidateCache.set(designSystemKey, candidateCache);
2011
+ const candidateCacheKey = createCandidateCacheKey(designSystemKey, providedOptions);
2012
+ const candidateCache = designSystemCandidateCache.get(candidateCacheKey) ?? /* @__PURE__ */ new Map();
2013
+ designSystemCandidateCache.set(candidateCacheKey, candidateCache);
1772
2014
  const candidates = await extractRawCandidates(sources);
1773
2015
  const validCandidates = [];
1774
2016
  const uncachedCandidates = [];
@@ -1779,14 +2021,15 @@ async function extractValidCandidates(options) {
1779
2021
  continue;
1780
2022
  }
1781
2023
  if (cached === false) continue;
1782
- if (designSystem.parseCandidate(rawCandidate).length > 0) {
2024
+ const bareArbitrary = resolveBareArbitraryValueCandidate(rawCandidate, providedOptions.bareArbitraryValues);
2025
+ if (designSystem.parseCandidate(rawCandidate).length > 0 || bareArbitrary && designSystem.parseCandidate(bareArbitrary.canonicalCandidate).length > 0) {
1783
2026
  uncachedCandidates.push(rawCandidate);
1784
2027
  continue;
1785
2028
  }
1786
2029
  candidateCache.set(rawCandidate, false);
1787
2030
  }
1788
2031
  if (uncachedCandidates.length === 0) return validCandidates;
1789
- const validUncachedCandidates = resolveValidTailwindV4Candidates(designSystem, uncachedCandidates);
2032
+ const validUncachedCandidates = resolveValidTailwindV4Candidates(designSystem, uncachedCandidates, providedOptions.bareArbitraryValues === void 0 ? void 0 : { bareArbitraryValues: providedOptions.bareArbitraryValues });
1790
2033
  for (const candidate of uncachedCandidates) {
1791
2034
  const isValid = validUncachedCandidates.has(candidate);
1792
2035
  candidateCache.set(candidate, isValid);
@@ -1994,6 +2237,7 @@ async function collectClassesFromTailwindV4(options) {
1994
2237
  base: firstBase,
1995
2238
  baseFallbacks: designSystemBases.slice(1),
1996
2239
  css,
2240
+ ...v4Options.bareArbitraryValues === void 0 ? {} : { bareArbitraryValues: v4Options.bareArbitraryValues },
1997
2241
  ...sources === void 0 ? {} : { sources }
1998
2242
  });
1999
2243
  for (const candidate of candidates) if (options.filter(candidate)) set.add(candidate);
@@ -2004,6 +2248,7 @@ async function collectClassesFromTailwindV4(options) {
2004
2248
  const candidates = await extractValidCandidates({
2005
2249
  cwd: options.projectRoot,
2006
2250
  base: baseForCss,
2251
+ ...v4Options.bareArbitraryValues === void 0 ? {} : { bareArbitraryValues: v4Options.bareArbitraryValues },
2007
2252
  ...v4Options.css === void 0 ? {} : { css: v4Options.css },
2008
2253
  ...sources === void 0 ? {} : { sources }
2009
2254
  });
@@ -2668,6 +2913,9 @@ function resolveTailwindExecutionOptions(normalized, majorVersion) {
2668
2913
  };
2669
2914
  }
2670
2915
  var BaseCollector = class {
2916
+ packageInfo;
2917
+ options;
2918
+ majorVersion;
2671
2919
  constructor(packageInfo, options, majorVersion) {
2672
2920
  this.packageInfo = packageInfo;
2673
2921
  this.options = options;
@@ -2692,6 +2940,7 @@ var BaseCollector = class {
2692
2940
  }
2693
2941
  };
2694
2942
  var RuntimeCollector = class extends BaseCollector {
2943
+ snapshotFactory;
2695
2944
  inFlightBuild;
2696
2945
  constructor(packageInfo, options, majorVersion, snapshotFactory) {
2697
2946
  super(packageInfo, options, majorVersion);
@@ -3569,4 +3818,4 @@ var ValidateCommandError = class extends Error {
3569
3818
  }
3570
3819
  };
3571
3820
  //#endregion
3572
- export { extractTailwindV4InlineSourceCandidates as C, normalizeOptions as D, loadWorkspaceConfigModule as E, CacheStore as O, loadTailwindV4DesignSystem as S, loadPatchOptionsForWorkspace as T, extractRawCandidates as _, tailwindcssPatchCommands as a, groupTokensByFile as b, MIGRATION_REPORT_KIND as c, getPatchStatusReport as d, runTailwindBuild as f, extractProjectCandidatesWithPositions as g, collectClassesFromTailwindV4 as h, classifyValidateError as i, logger as k, MIGRATION_REPORT_SCHEMA_VERSION as l, collectClassesFromContexts as m, VALIDATE_FAILURE_REASONS as n, migrateConfigFiles as o, loadRuntimeContexts as p, ValidateCommandError as r, restoreConfigFiles as s, VALIDATE_EXIT_CODES as t, TailwindcssPatcher as u, extractRawCandidatesWithPositions as v, resolveValidTailwindV4Candidates as w, compileTailwindV4Source as x, extractValidCandidates as y };
3821
+ export { CacheStore as A, canonicalizeBareArbitraryValueCandidates as C, loadPatchOptionsForWorkspace as D, resolveValidTailwindV4Candidates as E, loadWorkspaceConfigModule as O, loadTailwindV4DesignSystem as S, replaceBareArbitraryValueSelectors as T, extractRawCandidates as _, tailwindcssPatchCommands as a, groupTokensByFile as b, MIGRATION_REPORT_KIND as c, getPatchStatusReport as d, runTailwindBuild as f, extractProjectCandidatesWithPositions as g, collectClassesFromTailwindV4 as h, classifyValidateError as i, logger as j, normalizeOptions as k, MIGRATION_REPORT_SCHEMA_VERSION as l, collectClassesFromContexts as m, VALIDATE_FAILURE_REASONS as n, migrateConfigFiles as o, loadRuntimeContexts as p, ValidateCommandError as r, restoreConfigFiles as s, VALIDATE_EXIT_CODES as t, TailwindcssPatcher as u, extractRawCandidatesWithPositions as v, extractTailwindV4InlineSourceCandidates as w, compileTailwindV4Source as x, extractValidCandidates as y };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwindcss-patch",
3
- "version": "9.2.1",
3
+ "version": "9.3.1",
4
4
  "description": "patch tailwindcss for exposing context and extract classes",
5
5
  "author": "ice breaker <1324318532@qq.com>",
6
6
  "license": "MIT",
@@ -65,21 +65,21 @@
65
65
  "@babel/parser": "^7.29.3",
66
66
  "@babel/traverse": "^7.29.0",
67
67
  "@babel/types": "^7.29.0",
68
- "@tailwindcss/node": "^4.2.4",
69
- "@tailwindcss/oxide": "^4.2.4",
68
+ "@tailwindcss/node": "^4.3.0",
69
+ "@tailwindcss/oxide": "^4.3.0",
70
70
  "cac": "6.7.14",
71
71
  "consola": "^3.4.2",
72
- "fs-extra": "^11.3.4",
72
+ "fs-extra": "^11.3.5",
73
73
  "local-pkg": "^1.1.2",
74
74
  "pathe": "^2.0.3",
75
75
  "postcss": "^8.5.14",
76
- "semver": "^7.7.4",
76
+ "semver": "^7.8.0",
77
77
  "tailwindcss-config": "^1.1.5",
78
- "@tailwindcss-mangle/config": "7.0.1"
78
+ "@tailwindcss-mangle/config": "7.0.2"
79
79
  },
80
80
  "devDependencies": {
81
- "@tailwindcss/postcss": "^4.2.4",
82
- "@tailwindcss/vite": "^4.2.4",
81
+ "@tailwindcss/postcss": "^4.3.0",
82
+ "@tailwindcss/vite": "^4.3.0",
83
83
  "tailwindcss": "^4.1.18",
84
84
  "tailwindcss-3": "npm:tailwindcss@^3.4.19",
85
85
  "tailwindcss-4": "npm:tailwindcss@^4.1.18"
@@ -8,6 +8,10 @@ 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
 
@@ -48,6 +52,17 @@ export interface ExtractValidCandidatesOption {
48
52
  baseFallbacks?: string[]
49
53
  css?: string
50
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)}`
51
66
  }
52
67
 
53
68
  export async function extractRawCandidatesWithPositions(
@@ -102,8 +117,9 @@ export async function extractValidCandidates(options?: ExtractValidCandidatesOpt
102
117
  }
103
118
  const designSystemKey = getTailwindV4DesignSystemCacheKey(source)
104
119
  const designSystem = await loadTailwindV4DesignSystem(source)
105
- const candidateCache = designSystemCandidateCache.get(designSystemKey) ?? new Map<string, boolean>()
106
- designSystemCandidateCache.set(designSystemKey, candidateCache)
120
+ const candidateCacheKey = createCandidateCacheKey(designSystemKey, providedOptions)
121
+ const candidateCache = designSystemCandidateCache.get(candidateCacheKey) ?? new Map<string, boolean>()
122
+ designSystemCandidateCache.set(candidateCacheKey, candidateCache)
107
123
 
108
124
  const candidates = await extractRawCandidates(sources)
109
125
  const validCandidates: string[] = []
@@ -120,7 +136,11 @@ export async function extractValidCandidates(options?: ExtractValidCandidatesOpt
120
136
  continue
121
137
  }
122
138
 
123
- if (designSystem.parseCandidate(rawCandidate).length > 0) {
139
+ const bareArbitrary = resolveBareArbitraryValueCandidate(rawCandidate, providedOptions.bareArbitraryValues)
140
+ if (
141
+ designSystem.parseCandidate(rawCandidate).length > 0
142
+ || (bareArbitrary && designSystem.parseCandidate(bareArbitrary.canonicalCandidate).length > 0)
143
+ ) {
124
144
  uncachedCandidates.push(rawCandidate)
125
145
  continue
126
146
  }
@@ -132,7 +152,13 @@ export async function extractValidCandidates(options?: ExtractValidCandidatesOpt
132
152
  return validCandidates
133
153
  }
134
154
 
135
- const validUncachedCandidates = resolveValidTailwindV4Candidates(designSystem, uncachedCandidates)
155
+ const validUncachedCandidates = resolveValidTailwindV4Candidates(
156
+ designSystem,
157
+ uncachedCandidates,
158
+ providedOptions.bareArbitraryValues === undefined
159
+ ? undefined
160
+ : { bareArbitraryValues: providedOptions.bareArbitraryValues },
161
+ )
136
162
 
137
163
  for (const candidate of uncachedCandidates) {
138
164
  const isValid = validUncachedCandidates.has(candidate)
@@ -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
 
@@ -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
  }