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 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, renders every repo carrying a
6
- `site` field from its site source directory to its target directory (typically `docs/`), injects
7
- nav / pager / footer, replaces version placeholders, copies assets, writes `.nojekyll` and a
8
- tree baseline (`site-baseline.json`), and runs a content-level leak scan over every output file
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.2.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.2.0 consumes the three Foundation packages at the exact `0.18.0` pin:
25
- `skill-family-contracts@0.18.0`, `skill-family-harness-node@0.18.0` and
26
- `skill-family-engineering-kit@0.18.0` (the last one is used by the workspace profile check).
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.2.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.2.0 --check
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.2.0 --repo <name>
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.2.0 --assert-git
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
- Exit codes: `0` success; `1` drift class — `--check` drift, leak-scan hit, `--assert-git`
48
- missing files, missing/corrupt baseline; `2` configuration class — missing/invalid
49
- `public-release.json` or `pages.json`, JSON parse failures, unreplaced `@TOKEN@` placeholders,
50
- invalid `--repo` usage (the message includes the JSON field path). When several repos are
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.pages` points to a pages manifest: `{ "pages": [{ "id", "title", "order", "inPager" }] }`,
87
- validated against `schemas/pages.schema.json`. Pages are sorted by `order`;
88
- `inPager: false` excludes a page from the prev/next pager. Page `id` is restricted to
89
- `[A-Za-z0-9][A-Za-z0-9_-]*`.
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
- ## Placeholders
167
+ ### Legacy HTML compatibility
93
168
 
94
- Source pages use three HTML-comment injection points, replaced at render time:
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 arbitrary static placeholder replacements on top. If a rendered page still
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 and adds no other runtime
149
- dependencies:
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 sibling directory under the target's canonical
155
- parent, with contained writes through `writeFileAtomic`. A new target uses
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-baseline.json`; validation failure aborts with exit code 2.
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:** after installing the exact `skill-family-doc-render@0.2.0`, run
170
- > `./node_modules/.bin/skill-family-doc-render --check` — the drift check is read-only:
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:** this CLI writes the declared target and a controlled sibling
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.2.0 --help # show usage
189
- npx skill-family-doc-render@0.2.0 --check # read-only drift check — the safe first command
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.2.1",
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": "站点页面清单:页面顺序、导航与翻页的真源。site 块为站点元数据(渲染器不消费)。id 限文件名片段字符,顺带消除拼路径时的 shell 元字符面。",
6
- "type": "object",
7
- "additionalProperties": false,
8
- "required": ["pages"],
9
- "properties": {
10
- "site": { "type": "object" },
11
- "pages": {
12
- "type": "array",
13
- "minItems": 1,
14
- "items": {
15
- "type": "object",
16
- "additionalProperties": false,
17
- "required": ["id", "title", "order"],
18
- "properties": {
19
- "id": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9_-]*$" },
20
- "title": { "type": "string", "minLength": 1 },
21
- "order": { "type": "integer" },
22
- "inPager": { "type": "boolean" }
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
+ }