dsh-plugin-update 0.4.0 → 0.5.1
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/CHANGELOG.md +18 -0
- package/README.md +11 -8
- package/dist/changelog-io.d.ts +5 -0
- package/dist/changelog.d.ts +66 -3
- package/dist/changelog.js +412 -35
- package/dist/entry.d.ts +8 -3
- package/dist/entry.js +26 -15
- package/dist/host.d.ts +2 -2
- package/dist/host.js +57 -7
- package/dist/panel-batch.js +46 -11
- package/dist/panel.d.ts +17 -3
- package/dist/panel.js +91 -18
- package/package.json +1 -1
package/dist/changelog.js
CHANGED
|
@@ -15,8 +15,8 @@ const CHANGELOG_ALL_CATEGORIES = [
|
|
|
15
15
|
"Removed",
|
|
16
16
|
"Security"
|
|
17
17
|
];
|
|
18
|
-
const CHANGELOG_MUST_SHOW = ["Added", "Fixed", "Changed"];
|
|
19
|
-
const CHANGELOG_FOLDED = ["Deprecated", "Removed"
|
|
18
|
+
const CHANGELOG_MUST_SHOW = ["Added", "Fixed", "Changed", "Security"];
|
|
19
|
+
const CHANGELOG_FOLDED = ["Deprecated", "Removed"];
|
|
20
20
|
const CHANGELOG_CATEGORY_ZH = {
|
|
21
21
|
Added: "\u65B0\u589E",
|
|
22
22
|
Fixed: "\u4FEE\u590D",
|
|
@@ -28,6 +28,9 @@ const CHANGELOG_CATEGORY_ZH = {
|
|
|
28
28
|
function emptySections() {
|
|
29
29
|
return { Added: [], Fixed: [], Changed: [], Deprecated: [], Removed: [], Security: [] };
|
|
30
30
|
}
|
|
31
|
+
function emptyCounts() {
|
|
32
|
+
return { Added: 0, Fixed: 0, Changed: 0, Deprecated: 0, Removed: 0, Security: 0 };
|
|
33
|
+
}
|
|
31
34
|
function isCategoryName(v) {
|
|
32
35
|
return CHANGELOG_ALL_CATEGORIES.includes(v);
|
|
33
36
|
}
|
|
@@ -60,6 +63,119 @@ function truncateBullet(text) {
|
|
|
60
63
|
if (t.length <= CHANGELOG_MAX_BULLET_CHARS) return t;
|
|
61
64
|
return `${t.slice(0, CHANGELOG_MAX_BULLET_CHARS - 1)}\u2026`;
|
|
62
65
|
}
|
|
66
|
+
const RE_VERSION_HEADING = /^##(?!#)\s*(.+?)\s*$/;
|
|
67
|
+
const RE_CATEGORY_HEADING = /^###\s*(.+?)\s*$/;
|
|
68
|
+
const RE_BULLET = /^\s*[-*+]\s+(.+?)\s*$/;
|
|
69
|
+
const RE_FENCE_TOGGLE = new RegExp("^\\s*(" + String.fromCharCode(96).repeat(3) + "|~~~)");
|
|
70
|
+
const RE_VERSION_NUM = /(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)/;
|
|
71
|
+
const RE_VERSION_DATE = /(\d{4}-\d{2}-\d{2})/;
|
|
72
|
+
const RE_YANKED = /\[YANKED\]/i;
|
|
73
|
+
const RE_UNRELEASED = /unreleased/i;
|
|
74
|
+
function matchVersionHeading(line) {
|
|
75
|
+
try {
|
|
76
|
+
const s = String(line !== null && line !== void 0 ? line : "");
|
|
77
|
+
const m = s.match(RE_VERSION_HEADING);
|
|
78
|
+
if (!m) return null;
|
|
79
|
+
return String(m[1] !== void 0 && m[1] !== null ? m[1] : "").trim();
|
|
80
|
+
} catch {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function matchCategoryHeading(line) {
|
|
85
|
+
try {
|
|
86
|
+
const s = String(line !== null && line !== void 0 ? line : "");
|
|
87
|
+
const m = s.match(RE_CATEGORY_HEADING);
|
|
88
|
+
if (!m) return null;
|
|
89
|
+
return String(m[1] !== void 0 && m[1] !== null ? m[1] : "").trim();
|
|
90
|
+
} catch {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function matchBulletBody(line) {
|
|
95
|
+
try {
|
|
96
|
+
const s = String(line !== null && line !== void 0 ? line : "");
|
|
97
|
+
const m = s.match(RE_BULLET);
|
|
98
|
+
if (!m) return null;
|
|
99
|
+
return String(m[1] !== void 0 && m[1] !== null ? m[1] : "");
|
|
100
|
+
} catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function isFenceToggle(line) {
|
|
105
|
+
try {
|
|
106
|
+
return RE_FENCE_TOGGLE.test(String(line !== null && line !== void 0 ? line : ""));
|
|
107
|
+
} catch {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const BREAKING_BADGE_TEXT = "\u4E0D\u517C\u5BB9";
|
|
112
|
+
function stripBreakingDecorations(s) {
|
|
113
|
+
try {
|
|
114
|
+
let t = String(s !== null && s !== void 0 ? s : "").trim();
|
|
115
|
+
let changed = true;
|
|
116
|
+
while (changed) {
|
|
117
|
+
changed = false;
|
|
118
|
+
if (t.charAt(0) === ">") {
|
|
119
|
+
t = t.slice(1).trim();
|
|
120
|
+
changed = true;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (t.slice(0, 2) === "**" || t.slice(0, 2) === "__") {
|
|
124
|
+
t = t.slice(2).trim();
|
|
125
|
+
changed = true;
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (t.charAt(0) === "*" || t.charAt(0) === "_") {
|
|
129
|
+
t = t.slice(1).trim();
|
|
130
|
+
changed = true;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return t;
|
|
135
|
+
} catch {
|
|
136
|
+
return "";
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function isBreakingChangelogItem(item) {
|
|
140
|
+
try {
|
|
141
|
+
if (typeof item !== "string") return false;
|
|
142
|
+
const t = stripBreakingDecorations(item);
|
|
143
|
+
if (!t) return false;
|
|
144
|
+
return /^(breaking|不兼容)\s*[::]/i.test(t);
|
|
145
|
+
} catch {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function splitBreakingPrefix(item) {
|
|
150
|
+
try {
|
|
151
|
+
const s = String(item !== null && item !== void 0 ? item : "");
|
|
152
|
+
const m = s.match(/^(\s*(?:>\s*|\*\*\s*|__\s*|\*\s*|_\s*)*)(breaking|不兼容)(\s*[::])/i);
|
|
153
|
+
if (!m) return null;
|
|
154
|
+
const head = String(m[1] !== void 0 && m[1] !== null ? m[1] : "");
|
|
155
|
+
const core = String(m[2] !== void 0 && m[2] !== null ? m[2] : "");
|
|
156
|
+
const colon = String(m[3] !== void 0 && m[3] !== null ? m[3] : "");
|
|
157
|
+
const prefix = core + colon;
|
|
158
|
+
const rest = s.slice(m[0].length);
|
|
159
|
+
return { head, prefix, rest };
|
|
160
|
+
} catch {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const CHANGELOG_POLL_BACKOFF_MS = 30 * 1e3;
|
|
165
|
+
function shouldFetchChangelog(opts) {
|
|
166
|
+
try {
|
|
167
|
+
const o = opts;
|
|
168
|
+
if (o.hasCache === true) return false;
|
|
169
|
+
if (o.isManual === true) return true;
|
|
170
|
+
const now = typeof o.now === "number" && Number.isFinite(o.now) ? o.now : Date.now();
|
|
171
|
+
const failedAt = typeof o.failedAt === "number" && Number.isFinite(o.failedAt) ? o.failedAt : null;
|
|
172
|
+
if (failedAt === null) return true;
|
|
173
|
+
const backoff = typeof o.backoffMs === "number" && Number.isFinite(o.backoffMs) && o.backoffMs > 0 ? Math.floor(o.backoffMs) : CHANGELOG_POLL_BACKOFF_MS;
|
|
174
|
+
return now - failedAt >= backoff;
|
|
175
|
+
} catch {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
63
179
|
function parseChangelog(markdown) {
|
|
64
180
|
try {
|
|
65
181
|
if (typeof markdown !== "string" || !markdown.trim()) return [];
|
|
@@ -86,32 +202,38 @@ function parseChangelog(markdown) {
|
|
|
86
202
|
};
|
|
87
203
|
for (const rawLine of lines) {
|
|
88
204
|
const line = String(rawLine ?? "");
|
|
89
|
-
if (
|
|
205
|
+
if (isFenceToggle(line)) {
|
|
90
206
|
inFence = !inFence;
|
|
91
207
|
continue;
|
|
92
208
|
}
|
|
93
209
|
if (inFence) continue;
|
|
94
|
-
const
|
|
95
|
-
if (
|
|
210
|
+
const versionTitle = matchVersionHeading(line);
|
|
211
|
+
if (versionTitle !== null) {
|
|
96
212
|
pushCurrent();
|
|
97
213
|
cur = null;
|
|
98
214
|
curCat = null;
|
|
99
|
-
const title =
|
|
215
|
+
const title = versionTitle;
|
|
100
216
|
const { version, date, yanked } = extractVersionDateAndYanked(title);
|
|
101
217
|
if (!version) continue;
|
|
102
|
-
cur = { version, date, yanked, sections: emptySections() };
|
|
218
|
+
cur = { version, date, yanked, sections: emptySections(), counts: emptyCounts() };
|
|
103
219
|
continue;
|
|
104
220
|
}
|
|
105
|
-
const
|
|
106
|
-
if (
|
|
107
|
-
const cat = normalizeCategory(
|
|
221
|
+
const catTitle = matchCategoryHeading(line);
|
|
222
|
+
if (catTitle !== null) {
|
|
223
|
+
const cat = normalizeCategory(catTitle);
|
|
108
224
|
curCat = cur && cat && isCategoryName(cat) ? cat : null;
|
|
109
225
|
continue;
|
|
110
226
|
}
|
|
111
|
-
const
|
|
112
|
-
if (
|
|
113
|
-
const item = truncateBullet(
|
|
114
|
-
if (item)
|
|
227
|
+
const bulletBody = matchBulletBody(line);
|
|
228
|
+
if (bulletBody !== null && cur && curCat) {
|
|
229
|
+
const item = truncateBullet(bulletBody);
|
|
230
|
+
if (item) {
|
|
231
|
+
cur.sections[curCat].push(item);
|
|
232
|
+
try {
|
|
233
|
+
if (cur.counts) cur.counts[curCat] += 1;
|
|
234
|
+
} catch {
|
|
235
|
+
}
|
|
236
|
+
}
|
|
115
237
|
continue;
|
|
116
238
|
}
|
|
117
239
|
const trimmed = line.trim();
|
|
@@ -189,46 +311,119 @@ function changelogForUpdate(entries, runningVersion, latestVersion, installedVer
|
|
|
189
311
|
function escapeChangelogHtml(text) {
|
|
190
312
|
return String(text ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
191
313
|
}
|
|
314
|
+
function countsOf(entry) {
|
|
315
|
+
try {
|
|
316
|
+
const out = { Added: 0, Fixed: 0, Changed: 0, Deprecated: 0, Removed: 0, Security: 0 };
|
|
317
|
+
if (!entry || typeof entry !== "object") return out;
|
|
318
|
+
for (const c of CHANGELOG_ALL_CATEGORIES) {
|
|
319
|
+
const n = entry.counts;
|
|
320
|
+
const v = n && typeof n[c] === "number" && Number.isFinite(n[c]) ? Math.floor(n[c]) : null;
|
|
321
|
+
if (v !== null && v >= 0) {
|
|
322
|
+
out[c] = v;
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
const list = entry.sections;
|
|
326
|
+
const arr = list ? list[c] : null;
|
|
327
|
+
out[c] = Array.isArray(arr) ? arr.length : 0;
|
|
328
|
+
}
|
|
329
|
+
return out;
|
|
330
|
+
} catch {
|
|
331
|
+
return { Added: 0, Fixed: 0, Changed: 0, Deprecated: 0, Removed: 0, Security: 0 };
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
function truncatedNoteHTML(total, shown) {
|
|
335
|
+
try {
|
|
336
|
+
const m = Math.floor(total);
|
|
337
|
+
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>";
|
|
339
|
+
} catch {
|
|
340
|
+
return "";
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
function yankedBannerHTML(version) {
|
|
344
|
+
try {
|
|
345
|
+
const v = typeof version === "string" ? version.trim() : "";
|
|
346
|
+
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>";
|
|
348
|
+
} catch {
|
|
349
|
+
return "";
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
function renderChangelogItem(item) {
|
|
353
|
+
try {
|
|
354
|
+
const s = String(item !== null && item !== void 0 ? item : "");
|
|
355
|
+
if (!s) return "";
|
|
356
|
+
const split = splitBreakingPrefix(s);
|
|
357
|
+
if (!split) return "<li>" + escapeChangelogHtml(s) + "</li>";
|
|
358
|
+
const head = escapeChangelogHtml(split.head);
|
|
359
|
+
const prefix = escapeChangelogHtml(split.prefix);
|
|
360
|
+
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> ";
|
|
362
|
+
return "<li>" + head + badge + "<strong>" + prefix + "</strong>" + rest + "</li>";
|
|
363
|
+
} catch {
|
|
364
|
+
return "";
|
|
365
|
+
}
|
|
366
|
+
}
|
|
192
367
|
function renderChangelogSection(entry) {
|
|
193
368
|
try {
|
|
194
369
|
if (!entry || typeof entry !== "object") return "";
|
|
195
|
-
const version = String(entry.version
|
|
370
|
+
const version = String(entry.version !== void 0 && entry.version !== null ? String(entry.version) : "").trim();
|
|
196
371
|
if (!version || isUnreleasedVersion(version)) return "";
|
|
197
372
|
if (!hasVisibleSections(entry)) return "";
|
|
198
|
-
const
|
|
199
|
-
const
|
|
200
|
-
const
|
|
373
|
+
const dateRaw = entry.date;
|
|
374
|
+
const date = typeof dateRaw === "string" ? dateRaw : "";
|
|
375
|
+
const yankedFlag = entry.yanked === true;
|
|
376
|
+
const yankedSuffix = yankedFlag ? " \xB7 \u5DF2\u64A4\u56DE" : "";
|
|
377
|
+
const title = (date ? version + " \xB7 " + date : version) + yankedSuffix;
|
|
378
|
+
const counts = countsOf(entry);
|
|
201
379
|
const parts = [];
|
|
202
|
-
parts.push(
|
|
203
|
-
parts.push(
|
|
380
|
+
parts.push('<div class="dsh-upd-changelog-version" data-version="' + escapeChangelogHtml(version) + '">');
|
|
381
|
+
parts.push('<div class="dsh-upd-changelog-title">' + escapeChangelogHtml(title) + "</div>");
|
|
204
382
|
for (const cat of CHANGELOG_MUST_SHOW) {
|
|
205
|
-
const items = Array.isArray(entry.sections
|
|
206
|
-
if (items.length === 0) continue;
|
|
207
|
-
const label =
|
|
208
|
-
parts.push(
|
|
209
|
-
parts.push(
|
|
383
|
+
const items = Array.isArray(entry.sections ? entry.sections[cat] : null) ? entry.sections[cat] : [];
|
|
384
|
+
if (!items || items.length === 0) continue;
|
|
385
|
+
const label = cat + " \xB7 " + CHANGELOG_CATEGORY_ZH[cat];
|
|
386
|
+
parts.push('<div class="dsh-upd-changelog-cat" data-cat="' + cat + '">');
|
|
387
|
+
parts.push('<div class="dsh-upd-changelog-catname">' + escapeChangelogHtml(label) + "</div>");
|
|
388
|
+
const total = counts[cat];
|
|
389
|
+
const shown = items.length;
|
|
390
|
+
if (total > shown) {
|
|
391
|
+
parts.push(truncatedNoteHTML(total, shown));
|
|
392
|
+
}
|
|
210
393
|
parts.push("<ul>");
|
|
211
394
|
for (const item of items) {
|
|
212
395
|
if (!item) continue;
|
|
213
|
-
|
|
396
|
+
const li = renderChangelogItem(item);
|
|
397
|
+
if (li) parts.push(li);
|
|
398
|
+
}
|
|
399
|
+
parts.push("</ul>");
|
|
400
|
+
if (cat === "Security" && total > shown) {
|
|
401
|
+
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>');
|
|
214
403
|
}
|
|
215
|
-
parts.push("</
|
|
404
|
+
parts.push("</div>");
|
|
216
405
|
}
|
|
217
406
|
for (const cat of CHANGELOG_FOLDED) {
|
|
218
|
-
const items = Array.isArray(entry.sections
|
|
219
|
-
if (items.length === 0) continue;
|
|
220
|
-
const label =
|
|
221
|
-
parts.push(
|
|
222
|
-
parts.push(
|
|
407
|
+
const items = Array.isArray(entry.sections ? entry.sections[cat] : null) ? entry.sections[cat] : [];
|
|
408
|
+
if (!items || items.length === 0) continue;
|
|
409
|
+
const label = cat + " \xB7 " + CHANGELOG_CATEGORY_ZH[cat] + "\uFF08" + String(items.length) + "\uFF09";
|
|
410
|
+
parts.push('<details class="dsh-upd-changelog-fold" data-cat="' + cat + '">');
|
|
411
|
+
parts.push("<summary>" + escapeChangelogHtml(label) + "</summary>");
|
|
412
|
+
const total = counts[cat];
|
|
413
|
+
const shown = items.length;
|
|
414
|
+
if (total > shown) {
|
|
415
|
+
parts.push(truncatedNoteHTML(total, shown));
|
|
416
|
+
}
|
|
223
417
|
parts.push("<ul>");
|
|
224
418
|
for (const item of items) {
|
|
225
419
|
if (!item) continue;
|
|
226
|
-
|
|
420
|
+
const li = renderChangelogItem(item);
|
|
421
|
+
if (li) parts.push(li);
|
|
227
422
|
}
|
|
228
423
|
parts.push("</ul></details>");
|
|
229
424
|
}
|
|
230
425
|
parts.push("</div>");
|
|
231
|
-
return parts.join(
|
|
426
|
+
return parts.join(String.fromCharCode(10));
|
|
232
427
|
} catch {
|
|
233
428
|
return "";
|
|
234
429
|
}
|
|
@@ -264,7 +459,165 @@ ${blocks.join("\n")}
|
|
|
264
459
|
return renderChangelogNeutral();
|
|
265
460
|
}
|
|
266
461
|
}
|
|
462
|
+
const CHANGELOG_VALIDATE_HINTS = {
|
|
463
|
+
E_VERSION_TITLE: "\u8BE5\u6807\u9898\u4E0D\u662F\u5408\u6CD5\u7248\u672C\u53F7\uFF0C\u5176\u4E0B\u6761\u76EE\u5DF2\u88AB\u5FFD\u7565\uFF0C\u8BF7\u6539\u6210 ## [x.y.z] \u5F62\u6001",
|
|
464
|
+
E_CATEGORY: "\u672A\u77E5\u5206\u7C7B\uFF0C\u5176\u4E0B\u6761\u76EE\u5DF2\u88AB\u5FFD\u7565\uFF0C\u4EC5\u6536 Added/Fixed/Changed/Deprecated/Removed/Security",
|
|
465
|
+
E_BULLET_ORPHAN: "\u8BE5\u6761\u76EE\u4E0D\u5728\u7248\u672C\u8282\u4E0E\u5206\u7C7B\u4E0B\uFF0C\u5DF2\u88AB\u5FFD\u7565",
|
|
466
|
+
W_BREAKING_MAYBE: "\u7591\u4F3C\u7834\u574F\u6807\u8BB0\u8BEF\u5199\uFF08\u7F3A\u5192\u53F7/\u62FC\u5199\u63A5\u8FD1/\u4F4D\u7F6E\u7591\u4F3C\u653E\u9519\uFF09\uFF0C\u8BF7\u68C0\u67E5\u662F\u5426\u60F3\u5199 BREAKING:/\u4E0D\u517C\u5BB9:",
|
|
467
|
+
W_YANKED: "\u8BE5\u7248\u672C\u5DF2\u88AB\u6807\u8BB0\u64A4\u56DE\uFF08yanked\uFF09\uFF0C\u5B89\u88C5\u4E0D\u53D7\u5F71\u54CD\uFF0C\u7EE7\u7EED\u524D\u8BF7\u786E\u8BA4",
|
|
468
|
+
W_TRUNCATED: "\u8BE5\u7C7B\u5171 M \u6761\uFF0C\u4EC5\u663E\u793A\u524D N \u6761",
|
|
469
|
+
W_TRUNCATED_FILE: "\u6587\u4EF6\u8D85 64K\uFF0C\u4EC5\u6821\u9A8C\u524D 64K",
|
|
470
|
+
W_EMPTY: "\u672A\u89E3\u6790\u5230\u4EFB\u4F55\u7248\u672C\u8282\uFF0C\u9762\u677F\u5C06\u663E\u793A\u4E2D\u6027\u63D0\u793A"
|
|
471
|
+
};
|
|
472
|
+
function isMaybeBreakingMisuse(bulletBody) {
|
|
473
|
+
try {
|
|
474
|
+
if (typeof bulletBody !== "string") return false;
|
|
475
|
+
const t = stripBreakingDecorations(bulletBody);
|
|
476
|
+
if (!t) return false;
|
|
477
|
+
if (isBreakingChangelogItem(bulletBody)) return false;
|
|
478
|
+
if (/^breaking\s*$/i.test(t)) return true;
|
|
479
|
+
if (/^breaking\s+[^::]/i.test(t)) return true;
|
|
480
|
+
if (/^breaking[^::\s\w]/i.test(t)) return true;
|
|
481
|
+
if (/^不兼容\s*$/i.test(t)) return true;
|
|
482
|
+
if (/^不兼容\s*[^::]/i.test(t)) return true;
|
|
483
|
+
if (/^(braking|breking|breakign|brekaing|braeking|breakingg)\b/i.test(t)) return true;
|
|
484
|
+
if (/^break[^i::\s]/i.test(t)) return true;
|
|
485
|
+
return false;
|
|
486
|
+
} catch {
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
function validateChangelog(markdown) {
|
|
491
|
+
try {
|
|
492
|
+
if (typeof markdown !== "string" || !markdown.trim()) {
|
|
493
|
+
return { ok: true, diagnostics: [{ line: 1, code: "W_EMPTY", hint: CHANGELOG_VALIDATE_HINTS.W_EMPTY }] };
|
|
494
|
+
}
|
|
495
|
+
let raw = String(markdown).replace(/\r\n/g, String.fromCharCode(10));
|
|
496
|
+
let fileTruncated = false;
|
|
497
|
+
if (raw.length > CHANGELOG_MAX_CHARS) {
|
|
498
|
+
fileTruncated = true;
|
|
499
|
+
raw = raw.slice(0, CHANGELOG_MAX_CHARS);
|
|
500
|
+
}
|
|
501
|
+
const lines = raw.split(String.fromCharCode(10));
|
|
502
|
+
const diags = [];
|
|
503
|
+
let inFence = false;
|
|
504
|
+
let curValid = false;
|
|
505
|
+
let curCat = null;
|
|
506
|
+
let catLineByCat = {};
|
|
507
|
+
let countByCat = {};
|
|
508
|
+
let hasVisibleVersion = false;
|
|
509
|
+
const flushCounts = function() {
|
|
510
|
+
try {
|
|
511
|
+
for (const k of Object.keys(countByCat)) {
|
|
512
|
+
const n = countByCat[k];
|
|
513
|
+
if (n > CHANGELOG_MAX_BULLETS_PER_SECTION) {
|
|
514
|
+
const lineNo = catLineByCat[k] ? catLineByCat[k] : lines.length;
|
|
515
|
+
const hint = "\u5206\u7C7B " + k + " \u5171 " + String(n) + " \u6761\uFF0C\u4EC5\u663E\u793A\u524D " + String(CHANGELOG_MAX_BULLETS_PER_SECTION) + " \u6761";
|
|
516
|
+
diags.push({ line: lineNo, code: "W_TRUNCATED", hint });
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
} catch {
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
for (let i = 0; i < lines.length; i++) {
|
|
523
|
+
const lineNo = i + 1;
|
|
524
|
+
const line = String(lines[i] !== void 0 && lines[i] !== null ? lines[i] : "");
|
|
525
|
+
if (isFenceToggle(line)) {
|
|
526
|
+
inFence = !inFence;
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
if (inFence) continue;
|
|
530
|
+
const vTitle = matchVersionHeading(line);
|
|
531
|
+
if (vTitle !== null) {
|
|
532
|
+
flushCounts();
|
|
533
|
+
catLineByCat = {};
|
|
534
|
+
countByCat = {};
|
|
535
|
+
curValid = false;
|
|
536
|
+
curCat = null;
|
|
537
|
+
const info = extractVersionDateAndYanked(vTitle);
|
|
538
|
+
if (!info.version) {
|
|
539
|
+
diags.push({ line: lineNo, code: "E_VERSION_TITLE", hint: CHANGELOG_VALIDATE_HINTS.E_VERSION_TITLE });
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
542
|
+
if (isUnreleasedVersion(info.version)) {
|
|
543
|
+
curValid = false;
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
curValid = true;
|
|
547
|
+
hasVisibleVersion = true;
|
|
548
|
+
if (info.yanked) {
|
|
549
|
+
diags.push({ line: lineNo, code: "W_YANKED", hint: CHANGELOG_VALIDATE_HINTS.W_YANKED });
|
|
550
|
+
}
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
const cTitle = matchCategoryHeading(line);
|
|
554
|
+
if (cTitle !== null) {
|
|
555
|
+
const cat = normalizeCategory(cTitle);
|
|
556
|
+
if (!cat) {
|
|
557
|
+
curCat = null;
|
|
558
|
+
diags.push({ line: lineNo, code: "E_CATEGORY", hint: CHANGELOG_VALIDATE_HINTS.E_CATEGORY });
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
if (!curValid) {
|
|
562
|
+
curCat = null;
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
565
|
+
curCat = cat;
|
|
566
|
+
catLineByCat[cat] = lineNo;
|
|
567
|
+
if (countByCat[cat] === void 0) countByCat[cat] = 0;
|
|
568
|
+
continue;
|
|
569
|
+
}
|
|
570
|
+
const body = matchBulletBody(line);
|
|
571
|
+
if (body !== null) {
|
|
572
|
+
if (!curValid || !curCat) {
|
|
573
|
+
diags.push({ line: lineNo, code: "E_BULLET_ORPHAN", hint: CHANGELOG_VALIDATE_HINTS.E_BULLET_ORPHAN });
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
countByCat[curCat] = (countByCat[curCat] ? countByCat[curCat] : 0) + 1;
|
|
577
|
+
if (isMaybeBreakingMisuse(body)) {
|
|
578
|
+
diags.push({ line: lineNo, code: "W_BREAKING_MAYBE", hint: CHANGELOG_VALIDATE_HINTS.W_BREAKING_MAYBE });
|
|
579
|
+
}
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
flushCounts();
|
|
584
|
+
if (fileTruncated) {
|
|
585
|
+
diags.push({ line: lines.length, code: "W_TRUNCATED_FILE", hint: CHANGELOG_VALIDATE_HINTS.W_TRUNCATED_FILE });
|
|
586
|
+
}
|
|
587
|
+
if (!hasVisibleVersion) {
|
|
588
|
+
let anyVisible = false;
|
|
589
|
+
try {
|
|
590
|
+
const parsed = parseChangelog(markdown);
|
|
591
|
+
for (const e of parsed) {
|
|
592
|
+
if (e && !isUnreleasedVersion(e.version) && hasVisibleSections(e)) {
|
|
593
|
+
anyVisible = true;
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
} catch {
|
|
598
|
+
anyVisible = false;
|
|
599
|
+
}
|
|
600
|
+
if (!anyVisible) {
|
|
601
|
+
diags.push({ line: lines.length, code: "W_EMPTY", hint: CHANGELOG_VALIDATE_HINTS.W_EMPTY });
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
diags.sort(function(a, b) {
|
|
605
|
+
return a.line - b.line;
|
|
606
|
+
});
|
|
607
|
+
let ok = true;
|
|
608
|
+
for (const d of diags) {
|
|
609
|
+
if (d.code.charAt(0) === "E") {
|
|
610
|
+
ok = false;
|
|
611
|
+
break;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
return { ok, diagnostics: diags };
|
|
615
|
+
} catch {
|
|
616
|
+
return { ok: false, diagnostics: [] };
|
|
617
|
+
}
|
|
618
|
+
}
|
|
267
619
|
export {
|
|
620
|
+
BREAKING_BADGE_TEXT,
|
|
268
621
|
CHANGELOG_ALL_CATEGORIES,
|
|
269
622
|
CHANGELOG_CATEGORY_ZH,
|
|
270
623
|
CHANGELOG_FILENAME,
|
|
@@ -276,12 +629,36 @@ export {
|
|
|
276
629
|
CHANGELOG_MUST_SHOW,
|
|
277
630
|
CHANGELOG_NEUTRAL_HINT,
|
|
278
631
|
CHANGELOG_NEUTRAL_LINE,
|
|
632
|
+
CHANGELOG_POLL_BACKOFF_MS,
|
|
633
|
+
CHANGELOG_VALIDATE_HINTS,
|
|
634
|
+
RE_BULLET,
|
|
635
|
+
RE_CATEGORY_HEADING,
|
|
636
|
+
RE_FENCE_TOGGLE,
|
|
637
|
+
RE_UNRELEASED,
|
|
638
|
+
RE_VERSION_DATE,
|
|
639
|
+
RE_VERSION_HEADING,
|
|
640
|
+
RE_VERSION_NUM,
|
|
641
|
+
RE_YANKED,
|
|
279
642
|
changelogForUpdate,
|
|
643
|
+
countsOf,
|
|
280
644
|
hasVisibleSections,
|
|
645
|
+
isBreakingChangelogItem,
|
|
646
|
+
isFenceToggle,
|
|
647
|
+
isMaybeBreakingMisuse,
|
|
281
648
|
isUnreleasedVersion,
|
|
649
|
+
matchBulletBody,
|
|
650
|
+
matchCategoryHeading,
|
|
651
|
+
matchVersionHeading,
|
|
282
652
|
parseChangelog,
|
|
283
653
|
renderChangelogHTML,
|
|
654
|
+
renderChangelogItem,
|
|
284
655
|
renderChangelogNeutral,
|
|
285
656
|
renderChangelogSection,
|
|
286
|
-
selectChangelogEntries
|
|
657
|
+
selectChangelogEntries,
|
|
658
|
+
shouldFetchChangelog,
|
|
659
|
+
splitBreakingPrefix,
|
|
660
|
+
stripBreakingDecorations,
|
|
661
|
+
truncatedNoteHTML,
|
|
662
|
+
validateChangelog,
|
|
663
|
+
yankedBannerHTML
|
|
287
664
|
};
|
package/dist/entry.d.ts
CHANGED
|
@@ -5,7 +5,11 @@ export type EntryVariant = 'button' | 'badge' | 'inline';
|
|
|
5
5
|
/** 什么时候主动查一次(只读,联网一次)。 */
|
|
6
6
|
export type EntryAutoCheck = 'mount' | 'never';
|
|
7
7
|
/** 用户点下去之后做什么。 */
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* 点下去之后做什么:`has-update` 有新版才开面板(无事只给一句小字);`always` 检查完总是开;
|
|
10
|
+
* `manual` 交给 onActivate;`direct` 点开即弹窗、不预查(面板挂载即自查;badge 仍走回调口径)。
|
|
11
|
+
*/
|
|
12
|
+
export type EntryOpenOn = 'has-update' | 'always' | 'manual' | 'direct';
|
|
9
13
|
/** 入口件主题(与面板同一套取值,切换即换肤)。 */
|
|
10
14
|
export type EntryTheme = UpdatePanelTheme;
|
|
11
15
|
/** 入口件的状态档:只用来算文案与 data-state,不另立状态机。 */
|
|
@@ -22,7 +26,8 @@ export interface UpdateEntryOptions {
|
|
|
22
26
|
/** 调宿主电话:(phoneName, args) => Promise<reply>。 */
|
|
23
27
|
call: (name: string, args: Record<string, unknown>) => Promise<unknown>;
|
|
24
28
|
variant?: EntryVariant;
|
|
25
|
-
|
|
29
|
+
/** 主题:`default` 最小可用深色,`archive` 档案卷纸面浅色(`d5-paper` 为旧别名仍可用)。 */
|
|
30
|
+
theme?: UpdatePanelTheme;
|
|
26
31
|
/** 缺省 'mount':进页面静默查一次(只读)。'never' 则只在用户点击时查。 */
|
|
27
32
|
autoCheck?: EntryAutoCheck;
|
|
28
33
|
/** 缺省 'has-update':有新版才开面板,没有就只在原地给一句提示。 */
|
|
@@ -52,7 +57,7 @@ export interface UpdateEntryController {
|
|
|
52
57
|
close(): void;
|
|
53
58
|
/** 当前按钮上的状态文案(接入方做自定义排版时读它)。 */
|
|
54
59
|
label(): string;
|
|
55
|
-
setTheme(theme:
|
|
60
|
+
setTheme(theme: UpdatePanelTheme): void;
|
|
56
61
|
unmount(): void;
|
|
57
62
|
}
|
|
58
63
|
/**
|
package/dist/entry.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import { DEFAULT_PREFIX, MIN_PANEL_POLL_MS, buildPhoneNames } from "./config.js";
|
|
3
3
|
import {
|
|
4
4
|
failureCodeOf,
|
|
5
|
-
mountUpdatePanel
|
|
5
|
+
mountUpdatePanel,
|
|
6
|
+
normalizePanelTheme
|
|
6
7
|
} from "./panel.js";
|
|
7
8
|
const LABEL_IDLE = "\u68C0\u67E5\u66F4\u65B0";
|
|
8
9
|
const LABEL_FAILED = "\u66F4\u65B0\u5931\u8D25\uFF0C\u70B9\u6B64\u67E5\u770B";
|
|
@@ -63,10 +64,15 @@ const UPDATE_ENTRY_CSS = [
|
|
|
63
64
|
'.dsh-upd-entry[data-state="update"] .dsh-upd-entry-dot{background:var(--dsh-upd-ok-line,#059669)}',
|
|
64
65
|
'.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)}',
|
|
65
66
|
'.dsh-upd-entry[data-state="failed"] .dsh-upd-entry-dot{background:var(--dsh-upd-bad-line,#dc2626)}',
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
'.dsh-upd-entry[data-theme="d5-paper"] .dsh-upd-entry-
|
|
69
|
-
'.dsh-upd-entry[data-theme="d5-paper"]
|
|
67
|
+
// 小字自带底(深色宿主 + 浅色变量时也读得出;浅底宿主上只是多一圈细线,不抢戏)。
|
|
68
|
+
".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}",
|
|
69
|
+
'.dsh-upd-entry[data-theme="d5-paper"] .dsh-upd-entry-note{background:var(--d5-card);border-color:var(--d5-line-strong);color:var(--d5-ink)}',
|
|
70
|
+
'.dsh-upd-entry[data-theme="d5-paper"]{--d5-ink:#1a1a1a;--d5-muted:#6f675a;--d5-line-strong:#c4b896;--d5-accent:#c8402a;--d5-card:#fffdf6;',
|
|
71
|
+
'font-family:Georgia,"Songti SC","STSong","SimSun",serif;color:var(--d5-ink)}',
|
|
72
|
+
// 按钮脸自己不透明(深色宿主 + 浅色系统变量时也读得出;hover 红在深浅底上都可见)。
|
|
73
|
+
'.dsh-upd-entry[data-theme="d5-paper"] .dsh-upd-entry-btn{border-color:var(--d5-line-strong);background:var(--d5-card);color:var(--d5-ink);border-radius:3px}',
|
|
74
|
+
'.dsh-upd-entry[data-theme="d5-paper"] .dsh-upd-entry-btn:hover{border-color:var(--d5-accent);color:var(--d5-accent)}',
|
|
75
|
+
'@media (prefers-color-scheme: dark){.dsh-upd-entry[data-theme="d5-paper"]{--d5-ink:#ece5d3;--d5-muted:#a89c83;--d5-line-strong:#5c4e3b;--d5-accent:#e0684e;--d5-card:#1e1a15}}',
|
|
70
76
|
"@media (prefers-color-scheme: dark){.dsh-upd-entry{color:#e5e7eb}",
|
|
71
77
|
".dsh-upd-entry-btn{--dsh-upd-btn:#1f2937;--dsh-upd-line:#374151}}"
|
|
72
78
|
].join("\n");
|
|
@@ -110,13 +116,13 @@ function mountUpdateEntry(container, options) {
|
|
|
110
116
|
throw new Error(`[dsh-plugin-update] \u81EA\u52A8\u68C0\u67E5\u65F6\u673A\u975E\u6CD5\uFF1A\u53EA\u6536 mount \u6216 never\uFF08\u6536\u5230 ${JSON.stringify(options.autoCheck)}\uFF09`);
|
|
111
117
|
}
|
|
112
118
|
const openOn = options.openOn ?? "has-update";
|
|
113
|
-
if (openOn !== "has-update" && openOn !== "always" && openOn !== "manual") {
|
|
114
|
-
throw new Error(`[dsh-plugin-update] \u70B9\u51FB\u53BB\u5411\u975E\u6CD5\uFF1A\u53EA\u6536 has-update / always / manual\uFF08\u6536\u5230 ${JSON.stringify(options.openOn)}\uFF09`);
|
|
119
|
+
if (openOn !== "has-update" && openOn !== "always" && openOn !== "manual" && openOn !== "direct") {
|
|
120
|
+
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`);
|
|
115
121
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
throw new Error(`[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 d5-paper\uFF08\u6536\u5230 ${JSON.stringify(options.theme)}\uFF09`);
|
|
122
|
+
if (options.theme !== void 0 && options.theme !== "default" && options.theme !== "archive" && options.theme !== "d5-paper") {
|
|
123
|
+
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`);
|
|
119
124
|
}
|
|
125
|
+
let theme = normalizePanelTheme(options.theme ?? "default");
|
|
120
126
|
const pollMs = options.pollMs;
|
|
121
127
|
if (pollMs !== void 0 && (typeof pollMs !== "number" || !Number.isFinite(pollMs) || pollMs < MIN_PANEL_POLL_MS)) {
|
|
122
128
|
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`);
|
|
@@ -219,6 +225,8 @@ function mountUpdateEntry(container, options) {
|
|
|
219
225
|
profileName,
|
|
220
226
|
autoChangelog: options.autoChangelog,
|
|
221
227
|
changelogMarkdown: options.changelogMarkdown ?? null,
|
|
228
|
+
// 面板点「关闭」即走入口件的完整关闭(收 dialog + 还原按钮 + 重查一次),不再是面板自己停轮询。
|
|
229
|
+
onCloseRequested: () => close(),
|
|
222
230
|
call: panelCall
|
|
223
231
|
});
|
|
224
232
|
panelMode = mode;
|
|
@@ -245,6 +253,10 @@ function mountUpdateEntry(container, options) {
|
|
|
245
253
|
}
|
|
246
254
|
async function activate() {
|
|
247
255
|
if (!mounted || panelMode !== null || activating) return;
|
|
256
|
+
if (openOn === "direct" && variant === "button") {
|
|
257
|
+
openDialog();
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
248
260
|
activating = true;
|
|
249
261
|
note = null;
|
|
250
262
|
render();
|
|
@@ -268,11 +280,11 @@ function mountUpdateEntry(container, options) {
|
|
|
268
280
|
render();
|
|
269
281
|
}
|
|
270
282
|
function setTheme(next) {
|
|
271
|
-
if (next !== "default" && next !== "d5-paper") {
|
|
272
|
-
throw new Error(`[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216
|
|
283
|
+
if (next !== "default" && next !== "archive" && next !== "d5-paper") {
|
|
284
|
+
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`);
|
|
273
285
|
}
|
|
274
|
-
theme = next;
|
|
275
|
-
if (panel) void panel.setTheme(
|
|
286
|
+
theme = normalizePanelTheme(next);
|
|
287
|
+
if (panel) void panel.setTheme(theme);
|
|
276
288
|
else render();
|
|
277
289
|
}
|
|
278
290
|
function onClick(ev) {
|
|
@@ -285,7 +297,6 @@ function mountUpdateEntry(container, options) {
|
|
|
285
297
|
void activate();
|
|
286
298
|
return;
|
|
287
299
|
}
|
|
288
|
-
if (panelMode === "dialog" && closest('[data-action="close-view"]')) close();
|
|
289
300
|
} catch {
|
|
290
301
|
}
|
|
291
302
|
}
|
package/dist/host.d.ts
CHANGED
|
@@ -10,8 +10,8 @@ export { COPY_BUDGET_CHARS, DETAIL_MAX_CHARS, DIAG_DROP_ORDER, DIAG_INLINE_BUDGE
|
|
|
10
10
|
export type { DiagDropKey, RedactionRuleName } from './redaction.js';
|
|
11
11
|
export { DIAG_ACTIONS, DIAG_KEYS, DIAG_KNOWN_TYPES, DIAG_STAGE_EXPECT, DIAG_STAGES, DIAG_VERSION, buildDiag, deriveAction, deriveRouteMethod, deriveStage, enforceBudget as enforceDiagBudgetForPhone, } from './diag.js';
|
|
12
12
|
export type { DiagAction, DiagInput, DiagObject, DiagStage } from './diag.js';
|
|
13
|
-
export { CHANGELOG_ALL_CATEGORIES, CHANGELOG_FILENAME, CHANGELOG_FOLDED, CHANGELOG_MAX_BULLETS_PER_SECTION, CHANGELOG_MAX_BULLET_CHARS, CHANGELOG_MAX_CHARS, CHANGELOG_MAX_ENTRIES, CHANGELOG_MUST_SHOW, CHANGELOG_NEUTRAL_HINT, CHANGELOG_NEUTRAL_LINE, changelogForUpdate, hasVisibleSections, isUnreleasedVersion, parseChangelog, renderChangelogHTML, renderChangelogNeutral, renderChangelogSection, selectChangelogEntries, } from './changelog.js';
|
|
14
|
-
export type { ChangelogCategory, ChangelogEntry } from './changelog.js';
|
|
13
|
+
export { CHANGELOG_ALL_CATEGORIES, CHANGELOG_FILENAME, CHANGELOG_FOLDED, CHANGELOG_MAX_BULLETS_PER_SECTION, CHANGELOG_MAX_BULLET_CHARS, CHANGELOG_MAX_CHARS, CHANGELOG_MAX_ENTRIES, CHANGELOG_MUST_SHOW, CHANGELOG_NEUTRAL_HINT, CHANGELOG_NEUTRAL_LINE, BREAKING_BADGE_TEXT, CHANGELOG_POLL_BACKOFF_MS, changelogForUpdate, countsOf, hasVisibleSections, isBreakingChangelogItem, isUnreleasedVersion, parseChangelog, renderChangelogHTML, renderChangelogItem, renderChangelogNeutral, renderChangelogSection, selectChangelogEntries, shouldFetchChangelog, splitBreakingPrefix, truncatedNoteHTML, validateChangelog, yankedBannerHTML, } from './changelog.js';
|
|
14
|
+
export type { ChangelogCategory, ChangelogDiagnostic, ChangelogEntry, ChangelogValidation } from './changelog.js';
|
|
15
15
|
export { CHANGELOG_DEFAULT_REGISTRY, CHANGELOG_FETCH_MAX_BYTES, CHANGELOG_TAR_MAX_BYTES, CHANGELOG_TARBALL_MAX_BYTES, extractChangelogFromTar, fetchReleaseChangelogText, readInstalledChangelogText, } from './changelog-io.js';
|
|
16
16
|
export type { ReleaseChangelogRef } from './changelog-io.js';
|
|
17
17
|
export { createUpdateDiskPorts, createUpdateExecutor, pathsForUpdate, resolveCliEntry } from './store.js';
|