dsh-plugin-update 0.5.8 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,11 +20,12 @@
20
20
  * - 截断数值不动(100 节/每类 200 条/单条 500 字/全文 64K),解析附计数元数据只记数字;
21
21
  * 超限类标计数小字,Security 超限进内折叠;BREAKING 前缀识别 + 行首徽标;yanked 横幅只看 to 版。
22
22
  */
23
+ import { type AppLang } from './lang.js';
23
24
  /** 包内日志文件名(包根,与 tarball 内同名文件同一名字)。 */
24
25
  export declare const CHANGELOG_FILENAME = "CHANGELOG.md";
25
- /** 缺日志时的中性提示(不挡安装,安装按钮状态不变)。 */
26
+ /** 缺日志时的中性提示(不挡安装,安装按钮状态不变;zh 原文,渲染走字典 changelog.neutral.hint,留常量只为兼容既有导入)。 */
26
27
  export declare const CHANGELOG_NEUTRAL_HINT = "\u4F5C\u8005\u672A\u63D0\u4F9B\u66F4\u65B0\u8BF4\u660E";
27
- /** 中性提示完整行(含“安装不受影响”,把“不挡安装”说成人话)。 */
28
+ /** 中性提示完整行(含“安装不受影响”,把“不挡安装”说成人话;渲染走字典 changelog.neutral.line)。 */
28
29
  export declare const CHANGELOG_NEUTRAL_LINE = "\u4F5C\u8005\u672A\u63D0\u4F9B\u66F4\u65B0\u8BF4\u660E\uFF0C\u5B89\u88C5\u4E0D\u53D7\u5F71\u54CD\u3002";
29
30
  /** 输入上限(字符):超限截断后解析,永不抛错、不OOM。 */
30
31
  export declare const CHANGELOG_MAX_CHARS: number;
@@ -79,8 +80,12 @@ export declare function matchVersionHeading(line: unknown): string | null;
79
80
  export declare function matchCategoryHeading(line: unknown): string | null;
80
81
  export declare function matchBulletBody(line: unknown): string | null;
81
82
  export declare function isFenceToggle(line: unknown): boolean;
82
- /** 破坏标记徽标文案(中文 UI 一致,原文前缀另行加粗保留)。 */
83
+ /** 破坏标记徽标文案(中文 UI 一致,原文前缀另行加粗保留;渲染走字典 changelog.breaking.badge/aria,留常量只为兼容既有导入)。 */
83
84
  export declare const BREAKING_BADGE_TEXT = "\u4E0D\u517C\u5BB9";
85
+ /** 六类标题按当前语言单语组装(#66,唯一源仍是 CATEGORY_ZH,不另起第二套映射):中文「新增(Added)」观感、英文「Added」。 */
86
+ export declare function changelogCategoryLabel(cat: ChangelogCategory, lang?: AppLang | string | null): string;
87
+ /** 折叠类标题(含条数):中文「弃用预告(Deprecated)(3)」/英文「Deprecated (3)」;条数是变量值,不译。 */
88
+ export declare function changelogFoldedLabel(cat: ChangelogCategory, count: number, lang?: AppLang | string | null): string;
84
89
  /** 剥行首 markdown 装饰(加粗/引用/前后空白),只为识别,渲染保留原文一字不动。 */
85
90
  export declare function stripBreakingDecorations(s: unknown): string;
86
91
  /** 条目是否为破坏标记(去饰后开头匹配,大小写不敏感,中英文冒号皆可)。 */
@@ -122,16 +127,16 @@ export declare function selectChangelogEntries(entries: unknown, fromExclusive:
122
127
  export declare function changelogForUpdate(entries: unknown, runningVersion: unknown, latestVersion: unknown, installedVersion?: unknown): ChangelogEntry[];
123
128
  /** 计数元数据取值(缺省视为与 sections 等长,只记数字)。 */
124
129
  export declare function countsOf(entry: ChangelogEntry | null | undefined): Record<ChangelogCategory, number>;
125
- /** 超限小字(诚实截断):共 M 条,仅显示前 N 条。 */
126
- export declare function truncatedNoteHTML(total: number, shown: number): string;
127
- /** 撤回横幅(只看 to 版,纯展示,不挡安装,文案冻结)。 */
128
- export declare function yankedBannerHTML(version: unknown): string;
129
- /** 单条目 HTML(含破坏标记徽标与前缀加粗,正文一字不动)。 */
130
- export declare function renderChangelogItem(item: string): string;
131
- /** 单节 HTML(调用方保证已过滤 Unreleased 与空节,本函数再兜底一次)。 */
132
- export declare function renderChangelogSection(entry: ChangelogEntry): string;
133
- /** 中性提示 HTML(缺日志、取不到、无区间内容时统一用它,不挡安装)。 */
134
- export declare function renderChangelogNeutral(): string;
130
+ /** 超限小字(诚实截断,#66 入字典单语,lang 缺省 zh 零回归):中文与旧文案一字不差,英文走字典。 */
131
+ export declare function truncatedNoteHTML(total: number, shown: number, lang?: AppLang | string | null): string;
132
+ /** 撤回横幅(只看 to 版,纯展示,不挡安装,#66 入字典单语,lang 缺省 zh 零回归;中文与旧文案一字不差)。 */
133
+ export declare function yankedBannerHTML(version: unknown, lang?: AppLang | string | null): string;
134
+ /** 单条目 HTML(含破坏标记徽标与前缀加粗,正文一字不动;#66 徽标与无障碍名入字典单语,lang 缺省 zh 零回归)。 */
135
+ export declare function renderChangelogItem(item: string, lang?: AppLang | string | null): string;
136
+ /** 单节 HTML(调用方保证已过滤 Unreleased 与空节,本函数再兜底一次;#66 按 lang 单语,缺省 zh 零回归)。 */
137
+ export declare function renderChangelogSection(entry: ChangelogEntry, lang?: AppLang | string | null): string;
138
+ /** 中性提示 HTML(缺日志、取不到、无区间内容时统一用它,不挡安装;#66 入字典单语,lang 缺省 zh 零回归)。 */
139
+ export declare function renderChangelogNeutral(lang?: AppLang | string | null): string;
135
140
  /**
136
141
  * 区间渲染 HTML(纯函数):
137
142
  * entries 非数组/空、无可见区间内容一律回中性提示;
@@ -140,6 +145,7 @@ export declare function renderChangelogNeutral(): string;
140
145
  export declare function renderChangelogHTML(entries: unknown, opts?: {
141
146
  from?: string | null;
142
147
  to?: string | null;
148
+ lang?: AppLang | string | null;
143
149
  }): string;
144
150
  /** 校验诊断(一行一码,行号为原文件 1-based,诊断按行号排序)。 */
145
151
  export interface ChangelogDiagnostic {
package/dist/changelog.js CHANGED
@@ -1,5 +1,7 @@
1
1
  // AUTO-GENERATED by node build.mjs — DO NOT EDIT. Source: src/changelog.ts
2
2
  import { compareReleaseVersions, validReleaseVersion } from "./service.js";
3
+ import { copyText } from "./bilingual.js";
4
+ import { normalizeLangTag } from "./lang.js";
3
5
  const CHANGELOG_FILENAME = "CHANGELOG.md";
4
6
  const CHANGELOG_NEUTRAL_HINT = "\u4F5C\u8005\u672A\u63D0\u4F9B\u66F4\u65B0\u8BF4\u660E";
5
7
  const CHANGELOG_NEUTRAL_LINE = "\u4F5C\u8005\u672A\u63D0\u4F9B\u66F4\u65B0\u8BF4\u660E\uFF0C\u5B89\u88C5\u4E0D\u53D7\u5F71\u54CD\u3002";
@@ -109,6 +111,18 @@ function isFenceToggle(line) {
109
111
  }
110
112
  }
111
113
  const BREAKING_BADGE_TEXT = "\u4E0D\u517C\u5BB9";
114
+ function changelogCategoryLabel(cat, lang) {
115
+ const l = normalizeLangTag(lang ?? "zh");
116
+ const zh = CHANGELOG_CATEGORY_ZH[cat];
117
+ if (l === "en") return cat;
118
+ return zh + "\uFF08" + cat + "\uFF09";
119
+ }
120
+ function changelogFoldedLabel(cat, count, lang) {
121
+ const l = normalizeLangTag(lang ?? "zh");
122
+ const n = String(Math.floor(count));
123
+ if (l === "en") return cat + " (" + n + ")";
124
+ return CHANGELOG_CATEGORY_ZH[cat] + "\uFF08" + cat + "\uFF09\uFF08" + n + "\uFF09";
125
+ }
112
126
  function stripBreakingDecorations(s) {
113
127
  try {
114
128
  let t = String(s !== null && s !== void 0 ? s : "").trim();
@@ -331,26 +345,31 @@ function countsOf(entry) {
331
345
  return { Added: 0, Fixed: 0, Changed: 0, Deprecated: 0, Removed: 0, Security: 0 };
332
346
  }
333
347
  }
334
- function truncatedNoteHTML(total, shown) {
348
+ function truncatedNoteHTML(total, shown, lang) {
335
349
  try {
350
+ const l = normalizeLangTag(lang ?? "zh");
336
351
  const m = Math.floor(total);
337
352
  const n = Math.floor(shown);
338
- return '<div class="dsh-upd-changelog-count">\u5171 ' + String(m) + " \u6761\uFF0C\u4EC5\u663E\u793A\u524D " + String(n) + " \u6761</div>";
353
+ const text = copyText("changelog.truncated.count", l, { m: String(m), n: String(n) });
354
+ return '<div class="dsh-upd-changelog-count">' + escapeChangelogHtml(text) + "</div>";
339
355
  } catch {
340
356
  return "";
341
357
  }
342
358
  }
343
- function yankedBannerHTML(version) {
359
+ function yankedBannerHTML(version, lang) {
344
360
  try {
361
+ const l = normalizeLangTag(lang ?? "zh");
345
362
  const v = typeof version === "string" ? version.trim() : "";
346
363
  if (!v) return "";
347
- return '<div class="dsh-upd-changelog-yanked" role="alert">\u76EE\u6807\u7248\u672C ' + escapeChangelogHtml(v) + " \u5DF2\u88AB\u4F5C\u8005\u64A4\u56DE\uFF08yanked\uFF09\uFF0C\u5B89\u88C5\u4E0D\u53D7\u5F71\u54CD\uFF0C\u7EE7\u7EED\u524D\u8BF7\u786E\u8BA4\u3002</div>";
364
+ const text = copyText("changelog.yanked.banner", l, { version: v });
365
+ return '<div class="dsh-upd-changelog-yanked" role="alert">' + escapeChangelogHtml(text) + "</div>";
348
366
  } catch {
349
367
  return "";
350
368
  }
351
369
  }
352
- function renderChangelogItem(item) {
370
+ function renderChangelogItem(item, lang) {
353
371
  try {
372
+ const l = normalizeLangTag(lang ?? "zh");
354
373
  const s = String(item !== null && item !== void 0 ? item : "");
355
374
  if (!s) return "";
356
375
  const split = splitBreakingPrefix(s);
@@ -358,22 +377,25 @@ function renderChangelogItem(item) {
358
377
  const head = escapeChangelogHtml(split.head);
359
378
  const prefix = escapeChangelogHtml(split.prefix);
360
379
  const rest = escapeChangelogHtml(split.rest);
361
- const badge = '<span class="dsh-upd-breaking-badge" role="img" aria-label="\u7834\u574F\u6027\u53D8\u66F4">' + BREAKING_BADGE_TEXT + "</span> ";
380
+ const badgeText = copyText("changelog.breaking.badge", l);
381
+ const badgeAria = copyText("changelog.breaking.aria", l);
382
+ const badge = '<span class="dsh-upd-breaking-badge" role="img" aria-label="' + escapeChangelogHtml(badgeAria) + '">' + escapeChangelogHtml(badgeText) + "</span> ";
362
383
  return "<li>" + head + badge + "<strong>" + prefix + "</strong>" + rest + "</li>";
363
384
  } catch {
364
385
  return "";
365
386
  }
366
387
  }
367
- function renderChangelogSection(entry) {
388
+ function renderChangelogSection(entry, lang) {
368
389
  try {
369
390
  if (!entry || typeof entry !== "object") return "";
370
391
  const version = String(entry.version !== void 0 && entry.version !== null ? String(entry.version) : "").trim();
371
392
  if (!version || isUnreleasedVersion(version)) return "";
372
393
  if (!hasVisibleSections(entry)) return "";
394
+ const l = normalizeLangTag(lang ?? "zh");
373
395
  const dateRaw = entry.date;
374
396
  const date = typeof dateRaw === "string" ? dateRaw : "";
375
397
  const yankedFlag = entry.yanked === true;
376
- const yankedSuffix = yankedFlag ? " \xB7 \u5DF2\u64A4\u56DE" : "";
398
+ const yankedSuffix = yankedFlag ? copyText("changelog.yanked.suffix", l) : "";
377
399
  const title = (date ? version + " \xB7 " + date : version) + yankedSuffix;
378
400
  const counts = countsOf(entry);
379
401
  const parts = [];
@@ -382,42 +404,44 @@ function renderChangelogSection(entry) {
382
404
  for (const cat of CHANGELOG_MUST_SHOW) {
383
405
  const items = Array.isArray(entry.sections ? entry.sections[cat] : null) ? entry.sections[cat] : [];
384
406
  if (!items || items.length === 0) continue;
385
- const label = cat + " \xB7 " + CHANGELOG_CATEGORY_ZH[cat];
407
+ const label = changelogCategoryLabel(cat, l);
386
408
  parts.push('<div class="dsh-upd-changelog-cat" data-cat="' + cat + '">');
387
409
  parts.push('<div class="dsh-upd-changelog-catname">' + escapeChangelogHtml(label) + "</div>");
388
410
  const total = counts[cat];
389
411
  const shown = items.length;
390
412
  if (total > shown) {
391
- parts.push(truncatedNoteHTML(total, shown));
413
+ parts.push(truncatedNoteHTML(total, shown, l));
392
414
  }
393
415
  parts.push("<ul>");
394
416
  for (const item of items) {
395
417
  if (!item) continue;
396
- const li = renderChangelogItem(item);
418
+ const li = renderChangelogItem(item, l);
397
419
  if (li) parts.push(li);
398
420
  }
399
421
  parts.push("</ul>");
400
422
  if (cat === "Security" && total > shown) {
401
423
  const restCount = total - shown;
402
- parts.push('<details class="dsh-upd-changelog-security-more"><summary>\u5176\u4F59 ' + String(restCount) + ' \u6761</summary><div class="dsh-upd-changelog-more-note">\u4E3A\u4FDD\u6301\u9762\u677F\u6027\u80FD\uFF0C\u5176\u4F59\u6761\u76EE\u5DF2\u6298\u53E0\uFF0C\u53EF\u67E5\u770B\u539F\u6587\u3002</div></details>');
424
+ const sumText = copyText("changelog.security.summary", l, { n: String(restCount) });
425
+ const noteText = copyText("changelog.security.note", l);
426
+ parts.push('<details class="dsh-upd-changelog-security-more"><summary>' + escapeChangelogHtml(sumText) + '</summary><div class="dsh-upd-changelog-more-note">' + escapeChangelogHtml(noteText) + "</div></details>");
403
427
  }
404
428
  parts.push("</div>");
405
429
  }
406
430
  for (const cat of CHANGELOG_FOLDED) {
407
431
  const items = Array.isArray(entry.sections ? entry.sections[cat] : null) ? entry.sections[cat] : [];
408
432
  if (!items || items.length === 0) continue;
409
- const label = cat + " \xB7 " + CHANGELOG_CATEGORY_ZH[cat] + "\uFF08" + String(items.length) + "\uFF09";
433
+ const label = changelogFoldedLabel(cat, items.length, l);
410
434
  parts.push('<details class="dsh-upd-changelog-fold" data-cat="' + cat + '">');
411
435
  parts.push("<summary>" + escapeChangelogHtml(label) + "</summary>");
412
436
  const total = counts[cat];
413
437
  const shown = items.length;
414
438
  if (total > shown) {
415
- parts.push(truncatedNoteHTML(total, shown));
439
+ parts.push(truncatedNoteHTML(total, shown, l));
416
440
  }
417
441
  parts.push("<ul>");
418
442
  for (const item of items) {
419
443
  if (!item) continue;
420
- const li = renderChangelogItem(item);
444
+ const li = renderChangelogItem(item, l);
421
445
  if (li) parts.push(li);
422
446
  }
423
447
  parts.push("</ul></details>");
@@ -428,12 +452,19 @@ function renderChangelogSection(entry) {
428
452
  return "";
429
453
  }
430
454
  }
431
- function renderChangelogNeutral() {
432
- return `<div class="dsh-upd-changelog-neutral">${escapeChangelogHtml(CHANGELOG_NEUTRAL_LINE)}</div>`;
455
+ function renderChangelogNeutral(lang) {
456
+ try {
457
+ const l = normalizeLangTag(lang ?? "zh");
458
+ const text = copyText("changelog.neutral.line", l);
459
+ return `<div class="dsh-upd-changelog-neutral">${escapeChangelogHtml(text)}</div>`;
460
+ } catch {
461
+ return "";
462
+ }
433
463
  }
434
464
  function renderChangelogHTML(entries, opts) {
435
465
  try {
436
- if (!Array.isArray(entries) || entries.length === 0) return renderChangelogNeutral();
466
+ const l = normalizeLangTag(opts?.lang ?? "zh");
467
+ if (!Array.isArray(entries) || entries.length === 0) return renderChangelogNeutral(l);
437
468
  const from = opts && typeof opts.from === "string" ? opts.from : null;
438
469
  const to = opts && typeof opts.to === "string" ? opts.to : null;
439
470
  let ranged;
@@ -449,14 +480,19 @@ function renderChangelogHTML(entries, opts) {
449
480
  }
450
481
  });
451
482
  }
452
- if (ranged.length === 0) return renderChangelogNeutral();
453
- const blocks = ranged.map((e) => renderChangelogSection(e)).filter((s) => !!s);
454
- if (blocks.length === 0) return renderChangelogNeutral();
483
+ if (ranged.length === 0) return renderChangelogNeutral(l);
484
+ const blocks = ranged.map((e) => renderChangelogSection(e, l)).filter((s) => !!s);
485
+ if (blocks.length === 0) return renderChangelogNeutral(l);
455
486
  return `<div class="dsh-upd-changelog">
456
487
  ${blocks.join("\n")}
457
488
  </div>`;
458
489
  } catch {
459
- return renderChangelogNeutral();
490
+ try {
491
+ const ll = normalizeLangTag(opts?.lang ?? "zh");
492
+ return renderChangelogNeutral(ll);
493
+ } catch {
494
+ return "";
495
+ }
460
496
  }
461
497
  }
462
498
  const CHANGELOG_VALIDATE_HINTS = {
@@ -639,6 +675,8 @@ export {
639
675
  RE_VERSION_HEADING,
640
676
  RE_VERSION_NUM,
641
677
  RE_YANKED,
678
+ changelogCategoryLabel,
679
+ changelogFoldedLabel,
642
680
  changelogForUpdate,
643
681
  countsOf,
644
682
  hasVisibleSections,
package/dist/diag.d.ts CHANGED
@@ -31,6 +31,7 @@
31
31
  * 构造全程 best-effort:任何一步异常即回 undefined(调用方按无 diag 的旧形状返回,
32
32
  * 新面板×旧载荷仍为正常缺省,不抛)。
33
33
  */
34
+ import { type AppLang } from './lang.js';
34
35
  /** diag 对象版本:只管大门,新增可选键不 bump,面板永不分支于版本。 */
35
36
  export declare const DIAG_VERSION = 1;
36
37
  /** 阶段枚举(冻结 6 值,与真实接缝对齐)。 */
@@ -67,6 +68,8 @@ export interface DiagInput {
67
68
  environmentKind?: unknown;
68
69
  /** 本次电话耗时毫秒(只收有限非负数)。 */
69
70
  latencyMs?: unknown;
71
+ /** 人话兜底渲染语言(#66 单语:缺省 zh 零回归;电话侧无 DOM 信号时仍落 zh,面板侧 free-text 英文混入属正常见 #57 v2 非目标)。 */
72
+ lang?: AppLang | string | null;
70
73
  }
71
74
  export interface DiagObject {
72
75
  v: number;
package/dist/diag.js CHANGED
@@ -1,6 +1,8 @@
1
1
  // AUTO-GENERATED by node build.mjs — DO NOT EDIT. Source: src/diag.ts
2
2
  import { DIAG_INLINE_BUDGET_BYTES, diagByteLength, enforceDiagBudget, resolveRegistryHost, sanitizeDetail } from "./redaction.js";
3
3
  import { validReleaseVersion, validRequestId } from "./service.js";
4
+ import { copyText } from "./bilingual.js";
5
+ import { normalizeLangTag } from "./lang.js";
4
6
  const DIAG_VERSION = 1;
5
7
  const DIAG_STAGES = [
6
8
  "read-installed",
@@ -116,7 +118,7 @@ function pickEnvironmentKind(raw) {
116
118
  function pickId(raw) {
117
119
  return typeof raw === "string" && validRequestId(raw) ? raw.trim() : null;
118
120
  }
119
- function pickDetail(errorCode, error, httpStatus, phoneKind) {
121
+ function pickDetail(errorCode, error, httpStatus, phoneKind, lang) {
120
122
  try {
121
123
  const rawDetail = error?.detail;
122
124
  if (typeof rawDetail === "string" && rawDetail.trim()) {
@@ -132,24 +134,34 @@ function pickDetail(errorCode, error, httpStatus, phoneKind) {
132
134
  }
133
135
  const code = String(errorCode || "");
134
136
  const phone = String(phoneKind || "");
135
- let fallback = "\u64CD\u4F5C\u5931\u8D25";
136
- if (code === "check-failed" && phone === "update-status") fallback = "\u8BFB\u672C\u5730\u72B6\u6001\u6CA1\u6210\u529F";
137
- else if ((code === "check-failed" || code === "internal") && phone === "update-install") fallback = "\u88C5\u524D\u91CD\u9A8C\u53D6\u6570\u6CA1\u6210\u529F";
138
- else if (code === "check-failed" && httpStatus === 429) fallback = "\u6E90\u8FD4\u56DE 429\uFF0C\u8FD9\u4E00\u5206\u949F\u8BF7\u6C42\u592A\u591A";
139
- else if (code === "check-failed" && typeof httpStatus === "number") fallback = `\u6E90\u8FD4\u56DE ${httpStatus}\uFF0C\u91CD\u8BD5\u4ECD\u5931\u8D25`;
140
- else if (code === "check-failed" || code === "internal") fallback = "\u67E5\u65B0\u7248\u6CA1\u6210\u529F\uFF08\u8054\u7F51\u3001\u6E90\u3001\u9650\u6D41\u90FD\u53EF\u80FD\uFF09";
141
- else if (code === "invalid-release") fallback = "\u6E05\u5355\u91CC\u7684\u7248\u672C\u53F7\u4E0D\u662F\u5408\u6CD5\u7248\u672C";
142
- else if (code === "check-expired") fallback = "\u51ED\u8BC1\u8FC7\u671F\u4E86\uFF0C\u5B89\u88C5\u8BF7\u6C42\u88AB\u62D2";
143
- else if (code === "update-busy") fallback = "\u540C\u4E00\u4F7F\u7528\u8303\u56F4\u6B63\u5728\u88C5\u53E6\u4E00\u4E2A";
144
- else if (code === "install-failed") fallback = "\u5B89\u88C5\u5931\u8D25";
145
- else if (code === "unknown-profile") fallback = "\u4F7F\u7528\u8303\u56F4\u6216\u63D2\u4EF6\u4F4D\u7F6E\u8BA4\u4E0D\u51FA";
146
- else if (code === "source-install") fallback = "\u5F53\u524D\u662F\u4ECE\u6E90\u7801\u88C5\u7684\uFF0C\u4E0D\u662F\u6309\u7248\u672C\u53F7\u88C5\u7684";
147
- else if (code === "invalid-installation") fallback = "\u5DF2\u88C5\u7684\u5305\u4E0D\u5B8C\u6574";
148
- else if (code === "installation-changed") fallback = "\u5B89\u88C5\u4F4D\u7F6E\u5728\u4F7F\u7528\u4E2D\u9014\u53D8\u4E86";
149
- else if (code === "pending-restart") fallback = "\u65B0\u7248\u5DF2\u88C5\u5230\u78C1\u76D8\uFF0C\u6B63\u5728\u8DD1\u7684\u8FD8\u662F\u65E7\u7248";
150
- else if (code === "incompatible-node") fallback = "\u65B0\u7248\u8981\u6C42\u7684 Node \u4E0E\u5F53\u524D\u8FD0\u884C\u7684\u5BF9\u4E0D\u4E0A";
151
- else if (code === "registry-conflict") fallback = "\u672C\u5730\u58F0\u660E\u7684\u7248\u672C\u4E0E\u78C1\u76D8\u5B9E\u9645\u7248\u672C\u4E92\u76F8\u77DB\u76FE";
152
- else if (code === "recovery-required") fallback = "\u4E0A\u6B21\u5B89\u88C5\u88AB\u6253\u65AD\uFF0C\u7559\u4E0B\u4E00\u4E2A\u534A\u622A\u4EFB\u52A1";
137
+ const l = normalizeLangTag(lang ?? "zh");
138
+ let key = "diag.fallback.generic";
139
+ let values;
140
+ if (code === "check-failed" && phone === "update-status") key = "diag.fallback.read-installed";
141
+ else if ((code === "check-failed" || code === "internal") && phone === "update-install") key = "diag.fallback.revalidate-fetch";
142
+ else if (code === "check-failed" && httpStatus === 429) key = "diag.fallback.rate-limited";
143
+ else if (code === "check-failed" && typeof httpStatus === "number") {
144
+ key = "diag.fallback.http-status";
145
+ values = { status: String(httpStatus) };
146
+ } else if (code === "check-failed" || code === "internal") key = "panel.failure.check-failed.title";
147
+ else if (code === "invalid-release") key = "diag.fallback.invalid-release";
148
+ else if (code === "check-expired") key = "panel.failure.check-expired.title";
149
+ else if (code === "update-busy") key = "panel.failure.update-busy.title";
150
+ else if (code === "install-failed") key = "diag.fallback.install-failed";
151
+ else if (code === "unknown-profile") key = "diag.fallback.unknown-profile";
152
+ else if (code === "source-install") key = "diag.fallback.source-install";
153
+ else if (code === "invalid-installation") key = "diag.fallback.invalid-installation";
154
+ else if (code === "installation-changed") key = "diag.fallback.installation-changed";
155
+ else if (code === "pending-restart") key = "diag.fallback.pending-restart";
156
+ else if (code === "incompatible-node") key = "diag.fallback.incompatible-node";
157
+ else if (code === "registry-conflict") key = "diag.fallback.registry-conflict";
158
+ else if (code === "recovery-required") key = "diag.fallback.recovery-required";
159
+ let fallback;
160
+ try {
161
+ fallback = copyText(key, l, values);
162
+ } catch {
163
+ fallback = copyText("diag.fallback.generic", "zh");
164
+ }
153
165
  const clean = sanitizeDetail(fallback);
154
166
  return clean ? clean : null;
155
167
  } catch {
@@ -176,7 +188,7 @@ function buildDiag(input) {
176
188
  const httpStatus = pickHttpStatus(stage, input?.error);
177
189
  const exitCode = pickExitCode(stage, input?.error);
178
190
  const latencyMs = pickLatencyMs(input?.latencyMs);
179
- const detail = pickDetail(errorCode, input?.error, httpStatus, phoneKind);
191
+ const detail = pickDetail(errorCode, input?.error, httpStatus, phoneKind, input?.lang ?? "zh");
180
192
  const targetPackageName = pickPackageName(input?.targetPackageName);
181
193
  const runningVersion = pickVersion(input?.runningVersion);
182
194
  const latestVersion = pickVersion(input?.latestVersion);
@@ -40,10 +40,14 @@ export interface UpdateBatchEntryOptions {
40
40
  /** 调宿主电话:(phoneName, args) => Promise<reply>。 */
41
41
  call: (name: string, args: Record<string, unknown>) => Promise<unknown>;
42
42
  variant?: BatchEntryVariant;
43
- /** 主题:与单入口/面板同一套(default/archive,d5-paper 为旧别名仍可用)。 */
43
+ /** 主题:与单入口/面板同一套(default/archive)。 */
44
44
  theme?: UpdatePanelTheme;
45
45
  /** 缺省 'mount':进页面静默查一次(只调 .batchStatus,只读)。'never' 则只在用户点击时查。 */
46
46
  autoCheck?: BatchEntryAutoCheck;
47
+ /** 打开面板自动查(#59 D3,透传给批量面板):缺省 true;面板按用户偏好 > 本选项 > 缺省,并与入口预查共用知识时间戳去重(一击只查一次)。 */
48
+ checkOnOpen?: boolean;
49
+ /** 自动继续未终态轮次(#59 Q3,透传给批量面板):缺省 true,与显式按钮并存。 */
50
+ autoResume?: boolean;
47
51
  /** 缺省 'always':查完总是开批量面板(见本类型说明)。 */
48
52
  openOn?: BatchEntryOpenOn;
49
53
  /** 覆盖默认按钮文案(不传就用聚合文案)。 */
@@ -145,8 +145,8 @@ function mountUpdateBatchEntry(container, options) {
145
145
  if (openOn !== "has-update" && openOn !== "always" && openOn !== "manual" && openOn !== "direct") {
146
146
  throw new Error("[dsh-plugin-update] \u70B9\u51FB\u53BB\u5411\u975E\u6CD5\uFF1A\u53EA\u6536 has-update / always / manual / direct\uFF08\u6536\u5230 " + JSON.stringify(options.openOn) + "\uFF09");
147
147
  }
148
- if (options.theme !== void 0 && options.theme !== "default" && options.theme !== "archive" && options.theme !== "d5-paper") {
149
- throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08d5-paper \u4E3A\u65E7\u522B\u540D\u4ECD\u53EF\u7528\uFF09\uFF08\u6536\u5230 " + JSON.stringify(options.theme) + "\uFF09");
148
+ if (options.theme !== void 0 && options.theme !== "default" && options.theme !== "archive") {
149
+ throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08\u6536\u5230 " + JSON.stringify(options.theme) + "\uFF09");
150
150
  }
151
151
  let theme = normalizePanelTheme(options.theme ?? "default");
152
152
  const pollMs = options.pollMs;
@@ -273,6 +273,8 @@ function mountUpdateBatchEntry(container, options) {
273
273
  copyText: options.copyText,
274
274
  autoChangelog: options.autoChangelog,
275
275
  locale: localeOpt,
276
+ checkOnOpen: options.checkOnOpen,
277
+ autoResume: options.autoResume,
276
278
  // 面板点「关闭」即走入口件的完整关闭(收 dialog + 还原按钮 + 重查一次),不再是面板自己停轮询。
277
279
  onCloseRequested: () => close(),
278
280
  call: panelCall
@@ -337,8 +339,8 @@ function mountUpdateBatchEntry(container, options) {
337
339
  render();
338
340
  }
339
341
  function setTheme(next) {
340
- if (next !== "default" && next !== "archive" && next !== "d5-paper") {
341
- throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08d5-paper \u4E3A\u65E7\u522B\u540D\u4ECD\u53EF\u7528\uFF09\uFF08\u6536\u5230 " + JSON.stringify(next) + "\uFF09");
342
+ if (next !== "default" && next !== "archive") {
343
+ throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08\u6536\u5230 " + JSON.stringify(next) + "\uFF09");
342
344
  }
343
345
  theme = normalizePanelTheme(next);
344
346
  if (panel) void panel.setTheme(theme);
package/dist/entry.d.ts CHANGED
@@ -21,6 +21,24 @@ export interface UpdateEntryState {
21
21
  snapshot: UpdateSnapshot | null;
22
22
  error: string | null;
23
23
  }
24
+ /**
25
+ * 入口件按钮尺寸覆盖(#69):只影响 button 本体(字号/内边距/圆角/整体缩放),不碰 dialog 面板。
26
+ * 缺省(不传)保持现状、零回归;badge 圆点与 inline 内嵌不读这些变量,天然不受影响。
27
+ * 实现口径与现有 `--dsh-upd-*` 颜色变量一致:本选项只是把同样的 CSS 变量以内联方式写到容器上,
28
+ * 手写 CSS 变量(`--dsh-update-entry-font-size` / `--dsh-update-entry-padding` /
29
+ * `--dsh-update-entry-border-radius` / `--dsh-update-entry-scale`)同样生效,两者等价。
30
+ * `scale` 即宿主临时方案里容器 `zoom: 1` 开关的正式形态:改一个数即缩放(默认 1)。
31
+ */
32
+ export interface EntrySizing {
33
+ /** 按钮字号(CSS font-size 值,如 '12px'),不传即 13px 默认。 */
34
+ fontSize?: string;
35
+ /** 按钮内边距(CSS padding 值,如 '2px 8px'),不传即 '4px 12px' 默认。 */
36
+ padding?: string;
37
+ /** 按钮圆角(CSS border-radius 值,如 '8px'),不传即默认主题 6px / archive 主题 3px。 */
38
+ borderRadius?: string;
39
+ /** 整体缩放(对应 CSS `zoom`,如 1.2 放大、0.9 缩小),须为大于 0 的有限数,不传即 1。 */
40
+ scale?: number;
41
+ }
24
42
  export interface UpdateEntryOptions {
25
43
  pluginId: string;
26
44
  /** 单插件电话前缀(与宿主侧一致)。 */
@@ -28,7 +46,7 @@ export interface UpdateEntryOptions {
28
46
  /** 调宿主电话:(phoneName, args) => Promise<reply>。 */
29
47
  call: (name: string, args: Record<string, unknown>) => Promise<unknown>;
30
48
  variant?: EntryVariant;
31
- /** 主题:`default` 最小可用深色,`archive` 档案卷纸面浅色(`d5-paper` 为旧别名仍可用)。 */
49
+ /** 主题:`default` 最小可用深色,`archive` 档案卷纸面浅色(仍可用)。 */
32
50
  theme?: UpdatePanelTheme;
33
51
  /** 缺省 'mount':进页面静默查一次(只读)。'never' 则只在用户点击时查。 */
34
52
  autoCheck?: EntryAutoCheck;
@@ -36,6 +54,8 @@ export interface UpdateEntryOptions {
36
54
  openOn?: EntryOpenOn;
37
55
  /** 覆盖默认按钮文案(不传就用状态联动文案)。 */
38
56
  label?: string;
57
+ /** 按钮尺寸覆盖(#69):见 EntrySizing;不传即零回归,badge/inline 不受影响。 */
58
+ sizing?: EntrySizing;
39
59
  /** 语言覆盖(#60 v2):'zh' | 'en' | { getActive(): string; subscribe?(cb): () => void },不传即跟随 html[lang] > navigator > zh。 */
40
60
  locale?: LocaleOption;
41
61
  profileName?: string;
@@ -82,5 +102,10 @@ export declare function entryBilingualHTMLFor(state: UpdateEntryState | null | u
82
102
  export declare function entryBilingualTextFor(state: UpdateEntryState | null | undefined, lang?: AppLang | string | null): string;
83
103
  /** 入口件文案第二出口(唯一出处:测试与接入方都读它;与 HTML 出口同语言,v2 起按 lang 取字典,不再硬编码中文)。 */
84
104
  export declare function entryLabelFor(state: UpdateEntryState | null | undefined, lang?: AppLang | string | null): string;
105
+ /**
106
+ * `sizing` → 容器 style 属性体(纯函数:同一输入永远算出同一串;空/缺省回空串,即不写 style)。
107
+ * 非法即抛(未知键、空串、注入字符、非正有限 scale 都不收)。
108
+ */
109
+ export declare function entrySizingStyleFor(sizing: EntrySizing | null | undefined): string;
85
110
  export declare const UPDATE_ENTRY_CSS: string;
86
111
  export declare function mountUpdateEntry(container: UpdatePanelContainer, options: UpdateEntryOptions): UpdateEntryController;
package/dist/entry.js CHANGED
@@ -62,11 +62,51 @@ function entryLabelFor(state, lang) {
62
62
  const l = lang ?? resolveLang();
63
63
  return copyText(entryBilingualKeyFor(state), l, entryBilingualValuesFor(state));
64
64
  }
65
+ function entrySizingError(raw) {
66
+ return new Error(`[dsh-plugin-update] \u5165\u53E3\u4EF6\u5C3A\u5BF8\u53C2\u6570 sizing \u975E\u6CD5\uFF1A\u53EA\u6536 fontSize / padding / borderRadius\uFF08\u975E\u7A7A CSS \u503C\uFF09\u4E0E scale\uFF08\u5927\u4E8E 0 \u7684\u6709\u9650\u6570\uFF09\uFF08\u6536\u5230 ${JSON.stringify(raw ?? null)})`);
67
+ }
68
+ function isSafeEntryCssValue(value) {
69
+ const v = value.trim();
70
+ if (!v || v.length > 200) return false;
71
+ if (/[;"'<>`{}!&]/.test(v)) return false;
72
+ if (/url\s*\(/i.test(v)) return false;
73
+ if (/expression\s*\(/i.test(v)) return false;
74
+ if (/javascript\s*:/i.test(v)) return false;
75
+ return true;
76
+ }
77
+ function entrySizingStyleFor(sizing) {
78
+ if (sizing === void 0 || sizing === null) return "";
79
+ if (typeof sizing !== "object" || Array.isArray(sizing)) throw entrySizingError(sizing);
80
+ for (const key of Object.keys(sizing)) {
81
+ if (key !== "fontSize" && key !== "padding" && key !== "borderRadius" && key !== "scale") {
82
+ throw entrySizingError(sizing);
83
+ }
84
+ }
85
+ const parts = [];
86
+ const { fontSize, padding, borderRadius, scale } = sizing;
87
+ if (fontSize !== void 0) {
88
+ if (typeof fontSize !== "string" || !isSafeEntryCssValue(fontSize)) throw entrySizingError(sizing);
89
+ parts.push(`--dsh-update-entry-font-size:${fontSize.trim()}`);
90
+ }
91
+ if (padding !== void 0) {
92
+ if (typeof padding !== "string" || !isSafeEntryCssValue(padding)) throw entrySizingError(sizing);
93
+ parts.push(`--dsh-update-entry-padding:${padding.trim()}`);
94
+ }
95
+ if (borderRadius !== void 0) {
96
+ if (typeof borderRadius !== "string" || !isSafeEntryCssValue(borderRadius)) throw entrySizingError(sizing);
97
+ parts.push(`--dsh-update-entry-border-radius:${borderRadius.trim()}`);
98
+ }
99
+ if (scale !== void 0) {
100
+ if (typeof scale !== "number" || !Number.isFinite(scale) || scale <= 0) throw entrySizingError(sizing);
101
+ parts.push(`--dsh-update-entry-scale:${String(scale)}`);
102
+ }
103
+ return parts.join(";");
104
+ }
65
105
  const UPDATE_ENTRY_CSS = [
66
- '.dsh-upd-entry{display:inline-flex;align-items:center;gap:8px;font:13px/1.6 system-ui,"Microsoft YaHei",sans-serif;color:var(--dsh-upd-fg,#1f2937)}',
67
- ".dsh-upd-entry-btn{font:inherit;border:1px solid var(--dsh-upd-line,#d1d5db);border-radius:6px;",
68
- "background:var(--dsh-upd-btn,#f9fafb);color:inherit;padding:4px 12px;cursor:pointer}",
69
- ".dsh-upd-entry-btn:hover{border-color:var(--dsh-upd-primary,#2563eb)}",
106
+ '.dsh-upd-entry{display:inline-flex;align-items:center;gap:8px;font:13px/1.6 var(--dsh-update-font-sans,system-ui,"Microsoft YaHei",sans-serif);font-size:var(--dsh-update-entry-font-size,13px);color:var(--dsh-update-text,#1f2937)}',
107
+ ".dsh-upd-entry-btn{font:inherit;border:1px solid var(--dsh-update-border,#d1d5db);border-radius:var(--dsh-update-entry-border-radius,6px);",
108
+ "background:var(--dsh-update-button-bg,#f9fafb);color:inherit;padding:var(--dsh-update-entry-padding,4px 12px);zoom:var(--dsh-update-entry-scale,1);cursor:pointer}",
109
+ ".dsh-upd-entry-btn:hover{border-color:var(--dsh-update-primary,#2563eb)}",
70
110
  ".dsh-upd-entry-btn,.dsh-upd-entry-dot{transition:background-color .15s ease,border-color .15s ease,color .15s ease,transform .06s ease}",
71
111
  ".dsh-upd-entry-btn:active:not(:disabled){transform:translateY(1px)}",
72
112
  ".dsh-upd-entry-btn:disabled,.dsh-upd-entry-dot:disabled{opacity:.55;cursor:wait}",
@@ -74,25 +114,26 @@ const UPDATE_ENTRY_CSS = [
74
114
  "border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:dsh-upd-entry-spin .8s linear infinite}",
75
115
  "@keyframes dsh-upd-entry-spin{to{transform:rotate(360deg)}}",
76
116
  '@media (prefers-reduced-motion: reduce){.dsh-upd-entry-btn,.dsh-upd-entry-dot{transition:none}.dsh-upd-entry-btn[aria-busy="true"]::after{animation:none}}',
77
- ".dsh-upd-entry-btn:focus-visible,.dsh-upd-entry-dot:focus-visible{outline:2px solid var(--dsh-upd-focus,#2563eb);outline-offset:1px}",
78
- '.dsh-upd-entry[data-state="update"] .dsh-upd-entry-btn{border-color:var(--dsh-upd-ok-line,#059669);color:var(--dsh-upd-ok-line,#059669)}',
79
- '.dsh-upd-entry[data-state="restart"] .dsh-upd-entry-btn{border-color:var(--dsh-upd-warn-line,#d97706);color:var(--dsh-upd-warn-line,#d97706)}',
80
- '.dsh-upd-entry[data-state="failed"] .dsh-upd-entry-btn{border-color:var(--dsh-upd-bad-line,#dc2626);color:var(--dsh-upd-bad-line,#dc2626)}',
81
- ".dsh-upd-entry-dot{width:10px;height:10px;padding:0;border:0;border-radius:50%;background:var(--dsh-upd-line,#9ca3af);cursor:pointer}",
82
- '.dsh-upd-entry[data-state="update"] .dsh-upd-entry-dot{background:var(--dsh-upd-ok-line,#059669)}',
83
- '.dsh-upd-entry[data-state="busy"] .dsh-upd-entry-dot,.dsh-upd-entry[data-state="restart"] .dsh-upd-entry-dot{background:var(--dsh-upd-warn-line,#d97706)}',
84
- '.dsh-upd-entry[data-state="failed"] .dsh-upd-entry-dot{background:var(--dsh-upd-bad-line,#dc2626)}',
117
+ ".dsh-upd-entry-btn:focus-visible,.dsh-upd-entry-dot:focus-visible{outline:2px solid var(--dsh-update-focus,#2563eb);outline-offset:1px}",
118
+ '.dsh-upd-entry[data-state="update"] .dsh-upd-entry-btn{border-color:var(--dsh-update-ok-border,#059669);color:var(--dsh-update-ok-border,#059669)}',
119
+ '.dsh-upd-entry[data-state="restart"] .dsh-upd-entry-btn{border-color:var(--dsh-update-warn-border,#d97706);color:var(--dsh-update-warn-border,#d97706)}',
120
+ '.dsh-upd-entry[data-state="failed"] .dsh-upd-entry-btn{border-color:var(--dsh-update-bad-border,#dc2626);color:var(--dsh-update-bad-border,#dc2626)}',
121
+ ".dsh-upd-entry-dot{width:10px;height:10px;padding:0;border:0;border-radius:50%;background:var(--dsh-update-border,#9ca3af);cursor:pointer}",
122
+ '.dsh-upd-entry[data-state="update"] .dsh-upd-entry-dot{background:var(--dsh-update-ok-border,#059669)}',
123
+ '.dsh-upd-entry[data-state="busy"] .dsh-upd-entry-dot,.dsh-upd-entry[data-state="restart"] .dsh-upd-entry-dot{background:var(--dsh-update-warn-border,#d97706)}',
124
+ '.dsh-upd-entry[data-state="failed"] .dsh-upd-entry-dot{background:var(--dsh-update-bad-border,#dc2626)}',
85
125
  // 小字自带底(深色宿主 + 浅色变量时也读得出;浅底宿主上只是多一圈细线,不抢戏)。
86
- ".dsh-upd-entry-note{font-size:12.5px;opacity:.9;background:var(--dsh-upd-bg,#ffffff);border:1px solid var(--dsh-upd-line,#e5e7eb);border-radius:4px;padding:1px 8px}",
87
- '.dsh-upd-entry[data-theme="archive"] .dsh-upd-entry-note{background:var(--d5-card);border-color:var(--d5-line-strong);color:var(--d5-ink)}',
88
- '.dsh-upd-entry[data-theme="archive"]{--d5-ink:#1a1a1a;--d5-muted:#6f675a;--d5-line-strong:#c4b896;--d5-accent:#c8402a;--d5-card:#fffdf6;',
89
- 'font-family:Georgia,"Songti SC","STSong","SimSun",serif;color:var(--d5-ink)}',
126
+ ".dsh-upd-entry-note{font-size:12.5px;opacity:.9;background:var(--dsh-update-bg,#ffffff);border:1px solid var(--dsh-update-border,#e5e7eb);border-radius:var(--dsh-update-radius-badge,4px);padding:1px 8px}",
127
+ '.dsh-upd-entry[data-theme="archive"] .dsh-upd-entry-note{background:var(--dsh-update-bg);border-color:var(--dsh-update-border-strong);color:var(--dsh-update-text)}',
128
+ '.dsh-upd-entry[data-theme="archive"]{--dsh-update-text:#1a1a1a;--dsh-update-text-muted:#6f675a;--dsh-update-border-strong:#c4b896;--dsh-update-primary:#c8402a;--dsh-update-bg:#fffdf6;',
129
+ '--dsh-update-font-serif:Georgia,"Songti SC","STSong","SimSun",serif;',
130
+ 'font-family:var(--dsh-update-font-serif,Georgia,"Songti SC","STSong","SimSun",serif);color:var(--dsh-update-text)}',
90
131
  // 按钮脸自己不透明(深色宿主 + 浅色系统变量时也读得出;hover 红在深浅底上都可见)。
91
- '.dsh-upd-entry[data-theme="archive"] .dsh-upd-entry-btn{border-color:var(--d5-line-strong);background:var(--d5-card);color:var(--d5-ink);border-radius:3px}',
92
- '.dsh-upd-entry[data-theme="archive"] .dsh-upd-entry-btn:hover{border-color:var(--d5-accent);color:var(--d5-accent)}',
93
- '@media (prefers-color-scheme: dark){.dsh-upd-entry[data-theme="archive"]{--d5-ink:#ece5d3;--d5-muted:#a89c83;--d5-line-strong:#5c4e3b;--d5-accent:#e0684e;--d5-card:#1e1a15}}',
132
+ '.dsh-upd-entry[data-theme="archive"] .dsh-upd-entry-btn{border-color:var(--dsh-update-border-strong);background:var(--dsh-update-bg);color:var(--dsh-update-text);border-radius:var(--dsh-update-entry-border-radius,3px)}',
133
+ '.dsh-upd-entry[data-theme="archive"] .dsh-upd-entry-btn:hover{border-color:var(--dsh-update-primary);color:var(--dsh-update-primary)}',
134
+ '@media (prefers-color-scheme: dark){.dsh-upd-entry[data-theme="archive"]{--dsh-update-text:#ece5d3;--dsh-update-text-muted:#a89c83;--dsh-update-border-strong:#5c4e3b;--dsh-update-primary:#e0684e;--dsh-update-bg:#1e1a15}}',
94
135
  "@media (prefers-color-scheme: dark){.dsh-upd-entry{color:#e5e7eb}",
95
- ".dsh-upd-entry-btn{--dsh-upd-btn:#1f2937;--dsh-upd-line:#374151}}"
136
+ ".dsh-upd-entry-btn{--dsh-update-button-bg:#1f2937;--dsh-update-border:#374151}}"
96
137
  ].join("\n");
97
138
  const ENTRY_ATTR = "data-dsh-upd-entry";
98
139
  const ENTRY_SELECTOR = "[data-dsh-upd-entry]";
@@ -137,8 +178,8 @@ function mountUpdateEntry(container, options) {
137
178
  if (openOn !== "has-update" && openOn !== "always" && openOn !== "manual" && openOn !== "direct") {
138
179
  throw new Error(`[dsh-plugin-update] \u70B9\u51FB\u53BB\u5411\u975E\u6CD5\uFF1A\u53EA\u6536 has-update / always / manual / direct\uFF08\u6536\u5230 ${JSON.stringify(options.openOn)}\uFF09`);
139
180
  }
140
- if (options.theme !== void 0 && options.theme !== "default" && options.theme !== "archive" && options.theme !== "d5-paper") {
141
- throw new Error(`[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08d5-paper \u4E3A\u65E7\u522B\u540D\u4ECD\u53EF\u7528\uFF09\uFF08\u6536\u5230 ${JSON.stringify(options.theme)}\uFF09`);
181
+ if (options.theme !== void 0 && options.theme !== "default" && options.theme !== "archive") {
182
+ throw new Error(`[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08\u6536\u5230 ${JSON.stringify(options.theme)}\uFF09`);
142
183
  }
143
184
  let theme = normalizePanelTheme(options.theme ?? "default");
144
185
  const pollMs = options.pollMs;
@@ -146,6 +187,8 @@ function mountUpdateEntry(container, options) {
146
187
  throw new Error(`[dsh-plugin-update] \u9762\u677F\u8F6E\u8BE2\u95F4\u9694\u975E\u6CD5\uFF1A\u4E0D\u5F97\u5C0F\u4E8E 250 \u6BEB\u79D2\uFF08\u6536\u5230 ${JSON.stringify(options.pollMs)}\uFF09`);
147
188
  }
148
189
  const labelOverride = typeof options.label === "string" && options.label ? options.label : null;
190
+ const sizingStyle = entrySizingStyleFor(options.sizing ?? void 0);
191
+ const sizingAttr = sizingStyle ? ` style="${sizingStyle}"` : "";
149
192
  const localeOpt = options.locale ?? void 0;
150
193
  if (localeOpt !== void 0 && localeOpt !== null) {
151
194
  const isStr = typeof localeOpt === "string";
@@ -211,7 +254,7 @@ function mountUpdateEntry(container, options) {
211
254
  const noteHTML = noteVersion ? `<span class="dsh-upd-entry-note" data-dsh-upd-note="1">${copyHTML("entry.note.up-to-date", lang, { version: noteVersion })}</span>` : "";
212
255
  return `<style>${UPDATE_ENTRY_CSS}
213
256
  ${BILINGUAL_CSS}</style>
214
- <span class="dsh-upd-entry" data-variant="${variant}" data-state="${kind}"${themeAttr}>${control}${noteHTML}</span>`;
257
+ <span class="dsh-upd-entry" data-variant="${variant}" data-state="${kind}"${themeAttr}${sizingAttr}>${control}${noteHTML}</span>`;
215
258
  }
216
259
  function render() {
217
260
  if (!mounted) return;
@@ -316,8 +359,8 @@ ${BILINGUAL_CSS}</style>
316
359
  render();
317
360
  }
318
361
  function setTheme(next) {
319
- if (next !== "default" && next !== "archive" && next !== "d5-paper") {
320
- throw new Error(`[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08d5-paper \u4E3A\u65E7\u522B\u540D\u4ECD\u53EF\u7528\uFF09\uFF08\u6536\u5230 ${JSON.stringify(next)}\uFF09`);
362
+ if (next !== "default" && next !== "archive") {
363
+ throw new Error(`[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08\u6536\u5230 ${JSON.stringify(next)}\uFF09`);
321
364
  }
322
365
  theme = normalizePanelTheme(next);
323
366
  if (panel) void panel.setTheme(theme);
@@ -390,6 +433,7 @@ export {
390
433
  entryBilingualTextFor,
391
434
  entryBilingualValuesFor,
392
435
  entryLabelFor,
436
+ entrySizingStyleFor,
393
437
  entryStateKind,
394
438
  mountUpdateEntry
395
439
  };