@cloudglab/confluence-cli 0.0.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.
Files changed (100) hide show
  1. package/AGENTS.md +34 -0
  2. package/CHANGELOG.md +26 -0
  3. package/README.md +147 -0
  4. package/assets/readme/confluence-cli-hero.png +0 -0
  5. package/assets/readme/confluence-cli-hero.svg +7 -0
  6. package/assets/readme/prompts/01-cover-confluence-cli.md +61 -0
  7. package/dist/api/endpoints.d.ts +404 -0
  8. package/dist/api/endpoints.js +85 -0
  9. package/dist/api/index.d.ts +148 -0
  10. package/dist/api/index.js +143 -0
  11. package/dist/bin/confluence-reader.d.ts +2 -0
  12. package/dist/bin/confluence-reader.js +8 -0
  13. package/dist/bin/confluence-writer.d.ts +2 -0
  14. package/dist/bin/confluence-writer.js +8 -0
  15. package/dist/bin/confluence.d.ts +2 -0
  16. package/dist/bin/confluence.js +11 -0
  17. package/dist/cli.d.ts +1 -0
  18. package/dist/cli.js +154 -0
  19. package/dist/core/api-provider.d.ts +3 -0
  20. package/dist/core/api-provider.js +13 -0
  21. package/dist/core/changelog.d.ts +7 -0
  22. package/dist/core/changelog.js +42 -0
  23. package/dist/core/cli-output.d.ts +16 -0
  24. package/dist/core/cli-output.js +318 -0
  25. package/dist/core/cli-registry.d.ts +20 -0
  26. package/dist/core/cli-registry.js +148 -0
  27. package/dist/core/command-groups.generated.d.ts +2 -0
  28. package/dist/core/command-groups.generated.js +88 -0
  29. package/dist/core/config.d.ts +5 -0
  30. package/dist/core/config.js +108 -0
  31. package/dist/core/http-error.d.ts +2 -0
  32. package/dist/core/http-error.js +4 -0
  33. package/dist/core/http.d.ts +28 -0
  34. package/dist/core/http.js +124 -0
  35. package/dist/core/inline-comment.d.ts +23 -0
  36. package/dist/core/inline-comment.js +27 -0
  37. package/dist/core/list-result.d.ts +14 -0
  38. package/dist/core/list-result.js +81 -0
  39. package/dist/core/manifest.d.ts +11 -0
  40. package/dist/core/manifest.js +42 -0
  41. package/dist/core/pagination.d.ts +26 -0
  42. package/dist/core/pagination.js +45 -0
  43. package/dist/core/roles.d.ts +4 -0
  44. package/dist/core/roles.js +12 -0
  45. package/dist/core/tool-registry.d.ts +9 -0
  46. package/dist/core/tool-registry.js +60 -0
  47. package/dist/core/validation.d.ts +2 -0
  48. package/dist/core/validation.js +10 -0
  49. package/dist/core/value.d.ts +2 -0
  50. package/dist/core/value.js +19 -0
  51. package/dist/core/write-guard.d.ts +25 -0
  52. package/dist/core/write-guard.js +49 -0
  53. package/dist/index.d.ts +3 -0
  54. package/dist/index.js +3 -0
  55. package/dist/install.d.ts +3 -0
  56. package/dist/install.js +407 -0
  57. package/dist/manifest.json +122 -0
  58. package/dist/tools/attachments.d.ts +2 -0
  59. package/dist/tools/attachments.js +46 -0
  60. package/dist/tools/content.d.ts +2 -0
  61. package/dist/tools/content.js +45 -0
  62. package/dist/tools/convert.d.ts +2 -0
  63. package/dist/tools/convert.js +63 -0
  64. package/dist/tools/init.d.ts +2 -0
  65. package/dist/tools/init.js +24 -0
  66. package/dist/tools/install.d.ts +2 -0
  67. package/dist/tools/install.js +52 -0
  68. package/dist/tools/labels.d.ts +2 -0
  69. package/dist/tools/labels.js +22 -0
  70. package/dist/tools/metadata.d.ts +2 -0
  71. package/dist/tools/metadata.js +26 -0
  72. package/dist/tools/rest.d.ts +2 -0
  73. package/dist/tools/rest.js +52 -0
  74. package/dist/tools/spaces.d.ts +2 -0
  75. package/dist/tools/spaces.js +18 -0
  76. package/dist/tools/transfer.d.ts +2 -0
  77. package/dist/tools/transfer.js +407 -0
  78. package/dist/types/common.d.ts +17 -0
  79. package/dist/types/common.js +2 -0
  80. package/dist/update-probe.d.ts +2 -0
  81. package/dist/update-probe.js +142 -0
  82. package/dist/utils/mark-metadata.d.ts +9 -0
  83. package/dist/utils/mark-metadata.js +16 -0
  84. package/dist/utils/markdown.d.ts +9 -0
  85. package/dist/utils/markdown.js +220 -0
  86. package/dist/utils/result.d.ts +3 -0
  87. package/dist/utils/result.js +7 -0
  88. package/dist/version.d.ts +1 -0
  89. package/dist/version.js +2 -0
  90. package/docs/confluence-7.13.7-api.md +183 -0
  91. package/docs/index.html +608 -0
  92. package/docs/release.md +41 -0
  93. package/package.json +63 -0
  94. package/skills/confluence-cli/SKILL.md +63 -0
  95. package/skills/confluence-cli/reference/cli.md +36 -0
  96. package/skills/confluence-cli/reference/commands.md +41 -0
  97. package/skills/confluence-cli/reference/content.md +23 -0
  98. package/skills/confluence-cli/reference/overview.md +23 -0
  99. package/skills/confluence-cli/reference/rest.md +19 -0
  100. package/skills/confluence-cli/reference/transfer.md +27 -0
@@ -0,0 +1,608 @@
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>confluence-cli · Confluence 命令速查</title>
7
+ <meta name="description" content="confluence-cli 极简命令速查、安装和更新入口。">
8
+ <style>
9
+ :root {
10
+ color-scheme: light;
11
+ --paper: #fbfaf7;
12
+ --ink: #161616;
13
+ --muted: #606060;
14
+ --hairline: #161616;
15
+ --soft-line: #d7d4cc;
16
+ --inverse: #f6f3eb;
17
+ font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
18
+ }
19
+
20
+ * { box-sizing: border-box; }
21
+
22
+ body {
23
+ margin: 0;
24
+ color: var(--ink);
25
+ background:
26
+ linear-gradient(var(--soft-line) 1px, transparent 1px),
27
+ linear-gradient(90deg, var(--soft-line) 1px, transparent 1px),
28
+ var(--paper);
29
+ background-size: 28px 28px;
30
+ line-height: 1.6;
31
+ }
32
+
33
+ main {
34
+ width: min(1180px, calc(100% - 32px));
35
+ margin: 0 auto;
36
+ padding: 36px 0 48px;
37
+ }
38
+
39
+ .hero {
40
+ display: grid;
41
+ grid-template-columns: minmax(0, 1.05fr) minmax(320px, 0.95fr);
42
+ gap: 18px;
43
+ align-items: stretch;
44
+ margin-bottom: 18px;
45
+ }
46
+
47
+ .panel, .command, .section {
48
+ min-width: 0;
49
+ border: 1px solid var(--hairline);
50
+ background: var(--paper);
51
+ }
52
+
53
+ .panel {
54
+ display: grid;
55
+ align-content: space-between;
56
+ min-height: 356px;
57
+ padding: 34px;
58
+ }
59
+
60
+ .eyebrow {
61
+ display: inline-flex;
62
+ align-items: center;
63
+ gap: 8px;
64
+ margin-bottom: 34px;
65
+ color: var(--ink);
66
+ font-size: 14px;
67
+ font-weight: 800;
68
+ letter-spacing: 0.16em;
69
+ text-transform: uppercase;
70
+ }
71
+
72
+ .eyebrow::before {
73
+ content: "";
74
+ display: inline-block;
75
+ width: 44px;
76
+ height: 1px;
77
+ background: var(--ink);
78
+ }
79
+
80
+ h1 {
81
+ margin: 0;
82
+ max-width: 7em;
83
+ font-size: clamp(44px, 9vw, 104px);
84
+ line-height: 0.88;
85
+ letter-spacing: -0.08em;
86
+ }
87
+
88
+ .lead {
89
+ max-width: 620px;
90
+ margin: 30px 0 0;
91
+ color: var(--muted);
92
+ font-size: clamp(16px, 1.8vw, 20px);
93
+ }
94
+
95
+ .actions {
96
+ display: flex;
97
+ flex-wrap: wrap;
98
+ gap: 0;
99
+ margin-top: 34px;
100
+ }
101
+
102
+ a, button { font: inherit; }
103
+
104
+ .button {
105
+ display: inline-flex;
106
+ align-items: center;
107
+ justify-content: center;
108
+ min-height: 46px;
109
+ margin-right: -1px;
110
+ padding: 0 18px;
111
+ border: 1px solid var(--hairline);
112
+ color: var(--ink);
113
+ background: var(--paper);
114
+ text-decoration: none;
115
+ cursor: pointer;
116
+ }
117
+
118
+ .button.primary {
119
+ color: var(--inverse);
120
+ background: var(--ink);
121
+ font-weight: 700;
122
+ }
123
+
124
+ .stack {
125
+ display: grid;
126
+ gap: 0;
127
+ }
128
+
129
+ .command {
130
+ display: grid;
131
+ align-content: center;
132
+ min-height: 108px;
133
+ padding: 18px 20px;
134
+ border-bottom: 0;
135
+ }
136
+
137
+ .command:last-child {
138
+ border-bottom: 1px solid var(--hairline);
139
+ }
140
+
141
+ .command strong {
142
+ display: block;
143
+ margin-bottom: 12px;
144
+ font-size: 14px;
145
+ color: var(--muted);
146
+ letter-spacing: 0.02em;
147
+ }
148
+
149
+ .copy-row {
150
+ display: grid;
151
+ grid-template-columns: minmax(0, 1fr) 76px;
152
+ gap: 0;
153
+ align-items: center;
154
+ }
155
+
156
+ code {
157
+ display: block;
158
+ width: 100%;
159
+ min-width: 0;
160
+ padding: 12px 13px;
161
+ overflow-x: auto;
162
+ border: 1px solid var(--hairline);
163
+ color: var(--ink);
164
+ background: var(--inverse);
165
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
166
+ font-size: 13px;
167
+ line-height: 1.45;
168
+ white-space: nowrap;
169
+ scrollbar-width: thin;
170
+ }
171
+
172
+ .copy {
173
+ min-height: 48px;
174
+ margin-left: -1px;
175
+ padding: 0 12px;
176
+ border: 1px solid var(--hairline);
177
+ color: var(--ink);
178
+ background: var(--paper);
179
+ cursor: pointer;
180
+ }
181
+
182
+ .button:hover, .copy:hover {
183
+ color: var(--inverse);
184
+ background: var(--ink);
185
+ }
186
+
187
+ .wiki {
188
+ margin-top: 18px;
189
+ padding: 24px;
190
+ }
191
+
192
+ .wiki-head {
193
+ display: grid;
194
+ grid-template-columns: minmax(0, 1fr) minmax(280px, 420px);
195
+ gap: 18px;
196
+ align-items: end;
197
+ }
198
+
199
+ .wiki p {
200
+ max-width: 680px;
201
+ margin: -6px 0 0;
202
+ color: var(--muted);
203
+ font-size: 14px;
204
+ }
205
+
206
+ .wiki-search {
207
+ display: grid;
208
+ gap: 8px;
209
+ }
210
+
211
+ .wiki-search label {
212
+ color: var(--muted);
213
+ font-size: 13px;
214
+ font-weight: 700;
215
+ }
216
+
217
+ .wiki-search input {
218
+ width: 100%;
219
+ min-height: 46px;
220
+ padding: 0 14px;
221
+ border: 1px solid var(--hairline);
222
+ border-radius: 0;
223
+ color: var(--ink);
224
+ background: var(--paper);
225
+ font: inherit;
226
+ outline: none;
227
+ }
228
+
229
+ .wiki-search input:focus {
230
+ box-shadow: inset 0 0 0 2px var(--ink);
231
+ }
232
+
233
+ .wiki-status {
234
+ margin-top: 16px;
235
+ color: var(--muted);
236
+ font-size: 13px;
237
+ }
238
+
239
+ .grid {
240
+ display: grid;
241
+ grid-template-columns: repeat(3, minmax(0, 1fr));
242
+ gap: 18px;
243
+ margin-top: 18px;
244
+ }
245
+
246
+ .section {
247
+ padding: 22px;
248
+ }
249
+
250
+ h2 {
251
+ display: flex;
252
+ align-items: center;
253
+ gap: 12px;
254
+ margin: 0 0 18px;
255
+ font-size: 20px;
256
+ letter-spacing: -0.04em;
257
+ }
258
+
259
+ h2::after {
260
+ content: "";
261
+ flex: 1;
262
+ height: 1px;
263
+ background: var(--hairline);
264
+ }
265
+
266
+ ul {
267
+ display: grid;
268
+ gap: 14px;
269
+ padding: 0;
270
+ margin: 0;
271
+ list-style: none;
272
+ }
273
+
274
+ li {
275
+ min-width: 0;
276
+ color: var(--muted);
277
+ font-size: 14px;
278
+ }
279
+
280
+ li code {
281
+ font-size: 12px;
282
+ }
283
+
284
+ li .copy-row {
285
+ position: relative;
286
+ display: block;
287
+ margin-top: 6px;
288
+ }
289
+
290
+ li code {
291
+ min-height: 46px;
292
+ padding-right: 88px;
293
+ overflow-x: visible;
294
+ white-space: normal;
295
+ overflow-wrap: anywhere;
296
+ }
297
+
298
+ li .copy {
299
+ position: absolute;
300
+ top: 0;
301
+ right: 0;
302
+ width: 76px;
303
+ height: 100%;
304
+ min-height: 46px;
305
+ margin-top: 0;
306
+ margin-left: 0;
307
+ font-size: 13px;
308
+ opacity: 0;
309
+ pointer-events: none;
310
+ transform: translateX(6px);
311
+ transition: opacity 120ms ease, transform 120ms ease;
312
+ }
313
+
314
+ li .copy-row:hover code,
315
+ li .copy-row:focus-within code {
316
+ background: var(--paper);
317
+ }
318
+
319
+ li .copy-row:hover .copy,
320
+ li .copy-row:focus-within .copy {
321
+ opacity: 1;
322
+ pointer-events: auto;
323
+ transform: translateX(0);
324
+ }
325
+
326
+ footer {
327
+ margin-top: 28px;
328
+ color: var(--muted);
329
+ font-size: 13px;
330
+ text-align: center;
331
+ }
332
+
333
+ footer code {
334
+ display: inline;
335
+ width: auto;
336
+ padding: 2px 6px;
337
+ border: 1px solid var(--hairline);
338
+ background: transparent;
339
+ white-space: normal;
340
+ }
341
+
342
+ @media (max-width: 860px) {
343
+ main { padding-top: 20px; }
344
+ .hero, .wiki-head, .grid { grid-template-columns: 1fr; }
345
+ .panel {
346
+ min-height: auto;
347
+ padding: 26px;
348
+ }
349
+ .stack { border-bottom: 1px solid var(--hairline); }
350
+ .command:last-child { border-bottom: 0; }
351
+ }
352
+
353
+ @media (max-width: 520px) {
354
+ main { width: min(100% - 18px, 1180px); }
355
+ h1 { font-size: clamp(42px, 18vw, 76px); }
356
+ .actions { display: grid; }
357
+ .button {
358
+ width: 100%;
359
+ margin-right: 0;
360
+ margin-bottom: -1px;
361
+ }
362
+ .command .copy-row { grid-template-columns: 1fr; }
363
+ .command .copy {
364
+ width: 100%;
365
+ margin-top: -1px;
366
+ margin-left: 0;
367
+ }
368
+ }
369
+
370
+ @media (hover: none), (pointer: coarse) {
371
+ li .copy {
372
+ opacity: 1;
373
+ pointer-events: auto;
374
+ transform: none;
375
+ }
376
+ }
377
+ </style>
378
+ </head>
379
+ <body>
380
+ <main>
381
+ <section class="hero">
382
+ <div class="panel">
383
+ <div class="eyebrow">Confluence CLI</div>
384
+ <h1>命令速查</h1>
385
+ <p class="lead">把 Confluence 内容发布、评论、标签、附件、REST 查询和 AI Skill 工作流接到终端、脚本与发布流程。</p>
386
+ <div class="actions">
387
+ <button class="button primary" type="button" data-copy="npx -y @cloudglab/confluence-cli@latest install">复制安装命令</button>
388
+ <a class="button" href="https://github.com/cloudglab/confluence-cli">GitHub</a>
389
+ <a class="button" href="https://www.npmjs.com/package/@cloudglab/confluence-cli">npm</a>
390
+ </div>
391
+ </div>
392
+ <div class="stack">
393
+ <div class="command">
394
+ <strong>一键安装 CLI + Skill</strong>
395
+ <div class="copy-row"><code>npx -y @cloudglab/confluence-cli@latest install</code><button class="copy" type="button" data-copy="npx -y @cloudglab/confluence-cli@latest install">复制</button></div>
396
+ </div>
397
+ <div class="command">
398
+ <strong>已安装后更新</strong>
399
+ <div class="copy-row"><code>confluence update</code><button class="copy" type="button" data-copy="confluence update">复制</button></div>
400
+ </div>
401
+ <div class="command">
402
+ <strong>自举更新</strong>
403
+ <div class="copy-row"><code>npx -y @cloudglab/confluence-cli@latest update</code><button class="copy" type="button" data-copy="npx -y @cloudglab/confluence-cli@latest update">复制</button></div>
404
+ </div>
405
+ </div>
406
+ </section>
407
+
408
+ <section class="section wiki" aria-labelledby="wiki-title">
409
+ <div class="wiki-head">
410
+ <div>
411
+ <h2 id="wiki-title">Wiki / 检索</h2>
412
+ <p>先做成静态检索:安装、角色、内容查询、REST 透传、发布、附件、评论和环境变量都能在本页快速过滤。后续可以扩展为构建期索引,覆盖 README、CHANGELOG 和源码导出的命令清单。</p>
413
+ </div>
414
+ <div class="wiki-search">
415
+ <label for="wiki-query">输入关键词</label>
416
+ <input id="wiki-query" type="search" placeholder="例如:upload、comment、label、rest、update" autocomplete="off">
417
+ </div>
418
+ </div>
419
+ <div class="wiki-status" id="wiki-status">输入关键词后过滤下方命令。</div>
420
+ </section>
421
+
422
+ <section class="grid" aria-label="命令速查">
423
+ <div class="section">
424
+ <h2>常用场景</h2>
425
+ <ul>
426
+ <li>搜索页面<code>confluence searchContent --cql 'space = "DEV" AND text ~ "API"' --limit 10</code></li>
427
+ <li>查看页面详情<code>confluence getContent --id 123456</code></li>
428
+ <li>发布 Markdown<code>confluence uploadMarkdown --file docs/page.md --space DEV --toc --confirm true</code></li>
429
+ <li>下载页面和附件<code>confluence downloadPage --id 123456 --outputDir exports --downloadAttachments true</code></li>
430
+ <li>查看 REST 端点<code>confluence listRestApis --group content --limit 20</code></li>
431
+ <li>透传 REST 查询<code>confluence callRestApi --method GET --path '/content/{id}' --pathParams '{"id":"123456"}'</code></li>
432
+ </ul>
433
+ </div>
434
+ <div class="section">
435
+ <h2>基础 / 安装</h2>
436
+ <ul>
437
+ <li>一键安装<code>npx -y @cloudglab/confluence-cli@latest install</code></li>
438
+ <li>更新 CLI<code>confluence update</code></li>
439
+ <li>查看版本<code>confluence version</code></li>
440
+ <li>列出命令<code>confluence list</code></li>
441
+ <li>查看参数<code>confluence help uploadMarkdown</code></li>
442
+ <li>初始化配置<code>confluence initConfluence --url https://confluence.example.com --pat token</code></li>
443
+ </ul>
444
+ </div>
445
+ <div class="section">
446
+ <h2>角色入口</h2>
447
+ <ul>
448
+ <li>完整能力<code>confluence --role full list</code></li>
449
+ <li>只读入口<code>confluence-reader list</code></li>
450
+ <li>写入入口<code>confluence-writer list</code></li>
451
+ <li>内联角色<code>confluence --role=reader searchContent --limit 10</code></li>
452
+ </ul>
453
+ </div>
454
+ <div class="section">
455
+ <h2>内容 / 评论</h2>
456
+ <ul>
457
+ <li>页面详情<code>confluence getContent --id 123456</code></li>
458
+ <li>子页面<code>confluence getPageChildren --id 123456 --type page</code></li>
459
+ <li>查评论<code>confluence getComments --id 123456</code></li>
460
+ <li>加评论<code>confluence addComment --id 123456 --text "已更新" --confirm true</code></li>
461
+ <li>删除页面<code>confluence deleteContent --id 123456 --confirm true</code></li>
462
+ </ul>
463
+ </div>
464
+ <div class="section">
465
+ <h2>标签 / 附件</h2>
466
+ <ul>
467
+ <li>查看标签<code>confluence getLabels --id 123456</code></li>
468
+ <li>添加标签<code>confluence addLabels --id 123456 --labels '["api","docs"]' --confirm true</code></li>
469
+ <li>列出附件<code>confluence listAttachments --id 123456</code></li>
470
+ <li>上传附件<code>confluence uploadAttachment --id 123456 --file docs/a.png --confirm true</code></li>
471
+ <li>下载附件<code>confluence downloadAttachment --id 123456 --attachmentId att123</code></li>
472
+ </ul>
473
+ </div>
474
+ <div class="section">
475
+ <h2>发布 / 转换</h2>
476
+ <ul>
477
+ <li>Markdown 转 wiki<code>confluence convertMarkdownToWiki --file docs/page.md</code></li>
478
+ <li>生成 mark metadata<code>confluence generateMarkMetadata --file docs/page.md --space DEV</code></li>
479
+ <li>上传 Markdown<code>confluence uploadMarkdown --file docs/page.md --space DEV --toc --confirm true</code></li>
480
+ <li>上传 HTML<code>confluence uploadHtml --file dist/page.html --space DEV --confirm true</code></li>
481
+ </ul>
482
+ </div>
483
+ <div class="section">
484
+ <h2>REST / 调试</h2>
485
+ <ul>
486
+ <li>列出 content 端点<code>confluence listRestApis --group content --limit 20</code></li>
487
+ <li>只看 GET<code>confluence listRestApis --method GET --limit 20</code></li>
488
+ <li>调用 GET 端点<code>confluence callRestApi --method GET --path '/content/{id}' --pathParams '{"id":"123456"}'</code></li>
489
+ <li>调用写端点<code>confluence callRestApi --method POST --path '/content' --body '{"type":"page"}' --confirm true</code></li>
490
+ </ul>
491
+ </div>
492
+ <div class="section">
493
+ <h2>工程命令</h2>
494
+ <ul>
495
+ <li>类型检查<code>pnpm typecheck</code></li>
496
+ <li>运行测试<code>pnpm test</code></li>
497
+ <li>构建产物<code>pnpm build</code></li>
498
+ <li>发版前 smoke<code>pnpm release:smoke-query --dry-run</code></li>
499
+ </ul>
500
+ </div>
501
+ <div class="section">
502
+ <h2>环境变量</h2>
503
+ <ul>
504
+ <li>服务地址<code>export CONFLUENCE_URL="https://confluence.example.com"</code></li>
505
+ <li>PAT 凭证<code>export CONFLUENCE_PAT="your-personal-access-token"</code></li>
506
+ <li>自定义 API 地址<code>export CONFLUENCE_API_BASE_URL="https://confluence.example.com/rest/api"</code></li>
507
+ <li>禁用真实写入<code>export CONFLUENCE_DISABLE_WRITE=true</code></li>
508
+ <li>关闭更新探针<code>export CONFLUENCE_SKIP_UPDATE_CHECK=true</code></li>
509
+ </ul>
510
+ </div>
511
+ </section>
512
+
513
+ <footer>写操作默认受保护;真实写入仍需显式传入 <code>confirm=true</code>,也可以用 <code>CONFLUENCE_DISABLE_WRITE=true</code> 全局禁用。</footer>
514
+ </main>
515
+ <script>
516
+ document.querySelectorAll('li code').forEach((code) => {
517
+ if (code.parentElement?.classList.contains('copy-row')) return;
518
+ const row = document.createElement('div');
519
+ row.className = 'copy-row';
520
+ const copy = document.createElement('button');
521
+ copy.className = 'copy';
522
+ copy.type = 'button';
523
+ copy.textContent = '复制';
524
+ copy.dataset.copy = code.textContent.trim();
525
+ code.before(row);
526
+ row.append(code, copy);
527
+ });
528
+
529
+ async function copyText(text) {
530
+ if (navigator.clipboard?.writeText) {
531
+ try {
532
+ await navigator.clipboard.writeText(text);
533
+ return true;
534
+ } catch (error) {
535
+ void error;
536
+ }
537
+ }
538
+
539
+ const textarea = document.createElement('textarea');
540
+ textarea.value = text;
541
+ textarea.setAttribute('readonly', '');
542
+ textarea.style.position = 'fixed';
543
+ textarea.style.left = '-9999px';
544
+ document.body.appendChild(textarea);
545
+ textarea.select();
546
+ const ok = document.execCommand('copy');
547
+ textarea.remove();
548
+ return ok;
549
+ }
550
+
551
+ document.querySelectorAll('[data-copy]').forEach((button) => {
552
+ button.addEventListener('click', async () => {
553
+ const text = button.textContent;
554
+ const ok = await copyText(button.dataset.copy);
555
+ button.textContent = ok ? '已复制' : '复制失败';
556
+ window.setTimeout(() => { button.textContent = text; }, 1200);
557
+ });
558
+ });
559
+
560
+ const wikiQuery = document.querySelector('#wiki-query');
561
+ const wikiStatus = document.querySelector('#wiki-status');
562
+ const commandSections = [...document.querySelectorAll('.grid .section')].map((section) => {
563
+ const items = [...section.querySelectorAll('li')].map((item) => ({
564
+ element: item,
565
+ text: item.textContent.toLowerCase(),
566
+ }));
567
+ return {
568
+ element: section,
569
+ text: section.textContent.toLowerCase(),
570
+ items,
571
+ };
572
+ });
573
+
574
+ function filterWiki() {
575
+ const query = wikiQuery.value.trim().toLowerCase();
576
+ let visibleItems = 0;
577
+ let visibleSections = 0;
578
+
579
+ commandSections.forEach((section) => {
580
+ let sectionHasMatch = false;
581
+ section.items.forEach((item) => {
582
+ const itemMatch = !query || item.text.includes(query);
583
+ item.element.hidden = !itemMatch;
584
+ if (itemMatch) {
585
+ sectionHasMatch = true;
586
+ visibleItems += 1;
587
+ }
588
+ });
589
+
590
+ const sectionMatch = !query || section.text.includes(query);
591
+ section.element.hidden = !(sectionHasMatch || sectionMatch);
592
+ if (!section.element.hidden) visibleSections += 1;
593
+ });
594
+
595
+ if (!query) {
596
+ wikiStatus.textContent = '输入关键词后过滤下方命令。';
597
+ return;
598
+ }
599
+
600
+ wikiStatus.textContent = visibleItems
601
+ ? `找到 ${visibleItems} 条命令,分布在 ${visibleSections} 个分类。`
602
+ : '没有匹配命令,可以换个关键词。';
603
+ }
604
+
605
+ wikiQuery.addEventListener('input', filterWiki);
606
+ </script>
607
+ </body>
608
+ </html>
@@ -0,0 +1,41 @@
1
+ # Release
2
+
3
+ ## 发布前检查
4
+
5
+ ```bash
6
+ pnpm typecheck
7
+ pnpm test
8
+ pnpm build
9
+ pnpm release:smoke-query --dry-run
10
+ ```
11
+
12
+ 如需连接真实 Confluence 做 smoke 查询,先设置:
13
+
14
+ ```bash
15
+ CONFLUENCE_SMOKE_CONTENT_ID=123456
16
+ CONFLUENCE_SMOKE_SPACE=DEV
17
+ CONFLUENCE_SMOKE_TITLE="API Guide"
18
+ ```
19
+
20
+ ## 发布流程
21
+
22
+ ```bash
23
+ git tag v0.1.0
24
+ git push origin v0.1.0
25
+ ```
26
+
27
+ `.github/workflows/publish.yml` 会校验 tag 版本与 `package.json` 一致,然后执行:
28
+
29
+ - `pnpm install --frozen-lockfile`
30
+ - `pnpm check`
31
+ - `npm publish --provenance --access public`
32
+
33
+ ## 安全约定
34
+
35
+ - 真实写操作必须显式传 `--confirm true`
36
+ - `CONFLUENCE_DISABLE_WRITE=true` 可全局禁用真实写操作
37
+ - 发布前优先跑 `pnpm release:smoke-query --dry-run`
38
+
39
+ ## 文档发布
40
+
41
+ `docs/index.html` 由 `.github/workflows/pages.yml` 发布到 GitHub Pages。更新 README、skill reference 或 release 文档后,可先本地打开 `docs/index.html` 检查命令速查页。