skill-family-doc-render 0.2.1 → 0.4.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.
- package/CHANGELOG.md +42 -0
- package/README.md +149 -37
- package/package.json +3 -1
- package/schemas/pages.schema.json +76 -18
- package/schemas/public-release.schema.json +36 -0
- package/schemas/site-coverage-lock.schema.json +28 -0
- package/scripts/lib/markdown-v1.mjs +213 -0
- package/scripts/lib/rendered-links.mjs +124 -0
- package/scripts/lib/svg-safety.mjs +45 -0
- package/scripts/render-public-site.mjs +526 -47
- package/templates/editorial/README.md +129 -0
- package/templates/editorial/assets/mark.svg +1 -0
- package/templates/editorial/assets/site.js +220 -0
- package/templates/editorial/assets/style.css +330 -0
- package/templates/editorial/index.mjs +283 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# 变更日志
|
|
2
2
|
|
|
3
|
+
## 0.4.0 - 2026-09-07
|
|
4
|
+
|
|
5
|
+
### 新增
|
|
6
|
+
|
|
7
|
+
- 增加显式成对的 `site.format: markdown-v1` 与 `site.template: editorial`。受限 Markdown
|
|
8
|
+
由精确依赖 `marked@18.0.11` 分词,再经过本包的结构、链接和锚点校验;包内模板生成
|
|
9
|
+
完整 HTML、分组目录、静态搜索、交互与首尾不循环的教程翻页。
|
|
10
|
+
- 增加包内 `editorial` 模板的 CSS、JavaScript 和 SVG 图标。新模式不读取项目自有主题
|
|
11
|
+
CSS 或 JavaScript,同一冻结输入会产生确定的页面及资源字节。
|
|
12
|
+
- 增加站内 SVG 主动内容检查。脚本、事件属性、`foreignObject`、DTD/实体声明,以及
|
|
13
|
+
外部或 data 资源会在输出替换前被拒绝;SVG 不内联。
|
|
14
|
+
- 增加只读的 `--check-project --repo <name>`,依次检查输入与公开安全、Markdown 机械
|
|
15
|
+
合同、覆盖状态、渲染与基线、内部链接和资源,并在失败时输出可复制的恢复提示。
|
|
16
|
+
|
|
17
|
+
### 安全与兼容
|
|
18
|
+
|
|
19
|
+
- `site.format` 与 `site.template` 同时缺省时继续使用完整 HTML 注入。该路径只供既有
|
|
20
|
+
消费者兼容,不获得新主题;新建站点使用 `markdown-v1` 与 `editorial`。
|
|
21
|
+
- `--check-project` 必须与单个 `--repo` 一起使用,不与其他模式组合。全程只读;状态
|
|
22
|
+
问题返回 1,输入或工具问题返回 2。
|
|
23
|
+
|
|
24
|
+
## 0.3.0 - 2026-09-07
|
|
25
|
+
|
|
26
|
+
### 新增
|
|
27
|
+
|
|
28
|
+
- 增加 `site.coverage` 和最小 `site-coverage-lock.json`,记录已审阅产品输入的文件摘要、
|
|
29
|
+
聚合摘要,以及启用 artifact-graph 时的版本锁摘要。
|
|
30
|
+
- 增加只读的 `--status --repo <name>` 和只更新覆盖快照的
|
|
31
|
+
`--refresh-coverage --repo <name>`。状态命令会报告覆盖提交、当前摘要、变化文件、
|
|
32
|
+
权威版本值和建议执行的 Git diff 命令。
|
|
33
|
+
- 状态命令从 `repo.source` 发现所属 Git 仓库。目标位于外层工作区中的独立内层仓库时,
|
|
34
|
+
覆盖提交、变化路径和 diff 建议只使用内层仓库历史。
|
|
35
|
+
- 增加 `site.versionSources`。渲染器从收容于 `repo.source` 的 JSON 文件和 JSON Pointer
|
|
36
|
+
读取版本值,版本源文件自动加入覆盖输入。
|
|
37
|
+
|
|
38
|
+
### 安全与兼容
|
|
39
|
+
|
|
40
|
+
- 覆盖输入拒绝绝对路径、越界路径、空匹配和符号链接逃逸;覆盖锁始终排除自身,
|
|
41
|
+
避免形成摘要循环。
|
|
42
|
+
- 保留现有静态 token 和按仓库名派生版本 token 的兼容行为;同名
|
|
43
|
+
`site.versionSources` 取值优先。
|
|
44
|
+
|
|
3
45
|
## 0.2.1 - 2026-09-06
|
|
4
46
|
|
|
5
47
|
### 变更
|
package/README.md
CHANGED
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
Config-driven GitHub Pages knowledge-site renderer for skill-family projects (multi-repo capable).
|
|
4
4
|
|
|
5
|
-
Reads `public-release.json` from the current working directory
|
|
6
|
-
`site` field from its site source directory to its target directory (typically `docs/`)
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
Reads `public-release.json` from the current working directory and renders every repo carrying a
|
|
6
|
+
`site` field from its site source directory to its target directory (typically `docs/`). New
|
|
7
|
+
sites explicitly select `format: "markdown-v1"` and `template: "editorial"`; the renderer parses
|
|
8
|
+
restricted Markdown and supplies the complete page structure, navigation, theme, interactions,
|
|
9
|
+
and search data. Sites without `format` keep the legacy complete-HTML injection path for
|
|
10
|
+
compatibility. Both paths replace version placeholders, write `.nojekyll` and a
|
|
11
|
+
tree baseline (`site-baseline.json`), and run a content-level leak scan over every output file
|
|
9
12
|
(pages **and** assets) before any target change. Render, scan, baseline computation and the
|
|
10
13
|
`--assert-git` preflight all finish before the target is changed, so failures in those steps
|
|
11
14
|
leave the existing target untouched. The final directory commit uses Foundation's fixed-set
|
|
@@ -13,41 +16,69 @@ publication APIs. A failure before commit removes staging and leaves the existin
|
|
|
13
16
|
untouched. After commit, or when publication is indeterminate, staging or displaced data may
|
|
14
17
|
remain for diagnosis; the renderer does not guess or roll back.
|
|
15
18
|
|
|
19
|
+
> **Version boundary:** this source tree is version `0.4.0`. Verify that exact version in the
|
|
20
|
+
> official npm registry before treating it as installable. Version 0.4.0 adds `markdown-v1`, the
|
|
21
|
+
> `editorial` template, and `--check-project` on top of the 0.3.0 coverage workflow.
|
|
22
|
+
|
|
16
23
|
## Install
|
|
17
24
|
|
|
25
|
+
After confirming availability, install this release with an exact version:
|
|
26
|
+
|
|
18
27
|
```sh
|
|
19
|
-
npm install skill-family-doc-render@0.
|
|
28
|
+
npm install --save-exact skill-family-doc-render@0.4.0
|
|
20
29
|
```
|
|
21
30
|
|
|
22
31
|
Requires Node.js `>=22.22.2 <23` (aligned with the skill-family foundation packages).
|
|
23
32
|
|
|
24
|
-
0.
|
|
25
|
-
`skill-family-contracts@0.18.0`, `skill-family-harness-node@0.18.0`
|
|
26
|
-
|
|
33
|
+
Version 0.4.0 has exact runtime dependencies on `marked@18.0.11`,
|
|
34
|
+
`skill-family-contracts@0.18.0`, and `skill-family-harness-node@0.18.0`. `marked` supplies the
|
|
35
|
+
Markdown lexer; the renderer applies its own restricted-format validation before passing semantic
|
|
36
|
+
content to the template. The workspace profile check separately uses
|
|
37
|
+
`skill-family-engineering-kit@0.18.0`.
|
|
27
38
|
The 0.2.0 baseline format and exit-code changes are breaking changes; existing 0.1.x users
|
|
28
39
|
must re-render their baseline before using `--check`. See the changelog for the full migration
|
|
29
40
|
notes.
|
|
30
41
|
|
|
31
42
|
## CLI
|
|
32
43
|
|
|
44
|
+
Use the exact 0.4.0 CLI for rendering, checks, coverage maintenance, and the Git index assertion:
|
|
45
|
+
|
|
33
46
|
```sh
|
|
34
47
|
# render all repos with a site field (writes to disk)
|
|
35
|
-
npx skill-family-doc-render@0.
|
|
48
|
+
npx skill-family-doc-render@0.4.0
|
|
36
49
|
|
|
37
50
|
# drift check only: compare in-memory render against committed site-baseline.json, write nothing
|
|
38
|
-
npx skill-family-doc-render@0.
|
|
51
|
+
npx skill-family-doc-render@0.4.0 --check
|
|
39
52
|
|
|
40
53
|
# render / check a single repo by name
|
|
41
|
-
npx skill-family-doc-render@0.
|
|
54
|
+
npx skill-family-doc-render@0.4.0 --repo <name>
|
|
42
55
|
|
|
43
56
|
# additionally assert every rendered file is tracked in the git index
|
|
44
|
-
npx skill-family-doc-render@0.
|
|
57
|
+
npx skill-family-doc-render@0.4.0 --assert-git
|
|
58
|
+
|
|
59
|
+
# inspect or refresh the reviewed product-input snapshot
|
|
60
|
+
npx skill-family-doc-render@0.4.0 --status --repo <name>
|
|
61
|
+
npx skill-family-doc-render@0.4.0 --refresh-coverage --repo <name>
|
|
62
|
+
npx skill-family-doc-render@0.4.0 --check-project --repo <name>
|
|
45
63
|
```
|
|
46
64
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
65
|
+
The current directory must be the workspace that owns `public-release.json`. From this package's
|
|
66
|
+
source checkout, `node bin/skill-family-doc-render.mjs` is the equivalent local CLI entry.
|
|
67
|
+
|
|
68
|
+
`--check-project` requires exactly one `--repo <name>`. It cannot be combined with `--check`,
|
|
69
|
+
`--status`, `--refresh-coverage`, `--assert-git`, or `--help`. It checks input and public-content
|
|
70
|
+
safety, the mechanical Markdown contract, coverage freshness, the in-memory render and baseline,
|
|
71
|
+
then internal links and resources. It writes nothing. A failure identifies the repo,
|
|
72
|
+
`public-release.json`, the reason, and a copyable `skill-family-docs-render-site` recovery prompt.
|
|
73
|
+
|
|
74
|
+
Exit codes: `0` success; `1` drift/status class — `--check` drift, leak-scan hit, `--assert-git`
|
|
75
|
+
missing files, missing/corrupt render baseline, or missing/stale coverage snapshot; `2`
|
|
76
|
+
configuration/tool class — missing/invalid `public-release.json` or `pages.json`, JSON parse
|
|
77
|
+
failures, unreplaced `@TOKEN@` placeholders, invalid `--repo` usage, invalid coverage inputs, or
|
|
78
|
+
Git failure (the message includes the JSON field path). `--check-project` uses the same classes:
|
|
79
|
+
public-safety, coverage, render, link, or resource findings return `1`; invalid input,
|
|
80
|
+
configuration, or tool errors return `2`.
|
|
81
|
+
When several repos are
|
|
51
82
|
rendered in one run, each repo is isolated: a failure in one does not stop the others, and the
|
|
52
83
|
run ends with a summary of successes/failures plus a non-zero exit (2 if any failure was
|
|
53
84
|
configuration-class, otherwise 1).
|
|
@@ -56,7 +87,8 @@ configuration-class, otherwise 1).
|
|
|
56
87
|
|
|
57
88
|
The config file lives at the workspace root (resolved from `process.cwd()`). It is validated
|
|
58
89
|
against `schemas/public-release.schema.json` (JSON Schema 2020-12, strict policy) before
|
|
59
|
-
anything runs.
|
|
90
|
+
anything runs. The paired `format` and `template` fields in the example below require version
|
|
91
|
+
0.4.0 or later.
|
|
60
92
|
|
|
61
93
|
```json
|
|
62
94
|
{
|
|
@@ -72,6 +104,23 @@ anything runs.
|
|
|
72
104
|
"dir": "site-src",
|
|
73
105
|
"target": "docs",
|
|
74
106
|
"pages": "pages.json",
|
|
107
|
+
"format": "markdown-v1",
|
|
108
|
+
"template": "editorial",
|
|
109
|
+
"coverage": {
|
|
110
|
+
"lock": "site-coverage-lock.json",
|
|
111
|
+
"inputs": ["package.json", "src/**", "schemas/**"]
|
|
112
|
+
},
|
|
113
|
+
"versionSources": {
|
|
114
|
+
"@COMPONENT_VERSION@": {
|
|
115
|
+
"source": "package.json",
|
|
116
|
+
"pointer": "/version"
|
|
117
|
+
},
|
|
118
|
+
"@COMPONENT_TAG@": {
|
|
119
|
+
"source": "package.json",
|
|
120
|
+
"pointer": "/version",
|
|
121
|
+
"prefix": "component-v"
|
|
122
|
+
}
|
|
123
|
+
},
|
|
75
124
|
"tokens": { "@CUSTOM_NOTE@": "any static placeholder" }
|
|
76
125
|
}
|
|
77
126
|
}
|
|
@@ -83,27 +132,60 @@ anything runs.
|
|
|
83
132
|
|
|
84
133
|
- Only repos with a `site` field are rendered; `--repo <name>` selects one by `name`
|
|
85
134
|
(`--repo` without a valid value is an error, never a silent "render all").
|
|
86
|
-
- `site.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
`
|
|
135
|
+
- `site.format` and `site.template` are paired. New sites use only `markdown-v1` and `editorial`.
|
|
136
|
+
Omitting both selects the legacy HTML compatibility path.
|
|
137
|
+
- `site.pages` points to a manifest validated against `schemas/pages.schema.json`. A
|
|
138
|
+
`markdown-v1` manifest declares site metadata, navigation groups, and each page's `id`, title,
|
|
139
|
+
reader role, layout kind, group, unique order, and `inPager` state. The page `id` is restricted
|
|
140
|
+
to `[A-Za-z0-9][A-Za-z0-9_-]*`.
|
|
90
141
|
- `forbiddenPublicPaths` / `privateLiterals` append project-specific literals to the leak scan.
|
|
142
|
+
- `site.coverage` declares reviewed product inputs relative to `repo.source`. Each input accepts
|
|
143
|
+
`*` and `**` glob syntax and must match at least one file after the coverage lock itself is
|
|
144
|
+
excluded.
|
|
145
|
+
- `site.versionSources` maps a token to an existing JSON file and an
|
|
146
|
+
[RFC 6901 JSON Pointer](https://www.rfc-editor.org/rfc/rfc6901). `prefix` and `suffix` format
|
|
147
|
+
the scalar value without copying the version into configuration. Every referenced JSON file
|
|
148
|
+
automatically joins the coverage inputs.
|
|
149
|
+
|
|
150
|
+
## Input formats
|
|
151
|
+
|
|
152
|
+
### Restricted Markdown and the editorial template
|
|
153
|
+
|
|
154
|
+
Each `markdown-v1` page is `site.dir/<id>.md`, with an exact one-to-one match to the manifest.
|
|
155
|
+
The format supports paragraphs, level 2–4 headings, ordered and unordered lists, tables, inline
|
|
156
|
+
links and emphasis, fenced code with a language, `NOTE` / `TIP` / `WARNING` callouts, and local
|
|
157
|
+
SVG images. The manifest supplies the only H1. A heading may end with `{#stable-id}`; otherwise a
|
|
158
|
+
deterministic slug is generated. Raw HTML, MDX, task or nested lists, indented or unlabelled code,
|
|
159
|
+
ordinary blockquotes, and arbitrary attributes are rejected before output replacement.
|
|
160
|
+
|
|
161
|
+
The editorial template owns HTML, CSS, JavaScript, icons, navigation, search, and the non-circular
|
|
162
|
+
tutorial pager. Projects using `markdown-v1` do not supply theme CSS or JavaScript. Project images
|
|
163
|
+
are limited to contained SVG files. Before rendering, SVG safety checks reject scripts, event
|
|
164
|
+
attributes, `foreignObject`, DTD/entity declarations, and external or data resources; SVG remains
|
|
165
|
+
an external image and is never inlined.
|
|
91
166
|
|
|
92
|
-
|
|
167
|
+
### Legacy HTML compatibility
|
|
93
168
|
|
|
94
|
-
|
|
169
|
+
When `format` and `template` are omitted, source pages remain complete HTML and use three comment
|
|
170
|
+
injection points:
|
|
95
171
|
|
|
96
172
|
- `<!--NAV-->` — table-of-contents nav (active page gets `class="active"`)
|
|
97
|
-
- `<!--PAGER-->` — circular prev/next pager
|
|
173
|
+
- `<!--PAGER-->` — legacy circular prev/next pager
|
|
98
174
|
- `<!--FOOTER-->` — site footer (owner + license)
|
|
99
175
|
|
|
176
|
+
Legacy HTML remains available for existing consumers, but it does not receive the editorial
|
|
177
|
+
theme. New sites should not start on this compatibility path.
|
|
178
|
+
|
|
179
|
+
## Version placeholders
|
|
180
|
+
|
|
100
181
|
Version tokens are derived automatically from the repo's `package.json` version and `name`
|
|
101
182
|
(uppercased, non-alphanumeric runs collapsed to `_`):
|
|
102
183
|
|
|
103
184
|
- `@{NAME}_TAG@` — e.g. `my-project` → `@MY_PROJECT_TAG@` = `tagPrefix` + version
|
|
104
185
|
- `@{NAME}_VERSION@` — the bare version
|
|
105
186
|
|
|
106
|
-
`site.tokens` adds
|
|
187
|
+
`site.tokens` adds non-version static placeholder replacements. A token also declared in
|
|
188
|
+
`site.versionSources` always takes its value from the JSON source. If a rendered page still
|
|
107
189
|
contains an unreplaced `@TOKEN@` (`@[A-Z0-9_]+@`), the run fails fast (exit 2) naming the
|
|
108
190
|
tokens and the file — placeholder typos never slip into the published site silently.
|
|
109
191
|
|
|
@@ -111,9 +193,32 @@ If a repo has no `package.json` (or no valid `version`), the version falls back
|
|
|
111
193
|
with a loud `WARNING` on stderr, because that fallback is baked into the output and the
|
|
112
194
|
baseline; a malformed `package.json` fails fast (exit 2).
|
|
113
195
|
|
|
196
|
+
## Coverage status
|
|
197
|
+
|
|
198
|
+
`--refresh-coverage --repo <name>` expands `site.coverage.inputs`, adds every configured version
|
|
199
|
+
source, computes the file digests and closure digest, then atomically writes the declared coverage
|
|
200
|
+
lock. It does not render the site or modify Git. The lock contains only:
|
|
201
|
+
|
|
202
|
+
- `sha256`: the Foundation resource-closure digest;
|
|
203
|
+
- `inputs`: sorted relative file paths and their byte digests;
|
|
204
|
+
- `artifactGraphVersionLockSha256`: the current `artifacts/traceability-version-lock.json`
|
|
205
|
+
digest when the repository contains `artifact-graph.config.yaml`.
|
|
206
|
+
|
|
207
|
+
`--status --repo <name>` recomputes the same facts without writing. It prints the last commit that
|
|
208
|
+
changed the coverage lock, the current and recorded closure digests, changed covered files,
|
|
209
|
+
current values from `site.versionSources`, and suggested `git diff` commands. A matching snapshot
|
|
210
|
+
returns `0`; a missing or stale snapshot returns `1`. A site without `coverage`, a path escape, an
|
|
211
|
+
empty glob, an invalid JSON pointer, a symlink escape, or a Git failure returns `2`.
|
|
212
|
+
|
|
213
|
+
Coverage paths are relative to `repo.source`. Absolute paths, lexical traversal, realpath escape,
|
|
214
|
+
and symlink escape are rejected through Foundation path containment. The coverage lock is always
|
|
215
|
+
excluded from its own inputs, avoiding a digest cycle. `--status` requires a Git repository with a
|
|
216
|
+
resolvable `HEAD`, because its report includes committed, staged, unstaged, and covered untracked
|
|
217
|
+
changes.
|
|
218
|
+
|
|
114
219
|
## Leak scan
|
|
115
220
|
|
|
116
|
-
Every output file — rendered pages **and** copied assets (`.html`/`.css`/`.js`/`.svg`) — is
|
|
221
|
+
Every output file — rendered pages **and** copied or template assets (`.html`/`.css`/`.js`/`.svg`) — is
|
|
117
222
|
scanned **before** any write (`scripts/lib/leak-scan.mjs`). The scanner decodes HTML entities
|
|
118
223
|
(two passes, defeating double encoding), JS escape sequences and URL percent-encoding first,
|
|
119
224
|
then matches case-insensitively against built-in private literals (absolute home paths) and
|
|
@@ -145,36 +250,41 @@ The digest is a deterministic set-level sha256 over the contained resources.
|
|
|
145
250
|
|
|
146
251
|
## Foundation dependencies
|
|
147
252
|
|
|
148
|
-
This package is a thin domain layer over the skill-family foundation
|
|
149
|
-
|
|
253
|
+
This package is a thin domain layer over the skill-family foundation. In addition to the two
|
|
254
|
+
Foundation packages below, it uses exact `marked@18.0.11` for Markdown tokenization:
|
|
150
255
|
|
|
151
256
|
- [`skill-family-harness-node`](https://github.com/ifoohoo/skill-family-harness-node) — all file
|
|
152
257
|
reads go through `resolveContained` / `readFileContained` (path traversal, symlink and realpath
|
|
153
258
|
escapes rejected), per-file digests use `digestBytes`, the tree baseline is computed with
|
|
154
|
-
`computeResourceClosure`. Output is staged in a
|
|
155
|
-
parent, with contained writes through
|
|
259
|
+
`computeResourceClosure`, and coverage locks use `writeFileAtomic`. Output is staged in a
|
|
260
|
+
sibling directory under the target's canonical parent, with contained writes through
|
|
261
|
+
`writeFileAtomic`. A new target uses
|
|
156
262
|
`createFixedSetPublicationManifest` followed by `publishFixedSet`; an existing target uses
|
|
157
263
|
`replaceFixedSetAtomic`. Staging is removed after success or a clearly pre-commit failure;
|
|
158
264
|
post-commit or indeterminate failures may retain it for diagnosis. These APIs do not add a
|
|
159
265
|
broader atomicity guarantee than Foundation provides.
|
|
160
266
|
- [`skill-family-contracts`](https://github.com/ifoohoo/skill-family-contracts) —
|
|
161
267
|
`validateDocument` (JSON Schema 2020-12, strict policy) validates `public-release.json`,
|
|
162
|
-
`pages.json` and `site-
|
|
268
|
+
`pages.json`, `site-baseline.json`, and `site-coverage-lock.json`; validation failure aborts
|
|
269
|
+
with exit code 2.
|
|
163
270
|
|
|
164
271
|
## License
|
|
165
272
|
|
|
166
273
|
Apache-2.0
|
|
167
274
|
|
|
168
275
|
<!-- release-skill:capability:safe-first-command -->
|
|
169
|
-
> **Start here:**
|
|
170
|
-
>
|
|
276
|
+
> **Start here:** run `npx skill-family-doc-render@0.4.0 --check-project --repo <name>` after
|
|
277
|
+
> confirming that exact release in the official registry. From a local checkout, use
|
|
278
|
+
> `node bin/skill-family-doc-render.mjs --check-project --repo <name>`. The check is read-only:
|
|
171
279
|
> it renders in memory, compares against the committed `site-baseline.json`, writes
|
|
172
280
|
> nothing and touches no network or credentials. The CLI performs no Git writes; only an
|
|
173
281
|
> explicit `--assert-git` performs a read-only query of the Git index.
|
|
174
282
|
|
|
175
283
|
<!-- release-skill:capability:external-write-boundary -->
|
|
176
|
-
> **External write boundary:**
|
|
177
|
-
> staging directory, both within the target's canonical parent, with contained path checks.
|
|
284
|
+
> **External write boundary:** rendering writes the declared target and a controlled sibling
|
|
285
|
+
> staging directory, both within the target's canonical parent, with contained path checks. An
|
|
286
|
+
> explicit `--refresh-coverage` writes only the declared coverage lock through an atomic file
|
|
287
|
+
> replacement. `--status`, `--check`, and `--check-project` write nothing.
|
|
178
288
|
> Render, scan, baseline and `--assert-git` preflight failures happen before target changes.
|
|
179
289
|
> Staging is removed after success or a clearly pre-commit failure; post-commit or
|
|
180
290
|
> indeterminate failures may retain it to preserve diagnosable state.
|
|
@@ -184,7 +294,9 @@ Apache-2.0
|
|
|
184
294
|
|
|
185
295
|
## Minimal example
|
|
186
296
|
|
|
297
|
+
Display help and run a read-only project check:
|
|
298
|
+
|
|
187
299
|
```sh
|
|
188
|
-
npx skill-family-doc-render@0.
|
|
189
|
-
npx skill-family-doc-render@0.
|
|
300
|
+
npx skill-family-doc-render@0.4.0 --help
|
|
301
|
+
npx skill-family-doc-render@0.4.0 --check-project --repo <name>
|
|
190
302
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skill-family-doc-render",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Config-driven GitHub Pages knowledge-site renderer for skill-family projects (multi-repo capable).",
|
|
5
5
|
"author": "广州市风荷科技有限公司",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"bin",
|
|
16
16
|
"scripts",
|
|
17
17
|
"schemas",
|
|
18
|
+
"templates",
|
|
18
19
|
"README.md",
|
|
19
20
|
"CHANGELOG.md",
|
|
20
21
|
"LICENSE"
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
"render:site:check": "node bin/skill-family-doc-render.mjs --check"
|
|
26
27
|
},
|
|
27
28
|
"dependencies": {
|
|
29
|
+
"marked": "18.0.11",
|
|
28
30
|
"skill-family-contracts": "0.18.0",
|
|
29
31
|
"skill-family-harness-node": "0.18.0"
|
|
30
32
|
}
|
|
@@ -2,24 +2,82 @@
|
|
|
2
2
|
"$id": "https://github.com/ifoohoo/skill-family-doc-render/schemas/pages.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"title": "pages.json",
|
|
5
|
-
"description": "
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
5
|
+
"description": "旧 HTML 与 markdown-v1 共用的页面清单合同。渲染器按 public-release.json 中的 format 选择对应语义。",
|
|
6
|
+
"oneOf": [
|
|
7
|
+
{ "$ref": "#/$defs/legacy" },
|
|
8
|
+
{ "$ref": "#/$defs/markdownV1" }
|
|
9
|
+
],
|
|
10
|
+
"$defs": {
|
|
11
|
+
"safeId": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9_-]*$" },
|
|
12
|
+
"legacy": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"additionalProperties": false,
|
|
15
|
+
"required": ["pages"],
|
|
16
|
+
"properties": {
|
|
17
|
+
"site": { "type": "object" },
|
|
18
|
+
"pages": {
|
|
19
|
+
"type": "array",
|
|
20
|
+
"minItems": 1,
|
|
21
|
+
"items": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"additionalProperties": false,
|
|
24
|
+
"required": ["id", "title", "order"],
|
|
25
|
+
"properties": {
|
|
26
|
+
"id": { "$ref": "#/$defs/safeId" },
|
|
27
|
+
"title": { "type": "string", "minLength": 1 },
|
|
28
|
+
"order": { "type": "integer" },
|
|
29
|
+
"inPager": { "type": "boolean" }
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"markdownV1": {
|
|
36
|
+
"type": "object",
|
|
37
|
+
"additionalProperties": false,
|
|
38
|
+
"required": ["site", "groups", "pages"],
|
|
39
|
+
"properties": {
|
|
40
|
+
"site": {
|
|
41
|
+
"type": "object",
|
|
42
|
+
"additionalProperties": false,
|
|
43
|
+
"required": ["title", "description", "productKind"],
|
|
44
|
+
"properties": {
|
|
45
|
+
"title": { "type": "string", "minLength": 1 },
|
|
46
|
+
"description": { "type": "string", "minLength": 1 },
|
|
47
|
+
"productKind": { "enum": ["plugin", "library"] }
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"groups": {
|
|
51
|
+
"type": "array",
|
|
52
|
+
"minItems": 1,
|
|
53
|
+
"items": {
|
|
54
|
+
"type": "object",
|
|
55
|
+
"additionalProperties": false,
|
|
56
|
+
"required": ["id", "title"],
|
|
57
|
+
"properties": {
|
|
58
|
+
"id": { "$ref": "#/$defs/safeId" },
|
|
59
|
+
"title": { "type": "string", "minLength": 1 }
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"pages": {
|
|
64
|
+
"type": "array",
|
|
65
|
+
"minItems": 1,
|
|
66
|
+
"items": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"additionalProperties": false,
|
|
69
|
+
"required": ["id", "title", "role", "kind", "group", "order", "inPager"],
|
|
70
|
+
"properties": {
|
|
71
|
+
"id": { "$ref": "#/$defs/safeId" },
|
|
72
|
+
"title": { "type": "string", "minLength": 1 },
|
|
73
|
+
"navTitle": { "type": "string", "minLength": 1 },
|
|
74
|
+
"role": { "enum": ["overview", "setup", "first-success", "maintenance", "release", "troubleshooting", "upgrade", "reference"] },
|
|
75
|
+
"kind": { "enum": ["home", "task", "reference", "troubleshooting"] },
|
|
76
|
+
"group": { "$ref": "#/$defs/safeId" },
|
|
77
|
+
"order": { "type": "integer" },
|
|
78
|
+
"inPager": { "type": "boolean" }
|
|
79
|
+
}
|
|
80
|
+
}
|
|
23
81
|
}
|
|
24
82
|
}
|
|
25
83
|
}
|
|
@@ -29,12 +29,48 @@
|
|
|
29
29
|
"dir": { "type": "string", "minLength": 1 },
|
|
30
30
|
"target": { "type": "string", "minLength": 1 },
|
|
31
31
|
"pages": { "type": "string", "minLength": 1 },
|
|
32
|
+
"format": { "const": "markdown-v1" },
|
|
33
|
+
"template": { "const": "editorial" },
|
|
34
|
+
"coverage": {
|
|
35
|
+
"type": "object",
|
|
36
|
+
"additionalProperties": false,
|
|
37
|
+
"required": ["lock", "inputs"],
|
|
38
|
+
"properties": {
|
|
39
|
+
"lock": { "type": "string", "minLength": 1, "pattern": "^[^*?\\[\\]{}()!]+$" },
|
|
40
|
+
"inputs": {
|
|
41
|
+
"type": "array",
|
|
42
|
+
"minItems": 1,
|
|
43
|
+
"uniqueItems": true,
|
|
44
|
+
"items": { "type": "string", "minLength": 1, "pattern": "^[^?\\[\\]{}()!]+$" }
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"versionSources": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"minProperties": 1,
|
|
51
|
+
"propertyNames": { "pattern": "^@[A-Z0-9_]+@$" },
|
|
52
|
+
"additionalProperties": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"additionalProperties": false,
|
|
55
|
+
"required": ["source", "pointer"],
|
|
56
|
+
"properties": {
|
|
57
|
+
"source": { "type": "string", "minLength": 1, "pattern": "^[^*?\\[\\]{}()!]+$" },
|
|
58
|
+
"pointer": { "type": "string", "pattern": "^/" },
|
|
59
|
+
"prefix": { "type": "string" },
|
|
60
|
+
"suffix": { "type": "string" }
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
32
64
|
"tokens": {
|
|
33
65
|
"type": "object",
|
|
34
66
|
"additionalProperties": {
|
|
35
67
|
"anyOf": [{ "type": "string" }, { "type": "number" }, { "type": "boolean" }]
|
|
36
68
|
}
|
|
37
69
|
}
|
|
70
|
+
},
|
|
71
|
+
"dependentRequired": {
|
|
72
|
+
"format": ["template"],
|
|
73
|
+
"template": ["format"]
|
|
38
74
|
}
|
|
39
75
|
}
|
|
40
76
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$id": "https://github.com/ifoohoo/skill-family-doc-render/schemas/site-coverage-lock.schema.json",
|
|
3
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
|
+
"title": "site-coverage-lock.json",
|
|
5
|
+
"description": "知识站已审阅产品输入的最小字节快照;不保存版本、发布状态或人工结论。",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["sha256", "inputs"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
|
|
11
|
+
"inputs": {
|
|
12
|
+
"type": "array",
|
|
13
|
+
"items": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"additionalProperties": false,
|
|
16
|
+
"required": ["path", "sha256"],
|
|
17
|
+
"properties": {
|
|
18
|
+
"path": { "type": "string", "minLength": 1 },
|
|
19
|
+
"sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"artifactGraphVersionLockSha256": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"pattern": "^[0-9a-f]{64}$"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|