digdesign 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +218 -141
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2054,9 +2054,178 @@ async function impactCommand(name, options) {
|
|
|
2054
2054
|
}
|
|
2055
2055
|
}
|
|
2056
2056
|
|
|
2057
|
+
// src/commands/review.ts
|
|
2058
|
+
import { readFile as readFile8 } from "fs/promises";
|
|
2059
|
+
import path11 from "path";
|
|
2060
|
+
|
|
2061
|
+
// src/lib/version.ts
|
|
2062
|
+
var CLI_VERSION = "0.7.0";
|
|
2063
|
+
|
|
2064
|
+
// src/commands/mcp.ts
|
|
2065
|
+
import { createInterface as createInterface2 } from "readline";
|
|
2066
|
+
var DEFAULT_MCP_URL = "https://docs.digdesign.ir/api/mcp";
|
|
2067
|
+
function parseSse(body) {
|
|
2068
|
+
const messages = [];
|
|
2069
|
+
for (const event of body.split(/\r?\n\r?\n/)) {
|
|
2070
|
+
const data = event.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).replace(/^ /, "")).join("\n");
|
|
2071
|
+
if (!data) continue;
|
|
2072
|
+
try {
|
|
2073
|
+
messages.push(JSON.parse(data));
|
|
2074
|
+
} catch {
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
return messages;
|
|
2078
|
+
}
|
|
2079
|
+
function requestIds(message) {
|
|
2080
|
+
const list = Array.isArray(message) ? message : [message];
|
|
2081
|
+
return list.filter((item) => typeof item === "object" && item !== null).filter((item) => item.method !== void 0 && item.id !== void 0 && item.id !== null).map((item) => item.id);
|
|
2082
|
+
}
|
|
2083
|
+
function createBridge(url, fetchImpl = fetch) {
|
|
2084
|
+
let sessionId;
|
|
2085
|
+
let protocolVersion;
|
|
2086
|
+
return {
|
|
2087
|
+
async handle(line) {
|
|
2088
|
+
let message;
|
|
2089
|
+
try {
|
|
2090
|
+
message = JSON.parse(line);
|
|
2091
|
+
} catch {
|
|
2092
|
+
return [{ jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error" } }];
|
|
2093
|
+
}
|
|
2094
|
+
const ids = requestIds(message);
|
|
2095
|
+
const fail = (reason) => ids.map((id) => ({ jsonrpc: "2.0", id, error: { code: -32603, message: `Dig MCP (${url}): ${reason}` } }));
|
|
2096
|
+
let response;
|
|
2097
|
+
try {
|
|
2098
|
+
response = await fetchImpl(url, {
|
|
2099
|
+
method: "POST",
|
|
2100
|
+
headers: {
|
|
2101
|
+
"content-type": "application/json",
|
|
2102
|
+
accept: "application/json, text/event-stream",
|
|
2103
|
+
"user-agent": `digdesign-cli/${CLI_VERSION}`,
|
|
2104
|
+
...sessionId && { "mcp-session-id": sessionId },
|
|
2105
|
+
...protocolVersion && { "mcp-protocol-version": protocolVersion }
|
|
2106
|
+
},
|
|
2107
|
+
body: line
|
|
2108
|
+
});
|
|
2109
|
+
} catch (error) {
|
|
2110
|
+
return fail(`network error: ${error.message}`);
|
|
2111
|
+
}
|
|
2112
|
+
sessionId = response.headers.get("mcp-session-id") ?? sessionId;
|
|
2113
|
+
if (response.status === 202) return [];
|
|
2114
|
+
const body = await response.text();
|
|
2115
|
+
if (!response.ok) return fail(`HTTP ${response.status} ${body.slice(0, 200)}`);
|
|
2116
|
+
let replies;
|
|
2117
|
+
if ((response.headers.get("content-type") ?? "").includes("text/event-stream")) replies = parseSse(body);
|
|
2118
|
+
else {
|
|
2119
|
+
try {
|
|
2120
|
+
replies = body.trim() ? [JSON.parse(body)] : [];
|
|
2121
|
+
} catch {
|
|
2122
|
+
return fail(`invalid JSON response: ${body.slice(0, 200)}`);
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
for (const reply of replies.flat()) {
|
|
2126
|
+
const result = reply?.result;
|
|
2127
|
+
if (result?.protocolVersion) protocolVersion = result.protocolVersion;
|
|
2128
|
+
}
|
|
2129
|
+
return replies;
|
|
2130
|
+
}
|
|
2131
|
+
};
|
|
2132
|
+
}
|
|
2133
|
+
async function mcpCommand(options) {
|
|
2134
|
+
const url = options.url ?? process.env.DIG_MCP_URL ?? DEFAULT_MCP_URL;
|
|
2135
|
+
const bridge = createBridge(url);
|
|
2136
|
+
const pending = /* @__PURE__ */ new Set();
|
|
2137
|
+
process.stderr.write(`dig mcp: stdio bridge to ${url}
|
|
2138
|
+
`);
|
|
2139
|
+
const input = createInterface2({ input: process.stdin, crlfDelay: Infinity });
|
|
2140
|
+
for await (const line of input) {
|
|
2141
|
+
if (!line.trim()) continue;
|
|
2142
|
+
const task = bridge.handle(line).then((replies) => {
|
|
2143
|
+
for (const reply of replies) process.stdout.write(`${JSON.stringify(reply)}
|
|
2144
|
+
`);
|
|
2145
|
+
});
|
|
2146
|
+
pending.add(task);
|
|
2147
|
+
void task.finally(() => pending.delete(task));
|
|
2148
|
+
}
|
|
2149
|
+
await Promise.all(pending);
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
// src/commands/review.ts
|
|
2153
|
+
var MAX_FILE_CHARS = 2e5;
|
|
2154
|
+
var MAX_FILES_PER_CALL = 25;
|
|
2155
|
+
async function readReviewFiles(paths, cwd) {
|
|
2156
|
+
const files = [];
|
|
2157
|
+
for (const input of paths) {
|
|
2158
|
+
const absolute = path11.resolve(cwd, input);
|
|
2159
|
+
let code;
|
|
2160
|
+
try {
|
|
2161
|
+
code = await readFile8(absolute, "utf8");
|
|
2162
|
+
} catch {
|
|
2163
|
+
throw new DigError(`\u0641\u0627\u06CC\u0644 \u062E\u0648\u0627\u0646\u062F\u0647 \u0646\u0634\u062F: ${input}`);
|
|
2164
|
+
}
|
|
2165
|
+
if (code.length > MAX_FILE_CHARS) throw new DigError(`${input} \u0628\u0632\u0631\u06AF\u200C\u062A\u0631 \u0627\u0632 ${MAX_FILE_CHARS} \u0646\u0648\u06CC\u0633\u0647 \u0627\u0633\u062A\u061B \u0628\u0647 \u0641\u0627\u06CC\u0644\u200C\u0647\u0627\u06CC \u06A9\u0648\u0686\u06A9\u200C\u062A\u0631 \u0628\u0634\u06A9\u0646.`);
|
|
2166
|
+
files.push({ path: path11.relative(cwd, absolute) || input, code });
|
|
2167
|
+
}
|
|
2168
|
+
return files;
|
|
2169
|
+
}
|
|
2170
|
+
async function callReview(url, files, fetchImpl = fetch) {
|
|
2171
|
+
let response;
|
|
2172
|
+
try {
|
|
2173
|
+
response = await fetchImpl(url, {
|
|
2174
|
+
method: "POST",
|
|
2175
|
+
headers: {
|
|
2176
|
+
"content-type": "application/json",
|
|
2177
|
+
accept: "application/json, text/event-stream",
|
|
2178
|
+
"user-agent": `digdesign-cli/${CLI_VERSION}`
|
|
2179
|
+
},
|
|
2180
|
+
body: JSON.stringify({
|
|
2181
|
+
jsonrpc: "2.0",
|
|
2182
|
+
id: 1,
|
|
2183
|
+
method: "tools/call",
|
|
2184
|
+
params: { name: "review_code", arguments: { files } }
|
|
2185
|
+
})
|
|
2186
|
+
});
|
|
2187
|
+
} catch (error) {
|
|
2188
|
+
throw new DigError(`\u0627\u062A\u0635\u0627\u0644 \u0628\u0647 ${url} \u0628\u0631\u0642\u0631\u0627\u0631 \u0646\u0634\u062F: ${error.message}`);
|
|
2189
|
+
}
|
|
2190
|
+
const body = await response.text();
|
|
2191
|
+
if (!response.ok) throw new DigError(`\u0628\u0627\u0632\u0628\u06CC\u0646\u06CC \u0634\u06A9\u0633\u062A \u062E\u0648\u0631\u062F (HTTP ${response.status}).`);
|
|
2192
|
+
const message = (response.headers.get("content-type") ?? "").includes("text/event-stream") ? parseSse(body)[0] : JSON.parse(body);
|
|
2193
|
+
const text = message?.result?.content?.[0]?.text;
|
|
2194
|
+
if (!text) throw new DigError("\u067E\u0627\u0633\u062E\u0650 \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0632 \u0633\u0631\u0648\u0631 MCP.");
|
|
2195
|
+
return JSON.parse(text);
|
|
2196
|
+
}
|
|
2197
|
+
async function reviewCommand(paths, options) {
|
|
2198
|
+
if (paths.length === 0) throw new DigError("\u062D\u062F\u0627\u0642\u0644 \u06CC\u06A9 \u0645\u0633\u06CC\u0631 \u0641\u0627\u06CC\u0644 \u0628\u062F\u0647: dig review src/app/page.tsx");
|
|
2199
|
+
const url = options.url ?? process.env.DIG_MCP_URL ?? DEFAULT_MCP_URL;
|
|
2200
|
+
const files = await readReviewFiles(paths, process.cwd());
|
|
2201
|
+
const merged = [];
|
|
2202
|
+
const reviewed = [];
|
|
2203
|
+
for (let i = 0; i < files.length; i += MAX_FILES_PER_CALL) {
|
|
2204
|
+
const result = await callReview(url, files.slice(i, i + MAX_FILES_PER_CALL));
|
|
2205
|
+
if (result.status === "invalid_input") throw new DigError(result.message ?? "\u0648\u0631\u0648\u062F\u06CC\u0650 \u0628\u0627\u0632\u0628\u06CC\u0646\u06CC \u0646\u0627\u0645\u0639\u062A\u0628\u0631 \u0627\u0633\u062A.");
|
|
2206
|
+
merged.push(...result.findings ?? []);
|
|
2207
|
+
reviewed.push(...result.reviewed ?? []);
|
|
2208
|
+
}
|
|
2209
|
+
const errors = merged.filter((finding) => finding.severity !== "warning").length;
|
|
2210
|
+
const status = errors > 0 ? "issues" : merged.length > 0 ? "warnings" : "ok";
|
|
2211
|
+
if (options.json) {
|
|
2212
|
+
console.log(JSON.stringify({ status, findings: merged, reviewed }, null, 2));
|
|
2213
|
+
} else {
|
|
2214
|
+
for (const finding of merged) {
|
|
2215
|
+
const where = `${finding.file ?? ""}:${finding.line}`;
|
|
2216
|
+
console.log(`${where} [${finding.severity ?? "error"}] ${finding.rule}
|
|
2217
|
+
${finding.found}
|
|
2218
|
+
\u2190 ${finding.fix}`);
|
|
2219
|
+
}
|
|
2220
|
+
const lines = reviewed.reduce((sum, file) => sum + file.lines, 0);
|
|
2221
|
+
console.log(merged.length === 0 ? `\u062A\u062E\u0644\u0641\u06CC \u067E\u06CC\u062F\u0627 \u0646\u0634\u062F (${files.length} \u0641\u0627\u06CC\u0644\u060C ${lines} \u062E\u0637).` : `${merged.length} \u06CC\u0627\u0641\u062A\u0647 \u062F\u0631 ${files.length} \u0641\u0627\u06CC\u0644 (${lines} \u062E\u0637).`);
|
|
2222
|
+
}
|
|
2223
|
+
if (errors > 0) process.exitCode = 1;
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2057
2226
|
// src/commands/skill.ts
|
|
2058
2227
|
import { mkdir as mkdir4, writeFile as writeFile6 } from "fs/promises";
|
|
2059
|
-
import
|
|
2228
|
+
import path12 from "path";
|
|
2060
2229
|
var SKILL_PATH = ".claude/skills/dig-design-system/SKILL.md";
|
|
2061
2230
|
async function skillCommand() {
|
|
2062
2231
|
const cwd = process.cwd();
|
|
@@ -2069,21 +2238,21 @@ async function skillCommand() {
|
|
|
2069
2238
|
throw new DigError(`\u0627\u062A\u0635\u0627\u0644 \u0628\u0647 ${url.origin} \u0628\u0631\u0627\u06CC \u06AF\u0631\u0641\u062A\u0646\u0650 Skill \u0628\u0631\u0642\u0631\u0627\u0631 \u0646\u0634\u062F.`);
|
|
2070
2239
|
}
|
|
2071
2240
|
if (!response.ok) throw new DigError(`Skill \u06AF\u0631\u0641\u062A\u0647 \u0646\u0634\u062F: ${response.status}`);
|
|
2072
|
-
const target =
|
|
2073
|
-
await mkdir4(
|
|
2241
|
+
const target = path12.join(cwd, SKILL_PATH);
|
|
2242
|
+
await mkdir4(path12.dirname(target), { recursive: true });
|
|
2074
2243
|
await writeFile6(target, await response.text(), "utf8");
|
|
2075
2244
|
console.log(`\u2713 ${SKILL_PATH} \u0646\u0648\u0634\u062A\u0647 \u0634\u062F (Skill\u0650 \u0631\u0633\u0645\u06CC\u0650 \u062F\u06CC\u06AF \u0628\u0631\u0627\u06CC Claude Code).`);
|
|
2076
2245
|
}
|
|
2077
2246
|
|
|
2078
2247
|
// src/commands/tokens.ts
|
|
2079
|
-
import { mkdir as mkdir5, readFile as
|
|
2080
|
-
import
|
|
2248
|
+
import { mkdir as mkdir5, readFile as readFile9, writeFile as writeFile7 } from "fs/promises";
|
|
2249
|
+
import path13 from "path";
|
|
2081
2250
|
async function tokensCommand(options) {
|
|
2082
2251
|
const cwd = process.cwd();
|
|
2083
2252
|
const registryUrl = await configExists(cwd) ? (await readConfig(cwd)).registryUrl : defaultConfig().registryUrl;
|
|
2084
|
-
const designMd = await
|
|
2253
|
+
const designMd = await readFile9(path13.join(cwd, DESIGN_MD_FILE), "utf8").catch(() => "");
|
|
2085
2254
|
const brand = options.brand ?? readDesignMdSettings(designMd).brand;
|
|
2086
|
-
const outDir =
|
|
2255
|
+
const outDir = path13.join(cwd, options.out ?? "tokens");
|
|
2087
2256
|
await mkdir5(outDir, { recursive: true });
|
|
2088
2257
|
for (const mode of ["light", "dark"]) {
|
|
2089
2258
|
const url = new URL("/api/tokens", registryUrl);
|
|
@@ -2099,20 +2268,20 @@ async function tokensCommand(options) {
|
|
|
2099
2268
|
const body = await response.json().catch(() => null);
|
|
2100
2269
|
throw new DigError(`\u062A\u0648\u06A9\u0646\u200C\u0647\u0627 \u06AF\u0631\u0641\u062A\u0647 \u0646\u0634\u062F: ${body?.error ?? response.status}`);
|
|
2101
2270
|
}
|
|
2102
|
-
const file =
|
|
2271
|
+
const file = path13.join(outDir, `dig-${mode}.tokens.json`);
|
|
2103
2272
|
await writeFile7(file, await response.text(), "utf8");
|
|
2104
|
-
console.log(`\u2713 ${
|
|
2273
|
+
console.log(`\u2713 ${path13.relative(cwd, file)} \u0646\u0648\u0634\u062A\u0647 \u0634\u062F${brand ? ` (\u0628\u0631\u0646\u062F ${brand})` : ""}.`);
|
|
2105
2274
|
}
|
|
2106
2275
|
console.log("\n\u062F\u0631 \u0641\u06CC\u06AF\u0645\u0627 \u0647\u0631 \u0641\u0627\u06CC\u0644 \u0631\u0627 \u06CC\u06A9 mode \u0627\u0632 Variables \u0648\u0627\u0631\u062F \u06A9\u0646\u06CC\u062F (\u0631\u0648\u0634\u0646 \u0648 \u062A\u06CC\u0631\u0647).");
|
|
2107
2276
|
}
|
|
2108
2277
|
|
|
2109
2278
|
// src/commands/init.ts
|
|
2110
|
-
import { readFile as
|
|
2111
|
-
import
|
|
2279
|
+
import { readFile as readFile12, writeFile as writeFile10 } from "fs/promises";
|
|
2280
|
+
import path17 from "path";
|
|
2112
2281
|
|
|
2113
2282
|
// src/lib/agent-instructions.ts
|
|
2114
|
-
import { mkdir as mkdir6, readFile as
|
|
2115
|
-
import
|
|
2283
|
+
import { mkdir as mkdir6, readFile as readFile10, writeFile as writeFile8 } from "fs/promises";
|
|
2284
|
+
import path14 from "path";
|
|
2116
2285
|
var AGENT_CLIENTS = [
|
|
2117
2286
|
{ value: "claude-code", label: "Claude Code (CLAUDE.md)" },
|
|
2118
2287
|
{ value: "codex", label: "Codex (AGENTS.md)" },
|
|
@@ -2164,16 +2333,16 @@ async function writeAgentInstructions(cwd, registryUrl, options) {
|
|
|
2164
2333
|
const files = await fetchSetupFiles(registryUrl, options);
|
|
2165
2334
|
const instructions = files.find((item) => /^[A-Z]+\.md$/.test(item.path) && item.path !== "DESIGN.md");
|
|
2166
2335
|
if (!instructions) throw new DigError("\u0641\u0627\u06CC\u0644\u0650 \u0627\u06CC\u062C\u0646\u062A \u062F\u0631 \u067E\u0627\u0633\u062E\u0650 \u0633\u0631\u0648\u0631 \u0646\u0628\u0648\u062F.");
|
|
2167
|
-
const target =
|
|
2168
|
-
const existing = await
|
|
2336
|
+
const target = path14.join(cwd, instructions.path);
|
|
2337
|
+
const existing = await readFile10(target, "utf8").catch(() => null);
|
|
2169
2338
|
await writeFile8(target, mergeInstructions(existing, instructions.content), "utf8");
|
|
2170
2339
|
console.log(
|
|
2171
2340
|
existing === null ? `\u2713 ${instructions.path} \u0646\u0648\u0634\u062A\u0647 \u0634\u062F (\u0627\u06CC\u062C\u0646\u062A \u0641\u0648\u0646\u062A \u0648 \u0631\u0646\u06AF \u0631\u0627 \u0627\u0632 \u0627\u06CC\u0646 \u0641\u0627\u06CC\u0644 \u0645\u06CC\u200C\u062E\u0648\u0627\u0646\u062F \u0648 \u062F\u0648\u0628\u0627\u0631\u0647 \u0646\u0645\u06CC\u200C\u067E\u0631\u0633\u062F).` : `\u2713 \u0628\u062E\u0634\u0650 \u062F\u06CC\u06AF \u062F\u0631 ${instructions.path} \u0628\u0647\u200C\u0631\u0648\u0632 \u0634\u062F\u061B \u0628\u0642\u06CC\u0647\u0654 \u0641\u0627\u06CC\u0644 \u062F\u0633\u062A \u0646\u062E\u0648\u0631\u062F.`
|
|
2172
2341
|
);
|
|
2173
2342
|
const skill = files.find((item) => item.path.endsWith("/SKILL.md"));
|
|
2174
2343
|
if (skill) {
|
|
2175
|
-
const skillTarget =
|
|
2176
|
-
await mkdir6(
|
|
2344
|
+
const skillTarget = path14.join(cwd, skill.path);
|
|
2345
|
+
await mkdir6(path14.dirname(skillTarget), { recursive: true });
|
|
2177
2346
|
await writeFile8(skillTarget, skill.content, "utf8");
|
|
2178
2347
|
console.log(`\u2713 ${skill.path} \u0646\u0648\u0634\u062A\u0647 \u0634\u062F (Skill\u0650 \u0631\u0633\u0645\u06CC\u0650 \u062F\u06CC\u06AF \u0628\u0631\u0627\u06CC \u0633\u0627\u062E\u062A\u0646\u0650 \u0635\u0641\u062D\u0647).`);
|
|
2179
2348
|
}
|
|
@@ -2181,8 +2350,8 @@ async function writeAgentInstructions(cwd, registryUrl, options) {
|
|
|
2181
2350
|
}
|
|
2182
2351
|
|
|
2183
2352
|
// src/commands/theme.ts
|
|
2184
|
-
import { access as access5, mkdir as mkdir7, readFile as
|
|
2185
|
-
import
|
|
2353
|
+
import { access as access5, mkdir as mkdir7, readFile as readFile11, writeFile as writeFile9 } from "fs/promises";
|
|
2354
|
+
import path16 from "path";
|
|
2186
2355
|
|
|
2187
2356
|
// src/lib/brand-ramp.ts
|
|
2188
2357
|
var RAMP_STEPS = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
|
|
@@ -2286,9 +2455,9 @@ function buildBrandRamp(hex) {
|
|
|
2286
2455
|
}
|
|
2287
2456
|
|
|
2288
2457
|
// src/lib/theme-files.ts
|
|
2289
|
-
import
|
|
2458
|
+
import path15 from "path";
|
|
2290
2459
|
function importPath(fromFile, toFile) {
|
|
2291
|
-
const rel = toPosixPath(
|
|
2460
|
+
const rel = toPosixPath(path15.relative(path15.dirname(fromFile), toFile));
|
|
2292
2461
|
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
2293
2462
|
}
|
|
2294
2463
|
function globalsCss(paths, extraStatements = []) {
|
|
@@ -2453,7 +2622,7 @@ function splitTheme(projectCss, digThemeCss) {
|
|
|
2453
2622
|
var THEME_ITEM = "theme";
|
|
2454
2623
|
async function readIfExists2(target) {
|
|
2455
2624
|
try {
|
|
2456
|
-
return await
|
|
2625
|
+
return await readFile11(target, "utf8");
|
|
2457
2626
|
} catch {
|
|
2458
2627
|
return null;
|
|
2459
2628
|
}
|
|
@@ -2467,7 +2636,7 @@ async function exists(target) {
|
|
|
2467
2636
|
}
|
|
2468
2637
|
}
|
|
2469
2638
|
function themePaths(config) {
|
|
2470
|
-
const dir =
|
|
2639
|
+
const dir = path16.posix.dirname(toPosixPath(config.tailwind.css));
|
|
2471
2640
|
return {
|
|
2472
2641
|
css: config.tailwind.css,
|
|
2473
2642
|
theme: config.tailwind.theme ?? `${dir}/dig-theme.css`,
|
|
@@ -2501,8 +2670,8 @@ async function recordTheme(cwd, config, themeRel, item) {
|
|
|
2501
2670
|
await writeLock(lock, cwd);
|
|
2502
2671
|
}
|
|
2503
2672
|
async function writeText(cwd, rel, content) {
|
|
2504
|
-
const target =
|
|
2505
|
-
await mkdir7(
|
|
2673
|
+
const target = path16.join(cwd, rel);
|
|
2674
|
+
await mkdir7(path16.dirname(target), { recursive: true });
|
|
2506
2675
|
await writeFile9(target, content, "utf8");
|
|
2507
2676
|
}
|
|
2508
2677
|
async function installTheme(cwd, config, options) {
|
|
@@ -2511,7 +2680,7 @@ async function installTheme(cwd, config, options) {
|
|
|
2511
2680
|
const ramp = options.brand ? buildBrandRamp(options.brand) : void 0;
|
|
2512
2681
|
await writeText(cwd, paths.theme, item.content);
|
|
2513
2682
|
console.log(`\u2713 \u062A\u0645\u0650 \u062F\u06CC\u06AF \u062F\u0631 ${paths.theme} \u0646\u0648\u0634\u062A\u0647 \u0634\u062F (\u0645\u0627\u0644\u0650 \u062F\u06CC\u06AF\u061B \u0628\u0627 \xABdig update theme\xBB \u0628\u0647\u200C\u0631\u0648\u0632 \u0645\u06CC\u200C\u0634\u0648\u062F).`);
|
|
2514
|
-
const existingBrand = await readIfExists2(
|
|
2683
|
+
const existingBrand = await readIfExists2(path16.join(cwd, paths.brand));
|
|
2515
2684
|
if (existingBrand === null) {
|
|
2516
2685
|
await writeText(cwd, paths.brand, brandCss({ ramp, hex: options.brand }));
|
|
2517
2686
|
console.log(`\u2713 ${paths.brand} \u0633\u0627\u062E\u062A\u0647 \u0634\u062F (\u0645\u0627\u0644\u0650 \u067E\u0631\u0648\u0698\u0647\u061B \u062F\u06CC\u06AF \u0647\u0631\u06AF\u0632 \u0628\u0627\u0632\u0646\u0648\u06CC\u0633\u06CC\u200C\u0627\u0634 \u0646\u0645\u06CC\u200C\u06A9\u0646\u062F).`);
|
|
@@ -2522,7 +2691,7 @@ async function installTheme(cwd, config, options) {
|
|
|
2522
2691
|
console.log(`- ${paths.brand} \u0627\u0632 \u0642\u0628\u0644 \u0647\u0633\u062A\u061B \u062F\u0633\u062A \u0646\u062E\u0648\u0631\u062F.`);
|
|
2523
2692
|
}
|
|
2524
2693
|
if (ramp) reportContrast(ramp.primaryContrast);
|
|
2525
|
-
const cssTarget =
|
|
2694
|
+
const cssTarget = path16.join(cwd, paths.css);
|
|
2526
2695
|
const existingCss = await readIfExists2(cssTarget);
|
|
2527
2696
|
if (!isBoilerplateCss(existingCss) && existingCss !== null) {
|
|
2528
2697
|
await writeFile9(`${cssTarget}.backup`, existingCss, "utf8");
|
|
@@ -2558,11 +2727,11 @@ async function themeSplitCommand(options) {
|
|
|
2558
2727
|
return;
|
|
2559
2728
|
}
|
|
2560
2729
|
const paths = themePaths(config);
|
|
2561
|
-
const current = await readIfExists2(
|
|
2730
|
+
const current = await readIfExists2(path16.join(cwd, paths.css));
|
|
2562
2731
|
if (current === null || isBoilerplateCss(current)) {
|
|
2563
2732
|
throw new DigError(`${paths.css} \u062A\u0645\u06CC \u0646\u062F\u0627\u0631\u062F\u061B \u0628\u0631\u0627\u06CC \u0646\u0635\u0628\u0650 \u062A\u0627\u0632\u0647 \xABdig init\xBB \u0631\u0627 \u0627\u062C\u0631\u0627 \u06A9\u0646\u06CC\u062F.`);
|
|
2564
2733
|
}
|
|
2565
|
-
if (await exists(
|
|
2734
|
+
if (await exists(path16.join(cwd, paths.brand))) {
|
|
2566
2735
|
throw new DigError(`${paths.brand} \u0627\u0632 \u0642\u0628\u0644 \u0648\u062C\u0648\u062F \u062F\u0627\u0631\u062F\u061B \u0628\u0631\u0627\u06CC \u062C\u0644\u0648\u06AF\u06CC\u0631\u06CC \u0627\u0632 \u0628\u0627\u0632\u0646\u0648\u06CC\u0633\u06CC\u060C \u0627\u0648\u0644 \u062C\u0627\u0628\u0647\u200C\u062C\u0627\u06CC\u0634 \u06A9\u0646\u06CC\u062F.`);
|
|
2567
2736
|
}
|
|
2568
2737
|
console.log(`\u062F\u0631\u06CC\u0627\u0641\u062A\u0650 \u062A\u0645\u0650 \u062F\u06CC\u06AF \u0627\u0632 ${config.registryUrl} \u2026`);
|
|
@@ -2581,7 +2750,7 @@ ${split.changed} \u062A\u0648\u06A9\u0646\u0650 \u0639\u0648\u0636\u200C\u0634\u
|
|
|
2581
2750
|
console.log(split.body || "(\u062E\u0627\u0644\u06CC: \u067E\u0631\u0648\u0698\u0647 \u0686\u06CC\u0632\u06CC \u062F\u0631 \u062A\u0645 \u0639\u0648\u0636 \u0646\u06A9\u0631\u062F\u0647)");
|
|
2582
2751
|
return;
|
|
2583
2752
|
}
|
|
2584
|
-
await writeFile9(
|
|
2753
|
+
await writeFile9(path16.join(cwd, `${paths.css}.backup`), current, "utf8");
|
|
2585
2754
|
await writeText(cwd, paths.theme, item.content);
|
|
2586
2755
|
await writeText(cwd, paths.brand, brandCss({ body: split.body }));
|
|
2587
2756
|
await writeText(cwd, paths.css, globalsCss(paths, split.extraStatements));
|
|
@@ -2605,7 +2774,7 @@ async function themeBrandCommand(hex) {
|
|
|
2605
2774
|
}
|
|
2606
2775
|
const paths = themePaths(config);
|
|
2607
2776
|
const ramp = buildBrandRamp(hex);
|
|
2608
|
-
const existing = await readIfExists2(
|
|
2777
|
+
const existing = await readIfExists2(path16.join(cwd, paths.brand)) ?? brandCss({});
|
|
2609
2778
|
const next = replaceBrandRamp(existing, ramp, hex);
|
|
2610
2779
|
await writeText(cwd, paths.brand, next);
|
|
2611
2780
|
console.log(`\u2713 \u0631\u0645\u067E\u0650 \u0628\u0631\u0646\u062F \u062F\u0631 ${paths.brand} \u0627\u0632 ${hex} \u0633\u0627\u062E\u062A\u0647 \u0634\u062F (Shade \u06F6\u06F0\u06F0 = \u0631\u0646\u06AF\u0650 \u062F\u0627\u062F\u0647\u200C\u0634\u062F\u0647).`);
|
|
@@ -2623,14 +2792,14 @@ async function themeBrandCommand(hex) {
|
|
|
2623
2792
|
// src/commands/init.ts
|
|
2624
2793
|
async function readIfExists3(target) {
|
|
2625
2794
|
try {
|
|
2626
|
-
return await
|
|
2795
|
+
return await readFile12(target, "utf8");
|
|
2627
2796
|
} catch {
|
|
2628
2797
|
return null;
|
|
2629
2798
|
}
|
|
2630
2799
|
}
|
|
2631
2800
|
async function writeTheme(config, cwd, options) {
|
|
2632
2801
|
const paths = themePaths(config);
|
|
2633
|
-
const existing = await readIfExists3(
|
|
2802
|
+
const existing = await readIfExists3(path17.join(cwd, paths.css));
|
|
2634
2803
|
if (!isBoilerplateCss(existing) && !options.yes) {
|
|
2635
2804
|
console.log(`
|
|
2636
2805
|
${paths.css} \u0627\u0632 \u0642\u0628\u0644 \u0645\u062D\u062A\u0648\u0627 \u062F\u0627\u0631\u062F.`);
|
|
@@ -2655,7 +2824,7 @@ ${paths.css} \u0627\u0632 \u0642\u0628\u0644 \u0645\u062D\u062A\u0648\u0627 \u06
|
|
|
2655
2824
|
}
|
|
2656
2825
|
async function applyRtl(cwd) {
|
|
2657
2826
|
for (const candidate of ["src/app/layout.tsx", "app/layout.tsx"]) {
|
|
2658
|
-
const target =
|
|
2827
|
+
const target = path17.join(cwd, candidate);
|
|
2659
2828
|
const source = await readIfExists3(target);
|
|
2660
2829
|
if (source === null) continue;
|
|
2661
2830
|
if (/<html[^>]*\sdir=/.test(source)) {
|
|
@@ -2700,14 +2869,14 @@ async function initCommand(options) {
|
|
|
2700
2869
|
rtl: await confirm("\u067E\u0631\u0648\u0698\u0647 \u0631\u0627\u0633\u062A\u200C\u0628\u0647\u200C\u0686\u067E (RTL) \u0627\u0633\u062A\u061F", base.rtl),
|
|
2701
2870
|
tailwind: await (async () => {
|
|
2702
2871
|
const css = await ask("\u0645\u0633\u06CC\u0631 \u0641\u0627\u06CC\u0644 CSS \u0627\u0635\u0644\u06CC \u062A\u06CC\u0644\u0648\u06CC\u0646\u062F\u061F", base.tailwind.css);
|
|
2703
|
-
const dir =
|
|
2872
|
+
const dir = path17.posix.dirname(css.split(path17.sep).join("/"));
|
|
2704
2873
|
return { ...base.tailwind, css, theme: `${dir}/dig-theme.css`, brand: `${dir}/brand.css` };
|
|
2705
2874
|
})()
|
|
2706
2875
|
};
|
|
2707
2876
|
const decisions = await askProjectDecisions(options);
|
|
2708
2877
|
options = { ...options, brand: decisions.brand };
|
|
2709
2878
|
await writeConfig(config, cwd);
|
|
2710
|
-
console.log(`\u2713 ${
|
|
2879
|
+
console.log(`\u2713 ${path17.join(cwd, "dig.json")} \u0646\u0648\u0634\u062A\u0647 \u0634\u062F.`);
|
|
2711
2880
|
const theme2 = await writeTheme(config, cwd, options);
|
|
2712
2881
|
if (config.rtl) {
|
|
2713
2882
|
await applyRtl(cwd);
|
|
@@ -2731,102 +2900,9 @@ async function initCommand(options) {
|
|
|
2731
2900
|
}
|
|
2732
2901
|
}
|
|
2733
2902
|
|
|
2734
|
-
// src/commands/mcp.ts
|
|
2735
|
-
import { createInterface as createInterface2 } from "readline";
|
|
2736
|
-
|
|
2737
|
-
// src/lib/version.ts
|
|
2738
|
-
var CLI_VERSION = "0.6.2";
|
|
2739
|
-
|
|
2740
|
-
// src/commands/mcp.ts
|
|
2741
|
-
var DEFAULT_MCP_URL = "https://docs.digdesign.ir/api/mcp";
|
|
2742
|
-
function parseSse(body) {
|
|
2743
|
-
const messages = [];
|
|
2744
|
-
for (const event of body.split(/\r?\n\r?\n/)) {
|
|
2745
|
-
const data = event.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).replace(/^ /, "")).join("\n");
|
|
2746
|
-
if (!data) continue;
|
|
2747
|
-
try {
|
|
2748
|
-
messages.push(JSON.parse(data));
|
|
2749
|
-
} catch {
|
|
2750
|
-
}
|
|
2751
|
-
}
|
|
2752
|
-
return messages;
|
|
2753
|
-
}
|
|
2754
|
-
function requestIds(message) {
|
|
2755
|
-
const list = Array.isArray(message) ? message : [message];
|
|
2756
|
-
return list.filter((item) => typeof item === "object" && item !== null).filter((item) => item.method !== void 0 && item.id !== void 0 && item.id !== null).map((item) => item.id);
|
|
2757
|
-
}
|
|
2758
|
-
function createBridge(url, fetchImpl = fetch) {
|
|
2759
|
-
let sessionId;
|
|
2760
|
-
let protocolVersion;
|
|
2761
|
-
return {
|
|
2762
|
-
async handle(line) {
|
|
2763
|
-
let message;
|
|
2764
|
-
try {
|
|
2765
|
-
message = JSON.parse(line);
|
|
2766
|
-
} catch {
|
|
2767
|
-
return [{ jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error" } }];
|
|
2768
|
-
}
|
|
2769
|
-
const ids = requestIds(message);
|
|
2770
|
-
const fail = (reason) => ids.map((id) => ({ jsonrpc: "2.0", id, error: { code: -32603, message: `Dig MCP (${url}): ${reason}` } }));
|
|
2771
|
-
let response;
|
|
2772
|
-
try {
|
|
2773
|
-
response = await fetchImpl(url, {
|
|
2774
|
-
method: "POST",
|
|
2775
|
-
headers: {
|
|
2776
|
-
"content-type": "application/json",
|
|
2777
|
-
accept: "application/json, text/event-stream",
|
|
2778
|
-
"user-agent": `digdesign-cli/${CLI_VERSION}`,
|
|
2779
|
-
...sessionId && { "mcp-session-id": sessionId },
|
|
2780
|
-
...protocolVersion && { "mcp-protocol-version": protocolVersion }
|
|
2781
|
-
},
|
|
2782
|
-
body: line
|
|
2783
|
-
});
|
|
2784
|
-
} catch (error) {
|
|
2785
|
-
return fail(`network error: ${error.message}`);
|
|
2786
|
-
}
|
|
2787
|
-
sessionId = response.headers.get("mcp-session-id") ?? sessionId;
|
|
2788
|
-
if (response.status === 202) return [];
|
|
2789
|
-
const body = await response.text();
|
|
2790
|
-
if (!response.ok) return fail(`HTTP ${response.status} ${body.slice(0, 200)}`);
|
|
2791
|
-
let replies;
|
|
2792
|
-
if ((response.headers.get("content-type") ?? "").includes("text/event-stream")) replies = parseSse(body);
|
|
2793
|
-
else {
|
|
2794
|
-
try {
|
|
2795
|
-
replies = body.trim() ? [JSON.parse(body)] : [];
|
|
2796
|
-
} catch {
|
|
2797
|
-
return fail(`invalid JSON response: ${body.slice(0, 200)}`);
|
|
2798
|
-
}
|
|
2799
|
-
}
|
|
2800
|
-
for (const reply of replies.flat()) {
|
|
2801
|
-
const result = reply?.result;
|
|
2802
|
-
if (result?.protocolVersion) protocolVersion = result.protocolVersion;
|
|
2803
|
-
}
|
|
2804
|
-
return replies;
|
|
2805
|
-
}
|
|
2806
|
-
};
|
|
2807
|
-
}
|
|
2808
|
-
async function mcpCommand(options) {
|
|
2809
|
-
const url = options.url ?? process.env.DIG_MCP_URL ?? DEFAULT_MCP_URL;
|
|
2810
|
-
const bridge = createBridge(url);
|
|
2811
|
-
const pending = /* @__PURE__ */ new Set();
|
|
2812
|
-
process.stderr.write(`dig mcp: stdio bridge to ${url}
|
|
2813
|
-
`);
|
|
2814
|
-
const input = createInterface2({ input: process.stdin, crlfDelay: Infinity });
|
|
2815
|
-
for await (const line of input) {
|
|
2816
|
-
if (!line.trim()) continue;
|
|
2817
|
-
const task = bridge.handle(line).then((replies) => {
|
|
2818
|
-
for (const reply of replies) process.stdout.write(`${JSON.stringify(reply)}
|
|
2819
|
-
`);
|
|
2820
|
-
});
|
|
2821
|
-
pending.add(task);
|
|
2822
|
-
void task.finally(() => pending.delete(task));
|
|
2823
|
-
}
|
|
2824
|
-
await Promise.all(pending);
|
|
2825
|
-
}
|
|
2826
|
-
|
|
2827
2903
|
// src/lib/migration-apply.ts
|
|
2828
|
-
import { readFile as
|
|
2829
|
-
import
|
|
2904
|
+
import { readFile as readFile13, writeFile as writeFile11 } from "fs/promises";
|
|
2905
|
+
import path18 from "path";
|
|
2830
2906
|
|
|
2831
2907
|
// src/lib/migration-strategy.ts
|
|
2832
2908
|
var TextReplaceStrategy = class {
|
|
@@ -2903,7 +2979,7 @@ function looksBinary2(buffer) {
|
|
|
2903
2979
|
async function readTextFileSafely2(target) {
|
|
2904
2980
|
let buffer;
|
|
2905
2981
|
try {
|
|
2906
|
-
buffer = await
|
|
2982
|
+
buffer = await readFile13(target);
|
|
2907
2983
|
} catch (error) {
|
|
2908
2984
|
if (error.code === "ENOENT") return void 0;
|
|
2909
2985
|
throw error;
|
|
@@ -2948,8 +3024,8 @@ async function planOrApplyMigrations(params) {
|
|
|
2948
3024
|
};
|
|
2949
3025
|
}
|
|
2950
3026
|
const fileTargets = registryItem.files.map((file) => {
|
|
2951
|
-
const target =
|
|
2952
|
-
return { relPath: toPosixPath(
|
|
3027
|
+
const target = path18.join(cwd, resolveTargetPath(file.path, aliases, paths));
|
|
3028
|
+
return { relPath: toPosixPath(path18.relative(cwd, target)), target };
|
|
2953
3029
|
});
|
|
2954
3030
|
const currentContents = /* @__PURE__ */ new Map();
|
|
2955
3031
|
for (const ft of fileTargets) {
|
|
@@ -3633,7 +3709,7 @@ ${entry.migrationHint}`);
|
|
|
3633
3709
|
|
|
3634
3710
|
// src/lib/missing-dependencies.ts
|
|
3635
3711
|
import { access as access6 } from "fs/promises";
|
|
3636
|
-
import
|
|
3712
|
+
import path19 from "path";
|
|
3637
3713
|
async function exists2(target) {
|
|
3638
3714
|
try {
|
|
3639
3715
|
await access6(target);
|
|
@@ -3654,7 +3730,7 @@ async function findMissingDependencies(params) {
|
|
|
3654
3730
|
for (const item of tree.values()) {
|
|
3655
3731
|
if (requested.has(item.name) || lock.components[item.name]) continue;
|
|
3656
3732
|
for (const file of item.files) {
|
|
3657
|
-
const target =
|
|
3733
|
+
const target = path19.join(
|
|
3658
3734
|
cwd,
|
|
3659
3735
|
resolveTargetPath(file.path, config.aliases, targetPathOptions(config))
|
|
3660
3736
|
);
|
|
@@ -3668,8 +3744,8 @@ async function findMissingDependencies(params) {
|
|
|
3668
3744
|
}
|
|
3669
3745
|
|
|
3670
3746
|
// src/lib/update.ts
|
|
3671
|
-
import { mkdir as mkdir8, readFile as
|
|
3672
|
-
import
|
|
3747
|
+
import { mkdir as mkdir8, readFile as readFile14, rm as rm2, writeFile as writeFile12 } from "fs/promises";
|
|
3748
|
+
import path20 from "path";
|
|
3673
3749
|
function safeFileIndexes(drift) {
|
|
3674
3750
|
const indexes = [];
|
|
3675
3751
|
drift.files.forEach((file, index) => {
|
|
@@ -3689,7 +3765,7 @@ async function applySafeFiles(cwd, aliases, drift, registryItem, dryRun, paths)
|
|
|
3689
3765
|
for (const index of safeIndexes) {
|
|
3690
3766
|
const file = drift.files[index];
|
|
3691
3767
|
const registryFile = registryItem.files[index];
|
|
3692
|
-
const target =
|
|
3768
|
+
const target = path20.join(cwd, resolveTargetPath(registryFile.path, aliases, paths));
|
|
3693
3769
|
const isNewFile = file.status === "new_upstream";
|
|
3694
3770
|
pending.push({
|
|
3695
3771
|
index,
|
|
@@ -3697,13 +3773,13 @@ async function applySafeFiles(cwd, aliases, drift, registryItem, dryRun, paths)
|
|
|
3697
3773
|
newContent: registryFile.content,
|
|
3698
3774
|
newHash: registryFile.hash ?? hashContent(registryFile.content),
|
|
3699
3775
|
isNewFile,
|
|
3700
|
-
originalContent: isNewFile ? void 0 : await
|
|
3776
|
+
originalContent: isNewFile ? void 0 : await readFile14(target, "utf8")
|
|
3701
3777
|
});
|
|
3702
3778
|
}
|
|
3703
3779
|
const written = [];
|
|
3704
3780
|
try {
|
|
3705
3781
|
for (const item of pending) {
|
|
3706
|
-
if (item.isNewFile) await mkdir8(
|
|
3782
|
+
if (item.isNewFile) await mkdir8(path20.dirname(item.target), { recursive: true });
|
|
3707
3783
|
await writeFile12(item.target, item.newContent, "utf8");
|
|
3708
3784
|
written.push(item);
|
|
3709
3785
|
}
|
|
@@ -4044,6 +4120,7 @@ program.command("init").description(
|
|
|
4044
4120
|
program.command("tokens").description("\u062A\u0648\u06A9\u0646\u200C\u0647\u0627\u06CC \u062F\u06CC\u06AF \u062F\u0631 \u0642\u0627\u0644\u0628\u0650 \u0627\u0633\u062A\u0627\u0646\u062F\u0627\u0631\u062F\u0650 DTCG \u0628\u0631\u0627\u06CC \u0641\u06CC\u06AF\u0645\u0627 \u0648 \u0627\u0628\u0632\u0627\u0631\u0647\u0627\u06CC \u0637\u0631\u0627\u062D\u06CC\u060C \u06CC\u06A9 \u0641\u0627\u06CC\u0644 \u0628\u0631\u0627\u06CC \u0647\u0631 \u062D\u0627\u0644\u062A").option("--brand <hex>", "\u0631\u0646\u06AF \u0628\u0631\u0646\u062F\u061B \u067E\u06CC\u0634\u200C\u0641\u0631\u0636 \u0627\u0632 DESIGN.md\u0650 \u067E\u0631\u0648\u0698\u0647").option("--out <dir>", "\u067E\u0648\u0634\u0647\u0654 \u062E\u0631\u0648\u062C\u06CC (\u067E\u06CC\u0634\u200C\u0641\u0631\u0636 tokens)").action(tokensCommand);
|
|
4045
4121
|
program.command("skill").description("\u06AF\u0630\u0627\u0634\u062A\u0646 \u06CC\u0627 \u0628\u0647\u200C\u0631\u0648\u0632\u06A9\u0631\u062F\u0646\u0650 Skill\u0650 \u0631\u0633\u0645\u06CC\u0650 \u062F\u06CC\u06AF \u0628\u0631\u0627\u06CC Claude Code \u062F\u0631 .claude/skills").action(skillCommand);
|
|
4046
4122
|
program.command("design-md").description("\u0633\u0627\u062E\u062A\u0646\u0650 DESIGN.md \u062F\u0631 \u0631\u06CC\u0634\u0647\u0654 \u067E\u0631\u0648\u0698\u0647: \u062A\u0648\u06A9\u0646\u200C\u0647\u0627 \u0648 \u0642\u0627\u0639\u062F\u0647\u200C\u0647\u0627\u06CC \u062F\u06CC\u06AF \u0628\u0631\u0627\u06CC \u0627\u06CC\u062C\u0646\u062A\u200C\u0647\u0627\u06CC \u06A9\u062F\u0646\u0648\u06CC\u0633").option("--brand <hex>", "\u0631\u0646\u06AF \u0628\u0631\u0646\u062F \u062A\u0627 \u0631\u0646\u06AF\u200C\u0647\u0627\u06CC \u0648\u0627\u0642\u0639\u06CC\u0650 \u0628\u0631\u0646\u062F \u062F\u0631 \u0641\u0627\u06CC\u0644 \u0628\u06CC\u0627\u06CC\u062F\u060C \u0645\u062B\u0644 #2C4C5B").option("--secondary <hex>", "\u0631\u0646\u06AF \u062F\u0648\u0645\u0650 \u0628\u0631\u0646\u062F").option("--name <name>", "\u0646\u0627\u0645 \u0645\u062D\u0635\u0648\u0644").option("--font <font>", "\u0641\u0648\u0646\u062A: iransans\u060C yekan \u06CC\u0627 vazirmatn").option("--radius <radius>", "\u0634\u0639\u0627\u0639: none\u060C sm\u060C md\u060C lg\u060C xl \u06CC\u0627 full").option("--force", "\u0628\u0627\u0632\u0646\u0648\u06CC\u0633\u06CC\u0650 DESIGN.md\u0650 \u062F\u0633\u062A\u200C\u0646\u0648\u0634\u062A\u0647", false).action(designMdCommand);
|
|
4123
|
+
program.command("review").description("\u0628\u0627\u0632\u0628\u06CC\u0646\u06CC\u0650 \u0641\u0627\u06CC\u0644\u200C\u0647\u0627\u06CC \u0631\u0627\u0628\u0637 \u0628\u0627 \u0642\u0648\u0627\u0639\u062F \u062F\u06CC\u06AF (\u0647\u0645\u0627\u0646 review_code \u062F\u0631 MCP)\u060C \u0628\u0627 \u0634\u0645\u0627\u0631\u0647\u0654 \u062E\u0637\u0650 \u0647\u0631 \u06CC\u0627\u0641\u062A\u0647").argument("<paths...>", "\u0645\u0633\u06CC\u0631 \u0641\u0627\u06CC\u0644\u200C\u0647\u0627\u06CC tsx/jsx").option("--url <url>", "\u0622\u062F\u0631\u0633 \u0633\u0631\u0648\u0631 MCP (\u067E\u06CC\u0634\u200C\u0641\u0631\u0636 https://docs.digdesign.ir/api/mcp)").option("--json", "\u062E\u0631\u0648\u062C\u06CC JSON \u0628\u0631\u0627\u06CC \u0627\u0633\u06A9\u0631\u06CC\u067E\u062A/\u0627\u0628\u0632\u0627\u0631", false).action(reviewCommand);
|
|
4047
4124
|
var theme = program.command("theme").description("\u062A\u0645 \u0648 \u0628\u0631\u0646\u062F: \u062C\u062F\u0627 \u06A9\u0631\u062F\u0646\u0650 \u062A\u0645\u0650 \u062F\u06CC\u06AF \u0627\u0632 \u0628\u0631\u0646\u062F\u0650 \u067E\u0631\u0648\u0698\u0647");
|
|
4048
4125
|
theme.command("split").description("\u067E\u0631\u0648\u0698\u0647\u0654 \u0642\u062F\u06CC\u0645\u06CC \u0631\u0627 \u0628\u0647 \u0633\u0627\u062E\u062A\u0627\u0631\u0650 \u062F\u0648\u0641\u0627\u06CC\u0644\u06CC \u0645\u06CC\u200C\u0628\u0631\u062F (dig-theme.css \u0645\u0627\u0644\u0650 \u062F\u06CC\u06AF\u060C brand.css \u0645\u0627\u0644\u0650 \u067E\u0631\u0648\u0698\u0647)").option("--dry-run", "\u0641\u0642\u0637 \u0646\u0634\u0627\u0646 \u0628\u062F\u0647 \u0686\u0647 \u0686\u06CC\u0632\u06CC \u0628\u0647 brand.css \u0645\u06CC\u200C\u0631\u0648\u062F\u060C \u0686\u06CC\u0632\u06CC \u0646\u0646\u0648\u06CC\u0633", false).action(themeSplitCommand);
|
|
4049
4126
|
theme.command("brand").description("\u0631\u0645\u067E\u0650 \u0628\u0631\u0646\u062F \u0631\u0627 \u062F\u0631 brand.css \u0627\u0632 \u06CC\u06A9 \u0631\u0646\u06AF \u0645\u06CC\u200C\u0633\u0627\u0632\u062F\u061B \u0628\u0642\u06CC\u0647\u0654 \u0641\u0627\u06CC\u0644 \u062F\u0633\u062A \u0646\u0645\u06CC\u200C\u062E\u0648\u0631\u062F").argument("<hex>", "\u0631\u0646\u06AF\u0650 \u0627\u0635\u0644\u06CC\u0650 \u0628\u0631\u0646\u062F\u060C \u0645\u062B\u0644 #2C4C5B").action(themeBrandCommand);
|