tailwind-styled-v4 5.1.21 → 5.1.22
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/CHANGELOG.md +182 -0
- package/dist/cli.d.mts +28 -16
- package/dist/cli.d.ts +28 -16
- package/dist/cli.js +357 -77
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +354 -75
- package/dist/cli.mjs.map +1 -1
- package/dist/tw.js +355 -77
- package/dist/tw.js.map +1 -1
- package/dist/tw.mjs +353 -75
- package/dist/tw.mjs.map +1 -1
- package/package.json +1 -1
package/dist/tw.mjs
CHANGED
|
@@ -998,8 +998,8 @@ var require_command = __commonJS({
|
|
|
998
998
|
init_esm_shims();
|
|
999
999
|
var EventEmitter = __require("events").EventEmitter;
|
|
1000
1000
|
var childProcess = __require("child_process");
|
|
1001
|
-
var
|
|
1002
|
-
var
|
|
1001
|
+
var path33 = __require("path");
|
|
1002
|
+
var fs18 = __require("fs");
|
|
1003
1003
|
var process2 = __require("process");
|
|
1004
1004
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
1005
1005
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1931,11 +1931,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1931
1931
|
let launchWithNode = false;
|
|
1932
1932
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1933
1933
|
function findFile(baseDir, baseName) {
|
|
1934
|
-
const localBin =
|
|
1935
|
-
if (
|
|
1936
|
-
if (sourceExt.includes(
|
|
1934
|
+
const localBin = path33.resolve(baseDir, baseName);
|
|
1935
|
+
if (fs18.existsSync(localBin)) return localBin;
|
|
1936
|
+
if (sourceExt.includes(path33.extname(baseName))) return void 0;
|
|
1937
1937
|
const foundExt = sourceExt.find(
|
|
1938
|
-
(ext) =>
|
|
1938
|
+
(ext) => fs18.existsSync(`${localBin}${ext}`)
|
|
1939
1939
|
);
|
|
1940
1940
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1941
1941
|
return void 0;
|
|
@@ -1947,21 +1947,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1947
1947
|
if (this._scriptPath) {
|
|
1948
1948
|
let resolvedScriptPath;
|
|
1949
1949
|
try {
|
|
1950
|
-
resolvedScriptPath =
|
|
1950
|
+
resolvedScriptPath = fs18.realpathSync(this._scriptPath);
|
|
1951
1951
|
} catch (err) {
|
|
1952
1952
|
resolvedScriptPath = this._scriptPath;
|
|
1953
1953
|
}
|
|
1954
|
-
executableDir =
|
|
1955
|
-
|
|
1954
|
+
executableDir = path33.resolve(
|
|
1955
|
+
path33.dirname(resolvedScriptPath),
|
|
1956
1956
|
executableDir
|
|
1957
1957
|
);
|
|
1958
1958
|
}
|
|
1959
1959
|
if (executableDir) {
|
|
1960
1960
|
let localFile = findFile(executableDir, executableFile);
|
|
1961
1961
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
1962
|
-
const legacyName =
|
|
1962
|
+
const legacyName = path33.basename(
|
|
1963
1963
|
this._scriptPath,
|
|
1964
|
-
|
|
1964
|
+
path33.extname(this._scriptPath)
|
|
1965
1965
|
);
|
|
1966
1966
|
if (legacyName !== this._name) {
|
|
1967
1967
|
localFile = findFile(
|
|
@@ -1972,7 +1972,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1972
1972
|
}
|
|
1973
1973
|
executableFile = localFile || executableFile;
|
|
1974
1974
|
}
|
|
1975
|
-
launchWithNode = sourceExt.includes(
|
|
1975
|
+
launchWithNode = sourceExt.includes(path33.extname(executableFile));
|
|
1976
1976
|
let proc;
|
|
1977
1977
|
if (process2.platform !== "win32") {
|
|
1978
1978
|
if (launchWithNode) {
|
|
@@ -2812,7 +2812,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2812
2812
|
* @return {Command}
|
|
2813
2813
|
*/
|
|
2814
2814
|
nameFromFilename(filename) {
|
|
2815
|
-
this._name =
|
|
2815
|
+
this._name = path33.basename(filename, path33.extname(filename));
|
|
2816
2816
|
return this;
|
|
2817
2817
|
}
|
|
2818
2818
|
/**
|
|
@@ -2826,9 +2826,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2826
2826
|
* @param {string} [path]
|
|
2827
2827
|
* @return {(string|null|Command)}
|
|
2828
2828
|
*/
|
|
2829
|
-
executableDir(
|
|
2830
|
-
if (
|
|
2831
|
-
this._executableDir =
|
|
2829
|
+
executableDir(path34) {
|
|
2830
|
+
if (path34 === void 0) return this._executableDir;
|
|
2831
|
+
this._executableDir = path34;
|
|
2832
2832
|
return this;
|
|
2833
2833
|
}
|
|
2834
2834
|
/**
|
|
@@ -3346,9 +3346,9 @@ function createDebugLogger(namespace, label) {
|
|
|
3346
3346
|
}
|
|
3347
3347
|
};
|
|
3348
3348
|
}
|
|
3349
|
-
function formatIssuePath(
|
|
3350
|
-
if (!
|
|
3351
|
-
return
|
|
3349
|
+
function formatIssuePath(path33) {
|
|
3350
|
+
if (!path33 || path33.length === 0) return "(root)";
|
|
3351
|
+
return path33.map(
|
|
3352
3352
|
(segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
|
|
3353
3353
|
).join(".");
|
|
3354
3354
|
}
|
|
@@ -3464,8 +3464,8 @@ var init_src = __esm({
|
|
|
3464
3464
|
/** Buat TwError dari ZodError — dukung shape Zod v3 (`errors`) dan v4 (`issues`). */
|
|
3465
3465
|
static fromZod(err) {
|
|
3466
3466
|
const first = err.issues?.[0] ?? err.errors?.[0];
|
|
3467
|
-
const
|
|
3468
|
-
const message = first ? `${
|
|
3467
|
+
const path33 = formatIssuePath(first?.path);
|
|
3468
|
+
const message = first ? `${path33}: ${first.message}` : "Schema validation failed";
|
|
3469
3469
|
return new _TwError("validation", "SCHEMA_VALIDATION_FAILED", message, err);
|
|
3470
3470
|
}
|
|
3471
3471
|
static wrap(source, code, err) {
|
|
@@ -4021,12 +4021,12 @@ var init_schemas = __esm({
|
|
|
4021
4021
|
"use strict";
|
|
4022
4022
|
init_esm_shims();
|
|
4023
4023
|
init_src();
|
|
4024
|
-
formatIssuePath2 = (
|
|
4024
|
+
formatIssuePath2 = (path33) => path33.length > 0 ? path33.map(
|
|
4025
4025
|
(segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
|
|
4026
4026
|
).join(".") : "<root>";
|
|
4027
4027
|
formatIssues = (error) => error.issues.map((issue) => {
|
|
4028
|
-
const
|
|
4029
|
-
return `${
|
|
4028
|
+
const path33 = formatIssuePath2(issue.path);
|
|
4029
|
+
return `${path33}: ${issue.message}`;
|
|
4030
4030
|
}).join("; ");
|
|
4031
4031
|
parseWithSchema = (schema, data, label) => {
|
|
4032
4032
|
const parsed = schema.safeParse(data);
|
|
@@ -4631,7 +4631,7 @@ var init_schemas2 = __esm({
|
|
|
4631
4631
|
"use strict";
|
|
4632
4632
|
init_esm_shims();
|
|
4633
4633
|
init_src();
|
|
4634
|
-
formatIssuePath3 = (
|
|
4634
|
+
formatIssuePath3 = (path33) => path33.length > 0 ? path33.map(
|
|
4635
4635
|
(segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
|
|
4636
4636
|
).join(".") : "<root>";
|
|
4637
4637
|
isPlainObject = (value) => {
|
|
@@ -4640,8 +4640,8 @@ var init_schemas2 = __esm({
|
|
|
4640
4640
|
return proto === Object.prototype || proto === null;
|
|
4641
4641
|
};
|
|
4642
4642
|
formatIssues2 = (error) => error.issues.map((issue) => {
|
|
4643
|
-
const
|
|
4644
|
-
return `${
|
|
4643
|
+
const path33 = formatIssuePath3(issue.path);
|
|
4644
|
+
return `${path33}: ${issue.message}`;
|
|
4645
4645
|
}).join("; ");
|
|
4646
4646
|
parseWithSchema2 = (schema, data, label) => {
|
|
4647
4647
|
const parsed = schema.safeParse(data);
|
|
@@ -6262,7 +6262,7 @@ var init_nativeBridge = __esm({
|
|
|
6262
6262
|
"use strict";
|
|
6263
6263
|
init_esm_shims();
|
|
6264
6264
|
init_src();
|
|
6265
|
-
_loadNative = (
|
|
6265
|
+
_loadNative = (path33) => __require(path33);
|
|
6266
6266
|
log3 = (...args) => {
|
|
6267
6267
|
if (process.env.DEBUG?.includes("compiler:native")) {
|
|
6268
6268
|
console.log("[compiler:native]", ...args);
|
|
@@ -6405,8 +6405,8 @@ var init_watch = __esm({
|
|
|
6405
6405
|
});
|
|
6406
6406
|
|
|
6407
6407
|
// packages/domain/compiler/src/routeGraph.ts
|
|
6408
|
-
import
|
|
6409
|
-
import
|
|
6408
|
+
import fs13 from "fs";
|
|
6409
|
+
import path26 from "path";
|
|
6410
6410
|
var init_routeGraph = __esm({
|
|
6411
6411
|
"packages/domain/compiler/src/routeGraph.ts"() {
|
|
6412
6412
|
"use strict";
|
|
@@ -6415,8 +6415,8 @@ var init_routeGraph = __esm({
|
|
|
6415
6415
|
});
|
|
6416
6416
|
|
|
6417
6417
|
// packages/domain/compiler/src/index.ts
|
|
6418
|
-
import
|
|
6419
|
-
import
|
|
6418
|
+
import fs14 from "fs";
|
|
6419
|
+
import path27 from "path";
|
|
6420
6420
|
import { createRequire as createRequire4 } from "module";
|
|
6421
6421
|
var _require3, compileCssFromClasses;
|
|
6422
6422
|
var init_src4 = __esm({
|
|
@@ -8737,12 +8737,284 @@ function printDoctorOutput(result, output) {
|
|
|
8737
8737
|
);
|
|
8738
8738
|
}
|
|
8739
8739
|
|
|
8740
|
+
// packages/infrastructure/cli/src/commands/figma.ts
|
|
8741
|
+
init_esm_shims();
|
|
8742
|
+
init_errors();
|
|
8743
|
+
import fs12 from "fs";
|
|
8744
|
+
import path24 from "path";
|
|
8745
|
+
|
|
8746
|
+
// packages/infrastructure/cli/src/utils/figmaApi.ts
|
|
8747
|
+
init_esm_shims();
|
|
8748
|
+
async function figmaRequest(endpoint, options) {
|
|
8749
|
+
const { token, fileKey } = options;
|
|
8750
|
+
if (!token) {
|
|
8751
|
+
throw new Error("FIGMA_TOKEN environment variable not set");
|
|
8752
|
+
}
|
|
8753
|
+
if (!fileKey) {
|
|
8754
|
+
throw new Error("FIGMA_FILE_KEY environment variable not set");
|
|
8755
|
+
}
|
|
8756
|
+
const url = `https://api.figma.com/v1${endpoint.replace(":fileKey", fileKey)}`;
|
|
8757
|
+
const res = await fetch(url, {
|
|
8758
|
+
headers: { "X-Figma-Token": token }
|
|
8759
|
+
});
|
|
8760
|
+
if (!res.ok) {
|
|
8761
|
+
const body = await res.text();
|
|
8762
|
+
throw new Error(`Figma API ${res.status}: ${body.slice(0, 200)}`);
|
|
8763
|
+
}
|
|
8764
|
+
return res.json();
|
|
8765
|
+
}
|
|
8766
|
+
function figmaColorToHex(color) {
|
|
8767
|
+
const { r, g, b, a = 1 } = color;
|
|
8768
|
+
const toHex = (v) => Math.round(v * 255).toString(16).padStart(2, "0");
|
|
8769
|
+
const hex = `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
8770
|
+
return a < 1 ? `${hex}${toHex(a)}` : hex;
|
|
8771
|
+
}
|
|
8772
|
+
function figmaVariablesToTokens(variablesData) {
|
|
8773
|
+
const tokens = {};
|
|
8774
|
+
const { variables = {}, variableCollections = {} } = variablesData;
|
|
8775
|
+
for (const [id, variable] of Object.entries(variables)) {
|
|
8776
|
+
const collection = variableCollections[variable.variableCollectionId];
|
|
8777
|
+
if (!collection) continue;
|
|
8778
|
+
const modeId = Object.keys(variable.valuesByMode)[0];
|
|
8779
|
+
const rawValue = variable.valuesByMode[modeId];
|
|
8780
|
+
if (rawValue === void 0) continue;
|
|
8781
|
+
const parts = variable.name.split("/").map(
|
|
8782
|
+
(p) => p.toLowerCase().replace(/[^a-z0-9]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "")
|
|
8783
|
+
);
|
|
8784
|
+
let cursor = tokens;
|
|
8785
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
8786
|
+
cursor[parts[i]] ??= {};
|
|
8787
|
+
cursor = cursor[parts[i]];
|
|
8788
|
+
}
|
|
8789
|
+
const leafKey = parts[parts.length - 1];
|
|
8790
|
+
if (variable.resolvedType === "COLOR") {
|
|
8791
|
+
cursor[leafKey] = {
|
|
8792
|
+
$value: typeof rawValue === "object" && "r" in rawValue ? figmaColorToHex(rawValue) : String(rawValue),
|
|
8793
|
+
$type: "color",
|
|
8794
|
+
$description: variable.description || void 0,
|
|
8795
|
+
_figmaId: id
|
|
8796
|
+
};
|
|
8797
|
+
} else if (variable.resolvedType === "FLOAT") {
|
|
8798
|
+
cursor[leafKey] = {
|
|
8799
|
+
$value: typeof rawValue === "number" ? `${rawValue}px` : String(rawValue),
|
|
8800
|
+
$type: "dimension",
|
|
8801
|
+
_figmaId: id
|
|
8802
|
+
};
|
|
8803
|
+
} else if (variable.resolvedType === "STRING") {
|
|
8804
|
+
cursor[leafKey] = {
|
|
8805
|
+
$value: String(rawValue),
|
|
8806
|
+
$type: "other",
|
|
8807
|
+
_figmaId: id
|
|
8808
|
+
};
|
|
8809
|
+
}
|
|
8810
|
+
}
|
|
8811
|
+
return tokens;
|
|
8812
|
+
}
|
|
8813
|
+
|
|
8814
|
+
// packages/infrastructure/cli/src/utils/tokenUtils.ts
|
|
8815
|
+
init_esm_shims();
|
|
8816
|
+
function tokensToFigmaUpdates(tokens, existingVariables = {}) {
|
|
8817
|
+
const updates = [];
|
|
8818
|
+
function walk(obj, path33 = []) {
|
|
8819
|
+
for (const [key, val] of Object.entries(obj)) {
|
|
8820
|
+
if (val.$value !== void 0) {
|
|
8821
|
+
const name = path33.concat(key).map(
|
|
8822
|
+
(p) => p.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("")
|
|
8823
|
+
).join("/");
|
|
8824
|
+
const existing = Object.values(existingVariables).find(
|
|
8825
|
+
(v) => v.name === name
|
|
8826
|
+
);
|
|
8827
|
+
if (existing) {
|
|
8828
|
+
updates.push({
|
|
8829
|
+
id: existing.id,
|
|
8830
|
+
name,
|
|
8831
|
+
value: val.$value,
|
|
8832
|
+
type: val.$type
|
|
8833
|
+
});
|
|
8834
|
+
}
|
|
8835
|
+
} else if (typeof val === "object" && !val.$type) {
|
|
8836
|
+
walk(val, path33.concat(key));
|
|
8837
|
+
}
|
|
8838
|
+
}
|
|
8839
|
+
}
|
|
8840
|
+
walk(tokens);
|
|
8841
|
+
return updates;
|
|
8842
|
+
}
|
|
8843
|
+
function flattenTokens(obj, prefix = "", target = {}) {
|
|
8844
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
8845
|
+
const key = [prefix, k].filter(Boolean).join(".");
|
|
8846
|
+
if (v.$value !== void 0) {
|
|
8847
|
+
target[key] = v.$value;
|
|
8848
|
+
} else if (typeof v === "object" && !v.$type) {
|
|
8849
|
+
flattenTokens(v, key, target);
|
|
8850
|
+
}
|
|
8851
|
+
}
|
|
8852
|
+
return target;
|
|
8853
|
+
}
|
|
8854
|
+
function diffTokens(local, figma) {
|
|
8855
|
+
const allKeys = /* @__PURE__ */ new Set([...Object.keys(local), ...Object.keys(figma)]);
|
|
8856
|
+
const diffs = [];
|
|
8857
|
+
for (const key of allKeys) {
|
|
8858
|
+
if (local[key] !== figma[key]) {
|
|
8859
|
+
diffs.push({
|
|
8860
|
+
key,
|
|
8861
|
+
local: local[key],
|
|
8862
|
+
figma: figma[key]
|
|
8863
|
+
});
|
|
8864
|
+
}
|
|
8865
|
+
}
|
|
8866
|
+
return diffs;
|
|
8867
|
+
}
|
|
8868
|
+
|
|
8869
|
+
// packages/infrastructure/cli/src/commands/figma.ts
|
|
8870
|
+
var figmaCommand = {
|
|
8871
|
+
name: "figma",
|
|
8872
|
+
async run(args, context) {
|
|
8873
|
+
const cmd = args[0];
|
|
8874
|
+
const isDryRun = args.includes("--dry-run");
|
|
8875
|
+
const FIGMA_TOKEN = process.env.FIGMA_TOKEN;
|
|
8876
|
+
const FIGMA_FILE_KEY = process.env.FIGMA_FILE_KEY;
|
|
8877
|
+
const TOKEN_FILE = path24.join(context.cwd, "tokens.sync.json");
|
|
8878
|
+
if (!cmd || cmd === "help") {
|
|
8879
|
+
context.output.log(`Usage: tw figma <pull|push|diff> [--dry-run]
|
|
8880
|
+
|
|
8881
|
+
Environment variables:
|
|
8882
|
+
FIGMA_TOKEN \u2014 Figma personal access token (figd_...)
|
|
8883
|
+
FIGMA_FILE_KEY \u2014 Figma file key (from URL: figma.com/file/<KEY>/...)
|
|
8884
|
+
|
|
8885
|
+
Commands:
|
|
8886
|
+
pull Import Figma variables \u2192 tokens.sync.json
|
|
8887
|
+
push Export tokens.sync.json \u2192 Figma variables
|
|
8888
|
+
diff Show differences between local and Figma
|
|
8889
|
+
|
|
8890
|
+
Options:
|
|
8891
|
+
--dry-run Show what would change without writing`);
|
|
8892
|
+
return;
|
|
8893
|
+
}
|
|
8894
|
+
if (cmd === "pull") {
|
|
8895
|
+
if (!FIGMA_TOKEN || !FIGMA_FILE_KEY) {
|
|
8896
|
+
throw new CliUsageError(
|
|
8897
|
+
"Missing FIGMA_TOKEN or FIGMA_FILE_KEY\nSet environment variables and retry\n\nExample:\n export FIGMA_TOKEN=figd_your_token_here\n export FIGMA_FILE_KEY=abc123XYZ"
|
|
8898
|
+
);
|
|
8899
|
+
}
|
|
8900
|
+
try {
|
|
8901
|
+
context.output.status("[figma] Fetching Figma variables...");
|
|
8902
|
+
const data = await figmaRequest("/files/:fileKey/variables/local", {
|
|
8903
|
+
token: FIGMA_TOKEN,
|
|
8904
|
+
fileKey: FIGMA_FILE_KEY
|
|
8905
|
+
});
|
|
8906
|
+
const tokens = figmaVariablesToTokens(data);
|
|
8907
|
+
const variableCount = Object.values(data.variables ?? {}).length;
|
|
8908
|
+
if (isDryRun) {
|
|
8909
|
+
context.output.log("[figma] DRY RUN \u2014 would write:");
|
|
8910
|
+
context.output.log(JSON.stringify({ version: 1, tokens }, null, 2));
|
|
8911
|
+
} else {
|
|
8912
|
+
let existing = { version: 1, tokens: {} };
|
|
8913
|
+
if (fs12.existsSync(TOKEN_FILE)) {
|
|
8914
|
+
try {
|
|
8915
|
+
existing = JSON.parse(fs12.readFileSync(TOKEN_FILE, "utf8"));
|
|
8916
|
+
} catch {
|
|
8917
|
+
}
|
|
8918
|
+
}
|
|
8919
|
+
const merged = {
|
|
8920
|
+
...existing,
|
|
8921
|
+
tokens: { ...existing.tokens, ...tokens },
|
|
8922
|
+
figmaFileKey: FIGMA_FILE_KEY,
|
|
8923
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8924
|
+
source: "figma"
|
|
8925
|
+
};
|
|
8926
|
+
fs12.writeFileSync(TOKEN_FILE, JSON.stringify(merged, null, 2) + "\n");
|
|
8927
|
+
context.output.success(
|
|
8928
|
+
`Pulled ${variableCount} variables from Figma \u2192 ${TOKEN_FILE}`
|
|
8929
|
+
);
|
|
8930
|
+
}
|
|
8931
|
+
} catch (e) {
|
|
8932
|
+
throw new CliUsageError(
|
|
8933
|
+
`Pull failed: ${e instanceof Error ? e.message : String(e)}`
|
|
8934
|
+
);
|
|
8935
|
+
}
|
|
8936
|
+
} else if (cmd === "push") {
|
|
8937
|
+
if (!FIGMA_TOKEN || !FIGMA_FILE_KEY) {
|
|
8938
|
+
throw new CliUsageError("Missing FIGMA_TOKEN or FIGMA_FILE_KEY");
|
|
8939
|
+
}
|
|
8940
|
+
if (!fs12.existsSync(TOKEN_FILE)) {
|
|
8941
|
+
throw new CliUsageError(
|
|
8942
|
+
`${TOKEN_FILE} not found. Run 'tw sync init' first.`
|
|
8943
|
+
);
|
|
8944
|
+
}
|
|
8945
|
+
try {
|
|
8946
|
+
const local = JSON.parse(fs12.readFileSync(TOKEN_FILE, "utf8"));
|
|
8947
|
+
const data = await figmaRequest("/files/:fileKey/variables/local", {
|
|
8948
|
+
token: FIGMA_TOKEN,
|
|
8949
|
+
fileKey: FIGMA_FILE_KEY
|
|
8950
|
+
});
|
|
8951
|
+
const updates = tokensToFigmaUpdates(local.tokens ?? {}, data.variables ?? {});
|
|
8952
|
+
if (isDryRun) {
|
|
8953
|
+
context.output.log(
|
|
8954
|
+
`[figma] DRY RUN \u2014 would update ${updates.length} variables in Figma:`
|
|
8955
|
+
);
|
|
8956
|
+
updates.forEach((u) => context.output.log(` ${u.name}: ${u.value}`));
|
|
8957
|
+
} else {
|
|
8958
|
+
if (updates.length === 0) {
|
|
8959
|
+
context.output.log("[figma] No matching variables to update");
|
|
8960
|
+
} else {
|
|
8961
|
+
context.output.success(`Updated ${updates.length} variables in Figma`);
|
|
8962
|
+
}
|
|
8963
|
+
}
|
|
8964
|
+
} catch (e) {
|
|
8965
|
+
throw new CliUsageError(
|
|
8966
|
+
`Push failed: ${e instanceof Error ? e.message : String(e)}`
|
|
8967
|
+
);
|
|
8968
|
+
}
|
|
8969
|
+
} else if (cmd === "diff") {
|
|
8970
|
+
if (!FIGMA_TOKEN || !FIGMA_FILE_KEY) {
|
|
8971
|
+
throw new CliUsageError("Missing FIGMA_TOKEN or FIGMA_FILE_KEY");
|
|
8972
|
+
}
|
|
8973
|
+
if (!fs12.existsSync(TOKEN_FILE)) {
|
|
8974
|
+
throw new CliUsageError("tokens.sync.json not found");
|
|
8975
|
+
}
|
|
8976
|
+
try {
|
|
8977
|
+
const [local, figmaData] = await Promise.all([
|
|
8978
|
+
JSON.parse(fs12.readFileSync(TOKEN_FILE, "utf8")),
|
|
8979
|
+
figmaRequest("/files/:fileKey/variables/local", {
|
|
8980
|
+
token: FIGMA_TOKEN,
|
|
8981
|
+
fileKey: FIGMA_FILE_KEY
|
|
8982
|
+
})
|
|
8983
|
+
]);
|
|
8984
|
+
const figmaTokens = figmaVariablesToTokens(figmaData);
|
|
8985
|
+
const figmaFlat = {};
|
|
8986
|
+
const localFlat = {};
|
|
8987
|
+
flattenTokens(local.tokens ?? {}, "", localFlat);
|
|
8988
|
+
flattenTokens(figmaTokens, "", figmaFlat);
|
|
8989
|
+
const diffs = diffTokens(localFlat, figmaFlat);
|
|
8990
|
+
if (diffs.length === 0) {
|
|
8991
|
+
context.output.success("No differences \u2014 local and Figma are in sync");
|
|
8992
|
+
} else {
|
|
8993
|
+
context.output.log(`${diffs.length} differences found:
|
|
8994
|
+
`);
|
|
8995
|
+
diffs.forEach((d) => {
|
|
8996
|
+
context.output.log(` ${d.key}`);
|
|
8997
|
+
context.output.log(` local: ${d.local ?? "(missing)"}`);
|
|
8998
|
+
context.output.log(` figma: ${d.figma ?? "(missing)"}`);
|
|
8999
|
+
});
|
|
9000
|
+
}
|
|
9001
|
+
} catch (e) {
|
|
9002
|
+
throw new CliUsageError(
|
|
9003
|
+
`Diff failed: ${e instanceof Error ? e.message : String(e)}`
|
|
9004
|
+
);
|
|
9005
|
+
}
|
|
9006
|
+
} else {
|
|
9007
|
+
throw new CliUsageError(`Unknown command: ${cmd}`);
|
|
9008
|
+
}
|
|
9009
|
+
}
|
|
9010
|
+
};
|
|
9011
|
+
|
|
8740
9012
|
// packages/infrastructure/cli/src/commands/misc.ts
|
|
8741
9013
|
init_esm_shims();
|
|
8742
9014
|
init_errors();
|
|
8743
9015
|
init_fs();
|
|
8744
9016
|
init_json();
|
|
8745
|
-
import
|
|
9017
|
+
import path25 from "path";
|
|
8746
9018
|
import { parseArgs as parseNodeArgs9 } from "util";
|
|
8747
9019
|
var testCommand = {
|
|
8748
9020
|
name: "test",
|
|
@@ -8772,7 +9044,7 @@ var shareCommand = {
|
|
|
8772
9044
|
name: "share",
|
|
8773
9045
|
async run(args, context) {
|
|
8774
9046
|
const name = args.find((arg) => !arg.startsWith("-")) ?? "component-name";
|
|
8775
|
-
const manifestPath =
|
|
9047
|
+
const manifestPath = path25.join(process.cwd(), ".tw-cache", "deploy-manifest.json");
|
|
8776
9048
|
const defaultManifest = {
|
|
8777
9049
|
name,
|
|
8778
9050
|
version: "0.1.0"
|
|
@@ -8858,14 +9130,14 @@ var isVersionOutdated = (currentVersion, latestVersion) => {
|
|
|
8858
9130
|
};
|
|
8859
9131
|
var resolveCurrentCliVersion = async (context) => {
|
|
8860
9132
|
const candidates = [
|
|
8861
|
-
|
|
8862
|
-
|
|
8863
|
-
|
|
9133
|
+
path25.resolve(context.runtimeDir, "..", "package.json"),
|
|
9134
|
+
path25.resolve(process.cwd(), "packages", "cli", "package.json"),
|
|
9135
|
+
path25.resolve(process.cwd(), "package.json")
|
|
8864
9136
|
];
|
|
8865
9137
|
for (const candidate of candidates) {
|
|
8866
9138
|
if (!await pathExists2(candidate)) continue;
|
|
8867
9139
|
const pkg = await readJsonSafe(candidate);
|
|
8868
|
-
const isCliPackage = pkg?.version && (pkg.name === CLI_PACKAGE_NAME || candidate.includes(`${
|
|
9140
|
+
const isCliPackage = pkg?.version && (pkg.name === CLI_PACKAGE_NAME || candidate.includes(`${path25.sep}packages${path25.sep}cli${path25.sep}`));
|
|
8869
9141
|
if (isCliPackage) return pkg.version ?? "0.0.0";
|
|
8870
9142
|
}
|
|
8871
9143
|
return "0.0.0";
|
|
@@ -9113,7 +9385,7 @@ init_errors();
|
|
|
9113
9385
|
init_fs();
|
|
9114
9386
|
init_json();
|
|
9115
9387
|
init_src4();
|
|
9116
|
-
import
|
|
9388
|
+
import path28 from "path";
|
|
9117
9389
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
9118
9390
|
var DEFAULT_TAILWIND_CSS2 = '@import "tailwindcss";\n';
|
|
9119
9391
|
var DEFAULT_TW_CONFIG = `${JSON.stringify(
|
|
@@ -9140,8 +9412,8 @@ async function validateThemeConfig(cwd2) {
|
|
|
9140
9412
|
const twConfigFiles = ["tailwind.config.ts", "tailwind.config.js", "tailwind.config.mjs"];
|
|
9141
9413
|
let configPath = null;
|
|
9142
9414
|
for (const file of twConfigFiles) {
|
|
9143
|
-
if (await pathExists2(
|
|
9144
|
-
configPath =
|
|
9415
|
+
if (await pathExists2(path28.join(cwd2, file))) {
|
|
9416
|
+
configPath = path28.join(cwd2, file);
|
|
9145
9417
|
break;
|
|
9146
9418
|
}
|
|
9147
9419
|
}
|
|
@@ -9232,7 +9504,7 @@ function resolveCliEntry(scriptPath) {
|
|
|
9232
9504
|
async function hasTailwindCssImport(cwd2) {
|
|
9233
9505
|
const cssFiles = ["src/app/globals.css", "src/index.css", "src/style.css", "app/globals.css"];
|
|
9234
9506
|
for (const file of cssFiles) {
|
|
9235
|
-
const raw = await readFileSafe(
|
|
9507
|
+
const raw = await readFileSafe(path28.join(cwd2, file));
|
|
9236
9508
|
if (raw?.includes("tailwindcss")) return true;
|
|
9237
9509
|
}
|
|
9238
9510
|
return false;
|
|
@@ -9248,7 +9520,7 @@ async function hasSafelistSource(cwd2) {
|
|
|
9248
9520
|
"app/globals.css"
|
|
9249
9521
|
];
|
|
9250
9522
|
for (const file of cssFiles) {
|
|
9251
|
-
const raw = await readFileSafe(
|
|
9523
|
+
const raw = await readFileSafe(path28.join(cwd2, file));
|
|
9252
9524
|
if (raw === null) continue;
|
|
9253
9525
|
if (raw.includes("tw-classes")) return { found: true, cssFile: file };
|
|
9254
9526
|
if (raw.includes("tailwindcss")) return { found: false, cssFile: file };
|
|
@@ -9256,8 +9528,8 @@ async function hasSafelistSource(cwd2) {
|
|
|
9256
9528
|
return { found: false, cssFile: null };
|
|
9257
9529
|
}
|
|
9258
9530
|
async function applyTailwindInit(cwd2) {
|
|
9259
|
-
await ensureFileSafe(
|
|
9260
|
-
await ensureFileSafe(
|
|
9531
|
+
await ensureFileSafe(path28.join(cwd2, "src", "tailwind.css"), DEFAULT_TAILWIND_CSS2);
|
|
9532
|
+
await ensureFileSafe(path28.join(cwd2, "tailwind-styled.config.json"), DEFAULT_TW_CONFIG);
|
|
9261
9533
|
}
|
|
9262
9534
|
function check(results, id, label, pass, message, fix) {
|
|
9263
9535
|
results.push({ id, label, pass, message, fix });
|
|
@@ -9279,7 +9551,7 @@ async function runPreflightCli(rawArgs) {
|
|
|
9279
9551
|
node.major >= 20 ? `Node ${node.full} OK` : `Node ${node.full} - requires >=20. Download: https://nodejs.org`,
|
|
9280
9552
|
node.major < 20 ? "Install Node.js 20 LTS or newer from https://nodejs.org" : void 0
|
|
9281
9553
|
);
|
|
9282
|
-
const pkg = await readJsonSafe(
|
|
9554
|
+
const pkg = await readJsonSafe(path28.join(cwd2, "package.json"));
|
|
9283
9555
|
check(
|
|
9284
9556
|
results,
|
|
9285
9557
|
"package-json",
|
|
@@ -9313,7 +9585,7 @@ async function runPreflightCli(rawArgs) {
|
|
|
9313
9585
|
}
|
|
9314
9586
|
const twConfigFiles = ["tailwind.config.ts", "tailwind.config.js", "tailwind.config.mjs"];
|
|
9315
9587
|
const twConfigChecks = await Promise.all(
|
|
9316
|
-
twConfigFiles.map(async (file) => ({ file, exists: await pathExists2(
|
|
9588
|
+
twConfigFiles.map(async (file) => ({ file, exists: await pathExists2(path28.join(cwd2, file)) }))
|
|
9317
9589
|
);
|
|
9318
9590
|
const foundTwConfig = twConfigChecks.find((item) => item.exists)?.file ?? null;
|
|
9319
9591
|
const hasCssConfig = await hasTailwindCssImport(cwd2);
|
|
@@ -9325,7 +9597,7 @@ async function runPreflightCli(rawArgs) {
|
|
|
9325
9597
|
foundTwConfig ? `${foundTwConfig} found OK` : hasCssConfig ? "@import tailwindcss found in CSS OK" : "No Tailwind config found - run: tw init",
|
|
9326
9598
|
"tw init"
|
|
9327
9599
|
);
|
|
9328
|
-
const oldConfig = await readJsonSafe(
|
|
9600
|
+
const oldConfig = await readJsonSafe(path28.join(cwd2, "tailwind.config.js")) ?? await readJsonSafe(path28.join(cwd2, "tailwind.config.ts"));
|
|
9329
9601
|
if (oldConfig) {
|
|
9330
9602
|
const hasOldJit = oldConfig.mode === "jit";
|
|
9331
9603
|
const hasOldPurge = "purge" in oldConfig;
|
|
@@ -9349,7 +9621,7 @@ async function runPreflightCli(rawArgs) {
|
|
|
9349
9621
|
validation.message
|
|
9350
9622
|
);
|
|
9351
9623
|
}
|
|
9352
|
-
const hasTsConfig = await pathExists2(
|
|
9624
|
+
const hasTsConfig = await pathExists2(path28.join(cwd2, "tsconfig.json"));
|
|
9353
9625
|
check(
|
|
9354
9626
|
results,
|
|
9355
9627
|
"typescript",
|
|
@@ -9711,7 +9983,7 @@ init_esm_shims();
|
|
|
9711
9983
|
init_errors();
|
|
9712
9984
|
init_fs();
|
|
9713
9985
|
init_json();
|
|
9714
|
-
import
|
|
9986
|
+
import path29 from "path";
|
|
9715
9987
|
import { parseArgs as parseNodeArgs11 } from "util";
|
|
9716
9988
|
var storybookCommand = {
|
|
9717
9989
|
name: "storybook",
|
|
@@ -9750,7 +10022,7 @@ var storybookCommand = {
|
|
|
9750
10022
|
context.output.writeText(
|
|
9751
10023
|
`[tw storybook] Tip: use --variants='{"size":["sm","lg"]}' to enumerate variant combinations`
|
|
9752
10024
|
);
|
|
9753
|
-
const localBin =
|
|
10025
|
+
const localBin = path29.join(
|
|
9754
10026
|
process.cwd(),
|
|
9755
10027
|
"node_modules",
|
|
9756
10028
|
".bin",
|
|
@@ -10937,10 +11209,10 @@ async function traceClass(className, options) {
|
|
|
10937
11209
|
init_esm_shims();
|
|
10938
11210
|
init_internal();
|
|
10939
11211
|
init_src2();
|
|
10940
|
-
import
|
|
10941
|
-
import
|
|
11212
|
+
import fs15 from "fs";
|
|
11213
|
+
import path30 from "path";
|
|
10942
11214
|
function toRelativePath(root, value) {
|
|
10943
|
-
const relative =
|
|
11215
|
+
const relative = path30.relative(root, value);
|
|
10944
11216
|
return relative.length > 0 ? relative : ".";
|
|
10945
11217
|
}
|
|
10946
11218
|
function uniqueSorted(values) {
|
|
@@ -11009,7 +11281,7 @@ function tryCompileClasses(classes) {
|
|
|
11009
11281
|
}
|
|
11010
11282
|
}
|
|
11011
11283
|
function traceSingleFile(filePath, root) {
|
|
11012
|
-
const source =
|
|
11284
|
+
const source = fs15.readFileSync(filePath, "utf8");
|
|
11013
11285
|
const classes = uniqueSorted(scanSource(source));
|
|
11014
11286
|
const imports = extractImports(source);
|
|
11015
11287
|
const compiled = tryCompileClasses(classes);
|
|
@@ -11040,7 +11312,7 @@ function traceDirectory(targetDir, root) {
|
|
|
11040
11312
|
const imports = [];
|
|
11041
11313
|
const importKeys = /* @__PURE__ */ new Set();
|
|
11042
11314
|
const files = scanResult.files.filter((entry) => isScannableFile2(entry.file, DEFAULT_EXTENSIONS)).map((entry) => {
|
|
11043
|
-
const source =
|
|
11315
|
+
const source = fs15.readFileSync(entry.file, "utf8");
|
|
11044
11316
|
const fileImports = extractImports(source);
|
|
11045
11317
|
for (const fileImport of fileImports) {
|
|
11046
11318
|
const key = `${fileImport.kind}:${fileImport.source}`;
|
|
@@ -11071,12 +11343,12 @@ function traceDirectory(targetDir, root) {
|
|
|
11071
11343
|
};
|
|
11072
11344
|
}
|
|
11073
11345
|
async function traceTarget(target, options = {}) {
|
|
11074
|
-
const root =
|
|
11075
|
-
const resolvedTarget =
|
|
11076
|
-
if (!
|
|
11346
|
+
const root = path30.resolve(options.root ?? process.cwd());
|
|
11347
|
+
const resolvedTarget = path30.resolve(root, target);
|
|
11348
|
+
if (!fs15.existsSync(resolvedTarget)) {
|
|
11077
11349
|
throw new Error(`Trace target not found: ${resolvedTarget}`);
|
|
11078
11350
|
}
|
|
11079
|
-
const stat =
|
|
11351
|
+
const stat = fs15.statSync(resolvedTarget);
|
|
11080
11352
|
if (stat.isDirectory()) {
|
|
11081
11353
|
return traceDirectory(resolvedTarget, root);
|
|
11082
11354
|
}
|
|
@@ -11241,14 +11513,14 @@ function printClassTraceOutput(result, output) {
|
|
|
11241
11513
|
init_esm_shims();
|
|
11242
11514
|
var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
11243
11515
|
init_output();
|
|
11244
|
-
import
|
|
11245
|
-
import
|
|
11516
|
+
import fs16 from "fs";
|
|
11517
|
+
import path31 from "path";
|
|
11246
11518
|
async function runGenerateTypesCli(rawArgs) {
|
|
11247
11519
|
const output = createCliOutput({ json: rawArgs.includes("--json") });
|
|
11248
11520
|
const logger = createCliLogger({ output });
|
|
11249
11521
|
const cwd2 = process.cwd();
|
|
11250
11522
|
const outFile = rawArgs.find((a) => a.startsWith("--out="))?.slice(6) ?? "src/types/tailwind-styled.d.ts";
|
|
11251
|
-
const outPath =
|
|
11523
|
+
const outPath = path31.resolve(cwd2, outFile);
|
|
11252
11524
|
output.writeText("");
|
|
11253
11525
|
output.writeText(import_picocolors6.default.bold(import_picocolors6.default.cyan(" \u25C6 tw generate-types")));
|
|
11254
11526
|
output.writeText(import_picocolors6.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
@@ -11284,12 +11556,12 @@ async function runGenerateTypesCli(rawArgs) {
|
|
|
11284
11556
|
}
|
|
11285
11557
|
output.writeText("");
|
|
11286
11558
|
output.writeText(import_picocolors6.default.bold(" [2/2]") + import_picocolors6.default.cyan(" generate .d.ts"));
|
|
11287
|
-
const outDir =
|
|
11288
|
-
if (!
|
|
11289
|
-
|
|
11559
|
+
const outDir = path31.dirname(outPath);
|
|
11560
|
+
if (!fs16.existsSync(outDir)) {
|
|
11561
|
+
fs16.mkdirSync(outDir, { recursive: true });
|
|
11290
11562
|
}
|
|
11291
|
-
|
|
11292
|
-
logger.ok(
|
|
11563
|
+
fs16.writeFileSync(outPath, result.dtsContent, "utf-8");
|
|
11564
|
+
logger.ok(path31.relative(cwd2, outPath));
|
|
11293
11565
|
output.writeText("");
|
|
11294
11566
|
output.writeText(import_picocolors6.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
11295
11567
|
output.writeText(import_picocolors6.default.bold(import_picocolors6.default.green(" \u2713 types generated")));
|
|
@@ -11300,11 +11572,11 @@ async function runGenerateTypesCli(rawArgs) {
|
|
|
11300
11572
|
}
|
|
11301
11573
|
async function loadNativeBinding2(cwd2) {
|
|
11302
11574
|
const candidates = [
|
|
11303
|
-
|
|
11304
|
-
|
|
11575
|
+
path31.join(cwd2, "native", "tailwind-styled-native.node"),
|
|
11576
|
+
path31.join(cwd2, "node_modules", "tailwind-styled-v4", "native", "tailwind-styled-native.node")
|
|
11305
11577
|
];
|
|
11306
11578
|
for (const candidate of candidates) {
|
|
11307
|
-
if (
|
|
11579
|
+
if (fs16.existsSync(candidate)) {
|
|
11308
11580
|
try {
|
|
11309
11581
|
return __require(candidate);
|
|
11310
11582
|
} catch {
|
|
@@ -11322,8 +11594,8 @@ import { parseArgs as parseNodeArgs14 } from "util";
|
|
|
11322
11594
|
// packages/infrastructure/cli/src/utils/whyService.ts
|
|
11323
11595
|
init_esm_shims();
|
|
11324
11596
|
init_internal();
|
|
11325
|
-
import
|
|
11326
|
-
import
|
|
11597
|
+
import fs17 from "fs";
|
|
11598
|
+
import path32 from "path";
|
|
11327
11599
|
init_src2();
|
|
11328
11600
|
function extractVariantChain(usage) {
|
|
11329
11601
|
const segments = normalizeScannedClass(usage).split(":").filter(Boolean);
|
|
@@ -11371,7 +11643,7 @@ async function whyClass(className, options) {
|
|
|
11371
11643
|
for (const file of scanResult.files) {
|
|
11372
11644
|
const source = (() => {
|
|
11373
11645
|
try {
|
|
11374
|
-
return
|
|
11646
|
+
return fs17.readFileSync(file.file, "utf8");
|
|
11375
11647
|
} catch {
|
|
11376
11648
|
return "";
|
|
11377
11649
|
}
|
|
@@ -11385,7 +11657,7 @@ async function whyClass(className, options) {
|
|
|
11385
11657
|
className
|
|
11386
11658
|
]);
|
|
11387
11659
|
usedIn.push({
|
|
11388
|
-
file:
|
|
11660
|
+
file: path32.relative(root, file.file) || path32.basename(file.file),
|
|
11389
11661
|
line: location.line,
|
|
11390
11662
|
column: location.column,
|
|
11391
11663
|
usage: normalizeScannedClass(fileClass)
|
|
@@ -11692,6 +11964,12 @@ function buildMainProgram(context) {
|
|
|
11692
11964
|
);
|
|
11693
11965
|
});
|
|
11694
11966
|
});
|
|
11967
|
+
const figmaTopLevel = program2.command("figma").description("Figma design token sync");
|
|
11968
|
+
["pull", "push", "diff"].forEach((subcommand) => {
|
|
11969
|
+
figmaTopLevel.command(`${subcommand} [args...]`).description(`Figma ${subcommand}`).allowUnknownOption(true).action(async (args) => {
|
|
11970
|
+
await figmaCommand.run(contextArgs([subcommand, ...toVariadic(args)], context), context);
|
|
11971
|
+
});
|
|
11972
|
+
});
|
|
11695
11973
|
program2.command("test").description("Test shortcut wrapper").option("--watch", "Watch mode").action(async (...actionArgs) => {
|
|
11696
11974
|
const options = actionCommand(actionArgs).opts();
|
|
11697
11975
|
const args = [];
|