@linkdesk/plugin-sdk 0.1.7 → 0.1.8
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/package.json +3 -3
- package/dist/publish.test.d.ts +0 -2
- package/dist/publish.test.d.ts.map +0 -1
- package/dist/publish.test.js +0 -208
- package/dist/publish.test.js.map +0 -1
- package/dist/validate.test.d.ts +0 -2
- package/dist/validate.test.d.ts.map +0 -1
- package/dist/validate.test.js +0 -73
- package/dist/validate.test.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linkdesk/plugin-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "@linkdesk/plugin-sdk——LinkDesk 插件作者 SDK(对标 @types/vscode):window.linkdesk.* 类型 + 一键 build(.linkdesk-plugin) + dev 宿主 + plugin.json 验证 + eslint 门禁(E6#54d)。作者 npm i 后零壳源码依赖。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"node": ">=20.0.0"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
|
-
"build": "tsc",
|
|
35
|
+
"build": "tsc -p tsconfig.build.json",
|
|
36
36
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
37
|
-
"prepack": "tsc"
|
|
37
|
+
"prepack": "tsc -p tsconfig.build.json"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@linkdesk/contracts": "^0.1.1",
|
package/dist/publish.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"publish.test.d.ts","sourceRoot":"","sources":["../src/publish.test.ts"],"names":[],"mappings":""}
|
package/dist/publish.test.js
DELETED
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* publish 纯函数测试(E6#91e,L3.7 第 3.7.2 轮)——**CHANGELOG 切段的 B1–B10 十条边界**。
|
|
3
|
-
*
|
|
4
|
-
* 为什么值得单列一个文件:这段切段逻辑是「未装插件『更改日志』页签」的**唯一写入方**,切错了
|
|
5
|
-
* 是**发错信息**(把上一版的说明挂到新版本上)——比不显示更坏。故每条边界都钉一个用例。
|
|
6
|
-
*
|
|
7
|
-
* **对照基线**:文件下半 `describe("旧行为对照")` 里的 `naiveSlice` 是**朴素第一版写法**(测试专用,
|
|
8
|
-
* 非生产代码)。它存在的唯一理由是满足 memory `snapshot-shadows-truth-bug-class` 的硬要求——
|
|
9
|
-
* **回归测试必须证明「在旧行为上会红」**。光断言「新实现对」证明不了边界有被守住;断言「朴素写法在这条
|
|
10
|
-
* 用例上给出错误结果」才是。哪些用例两种写法一致、哪些分道扬镳,逐条写明。
|
|
11
|
-
*/
|
|
12
|
-
import { describe, it, expect } from "vitest";
|
|
13
|
-
import { buildCatalogEntry, readmeRawUrl, sliceChangelogSection, } from "./publish.js";
|
|
14
|
-
/* ── 样本 ─────────────────────────────────────────────────────────────── */
|
|
15
|
-
const SAMPLE = [
|
|
16
|
-
"# 更新日志",
|
|
17
|
-
"",
|
|
18
|
-
"## v1.2.0(2026-09-11)",
|
|
19
|
-
"- 修了某某问题",
|
|
20
|
-
"- 加了某个能力",
|
|
21
|
-
"",
|
|
22
|
-
"## v1.1.0(2026-08-01)",
|
|
23
|
-
"- 旧的一条",
|
|
24
|
-
"",
|
|
25
|
-
"## v1.0.0(2026-07-01)",
|
|
26
|
-
"- 最早的一条",
|
|
27
|
-
"",
|
|
28
|
-
].join("\n");
|
|
29
|
-
const view = (version) => ({ id: "demo-plugin", name: "Demo", version });
|
|
30
|
-
/* ── B1–B10 十条边界 ─────────────────────────────────────────────────── */
|
|
31
|
-
describe("sliceChangelogSection——B1–B10 边界", () => {
|
|
32
|
-
it("正常路径:切出目标版本正文,到下一个段标题为止", () => {
|
|
33
|
-
expect(sliceChangelogSection(SAMPLE, "1.2.0")).toBe("- 修了某某问题\n- 加了某个能力");
|
|
34
|
-
expect(sliceChangelogSection(SAMPLE, "1.0.0")).toBe("- 最早的一条");
|
|
35
|
-
});
|
|
36
|
-
it("B1 字段缺省:无 changelog 时不写该键(不是填空串)", () => {
|
|
37
|
-
// 「文件不存在」是 IO 层的事(collectPreview),纯函数层可断言的是**缺省即不写键**这条契约:
|
|
38
|
-
// 渲染层对「字段缺省」与「空串」走同一兜底,但缺省更诚实。
|
|
39
|
-
const entry = buildCatalogEntry(view("1.2.0"), "https://example.invalid/a.zip", 1, "owner", "2026-09-11T00:00:00Z", {});
|
|
40
|
-
expect("changelog" in entry.versions[0]).toBe(false);
|
|
41
|
-
expect("readmeUrl" in entry).toBe(false);
|
|
42
|
-
// 有值时两个键都在,且 changelog 落在 versions[0] 上(历史由 upsertCatalogEntry 拼)
|
|
43
|
-
const filled = buildCatalogEntry(view("1.2.0"), "https://example.invalid/a.zip", 1, "owner", "2026-09-11T00:00:00Z", {
|
|
44
|
-
readmeUrl: "https://example.invalid/README.md",
|
|
45
|
-
changelog: "- 一条",
|
|
46
|
-
});
|
|
47
|
-
expect(filled.readmeUrl).toBe("https://example.invalid/README.md");
|
|
48
|
-
expect(filled.versions[0].changelog).toBe("- 一条");
|
|
49
|
-
});
|
|
50
|
-
it("B2 版本切不到 → undefined(绝不回落到「取第一段」)", () => {
|
|
51
|
-
// 回落 = 把上一版的说明挂到新版本上,是发错信息——同 marketCatalog/select.ts「不发错包」的纪律
|
|
52
|
-
expect(sliceChangelogSection(SAMPLE, "9.9.9")).toBeUndefined();
|
|
53
|
-
});
|
|
54
|
-
it("B2b 版本号严格相等:1.0 不吃 1.0.0(不做 semver 松弛匹配)", () => {
|
|
55
|
-
expect(sliceChangelogSection(SAMPLE, "1.0")).toBeUndefined();
|
|
56
|
-
expect(sliceChangelogSection(SAMPLE, "1.2")).toBeUndefined();
|
|
57
|
-
});
|
|
58
|
-
it("B3 段标题下直接跟下一个标题(空正文)→ undefined", () => {
|
|
59
|
-
const text = "## v1.0.0\n\n## v0.9.0\n- 旧\n";
|
|
60
|
-
expect(sliceChangelogSection(text, "1.0.0")).toBeUndefined();
|
|
61
|
-
});
|
|
62
|
-
it("B4 围栏代码块内的假标题必须跳过(贴示例日志是常态)", () => {
|
|
63
|
-
const text = [
|
|
64
|
-
"# 更新日志",
|
|
65
|
-
"",
|
|
66
|
-
"## v1.2.0(2026-09-11)",
|
|
67
|
-
"示例(别当真):",
|
|
68
|
-
"",
|
|
69
|
-
"```markdown",
|
|
70
|
-
"## v1.1.0",
|
|
71
|
-
"- 这是代码块里的假段标题",
|
|
72
|
-
"```",
|
|
73
|
-
"",
|
|
74
|
-
"真·收尾一行",
|
|
75
|
-
"",
|
|
76
|
-
"## v1.1.0(2026-08-01)",
|
|
77
|
-
"- 真的旧版说明",
|
|
78
|
-
"",
|
|
79
|
-
].join("\n");
|
|
80
|
-
// 真段标题之后的正文 = 示例块 + 收尾行,**一直到下一个真段标题**——假标题不得截断它
|
|
81
|
-
const got = sliceChangelogSection(text, "1.2.0");
|
|
82
|
-
expect(got).toContain("真·收尾一行");
|
|
83
|
-
expect(got).toContain("- 这是代码块里的假段标题");
|
|
84
|
-
expect(got).not.toContain("- 真的旧版说明");
|
|
85
|
-
// 而 v1.1.0 仍能正确切出真段
|
|
86
|
-
expect(sliceChangelogSection(text, "1.1.0")).toBe("- 真的旧版说明");
|
|
87
|
-
});
|
|
88
|
-
it("B5 CRLF 正文不带 \\r(正文内部也不带,不只是两端)", () => {
|
|
89
|
-
const text = "# 更新日志\r\n\r\n## v1.0.0\r\n- 第一行\r\n- 第二行\r\n\r\n## v0.9.0\r\n- 旧\r\n";
|
|
90
|
-
const got = sliceChangelogSection(text, "1.0.0");
|
|
91
|
-
expect(got).toBe("- 第一行\n- 第二行");
|
|
92
|
-
expect(got).not.toContain("\r");
|
|
93
|
-
});
|
|
94
|
-
it("B6 BOM 剥离——首行就是段标题时也能切到", () => {
|
|
95
|
-
const text = "## v1.0.0\n- 有 BOM 的一段\n";
|
|
96
|
-
expect(sliceChangelogSection(text, "1.0.0")).toBe("- 有 BOM 的一段");
|
|
97
|
-
});
|
|
98
|
-
it("B7 prerelease 后缀整段捕获——不与同文件里的正式版段撞号", () => {
|
|
99
|
-
const text = ["## v1.0.0", "- 正式版", "", "## v1.0.0-beta.1", "- 预发布版", ""].join("\n");
|
|
100
|
-
expect(sliceChangelogSection(text, "1.0.0-beta.1")).toBe("- 预发布版");
|
|
101
|
-
expect(sliceChangelogSection(text, "1.0.0")).toBe("- 正式版");
|
|
102
|
-
});
|
|
103
|
-
it("B8 一级标题 `# 更新日志` 不当段标题(那是文档标题,不是版本号)", () => {
|
|
104
|
-
const text = "# v1.0.0\n- 这不是版本段\n";
|
|
105
|
-
expect(sliceChangelogSection(text, "1.0.0")).toBeUndefined();
|
|
106
|
-
});
|
|
107
|
-
it("B9 标题后无括号日期也正常通过(日期本就可选)", () => {
|
|
108
|
-
expect(sliceChangelogSection("## v1.0.0 后续补记\n- 一条\n", "1.0.0")).toBe("- 一条");
|
|
109
|
-
});
|
|
110
|
-
it("B10 Keep a Changelog 风格 `## [1.0.0] - 日期` 也认(解析器适配作者,不是反过来)", () => {
|
|
111
|
-
const text = ["# Changelog", "", "## [1.2.0] - 2026-09-11", "- 新版", "", "## [1.1.0] - 2026-08-01", "- 旧版", ""].join("\n");
|
|
112
|
-
expect(sliceChangelogSection(text, "1.2.0")).toBe("- 新版");
|
|
113
|
-
expect(sliceChangelogSection(text, "1.1.0")).toBe("- 旧版");
|
|
114
|
-
});
|
|
115
|
-
it("B10b 两种主流写法混排互不干扰", () => {
|
|
116
|
-
const text = ["## [1.2.0] - 2026-09-11", "- 方括号风", "", "## v1.1.0(2026-08-01)", "- 全角括号风", "", "## 1.0.0", "- 裸版本号", ""].join("\n");
|
|
117
|
-
expect(sliceChangelogSection(text, "1.2.0")).toBe("- 方括号风");
|
|
118
|
-
expect(sliceChangelogSection(text, "1.1.0")).toBe("- 全角括号风");
|
|
119
|
-
expect(sliceChangelogSection(text, "1.0.0")).toBe("- 裸版本号");
|
|
120
|
-
});
|
|
121
|
-
it("B11 同版本出现多次 → 取第一个(「最新在最上」是格式约定)", () => {
|
|
122
|
-
const text = ["## v1.0.0", "- 第一次出现(最新)", "", "## v1.0.0", "- 第二次出现(旧)", ""].join("\n");
|
|
123
|
-
expect(sliceChangelogSection(text, "1.0.0")).toBe("- 第一次出现(最新)");
|
|
124
|
-
});
|
|
125
|
-
it("两侧前导 v 等价:段标题带 v、传参不带(或反之)都认", () => {
|
|
126
|
-
expect(sliceChangelogSection("## v1.0.0\n- 一条\n", "v1.0.0")).toBe("- 一条");
|
|
127
|
-
expect(sliceChangelogSection("## 1.0.0\n- 一条\n", "1.0.0")).toBe("- 一条");
|
|
128
|
-
});
|
|
129
|
-
it("`###` / `####` 容忍,`#####` 不算段标题", () => {
|
|
130
|
-
expect(sliceChangelogSection("### v1.0.0\n- 三级\n", "1.0.0")).toBe("- 三级");
|
|
131
|
-
expect(sliceChangelogSection("#### v1.0.0\n- 四级\n", "1.0.0")).toBe("- 四级");
|
|
132
|
-
expect(sliceChangelogSection("##### v1.0.0\n- 五级不该认\n", "1.0.0")).toBeUndefined();
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
/* ── readmeUrl 形态 ──────────────────────────────────────────────────── */
|
|
136
|
-
describe("readmeRawUrl", () => {
|
|
137
|
-
it("固定形态 = raw.githubusercontent.com/{owner}/{repo}/{tag}/README.md", () => {
|
|
138
|
-
expect(readmeRawUrl({ owner: "demo-owner", repo: "demo-repo" }, "v1.2.0")).toBe("https://raw.githubusercontent.com/demo-owner/demo-repo/v1.2.0/README.md");
|
|
139
|
-
});
|
|
140
|
-
it("用 tag 不用 default_branch——未装看到的与装上后看到的同源", () => {
|
|
141
|
-
expect(readmeRawUrl({ owner: "o", repo: "r" }, "v1.0.0")).not.toContain("/main/");
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
/* ── 旧行为对照(证明上面这些边界在朴素写法上会红)──────────────────── */
|
|
145
|
-
/**
|
|
146
|
-
* 朴素第一版写法——**测试专用,非生产代码**。特征:按 `##` 行找段标题、正则**只捕三段版本号**、
|
|
147
|
-
* 不剥 BOM、不跳围栏、`split("\n")` 不兼容 CRLF。这是真正会有人写出来的第一版,不是稻草人。
|
|
148
|
-
*/
|
|
149
|
-
function naiveSlice(text, version) {
|
|
150
|
-
const lines = text.split("\n");
|
|
151
|
-
// 🔴 关键缺陷就在这条正则:只捕 `\d+.\d+.\d+` 三段——预发布号与方括号风格都漏
|
|
152
|
-
const heading = /^##\s+v?(\d+\.\d+\.\d+)/;
|
|
153
|
-
const target = version.replace(/^v/, "");
|
|
154
|
-
let start = -1;
|
|
155
|
-
let end = lines.length;
|
|
156
|
-
for (let i = 0; i < lines.length; i++) {
|
|
157
|
-
const m = heading.exec(lines[i] ?? "");
|
|
158
|
-
if (!m)
|
|
159
|
-
continue;
|
|
160
|
-
if (start < 0) {
|
|
161
|
-
if (m[1] === target)
|
|
162
|
-
start = i + 1;
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
end = i;
|
|
166
|
-
break;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
if (start < 0)
|
|
170
|
-
return undefined;
|
|
171
|
-
return lines.slice(start, end).join("\n").trim() || undefined;
|
|
172
|
-
}
|
|
173
|
-
describe("旧行为对照——朴素写法在这几条上会红", () => {
|
|
174
|
-
it("B4 围栏:朴素写法把代码块里的假标题当真段标题,正文被提前截断", () => {
|
|
175
|
-
const text = ["## v1.2.0", "正文甲", "```", "## v1.1.0", "```", "正文乙", "", "## v1.1.0", "- 真旧版", ""].join("\n");
|
|
176
|
-
expect(sliceChangelogSection(text, "1.2.0")).toBe("正文甲\n```\n## v1.1.0\n```\n正文乙");
|
|
177
|
-
// 朴素:在块内的假标题处就 break → 正文腰斩(实测值 = 正文甲 + 围栏起止行;「正文乙」整段丢失)
|
|
178
|
-
expect(naiveSlice(text, "1.2.0")).toBe("正文甲\n```");
|
|
179
|
-
});
|
|
180
|
-
it("B5 CRLF:朴素写法在正文内部留下 \\r", () => {
|
|
181
|
-
const text = "## v1.0.0\r\n- 第一行\r\n- 第二行\r\n";
|
|
182
|
-
expect(sliceChangelogSection(text, "1.0.0")).toBe("- 第一行\n- 第二行");
|
|
183
|
-
expect(naiveSlice(text, "1.0.0")).toContain("\r");
|
|
184
|
-
});
|
|
185
|
-
it("B6 BOM:朴素写法匹配不到首行段标题 → 整段丢失", () => {
|
|
186
|
-
const text = "## v1.0.0\n- 有 BOM 的一段\n";
|
|
187
|
-
expect(sliceChangelogSection(text, "1.0.0")).toBe("- 有 BOM 的一段");
|
|
188
|
-
expect(naiveSlice(text, "1.0.0")).toBeUndefined();
|
|
189
|
-
});
|
|
190
|
-
it("B7 预发布:朴素写法只捕三段 → 预发布版整段切不到(两条段撞成同一个版本号)", () => {
|
|
191
|
-
const text = ["## v1.0.0", "- 正式版", "", "## v1.0.0-beta.1", "- 预发布版", ""].join("\n");
|
|
192
|
-
expect(sliceChangelogSection(text, "1.0.0-beta.1")).toBe("- 预发布版");
|
|
193
|
-
// 朴素:两段都被捕成 "1.0.0",预发布版这一版**永远切不到**(真机症状 = 该版显示「此版本未提供变更说明」)
|
|
194
|
-
expect(naiveSlice(text, "1.0.0-beta.1")).toBeUndefined();
|
|
195
|
-
});
|
|
196
|
-
it("B10 Keep a Changelog:朴素写法认不得方括号 → 整段丢失", () => {
|
|
197
|
-
const text = "## [1.0.0] - 2026-09-11\n- 方括号风\n";
|
|
198
|
-
expect(sliceChangelogSection(text, "1.0.0")).toBe("- 方括号风");
|
|
199
|
-
expect(naiveSlice(text, "1.0.0")).toBeUndefined();
|
|
200
|
-
});
|
|
201
|
-
it("诚实记账:这几条朴素写法与生产写法**一致**(不假装它们也是边界)", () => {
|
|
202
|
-
// B1/B3/B8/B9 以及「切不到→undefined」在朴素写法上本来就对——写出来免得读者以为十条都靠新写法救
|
|
203
|
-
expect(naiveSlice(SAMPLE, "9.9.9")).toBeUndefined(); // B2:两边都 undefined
|
|
204
|
-
expect(naiveSlice(SAMPLE, "1.0.0")).toBe("- 最早的一条"); // 常规路径:两边都对
|
|
205
|
-
expect(naiveSlice("## v1.0.0\n\n## v0.9.0\n- 旧\n", "1.0.0")).toBeUndefined(); // B3:两边都 undefined
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
//# sourceMappingURL=publish.test.js.map
|
package/dist/publish.test.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"publish.test.js","sourceRoot":"","sources":["../src/publish.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,qBAAqB,GAEtB,MAAM,cAAc,CAAC;AAEtB,2EAA2E;AAE3E,MAAM,MAAM,GAAG;IACb,QAAQ;IACR,EAAE;IACF,uBAAuB;IACvB,UAAU;IACV,UAAU;IACV,EAAE;IACF,uBAAuB;IACvB,QAAQ;IACR,EAAE;IACF,uBAAuB;IACvB,SAAS;IACT,EAAE;CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,IAAI,GAAG,CAAC,OAAe,EAAgB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;AAE/F,wEAAwE;AAExE,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC1E,MAAM,CAAC,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,2DAA2D;QAC3D,+BAA+B;QAC/B,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,+BAA+B,EAAE,CAAC,EAAE,OAAO,EAAE,sBAAsB,EAAE,EAAE,CAAC,CAAC;QACxH,MAAM,CAAC,WAAW,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtD,MAAM,CAAC,WAAW,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzC,kEAAkE;QAClE,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,+BAA+B,EAAE,CAAC,EAAE,OAAO,EAAE,sBAAsB,EAAE;YACnH,SAAS,EAAE,mCAAmC;YAC9C,SAAS,EAAE,MAAM;SAClB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QACnE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,+DAA+D;QAC/D,MAAM,CAAC,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,CAAC,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAC7D,MAAM,CAAC,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,IAAI,GAAG,+BAA+B,CAAC;QAC7C,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,IAAI,GAAG;YACX,QAAQ;YACR,EAAE;YACF,uBAAuB;YACvB,UAAU;YACV,EAAE;YACF,aAAa;YACb,WAAW;YACX,eAAe;YACf,KAAK;YACL,EAAE;YACF,QAAQ;YACR,EAAE;YACF,uBAAuB;YACvB,UAAU;YACV,EAAE;SACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,iDAAiD;QACjD,MAAM,GAAG,GAAG,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAChC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QACvC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACtC,oBAAoB;QACpB,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,IAAI,GAAG,uEAAuE,CAAC;QACrF,MAAM,GAAG,GAAG,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,IAAI,GAAG,2BAA2B,CAAC;QACzC,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,kBAAkB,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrF,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnE,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,IAAI,GAAG,sBAAsB,CAAC;QACpC,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,CAAC,qBAAqB,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,IAAI,GAAG,CAAC,aAAa,EAAE,EAAE,EAAE,yBAAyB,EAAE,MAAM,EAAE,EAAE,EAAE,yBAAyB,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1H,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1D,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC3B,MAAM,IAAI,GAAG,CAAC,yBAAyB,EAAE,QAAQ,EAAE,EAAE,EAAE,uBAAuB,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpI,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5D,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7D,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE,aAAa,EAAE,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxF,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,qBAAqB,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1E,MAAM,CAAC,qBAAqB,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,qBAAqB,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1E,MAAM,CAAC,qBAAqB,CAAC,qBAAqB,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3E,MAAM,CAAC,qBAAqB,CAAC,yBAAyB,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACpF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,0EAA0E;AAE1E,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAC7E,yEAAyE,CAC1E,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,oDAAoD;AAEpD;;;GAGG;AACH,SAAS,UAAU,CAAC,IAAY,EAAE,OAAe;IAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,kDAAkD;IAClD,MAAM,OAAO,GAAG,yBAAyB,CAAC;IAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACzC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;IACf,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC;IACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACvC,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM;gBAAE,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,CAAC;aAAM,CAAC;YACN,GAAG,GAAG,CAAC,CAAC;YACR,MAAM;QACR,CAAC;IACH,CAAC;IACD,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAChC,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;AAChE,CAAC;AAED,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7G,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QACnF,yDAAyD;QACzD,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,IAAI,GAAG,iCAAiC,CAAC;QAC/C,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAClE,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,IAAI,GAAG,2BAA2B,CAAC;QACzC,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACjE,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,kBAAkB,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrF,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnE,8DAA8D;QAC9D,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,IAAI,GAAG,mCAAmC,CAAC;QACjD,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5D,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,6DAA6D;QAC7D,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,mBAAmB;QACxE,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY;QACjE,MAAM,CAAC,UAAU,CAAC,+BAA+B,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,mBAAmB;IACnG,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/validate.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate.test.d.ts","sourceRoot":"","sources":["../src/validate.test.ts"],"names":[],"mappings":""}
|
package/dist/validate.test.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* validate 墓碑提示测试(E6#91d,L3.7 第 3.7.2 轮)。
|
|
3
|
-
*
|
|
4
|
-
* 钉死两件事:
|
|
5
|
-
* ① 旧写法(`plugin.json` 里还有 `changelog` / `readme`)→ **有警告、仍 `valid`**(警告不是错误——
|
|
6
|
-
* 判错会让存量第三方插件的 `npm run build` 突然炸,为一个从无读取方的字段破坏构建不值)。
|
|
7
|
-
* ② 新写法(干净 manifest)→ **无警告**(墓碑不能变成噪音——那会让人习惯性忽略它)。
|
|
8
|
-
*
|
|
9
|
-
* fixture 一律用明显虚构值(硬约束 21:测试桩不指向真实插件)。
|
|
10
|
-
*/
|
|
11
|
-
import { afterEach, describe, expect, it } from "vitest";
|
|
12
|
-
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
13
|
-
import { tmpdir } from "node:os";
|
|
14
|
-
import { join } from "node:path";
|
|
15
|
-
import { validatePluginJson } from "./validate.js";
|
|
16
|
-
const dirs = [];
|
|
17
|
-
/** 造一个临时插件工程(写到盘上——validatePluginJson 是路径入口,含真实文件 IO) */
|
|
18
|
-
function fixture(manifest) {
|
|
19
|
-
const dir = mkdtempSync(join(tmpdir(), "linkdesk-fixture-"));
|
|
20
|
-
dirs.push(dir);
|
|
21
|
-
writeFileSync(join(dir, "plugin.json"), JSON.stringify({ name: "Demo Fixture", version: "1.0.0", ...manifest }, null, 2), "utf8");
|
|
22
|
-
return join(dir, "plugin.json");
|
|
23
|
-
}
|
|
24
|
-
afterEach(() => {
|
|
25
|
-
while (dirs.length > 0)
|
|
26
|
-
rmSync(dirs.pop(), { recursive: true, force: true });
|
|
27
|
-
});
|
|
28
|
-
describe("validatePluginJson——墓碑提示(E6#91d)", () => {
|
|
29
|
-
it("干净 manifest → 无 warnings 键(墓碑不是噪音)", () => {
|
|
30
|
-
const res = validatePluginJson(fixture({}));
|
|
31
|
-
expect(res.valid).toBe(true);
|
|
32
|
-
expect(res.errors).toEqual([]);
|
|
33
|
-
expect(res.warnings).toBeUndefined();
|
|
34
|
-
});
|
|
35
|
-
it("旧写法 changelog → 警告、valid 仍为 true(构建不炸)", () => {
|
|
36
|
-
const res = validatePluginJson(fixture({ changelog: [{ version: "1.0.0", date: "2026-09-11", changes: ["一条"] }] }));
|
|
37
|
-
expect(res.valid).toBe(true);
|
|
38
|
-
expect(res.errors).toEqual([]);
|
|
39
|
-
expect(res.warnings).toHaveLength(1);
|
|
40
|
-
expect(res.warnings?.[0]).toContain("changelog");
|
|
41
|
-
expect(res.warnings?.[0]).toContain("CHANGELOG.md"); // 警告必须给出**去哪**
|
|
42
|
-
});
|
|
43
|
-
it("旧写法 readme → 警告、valid 仍为 true", () => {
|
|
44
|
-
const res = validatePluginJson(fixture({ readme: "./README.md" }));
|
|
45
|
-
expect(res.valid).toBe(true);
|
|
46
|
-
expect(res.warnings).toHaveLength(1);
|
|
47
|
-
expect(res.warnings?.[0]).toContain("readme");
|
|
48
|
-
expect(res.warnings?.[0]).toContain("README.md");
|
|
49
|
-
});
|
|
50
|
-
it("两个都写 → 两条警告(各自指路,不合并成一条)", () => {
|
|
51
|
-
const res = validatePluginJson(fixture({ readme: "./README.md", changelog: [{ version: "1.0.0", date: "2026-09-11" }] }));
|
|
52
|
-
expect(res.valid).toBe(true);
|
|
53
|
-
expect(res.warnings).toHaveLength(2);
|
|
54
|
-
});
|
|
55
|
-
it("嵌套同名字段不算命中——只扫顶层(`cardDocMap` 里的键名 changelog 与墓碑无关)", () => {
|
|
56
|
-
// `cardDocMap` 是合法的「任意键」顶层对象——用它的**键名**叫 changelog 来证明扫描只看顶层 key,
|
|
57
|
-
// 不递归进子对象(递归 = 把用户数据当字段名,会误报)
|
|
58
|
-
const res = validatePluginJson(fixture({ cardDocMap: { changelog: "resources/demo.md", readme: "resources/demo.md" } }));
|
|
59
|
-
expect(res.valid).toBe(true);
|
|
60
|
-
expect(res.warnings).toBeUndefined();
|
|
61
|
-
});
|
|
62
|
-
it("schema 已经拦下的 manifest → 提前返回,不产 warnings(先修错,别看噪音)", () => {
|
|
63
|
-
// 缺 version(schema required)→ 走 valid:false 分支
|
|
64
|
-
const dir = mkdtempSync(join(tmpdir(), "linkdesk-fixture-"));
|
|
65
|
-
dirs.push(dir);
|
|
66
|
-
const p = join(dir, "plugin.json");
|
|
67
|
-
writeFileSync(p, JSON.stringify({ name: "Demo Fixture", changelog: [] }), "utf8");
|
|
68
|
-
const res = validatePluginJson(p);
|
|
69
|
-
expect(res.valid).toBe(false);
|
|
70
|
-
expect(res.warnings).toBeUndefined();
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
//# sourceMappingURL=validate.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate.test.js","sourceRoot":"","sources":["../src/validate.test.ts"],"names":[],"mappings":"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"}
|