tailwindcss-patch 9.3.1 → 9.3.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/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-Y1jzXpYx.js → index.bundle-BdxyJef9.js} +25 -6
- package/dist/{index.bundle-BKRsKEHP.mjs → index.bundle-C39laqrA.mjs} +25 -6
- package/dist/index.d.mts +2 -67
- package/dist/index.d.ts +2 -67
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{validate-Bd1fbQsd.js → validate-DABvQ44V.js} +147 -31
- package/dist/{validate-Bqych-z9.d.ts → validate-DDJnolx2.d.mts} +79 -5
- package/dist/{validate-CVInpab6.mjs → validate-cMWKFUKS.mjs} +147 -31
- package/dist/{validate-C8-qsOWo.d.mts → validate-rPPCy1cl.d.ts} +80 -4
- package/package.json +1 -1
- package/src/index.bundle.ts +1 -0
- package/src/index.ts +1 -0
- package/src/options/normalize.ts +14 -0
- package/src/options/types.ts +4 -0
- package/src/runtime/class-collector.ts +33 -13
- package/src/v4/bare-arbitrary-values.ts +110 -16
- package/src/v4/candidates.ts +48 -20
- package/src/v4/index.ts +1 -0
- package/src/v4/source.ts +48 -6
- package/src/v4/types.ts +8 -0
|
@@ -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.3.
|
|
19
|
+
var version = "9.3.3";
|
|
20
20
|
//#endregion
|
|
21
21
|
//#region src/constants.ts
|
|
22
22
|
const pkgName = "tailwindcss-patch";
|
|
@@ -1323,6 +1323,13 @@ function normalizeExtendLengthUnitsOptions(extend) {
|
|
|
1323
1323
|
function normalizeTailwindV4Options(v4, fallbackBase) {
|
|
1324
1324
|
const configuredBase = v4?.base ? path.resolve(v4.base) : void 0;
|
|
1325
1325
|
const base = configuredBase ?? fallbackBase;
|
|
1326
|
+
const resolveV4Path = (value) => path.isAbsolute(value) ? path.resolve(value) : path.resolve(fallbackBase, value);
|
|
1327
|
+
const cssSources = Array.isArray(v4?.cssSources) ? v4.cssSources.filter((source) => typeof source?.css === "string").map((source) => ({
|
|
1328
|
+
css: source.css,
|
|
1329
|
+
...source.base === void 0 ? {} : { base: resolveV4Path(source.base) },
|
|
1330
|
+
...source.file === void 0 ? {} : { file: resolveV4Path(source.file) },
|
|
1331
|
+
...source.dependencies === void 0 ? {} : { dependencies: source.dependencies.filter(Boolean).map(resolveV4Path) }
|
|
1332
|
+
})) : [];
|
|
1326
1333
|
const cssEntries = Array.isArray(v4?.cssEntries) ? v4.cssEntries.filter((entry) => Boolean(entry)).map((entry) => path.resolve(entry)) : [];
|
|
1327
1334
|
const userSources = v4?.sources;
|
|
1328
1335
|
const hasUserDefinedSources = Boolean(userSources?.length);
|
|
@@ -1335,6 +1342,7 @@ function normalizeTailwindV4Options(v4, fallbackBase) {
|
|
|
1335
1342
|
base,
|
|
1336
1343
|
...configuredBase === void 0 ? {} : { configuredBase },
|
|
1337
1344
|
...v4?.css === void 0 ? {} : { css: v4.css },
|
|
1345
|
+
cssSources,
|
|
1338
1346
|
cssEntries,
|
|
1339
1347
|
sources,
|
|
1340
1348
|
hasUserDefinedSources,
|
|
@@ -1477,7 +1485,8 @@ const DEFAULT_BARE_ARBITRARY_VALUE_UNITS = [
|
|
|
1477
1485
|
"ms"
|
|
1478
1486
|
];
|
|
1479
1487
|
const NUMBER_RE = /^-?(?:\d+|\d*\.\d+)$/;
|
|
1480
|
-
const FUNCTION_VALUE_RE = /^[a-
|
|
1488
|
+
const FUNCTION_VALUE_RE = /^[a-z_-][\w-]*\(/i;
|
|
1489
|
+
const HEX_ESCAPE_RE = /^[\da-f]$/i;
|
|
1481
1490
|
function splitVariantPrefix(candidate) {
|
|
1482
1491
|
let depth = 0;
|
|
1483
1492
|
let quote;
|
|
@@ -1543,8 +1552,38 @@ function isBalancedFunctionValue(value) {
|
|
|
1543
1552
|
}
|
|
1544
1553
|
return depth === 0 && quote === void 0;
|
|
1545
1554
|
}
|
|
1555
|
+
function isEscapedAt(value, index) {
|
|
1556
|
+
let slashCount = 0;
|
|
1557
|
+
for (let slashIndex = index - 1; slashIndex >= 0 && value[slashIndex] === "\\"; slashIndex--) slashCount++;
|
|
1558
|
+
return slashCount % 2 === 1;
|
|
1559
|
+
}
|
|
1560
|
+
function isBalancedBareArbitraryBody(value) {
|
|
1561
|
+
let depth = 0;
|
|
1562
|
+
let quote;
|
|
1563
|
+
for (let index = 0; index < value.length; index++) {
|
|
1564
|
+
const character = value[index];
|
|
1565
|
+
if (isEscapedAt(value, index)) continue;
|
|
1566
|
+
if (quote) {
|
|
1567
|
+
if (character === quote) quote = void 0;
|
|
1568
|
+
continue;
|
|
1569
|
+
}
|
|
1570
|
+
if (character === "\"" || character === "'") {
|
|
1571
|
+
quote = character;
|
|
1572
|
+
continue;
|
|
1573
|
+
}
|
|
1574
|
+
if (character === "(" || character === "{") {
|
|
1575
|
+
depth++;
|
|
1576
|
+
continue;
|
|
1577
|
+
}
|
|
1578
|
+
if (character === ")" || character === "}") {
|
|
1579
|
+
depth--;
|
|
1580
|
+
if (depth < 0) return false;
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
return depth === 0 && quote === void 0;
|
|
1584
|
+
}
|
|
1546
1585
|
function isHexColorValue(value) {
|
|
1547
|
-
return /^#(?:[0-9a-
|
|
1586
|
+
return /^#(?:[0-9a-f]{3,4}|[0-9a-f]{6,8})$/i.test(value);
|
|
1548
1587
|
}
|
|
1549
1588
|
function isQuotedValue(value) {
|
|
1550
1589
|
const quote = value[0];
|
|
@@ -1567,29 +1606,61 @@ function normalizeBareArbitraryValueOptions(options) {
|
|
|
1567
1606
|
if (normalizedUnits.length === 0) return;
|
|
1568
1607
|
return { units: normalizedUnits.sort((a, b) => b.length - a.length) };
|
|
1569
1608
|
}
|
|
1609
|
+
function normalizeEscapedValue(value) {
|
|
1610
|
+
let result = "";
|
|
1611
|
+
for (let index = 0; index < value.length; index++) {
|
|
1612
|
+
const character = value[index];
|
|
1613
|
+
if (character !== "\\") {
|
|
1614
|
+
result += character;
|
|
1615
|
+
continue;
|
|
1616
|
+
}
|
|
1617
|
+
const nextCharacter = value[index + 1];
|
|
1618
|
+
if (nextCharacter === void 0) {
|
|
1619
|
+
result += character;
|
|
1620
|
+
continue;
|
|
1621
|
+
}
|
|
1622
|
+
if (HEX_ESCAPE_RE.test(nextCharacter)) {
|
|
1623
|
+
let hex = "";
|
|
1624
|
+
let nextIndex = index + 1;
|
|
1625
|
+
while (nextIndex < value.length && hex.length < 6) {
|
|
1626
|
+
const hexCharacter = value[nextIndex];
|
|
1627
|
+
if (hexCharacter === void 0 || !HEX_ESCAPE_RE.test(hexCharacter)) break;
|
|
1628
|
+
hex += hexCharacter;
|
|
1629
|
+
nextIndex++;
|
|
1630
|
+
}
|
|
1631
|
+
if (/[\t\n\f\r ]/.test(value[nextIndex] ?? "")) nextIndex++;
|
|
1632
|
+
const decoded = String.fromCodePoint(Number.parseInt(hex, 16));
|
|
1633
|
+
result += decoded === "_" ? "\\_" : decoded;
|
|
1634
|
+
index = nextIndex - 1;
|
|
1635
|
+
continue;
|
|
1636
|
+
}
|
|
1637
|
+
result += nextCharacter === "_" ? "\\_" : nextCharacter;
|
|
1638
|
+
index++;
|
|
1639
|
+
}
|
|
1640
|
+
return result;
|
|
1641
|
+
}
|
|
1570
1642
|
function resolveValueWithUnit(body, units) {
|
|
1643
|
+
const value = normalizeEscapedValue(body);
|
|
1571
1644
|
for (const unit of units) {
|
|
1572
|
-
if (!
|
|
1573
|
-
const numberPart =
|
|
1645
|
+
if (!value.endsWith(unit)) continue;
|
|
1646
|
+
const numberPart = value.slice(0, -unit.length);
|
|
1574
1647
|
if (NUMBER_RE.test(numberPart)) return `${numberPart}${unit}`;
|
|
1575
1648
|
}
|
|
1576
1649
|
}
|
|
1577
1650
|
function resolveArbitraryValue(body, units) {
|
|
1578
|
-
const
|
|
1651
|
+
const value = normalizeEscapedValue(body);
|
|
1652
|
+
const withUnit = resolveValueWithUnit(value, units);
|
|
1579
1653
|
if (withUnit) return withUnit;
|
|
1580
|
-
if (isHexColorValue(
|
|
1581
|
-
if (isQuotedValue(
|
|
1582
|
-
if (FUNCTION_VALUE_RE.test(
|
|
1654
|
+
if (isHexColorValue(value)) return value;
|
|
1655
|
+
if (isQuotedValue(value)) return value;
|
|
1656
|
+
if (FUNCTION_VALUE_RE.test(value) && value.endsWith(")") && isBalancedFunctionValue(value)) return value;
|
|
1583
1657
|
}
|
|
1584
1658
|
function resolveUtilityAndValue(body, units) {
|
|
1585
1659
|
let depth = 0;
|
|
1586
1660
|
let quote;
|
|
1587
|
-
for (let index = 1; index
|
|
1661
|
+
for (let index = body.length - 1; index > 0; index--) {
|
|
1588
1662
|
const character = body[index];
|
|
1589
|
-
if (
|
|
1590
|
-
index++;
|
|
1591
|
-
continue;
|
|
1592
|
-
}
|
|
1663
|
+
if (isEscapedAt(body, index)) continue;
|
|
1593
1664
|
if (quote) {
|
|
1594
1665
|
if (character === quote) quote = void 0;
|
|
1595
1666
|
continue;
|
|
@@ -1598,11 +1669,11 @@ function resolveUtilityAndValue(body, units) {
|
|
|
1598
1669
|
quote = character;
|
|
1599
1670
|
continue;
|
|
1600
1671
|
}
|
|
1601
|
-
if (character === "
|
|
1672
|
+
if (character === ")" || character === "}") {
|
|
1602
1673
|
depth++;
|
|
1603
1674
|
continue;
|
|
1604
1675
|
}
|
|
1605
|
-
if (character === "
|
|
1676
|
+
if (character === "(" || character === "{") {
|
|
1606
1677
|
depth = Math.max(0, depth - 1);
|
|
1607
1678
|
continue;
|
|
1608
1679
|
}
|
|
@@ -1625,6 +1696,7 @@ function resolveBareArbitraryValueCandidate(candidate, options) {
|
|
|
1625
1696
|
let normalizedBody = important ? body.slice(1) : body;
|
|
1626
1697
|
const negative = normalizedBody.startsWith("-") ? "-" : "";
|
|
1627
1698
|
if (negative) normalizedBody = normalizedBody.slice(1);
|
|
1699
|
+
if (!isBalancedBareArbitraryBody(normalizedBody)) return;
|
|
1628
1700
|
const resolved = resolveUtilityAndValue(normalizedBody, normalizedOptions.units);
|
|
1629
1701
|
if (!resolved) return;
|
|
1630
1702
|
return {
|
|
@@ -1658,23 +1730,32 @@ function escapeCssClassName(value) {
|
|
|
1658
1730
|
function resolveValidTailwindV4Candidates(designSystem, candidates, options) {
|
|
1659
1731
|
const validCandidates = /* @__PURE__ */ new Set();
|
|
1660
1732
|
const parsedCandidates = [];
|
|
1661
|
-
const
|
|
1733
|
+
const originalCandidatesByCanonical = /* @__PURE__ */ new Map();
|
|
1662
1734
|
for (const candidate of candidates) {
|
|
1663
1735
|
if (!candidate) continue;
|
|
1664
1736
|
const bareArbitrary = resolveBareArbitraryValueCandidate(candidate, options?.bareArbitraryValues);
|
|
1665
1737
|
const candidateToCheck = bareArbitrary?.canonicalCandidate ?? candidate;
|
|
1666
|
-
if (
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1738
|
+
if (bareArbitrary) {
|
|
1739
|
+
const originalCandidates = originalCandidatesByCanonical.get(candidateToCheck) ?? /* @__PURE__ */ new Set();
|
|
1740
|
+
originalCandidates.add(candidate);
|
|
1741
|
+
originalCandidatesByCanonical.set(candidateToCheck, originalCandidates);
|
|
1670
1742
|
}
|
|
1743
|
+
if (parsedCandidates.includes(candidateToCheck)) continue;
|
|
1744
|
+
if (designSystem.parseCandidate(candidateToCheck).length > 0) parsedCandidates.push(candidateToCheck);
|
|
1671
1745
|
}
|
|
1672
1746
|
if (parsedCandidates.length === 0) return validCandidates;
|
|
1673
1747
|
const cssByCandidate = designSystem.candidatesToCss(parsedCandidates);
|
|
1674
1748
|
for (let index = 0; index < parsedCandidates.length; index++) {
|
|
1675
1749
|
const candidate = parsedCandidates[index];
|
|
1676
1750
|
const candidateCss = cssByCandidate[index];
|
|
1677
|
-
if (candidate && typeof candidateCss === "string" && candidateCss.trim().length > 0)
|
|
1751
|
+
if (candidate && typeof candidateCss === "string" && candidateCss.trim().length > 0) {
|
|
1752
|
+
const originalCandidates = originalCandidatesByCanonical.get(candidate);
|
|
1753
|
+
if (originalCandidates) {
|
|
1754
|
+
for (const originalCandidate of originalCandidates) validCandidates.add(originalCandidate);
|
|
1755
|
+
continue;
|
|
1756
|
+
}
|
|
1757
|
+
validCandidates.add(candidate);
|
|
1758
|
+
}
|
|
1678
1759
|
}
|
|
1679
1760
|
return validCandidates;
|
|
1680
1761
|
}
|
|
@@ -1683,16 +1764,34 @@ function createSelectorAliasMap(candidates, options) {
|
|
|
1683
1764
|
for (const candidate of candidates) {
|
|
1684
1765
|
const bareArbitrary = resolveBareArbitraryValueCandidate(candidate, options);
|
|
1685
1766
|
if (!bareArbitrary) continue;
|
|
1686
|
-
|
|
1767
|
+
const canonicalSelector = escapeCssClassName(bareArbitrary.canonicalCandidate);
|
|
1768
|
+
const bareSelectors = aliases.get(canonicalSelector) ?? /* @__PURE__ */ new Set();
|
|
1769
|
+
bareSelectors.add(escapeCssClassName(bareArbitrary.candidate));
|
|
1770
|
+
aliases.set(canonicalSelector, bareSelectors);
|
|
1687
1771
|
}
|
|
1688
1772
|
return aliases;
|
|
1689
1773
|
}
|
|
1690
1774
|
function replaceBareArbitraryValueSelectors(css, candidates, options) {
|
|
1691
1775
|
const aliases = createSelectorAliasMap(candidates, options);
|
|
1692
1776
|
if (aliases.size === 0) return css;
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1777
|
+
if (Array.from(aliases.values()).every((bareSelectors) => bareSelectors.size === 1)) {
|
|
1778
|
+
let result = css;
|
|
1779
|
+
for (const [canonicalSelector, bareSelectors] of aliases) {
|
|
1780
|
+
const bareSelector = Array.from(bareSelectors)[0];
|
|
1781
|
+
if (bareSelector !== void 0) result = result.replaceAll(canonicalSelector, bareSelector);
|
|
1782
|
+
}
|
|
1783
|
+
return result;
|
|
1784
|
+
}
|
|
1785
|
+
const root = postcss.parse(css);
|
|
1786
|
+
root.walkRules((rule) => {
|
|
1787
|
+
let selectors = rule.selectors;
|
|
1788
|
+
for (const [canonicalSelector, bareSelectors] of aliases) selectors = selectors.flatMap((selector) => {
|
|
1789
|
+
if (!selector.includes(canonicalSelector)) return selector;
|
|
1790
|
+
return Array.from(bareSelectors, (bareSelector) => selector.replaceAll(canonicalSelector, bareSelector));
|
|
1791
|
+
});
|
|
1792
|
+
rule.selectors = selectors;
|
|
1793
|
+
});
|
|
1794
|
+
return root.toString();
|
|
1696
1795
|
}
|
|
1697
1796
|
function canonicalizeBareArbitraryValueCandidates(candidates, options) {
|
|
1698
1797
|
return Array.from(candidates, (candidate) => {
|
|
@@ -2224,6 +2323,25 @@ async function collectClassesFromTailwindV4(options) {
|
|
|
2224
2323
|
negated: source.negated
|
|
2225
2324
|
}));
|
|
2226
2325
|
};
|
|
2326
|
+
const addCandidates = async (extractOptions) => {
|
|
2327
|
+
const candidates = await extractValidCandidates(extractOptions);
|
|
2328
|
+
for (const candidate of candidates) if (options.filter(candidate)) set.add(candidate);
|
|
2329
|
+
};
|
|
2330
|
+
if (v4Options.cssSources.length > 0) for (const source of v4Options.cssSources) {
|
|
2331
|
+
const sourceFile = toAbsolute(source.file);
|
|
2332
|
+
const sourceBase = toAbsolute(source.base) ?? (sourceFile ? path.dirname(sourceFile) : resolvedDefaultBase);
|
|
2333
|
+
const designSystemBases = resolvedConfiguredBase && resolvedConfiguredBase !== sourceBase ? [sourceBase, resolvedConfiguredBase] : [sourceBase];
|
|
2334
|
+
const sources = resolveSources(sourceBase);
|
|
2335
|
+
const firstBase = designSystemBases[0] ?? sourceBase;
|
|
2336
|
+
await addCandidates({
|
|
2337
|
+
cwd: options.projectRoot,
|
|
2338
|
+
base: firstBase,
|
|
2339
|
+
baseFallbacks: designSystemBases.slice(1),
|
|
2340
|
+
css: source.css,
|
|
2341
|
+
...v4Options.bareArbitraryValues === void 0 ? {} : { bareArbitraryValues: v4Options.bareArbitraryValues },
|
|
2342
|
+
...sources === void 0 ? {} : { sources }
|
|
2343
|
+
});
|
|
2344
|
+
}
|
|
2227
2345
|
if (v4Options.cssEntries.length > 0) for (const entry of v4Options.cssEntries) {
|
|
2228
2346
|
const filePath = path.isAbsolute(entry) ? entry : path.resolve(options.projectRoot, entry);
|
|
2229
2347
|
if (!await fs.pathExists(filePath)) continue;
|
|
@@ -2232,7 +2350,7 @@ async function collectClassesFromTailwindV4(options) {
|
|
|
2232
2350
|
const designSystemBases = resolvedConfiguredBase && resolvedConfiguredBase !== entryDir ? [entryDir, resolvedConfiguredBase] : [entryDir];
|
|
2233
2351
|
const sources = resolveSources(resolvedConfiguredBase ?? entryDir);
|
|
2234
2352
|
const firstBase = designSystemBases[0] ?? entryDir;
|
|
2235
|
-
|
|
2353
|
+
await addCandidates({
|
|
2236
2354
|
cwd: options.projectRoot,
|
|
2237
2355
|
base: firstBase,
|
|
2238
2356
|
baseFallbacks: designSystemBases.slice(1),
|
|
@@ -2240,19 +2358,17 @@ async function collectClassesFromTailwindV4(options) {
|
|
|
2240
2358
|
...v4Options.bareArbitraryValues === void 0 ? {} : { bareArbitraryValues: v4Options.bareArbitraryValues },
|
|
2241
2359
|
...sources === void 0 ? {} : { sources }
|
|
2242
2360
|
});
|
|
2243
|
-
for (const candidate of candidates) if (options.filter(candidate)) set.add(candidate);
|
|
2244
2361
|
}
|
|
2245
|
-
else {
|
|
2362
|
+
else if (v4Options.cssSources.length === 0) {
|
|
2246
2363
|
const baseForCss = resolvedConfiguredBase ?? resolvedDefaultBase;
|
|
2247
2364
|
const sources = resolveSources(baseForCss);
|
|
2248
|
-
|
|
2365
|
+
await addCandidates({
|
|
2249
2366
|
cwd: options.projectRoot,
|
|
2250
2367
|
base: baseForCss,
|
|
2251
2368
|
...v4Options.bareArbitraryValues === void 0 ? {} : { bareArbitraryValues: v4Options.bareArbitraryValues },
|
|
2252
2369
|
...v4Options.css === void 0 ? {} : { css: v4Options.css },
|
|
2253
2370
|
...sources === void 0 ? {} : { sources }
|
|
2254
2371
|
});
|
|
2255
|
-
for (const candidate of candidates) if (options.filter(candidate)) set.add(candidate);
|
|
2256
2372
|
}
|
|
2257
2373
|
return set;
|
|
2258
2374
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { PackageInfo, PackageResolvingOptions } from "local-pkg";
|
|
2
|
-
import * as _$consola from "consola";
|
|
3
|
-
import { Node, Rule } from "postcss";
|
|
4
1
|
import { CAC, Command } from "cac";
|
|
2
|
+
import { PackageInfo, PackageResolvingOptions } from "local-pkg";
|
|
5
3
|
import { SourceEntry } from "@tailwindcss/oxide";
|
|
4
|
+
import { Node, Rule } from "postcss";
|
|
6
5
|
import { Config } from "tailwindcss";
|
|
6
|
+
import * as _$consola from "consola";
|
|
7
|
+
|
|
7
8
|
//#region src/cache/types.d.ts
|
|
8
9
|
declare const CACHE_SCHEMA_VERSION = 2;
|
|
9
10
|
declare const CACHE_FINGERPRINT_VERSION = 1;
|
|
@@ -158,6 +159,78 @@ interface PatchStatusReport {
|
|
|
158
159
|
entries: PatchStatusEntry[];
|
|
159
160
|
}
|
|
160
161
|
//#endregion
|
|
162
|
+
//#region src/v4/types.d.ts
|
|
163
|
+
interface TailwindV4SourceOptions {
|
|
164
|
+
projectRoot?: string;
|
|
165
|
+
cwd?: string;
|
|
166
|
+
base?: string;
|
|
167
|
+
baseFallbacks?: string[];
|
|
168
|
+
css?: string;
|
|
169
|
+
cssSources?: TailwindV4CssSource[];
|
|
170
|
+
cssEntries?: string[];
|
|
171
|
+
packageName?: string;
|
|
172
|
+
}
|
|
173
|
+
interface TailwindV4CssSource {
|
|
174
|
+
css: string;
|
|
175
|
+
base?: string;
|
|
176
|
+
file?: string;
|
|
177
|
+
dependencies?: string[];
|
|
178
|
+
}
|
|
179
|
+
interface TailwindV4ResolvedSource {
|
|
180
|
+
projectRoot: string;
|
|
181
|
+
base: string;
|
|
182
|
+
baseFallbacks: string[];
|
|
183
|
+
css: string;
|
|
184
|
+
dependencies: string[];
|
|
185
|
+
}
|
|
186
|
+
interface TailwindV4CandidateSource {
|
|
187
|
+
content: string;
|
|
188
|
+
extension?: string;
|
|
189
|
+
}
|
|
190
|
+
interface TailwindV4GenerateOptions {
|
|
191
|
+
candidates?: Iterable<string>;
|
|
192
|
+
sources?: TailwindV4CandidateSource[];
|
|
193
|
+
/**
|
|
194
|
+
* Enables UnoCSS-style bare arbitrary values such as `p-10%` and `p-2.5px`.
|
|
195
|
+
*/
|
|
196
|
+
bareArbitraryValues?: boolean | {
|
|
197
|
+
units?: string[];
|
|
198
|
+
};
|
|
199
|
+
/**
|
|
200
|
+
* 扫描文件系统 source entries 中的候选类名。
|
|
201
|
+
*
|
|
202
|
+
* - `true`:使用 Tailwind v4 编译入口解析出的 `@source` 列表。
|
|
203
|
+
* - `TailwindV4SourcePattern[]`:使用调用方显式传入的 source 列表。
|
|
204
|
+
*/
|
|
205
|
+
scanSources?: boolean | TailwindV4SourcePattern[];
|
|
206
|
+
}
|
|
207
|
+
interface TailwindV4SourcePattern {
|
|
208
|
+
base: string;
|
|
209
|
+
pattern: string;
|
|
210
|
+
negated: boolean;
|
|
211
|
+
}
|
|
212
|
+
interface TailwindV4GenerateResult {
|
|
213
|
+
css: string;
|
|
214
|
+
classSet: Set<string>;
|
|
215
|
+
rawCandidates: Set<string>;
|
|
216
|
+
dependencies: string[];
|
|
217
|
+
sources: TailwindV4SourcePattern[];
|
|
218
|
+
root: null | 'none' | {
|
|
219
|
+
base: string;
|
|
220
|
+
pattern: string;
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
interface TailwindV4DesignSystem {
|
|
224
|
+
parseCandidate: (candidate: string) => unknown[];
|
|
225
|
+
candidatesToCss: (candidates: string[]) => Array<string | null | undefined>;
|
|
226
|
+
}
|
|
227
|
+
interface TailwindV4Engine {
|
|
228
|
+
source: TailwindV4ResolvedSource;
|
|
229
|
+
loadDesignSystem: () => Promise<TailwindV4DesignSystem>;
|
|
230
|
+
validateCandidates: (candidates: Iterable<string>) => Promise<Set<string>>;
|
|
231
|
+
generate: (options?: TailwindV4GenerateOptions) => Promise<TailwindV4GenerateResult>;
|
|
232
|
+
}
|
|
233
|
+
//#endregion
|
|
161
234
|
//#region src/options/types.d.ts
|
|
162
235
|
type CacheStrategy = 'merge' | 'overwrite';
|
|
163
236
|
type CacheDriver = 'file' | 'memory' | 'noop';
|
|
@@ -245,6 +318,8 @@ interface TailwindV4Options {
|
|
|
245
318
|
base?: string;
|
|
246
319
|
/** Raw CSS passed directly to the v4 design system. */
|
|
247
320
|
css?: string;
|
|
321
|
+
/** 构建器在 CSS 落盘前捕获的内存 CSS 入口。 */
|
|
322
|
+
cssSources?: TailwindV4CssSource[];
|
|
248
323
|
/** Set of CSS entry files that should be scanned for `@config` directives. */
|
|
249
324
|
cssEntries?: string[];
|
|
250
325
|
/** Overrides the content sources scanned by the oxide scanner. */
|
|
@@ -327,6 +402,7 @@ interface NormalizedTailwindV4Options {
|
|
|
327
402
|
base: string;
|
|
328
403
|
configuredBase?: string;
|
|
329
404
|
css?: string;
|
|
405
|
+
cssSources: TailwindV4CssSource[];
|
|
330
406
|
cssEntries: string[];
|
|
331
407
|
sources: SourceEntry[];
|
|
332
408
|
hasUserDefinedSources: boolean;
|
|
@@ -698,4 +774,4 @@ declare class ValidateCommandError extends Error {
|
|
|
698
774
|
constructor(summary: ValidateFailureSummary, options?: ErrorOptions);
|
|
699
775
|
}
|
|
700
776
|
//#endregion
|
|
701
|
-
export {
|
|
777
|
+
export { TailwindV4SourceOptions 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, TailwindV4DesignSystem as J, TailwindV4CandidateSource as K, ExtendLengthUnitsOptions as L, normalizeOptions as M, ApplyOptions as N, extractRawCandidatesWithPositions as O, CacheOptions as P, TailwindV4ResolvedSource as Q, ExtractOptions as R, MIGRATION_REPORT_KIND as S, TailwindcssPatcher as T, TailwindV2Options as U, TailwindCssOptions as V, TailwindV3Options as W, TailwindV4GenerateOptions as X, TailwindV4Engine as Y, TailwindV4GenerateResult as Z, ConfigFileMigrationEntry as _, CacheContextMetadata as _t, ValidateFailureSummary as a, PatchStatusReport as at, RestoreConfigFilesOptions as b, CacheReadResult as bt, TailwindcssPatchCliMountOptions as c, TailwindTokenFileKey as ct, TailwindcssPatchCommandContext as d, TailwindcssClassCache as dt, ExtractResult as et, TailwindcssPatchCommandHandler as f, TailwindcssRuntimeContext as ft, tailwindcssPatchCommands as g, CacheContextDescriptor as gt, TailwindcssPatchCommandOptions as h, CacheClearScope as ht, ValidateFailureReason as i, PatchStatusEntry as it, BareArbitraryValueOptions as j, extractValidCandidates as k, TailwindcssPatchCliOptions as l, TailwindTokenLocation as lt, TailwindcssPatchCommandOptionDefinition as m, CacheClearResult as mt, VALIDATE_FAILURE_REASONS as n, PatchCheckStatus as nt, ValidateJsonFailurePayload as o, TailwindPatchRuntime as ot, TailwindcssPatchCommandHandlerMap as p, CacheClearOptions as pt, TailwindV4CssSource as q, ValidateCommandError as r, PatchName as rt, ValidateJsonSuccessPayload as s, TailwindTokenByFileMap as st, VALIDATE_EXIT_CODES as t, ILengthUnitsPatchOptions as tt, TailwindcssPatchCommand as u, TailwindTokenReport as ut, ConfigFileMigrationReport as v, CacheIndexFileV2 as vt, logger as w, RestoreConfigFilesResult as x, MigrateConfigFilesOptions as y, CacheReadMeta as yt, NormalizedCacheOptions as z };
|
package/package.json
CHANGED
package/src/index.bundle.ts
CHANGED
package/src/index.ts
CHANGED
package/src/options/normalize.ts
CHANGED
|
@@ -148,6 +148,19 @@ function normalizeTailwindV4Options(
|
|
|
148
148
|
): NormalizedTailwindV4Options {
|
|
149
149
|
const configuredBase = v4?.base ? path.resolve(v4.base) : undefined
|
|
150
150
|
const base = configuredBase ?? fallbackBase
|
|
151
|
+
const resolveV4Path = (value: string) => path.isAbsolute(value) ? path.resolve(value) : path.resolve(fallbackBase, value)
|
|
152
|
+
const cssSources = Array.isArray(v4?.cssSources)
|
|
153
|
+
? v4!.cssSources
|
|
154
|
+
.filter(source => typeof source?.css === 'string')
|
|
155
|
+
.map(source => ({
|
|
156
|
+
css: source.css,
|
|
157
|
+
...(source.base === undefined ? {} : { base: resolveV4Path(source.base) }),
|
|
158
|
+
...(source.file === undefined ? {} : { file: resolveV4Path(source.file) }),
|
|
159
|
+
...(source.dependencies === undefined
|
|
160
|
+
? {}
|
|
161
|
+
: { dependencies: source.dependencies.filter(Boolean).map(resolveV4Path) }),
|
|
162
|
+
}))
|
|
163
|
+
: []
|
|
151
164
|
const cssEntries = Array.isArray(v4?.cssEntries)
|
|
152
165
|
? v4!.cssEntries.filter((entry): entry is string => Boolean(entry)).map(entry => path.resolve(entry))
|
|
153
166
|
: []
|
|
@@ -167,6 +180,7 @@ function normalizeTailwindV4Options(
|
|
|
167
180
|
base,
|
|
168
181
|
...(configuredBase === undefined ? {} : { configuredBase }),
|
|
169
182
|
...(v4?.css === undefined ? {} : { css: v4.css }),
|
|
183
|
+
cssSources,
|
|
170
184
|
cssEntries,
|
|
171
185
|
sources,
|
|
172
186
|
hasUserDefinedSources,
|
package/src/options/types.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { SourceEntry } from '@tailwindcss/oxide'
|
|
2
2
|
import type { PackageResolvingOptions } from 'local-pkg'
|
|
3
3
|
import type { ILengthUnitsPatchOptions } from '../types'
|
|
4
|
+
import type { TailwindV4CssSource } from '../v4/types'
|
|
4
5
|
|
|
5
6
|
export type CacheStrategy = 'merge' | 'overwrite'
|
|
6
7
|
export type CacheDriver = 'file' | 'memory' | 'noop'
|
|
@@ -97,6 +98,8 @@ export interface TailwindV4Options {
|
|
|
97
98
|
base?: string
|
|
98
99
|
/** Raw CSS passed directly to the v4 design system. */
|
|
99
100
|
css?: string
|
|
101
|
+
/** 构建器在 CSS 落盘前捕获的内存 CSS 入口。 */
|
|
102
|
+
cssSources?: TailwindV4CssSource[]
|
|
100
103
|
/** Set of CSS entry files that should be scanned for `@config` directives. */
|
|
101
104
|
cssEntries?: string[]
|
|
102
105
|
/** Overrides the content sources scanned by the oxide scanner. */
|
|
@@ -187,6 +190,7 @@ export interface NormalizedTailwindV4Options {
|
|
|
187
190
|
base: string
|
|
188
191
|
configuredBase?: string
|
|
189
192
|
css?: string
|
|
193
|
+
cssSources: TailwindV4CssSource[]
|
|
190
194
|
cssEntries: string[]
|
|
191
195
|
sources: SourceEntry[]
|
|
192
196
|
hasUserDefinedSources: boolean
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ExtractValidCandidatesOption } from '../extraction/candidate-extractor'
|
|
1
2
|
import type { NormalizedTailwindCssPatchOptions } from '../options/types'
|
|
2
3
|
import type { TailwindcssRuntimeContext } from '../types'
|
|
3
4
|
import process from 'node:process'
|
|
@@ -63,6 +64,35 @@ export async function collectClassesFromTailwindV4(
|
|
|
63
64
|
negated: source.negated,
|
|
64
65
|
}))
|
|
65
66
|
}
|
|
67
|
+
const addCandidates = async (extractOptions: ExtractValidCandidatesOption) => {
|
|
68
|
+
const candidates = await extractValidCandidates(extractOptions)
|
|
69
|
+
for (const candidate of candidates) {
|
|
70
|
+
if (options.filter(candidate)) {
|
|
71
|
+
set.add(candidate)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (v4Options.cssSources.length > 0) {
|
|
77
|
+
for (const source of v4Options.cssSources) {
|
|
78
|
+
const sourceFile = toAbsolute(source.file)
|
|
79
|
+
const sourceBase = toAbsolute(source.base)
|
|
80
|
+
?? (sourceFile ? path.dirname(sourceFile) : resolvedDefaultBase)
|
|
81
|
+
const designSystemBases = resolvedConfiguredBase && resolvedConfiguredBase !== sourceBase
|
|
82
|
+
? [sourceBase, resolvedConfiguredBase]
|
|
83
|
+
: [sourceBase]
|
|
84
|
+
const sources = resolveSources(sourceBase)
|
|
85
|
+
const firstBase = designSystemBases[0] ?? sourceBase
|
|
86
|
+
await addCandidates({
|
|
87
|
+
cwd: options.projectRoot,
|
|
88
|
+
base: firstBase,
|
|
89
|
+
baseFallbacks: designSystemBases.slice(1),
|
|
90
|
+
css: source.css,
|
|
91
|
+
...(v4Options.bareArbitraryValues === undefined ? {} : { bareArbitraryValues: v4Options.bareArbitraryValues }),
|
|
92
|
+
...(sources === undefined ? {} : { sources }),
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
}
|
|
66
96
|
|
|
67
97
|
if (v4Options.cssEntries.length > 0) {
|
|
68
98
|
for (const entry of v4Options.cssEntries) {
|
|
@@ -86,15 +116,10 @@ export async function collectClassesFromTailwindV4(
|
|
|
86
116
|
...(v4Options.bareArbitraryValues === undefined ? {} : { bareArbitraryValues: v4Options.bareArbitraryValues }),
|
|
87
117
|
...(sources === undefined ? {} : { sources }),
|
|
88
118
|
}
|
|
89
|
-
|
|
90
|
-
for (const candidate of candidates) {
|
|
91
|
-
if (options.filter(candidate)) {
|
|
92
|
-
set.add(candidate)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
119
|
+
await addCandidates(extractOptions)
|
|
95
120
|
}
|
|
96
121
|
}
|
|
97
|
-
else {
|
|
122
|
+
else if (v4Options.cssSources.length === 0) {
|
|
98
123
|
const baseForCss = resolvedConfiguredBase ?? resolvedDefaultBase
|
|
99
124
|
const sources = resolveSources(baseForCss)
|
|
100
125
|
const extractOptions = {
|
|
@@ -104,12 +129,7 @@ export async function collectClassesFromTailwindV4(
|
|
|
104
129
|
...(v4Options.css === undefined ? {} : { css: v4Options.css }),
|
|
105
130
|
...(sources === undefined ? {} : { sources }),
|
|
106
131
|
}
|
|
107
|
-
|
|
108
|
-
for (const candidate of candidates) {
|
|
109
|
-
if (options.filter(candidate)) {
|
|
110
|
-
set.add(candidate)
|
|
111
|
-
}
|
|
112
|
-
}
|
|
132
|
+
await addCandidates(extractOptions)
|
|
113
133
|
}
|
|
114
134
|
|
|
115
135
|
return set
|