zdashboard 2.8.4 → 2.8.6
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 +520 -292
- package/dist/cli.js.map +1 -1
- package/dist/web/assets/CodeViewer-_jAxbWVL.js +10 -0
- package/dist/web/assets/{FileIcon-1KBdrfw3.js → FileIcon-68etP2t6.js} +1 -1
- package/dist/web/assets/{FilterPills-CCubROoX.js → FilterPills-DGfzMpn_.js} +1 -1
- package/dist/web/assets/ImageViewer-ChZdzYPf.js +298 -0
- package/dist/web/assets/{Sidebar-DE0UBp9b.js → Sidebar-D83uLTNy.js} +1 -1
- package/dist/web/assets/{Sidebar-D4sJtPI_.js → Sidebar-N0HiMJRK.js} +1 -1
- package/dist/web/assets/Workspace-BE7p2hNz.js +1 -0
- package/dist/web/assets/Workspace-BpSq60xh.js +1 -0
- package/dist/web/assets/{Workspace-CvG5lIPT.js → Workspace-DW8xX3Tg.js} +1 -1
- package/dist/web/assets/Workspace-DjL1fdji.js +2 -0
- package/dist/web/assets/Workspace-DrN9--Je.js +1 -0
- package/dist/web/assets/index-DH1Mqw-g.css +1 -0
- package/dist/web/assets/{index-Co7MWSFf.js → index-D_uh-zkI.js} +3 -3
- package/dist/web/assets/{usePluginData-IoRqReIJ.js → usePluginData-Bk2M7LNj.js} +1 -1
- package/dist/web/assets/{web-BZSTgldm.js → web-BZukfmmT.js} +2 -2
- package/dist/web/assets/{web-DOEmlI8d.js → web-CEB9kTEr.js} +2 -2
- package/dist/web/assets/web-CGvrDSNo.js +2 -0
- package/dist/web/assets/{web-DxbVzGf3.js → web-CLKkH6eO.js} +2 -2
- package/dist/web/assets/web-CbW9uGDV.js +2 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/web/assets/BatchView-pClKtVa8.js +0 -2
- package/dist/web/assets/CheckpointViewer-CAbXbMti.js +0 -1
- package/dist/web/assets/CodeViewer-Cs0mG1h6.js +0 -279
- package/dist/web/assets/DependencyGraph-Czdg00AM.js +0 -1
- package/dist/web/assets/ProgressBar-DVfldtzq.js +0 -1
- package/dist/web/assets/SingleChangeView-BYcaGOyR.js +0 -1
- package/dist/web/assets/ViewHeader-DPfbaJmK.js +0 -1
- package/dist/web/assets/Workspace-B7MhdnwY.js +0 -2
- package/dist/web/assets/Workspace-CAcrVL-m.js +0 -1
- package/dist/web/assets/Workspace-DWHHR42N.js +0 -1
- package/dist/web/assets/Workspace-cXLWoMNL.js +0 -1
- package/dist/web/assets/index-CwS-KyOV.css +0 -1
- package/dist/web/assets/index-D6EJRHBV.js +0 -29
- package/dist/web/assets/web-CX1FEFxC.js +0 -2
- package/dist/web/assets/web-DLwxO4fO.js +0 -2
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import path9 from "path";
|
|
5
|
+
import fs9 from "fs";
|
|
6
6
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7
7
|
import { access, readdir } from "fs/promises";
|
|
8
8
|
import { parseArgs as utilParseArgs } from "util";
|
|
@@ -43,7 +43,7 @@ import { fileURLToPath } from "url";
|
|
|
43
43
|
// package.json
|
|
44
44
|
var package_default = {
|
|
45
45
|
name: "zdashboard",
|
|
46
|
-
version: "2.8.
|
|
46
|
+
version: "2.8.6",
|
|
47
47
|
description: "ZCode skill dashboard platform \u2014 pluggable viewers for zdesign/zview/zreview/zgoal",
|
|
48
48
|
type: "module",
|
|
49
49
|
bin: {
|
|
@@ -452,13 +452,13 @@ var ServerService = class extends Service {
|
|
|
452
452
|
});
|
|
453
453
|
this.start(config.port);
|
|
454
454
|
}
|
|
455
|
-
route(
|
|
456
|
-
this.routes.set(
|
|
457
|
-
this.ctx.effect(() => () => this.routes.delete(
|
|
455
|
+
route(path10, handler) {
|
|
456
|
+
this.routes.set(path10, handler);
|
|
457
|
+
this.ctx.effect(() => () => this.routes.delete(path10));
|
|
458
458
|
}
|
|
459
|
-
sse(
|
|
460
|
-
this.sses.set(
|
|
461
|
-
this.ctx.effect(() => () => this.sses.delete(
|
|
459
|
+
sse(path10, onConnect) {
|
|
460
|
+
this.sses.set(path10, onConnect);
|
|
461
|
+
this.ctx.effect(() => () => this.sses.delete(path10));
|
|
462
462
|
}
|
|
463
463
|
static(prefix, dir) {
|
|
464
464
|
this.prefixStatic.set(prefix, dir);
|
|
@@ -757,7 +757,7 @@ import path5 from "path";
|
|
|
757
757
|
import fs5 from "fs";
|
|
758
758
|
import path4 from "path";
|
|
759
759
|
function walkDir(root, opts = {}) {
|
|
760
|
-
const { skip = /* @__PURE__ */ new Set(), maxDepth, onFile, onDir } = opts;
|
|
760
|
+
const { skip = /* @__PURE__ */ new Set(), maxDepth, allowDotDirs = false, onFile, onDir } = opts;
|
|
761
761
|
function walk(dir, rel, depth) {
|
|
762
762
|
if (typeof maxDepth === "number" && depth > maxDepth) return;
|
|
763
763
|
let ents;
|
|
@@ -767,7 +767,7 @@ function walkDir(root, opts = {}) {
|
|
|
767
767
|
return;
|
|
768
768
|
}
|
|
769
769
|
for (const ent of ents) {
|
|
770
|
-
if (ent.name.startsWith(".")) continue;
|
|
770
|
+
if (ent.name.startsWith(".") && !(allowDotDirs && ent.isDirectory())) continue;
|
|
771
771
|
if (skip.has(ent.name)) continue;
|
|
772
772
|
const abs = path4.join(dir, ent.name);
|
|
773
773
|
const r = rel ? `${rel}/${ent.name}` : ent.name;
|
|
@@ -835,12 +835,14 @@ function prefixPaths(nodes, prefix) {
|
|
|
835
835
|
function scanTree(root, scanDirs, opts) {
|
|
836
836
|
const tree = [];
|
|
837
837
|
const defaultExpandDepth = typeof opts?.defaultExpandDepth === "number" ? opts.defaultExpandDepth : 2;
|
|
838
|
+
const dotDeclared = new Set(Array.isArray(opts?.dotDirs) ? opts.dotDirs : []);
|
|
838
839
|
const dirs = Array.isArray(scanDirs) ? scanDirs.filter((d) => typeof d === "string" && d) : [];
|
|
839
840
|
for (const dir of dirs) {
|
|
841
|
+
if (dir.startsWith(".") && !dotDeclared.has(dir)) continue;
|
|
840
842
|
const dirPath = path5.join(root, dir);
|
|
841
843
|
if (!fs6.existsSync(dirPath)) continue;
|
|
842
844
|
const paths = [];
|
|
843
|
-
walkDir(dirPath, { maxDepth: 4, onFile: (_, rel) => paths.push(rel) });
|
|
845
|
+
walkDir(dirPath, { maxDepth: 4, allowDotDirs: dotDeclared.has(dir), onFile: (_, rel) => paths.push(rel) });
|
|
844
846
|
const prefix = dir;
|
|
845
847
|
const children = prefixPaths(buildTree(paths, defaultExpandDepth), prefix);
|
|
846
848
|
if (children.length) {
|
|
@@ -851,7 +853,8 @@ function scanTree(root, scanDirs, opts) {
|
|
|
851
853
|
}
|
|
852
854
|
|
|
853
855
|
// src/core/tree.ts
|
|
854
|
-
var CONVENTION_SCAN_DIRS = ["openspec", "docs"];
|
|
856
|
+
var CONVENTION_SCAN_DIRS = ["openspec", "docs", ".zdev/apply"];
|
|
857
|
+
var CONVENTION_DOT_DIRS = CONVENTION_SCAN_DIRS.filter((d) => d.startsWith("."));
|
|
855
858
|
var apply = {
|
|
856
859
|
inject: ["server"],
|
|
857
860
|
apply(ctx, config) {
|
|
@@ -862,7 +865,7 @@ var apply = {
|
|
|
862
865
|
const url = new URL(req.url || "/", "http://localhost");
|
|
863
866
|
const wt = url.searchParams.get("wt");
|
|
864
867
|
const scanRoot = wt ? decodeURIComponent(wt) : config.root;
|
|
865
|
-
const tree = scanTree(scanRoot, [...CONVENTION_SCAN_DIRS]);
|
|
868
|
+
const tree = scanTree(scanRoot, [...CONVENTION_SCAN_DIRS], { dotDirs: [...CONVENTION_DOT_DIRS] });
|
|
866
869
|
res.writeHead(200, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-cache" });
|
|
867
870
|
res.end(JSON.stringify({ tree }));
|
|
868
871
|
} catch {
|
|
@@ -1228,18 +1231,18 @@ function definePlugin(def) {
|
|
|
1228
1231
|
);
|
|
1229
1232
|
return { ...defaults, ...stored };
|
|
1230
1233
|
},
|
|
1231
|
-
route(
|
|
1232
|
-
ctx.server.route(
|
|
1234
|
+
route(path10, handler) {
|
|
1235
|
+
ctx.server.route(path10, respondWith(handler));
|
|
1233
1236
|
},
|
|
1234
|
-
guardedRoute(
|
|
1237
|
+
guardedRoute(path10, handler) {
|
|
1235
1238
|
const token = () => ctx.server.stopToken;
|
|
1236
|
-
ctx.server.route(
|
|
1239
|
+
ctx.server.route(path10, (req, res) => {
|
|
1237
1240
|
if (!guarded(req, res, token())) return;
|
|
1238
1241
|
void respondWith(handler)(req, res);
|
|
1239
1242
|
});
|
|
1240
1243
|
},
|
|
1241
|
-
sse(
|
|
1242
|
-
ctx.server.sse(
|
|
1244
|
+
sse(path10, handler) {
|
|
1245
|
+
ctx.server.sse(path10, handler);
|
|
1243
1246
|
},
|
|
1244
1247
|
static(prefix, dir) {
|
|
1245
1248
|
ctx.server.static(prefix, dir);
|
|
@@ -1350,240 +1353,12 @@ var apply3 = defineBuiltin({
|
|
|
1350
1353
|
}
|
|
1351
1354
|
});
|
|
1352
1355
|
|
|
1353
|
-
// src/plugins/apply/scan.ts
|
|
1354
|
-
import fs7 from "fs";
|
|
1355
|
-
import path6 from "path";
|
|
1356
|
-
|
|
1357
|
-
// src/plugins/apply/parse-tasks.ts
|
|
1358
|
-
var TASK_RE = /^\s*-\s*\[([ xX])\]\s*(.*)$/;
|
|
1359
|
-
var MANUAL_PREFIX = "\u{1F527}[\u4EBA\u5DE5]";
|
|
1360
|
-
function parseTasks(md) {
|
|
1361
|
-
return md.split(/\r?\n/).filter((l) => TASK_RE.test(l)).map((l) => {
|
|
1362
|
-
const m = l.match(TASK_RE);
|
|
1363
|
-
const text = (m?.[2] ?? l).trim();
|
|
1364
|
-
return { text, checked: m?.[1] !== " ", manual: text.startsWith(MANUAL_PREFIX) };
|
|
1365
|
-
});
|
|
1366
|
-
}
|
|
1367
|
-
function countTasks(md) {
|
|
1368
|
-
const tasks = parseTasks(md);
|
|
1369
|
-
const normal = tasks.filter((t) => !t.manual);
|
|
1370
|
-
return {
|
|
1371
|
-
total: normal.length,
|
|
1372
|
-
done: normal.filter((t) => t.checked).length,
|
|
1373
|
-
manual: tasks.length - normal.length
|
|
1374
|
-
};
|
|
1375
|
-
}
|
|
1376
|
-
|
|
1377
|
-
// src/plugins/apply/scan.ts
|
|
1378
|
-
function readText(p) {
|
|
1379
|
-
try {
|
|
1380
|
-
return fs7.readFileSync(p, "utf8");
|
|
1381
|
-
} catch {
|
|
1382
|
-
return "";
|
|
1383
|
-
}
|
|
1384
|
-
}
|
|
1385
|
-
function worktreeDir(root, name) {
|
|
1386
|
-
return path6.join(root, ".zworktree", name);
|
|
1387
|
-
}
|
|
1388
|
-
function changeDir(root, name) {
|
|
1389
|
-
return path6.join(root, "openspec", "changes", name);
|
|
1390
|
-
}
|
|
1391
|
-
function parseDependsOn(proposal) {
|
|
1392
|
-
const deps = [];
|
|
1393
|
-
const m = proposal.match(/^##\s+依赖\s*\n([\s\S]*?)(?:\n#{1,6}\s|\n---\s*\n|$)/i);
|
|
1394
|
-
if (!m) return deps;
|
|
1395
|
-
for (const line of m[1].split("\n")) {
|
|
1396
|
-
if (!/^-\s+/.test(line)) continue;
|
|
1397
|
-
const name = line.replace(/^-\s+/, "").trim();
|
|
1398
|
-
if (name) deps.push(name);
|
|
1399
|
-
}
|
|
1400
|
-
return deps;
|
|
1401
|
-
}
|
|
1402
|
-
function scanApplyChanges(root) {
|
|
1403
|
-
const changesDir = path6.join(root, "openspec", "changes");
|
|
1404
|
-
if (!fs7.existsSync(changesDir)) return [];
|
|
1405
|
-
const out = [];
|
|
1406
|
-
for (const ent of fs7.readdirSync(changesDir, { withFileTypes: true })) {
|
|
1407
|
-
if (!ent.isDirectory() || ent.name.startsWith(".") || ent.name === "archive") continue;
|
|
1408
|
-
const wt = worktreeDir(root, ent.name);
|
|
1409
|
-
const tasks = readText(path6.join(wt, "openspec", "changes", ent.name, "tasks.md"));
|
|
1410
|
-
if (!tasks) {
|
|
1411
|
-
const fallback = readText(path6.join(changesDir, ent.name, "tasks.md"));
|
|
1412
|
-
if (fallback) {
|
|
1413
|
-
const { total, done } = countTasks(fallback);
|
|
1414
|
-
const wtChange = path6.join(wt, "openspec", "changes", ent.name);
|
|
1415
|
-
const mainChange = path6.join(changesDir, ent.name);
|
|
1416
|
-
out.push({
|
|
1417
|
-
name: ent.name,
|
|
1418
|
-
path: `openspec/changes/${ent.name}`,
|
|
1419
|
-
total,
|
|
1420
|
-
done,
|
|
1421
|
-
hasProposal: fs7.existsSync(path6.join(wtChange, "proposal.md")) || fs7.existsSync(path6.join(mainChange, "proposal.md")),
|
|
1422
|
-
hasDesign: fs7.existsSync(path6.join(wtChange, "design.md")) || fs7.existsSync(path6.join(mainChange, "design.md")),
|
|
1423
|
-
// worktree 目录存在即算执行中(tasks.md 可能尚未落盘)
|
|
1424
|
-
inWorktree: fs7.existsSync(wtChange)
|
|
1425
|
-
});
|
|
1426
|
-
}
|
|
1427
|
-
} else {
|
|
1428
|
-
const { total, done } = countTasks(tasks);
|
|
1429
|
-
const wtChange = path6.join(wt, "openspec", "changes", ent.name);
|
|
1430
|
-
const mainChange = path6.join(changesDir, ent.name);
|
|
1431
|
-
out.push({
|
|
1432
|
-
name: ent.name,
|
|
1433
|
-
path: `openspec/changes/${ent.name}`,
|
|
1434
|
-
total,
|
|
1435
|
-
done,
|
|
1436
|
-
// 任一侧存在即算(详情读取是 worktree 优先、主目录兜底,列表标记保持一致)
|
|
1437
|
-
hasProposal: fs7.existsSync(path6.join(wtChange, "proposal.md")) || fs7.existsSync(path6.join(mainChange, "proposal.md")),
|
|
1438
|
-
hasDesign: fs7.existsSync(path6.join(wtChange, "design.md")) || fs7.existsSync(path6.join(mainChange, "design.md")),
|
|
1439
|
-
inWorktree: true
|
|
1440
|
-
});
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
out.sort((a, b) => a.name.localeCompare(b.name));
|
|
1444
|
-
return out;
|
|
1445
|
-
}
|
|
1446
|
-
function readApplyChange(root, name) {
|
|
1447
|
-
const wt = worktreeDir(root, name);
|
|
1448
|
-
const mainChangeDir = changeDir(root, name);
|
|
1449
|
-
const proposalFrom = fs7.existsSync(path6.join(wt, "openspec", "changes", name, "proposal.md")) ? path6.join(wt, "openspec", "changes", name, "proposal.md") : path6.join(mainChangeDir, "proposal.md");
|
|
1450
|
-
const designFrom = fs7.existsSync(path6.join(wt, "openspec", "changes", name, "design.md")) ? path6.join(wt, "openspec", "changes", name, "design.md") : path6.join(mainChangeDir, "design.md");
|
|
1451
|
-
const tasksFrom = fs7.existsSync(path6.join(wt, "openspec", "changes", name, "tasks.md")) ? path6.join(wt, "openspec", "changes", name, "tasks.md") : path6.join(mainChangeDir, "tasks.md");
|
|
1452
|
-
const proposal = readText(proposalFrom);
|
|
1453
|
-
const design = readText(designFrom);
|
|
1454
|
-
const tasks = readText(tasksFrom);
|
|
1455
|
-
const { total, done } = countTasks(tasks);
|
|
1456
|
-
const inWorktree = fs7.existsSync(path6.join(wt, "openspec", "changes", name));
|
|
1457
|
-
const dependsOn = parseDependsOn(proposal);
|
|
1458
|
-
const hasTestStrategy = /^##\s+测试策略\s*$/m.test(design);
|
|
1459
|
-
return {
|
|
1460
|
-
name,
|
|
1461
|
-
path: `openspec/changes/${name}`,
|
|
1462
|
-
total,
|
|
1463
|
-
done,
|
|
1464
|
-
hasProposal: !!proposal,
|
|
1465
|
-
hasDesign: !!design,
|
|
1466
|
-
inWorktree,
|
|
1467
|
-
proposal,
|
|
1468
|
-
design,
|
|
1469
|
-
tasks,
|
|
1470
|
-
dependsOn,
|
|
1471
|
-
hasTestStrategy
|
|
1472
|
-
};
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
// src/plugins/apply/batch.ts
|
|
1476
|
-
import fs8 from "fs";
|
|
1477
|
-
import path7 from "path";
|
|
1478
|
-
var RUN_ID_PATTERN = /^[A-Za-z0-9-]+$/;
|
|
1479
|
-
function isPlainObject(v) {
|
|
1480
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
1481
|
-
}
|
|
1482
|
-
function readText2(p) {
|
|
1483
|
-
try {
|
|
1484
|
-
return fs8.readFileSync(p, "utf8");
|
|
1485
|
-
} catch {
|
|
1486
|
-
return null;
|
|
1487
|
-
}
|
|
1488
|
-
}
|
|
1489
|
-
function readBatchState(root, explicitRun) {
|
|
1490
|
-
const applyDir = path7.join(root, ".zdev", "apply");
|
|
1491
|
-
const requested = explicitRun?.trim() ?? "";
|
|
1492
|
-
const runId = requested && RUN_ID_PATTERN.test(requested) ? requested : readText2(path7.join(applyDir, "CURRENT"))?.trim() ?? "";
|
|
1493
|
-
if (!runId || !RUN_ID_PATTERN.test(runId)) {
|
|
1494
|
-
return { run: null, state: null };
|
|
1495
|
-
}
|
|
1496
|
-
const parsed = (() => {
|
|
1497
|
-
const text = readText2(path7.join(applyDir, "runs", runId, "state.json"));
|
|
1498
|
-
if (text == null) return null;
|
|
1499
|
-
try {
|
|
1500
|
-
return JSON.parse(text);
|
|
1501
|
-
} catch {
|
|
1502
|
-
return null;
|
|
1503
|
-
}
|
|
1504
|
-
})();
|
|
1505
|
-
if (!isPlainObject(parsed)) {
|
|
1506
|
-
return { run: { id: runId }, state: null };
|
|
1507
|
-
}
|
|
1508
|
-
return { run: { id: runId }, state: parsed };
|
|
1509
|
-
}
|
|
1510
|
-
function projectGraph(state) {
|
|
1511
|
-
if (!state) {
|
|
1512
|
-
return { changes: [], batches: [], conflicts: [] };
|
|
1513
|
-
}
|
|
1514
|
-
const rawChanges = state.changes;
|
|
1515
|
-
const rawBatches = state.batches;
|
|
1516
|
-
const rawConflicts = state.conflicts;
|
|
1517
|
-
return {
|
|
1518
|
-
changes: (Array.isArray(rawChanges) ? rawChanges : []).map((c) => ({
|
|
1519
|
-
name: c.name,
|
|
1520
|
-
status: c.status,
|
|
1521
|
-
dependencies: Array.isArray(c?.dependencies) ? c.dependencies : [],
|
|
1522
|
-
batchIndex: c.batchIndex
|
|
1523
|
-
})),
|
|
1524
|
-
batches: Array.isArray(rawBatches) ? rawBatches : [],
|
|
1525
|
-
conflicts: Array.isArray(rawConflicts) ? rawConflicts : []
|
|
1526
|
-
};
|
|
1527
|
-
}
|
|
1528
|
-
var BATCH_LOGS_TAIL = 100;
|
|
1529
|
-
function tailLogs(state) {
|
|
1530
|
-
const logs = state?.logs;
|
|
1531
|
-
return (Array.isArray(logs) ? logs : []).slice(-BATCH_LOGS_TAIL);
|
|
1532
|
-
}
|
|
1533
|
-
function readBatchPlan(root, runId) {
|
|
1534
|
-
return readText2(path7.join(root, ".zdev", "apply", "runs", runId, "plan.md"));
|
|
1535
|
-
}
|
|
1536
|
-
|
|
1537
|
-
// src/plugins/apply/manifest.ts
|
|
1538
|
-
var manifest2 = {
|
|
1539
|
-
mode: "apply",
|
|
1540
|
-
label: "\u6267\u884C\u8FDB\u5EA6",
|
|
1541
|
-
icon: "\u2699\uFE0F",
|
|
1542
|
-
description: "OpenSpec \u6267\u884C\u8FDB\u5EA6 \xB7 zapply \u5355 change \u4E0E\u6279\u91CF",
|
|
1543
|
-
order: 40
|
|
1544
|
-
};
|
|
1545
|
-
|
|
1546
|
-
// src/plugins/apply/index.ts
|
|
1547
|
-
function errorResponse(res, status, msg) {
|
|
1548
|
-
res.writeHead(status, { "Content-Type": "application/json; charset=utf-8" });
|
|
1549
|
-
res.end(JSON.stringify({ error: msg }));
|
|
1550
|
-
return void 0;
|
|
1551
|
-
}
|
|
1552
|
-
var apply4 = defineBuiltin({
|
|
1553
|
-
manifest: manifest2,
|
|
1554
|
-
setup(ctx, root) {
|
|
1555
|
-
ctx.route("/__apply", async () => scanApplyChanges(root));
|
|
1556
|
-
ctx.route("/__apply/change", async (req, res) => {
|
|
1557
|
-
const url = new URL(req.url || "", "http://x");
|
|
1558
|
-
const name = url.searchParams.get("name");
|
|
1559
|
-
const bad = (msg) => errorResponse(res, 400, msg);
|
|
1560
|
-
if (!name) return bad("missing name");
|
|
1561
|
-
if (name.includes("..") || name.includes("/") || name.includes("\\")) return bad("invalid name");
|
|
1562
|
-
try {
|
|
1563
|
-
return readApplyChange(root, name);
|
|
1564
|
-
} catch (e) {
|
|
1565
|
-
return bad(e instanceof Error ? e.message : "unknown error");
|
|
1566
|
-
}
|
|
1567
|
-
});
|
|
1568
|
-
const queryRun = (req) => new URL(req.url || "", "http://x").searchParams.get("run") ?? void 0;
|
|
1569
|
-
ctx.route("/__apply/batch", async (req) => readBatchState(root, queryRun(req)));
|
|
1570
|
-
ctx.route("/__apply/batch/graph", async (req) => projectGraph(readBatchState(root, queryRun(req)).state));
|
|
1571
|
-
ctx.route("/__apply/batch/logs", async (req) => tailLogs(readBatchState(root, queryRun(req)).state));
|
|
1572
|
-
ctx.route("/__apply/batch/plan", async (req, res) => {
|
|
1573
|
-
const snap = readBatchState(root, queryRun(req));
|
|
1574
|
-
const plan = snap.run ? readBatchPlan(root, snap.run.id) : null;
|
|
1575
|
-
if (plan == null) return errorResponse(res, 404, "plan not found");
|
|
1576
|
-
return { plan };
|
|
1577
|
-
});
|
|
1578
|
-
}
|
|
1579
|
-
});
|
|
1580
|
-
|
|
1581
1356
|
// src/plugins/design/index.ts
|
|
1582
|
-
import
|
|
1583
|
-
import
|
|
1357
|
+
import path7 from "path";
|
|
1358
|
+
import fs7 from "fs";
|
|
1584
1359
|
|
|
1585
1360
|
// src/server/design-assets.ts
|
|
1586
|
-
import
|
|
1361
|
+
import path6 from "path";
|
|
1587
1362
|
var PAGE_EXTS = [".html", ".htm"];
|
|
1588
1363
|
var ICON_EXTS = [".svg", ".png", ".ico", ".jpg", ".jpeg", ".gif", ".webp"];
|
|
1589
1364
|
var VIDEO_EXTS = [".mp4", ".webm", ".mov", ".ogg", ".ogv"];
|
|
@@ -1611,17 +1386,17 @@ function scanAssets(root, subDir = "") {
|
|
|
1611
1386
|
const keys = ["page", "component", "icon", "token", "md", "video", "audio", "pdf", "font"];
|
|
1612
1387
|
for (const k of keys) out[k] = [];
|
|
1613
1388
|
const SKIP = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", "coverage", ".next", ".cache"]);
|
|
1614
|
-
const scanRoot = subDir ?
|
|
1389
|
+
const scanRoot = subDir ? path6.join(root, subDir) : root;
|
|
1615
1390
|
walkDir(scanRoot, { skip: SKIP, onFile: (abs, rel) => {
|
|
1616
|
-
const ext =
|
|
1391
|
+
const ext = path6.extname(abs).toLowerCase();
|
|
1617
1392
|
const t = categorize(rel, ext);
|
|
1618
|
-
if (t) out[t].push({ path: rel, name:
|
|
1393
|
+
if (t) out[t].push({ path: rel, name: path6.basename(abs), ext, type: t });
|
|
1619
1394
|
} });
|
|
1620
1395
|
return out;
|
|
1621
1396
|
}
|
|
1622
1397
|
|
|
1623
1398
|
// src/plugins/design/manifest.ts
|
|
1624
|
-
var
|
|
1399
|
+
var manifest2 = {
|
|
1625
1400
|
mode: "design",
|
|
1626
1401
|
label: "\u8BBE\u8BA1\u8D44\u4EA7",
|
|
1627
1402
|
icon: "\u{1F3A8}",
|
|
@@ -1636,35 +1411,35 @@ function emptyScan() {
|
|
|
1636
1411
|
for (const k of ASSET_KEYS) out[k] = [];
|
|
1637
1412
|
return out;
|
|
1638
1413
|
}
|
|
1639
|
-
var
|
|
1640
|
-
manifest:
|
|
1414
|
+
var apply4 = defineBuiltin({
|
|
1415
|
+
manifest: manifest2,
|
|
1641
1416
|
setup(ctx, root) {
|
|
1642
1417
|
ctx.route("/__design/assets", async () => {
|
|
1643
|
-
const designRoot =
|
|
1644
|
-
return
|
|
1418
|
+
const designRoot = path7.join(root, ".zdev", "design");
|
|
1419
|
+
return fs7.existsSync(designRoot) ? scanAssets(designRoot) : emptyScan();
|
|
1645
1420
|
});
|
|
1646
1421
|
ctx.route("/__design/asset", async (req, res) => {
|
|
1647
1422
|
const rel = new URL(req.url || "/", "http://localhost").searchParams.get("path") ?? "";
|
|
1648
|
-
if (!rel || rel.includes("..") || rel.includes("\\") ||
|
|
1423
|
+
if (!rel || rel.includes("..") || rel.includes("\\") || path7.isAbsolute(rel)) {
|
|
1649
1424
|
res.writeHead(400);
|
|
1650
1425
|
res.end("bad path");
|
|
1651
1426
|
return;
|
|
1652
1427
|
}
|
|
1653
|
-
const designRoot =
|
|
1654
|
-
const filePath =
|
|
1655
|
-
if (!filePath.startsWith(designRoot +
|
|
1428
|
+
const designRoot = path7.join(root, ".zdev", "design");
|
|
1429
|
+
const filePath = path7.join(designRoot, rel);
|
|
1430
|
+
if (!filePath.startsWith(designRoot + path7.sep)) {
|
|
1656
1431
|
res.writeHead(400);
|
|
1657
1432
|
res.end("bad path");
|
|
1658
1433
|
return;
|
|
1659
1434
|
}
|
|
1660
|
-
|
|
1435
|
+
fs7.stat(filePath, (err) => {
|
|
1661
1436
|
if (err) {
|
|
1662
1437
|
res.writeHead(404);
|
|
1663
1438
|
return res.end("Not found");
|
|
1664
1439
|
}
|
|
1665
|
-
const ct = MIME[
|
|
1440
|
+
const ct = MIME[path7.extname(filePath).toLowerCase()] ?? "application/octet-stream";
|
|
1666
1441
|
res.writeHead(200, { "Content-Type": ct, "Cache-Control": "no-cache" });
|
|
1667
|
-
const stream =
|
|
1442
|
+
const stream = fs7.createReadStream(filePath);
|
|
1668
1443
|
stream.on("error", () => {
|
|
1669
1444
|
try {
|
|
1670
1445
|
res.destroy();
|
|
@@ -1678,7 +1453,7 @@ var apply5 = defineBuiltin({
|
|
|
1678
1453
|
});
|
|
1679
1454
|
|
|
1680
1455
|
// src/plugins/view/manifest.ts
|
|
1681
|
-
var
|
|
1456
|
+
var manifest3 = {
|
|
1682
1457
|
mode: "view",
|
|
1683
1458
|
label: "\u9879\u76EE\u6D4F\u89C8",
|
|
1684
1459
|
icon: "\u{1F441}\uFE0F",
|
|
@@ -1687,19 +1462,19 @@ var manifest4 = {
|
|
|
1687
1462
|
};
|
|
1688
1463
|
|
|
1689
1464
|
// src/plugins/view/index.ts
|
|
1690
|
-
var
|
|
1691
|
-
manifest:
|
|
1465
|
+
var apply5 = defineBuiltin({
|
|
1466
|
+
manifest: manifest3,
|
|
1692
1467
|
setup() {
|
|
1693
1468
|
}
|
|
1694
1469
|
});
|
|
1695
1470
|
|
|
1696
1471
|
// src/plugins/stats/index.ts
|
|
1697
|
-
import
|
|
1698
|
-
import
|
|
1472
|
+
import fs8 from "fs";
|
|
1473
|
+
import path8 from "path";
|
|
1699
1474
|
import { execFile as execFile6 } from "child_process";
|
|
1700
1475
|
|
|
1701
1476
|
// src/plugins/stats/manifest.ts
|
|
1702
|
-
var
|
|
1477
|
+
var manifest4 = {
|
|
1703
1478
|
mode: "stats",
|
|
1704
1479
|
label: "\u9879\u76EE\u7EDF\u8BA1",
|
|
1705
1480
|
icon: "\u{1F4CA}",
|
|
@@ -1716,14 +1491,14 @@ function execFilePromise(file, args, opts) {
|
|
|
1716
1491
|
}
|
|
1717
1492
|
function scan(root) {
|
|
1718
1493
|
const stats = {
|
|
1719
|
-
root:
|
|
1494
|
+
root: path8.basename(root),
|
|
1720
1495
|
files: 0,
|
|
1721
1496
|
dirs: 0,
|
|
1722
1497
|
totalSize: 0,
|
|
1723
1498
|
byExt: [],
|
|
1724
1499
|
markdown: 0,
|
|
1725
1500
|
openspec: { active: 0, archived: 0 },
|
|
1726
|
-
hasJust:
|
|
1501
|
+
hasJust: fs8.existsSync(path8.join(root, "justfile")),
|
|
1727
1502
|
worktrees: 0
|
|
1728
1503
|
};
|
|
1729
1504
|
const extMap = /* @__PURE__ */ new Map();
|
|
@@ -1733,22 +1508,22 @@ function scan(root) {
|
|
|
1733
1508
|
}, onFile: (abs) => {
|
|
1734
1509
|
stats.files++;
|
|
1735
1510
|
try {
|
|
1736
|
-
stats.totalSize +=
|
|
1511
|
+
stats.totalSize += fs8.statSync(abs).size;
|
|
1737
1512
|
} catch {
|
|
1738
1513
|
}
|
|
1739
|
-
const ext =
|
|
1514
|
+
const ext = path8.extname(abs).toLowerCase() || "(\u65E0\u6269\u5C55\u540D)";
|
|
1740
1515
|
extMap.set(ext, (extMap.get(ext) ?? 0) + 1);
|
|
1741
1516
|
if (ext === ".md" || ext === ".markdown") stats.markdown++;
|
|
1742
1517
|
} });
|
|
1743
1518
|
};
|
|
1744
1519
|
walk(root);
|
|
1745
|
-
const changesDir =
|
|
1746
|
-
if (
|
|
1747
|
-
for (const ent of
|
|
1520
|
+
const changesDir = path8.join(root, "openspec", "changes");
|
|
1521
|
+
if (fs8.existsSync(changesDir)) {
|
|
1522
|
+
for (const ent of fs8.readdirSync(changesDir, { withFileTypes: true })) {
|
|
1748
1523
|
if (!ent.isDirectory() || ent.name.startsWith(".")) continue;
|
|
1749
1524
|
if (ent.name === "archive") {
|
|
1750
1525
|
try {
|
|
1751
|
-
stats.openspec.archived =
|
|
1526
|
+
stats.openspec.archived = fs8.readdirSync(path8.join(changesDir, "archive"), { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".")).length;
|
|
1752
1527
|
} catch {
|
|
1753
1528
|
}
|
|
1754
1529
|
} else stats.openspec.active++;
|
|
@@ -1757,8 +1532,8 @@ function scan(root) {
|
|
|
1757
1532
|
stats.byExt = Array.from(extMap.entries()).map(([ext, count]) => ({ ext, count })).sort((a, b) => b.count - a.count).slice(0, 10);
|
|
1758
1533
|
return stats;
|
|
1759
1534
|
}
|
|
1760
|
-
var
|
|
1761
|
-
manifest:
|
|
1535
|
+
var apply6 = defineBuiltin({
|
|
1536
|
+
manifest: manifest4,
|
|
1762
1537
|
setup(ctx, root) {
|
|
1763
1538
|
ctx.route("/__stats/data", async () => {
|
|
1764
1539
|
const stats = scan(root);
|
|
@@ -1783,8 +1558,461 @@ var apply7 = defineBuiltin({
|
|
|
1783
1558
|
}
|
|
1784
1559
|
});
|
|
1785
1560
|
|
|
1561
|
+
// src/plugins/market/manifest.ts
|
|
1562
|
+
var manifest5 = {
|
|
1563
|
+
mode: "market",
|
|
1564
|
+
label: "\u7075\u611F\u5E02\u573A",
|
|
1565
|
+
icon: "\u2728",
|
|
1566
|
+
description: "Logo / \u52A8\u6548 / \u8BBE\u8BA1\u7075\u611F\u6D4F\u89C8 \xB7 \u8F6C\u63D0\u793A\u8BCD\u95ED\u73AF",
|
|
1567
|
+
order: 40
|
|
1568
|
+
};
|
|
1569
|
+
|
|
1570
|
+
// src/plugins/market/sources/logotypes.ts
|
|
1571
|
+
var LOGOTYPES = [
|
|
1572
|
+
// ---- tech 消费与硬件 ----
|
|
1573
|
+
{ id: "apple", name: "Apple", category: "tech" },
|
|
1574
|
+
{ id: "google", name: "Google", category: "tech" },
|
|
1575
|
+
{ id: "samsung", name: "Samsung", category: "tech" },
|
|
1576
|
+
{ id: "huawei", name: "Huawei", category: "tech" },
|
|
1577
|
+
{ id: "xiaomi", name: "Xiaomi", category: "tech" },
|
|
1578
|
+
{ id: "sony", name: "Sony", category: "tech" },
|
|
1579
|
+
{ id: "panasonic", name: "Panasonic", category: "tech" },
|
|
1580
|
+
{ id: "lg", name: "LG", category: "tech" },
|
|
1581
|
+
{ id: "nvidia", name: "NVIDIA", category: "tech" },
|
|
1582
|
+
{ id: "amd", name: "AMD", category: "tech" },
|
|
1583
|
+
{ id: "intel", name: "Intel", category: "tech" },
|
|
1584
|
+
{ id: "oracle", name: "Oracle", category: "tech" },
|
|
1585
|
+
{ id: "dell", name: "Dell", category: "tech" },
|
|
1586
|
+
{ id: "asus", name: "ASUS", category: "tech" },
|
|
1587
|
+
{ id: "lenovo", name: "Lenovo", category: "tech" },
|
|
1588
|
+
{ id: "razer", name: "Razer", category: "tech" },
|
|
1589
|
+
{ id: "logitech", name: "Logitech", category: "tech" },
|
|
1590
|
+
{ id: "nikon", name: "Nikon", category: "tech" },
|
|
1591
|
+
{ id: "tesla", name: "Tesla", category: "tech" },
|
|
1592
|
+
{ id: "nokia", name: "Nokia", category: "tech" },
|
|
1593
|
+
{ id: "oneplus", name: "OnePlus", category: "tech" },
|
|
1594
|
+
{ id: "oppo", name: "OPPO", category: "tech" },
|
|
1595
|
+
// ---- social 社交内容 ----
|
|
1596
|
+
{ id: "facebook", name: "Facebook", category: "social" },
|
|
1597
|
+
{ id: "instagram", name: "Instagram", category: "social" },
|
|
1598
|
+
{ id: "whatsapp", name: "WhatsApp", category: "social" },
|
|
1599
|
+
{ id: "signal", name: "Signal", category: "social" },
|
|
1600
|
+
{ id: "telegram", name: "Telegram", category: "social" },
|
|
1601
|
+
{ id: "discord", name: "Discord", category: "social" },
|
|
1602
|
+
{ id: "slack", name: "Slack", category: "social" },
|
|
1603
|
+
{ id: "x", name: "X", category: "social" },
|
|
1604
|
+
{ id: "threads", name: "Threads", category: "social" },
|
|
1605
|
+
{ id: "bluesky", name: "Bluesky", category: "social" },
|
|
1606
|
+
{ id: "mastodon", name: "Mastodon", category: "social" },
|
|
1607
|
+
{ id: "reddit", name: "Reddit", category: "social" },
|
|
1608
|
+
{ id: "pinterest", name: "Pinterest", category: "social" },
|
|
1609
|
+
{ id: "tiktok", name: "TikTok", category: "social" },
|
|
1610
|
+
{ id: "youtube", name: "YouTube", category: "social" },
|
|
1611
|
+
{ id: "twitch", name: "Twitch", category: "social" },
|
|
1612
|
+
{ id: "wechat", name: "WeChat", category: "social" },
|
|
1613
|
+
{ id: "sinaweibo", name: "Sina Weibo", category: "social" },
|
|
1614
|
+
{ id: "bilibili", name: "bilibili", category: "social" },
|
|
1615
|
+
{ id: "tencentqq", name: "Tencent QQ", category: "social" },
|
|
1616
|
+
// ---- dev 开发 ----
|
|
1617
|
+
{ id: "github", name: "GitHub", category: "dev" },
|
|
1618
|
+
{ id: "gitlab", name: "GitLab", category: "dev" },
|
|
1619
|
+
{ id: "bitbucket", name: "Bitbucket", category: "dev" },
|
|
1620
|
+
{ id: "git", name: "Git", category: "dev" },
|
|
1621
|
+
{ id: "githubactions", name: "GitHub Actions", category: "dev" },
|
|
1622
|
+
{ id: "react", name: "React", category: "dev" },
|
|
1623
|
+
{ id: "vuedotjs", name: "Vue.js", category: "dev" },
|
|
1624
|
+
{ id: "angular", name: "Angular", category: "dev" },
|
|
1625
|
+
{ id: "svelte", name: "Svelte", category: "dev" },
|
|
1626
|
+
{ id: "nextdotjs", name: "Next.js", category: "dev" },
|
|
1627
|
+
{ id: "nuxtdotjs", name: "Nuxt", category: "dev" },
|
|
1628
|
+
{ id: "astro", name: "Astro", category: "dev" },
|
|
1629
|
+
{ id: "typescript", name: "TypeScript", category: "dev" },
|
|
1630
|
+
{ id: "javascript", name: "JavaScript", category: "dev" },
|
|
1631
|
+
{ id: "nodedotjs", name: "Node.js", category: "dev" },
|
|
1632
|
+
{ id: "python", name: "Python", category: "dev" },
|
|
1633
|
+
{ id: "rust", name: "Rust", category: "dev" },
|
|
1634
|
+
{ id: "go", name: "Go", category: "dev" },
|
|
1635
|
+
{ id: "swift", name: "Swift", category: "dev" },
|
|
1636
|
+
{ id: "kotlin", name: "Kotlin", category: "dev" },
|
|
1637
|
+
{ id: "php", name: "PHP", category: "dev" },
|
|
1638
|
+
{ id: "laravel", name: "Laravel", category: "dev" },
|
|
1639
|
+
{ id: "ruby", name: "Ruby", category: "dev" },
|
|
1640
|
+
{ id: "rubyonrails", name: "Ruby on Rails", category: "dev" },
|
|
1641
|
+
{ id: "cplusplus", name: "C++", category: "dev" },
|
|
1642
|
+
{ id: "sass", name: "Sass", category: "dev" },
|
|
1643
|
+
{ id: "tailwindcss", name: "Tailwind CSS", category: "dev" },
|
|
1644
|
+
{ id: "pnpm", name: "pnpm", category: "dev" },
|
|
1645
|
+
{ id: "npm", name: "npm", category: "dev" },
|
|
1646
|
+
{ id: "yarn", name: "Yarn", category: "dev" },
|
|
1647
|
+
{ id: "vite", name: "Vite", category: "dev" },
|
|
1648
|
+
{ id: "vitest", name: "Vitest", category: "dev" },
|
|
1649
|
+
{ id: "storybook", name: "Storybook", category: "dev" },
|
|
1650
|
+
{ id: "docker", name: "Docker", category: "dev" },
|
|
1651
|
+
{ id: "kubernetes", name: "Kubernetes", category: "dev" },
|
|
1652
|
+
{ id: "terraform", name: "Terraform", category: "dev" },
|
|
1653
|
+
{ id: "ansible", name: "Ansible", category: "dev" },
|
|
1654
|
+
{ id: "jenkins", name: "Jenkins", category: "dev" },
|
|
1655
|
+
{ id: "nginx", name: "NGINX", category: "dev" },
|
|
1656
|
+
{ id: "postgresql", name: "PostgreSQL", category: "dev" },
|
|
1657
|
+
{ id: "mysql", name: "MySQL", category: "dev" },
|
|
1658
|
+
{ id: "mongodb", name: "MongoDB", category: "dev" },
|
|
1659
|
+
{ id: "redis", name: "Redis", category: "dev" },
|
|
1660
|
+
{ id: "sqlite", name: "SQLite", category: "dev" },
|
|
1661
|
+
{ id: "elasticsearch", name: "Elasticsearch", category: "dev" },
|
|
1662
|
+
{ id: "graphql", name: "GraphQL", category: "dev" },
|
|
1663
|
+
{ id: "firebase", name: "Firebase", category: "dev" },
|
|
1664
|
+
{ id: "linux", name: "Linux", category: "dev" },
|
|
1665
|
+
{ id: "ubuntu", name: "Ubuntu", category: "dev" },
|
|
1666
|
+
{ id: "archlinux", name: "Arch Linux", category: "dev" },
|
|
1667
|
+
{ id: "vim", name: "Vim", category: "dev" },
|
|
1668
|
+
{ id: "xcode", name: "Xcode", category: "dev" },
|
|
1669
|
+
{ id: "dotnet", name: ".NET", category: "dev" },
|
|
1670
|
+
{ id: "sublimetext", name: "Sublime Text", category: "dev" },
|
|
1671
|
+
// ---- cloud 云服务 ----
|
|
1672
|
+
{ id: "googlecloud", name: "Google Cloud", category: "cloud" },
|
|
1673
|
+
{ id: "cloudflare", name: "Cloudflare", category: "cloud" },
|
|
1674
|
+
{ id: "vercel", name: "Vercel", category: "cloud" },
|
|
1675
|
+
{ id: "netlify", name: "Netlify", category: "cloud" },
|
|
1676
|
+
{ id: "heroku", name: "Heroku", category: "cloud" },
|
|
1677
|
+
{ id: "digitalocean", name: "DigitalOcean", category: "cloud" },
|
|
1678
|
+
{ id: "hetzner", name: "Hetzner", category: "cloud" },
|
|
1679
|
+
{ id: "fastly", name: "Fastly", category: "cloud" },
|
|
1680
|
+
{ id: "flydotio", name: "Fly.io", category: "cloud" },
|
|
1681
|
+
{ id: "render", name: "Render", category: "cloud" },
|
|
1682
|
+
{ id: "supabase", name: "Supabase", category: "cloud" },
|
|
1683
|
+
{ id: "alibabacloud", name: "Alibaba Cloud", category: "cloud" },
|
|
1684
|
+
{ id: "scaleway", name: "Scaleway", category: "cloud" },
|
|
1685
|
+
// ---- finance 金融支付 ----
|
|
1686
|
+
{ id: "visa", name: "Visa", category: "finance" },
|
|
1687
|
+
{ id: "mastercard", name: "Mastercard", category: "finance" },
|
|
1688
|
+
{ id: "paypal", name: "PayPal", category: "finance" },
|
|
1689
|
+
{ id: "stripe", name: "Stripe", category: "finance" },
|
|
1690
|
+
{ id: "wise", name: "Wise", category: "finance" },
|
|
1691
|
+
{ id: "square", name: "Square", category: "finance" },
|
|
1692
|
+
{ id: "applepay", name: "Apple Pay", category: "finance" },
|
|
1693
|
+
{ id: "googlepay", name: "Google Pay", category: "finance" },
|
|
1694
|
+
{ id: "alipay", name: "Alipay", category: "finance" },
|
|
1695
|
+
{ id: "bitcoin", name: "Bitcoin", category: "finance" },
|
|
1696
|
+
{ id: "ethereum", name: "Ethereum", category: "finance" },
|
|
1697
|
+
{ id: "binance", name: "Binance", category: "finance" },
|
|
1698
|
+
{ id: "coinbase", name: "Coinbase", category: "finance" },
|
|
1699
|
+
{ id: "americanexpress", name: "American Express", category: "finance" },
|
|
1700
|
+
// ---- media 媒体娱乐 ----
|
|
1701
|
+
{ id: "netflix", name: "Netflix", category: "media" },
|
|
1702
|
+
{ id: "spotify", name: "Spotify", category: "media" },
|
|
1703
|
+
{ id: "applemusic", name: "Apple Music", category: "media" },
|
|
1704
|
+
{ id: "soundcloud", name: "SoundCloud", category: "media" },
|
|
1705
|
+
{ id: "youtubemusic", name: "YouTube Music", category: "media" },
|
|
1706
|
+
{ id: "lastdotfm", name: "Last.fm", category: "media" },
|
|
1707
|
+
{ id: "primevideo", name: "Prime Video", category: "media" },
|
|
1708
|
+
{ id: "crunchyroll", name: "Crunchyroll", category: "media" },
|
|
1709
|
+
{ id: "vlcmediaplayer", name: "VLC Media Player", category: "media" },
|
|
1710
|
+
{ id: "unsplash", name: "Unsplash", category: "media" },
|
|
1711
|
+
{ id: "behance", name: "Behance", category: "media" },
|
|
1712
|
+
{ id: "dribbble", name: "Dribbble", category: "media" },
|
|
1713
|
+
{ id: "substack", name: "Substack", category: "media" },
|
|
1714
|
+
{ id: "pixiv", name: "pixiv", category: "media" },
|
|
1715
|
+
// ---- gaming 游戏 ----
|
|
1716
|
+
{ id: "steam", name: "Steam", category: "gaming" },
|
|
1717
|
+
{ id: "epicgames", name: "Epic Games", category: "gaming" },
|
|
1718
|
+
{ id: "playstation", name: "PlayStation", category: "gaming" },
|
|
1719
|
+
{ id: "nintendo", name: "Nintendo", category: "gaming" },
|
|
1720
|
+
{ id: "nintendoswitch", name: "Nintendo Switch", category: "gaming" },
|
|
1721
|
+
{ id: "roblox", name: "Roblox", category: "gaming" },
|
|
1722
|
+
{ id: "unity", name: "Unity", category: "gaming" },
|
|
1723
|
+
{ id: "unrealengine", name: "Unreal Engine", category: "gaming" },
|
|
1724
|
+
{ id: "godotengine", name: "Godot Engine", category: "gaming" },
|
|
1725
|
+
{ id: "itchdotio", name: "itch.io", category: "gaming" },
|
|
1726
|
+
{ id: "riotgames", name: "Riot Games", category: "gaming" },
|
|
1727
|
+
{ id: "dota2", name: "Dota 2", category: "gaming" },
|
|
1728
|
+
{ id: "ea", name: "EA", category: "gaming" },
|
|
1729
|
+
// ---- design 设计创作 ----
|
|
1730
|
+
{ id: "figma", name: "Figma", category: "design" },
|
|
1731
|
+
{ id: "sketch", name: "Sketch", category: "design" },
|
|
1732
|
+
{ id: "canva", name: "Canva", category: "design" },
|
|
1733
|
+
{ id: "adobe", name: "Adobe", category: "design" },
|
|
1734
|
+
{ id: "adobephotoshop", name: "Adobe Photoshop", category: "design" },
|
|
1735
|
+
{ id: "adobeillustrator", name: "Adobe Illustrator", category: "design" },
|
|
1736
|
+
{ id: "adobeaftereffects", name: "Adobe After Effects", category: "design" },
|
|
1737
|
+
{ id: "adobepremierepro", name: "Adobe Premiere Pro", category: "design" },
|
|
1738
|
+
{ id: "blender", name: "Blender", category: "design" },
|
|
1739
|
+
{ id: "affinitydesigner", name: "Affinity Designer", category: "design" },
|
|
1740
|
+
{ id: "framer", name: "Framer", category: "design" },
|
|
1741
|
+
{ id: "webflow", name: "Webflow", category: "design" },
|
|
1742
|
+
{ id: "wordpress", name: "WordPress", category: "design" },
|
|
1743
|
+
{ id: "penpot", name: "Penpot", category: "design" },
|
|
1744
|
+
{ id: "excalidraw", name: "Excalidraw", category: "design" },
|
|
1745
|
+
{ id: "miro", name: "Miro", category: "design" },
|
|
1746
|
+
// ---- shopping 电商零售 ----
|
|
1747
|
+
{ id: "shopify", name: "Shopify", category: "shopping" },
|
|
1748
|
+
{ id: "woocommerce", name: "WooCommerce", category: "shopping" },
|
|
1749
|
+
{ id: "magento", name: "Magento", category: "shopping" },
|
|
1750
|
+
{ id: "amazon", name: "Amazon", category: "shopping" },
|
|
1751
|
+
{ id: "ebay", name: "eBay", category: "shopping" },
|
|
1752
|
+
{ id: "etsy", name: "Etsy", category: "shopping" },
|
|
1753
|
+
{ id: "ikea", name: "IKEA", category: "shopping" },
|
|
1754
|
+
{ id: "target", name: "Target", category: "shopping" },
|
|
1755
|
+
{ id: "walmart", name: "Walmart", category: "shopping" },
|
|
1756
|
+
{ id: "zalando", name: "Zalando", category: "shopping" },
|
|
1757
|
+
// ---- productivity 效率办公 ----
|
|
1758
|
+
{ id: "notion", name: "Notion", category: "productivity" },
|
|
1759
|
+
{ id: "todoist", name: "Todoist", category: "productivity" },
|
|
1760
|
+
{ id: "asana", name: "Asana", category: "productivity" },
|
|
1761
|
+
{ id: "clickup", name: "ClickUp", category: "productivity" },
|
|
1762
|
+
{ id: "jira", name: "Jira", category: "productivity" },
|
|
1763
|
+
{ id: "confluence", name: "Confluence", category: "productivity" },
|
|
1764
|
+
{ id: "linear", name: "Linear", category: "productivity" },
|
|
1765
|
+
{ id: "zapier", name: "Zapier", category: "productivity" },
|
|
1766
|
+
{ id: "n8n", name: "n8n", category: "productivity" },
|
|
1767
|
+
{ id: "googledrive", name: "Google Drive", category: "productivity" },
|
|
1768
|
+
{ id: "googledocs", name: "Google Docs", category: "productivity" },
|
|
1769
|
+
{ id: "gmail", name: "Gmail", category: "productivity" },
|
|
1770
|
+
{ id: "dropbox", name: "Dropbox", category: "productivity" },
|
|
1771
|
+
{ id: "zoom", name: "Zoom", category: "productivity" },
|
|
1772
|
+
{ id: "googlemeet", name: "Google Meet", category: "productivity" },
|
|
1773
|
+
// ---- ai 人工智能 ----
|
|
1774
|
+
{ id: "openai", name: "OpenAI", category: "ai" },
|
|
1775
|
+
{ id: "anthropic", name: "Anthropic", category: "ai" },
|
|
1776
|
+
{ id: "huggingface", name: "Hugging Face", category: "ai" },
|
|
1777
|
+
{ id: "tensorflow", name: "TensorFlow", category: "ai" },
|
|
1778
|
+
{ id: "pytorch", name: "PyTorch", category: "ai" },
|
|
1779
|
+
{ id: "opencv", name: "OpenCV", category: "ai" },
|
|
1780
|
+
{ id: "scikitlearn", name: "scikit-learn", category: "ai" },
|
|
1781
|
+
{ id: "jupyter", name: "Jupyter", category: "ai" },
|
|
1782
|
+
{ id: "ollama", name: "Ollama", category: "ai" },
|
|
1783
|
+
{ id: "langchain", name: "LangChain", category: "ai" },
|
|
1784
|
+
{ id: "googlegemini", name: "Google Gemini", category: "ai" }
|
|
1785
|
+
];
|
|
1786
|
+
|
|
1787
|
+
// src/plugins/market/sources/motions.ts
|
|
1788
|
+
var MOTIONS = [
|
|
1789
|
+
// ---- animate.css:attention seekers 吸睛 ----
|
|
1790
|
+
{ id: "animate-bounce", name: "\u5F39\u8DF3", desc: "\u4E0A\u4E0B\u5F39\u8DF3,\u5E38\u7528\u4E8E\u5F15\u5BFC\u6CE8\u610F", cls: "animate__bounce", lib: "animate.css" },
|
|
1791
|
+
{ id: "animate-flash", name: "\u95EA\u70C1", desc: "\u900F\u660E\u5EA6\u5FEB\u901F\u95EA\u70C1", cls: "animate__flash", lib: "animate.css" },
|
|
1792
|
+
{ id: "animate-pulse", name: "\u8109\u51B2", desc: "\u7F29\u653E\u547C\u5438,\u5E38\u7528\u4E8E\u52A0\u8F7D\u4E0E\u76F4\u64AD\u72B6\u6001", cls: "animate__pulse", lib: "animate.css" },
|
|
1793
|
+
{ id: "animate-rubberband", name: "\u6A61\u76AE\u7B4B", desc: "\u5F39\u6027\u62C9\u4F38,\u5F3A\u8C03\u8DA3\u5473\u53CD\u9988", cls: "animate__rubberBand", lib: "animate.css" },
|
|
1794
|
+
{ id: "animate-shakex", name: "\u6A2A\u5411\u6296\u52A8", desc: "\u5DE6\u53F3\u6296\u52A8,\u5E38\u7528\u4E8E\u9519\u8BEF\u63D0\u793A", cls: "animate__shakeX", lib: "animate.css" },
|
|
1795
|
+
{ id: "animate-shakey", name: "\u7EB5\u5411\u6296\u52A8", desc: "\u4E0A\u4E0B\u6296\u52A8,\u8868\u5355\u6821\u9A8C\u53CD\u9988", cls: "animate__shakeY", lib: "animate.css" },
|
|
1796
|
+
{ id: "animate-headshake", name: "\u6447\u5934", desc: "\u7ED5\u7EB5\u8F74\u5C0F\u5E45\u6446\u5934", cls: "animate__headShake", lib: "animate.css" },
|
|
1797
|
+
{ id: "animate-swing", name: "\u6446\u52A8", desc: "\u9876\u90E8\u60AC\u6302\u5F0F\u5DE6\u53F3\u6446\u52A8", cls: "animate__swing", lib: "animate.css" },
|
|
1798
|
+
{ id: "animate-tada", name: "\u6B22\u547C", desc: "\u7F29\u653E\u52A0\u65CB\u8F6C\u7684\u7EC4\u5408\u5F3A\u8C03", cls: "animate__tada", lib: "animate.css" },
|
|
1799
|
+
{ id: "animate-wobble", name: "\u6447\u6643", desc: "\u5927\u5E45\u5DE6\u53F3\u6447\u6643", cls: "animate__wobble", lib: "animate.css" },
|
|
1800
|
+
{ id: "animate-jello", name: "\u679C\u51BB", desc: "\u503E\u659C\u52A0\u7F29\u653E\u7684\u679C\u51BB\u611F", cls: "animate__jello", lib: "animate.css" },
|
|
1801
|
+
{ id: "animate-heartbeat", name: "\u5FC3\u8DF3", desc: "\u53CC\u51FB\u5F0F\u5FC3\u8DF3\u7F29\u653E", cls: "animate__heartBeat", lib: "animate.css" },
|
|
1802
|
+
// ---- animate.css:入场 ----
|
|
1803
|
+
{ id: "animate-flipinx", name: "\u7FFB\u8F6C\u5165\u573A X", desc: "\u7ED5 X \u8F74\u7FFB\u8F6C\u5165\u573A", cls: "animate__flipInX", lib: "animate.css" },
|
|
1804
|
+
{ id: "animate-flipiny", name: "\u7FFB\u8F6C\u5165\u573A Y", desc: "\u7ED5 Y \u8F74\u7FFB\u8F6C\u5165\u573A", cls: "animate__flipInY", lib: "animate.css" },
|
|
1805
|
+
{ id: "animate-fadein", name: "\u6DE1\u5165", desc: "\u900F\u660E\u5EA6\u6E10\u5165", cls: "animate__fadeIn", lib: "animate.css" },
|
|
1806
|
+
{ id: "animate-fadeindown", name: "\u6DE1\u5165\u4E0B\u79FB", desc: "\u81EA\u4E0A\u800C\u4E0B\u6DE1\u5165", cls: "animate__fadeInDown", lib: "animate.css" },
|
|
1807
|
+
{ id: "animate-fadeinleft", name: "\u6DE1\u5165\u53F3\u79FB", desc: "\u81EA\u5DE6\u5411\u53F3\u6DE1\u5165", cls: "animate__fadeInLeft", lib: "animate.css" },
|
|
1808
|
+
{ id: "animate-fadeinright", name: "\u6DE1\u5165\u5DE6\u79FB", desc: "\u81EA\u53F3\u5411\u5DE6\u6DE1\u5165", cls: "animate__fadeInRight", lib: "animate.css" },
|
|
1809
|
+
{ id: "animate-fadeinup", name: "\u6DE1\u5165\u4E0A\u79FB", desc: "\u81EA\u4E0B\u800C\u4E0A\u6DE1\u5165,\u5361\u7247\u5217\u8868\u5E38\u7528", cls: "animate__fadeInUp", lib: "animate.css" },
|
|
1810
|
+
{ id: "animate-fadeinupbig", name: "\u5927\u5E45\u6DE1\u5165\u4E0A\u79FB", desc: "\u5927\u8DDD\u79BB\u81EA\u4E0B\u800C\u4E0A\u6DE1\u5165", cls: "animate__fadeInUpBig", lib: "animate.css" },
|
|
1811
|
+
{ id: "animate-zoomin", name: "\u653E\u5927\u5165\u573A", desc: "\u7531\u5C0F\u653E\u5927\u6DE1\u5165", cls: "animate__zoomIn", lib: "animate.css" },
|
|
1812
|
+
{ id: "animate-zoomindown", name: "\u653E\u5927\u5165\u573A(\u4E0B)", desc: "\u81EA\u4E0A\u800C\u4E0B\u653E\u5927\u5165\u573A", cls: "animate__zoomInDown", lib: "animate.css" },
|
|
1813
|
+
{ id: "animate-slideindown", name: "\u6ED1\u5165(\u4E0B)", desc: "\u81EA\u4E0A\u6ED1\u5165,\u901A\u77E5\u6761\u5E38\u7528", cls: "animate__slideInDown", lib: "animate.css" },
|
|
1814
|
+
{ id: "animate-slideinleft", name: "\u6ED1\u5165(\u5DE6)", desc: "\u81EA\u5DE6\u6ED1\u5165,\u4FA7\u680F\u62BD\u5C49\u5E38\u7528", cls: "animate__slideInLeft", lib: "animate.css" },
|
|
1815
|
+
{ id: "animate-slideinright", name: "\u6ED1\u5165(\u53F3)", desc: "\u81EA\u53F3\u6ED1\u5165,\u4FA7\u680F\u62BD\u5C49\u5E38\u7528", cls: "animate__slideInRight", lib: "animate.css" },
|
|
1816
|
+
{ id: "animate-slideinup", name: "\u6ED1\u5165(\u4E0A)", desc: "\u81EA\u4E0B\u6ED1\u5165,\u5E95\u90E8\u5F39\u5C42\u5E38\u7528", cls: "animate__slideInUp", lib: "animate.css" },
|
|
1817
|
+
{ id: "animate-backindown", name: "\u56DE\u5F39\u5165\u573A(\u4E0B)", desc: "\u5E26\u56DE\u5F39\u66F2\u7EBF\u81EA\u4E0A\u800C\u4E0B\u5165\u573A", cls: "animate__backInDown", lib: "animate.css" },
|
|
1818
|
+
{ id: "animate-backinleft", name: "\u56DE\u5F39\u5165\u573A(\u5DE6)", desc: "\u5E26\u56DE\u5F39\u66F2\u7EBF\u81EA\u5DE6\u5165\u573A", cls: "animate__backInLeft", lib: "animate.css" },
|
|
1819
|
+
{ id: "animate-backinup", name: "\u56DE\u5F39\u5165\u573A(\u4E0A)", desc: "\u5E26\u56DE\u5F39\u66F2\u7EBF\u81EA\u4E0B\u800C\u4E0A\u5165\u573A", cls: "animate__backInUp", lib: "animate.css" },
|
|
1820
|
+
{ id: "animate-bouncein", name: "\u5F39\u8DF3\u5165\u573A", desc: "\u5F39\u6027\u5F39\u8DF3\u5165\u573A", cls: "animate__bounceIn", lib: "animate.css" },
|
|
1821
|
+
{ id: "animate-bounceindown", name: "\u5F39\u8DF3\u5165\u573A(\u4E0B)", desc: "\u81EA\u4E0A\u5F39\u8DF3\u5165\u573A", cls: "animate__bounceInDown", lib: "animate.css" },
|
|
1822
|
+
{ id: "animate-bounceinup", name: "\u5F39\u8DF3\u5165\u573A(\u4E0A)", desc: "\u81EA\u4E0B\u5F39\u8DF3\u5165\u573A", cls: "animate__bounceInUp", lib: "animate.css" },
|
|
1823
|
+
{ id: "animate-rotatein", name: "\u65CB\u8F6C\u5165\u573A", desc: "\u65CB\u8F6C\u6DE1\u5165", cls: "animate__rotateIn", lib: "animate.css" },
|
|
1824
|
+
{ id: "animate-rotateindownleft", name: "\u65CB\u8F6C\u5165\u573A(\u5DE6\u4E0B)", desc: "\u81EA\u5DE6\u4E0B\u89D2\u65CB\u8F6C\u6DE1\u5165", cls: "animate__rotateInDownLeft", lib: "animate.css" },
|
|
1825
|
+
{ id: "animate-lightspeedinright", name: "\u5149\u901F\u5165\u573A", desc: "\u659C\u5207\u52A0\u9AD8\u901F\u98DE\u5165", cls: "animate__lightSpeedInRight", lib: "animate.css" },
|
|
1826
|
+
{ id: "animate-rollin", name: "\u6EDA\u5165", desc: "\u6C34\u5E73\u6EDA\u8F6C\u5165\u573A", cls: "animate__rollIn", lib: "animate.css" },
|
|
1827
|
+
{ id: "animate-jackinthebox", name: "\u8DF3\u8DF3\u76D2", desc: "\u5F39\u51FA\u76D2\u5F0F\u8DA3\u5473\u5165\u573A", cls: "animate__jackInTheBox", lib: "animate.css" },
|
|
1828
|
+
// ---- animate.css:退场 ----
|
|
1829
|
+
{ id: "animate-flipoutx", name: "\u7FFB\u8F6C\u9000\u573A X", desc: "\u7ED5 X \u8F74\u7FFB\u8F6C\u9000\u573A", cls: "animate__flipOutX", lib: "animate.css" },
|
|
1830
|
+
{ id: "animate-fadeout", name: "\u6DE1\u51FA", desc: "\u900F\u660E\u5EA6\u6E10\u51FA", cls: "animate__fadeOut", lib: "animate.css" },
|
|
1831
|
+
{ id: "animate-fadeoutdown", name: "\u6DE1\u51FA\u4E0B\u79FB", desc: "\u5411\u4E0B\u6DE1\u51FA,\u5F39\u5C42\u5173\u95ED\u5E38\u7528", cls: "animate__fadeOutDown", lib: "animate.css" },
|
|
1832
|
+
{ id: "animate-zoomout", name: "\u7F29\u5C0F\u9000\u573A", desc: "\u7F29\u5C0F\u6DE1\u51FA", cls: "animate__zoomOut", lib: "animate.css" },
|
|
1833
|
+
{ id: "animate-slideoutup", name: "\u6ED1\u51FA(\u4E0A)", desc: "\u5411\u4E0A\u6ED1\u51FA,\u901A\u77E5\u5173\u95ED\u5E38\u7528", cls: "animate__slideOutUp", lib: "animate.css" },
|
|
1834
|
+
{ id: "animate-bounceout", name: "\u5F39\u8DF3\u9000\u573A", desc: "\u5F39\u6027\u5F39\u8DF3\u9000\u573A", cls: "animate__bounceOut", lib: "animate.css" },
|
|
1835
|
+
{ id: "animate-hinge", name: "\u94F0\u94FE", desc: "\u60AC\u6302\u6446\u52A8\u5760\u843D,\u559C\u5267\u5F0F\u9000\u573A", cls: "animate__hinge", lib: "animate.css" },
|
|
1836
|
+
// ---- hover.css:hover 反馈 ----
|
|
1837
|
+
{ id: "hover-grow", name: "\u653E\u5927", desc: "hover \u65F6\u8F7B\u5FAE\u653E\u5927", cls: "hvr-grow", lib: "hover.css" },
|
|
1838
|
+
{ id: "hover-shrink", name: "\u7F29\u5C0F", desc: "hover \u65F6\u8F7B\u5FAE\u7F29\u5C0F", cls: "hvr-shrink", lib: "hover.css" },
|
|
1839
|
+
{ id: "hover-pulse", name: "\u8109\u51B2", desc: "hover \u671F\u95F4\u7F29\u653E\u8109\u51B2", cls: "hvr-pulse", lib: "hover.css" },
|
|
1840
|
+
{ id: "hover-push", name: "\u63A8\u6324", desc: "hover \u65F6\u538B\u6241\u518D\u56DE\u5F39", cls: "hvr-push", lib: "hover.css" },
|
|
1841
|
+
{ id: "hover-pop", name: "\u5F39\u51FA", desc: "hover \u65F6\u5F39\u51FA\u653E\u5927", cls: "hvr-pop", lib: "hover.css" },
|
|
1842
|
+
{ id: "hover-bounce-in", name: "\u5F39\u5165", desc: "hover \u65F6\u5F39\u6027\u653E\u5927", cls: "hvr-bounce-in", lib: "hover.css" },
|
|
1843
|
+
{ id: "hover-bounce-out", name: "\u5F39\u51FA", desc: "hover \u65F6\u5F39\u6027\u7F29\u5C0F", cls: "hvr-bounce-out", lib: "hover.css" },
|
|
1844
|
+
{ id: "hover-rotate", name: "\u65CB\u8F6C", desc: "hover \u65F6\u65CB\u8F6C 4 \u5EA6", cls: "hvr-rotate", lib: "hover.css" },
|
|
1845
|
+
{ id: "hover-grow-rotate", name: "\u653E\u5927\u65CB\u8F6C", desc: "hover \u65F6\u653E\u5927\u5E76\u65CB\u8F6C", cls: "hvr-grow-rotate", lib: "hover.css" },
|
|
1846
|
+
{ id: "hover-float", name: "\u4E0A\u6D6E", desc: "hover \u65F6\u4E0A\u6D6E,\u6309\u94AE\u5E38\u7528", cls: "hvr-float", lib: "hover.css" },
|
|
1847
|
+
{ id: "hover-sink", name: "\u4E0B\u6C89", desc: "hover \u65F6\u4E0B\u6C89\u6309\u538B\u611F", cls: "hvr-sink", lib: "hover.css" },
|
|
1848
|
+
{ id: "hover-bob", name: "\u6D6E\u52A8", desc: "hover \u671F\u95F4\u6301\u7EED\u4E0A\u4E0B\u6D6E\u52A8", cls: "hvr-bob", lib: "hover.css" },
|
|
1849
|
+
{ id: "hover-hang", name: "\u60AC\u6302", desc: "hover \u671F\u95F4\u60AC\u6302\u6446\u52A8", cls: "hvr-hang", lib: "hover.css" },
|
|
1850
|
+
{ id: "hover-skew", name: "\u659C\u5207", desc: "hover \u65F6\u659C\u5207\u53D8\u5F62", cls: "hvr-skew", lib: "hover.css" },
|
|
1851
|
+
{ id: "hover-wobble-horizontal", name: "\u6A2A\u5411\u6447\u6446", desc: "hover \u65F6\u6C34\u5E73\u6447\u6446", cls: "hvr-wobble-horizontal", lib: "hover.css" },
|
|
1852
|
+
{ id: "hover-wobble-vertical", name: "\u7EB5\u5411\u6447\u6446", desc: "hover \u65F6\u5782\u76F4\u6447\u6446", cls: "hvr-wobble-vertical", lib: "hover.css" },
|
|
1853
|
+
{ id: "hover-buzz", name: "\u9707\u52A8", desc: "hover \u65F6\u5C0F\u5E45\u9AD8\u9891\u9707\u52A8", cls: "hvr-buzz", lib: "hover.css" },
|
|
1854
|
+
{ id: "hover-sweep-to-right", name: "\u80CC\u666F\u53F3\u626B", desc: "\u80CC\u666F\u8272\u81EA\u5DE6\u5411\u53F3\u626B\u8FC7", cls: "hvr-sweep-to-right", lib: "hover.css" },
|
|
1855
|
+
{ id: "hover-bounce-to-right", name: "\u5F39\u6027\u53F3\u586B", desc: "\u80CC\u666F\u5F39\u6027\u586B\u6EE1(\u5411\u53F3)", cls: "hvr-bounce-to-right", lib: "hover.css" },
|
|
1856
|
+
{ id: "hover-radial-out", name: "\u5F84\u5411\u6269\u6563", desc: "\u80CC\u666F\u81EA\u4E2D\u5FC3\u5706\u5F62\u6269\u6563", cls: "hvr-radial-out", lib: "hover.css" },
|
|
1857
|
+
{ id: "hover-underline-from-left", name: "\u4E0B\u5212\u7EBF\u6ED1\u5165", desc: "\u4E0B\u5212\u7EBF\u81EA\u5DE6\u6ED1\u5165", cls: "hvr-underline-from-left", lib: "hover.css" },
|
|
1858
|
+
{ id: "hover-glow", name: "\u53D1\u5149", desc: "hover \u65F6\u5916\u53D1\u5149", cls: "hvr-glow", lib: "hover.css" },
|
|
1859
|
+
{ id: "hover-shadow", name: "\u9634\u5F71", desc: "hover \u65F6\u51FA\u73B0\u6295\u5F71", cls: "hvr-shadow", lib: "hover.css" },
|
|
1860
|
+
{ id: "hover-grow-shadow", name: "\u653E\u5927\u6295\u5F71", desc: "hover \u65F6\u653E\u5927\u5E76\u6295\u5F71", cls: "hvr-grow-shadow", lib: "hover.css" },
|
|
1861
|
+
{ id: "hover-float-shadow", name: "\u4E0A\u6D6E\u6295\u5F71", desc: "hover \u65F6\u4E0A\u6D6E\u5E76\u6295\u5F71", cls: "hvr-float-shadow", lib: "hover.css" }
|
|
1862
|
+
];
|
|
1863
|
+
|
|
1864
|
+
// src/plugins/market/sources/inspirations.ts
|
|
1865
|
+
var INSPIRATIONS = [
|
|
1866
|
+
{ id: "shadcn", name: "shadcn/ui", desc: "\u53EF\u590D\u5236\u7C98\u8D34\u7684 React \u7EC4\u4EF6\u96C6,\u4EE3\u7801\u5F52\u4F60\u6240\u6709", url: "https://ui.shadcn.com", tags: ["react", "tailwind", "\u8BBE\u8BA1\u7CFB\u7EDF"] },
|
|
1867
|
+
{ id: "radix", name: "Radix UI", desc: "\u65E0\u6837\u5F0F\u53EF\u8BBF\u95EE\u6027 React \u57FA\u7840\u7EC4\u4EF6", url: "https://www.radix-ui.com", tags: ["react", "\u65E0\u969C\u788D", "\u57FA\u7840\u7EC4\u4EF6"] },
|
|
1868
|
+
{ id: "tailwindcss", name: "Tailwind CSS", desc: "\u539F\u5B50\u5316 CSS \u6846\u67B6\u7684\u5B98\u65B9\u7AD9\u70B9", url: "https://tailwindcss.com", tags: ["css", "\u539F\u5B50\u5316", "\u5B98\u7F51"] },
|
|
1869
|
+
{ id: "antd", name: "Ant Design", desc: "\u4F01\u4E1A\u7EA7 React \u8BBE\u8BA1\u7CFB\u7EDF\u4E0E\u7EC4\u4EF6\u5E93", url: "https://ant.design", tags: ["react", "\u8BBE\u8BA1\u7CFB\u7EDF", "\u4F01\u4E1A\u7EA7"] },
|
|
1870
|
+
{ id: "arco", name: "Arco Design", desc: "\u5B57\u8282\u8DF3\u52A8\u4F01\u4E1A\u7EA7\u8BBE\u8BA1\u7CFB\u7EDF", url: "https://arco.design", tags: ["react", "\u8BBE\u8BA1\u7CFB\u7EDF", "\u4F01\u4E1A\u7EA7"] },
|
|
1871
|
+
{ id: "semi", name: "Semi Design", desc: "\u6296\u97F3\u524D\u7AEF\u56E2\u961F\u8BBE\u8BA1\u7CFB\u7EDF", url: "https://semi.design", tags: ["react", "\u8BBE\u8BA1\u7CFB\u7EDF", "\u4E3B\u9898\u5316"] },
|
|
1872
|
+
{ id: "chakra", name: "Chakra UI", desc: "\u4EE5\u65E0\u969C\u788D\u548C\u4E3B\u9898\u8457\u79F0\u7684 React \u7EC4\u4EF6\u5E93", url: "https://chakra-ui.com", tags: ["react", "\u65E0\u969C\u788D", "\u4E3B\u9898"] },
|
|
1873
|
+
{ id: "mui", name: "MUI", desc: "Material Design \u98CE\u683C React \u7EC4\u4EF6\u5E93", url: "https://mui.com", tags: ["react", "material", "\u7EC4\u4EF6\u5E93"] },
|
|
1874
|
+
{ id: "mantine", name: "Mantine", desc: "\u7EC4\u4EF6+hooks \u9F50\u5168\u7684 React \u5168\u5BB6\u6876", url: "https://mantine.dev", tags: ["react", "\u7EC4\u4EF6\u5E93", "hooks"] },
|
|
1875
|
+
{ id: "naiveui", name: "Naive UI", desc: "Vue 3 \u5168\u7C7B\u578B\u7EC4\u4EF6\u5E93,\u4E3B\u9898\u5B9A\u5236\u7EC6", url: "https://www.naiveui.com", tags: ["vue", "\u7EC4\u4EF6\u5E93", "\u4E3B\u9898"] },
|
|
1876
|
+
{ id: "element-plus", name: "Element Plus", desc: "Vue 3 \u8001\u724C\u4F01\u4E1A\u7EA7\u7EC4\u4EF6\u5E93", url: "https://element-plus.org", tags: ["vue", "\u7EC4\u4EF6\u5E93", "\u4F01\u4E1A\u7EA7"] },
|
|
1877
|
+
{ id: "daisyui", name: "daisyUI", desc: "Tailwind \u8BED\u4E49\u5316\u7EC4\u4EF6\u7C7B\u4E0E\u591A\u4E3B\u9898", url: "https://daisyui.com", tags: ["tailwind", "css", "\u4E3B\u9898"] },
|
|
1878
|
+
{ id: "nextui", name: "NextUI", desc: "\u7F8E\u89C2\u4F18\u5148\u7684 React + Tailwind \u7EC4\u4EF6\u5E93", url: "https://nextui.org", tags: ["react", "tailwind", "\u7EC4\u4EF6\u5E93"] },
|
|
1879
|
+
{ id: "headlessui", name: "Headless UI", desc: "\u5B8C\u5168\u65E0\u6837\u5F0F\u3001\u5E26\u884C\u4E3A\u7684 React/Vue \u7EC4\u4EF6", url: "https://headlessui.com", tags: ["react", "vue", "\u65E0\u6837\u5F0F"] },
|
|
1880
|
+
{ id: "carbon", name: "Carbon Design System", desc: "IBM \u5F00\u6E90\u8BBE\u8BA1\u7CFB\u7EDF,token \u4F53\u7CFB\u6559\u79D1\u4E66", url: "https://carbondesignsystem.com", tags: ["\u8BBE\u8BA1\u7CFB\u7EDF", "token", "\u6587\u6863"] },
|
|
1881
|
+
{ id: "polaris", name: "Polaris", desc: "Shopify \u8BBE\u8BA1\u7CFB\u7EDF,\u7535\u5546\u540E\u53F0\u8303\u5F0F", url: "https://polaris.shopify.com", tags: ["\u8BBE\u8BA1\u7CFB\u7EDF", "react", "\u7535\u5546"] },
|
|
1882
|
+
{ id: "material3", name: "Material Design 3", desc: "Google \u52A8\u6001\u53D6\u8272\u4E0E\u5F62\u53D8\u8BBE\u8BA1\u89C4\u8303", url: "https://m3.material.io", tags: ["google", "\u8BBE\u8BA1\u7CFB\u7EDF", "\u52A8\u6548"] },
|
|
1883
|
+
{ id: "storybook", name: "Storybook", desc: "\u7EC4\u4EF6\u5DE5\u4F5C\u53F0\u4E0E\u6587\u6863\u7684\u4E8B\u5B9E\u6807\u51C6", url: "https://storybook.js.org", tags: ["\u7EC4\u4EF6\u6587\u6863", "\u5DE5\u4F5C\u53F0", "\u534F\u4F5C"] },
|
|
1884
|
+
{ id: "geist", name: "Geist", desc: "Vercel \u6781\u7B80\u8BBE\u8BA1\u7CFB\u7EDF", url: "https://vercel.com/geist", tags: ["\u8BBE\u8BA1\u7CFB\u7EDF", "\u6781\u7B80", "vercel"] },
|
|
1885
|
+
{ id: "openprops", name: "Open Props", desc: "\u8D85\u5B9E\u7528 CSS \u53D8\u91CF\u96C6\u5408(\u52A8\u6548/\u989C\u8272/\u5E03\u5C40)", url: "https://open-props.style", tags: ["css", "\u53D8\u91CF", "\u52A8\u6548"] },
|
|
1886
|
+
{ id: "everylayout", name: "Every Layout", desc: "\u7528 CSS \u539F\u751F\u80FD\u529B\u89E3\u51B3\u5E03\u5C40\u95EE\u9898", url: "https://every-layout.dev", tags: ["css", "\u5E03\u5C40", "\u54CD\u5E94\u5F0F"] },
|
|
1887
|
+
{ id: "animatecss", name: "Animate.css", desc: "\u6700\u6D41\u884C\u7684\u5373\u7528\u578B CSS \u52A8\u753B\u5E93\u5B98\u7F51", url: "https://animate.style", tags: ["css", "\u52A8\u6548", "\u5E93"] },
|
|
1888
|
+
{ id: "csstricks", name: "CSS-Tricks", desc: "CSS \u6280\u5DE7\u4E0E\u6A21\u5F0F\u7684\u957F\u9752\u793E\u533A", url: "https://css-tricks.com", tags: ["css", "\u6559\u7A0B", "\u6A21\u5F0F"] },
|
|
1889
|
+
{ id: "webdev", name: "web.dev", desc: "Google Web \u6700\u4F73\u5B9E\u8DF5\u4E0E\u6027\u80FD\u6307\u5357", url: "https://web.dev", tags: ["\u6027\u80FD", "\u6700\u4F73\u5B9E\u8DF5", "google"] },
|
|
1890
|
+
{ id: "excalidraw", name: "Excalidraw", desc: "\u624B\u7ED8\u98CE\u534F\u4F5C\u767D\u677F,\u5F00\u6E90\u865A\u62DF\u767D\u677F\u6807\u6746", url: "https://excalidraw.com", tags: ["\u767D\u677F", "\u624B\u7ED8\u98CE", "\u534F\u4F5C"] },
|
|
1891
|
+
{ id: "tldraw", name: "tldraw", desc: "\u65E0\u9650\u753B\u5E03 SDK \u4E0E\u7CBE\u7F8E\u767D\u677F", url: "https://www.tldraw.com", tags: ["\u767D\u677F", "\u753B\u5E03", "sdk"] },
|
|
1892
|
+
{ id: "penpot", name: "Penpot", desc: "\u5F00\u6E90 Figma \u66FF\u4EE3,\u8BBE\u8BA1\u5F00\u53D1\u540C\u6E90", url: "https://penpot.app", tags: ["\u8BBE\u8BA1\u5DE5\u5177", "\u5F00\u6E90", "\u534F\u4F5C"] },
|
|
1893
|
+
{ id: "cal", name: "Cal.com", desc: "\u5F00\u6E90\u65E5\u7A0B\u9884\u7EA6,\u4EA7\u54C1\u7AD9\u4E0E\u4EA4\u4E92\u8303\u5F0F", url: "https://cal.com", tags: ["saas", "\u65E5\u7A0B", "\u8868\u5355"] },
|
|
1894
|
+
{ id: "dub", name: "Dub", desc: "\u5F00\u6E90\u77ED\u94FE\u5E73\u53F0,\u73B0\u4EE3 SaaS \u754C\u9762\u8303\u672C", url: "https://dub.co", tags: ["saas", "\u77ED\u94FE", "\u5206\u6790"] },
|
|
1895
|
+
{ id: "twenty", name: "Twenty", desc: "\u5F00\u6E90 Notion \u98CE CRM,\u8868\u683C\u4EA4\u4E92\u6559\u79D1\u4E66", url: "https://twenty.com", tags: ["crm", "\u8868\u683C", "saas"] },
|
|
1896
|
+
{ id: "umami", name: "Umami", desc: "\u9690\u79C1\u53CB\u597D\u7684\u5F00\u6E90\u7AD9\u70B9\u7EDF\u8BA1,\u4EEA\u8868\u76D8\u7B80\u6D01", url: "https://umami.is", tags: ["\u7EDF\u8BA1", "\u9690\u79C1", "\u4EEA\u8868\u76D8"] },
|
|
1897
|
+
{ id: "plausible", name: "Plausible", desc: "\u6781\u7B80\u5F00\u6E90\u5206\u6790,\u4E00\u5C4F\u4EEA\u8868\u76D8\u8303\u5F0F", url: "https://plausible.io", tags: ["\u7EDF\u8BA1", "\u9690\u79C1", "\u6781\u7B80"] },
|
|
1898
|
+
{ id: "outline", name: "Outline", desc: "\u5F00\u6E90\u56E2\u961F wiki,\u6392\u7248\u4E0E\u5FEB\u6377\u952E\u4F53\u9A8C\u4F73", url: "https://www.getoutline.com", tags: ["\u6587\u6863", "wiki", "\u56E2\u961F"] },
|
|
1899
|
+
{ id: "plane", name: "Plane", desc: "\u5F00\u6E90\u9879\u76EE\u7BA1\u7406,issue/\u770B\u677F/\u5468\u671F", url: "https://plane.so", tags: ["\u9879\u76EE\u7BA1\u7406", "\u770B\u677F", "issue"] },
|
|
1900
|
+
{ id: "huly", name: "Huly", desc: "\u5F00\u6E90\u5168\u6808\u9879\u76EE\u7BA1\u7406,\u89C6\u89C9\u534E\u4E3D", url: "https://huly.io", tags: ["\u9879\u76EE\u7BA1\u7406", "\u89C6\u89C9", "\u5168\u6808"] },
|
|
1901
|
+
{ id: "uptime-kuma", name: "Uptime Kuma", desc: "\u81EA\u6258\u7BA1\u76D1\u63A7\u4E0E\u72B6\u6001\u9875", url: "https://uptime.kuma.pet", tags: ["\u76D1\u63A7", "\u72B6\u6001\u9875", "\u81EA\u6258\u7BA1"] },
|
|
1902
|
+
{ id: "homepage", name: "Homepage", desc: "\u73B0\u4EE3\u5316\u81EA\u6258\u7BA1\u5BFC\u822A\u4EEA\u8868\u76D8", url: "https://gethomepage.dev", tags: ["\u4EEA\u8868\u76D8", "\u5BFC\u822A", "\u81EA\u6258\u7BA1"] },
|
|
1903
|
+
{ id: "nocodb", name: "NocoDB", desc: "\u5F00\u6E90 Airtable \u66FF\u4EE3,\u6570\u636E\u5E93\u8868\u683C\u5316", url: "https://nocodb.com", tags: ["\u6570\u636E\u5E93", "\u8868\u683C", "\u4F4E\u4EE3\u7801"] },
|
|
1904
|
+
{ id: "bruno", name: "Bruno", desc: "\u79BB\u7EBF\u4F18\u5148\u5F00\u6E90 API \u5BA2\u6237\u7AEF", url: "https://www.usebruno.com", tags: ["api", "\u79BB\u7EBF\u4F18\u5148", "\u5F00\u53D1\u5DE5\u5177"] },
|
|
1905
|
+
{ id: "grafana", name: "Grafana", desc: "\u5F00\u6E90\u53EF\u89C6\u5316\u76D1\u63A7\u9762\u677F\u6807\u6746", url: "https://grafana.com/oss/grafana/", tags: ["\u76D1\u63A7", "\u53EF\u89C6\u5316", "\u4EEA\u8868\u76D8"] }
|
|
1906
|
+
];
|
|
1907
|
+
|
|
1908
|
+
// src/plugins/market/sources/index.ts
|
|
1909
|
+
var MARKETS = ["logos", "motions", "inspirations"];
|
|
1910
|
+
function isMarketName(v) {
|
|
1911
|
+
return MARKETS.includes(v);
|
|
1912
|
+
}
|
|
1913
|
+
function catalogFor(market) {
|
|
1914
|
+
switch (market) {
|
|
1915
|
+
case "logos":
|
|
1916
|
+
return { entries: LOGOTYPES.map((e) => ({ ...e, slug: e.id })) };
|
|
1917
|
+
case "motions":
|
|
1918
|
+
return { entries: MOTIONS.map((e) => ({ ...e })) };
|
|
1919
|
+
case "inspirations":
|
|
1920
|
+
return { entries: INSPIRATIONS.map((e) => ({ ...e })) };
|
|
1921
|
+
default:
|
|
1922
|
+
return null;
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
// src/plugins/market/index.ts
|
|
1927
|
+
var ALLOWED_PROXY_HOSTS = ["cdn.jsdelivr.net", "data.jsdelivr.com"];
|
|
1928
|
+
var ALLOWED_PROXY_PORTS = /* @__PURE__ */ new Set(["", "80", "443"]);
|
|
1929
|
+
var PROXY_TIMEOUT_MS = 8e3;
|
|
1930
|
+
var PROXY_CACHE_MAX_ENTRIES = 200;
|
|
1931
|
+
var PROXY_CACHE_TTL_MS = 10 * 60 * 1e3;
|
|
1932
|
+
var CATALOG_PREFIX = "/__market/catalog/";
|
|
1933
|
+
var apply7 = defineBuiltin({
|
|
1934
|
+
manifest: manifest5,
|
|
1935
|
+
setup(ctx) {
|
|
1936
|
+
const cache = /* @__PURE__ */ new Map();
|
|
1937
|
+
ctx.route("/__market/proxy", async (req, res) => {
|
|
1938
|
+
const raw = new URL(req.url || "/", "http://localhost").searchParams.get("url");
|
|
1939
|
+
if (!raw) {
|
|
1940
|
+
res.writeHead(400);
|
|
1941
|
+
res.end("missing url");
|
|
1942
|
+
return;
|
|
1943
|
+
}
|
|
1944
|
+
let target;
|
|
1945
|
+
try {
|
|
1946
|
+
target = new URL(raw);
|
|
1947
|
+
} catch {
|
|
1948
|
+
res.writeHead(400);
|
|
1949
|
+
res.end("bad url");
|
|
1950
|
+
return;
|
|
1951
|
+
}
|
|
1952
|
+
if (target.protocol !== "https:" && target.protocol !== "http:") {
|
|
1953
|
+
res.writeHead(403);
|
|
1954
|
+
res.end("scheme not allowed");
|
|
1955
|
+
return;
|
|
1956
|
+
}
|
|
1957
|
+
if (!ALLOWED_PROXY_HOSTS.includes(target.hostname)) {
|
|
1958
|
+
res.writeHead(403);
|
|
1959
|
+
res.end("host not allowed");
|
|
1960
|
+
return;
|
|
1961
|
+
}
|
|
1962
|
+
if (!ALLOWED_PROXY_PORTS.has(target.port)) {
|
|
1963
|
+
res.writeHead(403);
|
|
1964
|
+
res.end("port not allowed");
|
|
1965
|
+
return;
|
|
1966
|
+
}
|
|
1967
|
+
const hit = cache.get(raw);
|
|
1968
|
+
if (hit && Date.now() - hit.cachedAt < PROXY_CACHE_TTL_MS) {
|
|
1969
|
+
res.writeHead(200, { "Content-Type": hit.contentType, "X-Market-Cache": "hit", "Cache-Control": "no-cache" });
|
|
1970
|
+
res.end(hit.body);
|
|
1971
|
+
return;
|
|
1972
|
+
}
|
|
1973
|
+
if (hit) cache.delete(raw);
|
|
1974
|
+
const controller = new AbortController();
|
|
1975
|
+
const timer = setTimeout(() => controller.abort(), PROXY_TIMEOUT_MS);
|
|
1976
|
+
try {
|
|
1977
|
+
const upstream = await fetch(raw, { signal: controller.signal, redirect: "error" });
|
|
1978
|
+
if (!upstream.ok) {
|
|
1979
|
+
res.writeHead(502);
|
|
1980
|
+
res.end("upstream error");
|
|
1981
|
+
return;
|
|
1982
|
+
}
|
|
1983
|
+
const body = await upstream.text();
|
|
1984
|
+
const contentType = upstream.headers.get("content-type") ?? "application/octet-stream";
|
|
1985
|
+
cache.set(raw, { body, contentType, cachedAt: Date.now() });
|
|
1986
|
+
if (cache.size > PROXY_CACHE_MAX_ENTRIES) {
|
|
1987
|
+
const oldest = cache.keys().next().value;
|
|
1988
|
+
if (oldest !== void 0) cache.delete(oldest);
|
|
1989
|
+
}
|
|
1990
|
+
res.writeHead(200, { "Content-Type": contentType, "X-Market-Cache": "miss", "Cache-Control": "no-cache" });
|
|
1991
|
+
res.end(body);
|
|
1992
|
+
} catch {
|
|
1993
|
+
if (!res.headersSent) {
|
|
1994
|
+
res.writeHead(502);
|
|
1995
|
+
res.end("upstream failed");
|
|
1996
|
+
}
|
|
1997
|
+
} finally {
|
|
1998
|
+
clearTimeout(timer);
|
|
1999
|
+
}
|
|
2000
|
+
});
|
|
2001
|
+
ctx.route("/__market/catalog", async (req, res) => {
|
|
2002
|
+
const pathname = new URL(req.url || "/", "http://localhost").pathname;
|
|
2003
|
+
const market = pathname.startsWith(CATALOG_PREFIX) ? pathname.slice(CATALOG_PREFIX.length).split("/")[0] : "";
|
|
2004
|
+
if (!market || !isMarketName(market)) {
|
|
2005
|
+
res.writeHead(404);
|
|
2006
|
+
res.end("unknown market");
|
|
2007
|
+
return;
|
|
2008
|
+
}
|
|
2009
|
+
return catalogFor(market);
|
|
2010
|
+
});
|
|
2011
|
+
}
|
|
2012
|
+
});
|
|
2013
|
+
|
|
1786
2014
|
// src/cli.ts
|
|
1787
|
-
var __dirname2 =
|
|
2015
|
+
var __dirname2 = path9.dirname(fileURLToPath2(import.meta.url));
|
|
1788
2016
|
var DEFAULT_PORT = 4190;
|
|
1789
2017
|
function parseArgs() {
|
|
1790
2018
|
const args = process.argv.slice(2);
|
|
@@ -1834,7 +2062,7 @@ async function loadExternal(ctx, dir, root) {
|
|
|
1834
2062
|
if (!ent.isDirectory()) continue;
|
|
1835
2063
|
const candidates = tsxLoaded ? ["index.ts", "index.js", "index.mjs"] : ["index.js", "index.mjs"];
|
|
1836
2064
|
for (const name of candidates) {
|
|
1837
|
-
const p =
|
|
2065
|
+
const p = path9.join(dir, ent.name, name);
|
|
1838
2066
|
if (await pathExists(p)) {
|
|
1839
2067
|
try {
|
|
1840
2068
|
const mod = await import(p);
|
|
@@ -1849,8 +2077,8 @@ async function loadExternal(ctx, dir, root) {
|
|
|
1849
2077
|
const m = ctx.dashboard.get(ent.name);
|
|
1850
2078
|
if (m && m.mode === ent.name) {
|
|
1851
2079
|
const patch = { external: true };
|
|
1852
|
-
const webDir =
|
|
1853
|
-
if (await pathExists(
|
|
2080
|
+
const webDir = path9.join(dir, ent.name, "web");
|
|
2081
|
+
if (await pathExists(path9.join(webDir, "index.html"))) {
|
|
1854
2082
|
ctx.server.static(`${PLUGIN_STATIC_PREFIX}${ent.name}/`, webDir);
|
|
1855
2083
|
if (!m.viewerUrl) patch.viewerUrl = `${PLUGIN_STATIC_PREFIX}${ent.name}/`;
|
|
1856
2084
|
}
|
|
@@ -1869,7 +2097,7 @@ async function loadExternal(ctx, dir, root) {
|
|
|
1869
2097
|
}
|
|
1870
2098
|
async function main() {
|
|
1871
2099
|
const args = parseArgs();
|
|
1872
|
-
const root =
|
|
2100
|
+
const root = path9.resolve(args.dir);
|
|
1873
2101
|
const existing = await findReusable(root);
|
|
1874
2102
|
if (existing && !args.restart) {
|
|
1875
2103
|
const u = `http://localhost:${existing.port}` + (args.page ? `#${args.page}` : "");
|
|
@@ -1883,14 +2111,14 @@ async function main() {
|
|
|
1883
2111
|
console.log(`[zdashboard] --restart\uFF1A\u505C\u6B62\u65E7\u5B9E\u4F8B pid=${oldRecord.pid}`);
|
|
1884
2112
|
await stopInstance(oldRecord);
|
|
1885
2113
|
}
|
|
1886
|
-
const appDir =
|
|
1887
|
-
const BUILTIN_PLUGINS = [
|
|
2114
|
+
const appDir = path9.resolve(__dirname2, "web");
|
|
2115
|
+
const BUILTIN_PLUGINS = [apply6, apply3, apply4, apply5, apply7];
|
|
1888
2116
|
if (stripDeadPluginConfig(root, BUILTIN_PLUGINS.map((p) => p.manifest))) {
|
|
1889
2117
|
console.log("[zdashboard] \u5DF2\u6E05\u7406 dashboard.json \u4E2D\u5185\u7F6E\u63D2\u4EF6\u7684\u8FC7\u65F6\u914D\u7F6E\u952E");
|
|
1890
2118
|
}
|
|
1891
2119
|
const startPort = oldRecord && !args.portExplicit ? oldRecord.port : args.port;
|
|
1892
|
-
const zdevDir =
|
|
1893
|
-
const dataDir =
|
|
2120
|
+
const zdevDir = path9.join(root, ".zdev");
|
|
2121
|
+
const dataDir = fs9.existsSync(zdevDir) ? ".zdev/" : "";
|
|
1894
2122
|
const det = await detect(root);
|
|
1895
2123
|
const ctx = new Context();
|
|
1896
2124
|
ctx.plugin(ServerService, {
|
|
@@ -1915,7 +2143,7 @@ async function main() {
|
|
|
1915
2143
|
}
|
|
1916
2144
|
}
|
|
1917
2145
|
if (args.plugins) {
|
|
1918
|
-
await loadExternal(ctx,
|
|
2146
|
+
await loadExternal(ctx, path9.resolve(args.plugins), root);
|
|
1919
2147
|
}
|
|
1920
2148
|
const shutdown = () => {
|
|
1921
2149
|
try {
|