termdock 1.0.1 → 1.0.2
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/client/assets/{abnfDiagram-VRR7QNED-Cf0p7Eu-.js → abnfDiagram-VRR7QNED-BjNCcQvm.js} +1 -1
- package/dist/client/assets/{arc-yhaVxFBi.js → arc-xcCAKMnT.js} +1 -1
- package/dist/client/assets/{architectureDiagram-ZJ3FMSHR-DV-OSXY6.js → architectureDiagram-ZJ3FMSHR-ijtAKPsW.js} +1 -1
- package/dist/client/assets/{blockDiagram-677ZJIJ3-ZFSHeVvK.js → blockDiagram-677ZJIJ3-GVIbuo6R.js} +1 -1
- package/dist/client/assets/{c4Diagram-LMCZKHZV-Z7p1zkZ5.js → c4Diagram-LMCZKHZV-B3IbU0ga.js} +1 -1
- package/dist/client/assets/channel-Fzeh-Sl6.js +1 -0
- package/dist/client/assets/{chunk-2Q5K7J3B-D03kywS-.js → chunk-2Q5K7J3B-DEwVqhvo.js} +1 -1
- package/dist/client/assets/{chunk-32BRIVSS-BPMnoBke.js → chunk-32BRIVSS-CGNuIJuG.js} +1 -1
- package/dist/client/assets/{chunk-5VM5RSS4-Ca--vT5Q.js → chunk-5VM5RSS4-DliA2ku3.js} +1 -1
- package/dist/client/assets/{chunk-EX3LRPZG-Bc42nIJ5.js → chunk-EX3LRPZG-DzFXj1M3.js} +1 -1
- package/dist/client/assets/{chunk-JWPE2WC7-N1WKBcc5.js → chunk-JWPE2WC7-h3s-pxcn.js} +1 -1
- package/dist/client/assets/{chunk-MOJQB5TN-BDc-GV5_.js → chunk-MOJQB5TN-CQST9jsX.js} +1 -1
- package/dist/client/assets/{chunk-RYQCIY6F-BpXNrVrz.js → chunk-RYQCIY6F-CXjnUh8k.js} +1 -1
- package/dist/client/assets/{chunk-V7JOEXUC-BTlki_tC.js → chunk-V7JOEXUC-CI7QyRAs.js} +1 -1
- package/dist/client/assets/{chunk-VR4S4FIN-BXnHZWrK.js → chunk-VR4S4FIN-DYQ8EokS.js} +1 -1
- package/dist/client/assets/{chunk-XXDRQBXY-zy3DIq5F.js → chunk-XXDRQBXY-BM9jxTTb.js} +1 -1
- package/dist/client/assets/classDiagram-OUVF2IWQ-DzF9pacK.js +1 -0
- package/dist/client/assets/classDiagram-v2-EOCWNBFH-DzF9pacK.js +1 -0
- package/dist/client/assets/{cose-bilkent-JH36ORCC-DcE2Tqcn.js → cose-bilkent-JH36ORCC-C4nYmp4I.js} +1 -1
- package/dist/client/assets/{cynefin-VYW2F7L2-CirPmVbw.js → cynefin-VYW2F7L2-DnlhMeVt.js} +1 -1
- package/dist/client/assets/{cynefinDiagram-TSTJHNR4-742hkNFA.js → cynefinDiagram-TSTJHNR4-DJuHDI6A.js} +1 -1
- package/dist/client/assets/{dagre-VKFMJZFB-Zmky1sDU.js → dagre-VKFMJZFB-CsBEz_S1.js} +1 -1
- package/dist/client/assets/{diagram-FQU43EPY-BAVYDJIF.js → diagram-FQU43EPY-BDNTGROP.js} +1 -1
- package/dist/client/assets/{diagram-G47NLZAW--BZg7BJ2.js → diagram-G47NLZAW-CJJwi6PP.js} +1 -1
- package/dist/client/assets/{diagram-NH7WQ7WH-7QMiGNb8.js → diagram-NH7WQ7WH-CXJWffic.js} +1 -1
- package/dist/client/assets/{diagram-OA4YK3LP-DTz1wt7W.js → diagram-OA4YK3LP-wOtL7NBA.js} +1 -1
- package/dist/client/assets/{diagram-WEI45ONY-IhWlLIuv.js → diagram-WEI45ONY-ClOt2G7I.js} +1 -1
- package/dist/client/assets/{ebnfDiagram-CCIWWBDH-CvudDgv1.js → ebnfDiagram-CCIWWBDH-DoXhiNjK.js} +1 -1
- package/dist/client/assets/{erDiagram-Q63AITRT-BxxNWFA6.js → erDiagram-Q63AITRT-DB5a-Aw4.js} +1 -1
- package/dist/client/assets/{flowDiagram-23GEKE2U-bDu_tMe8.js → flowDiagram-23GEKE2U-Cz9w-F5K.js} +1 -1
- package/dist/client/assets/{ganttDiagram-NO4QXBWP-B-EI33mG.js → ganttDiagram-NO4QXBWP-CDykkj3o.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-IHSO6WYX-DBjjTP9W.js → gitGraphDiagram-IHSO6WYX-CNkfDkzA.js} +1 -1
- package/dist/client/assets/{index-Bi0L0Km4.js → index-0d_16SRD.js} +3 -3
- package/dist/client/assets/{infoDiagram-FWYZ7A6U-DGjFR5qD.js → infoDiagram-FWYZ7A6U-CfrwrocT.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-FXEZZL3T-BHYp5v41.js → ishikawaDiagram-FXEZZL3T-C2AD_Ae2.js} +1 -1
- package/dist/client/assets/{journeyDiagram-5HDEW3XC-DKhoytdF.js → journeyDiagram-5HDEW3XC-DzQvMG3N.js} +1 -1
- package/dist/client/assets/{kanban-definition-HUTT4EX6-ascD0XVf.js → kanban-definition-HUTT4EX6-CUVhWmNF.js} +1 -1
- package/dist/client/assets/{linear-bkyU-Rlp.js → linear-D5qZ3q5c.js} +1 -1
- package/dist/client/assets/{mermaid.core-DAp1jSn7.js → mermaid.core-D-e_wdPJ.js} +4 -4
- package/dist/client/assets/{mindmap-definition-LN4V7U3C-C2GC8yQl.js → mindmap-definition-LN4V7U3C-CDHLWnzb.js} +1 -1
- package/dist/client/assets/{pegDiagram-2B236MQR-Z2ysn4Ju.js → pegDiagram-2B236MQR-9_bnKT8u.js} +1 -1
- package/dist/client/assets/{pieDiagram-ENE6RG2P-B1ae8akt.js → pieDiagram-ENE6RG2P-gw-xIG1b.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-ABIIQ3AL-CsjSqwMk.js → quadrantDiagram-ABIIQ3AL-Cn_lstJf.js} +1 -1
- package/dist/client/assets/{railroadDiagram-RFXS5EU6-MFxHHceB.js → railroadDiagram-RFXS5EU6-yZM8qXUp.js} +1 -1
- package/dist/client/assets/{requirementDiagram-TGXJPOKE-2uwCBtHV.js → requirementDiagram-TGXJPOKE-WQ1iDS_X.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-HTMAVEWB-D9kfU1GN.js → sankeyDiagram-HTMAVEWB-UVz3wsFF.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-DBY2YBRQ-DpVoVgLp.js → sequenceDiagram-DBY2YBRQ-BuJBBGcB.js} +1 -1
- package/dist/client/assets/{sizeCapture-X5ZJPWSS-DaOWqq1e.js → sizeCapture-X5ZJPWSS-CysR04La.js} +1 -1
- package/dist/client/assets/{stateDiagram-2N3HPSRC-D2VX0Qzz.js → stateDiagram-2N3HPSRC-DYC8TYxP.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-6OUMAXLB-Cru4nzfa.js +1 -0
- package/dist/client/assets/{swimlanes-5IMT3BWC-DSaEdpIw.js → swimlanes-5IMT3BWC-FT83sDlI.js} +2 -2
- package/dist/client/assets/swimlanesDiagram-G3AALYLV-DUvRCWFX.js +8 -0
- package/dist/client/assets/{timeline-definition-FHXFAJF6-DPNbaxGI.js → timeline-definition-FHXFAJF6-C-o8uRSU.js} +1 -1
- package/dist/client/assets/{vennDiagram-L72KCM5P-UKbbBFUs.js → vennDiagram-L72KCM5P-Cw-g3-Li.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-EHGQE667-JUcWelHZ.js → wardleyDiagram-EHGQE667-B_JEirkb.js} +1 -1
- package/dist/client/assets/{xychartDiagram-FW5EYKEG-BCEj_jKY.js → xychartDiagram-FW5EYKEG-B1LkJSxz.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/client/sw.js +1 -1
- package/dist/server/routes/terminal.js +9 -1
- package/package.json +5 -3
- package/scripts/inspect-diff-trace.mjs +148 -0
- package/scripts/inspect-fs-io.mjs +107 -0
- package/scripts/patch-termdock-font.py +134 -0
- package/scripts/postinstall.mjs +80 -0
- package/dist/client/assets/channel-OEjXE69P.js +0 -1
- package/dist/client/assets/classDiagram-OUVF2IWQ-BqnMVXbr.js +0 -1
- package/dist/client/assets/classDiagram-v2-EOCWNBFH-BqnMVXbr.js +0 -1
- package/dist/client/assets/stateDiagram-v2-6OUMAXLB-Dm3WkZpy.js +0 -1
- package/dist/client/assets/swimlanesDiagram-G3AALYLV-DrnizR1A.js +0 -8
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
|
|
6
|
+
const logPath = path.join(os.homedir(), '.termdock', 'fs-io.log');
|
|
7
|
+
const args = process.argv.slice(2);
|
|
8
|
+
const query = args.find((arg) => !arg.startsWith('--')) ?? '';
|
|
9
|
+
const sinceMinutesArg = args.find((arg) => arg.startsWith('--since-min='));
|
|
10
|
+
const slowMsArg = args.find((arg) => arg.startsWith('--slow-ms='));
|
|
11
|
+
const sinceMinutes = sinceMinutesArg ? Number(sinceMinutesArg.split('=')[1]) : 30;
|
|
12
|
+
const slowMs = slowMsArg ? Number(slowMsArg.split('=')[1]) : 500;
|
|
13
|
+
const sinceTs = Number.isFinite(sinceMinutes) && sinceMinutes > 0
|
|
14
|
+
? Date.now() - sinceMinutes * 60_000
|
|
15
|
+
: 0;
|
|
16
|
+
|
|
17
|
+
if (!fs.existsSync(logPath)) {
|
|
18
|
+
console.error(`No fs-io log found at ${logPath}`);
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const records = [];
|
|
23
|
+
for (const line of fs.readFileSync(logPath, 'utf8').trimEnd().split('\n').filter(Boolean)) {
|
|
24
|
+
try {
|
|
25
|
+
const item = JSON.parse(line);
|
|
26
|
+
const ts = Date.parse(item.ts);
|
|
27
|
+
if (sinceTs && Number.isFinite(ts) && ts < sinceTs) continue;
|
|
28
|
+
const haystack = [
|
|
29
|
+
item.op,
|
|
30
|
+
item.action,
|
|
31
|
+
item.event,
|
|
32
|
+
item.status,
|
|
33
|
+
item.path,
|
|
34
|
+
item.cwd,
|
|
35
|
+
item.repoRoot,
|
|
36
|
+
item.code,
|
|
37
|
+
item.error,
|
|
38
|
+
item.requestSlotId,
|
|
39
|
+
item.previousRequestId,
|
|
40
|
+
].filter(Boolean).join(' ');
|
|
41
|
+
if (query && !haystack.includes(query)) continue;
|
|
42
|
+
records.push({ ...item, _time: Number.isFinite(ts) ? ts : 0 });
|
|
43
|
+
} catch {
|
|
44
|
+
// Ignore malformed lines.
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (records.length === 0) {
|
|
49
|
+
console.log(`No fs-io records matched "${query}" in the last ${sinceMinutes} minute(s).`);
|
|
50
|
+
process.exit(0);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
records.sort((a, b) => a._time - b._time);
|
|
54
|
+
|
|
55
|
+
function short(value) {
|
|
56
|
+
if (!value || typeof value !== 'string') return '';
|
|
57
|
+
const home = os.homedir();
|
|
58
|
+
const normalized = value.startsWith(home) ? `~${value.slice(home.length)}` : value;
|
|
59
|
+
return normalized.length > 120 ? `...${normalized.slice(-117)}` : normalized;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function important(item) {
|
|
63
|
+
const duration = typeof item.durationMs === 'number' ? item.durationMs : 0;
|
|
64
|
+
return (
|
|
65
|
+
item.event === 'slot-cancel-previous'
|
|
66
|
+
|| item.event === 'git-child-abort-kill'
|
|
67
|
+
|| item.event === 'git-child-timeout-kill'
|
|
68
|
+
|| item.event === 'git-child-byte-limit-kill'
|
|
69
|
+
|| item.status === 'error'
|
|
70
|
+
|| item.code
|
|
71
|
+
|| item.error
|
|
72
|
+
|| duration >= slowMs
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const byOp = new Map();
|
|
77
|
+
for (const item of records) {
|
|
78
|
+
if (!item.op || item.event) continue;
|
|
79
|
+
const stat = byOp.get(item.op) ?? { count: 0, errors: 0, slow: 0, maxMs: 0 };
|
|
80
|
+
stat.count += 1;
|
|
81
|
+
if (item.status === 'error' || item.code || item.error) stat.errors += 1;
|
|
82
|
+
if ((item.durationMs ?? 0) >= slowMs) stat.slow += 1;
|
|
83
|
+
stat.maxMs = Math.max(stat.maxMs, item.durationMs ?? 0);
|
|
84
|
+
byOp.set(item.op, stat);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log(`fs-io records: ${records.length}; since=${sinceMinutes}m; slow>=${slowMs}ms`);
|
|
88
|
+
if (byOp.size > 0) {
|
|
89
|
+
console.log('\nSummary by op:');
|
|
90
|
+
for (const [op, stat] of [...byOp.entries()].sort((a, b) => b[1].maxMs - a[1].maxMs)) {
|
|
91
|
+
console.log(` ${op.padEnd(14)} count=${String(stat.count).padStart(3)} slow=${String(stat.slow).padStart(3)} errors=${String(stat.errors).padStart(3)} max=${Math.round(stat.maxMs)}ms`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const notable = records.filter(important);
|
|
96
|
+
console.log(`\nNotable events: ${notable.length}`);
|
|
97
|
+
for (const item of notable.slice(-200)) {
|
|
98
|
+
const duration = item.durationMs !== undefined ? ` duration=${Math.round(item.durationMs)}ms` : '';
|
|
99
|
+
const count = item.count !== undefined ? ` count=${item.count}` : '';
|
|
100
|
+
const total = item.total !== undefined ? ` total=${item.total}` : '';
|
|
101
|
+
const slot = item.requestSlotId ? ` slot=${item.requestSlotId}` : '';
|
|
102
|
+
const previous = item.previousRequestId !== undefined ? ` previous=${item.previousRequestId}` : '';
|
|
103
|
+
const code = item.code ? ` code=${item.code}` : '';
|
|
104
|
+
const error = item.error ? ` error=${JSON.stringify(item.error)}` : '';
|
|
105
|
+
const target = item.path ? ` path=${short(item.path)}` : item.cwd ? ` cwd=${short(item.cwd)}` : '';
|
|
106
|
+
console.log(`${item.ts} ${String(item.op ?? '').padEnd(14)} ${String(item.event ?? item.status ?? '').padEnd(24)}${duration}${count}${total}${slot}${previous}${code}${error}${target}`);
|
|
107
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import copy
|
|
5
|
+
import json
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from fontTools.ttLib import TTFont
|
|
9
|
+
from fontTools.ttLib.tables._g_l_y_f import Glyph, GlyphComponent
|
|
10
|
+
|
|
11
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
12
|
+
PATCH_FILE = ROOT / 'tools/font/termdock-glyph-patches.json'
|
|
13
|
+
FONT_DIR = ROOT / 'public/fonts'
|
|
14
|
+
WEIGHTS = ['Regular', 'Bold', 'Italic', 'BoldItalic']
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def parse_cp(value: str) -> int:
|
|
18
|
+
return int(value.replace('U+', ''), 16)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def build_cmap(font: TTFont) -> dict[int, str]:
|
|
22
|
+
cmap: dict[int, str] = {}
|
|
23
|
+
for table in font['cmap'].tables:
|
|
24
|
+
cmap.update(table.cmap)
|
|
25
|
+
return cmap
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def add_post_name(post, glyph_name: str) -> None:
|
|
29
|
+
if post and hasattr(post, 'extraNames') and hasattr(post, 'mapping'):
|
|
30
|
+
post.extraNames.append(glyph_name)
|
|
31
|
+
post.mapping[glyph_name] = glyph_name
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def add_unicode_mapping(font: TTFont, codepoint: int, glyph_name: str) -> None:
|
|
35
|
+
for table in font['cmap'].tables:
|
|
36
|
+
if table.isUnicode():
|
|
37
|
+
table.cmap[codepoint] = glyph_name
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def make_component(glyph_name: str, x: int, y: int, scale: float) -> GlyphComponent:
|
|
41
|
+
component = GlyphComponent()
|
|
42
|
+
component.glyphName = glyph_name
|
|
43
|
+
component.x = x
|
|
44
|
+
component.y = y
|
|
45
|
+
component.transform = ((scale, 0), (0, scale))
|
|
46
|
+
component.flags = 4
|
|
47
|
+
return component
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def add_black_diamond_minus_white_x(font: TTFont, cmap: dict[int, str], glyph_order: list[str], post) -> int:
|
|
51
|
+
dst_cp = 0x2756
|
|
52
|
+
if dst_cp in cmap:
|
|
53
|
+
return 0
|
|
54
|
+
src_name = cmap.get(0x25C6)
|
|
55
|
+
if not src_name:
|
|
56
|
+
print('missing source U+25C6 for U+2756', file=sys.stderr)
|
|
57
|
+
return 0
|
|
58
|
+
dst_name = 'termdock_uni2756'
|
|
59
|
+
if dst_name in glyph_order:
|
|
60
|
+
return 0
|
|
61
|
+
|
|
62
|
+
glyph = Glyph()
|
|
63
|
+
glyph.numberOfContours = -1
|
|
64
|
+
# Four small black diamonds arranged around the center. The source diamond
|
|
65
|
+
# is 600 units wide; scale 0.34 keeps the composite visually distinct from
|
|
66
|
+
# U+25C6 while staying inside a single terminal cell.
|
|
67
|
+
scale = 0.34
|
|
68
|
+
glyph.components = [
|
|
69
|
+
make_component(src_name, 198, 436, scale),
|
|
70
|
+
make_component(src_name, 198, 100, scale),
|
|
71
|
+
make_component(src_name, 30, 268, scale),
|
|
72
|
+
make_component(src_name, 366, 268, scale),
|
|
73
|
+
]
|
|
74
|
+
glyph_order.append(dst_name)
|
|
75
|
+
font['glyf'].glyphs[dst_name] = glyph
|
|
76
|
+
font['hmtx'].metrics[dst_name] = copy.deepcopy(font['hmtx'].metrics[src_name])
|
|
77
|
+
add_post_name(post, dst_name)
|
|
78
|
+
add_unicode_mapping(font, dst_cp, dst_name)
|
|
79
|
+
cmap[dst_cp] = dst_name
|
|
80
|
+
return 1
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def patch_font(path: Path, aliases: dict[int, int]) -> int:
|
|
84
|
+
font = TTFont(path)
|
|
85
|
+
cmap = build_cmap(font)
|
|
86
|
+
glyph_order = font.getGlyphOrder()
|
|
87
|
+
glyf = font['glyf']
|
|
88
|
+
hmtx = font['hmtx']
|
|
89
|
+
post = font['post'] if 'post' in font else None
|
|
90
|
+
patched = add_black_diamond_minus_white_x(font, cmap, glyph_order, post)
|
|
91
|
+
|
|
92
|
+
for dst_cp, src_cp in aliases.items():
|
|
93
|
+
if dst_cp in cmap:
|
|
94
|
+
continue
|
|
95
|
+
src_name = cmap.get(src_cp)
|
|
96
|
+
if not src_name:
|
|
97
|
+
print(f'{path.name}: missing source U+{src_cp:04X}', file=sys.stderr)
|
|
98
|
+
continue
|
|
99
|
+
dst_name = f'termdock_uni{dst_cp:04X}'
|
|
100
|
+
if dst_name in glyph_order:
|
|
101
|
+
continue
|
|
102
|
+
|
|
103
|
+
glyph_order.append(dst_name)
|
|
104
|
+
glyf.glyphs[dst_name] = copy.deepcopy(glyf[src_name])
|
|
105
|
+
hmtx.metrics[dst_name] = copy.deepcopy(hmtx.metrics[src_name])
|
|
106
|
+
add_post_name(post, dst_name)
|
|
107
|
+
add_unicode_mapping(font, dst_cp, dst_name)
|
|
108
|
+
patched += 1
|
|
109
|
+
|
|
110
|
+
if patched:
|
|
111
|
+
font.setGlyphOrder(glyph_order)
|
|
112
|
+
font['maxp'].numGlyphs = len(glyph_order)
|
|
113
|
+
font.save(path)
|
|
114
|
+
return patched
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def main() -> int:
|
|
118
|
+
config = json.loads(PATCH_FILE.read_text())
|
|
119
|
+
aliases = {parse_cp(k): parse_cp(v) for k, v in config.get('aliases', {}).items()}
|
|
120
|
+
total = 0
|
|
121
|
+
for weight in WEIGHTS:
|
|
122
|
+
path = FONT_DIR / f'JetBrainsMonoNLNerdFontMono-{weight}.ttf'
|
|
123
|
+
if not path.exists():
|
|
124
|
+
print(f'missing font: {path}', file=sys.stderr)
|
|
125
|
+
return 1
|
|
126
|
+
count = patch_font(path, aliases)
|
|
127
|
+
total += count
|
|
128
|
+
print(f'{path.name}: patched {count} glyphs')
|
|
129
|
+
print(f'total patched: {total}')
|
|
130
|
+
return 0
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
if __name__ == '__main__':
|
|
134
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Termdock postinstall — 确保原生模块编译 + tmux 可用
|
|
5
|
+
*
|
|
6
|
+
* 执行时机:每次 `npm install -g termdock`(含首次安装和更新)
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { execSync } from 'child_process';
|
|
10
|
+
import { existsSync } from 'fs';
|
|
11
|
+
import { createRequire } from 'module';
|
|
12
|
+
|
|
13
|
+
const require_ = createRequire(import.meta.url);
|
|
14
|
+
|
|
15
|
+
function run(cmd, opts = {}) {
|
|
16
|
+
console.log(` $ ${cmd}`);
|
|
17
|
+
return execSync(cmd, { stdio: 'inherit', ...opts });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function runOk(cmd) {
|
|
21
|
+
try { run(cmd); return true; } catch { return false; }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function which(bin) {
|
|
25
|
+
try { execSync(`which ${bin}`, { stdio: 'pipe' }); return true; } catch { return false; }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// —— native modules ——
|
|
29
|
+
console.log('\n=== Rebuilding native modules ===');
|
|
30
|
+
const pkgRoot = new URL('..', import.meta.url).pathname;
|
|
31
|
+
|
|
32
|
+
for (const mod of ['node-pty', '@parcel/watcher']) {
|
|
33
|
+
try {
|
|
34
|
+
require_(`${mod}`);
|
|
35
|
+
console.log(` ${mod} already usable, skip rebuild`);
|
|
36
|
+
} catch {
|
|
37
|
+
console.log(` ${mod} needs rebuild...`);
|
|
38
|
+
const modDir = require_.resolve(`${mod}/package.json`, { paths: [pkgRoot] });
|
|
39
|
+
const modRoot = modDir.replace('/package.json', '');
|
|
40
|
+
// 删掉预编译二进制,强制从源码构建
|
|
41
|
+
runOk(`rm -rf ${modRoot}/prebuilds/*`);
|
|
42
|
+
run(`cd ${modRoot} && npx --yes node-gyp rebuild`, { timeout: 120_000 });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// —— tmux ——
|
|
47
|
+
console.log('\n=== Checking tmux ===');
|
|
48
|
+
if (!which('tmux')) {
|
|
49
|
+
console.log(' tmux not found, attempting auto-install...');
|
|
50
|
+
const platform = process.platform;
|
|
51
|
+
let installed = false;
|
|
52
|
+
|
|
53
|
+
if (platform === 'darwin') {
|
|
54
|
+
// macOS: try brew first, then fallback message
|
|
55
|
+
if (which('brew')) {
|
|
56
|
+
installed = runOk('brew install tmux');
|
|
57
|
+
} else {
|
|
58
|
+
console.log(' Homebrew not found. Install it: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"');
|
|
59
|
+
}
|
|
60
|
+
} else if (platform === 'linux') {
|
|
61
|
+
if (runOk('apt-get install -y tmux 2>/dev/null')) {
|
|
62
|
+
installed = true;
|
|
63
|
+
} else if (runOk('yum install -y tmux 2>/dev/null')) {
|
|
64
|
+
installed = true;
|
|
65
|
+
} else if (runOk('apk add tmux 2>/dev/null')) {
|
|
66
|
+
installed = true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (installed) {
|
|
71
|
+
console.log(' ✓ tmux installed successfully');
|
|
72
|
+
} else if (!which('tmux')) {
|
|
73
|
+
console.log(' ⚠ Could not auto-install tmux. Termdock works without it (shell mode will be default).');
|
|
74
|
+
console.log(' To use tmux features: install tmux then restart termdock.');
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
console.log(` ✓ tmux already available: ${execSync('tmux -V', { encoding: 'utf-8' }).trim()}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log('\n✓ Termdock postinstall complete\n');
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{U as a,C as n}from"./mermaid.core-DAp1jSn7.js";const t=(r,o)=>a.lang.round(n.parse(r)[o]);export{t as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,a as s,c as t,C as e}from"./chunk-V7JOEXUC-BTlki_tC.js";import{b as i}from"./mermaid.core-DAp1jSn7.js";import"./chunk-5VM5RSS4-Ca--vT5Q.js";import"./chunk-XXDRQBXY-zy3DIq5F.js";import"./chunk-VR4S4FIN-BXnHZWrK.js";import"./chunk-32BRIVSS-BPMnoBke.js";import"./purify.es-CC4Brkr_.js";import"./index-Bi0L0Km4.js";import"./react-XDCjal2T.js";import"./dnd-BCFAPC0L.js";import"./terminal-C7X98Amf.js";var g={parser:t,get db(){return new e},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{g as diagram};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,a as s,c as t,C as e}from"./chunk-V7JOEXUC-BTlki_tC.js";import{b as i}from"./mermaid.core-DAp1jSn7.js";import"./chunk-5VM5RSS4-Ca--vT5Q.js";import"./chunk-XXDRQBXY-zy3DIq5F.js";import"./chunk-VR4S4FIN-BXnHZWrK.js";import"./chunk-32BRIVSS-BPMnoBke.js";import"./purify.es-CC4Brkr_.js";import"./index-Bi0L0Km4.js";import"./react-XDCjal2T.js";import"./dnd-BCFAPC0L.js";import"./terminal-C7X98Amf.js";var g={parser:t,get db(){return new e},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{g as diagram};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{b as r,a as e,s as a,S as i}from"./chunk-EX3LRPZG-Bc42nIJ5.js";import{b as s}from"./mermaid.core-DAp1jSn7.js";import"./chunk-XXDRQBXY-zy3DIq5F.js";import"./chunk-VR4S4FIN-BXnHZWrK.js";import"./chunk-32BRIVSS-BPMnoBke.js";import"./purify.es-CC4Brkr_.js";import"./index-Bi0L0Km4.js";import"./react-XDCjal2T.js";import"./dnd-BCFAPC0L.js";import"./terminal-C7X98Amf.js";var g={parser:a,get db(){return new i(2)},renderer:e,styles:r,init:s(t=>{t.state||(t.state={}),t.state.arrowMarkerAbsolute=t.arrowMarkerAbsolute},"init")};export{g as diagram};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import{c as r,s as e}from"./flowDiagram-23GEKE2U-bDu_tMe8.js";import{b as o}from"./mermaid.core-DAp1jSn7.js";import"./chunk-5VM5RSS4-Ca--vT5Q.js";import"./chunk-XXDRQBXY-zy3DIq5F.js";import"./chunk-VR4S4FIN-BXnHZWrK.js";import"./chunk-32BRIVSS-BPMnoBke.js";import"./purify.es-CC4Brkr_.js";import"./channel-OEjXE69P.js";import"./index-Bi0L0Km4.js";import"./react-XDCjal2T.js";import"./dnd-BCFAPC0L.js";import"./terminal-C7X98Amf.js";var a=o(t=>`${e(t)}
|
|
2
|
-
.swimlane.cluster rect {
|
|
3
|
-
stroke: ${t.clusterBorder} !important;
|
|
4
|
-
}
|
|
5
|
-
[data-look="neo"].cluster rect {
|
|
6
|
-
filter: none;
|
|
7
|
-
}
|
|
8
|
-
`,"getStyles"),m=a,v=r({defaultLayout:"swimlane",styles:m});export{v as diagram};
|