dsh-m 0.2.8 → 0.2.10
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/docs/DESIGN.md +19 -5
- package/lib/cli.js +5 -4
- package/lib/client.js +319 -239
- package/lib/core/dsh-cli.js +245 -52
- package/lib/core/host-api.js +38 -6
- package/lib/core/installed.js +89 -38
- package/lib/core/market.js +52 -301
- package/lib/core/npm-integrity.js +139 -13
- package/lib/core/profile-transaction.js +825 -0
- package/lib/host.js +1 -2
- package/lib/tools.js +15 -24
- package/package.json +2 -1
- package/registry.json +33 -0
package/lib/client.js
CHANGED
|
@@ -112,6 +112,299 @@ var init_market_state = __esm({
|
|
|
112
112
|
}
|
|
113
113
|
});
|
|
114
114
|
|
|
115
|
+
// src/client/markdown.js
|
|
116
|
+
var markdown_exports = {};
|
|
117
|
+
__export(markdown_exports, {
|
|
118
|
+
createMarkdown: () => createMarkdown,
|
|
119
|
+
safeUrl: () => safeUrl
|
|
120
|
+
});
|
|
121
|
+
function safeUrl(u) {
|
|
122
|
+
const t = String(u || "").trim();
|
|
123
|
+
if (/^(https?:\/\/|mailto:)/i.test(t)) return t;
|
|
124
|
+
if (/^[/#]/.test(t)) return t;
|
|
125
|
+
return "#";
|
|
126
|
+
}
|
|
127
|
+
function createMarkdown(h2) {
|
|
128
|
+
function ExtLink2({ href, className, children }) {
|
|
129
|
+
return h2(
|
|
130
|
+
"a",
|
|
131
|
+
{
|
|
132
|
+
className: className || "dshm-md-a",
|
|
133
|
+
href: safeUrl(href),
|
|
134
|
+
target: "_blank",
|
|
135
|
+
rel: "noopener noreferrer",
|
|
136
|
+
onClick: (e) => e.stopPropagation()
|
|
137
|
+
},
|
|
138
|
+
children
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
function MdImg2({ src, alt }) {
|
|
142
|
+
return h2("img", {
|
|
143
|
+
className: "dshm-md-img",
|
|
144
|
+
src: safeUrl(src),
|
|
145
|
+
alt: alt || "",
|
|
146
|
+
referrerPolicy: "no-referrer",
|
|
147
|
+
onError: (e) => {
|
|
148
|
+
e.currentTarget.style.display = "none";
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function mdInline(text, kb) {
|
|
153
|
+
const re = /(\[!\[[^\]]*\]\([^)]*\)\]\([^)]*\))|(!\[[^\]]*\]\([^)]*\))|(\[[^\]]*\]\([^)]*\))|(`[^`]+`)|(\*\*[^*]+\*\*)|(~~[^~]+~~)|(\*[^*\s][^*]*\*)|(<https?:\/\/[^>\s]+>)|(https?:\/\/[^\s<>()\[\]{}"'「」【】]+[^\s<>()\[\]{}"'「」【】.,;:!?…,。;:!?)】」"')])/g;
|
|
154
|
+
const src = String(text);
|
|
155
|
+
const nodes = [];
|
|
156
|
+
let last = 0;
|
|
157
|
+
let m;
|
|
158
|
+
let i = 0;
|
|
159
|
+
while (m = re.exec(src)) {
|
|
160
|
+
if (m.index > last) nodes.push(src.slice(last, m.index));
|
|
161
|
+
const tok = m[0];
|
|
162
|
+
const k = `${kb}-${i++}`;
|
|
163
|
+
if (tok.startsWith("[![")) {
|
|
164
|
+
const im = /^!\[([^\]]*)\]\(([^)]*)\)/.exec(tok.slice(1));
|
|
165
|
+
const lm = /\]\(([^)]*)\)\s*$/.exec(tok);
|
|
166
|
+
const img = h2(MdImg2, { src: im && im[2], alt: im && im[1] });
|
|
167
|
+
const href = lm && lm[1];
|
|
168
|
+
nodes.push(href && safeUrl(href) !== "#" ? h2(ExtLink2, { key: k, href }, img) : h2("span", { key: k }, img));
|
|
169
|
+
} else if (tok.startsWith("![") || tok.startsWith("<![")) {
|
|
170
|
+
const im = /^!\[([^\]]*)\]\(([^)]*)\)$/.exec(tok);
|
|
171
|
+
nodes.push(h2(MdImg2, { key: k, src: im && im[2], alt: im && im[1] }));
|
|
172
|
+
} else if (tok.startsWith("[")) {
|
|
173
|
+
const lm = /^\[([^\]]*)\]\(([^)]*)\)$/.exec(tok);
|
|
174
|
+
nodes.push(h2(ExtLink2, { key: k, href: lm && lm[2] }, mdInline(lm ? lm[1] : tok, k)));
|
|
175
|
+
} else if (tok.startsWith("`")) {
|
|
176
|
+
nodes.push(h2("code", { key: k }, tok.slice(1, -1)));
|
|
177
|
+
} else if (tok.startsWith("**")) {
|
|
178
|
+
nodes.push(h2("strong", { key: k }, mdInline(tok.slice(2, -2), k)));
|
|
179
|
+
} else if (tok.startsWith("~~")) {
|
|
180
|
+
nodes.push(h2("del", { key: k }, mdInline(tok.slice(2, -2), k)));
|
|
181
|
+
} else if (tok.startsWith("*")) {
|
|
182
|
+
nodes.push(h2("em", { key: k }, mdInline(tok.slice(1, -1), k)));
|
|
183
|
+
} else if (tok.startsWith("<")) {
|
|
184
|
+
const u = tok.slice(1, -1);
|
|
185
|
+
nodes.push(h2(ExtLink2, { key: k, href: u }, u));
|
|
186
|
+
} else {
|
|
187
|
+
nodes.push(h2(ExtLink2, { key: k, href: tok }, tok.length > 72 ? `${tok.slice(0, 69)}\u2026` : tok));
|
|
188
|
+
}
|
|
189
|
+
last = m.index + tok.length;
|
|
190
|
+
}
|
|
191
|
+
if (last < src.length) nodes.push(src.slice(last));
|
|
192
|
+
return nodes;
|
|
193
|
+
}
|
|
194
|
+
function mdBlocks(lines, kb) {
|
|
195
|
+
const out = [];
|
|
196
|
+
let i = 0;
|
|
197
|
+
let n = 0;
|
|
198
|
+
const isFence = (s) => /^\s*```/.test(s);
|
|
199
|
+
const isHeading = (s) => /^#{1,6}\s+/.test(s);
|
|
200
|
+
const isHr = (s) => /^\s*(-{3,}|\*{3,}|_{3,})\s*$/.test(s);
|
|
201
|
+
const isQuote = (s) => /^\s*>/.test(s);
|
|
202
|
+
const isUl = (s) => /^\s*[-*+]\s+/.test(s);
|
|
203
|
+
const isOl = (s) => /^\s*\d+[.)]\s+/.test(s);
|
|
204
|
+
const isTableRow = (s) => s.includes("|") && /^\s*\|/.test(s);
|
|
205
|
+
while (i < lines.length) {
|
|
206
|
+
const line = lines[i];
|
|
207
|
+
if (!line.trim()) {
|
|
208
|
+
i++;
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
const k = `${kb}-b${n++}`;
|
|
212
|
+
if (isFence(line)) {
|
|
213
|
+
const buf2 = [];
|
|
214
|
+
i++;
|
|
215
|
+
while (i < lines.length && !/^\s*```\s*$/.test(lines[i])) buf2.push(lines[i++]);
|
|
216
|
+
i++;
|
|
217
|
+
out.push(h2("pre", { key: k }, h2("code", null, buf2.join("\n"))));
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
if (isHeading(line)) {
|
|
221
|
+
const hm = /^(#{1,6})\s+(.*)$/.exec(line);
|
|
222
|
+
out.push(h2(`h${hm[1].length}`, { key: k }, mdInline(hm[2], k)));
|
|
223
|
+
i++;
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (isHr(line)) {
|
|
227
|
+
out.push(h2("hr", { key: k }));
|
|
228
|
+
i++;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if (isQuote(line)) {
|
|
232
|
+
const buf2 = [];
|
|
233
|
+
while (i < lines.length && isQuote(lines[i])) buf2.push(lines[i++].replace(/^\s*>\s?/, ""));
|
|
234
|
+
out.push(h2("blockquote", { key: k }, mdBlocks(buf2, k)));
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (isUl(line) || isOl(line)) {
|
|
238
|
+
const ordered = isOl(line);
|
|
239
|
+
const re = ordered ? /^\s*\d+[.)]\s+(.*)$/ : /^\s*[-*+]\s+(.*)$/;
|
|
240
|
+
const items = [];
|
|
241
|
+
while (i < lines.length && (ordered ? isOl(lines[i]) : isUl(lines[i]))) {
|
|
242
|
+
items.push(h2("li", { key: `li${items.length}` }, mdInline(re.exec(lines[i])[1], `${k}-${items.length}`)));
|
|
243
|
+
i++;
|
|
244
|
+
}
|
|
245
|
+
out.push(h2(ordered ? "ol" : "ul", { key: k }, items));
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (isTableRow(line) && i + 1 < lines.length && lines[i + 1].includes("-") && /^\s*\|?[\s:|-]+\|?\s*$/.test(lines[i + 1])) {
|
|
249
|
+
const cells = (s) => s.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map((c) => c.trim());
|
|
250
|
+
const head = cells(lines[i]);
|
|
251
|
+
i += 2;
|
|
252
|
+
const rows = [];
|
|
253
|
+
while (i < lines.length && isTableRow(lines[i])) {
|
|
254
|
+
rows.push(cells(lines[i]));
|
|
255
|
+
i++;
|
|
256
|
+
}
|
|
257
|
+
out.push(
|
|
258
|
+
h2(
|
|
259
|
+
"table",
|
|
260
|
+
{ key: k },
|
|
261
|
+
h2("thead", null, h2("tr", null, head.map((c, x) => h2("th", { key: x }, mdInline(c, `${k}h${x}`))))),
|
|
262
|
+
h2("tbody", null, rows.map((r, y) => h2("tr", { key: y }, r.map((c, x) => h2("td", { key: x }, mdInline(c, `${k}${y}x${x}`))))))
|
|
263
|
+
)
|
|
264
|
+
);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
const buf = [line];
|
|
268
|
+
i++;
|
|
269
|
+
while (i < lines.length && lines[i].trim() && !isFence(lines[i]) && !isHeading(lines[i]) && !isHr(lines[i]) && !isQuote(lines[i]) && !isUl(lines[i]) && !isOl(lines[i])) {
|
|
270
|
+
buf.push(lines[i]);
|
|
271
|
+
i++;
|
|
272
|
+
}
|
|
273
|
+
out.push(h2("p", { key: k }, mdInline(buf.join(" "), k)));
|
|
274
|
+
}
|
|
275
|
+
return out;
|
|
276
|
+
}
|
|
277
|
+
function renderMarkdown2(src) {
|
|
278
|
+
return mdBlocks(String(src || "").replace(/\r\n?/g, "\n").split("\n"), "md");
|
|
279
|
+
}
|
|
280
|
+
return { ExtLink: ExtLink2, MdImg: MdImg2, renderMarkdown: renderMarkdown2 };
|
|
281
|
+
}
|
|
282
|
+
var init_markdown = __esm({
|
|
283
|
+
"src/client/markdown.js"() {
|
|
284
|
+
"use strict";
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// src/client/installed-view.js
|
|
289
|
+
var installed_view_exports = {};
|
|
290
|
+
__export(installed_view_exports, {
|
|
291
|
+
installedViewModel: () => installedViewModel,
|
|
292
|
+
registrySourceKey: () => registrySourceKey
|
|
293
|
+
});
|
|
294
|
+
function uninstallGuardKeys(it) {
|
|
295
|
+
if (it.source === "link") {
|
|
296
|
+
return { confirmKey: "confirm.unlink", warnKey: "warn.unlink", warnParams: { path: it.path } };
|
|
297
|
+
}
|
|
298
|
+
if (it.source === "file") {
|
|
299
|
+
return { confirmKey: "confirm.core", warnKey: "warn.core", warnParams: {} };
|
|
300
|
+
}
|
|
301
|
+
return { confirmKey: "confirm.uninstall", warnKey: null, warnParams: {} };
|
|
302
|
+
}
|
|
303
|
+
function installedViewModel(it) {
|
|
304
|
+
return {
|
|
305
|
+
githubRepo: it.registryGithub || it.githubRepo || (it.spec.startsWith("github:") ? it.spec.slice(7).split("#")[0] : null),
|
|
306
|
+
sourceLabelKey: { npm: "src.npm", github: "src.github", link: "src.link", file: "src.file", unknown: "src.unknown" }[it.source] || null,
|
|
307
|
+
guard: uninstallGuardKeys(it),
|
|
308
|
+
latestLabel: it.latestTag || (it.latestVersion ? `v${it.latestVersion}` : ""),
|
|
309
|
+
latestLabelDetail: it.latestTag || (it.latestVersion ? `v${it.latestVersion}` : "\u2014")
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function registrySourceKey(data) {
|
|
313
|
+
if (!data) return null;
|
|
314
|
+
const map = {
|
|
315
|
+
"default-raw": "src.default.raw",
|
|
316
|
+
"default-jsdelivr": "src.default.jsdelivr",
|
|
317
|
+
"default-cache": "src.default.cache",
|
|
318
|
+
bundled: "src.bundled",
|
|
319
|
+
"custom-url": "src.custom.url",
|
|
320
|
+
"custom-file": "src.custom.file",
|
|
321
|
+
"custom-cache": "src.custom.cache",
|
|
322
|
+
"custom-unavailable": "src.custom.unavailable",
|
|
323
|
+
// 旧字段兼容
|
|
324
|
+
override: "src.override",
|
|
325
|
+
jsdelivr: "src.jsdelivr",
|
|
326
|
+
raw: "src.raw",
|
|
327
|
+
cache: "src.cache"
|
|
328
|
+
};
|
|
329
|
+
return map[data.source] || data.source;
|
|
330
|
+
}
|
|
331
|
+
var init_installed_view = __esm({
|
|
332
|
+
"src/client/installed-view.js"() {
|
|
333
|
+
"use strict";
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
// src/client/tool-view.js
|
|
338
|
+
var tool_view_exports = {};
|
|
339
|
+
__export(tool_view_exports, {
|
|
340
|
+
parseToolArgs: () => parseToolArgs,
|
|
341
|
+
pickPayload: () => pickPayload
|
|
342
|
+
});
|
|
343
|
+
function pickPayload(props) {
|
|
344
|
+
const found = [];
|
|
345
|
+
const visit = (node, depth) => {
|
|
346
|
+
if (!node || depth > 6) return;
|
|
347
|
+
if (typeof node === "string") {
|
|
348
|
+
const t = node.trim();
|
|
349
|
+
if ((t.startsWith("{") || t.startsWith("[")) && t.length > 8) {
|
|
350
|
+
try {
|
|
351
|
+
visit(JSON.parse(t), depth + 1);
|
|
352
|
+
} catch {
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
if (typeof node !== "object") return;
|
|
358
|
+
if (Array.isArray(node)) {
|
|
359
|
+
for (const x of node) visit(x, depth + 1);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
if (Array.isArray(node.items)) found.push(node);
|
|
363
|
+
for (const key of ["block", "meta", "result", "resultView", "view", "data", "value", "payload", "content", "message"]) {
|
|
364
|
+
if (node[key] != null) visit(node[key], depth + 1);
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
visit(props, 0);
|
|
368
|
+
return found.find((x) => x && Array.isArray(x.items)) || null;
|
|
369
|
+
}
|
|
370
|
+
function parseToolArgs(props) {
|
|
371
|
+
const block = props?.block;
|
|
372
|
+
const raw = (block && "kind" in block ? block.call?.argsRaw : block?.argsRaw) || "";
|
|
373
|
+
if (!raw || typeof raw !== "string") return {};
|
|
374
|
+
try {
|
|
375
|
+
return JSON.parse(raw);
|
|
376
|
+
} catch {
|
|
377
|
+
return {};
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
var init_tool_view = __esm({
|
|
381
|
+
"src/client/tool-view.js"() {
|
|
382
|
+
"use strict";
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
// src/client/restart-wait.js
|
|
387
|
+
var restart_wait_exports = {};
|
|
388
|
+
__export(restart_wait_exports, {
|
|
389
|
+
RESTART_DEADLINE_MS: () => RESTART_DEADLINE_MS,
|
|
390
|
+
RESTART_POLL_MS: () => RESTART_POLL_MS,
|
|
391
|
+
nextRestartWait: () => nextRestartWait
|
|
392
|
+
});
|
|
393
|
+
function nextRestartWait({ phase, now = 0, deadlineAt = Infinity, bootChanged = false }) {
|
|
394
|
+
if (phase === "before-ping") {
|
|
395
|
+
return now > deadlineAt ? "timeout" : "continue";
|
|
396
|
+
}
|
|
397
|
+
return bootChanged ? "done" : "continue";
|
|
398
|
+
}
|
|
399
|
+
var RESTART_POLL_MS, RESTART_DEADLINE_MS;
|
|
400
|
+
var init_restart_wait = __esm({
|
|
401
|
+
"src/client/restart-wait.js"() {
|
|
402
|
+
"use strict";
|
|
403
|
+
RESTART_POLL_MS = 2e3;
|
|
404
|
+
RESTART_DEADLINE_MS = 9e4;
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
|
|
115
408
|
// src/client/main.jsx
|
|
116
409
|
var React = require("react");
|
|
117
410
|
var rd = require("react-dom");
|
|
@@ -120,6 +413,11 @@ var { useState, useEffect, useCallback, useMemo, useRef } = React;
|
|
|
120
413
|
var PLUGIN_ID = "dsh-m";
|
|
121
414
|
var API = "/dshm";
|
|
122
415
|
var { MARKET_PAGE_SIZE: MARKET_PAGE_SIZE2, normalizeMarketQuery: normalizeMarketQuery2, resetPageOnFilterChange: resetPageOnFilterChange2, normalizeMarketResponse: normalizeMarketResponse2, registryNotice: registryNotice2 } = (init_market_state(), __toCommonJS(market_state_exports));
|
|
416
|
+
var { createMarkdown: createMarkdown2 } = (init_markdown(), __toCommonJS(markdown_exports));
|
|
417
|
+
var { ExtLink, MdImg, renderMarkdown } = createMarkdown2(h);
|
|
418
|
+
var { installedViewModel: installedViewModel2, registrySourceKey: registrySourceKey2 } = (init_installed_view(), __toCommonJS(installed_view_exports));
|
|
419
|
+
var { pickPayload: pickPayload2, parseToolArgs: parseToolArgs2 } = (init_tool_view(), __toCommonJS(tool_view_exports));
|
|
420
|
+
var { RESTART_POLL_MS: RESTART_POLL_MS2, RESTART_DEADLINE_MS: RESTART_DEADLINE_MS2, nextRestartWait: nextRestartWait2 } = (init_restart_wait(), __toCommonJS(restart_wait_exports));
|
|
123
421
|
var ZH = {
|
|
124
422
|
"market.title": "\u63D2\u4EF6\u5E02\u573A",
|
|
125
423
|
"tab.market": "\u5E02\u573A",
|
|
@@ -664,164 +962,6 @@ function Icon({ entry }) {
|
|
|
664
962
|
function Spin() {
|
|
665
963
|
return h("span", { className: "dshm-spin" });
|
|
666
964
|
}
|
|
667
|
-
function safeUrl(u) {
|
|
668
|
-
const t = String(u || "").trim();
|
|
669
|
-
if (/^(https?:\/\/|mailto:)/i.test(t)) return t;
|
|
670
|
-
if (/^[/#]/.test(t)) return t;
|
|
671
|
-
return "#";
|
|
672
|
-
}
|
|
673
|
-
function ExtLink({ href, className, children }) {
|
|
674
|
-
return h(
|
|
675
|
-
"a",
|
|
676
|
-
{
|
|
677
|
-
className: className || "dshm-md-a",
|
|
678
|
-
href: safeUrl(href),
|
|
679
|
-
target: "_blank",
|
|
680
|
-
rel: "noopener noreferrer",
|
|
681
|
-
onClick: (e) => e.stopPropagation()
|
|
682
|
-
},
|
|
683
|
-
children
|
|
684
|
-
);
|
|
685
|
-
}
|
|
686
|
-
function MdImg({ src, alt }) {
|
|
687
|
-
return h("img", {
|
|
688
|
-
className: "dshm-md-img",
|
|
689
|
-
src: safeUrl(src),
|
|
690
|
-
alt: alt || "",
|
|
691
|
-
referrerPolicy: "no-referrer",
|
|
692
|
-
onError: (e) => {
|
|
693
|
-
e.currentTarget.style.display = "none";
|
|
694
|
-
}
|
|
695
|
-
});
|
|
696
|
-
}
|
|
697
|
-
function mdInline(text, kb) {
|
|
698
|
-
const re = /(\[!\[[^\]]*\]\([^)]*\)\]\([^)]*\))|(!\[[^\]]*\]\([^)]*\))|(\[[^\]]*\]\([^)]*\))|(`[^`]+`)|(\*\*[^*]+\*\*)|(~~[^~]+~~)|(\*[^*\s][^*]*\*)|(<https?:\/\/[^>\s]+>)|(https?:\/\/[^\s<>()\[\]{}"'「」【】]+[^\s<>()\[\]{}"'「」【】.,;:!?…,。;:!?)】」"')])/g;
|
|
699
|
-
const src = String(text);
|
|
700
|
-
const nodes = [];
|
|
701
|
-
let last = 0;
|
|
702
|
-
let m;
|
|
703
|
-
let i = 0;
|
|
704
|
-
while (m = re.exec(src)) {
|
|
705
|
-
if (m.index > last) nodes.push(src.slice(last, m.index));
|
|
706
|
-
const tok = m[0];
|
|
707
|
-
const k = `${kb}-${i++}`;
|
|
708
|
-
if (tok.startsWith("[![")) {
|
|
709
|
-
const im = /^!\[([^\]]*)\]\(([^)]*)\)/.exec(tok.slice(1));
|
|
710
|
-
const lm = /\]\(([^)]*)\)\s*$/.exec(tok);
|
|
711
|
-
const img = h(MdImg, { src: im && im[2], alt: im && im[1] });
|
|
712
|
-
const href = lm && lm[1];
|
|
713
|
-
nodes.push(href && safeUrl(href) !== "#" ? h(ExtLink, { key: k, href }, img) : h("span", { key: k }, img));
|
|
714
|
-
} else if (tok.startsWith("![") || tok.startsWith("<![")) {
|
|
715
|
-
const im = /^!\[([^\]]*)\]\(([^)]*)\)$/.exec(tok);
|
|
716
|
-
nodes.push(h(MdImg, { key: k, src: im && im[2], alt: im && im[1] }));
|
|
717
|
-
} else if (tok.startsWith("[")) {
|
|
718
|
-
const lm = /^\[([^\]]*)\]\(([^)]*)\)$/.exec(tok);
|
|
719
|
-
nodes.push(h(ExtLink, { key: k, href: lm && lm[2] }, mdInline(lm ? lm[1] : tok, k)));
|
|
720
|
-
} else if (tok.startsWith("`")) {
|
|
721
|
-
nodes.push(h("code", { key: k }, tok.slice(1, -1)));
|
|
722
|
-
} else if (tok.startsWith("**")) {
|
|
723
|
-
nodes.push(h("strong", { key: k }, mdInline(tok.slice(2, -2), k)));
|
|
724
|
-
} else if (tok.startsWith("~~")) {
|
|
725
|
-
nodes.push(h("del", { key: k }, mdInline(tok.slice(2, -2), k)));
|
|
726
|
-
} else if (tok.startsWith("*")) {
|
|
727
|
-
nodes.push(h("em", { key: k }, mdInline(tok.slice(1, -1), k)));
|
|
728
|
-
} else if (tok.startsWith("<")) {
|
|
729
|
-
const u = tok.slice(1, -1);
|
|
730
|
-
nodes.push(h(ExtLink, { key: k, href: u }, u));
|
|
731
|
-
} else {
|
|
732
|
-
nodes.push(h(ExtLink, { key: k, href: tok }, tok.length > 72 ? `${tok.slice(0, 69)}\u2026` : tok));
|
|
733
|
-
}
|
|
734
|
-
last = m.index + tok.length;
|
|
735
|
-
}
|
|
736
|
-
if (last < src.length) nodes.push(src.slice(last));
|
|
737
|
-
return nodes;
|
|
738
|
-
}
|
|
739
|
-
function mdBlocks(lines, kb) {
|
|
740
|
-
const out = [];
|
|
741
|
-
let i = 0;
|
|
742
|
-
let n = 0;
|
|
743
|
-
const isFence = (s) => /^\s*```/.test(s);
|
|
744
|
-
const isHeading = (s) => /^#{1,6}\s+/.test(s);
|
|
745
|
-
const isHr = (s) => /^\s*(-{3,}|\*{3,}|_{3,})\s*$/.test(s);
|
|
746
|
-
const isQuote = (s) => /^\s*>/.test(s);
|
|
747
|
-
const isUl = (s) => /^\s*[-*+]\s+/.test(s);
|
|
748
|
-
const isOl = (s) => /^\s*\d+[.)]\s+/.test(s);
|
|
749
|
-
const isTableRow = (s) => s.includes("|") && /^\s*\|/.test(s);
|
|
750
|
-
while (i < lines.length) {
|
|
751
|
-
const line = lines[i];
|
|
752
|
-
if (!line.trim()) {
|
|
753
|
-
i++;
|
|
754
|
-
continue;
|
|
755
|
-
}
|
|
756
|
-
const k = `${kb}-b${n++}`;
|
|
757
|
-
if (isFence(line)) {
|
|
758
|
-
const buf2 = [];
|
|
759
|
-
i++;
|
|
760
|
-
while (i < lines.length && !/^\s*```\s*$/.test(lines[i])) buf2.push(lines[i++]);
|
|
761
|
-
i++;
|
|
762
|
-
out.push(h("pre", { key: k }, h("code", null, buf2.join("\n"))));
|
|
763
|
-
continue;
|
|
764
|
-
}
|
|
765
|
-
if (isHeading(line)) {
|
|
766
|
-
const hm = /^(#{1,6})\s+(.*)$/.exec(line);
|
|
767
|
-
out.push(h(`h${hm[1].length}`, { key: k }, mdInline(hm[2], k)));
|
|
768
|
-
i++;
|
|
769
|
-
continue;
|
|
770
|
-
}
|
|
771
|
-
if (isHr(line)) {
|
|
772
|
-
out.push(h("hr", { key: k }));
|
|
773
|
-
i++;
|
|
774
|
-
continue;
|
|
775
|
-
}
|
|
776
|
-
if (isQuote(line)) {
|
|
777
|
-
const buf2 = [];
|
|
778
|
-
while (i < lines.length && isQuote(lines[i])) buf2.push(lines[i++].replace(/^\s*>\s?/, ""));
|
|
779
|
-
out.push(h("blockquote", { key: k }, mdBlocks(buf2, k)));
|
|
780
|
-
continue;
|
|
781
|
-
}
|
|
782
|
-
if (isUl(line) || isOl(line)) {
|
|
783
|
-
const ordered = isOl(line);
|
|
784
|
-
const re = ordered ? /^\s*\d+[.)]\s+(.*)$/ : /^\s*[-*+]\s+(.*)$/;
|
|
785
|
-
const items = [];
|
|
786
|
-
while (i < lines.length && (ordered ? isOl(lines[i]) : isUl(lines[i]))) {
|
|
787
|
-
items.push(h("li", { key: `li${items.length}` }, mdInline(re.exec(lines[i])[1], `${k}-${items.length}`)));
|
|
788
|
-
i++;
|
|
789
|
-
}
|
|
790
|
-
out.push(h(ordered ? "ol" : "ul", { key: k }, items));
|
|
791
|
-
continue;
|
|
792
|
-
}
|
|
793
|
-
if (isTableRow(line) && i + 1 < lines.length && lines[i + 1].includes("-") && /^\s*\|?[\s:|-]+\|?\s*$/.test(lines[i + 1])) {
|
|
794
|
-
const cells = (s) => s.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map((c) => c.trim());
|
|
795
|
-
const head = cells(lines[i]);
|
|
796
|
-
i += 2;
|
|
797
|
-
const rows = [];
|
|
798
|
-
while (i < lines.length && isTableRow(lines[i])) {
|
|
799
|
-
rows.push(cells(lines[i]));
|
|
800
|
-
i++;
|
|
801
|
-
}
|
|
802
|
-
out.push(
|
|
803
|
-
h(
|
|
804
|
-
"table",
|
|
805
|
-
{ key: k },
|
|
806
|
-
h("thead", null, h("tr", null, head.map((c, x) => h("th", { key: x }, mdInline(c, `${k}h${x}`))))),
|
|
807
|
-
h("tbody", null, rows.map((r, y) => h("tr", { key: y }, r.map((c, x) => h("td", { key: x }, mdInline(c, `${k}${y}x${x}`))))))
|
|
808
|
-
)
|
|
809
|
-
);
|
|
810
|
-
continue;
|
|
811
|
-
}
|
|
812
|
-
const buf = [line];
|
|
813
|
-
i++;
|
|
814
|
-
while (i < lines.length && lines[i].trim() && !isFence(lines[i]) && !isHeading(lines[i]) && !isHr(lines[i]) && !isQuote(lines[i]) && !isUl(lines[i]) && !isOl(lines[i])) {
|
|
815
|
-
buf.push(lines[i]);
|
|
816
|
-
i++;
|
|
817
|
-
}
|
|
818
|
-
out.push(h("p", { key: k }, mdInline(buf.join(" "), k)));
|
|
819
|
-
}
|
|
820
|
-
return out;
|
|
821
|
-
}
|
|
822
|
-
function renderMarkdown(src) {
|
|
823
|
-
return mdBlocks(String(src || "").replace(/\r\n?/g, "\n").split("\n"), "md");
|
|
824
|
-
}
|
|
825
965
|
function officialLinks({ npm, github, homepage }) {
|
|
826
966
|
const links = [];
|
|
827
967
|
if (github) links.push(["GitHub", `https://github.com/${github}`]);
|
|
@@ -874,15 +1014,19 @@ function RestartBanner({ note, onDone }) {
|
|
|
874
1014
|
const ping0 = await api("ping");
|
|
875
1015
|
await api("restart");
|
|
876
1016
|
setPhase("waiting");
|
|
877
|
-
const
|
|
1017
|
+
const deadlineAt = Date.now() + RESTART_DEADLINE_MS2;
|
|
878
1018
|
for (; ; ) {
|
|
879
|
-
await new Promise((r) => setTimeout(r,
|
|
880
|
-
if (Date.now()
|
|
1019
|
+
await new Promise((r) => setTimeout(r, RESTART_POLL_MS2));
|
|
1020
|
+
if (nextRestartWait2({ phase: "before-ping", now: Date.now(), deadlineAt }) === "timeout") {
|
|
1021
|
+
throw new Error(lookup("restart.timeout"));
|
|
1022
|
+
}
|
|
1023
|
+
let bootChanged = false;
|
|
881
1024
|
try {
|
|
882
1025
|
const ping = await api("ping");
|
|
883
|
-
|
|
1026
|
+
bootChanged = ping.boot !== ping0.boot;
|
|
884
1027
|
} catch {
|
|
885
1028
|
}
|
|
1029
|
+
if (nextRestartWait2({ phase: "after-ping", bootChanged }) === "done") break;
|
|
886
1030
|
}
|
|
887
1031
|
setPhase("idle");
|
|
888
1032
|
onDone(true);
|
|
@@ -1091,18 +1235,6 @@ function ReadmeBlock({ pkg }) {
|
|
|
1091
1235
|
state.truncated ? h("div", { className: "dshm-md-note" }, lookup("readme.truncated")) : null
|
|
1092
1236
|
);
|
|
1093
1237
|
}
|
|
1094
|
-
function uninstallGuard(it) {
|
|
1095
|
-
if (it.source === "link") {
|
|
1096
|
-
return {
|
|
1097
|
-
confirm: lookup("confirm.unlink"),
|
|
1098
|
-
warn: lookup("warn.unlink", { path: it.path })
|
|
1099
|
-
};
|
|
1100
|
-
}
|
|
1101
|
-
if (it.source === "file") {
|
|
1102
|
-
return { confirm: lookup("confirm.core"), warn: lookup("warn.core") };
|
|
1103
|
-
}
|
|
1104
|
-
return { confirm: lookup("confirm.uninstall"), warn: null };
|
|
1105
|
-
}
|
|
1106
1238
|
function InstalledTab({ notify, installed }) {
|
|
1107
1239
|
const { loading, data, error, reload } = installed;
|
|
1108
1240
|
const [openPkg, setOpenPkg] = useState(null);
|
|
@@ -1158,33 +1290,33 @@ function InstalledTab({ notify, installed }) {
|
|
|
1158
1290
|
"div",
|
|
1159
1291
|
{ className: "dshm-cards" },
|
|
1160
1292
|
items.map((it) => {
|
|
1161
|
-
const
|
|
1293
|
+
const vm = installedViewModel2(it);
|
|
1162
1294
|
return Card({
|
|
1163
1295
|
key: it.pkg,
|
|
1164
|
-
icon: h(Icon, { entry: { name: it.name, github:
|
|
1296
|
+
icon: h(Icon, { entry: { name: it.name, github: vm.githubRepo, icon: null } }),
|
|
1165
1297
|
name: it.name,
|
|
1166
1298
|
badges: [
|
|
1167
|
-
it.outdated ? h("span", { className: "dshm-badge warn", key: "u" }, `\u2B06 ${
|
|
1299
|
+
it.outdated ? h("span", { className: "dshm-badge warn", key: "u" }, `\u2B06 ${vm.latestLabel}`.trim()) : null,
|
|
1168
1300
|
it.registryId ? h("span", { className: "dshm-badge", key: "r" }, lookup("badge.market")) : h("span", { className: "dshm-badge info", key: "r" }, lookup("badge.nonmarket"))
|
|
1169
1301
|
],
|
|
1170
1302
|
desc: it.description || "\uFF08\u65E0\u63CF\u8FF0\uFF09",
|
|
1171
1303
|
sub: [
|
|
1172
1304
|
`v${it.version || "?"}`,
|
|
1173
|
-
|
|
1305
|
+
vm.sourceLabelKey ? lookup(vm.sourceLabelKey) : it.source
|
|
1174
1306
|
].join(" \xB7 "),
|
|
1175
1307
|
links: h(LinksRow, {
|
|
1176
1308
|
npm: it.source === "npm" ? it.pkg : null,
|
|
1177
|
-
github:
|
|
1309
|
+
github: vm.githubRepo
|
|
1178
1310
|
}),
|
|
1179
1311
|
open: openPkg === it.pkg,
|
|
1180
1312
|
onToggle: () => setOpenPkg(openPkg === it.pkg ? null : it.pkg),
|
|
1181
1313
|
detail: readmePkg === it.pkg ? h(ReadmeBlock, { pkg: it.pkg }) : DetailRows([
|
|
1182
1314
|
[lookup("detail.pkg"), it.pkg],
|
|
1183
1315
|
[lookup("detail.spec"), it.spec],
|
|
1184
|
-
[lookup("detail.latest"),
|
|
1316
|
+
[lookup("detail.latest"), vm.latestLabelDetail],
|
|
1185
1317
|
[lookup("detail.listed"), it.registryId || lookup("detail.listed.no")],
|
|
1186
1318
|
[lookup("detail.path"), it.path],
|
|
1187
|
-
guard.
|
|
1319
|
+
vm.guard.warnKey ? [lookup("detail.note"), lookup(vm.guard.warnKey, vm.guard.warnParams)] : null
|
|
1188
1320
|
]),
|
|
1189
1321
|
actions: [
|
|
1190
1322
|
h("button", {
|
|
@@ -1211,7 +1343,7 @@ function InstalledTab({ notify, installed }) {
|
|
|
1211
1343
|
h(TwoStepButton, {
|
|
1212
1344
|
key: "un",
|
|
1213
1345
|
label: lookup("action.uninstall"),
|
|
1214
|
-
confirmLabel: guard.
|
|
1346
|
+
confirmLabel: lookup(vm.guard.confirmKey),
|
|
1215
1347
|
className: "dshm-btn sm",
|
|
1216
1348
|
disabled: busyPkg === it.pkg,
|
|
1217
1349
|
onConfirm: () => doUninstall(it)
|
|
@@ -1223,23 +1355,8 @@ function InstalledTab({ notify, installed }) {
|
|
|
1223
1355
|
);
|
|
1224
1356
|
}
|
|
1225
1357
|
function regSourceLabel(data) {
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
"default-raw": "src.default.raw",
|
|
1229
|
-
"default-jsdelivr": "src.default.jsdelivr",
|
|
1230
|
-
"default-cache": "src.default.cache",
|
|
1231
|
-
bundled: "src.bundled",
|
|
1232
|
-
"custom-url": "src.custom.url",
|
|
1233
|
-
"custom-file": "src.custom.file",
|
|
1234
|
-
"custom-cache": "src.custom.cache",
|
|
1235
|
-
"custom-unavailable": "src.custom.unavailable",
|
|
1236
|
-
// 旧字段兼容
|
|
1237
|
-
override: "src.override",
|
|
1238
|
-
jsdelivr: "src.jsdelivr",
|
|
1239
|
-
raw: "src.raw",
|
|
1240
|
-
cache: "src.cache"
|
|
1241
|
-
};
|
|
1242
|
-
return lookup(map[data.source] || data.source);
|
|
1358
|
+
const key = registrySourceKey2(data);
|
|
1359
|
+
return key === null ? "\u2014" : lookup(key);
|
|
1243
1360
|
}
|
|
1244
1361
|
function configStatusLabel(status) {
|
|
1245
1362
|
return lookup(`settings.status.${status || "loading"}` || "settings.status.loading");
|
|
@@ -1646,43 +1763,6 @@ function registerSlot(slots, options, component) {
|
|
|
1646
1763
|
if (next.key == null && next.id != null) next.key = next.id;
|
|
1647
1764
|
return slots.register(next, component);
|
|
1648
1765
|
}
|
|
1649
|
-
function pickPayload(props) {
|
|
1650
|
-
const found = [];
|
|
1651
|
-
const visit = (node, depth) => {
|
|
1652
|
-
if (!node || depth > 6) return;
|
|
1653
|
-
if (typeof node === "string") {
|
|
1654
|
-
const t = node.trim();
|
|
1655
|
-
if ((t.startsWith("{") || t.startsWith("[")) && t.length > 8) {
|
|
1656
|
-
try {
|
|
1657
|
-
visit(JSON.parse(t), depth + 1);
|
|
1658
|
-
} catch {
|
|
1659
|
-
}
|
|
1660
|
-
}
|
|
1661
|
-
return;
|
|
1662
|
-
}
|
|
1663
|
-
if (typeof node !== "object") return;
|
|
1664
|
-
if (Array.isArray(node)) {
|
|
1665
|
-
for (const x of node) visit(x, depth + 1);
|
|
1666
|
-
return;
|
|
1667
|
-
}
|
|
1668
|
-
if (Array.isArray(node.items)) found.push(node);
|
|
1669
|
-
for (const key of ["block", "meta", "result", "resultView", "view", "data", "value", "payload", "content", "message"]) {
|
|
1670
|
-
if (node[key] != null) visit(node[key], depth + 1);
|
|
1671
|
-
}
|
|
1672
|
-
};
|
|
1673
|
-
visit(props, 0);
|
|
1674
|
-
return found.find((x) => x && Array.isArray(x.items)) || null;
|
|
1675
|
-
}
|
|
1676
|
-
function parseToolArgs(props) {
|
|
1677
|
-
const block = props?.block;
|
|
1678
|
-
const raw = (block && "kind" in block ? block.call?.argsRaw : block?.argsRaw) || "";
|
|
1679
|
-
if (!raw || typeof raw !== "string") return {};
|
|
1680
|
-
try {
|
|
1681
|
-
return JSON.parse(raw);
|
|
1682
|
-
} catch {
|
|
1683
|
-
return {};
|
|
1684
|
-
}
|
|
1685
|
-
}
|
|
1686
1766
|
function ToolCardRow({ it, onInstalled }) {
|
|
1687
1767
|
const [busy, setBusy] = useState(false);
|
|
1688
1768
|
const install = async (e) => {
|
|
@@ -1723,8 +1803,8 @@ function ToolCardRow({ it, onInstalled }) {
|
|
|
1723
1803
|
}
|
|
1724
1804
|
function SearchToolView(props) {
|
|
1725
1805
|
useEffect(() => ensureCss(), []);
|
|
1726
|
-
const payload =
|
|
1727
|
-
const args =
|
|
1806
|
+
const payload = pickPayload2(props);
|
|
1807
|
+
const args = parseToolArgs2(props);
|
|
1728
1808
|
const query = String(payload?.query || args.query || "").trim();
|
|
1729
1809
|
const fromTool = Array.isArray(payload?.items) && payload.items.length ? payload.items : null;
|
|
1730
1810
|
const running = !!(props?.block && !("kind" in props.block));
|
|
@@ -1764,7 +1844,7 @@ function SearchToolView(props) {
|
|
|
1764
1844
|
}
|
|
1765
1845
|
function ListToolView(props) {
|
|
1766
1846
|
useEffect(() => ensureCss(), []);
|
|
1767
|
-
const payload =
|
|
1847
|
+
const payload = pickPayload2(props);
|
|
1768
1848
|
const items = Array.isArray(payload?.items) ? payload.items : [];
|
|
1769
1849
|
if (!items.length) return null;
|
|
1770
1850
|
return h(
|