skill-family-doc-render 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +21 -21
- package/package.json +1 -1
- package/templates/editorial/assets/site.js +52 -7
- package/templates/editorial/assets/style.css +10 -13
- package/templates/editorial/index.mjs +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# 变更日志
|
|
2
2
|
|
|
3
|
+
## 0.6.1 - 2026-10-12
|
|
4
|
+
|
|
5
|
+
### 变更
|
|
6
|
+
|
|
7
|
+
- 按本仓联合发布合同,`skill-family-doc-render` 与 `skill-family-docs`、公开站点对齐为 0.6.1。渲染器的公开 API、命令行参数、输入合同、模板和业务实现均未改变,运行依赖仍精确锁定原版本。Foundation 0.22.0 钉扎不变。
|
|
8
|
+
|
|
9
|
+
### 说明
|
|
10
|
+
|
|
11
|
+
- 本地源包版本为 0.6.1 候选,不代表已经正式发布。安装或使用 `npx` 前,先在官方 npm 确认 `skill-family-doc-render@0.6.1` 可用。已发布的 0.6.0 保留,不覆盖该版本。
|
|
12
|
+
|
|
13
|
+
## 0.6.0 - 2026-10-11
|
|
14
|
+
|
|
15
|
+
### 变更
|
|
16
|
+
|
|
17
|
+
- 与 `skill-family-docs` 和公开站点的 0.6.0 联合发布对齐版本。
|
|
18
|
+
- `editorial` 模板调整阅读与交互样式,包内单测同步。
|
|
19
|
+
|
|
20
|
+
### 说明
|
|
21
|
+
|
|
22
|
+
- 安装或 `npx` 前,先在官方 npm 确认 `skill-family-doc-render@0.6.0` 可用。本源版本不等于已发布或可安装版本。
|
|
23
|
+
|
|
3
24
|
## 0.5.0 - 2026-09-28
|
|
4
25
|
|
|
5
26
|
### 新增
|
package/README.md
CHANGED
|
@@ -16,20 +16,20 @@ publication APIs. A failure before commit removes staging and leaves the existin
|
|
|
16
16
|
untouched. After commit, or when publication is indeterminate, staging or displaced data may
|
|
17
17
|
remain for diagnosis; the renderer does not guess or roll back.
|
|
18
18
|
|
|
19
|
-
> **Version boundary:** this source tree is version `0.
|
|
19
|
+
> **Version boundary:** this source tree is version `0.6.1`. That is the local version and the
|
|
20
20
|
> intended joint target for the renderer, documentation plugin, and public site. Confirm this
|
|
21
21
|
> exact version in the official npm registry before `npm install` or `npx`. Published `0.4.5`
|
|
22
22
|
> preserves the `markdown-v1`, `editorial`, and `--check-project` behavior introduced in 0.4.0
|
|
23
|
-
> and has no `--conclusion-output` or `--read-proof`. Those two commands belong to this 0.
|
|
23
|
+
> and has no `--conclusion-output` or `--read-proof`. Those two commands belong to this 0.6.1
|
|
24
24
|
> CLI. The examples give the command shape for that version. They leave publication, Skill
|
|
25
|
-
> Family Hub registration, and new host-reply acceptance to the official records for `0.
|
|
25
|
+
> Family Hub registration, and new host-reply acceptance to the official records for `0.6.1`.
|
|
26
26
|
|
|
27
27
|
## Install
|
|
28
28
|
|
|
29
|
-
After confirming `skill-family-doc-render@0.
|
|
29
|
+
After confirming `skill-family-doc-render@0.6.1` in the official npm registry, install that exact version:
|
|
30
30
|
|
|
31
31
|
```sh
|
|
32
|
-
npm install --save-exact skill-family-doc-render@0.
|
|
32
|
+
npm install --save-exact skill-family-doc-render@0.6.1
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
Requires Node.js `>=22.22.2 <23` (aligned with the skill-family foundation packages).
|
|
@@ -39,41 +39,41 @@ This checkout currently pins exact runtime dependencies on `marked@18.0.11`,
|
|
|
39
39
|
Markdown lexer; the renderer applies its own restricted-format validation before passing semantic
|
|
40
40
|
content to the template. The workspace profile check separately uses
|
|
41
41
|
`skill-family-engineering-kit@0.22.0`. These pins describe the local source and installed
|
|
42
|
-
packages; they do not republish `0.
|
|
42
|
+
packages; they do not republish `0.6.0`.
|
|
43
43
|
The 0.2.0 baseline format and exit-code changes are breaking changes; existing 0.1.x users
|
|
44
44
|
must re-render their baseline before using `--check`. See the changelog for the full migration
|
|
45
45
|
notes.
|
|
46
46
|
|
|
47
47
|
## CLI
|
|
48
48
|
|
|
49
|
-
Use the exact 0.
|
|
49
|
+
Use the exact 0.6.1 CLI for rendering, checks, coverage maintenance, the Git index assertion, and the proof commands. Confirm `skill-family-doc-render@0.6.1` in the official npm registry before running them. Published 0.4.5 can run the commands that omit `--conclusion-output` and `--read-proof`.
|
|
50
50
|
|
|
51
51
|
```sh
|
|
52
52
|
# render all repos with a site field (writes to disk)
|
|
53
|
-
npx skill-family-doc-render@0.
|
|
53
|
+
npx skill-family-doc-render@0.6.1
|
|
54
54
|
|
|
55
55
|
# drift check only: compare in-memory render against the on-disk site-baseline.json, write nothing
|
|
56
|
-
npx skill-family-doc-render@0.
|
|
56
|
+
npx skill-family-doc-render@0.6.1 --check
|
|
57
57
|
|
|
58
58
|
# render / check a single repo by name
|
|
59
|
-
npx skill-family-doc-render@0.
|
|
59
|
+
npx skill-family-doc-render@0.6.1 --repo <name>
|
|
60
60
|
|
|
61
61
|
# assert every rendered file is tracked in the Git index, then render
|
|
62
|
-
npx skill-family-doc-render@0.
|
|
62
|
+
npx skill-family-doc-render@0.6.1 --assert-git
|
|
63
63
|
|
|
64
64
|
# run both the drift and Git index tracking checks without writing
|
|
65
|
-
npx skill-family-doc-render@0.
|
|
65
|
+
npx skill-family-doc-render@0.6.1 --check --assert-git
|
|
66
66
|
|
|
67
67
|
# inspect or refresh the reviewed product-input snapshot
|
|
68
|
-
npx skill-family-doc-render@0.
|
|
69
|
-
npx skill-family-doc-render@0.
|
|
70
|
-
npx skill-family-doc-render@0.
|
|
68
|
+
npx skill-family-doc-render@0.6.1 --status --repo <name>
|
|
69
|
+
npx skill-family-doc-render@0.6.1 --refresh-coverage --repo <name>
|
|
70
|
+
npx skill-family-doc-render@0.6.1 --check-project --repo <name>
|
|
71
71
|
|
|
72
72
|
# after the mechanical check, exclusive-create one proof; do not overwrite
|
|
73
|
-
npx skill-family-doc-render@0.
|
|
73
|
+
npx skill-family-doc-render@0.6.1 --check-project --repo <name> --conclusion-output /absolute/path/conclusion.json
|
|
74
74
|
|
|
75
75
|
# read one existing proof from any working directory; write nothing
|
|
76
|
-
npx skill-family-doc-render@0.
|
|
76
|
+
npx skill-family-doc-render@0.6.1 --read-proof --proof-root /absolute/proof-root --proof relative/conclusion.json
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
`--check-project` still requires the current directory to own `public-release.json`.
|
|
@@ -104,7 +104,7 @@ Same-version `DOCS_CLEAR` maps to `pass` only when `completion` is `complete`;
|
|
|
104
104
|
That status keeps the proof's recorded non-pass. A missing file, damaged JSON, a different
|
|
105
105
|
provider, or an unknown same-version domain code is `unavailable` (exit `2`). Earlier
|
|
106
106
|
local-candidate runs exercised proof output and proof reading; those runs keep their original
|
|
107
|
-
scene limits. Publication, Hub registration, and new host replies for `0.
|
|
107
|
+
scene limits. Publication, Hub registration, and new host replies for `0.6.1` stay with the
|
|
108
108
|
official records. These proof commands consume the Foundation
|
|
109
109
|
`professional-conclusion` contract from `skill-family-contracts@0.22.0`. Refreshing a proof
|
|
110
110
|
means running `--check-project` again to a new output path. Remediation, site creation, and
|
|
@@ -318,7 +318,7 @@ Foundation packages below, it uses exact `marked@18.0.11` for Markdown tokenizat
|
|
|
318
318
|
Apache-2.0
|
|
319
319
|
|
|
320
320
|
<!-- release-skill:capability:safe-first-command -->
|
|
321
|
-
> **Start here:** run `npx skill-family-doc-render@0.
|
|
321
|
+
> **Start here:** run `npx skill-family-doc-render@0.6.1 --check-project --repo <name>` after
|
|
322
322
|
> confirming that exact version in the official registry. From a local checkout, stay in the
|
|
323
323
|
> directory that owns `public-release.json` and call
|
|
324
324
|
> `node /absolute/path/to/skill-family-doc-render/bin/skill-family-doc-render.mjs --check-project --repo <name>`,
|
|
@@ -346,6 +346,6 @@ Apache-2.0
|
|
|
346
346
|
Display help and run a read-only project check:
|
|
347
347
|
|
|
348
348
|
```sh
|
|
349
|
-
npx skill-family-doc-render@0.
|
|
350
|
-
npx skill-family-doc-render@0.
|
|
349
|
+
npx skill-family-doc-render@0.6.1 --help
|
|
350
|
+
npx skill-family-doc-render@0.6.1 --check-project --repo <name>
|
|
351
351
|
```
|
package/package.json
CHANGED
|
@@ -99,12 +99,49 @@
|
|
|
99
99
|
let activeDialog;
|
|
100
100
|
// Release synchronously before following links or switching dialogs. The queued
|
|
101
101
|
// native close event must never restore an old position over a destination.
|
|
102
|
+
function captureViewport() {
|
|
103
|
+
return { left: window.scrollX, top: window.scrollY };
|
|
104
|
+
}
|
|
105
|
+
// Sticky header controls sit in document flow at y=0. Pointerdown/keydown must
|
|
106
|
+
// record the viewport before focus scrolls that in-flow box into view.
|
|
107
|
+
function bindOpener(button) {
|
|
108
|
+
let viewport = null;
|
|
109
|
+
const remember = () => { viewport = captureViewport(); };
|
|
110
|
+
button.addEventListener('pointerdown', remember);
|
|
111
|
+
button.addEventListener('touchstart', remember, { passive: true });
|
|
112
|
+
button.addEventListener('keydown', event => {
|
|
113
|
+
if (event.key === 'Enter' || event.key === ' ') remember();
|
|
114
|
+
});
|
|
115
|
+
button.addEventListener('mousedown', event => {
|
|
116
|
+
remember();
|
|
117
|
+
event.preventDefault();
|
|
118
|
+
});
|
|
119
|
+
return () => {
|
|
120
|
+
const value = viewport ?? captureViewport();
|
|
121
|
+
viewport = null;
|
|
122
|
+
return value;
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function restoreScroll(state) {
|
|
126
|
+
const html = document.documentElement;
|
|
127
|
+
const previous = html.style.scrollBehavior;
|
|
128
|
+
html.style.scrollBehavior = 'auto';
|
|
129
|
+
const apply = () => window.scrollTo({ left: state.left, top: state.top, behavior: 'auto' });
|
|
130
|
+
apply();
|
|
131
|
+
requestAnimationFrame(() => {
|
|
132
|
+
apply();
|
|
133
|
+
requestAnimationFrame(apply);
|
|
134
|
+
});
|
|
135
|
+
setTimeout(apply, 0);
|
|
136
|
+
html.style.scrollBehavior = previous;
|
|
137
|
+
}
|
|
102
138
|
function releaseDialog(state, returnFocus = true) {
|
|
103
139
|
if (activeDialog !== state) return;
|
|
104
140
|
activeDialog = null;
|
|
141
|
+
document.documentElement.classList.remove('modal-open');
|
|
105
142
|
document.body.classList.remove('modal-open');
|
|
106
143
|
document.body.style.removeProperty('top');
|
|
107
|
-
|
|
144
|
+
restoreScroll(state);
|
|
108
145
|
if (returnFocus && state.invoker?.isConnected) state.invoker.focus({ preventScroll: true });
|
|
109
146
|
}
|
|
110
147
|
function closeDialog(dialog, returnFocus = true) {
|
|
@@ -112,11 +149,17 @@
|
|
|
112
149
|
dialog.close();
|
|
113
150
|
if (state?.dialog === dialog) releaseDialog(state, returnFocus);
|
|
114
151
|
}
|
|
115
|
-
function showDialog(dialog, invoker) {
|
|
152
|
+
function showDialog(dialog, invoker, viewport) {
|
|
116
153
|
if (activeDialog) closeDialog(activeDialog.dialog);
|
|
117
|
-
const state = {
|
|
154
|
+
const state = {
|
|
155
|
+
dialog,
|
|
156
|
+
invoker,
|
|
157
|
+
left: viewport?.left ?? window.scrollX,
|
|
158
|
+
top: viewport?.top ?? window.scrollY,
|
|
159
|
+
};
|
|
118
160
|
activeDialog = state;
|
|
119
161
|
document.body.style.top = `${-state.top}px`;
|
|
162
|
+
document.documentElement.classList.add('modal-open');
|
|
120
163
|
document.body.classList.add('modal-open');
|
|
121
164
|
try { dialog.showModal(); } catch (error) { releaseDialog(state); throw error; }
|
|
122
165
|
}
|
|
@@ -130,7 +173,8 @@
|
|
|
130
173
|
if (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom) closeDialog(dialog);
|
|
131
174
|
});
|
|
132
175
|
}
|
|
133
|
-
|
|
176
|
+
const menuViewport = bindOpener(get('menu-toggle'));
|
|
177
|
+
get('menu-toggle').addEventListener('click', () => showDialog(menu, get('menu-toggle'), menuViewport()));
|
|
134
178
|
get('close-menu').addEventListener('click', () => closeDialog(menu));
|
|
135
179
|
menu.addEventListener('click', event => {
|
|
136
180
|
if (event.target.closest('a')) closeDialog(menu, false);
|
|
@@ -189,14 +233,15 @@
|
|
|
189
233
|
setActiveResult(0, false);
|
|
190
234
|
results.scrollTop = 0;
|
|
191
235
|
}
|
|
192
|
-
|
|
236
|
+
const searchViewport = bindOpener(searchToggle);
|
|
237
|
+
function openSearch(invoker, viewport) {
|
|
193
238
|
if (invoker?.closest('dialog')) invoker = searchToggle;
|
|
194
239
|
input.value = '';
|
|
195
240
|
updateSearch();
|
|
196
|
-
showDialog(searchDialog, invoker);
|
|
241
|
+
showDialog(searchDialog, invoker, viewport);
|
|
197
242
|
input.focus({ preventScroll: true });
|
|
198
243
|
}
|
|
199
|
-
searchToggle.addEventListener('click', () => openSearch(searchToggle));
|
|
244
|
+
searchToggle.addEventListener('click', () => openSearch(searchToggle, searchViewport()));
|
|
200
245
|
get('close-search').addEventListener('click', () => closeDialog(searchDialog));
|
|
201
246
|
input.addEventListener('input', updateSearch);
|
|
202
247
|
input.addEventListener('keydown', event => {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
--surface: #fff;
|
|
7
7
|
--ink: #26392f;
|
|
8
8
|
--text: #3d4b43;
|
|
9
|
-
--muted: #657168
|
|
9
|
+
--muted: #5f6c62; /* muted on tint must stay ≥4.5:1; #657168 was 4.394 */
|
|
10
10
|
--line: #dce3d9;
|
|
11
11
|
--green: #2f634c;
|
|
12
12
|
--tint: #e9f0e7;
|
|
@@ -122,8 +122,10 @@ main:focus:not(:focus-visible) { outline: none; }
|
|
|
122
122
|
.breadcrumb { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; color: var(--muted); font-size: 11px; margin: 0 auto 35px; max-width: 740px; }
|
|
123
123
|
.breadcrumb > span:last-child { color: var(--text); }
|
|
124
124
|
article { max-width: 740px; margin: 0 auto; }
|
|
125
|
-
.
|
|
125
|
+
article.page-home { overflow-x: clip; }
|
|
126
|
+
.intro { font-size: 16px; line-height: 1.8; color: var(--muted); margin-bottom: 20px; max-width: 44em; }
|
|
126
127
|
.page-heading { margin-bottom: 30px; }
|
|
128
|
+
.page-heading .text-action { display: inline-flex; margin: -6px 0 14px; }
|
|
127
129
|
.content-list { margin: 20px 0; padding-left: 1.5em; }
|
|
128
130
|
.content-list li { padding-left: .3em; margin: 12px 0; }
|
|
129
131
|
.heading-link { font-size: .7em; text-decoration: none; font-weight: 400; padding: 4px; opacity: .65; }
|
|
@@ -142,9 +144,9 @@ article { max-width: 740px; margin: 0 auto; }
|
|
|
142
144
|
.article-footer a { text-decoration: none; white-space: nowrap; }
|
|
143
145
|
|
|
144
146
|
/* Home page uses the same manifest-driven task sequence as the pager. */
|
|
145
|
-
.home-hero { display: grid; grid-template-columns: minmax(0,1fr) 180px; align-items: center; gap: 25px; }
|
|
147
|
+
.home-hero { display: grid; grid-template-columns: minmax(0,1fr) 180px; align-items: center; gap: 25px; overflow: hidden; }
|
|
146
148
|
.home-hero h1 { font-size: 38px; }
|
|
147
|
-
.home-hero .intro { font-size:
|
|
149
|
+
.home-hero .intro { font-size: 16px; }
|
|
148
150
|
.hero-actions { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; margin: 24px 0 12px; }
|
|
149
151
|
.hero-actions:empty { display: none; }
|
|
150
152
|
.button { display: inline-flex; align-items: center; justify-content: space-between; gap: 28px; text-decoration: none; border-radius: 7px; padding: 10px 14px 10px 18px; font-size: 13px; font-weight: 500; transition: transform 160ms var(--ease), background 160ms var(--ease); }
|
|
@@ -172,8 +174,8 @@ article { max-width: 740px; margin: 0 auto; }
|
|
|
172
174
|
.route-list > a:first-child { border-top: 0; }
|
|
173
175
|
.route-list > a:hover { background: var(--tint); padding-left: 10px; padding-right: 10px; }
|
|
174
176
|
.route-number { font-size: 11px; color: var(--muted); align-self: flex-start; padding-top: 4px; flex: none; }
|
|
175
|
-
.route-list h3 { font-size:
|
|
176
|
-
.route-list p { font-size:
|
|
177
|
+
.route-list h3 { font-size: 16px; margin: 0 0 3px; }
|
|
178
|
+
.route-list p { font-size: 16px; color: var(--muted); margin: 0; line-height: 1.8; }
|
|
177
179
|
.route-arrow { margin-left: auto; font-size: 18px; font-weight: 400; color: var(--green); flex: none; }
|
|
178
180
|
|
|
179
181
|
/* Semantic blocks; no project-provided layout classes. */
|
|
@@ -208,7 +210,7 @@ td code { white-space: nowrap; }
|
|
|
208
210
|
dialog { background: var(--surface); color: var(--text); border: 1px solid var(--line); border-radius: 12px; padding: 0; box-shadow: var(--shadow); }
|
|
209
211
|
dialog:not([open]) { display: none; }
|
|
210
212
|
dialog::backdrop { background: #162c2455; backdrop-filter: blur(3px); }
|
|
211
|
-
html
|
|
213
|
+
html.modal-open { overflow: hidden; }
|
|
212
214
|
body.modal-open { position: fixed; left: 0; right: 0; width: 100%; }
|
|
213
215
|
#editorial-search-dialog { width: min(600px,calc(100vw - 28px)); max-height: 75dvh; margin: 12dvh auto auto; }
|
|
214
216
|
#editorial-search-dialog[open] { display: flex; flex-direction: column; }
|
|
@@ -238,7 +240,6 @@ body.modal-open { position: fixed; left: 0; right: 0; width: 100%; }
|
|
|
238
240
|
.sidebar { padding-left: 32px; }
|
|
239
241
|
.home-hero { grid-template-columns: minmax(0,1fr) 200px; gap: 35px; }
|
|
240
242
|
.home-hero h1 { font-size: 42px; }
|
|
241
|
-
.home-hero .intro { font-size: 15px; }
|
|
242
243
|
}
|
|
243
244
|
@media (max-width: 1199px) {
|
|
244
245
|
.layout { grid-template-columns: 210px minmax(0,1fr); }
|
|
@@ -269,7 +270,6 @@ body.modal-open { position: fixed; left: 0; right: 0; width: 100%; }
|
|
|
269
270
|
.home-hero { grid-template-columns: minmax(0,1fr) 155px; gap: 20px; }
|
|
270
271
|
.home-hero h1 { font-size: 34px; }
|
|
271
272
|
h1 { font-size: 31px; }
|
|
272
|
-
.intro { font-size: 14px; }
|
|
273
273
|
.hero-actions { gap: 17px; }
|
|
274
274
|
.page-heading { margin-bottom: 24px; }
|
|
275
275
|
.article-footer { margin-top: 42px; }
|
|
@@ -278,14 +278,11 @@ body.modal-open { position: fixed; left: 0; right: 0; width: 100%; }
|
|
|
278
278
|
.home-hero { display: block; }
|
|
279
279
|
.source-illustration { display: none; }
|
|
280
280
|
.home-hero h1 { font-size: 34px; line-height: 1.42; }
|
|
281
|
-
.home-hero .intro { font-size: 14px; }
|
|
282
281
|
.hero-actions { gap: 18px; margin-top: 22px; }
|
|
283
282
|
h1 { font-size: 29px; letter-spacing: -.04em; }
|
|
284
283
|
h2 { font-size: 21px; }
|
|
285
284
|
.start-section { padding-top: 23px; margin-top: 30px; }
|
|
286
285
|
.route-list > a { padding: 18px 0; gap: 12px; }
|
|
287
|
-
.route-list h3 { font-size: 14px; }
|
|
288
|
-
.route-list p { font-size: 12px; }
|
|
289
286
|
.route-arrow { font-size: 16px; }
|
|
290
287
|
.route-number { font-size: 10px; }
|
|
291
288
|
.callout { padding: 14px; gap: 10px; font-size: 12px; }
|
|
@@ -313,7 +310,7 @@ body.modal-open { position: fixed; left: 0; right: 0; width: 100%; }
|
|
|
313
310
|
}
|
|
314
311
|
.site-header, .sidebar, .page-outline, .copy-button, .heading-copy, .heading-link,
|
|
315
312
|
.page-pager, .article-footer, .toast, dialog, .skip-link, .mobile-fallback { display: none !important; }
|
|
316
|
-
html
|
|
313
|
+
html.modal-open { overflow: visible; }
|
|
317
314
|
body.modal-open { position: static; top: auto !important; }
|
|
318
315
|
.layout { display: block; }
|
|
319
316
|
main { padding: 0; }
|
|
@@ -201,11 +201,13 @@ function tutorial(model, page) {
|
|
|
201
201
|
return `<nav class="page-pager" aria-label="教程翻页">${previous ? `<a class="pager-previous" href="${pageHref(previous)}" rel="prev"><span>上一步</span><strong>← ${escape(label(previous))}</strong></a>` : ''}${next ? `<a class="pager-next" href="${pageHref(next)}" rel="next"><span>下一步</span><strong>${escape(label(next))} →</strong></a>` : ''}</nav>`;
|
|
202
202
|
}
|
|
203
203
|
function hero(model, page) {
|
|
204
|
-
const
|
|
204
|
+
const intro = `<p class="intro">${renderInline(page.blocks[0].content)}</p>`;
|
|
205
205
|
if (page.kind !== 'home') {
|
|
206
206
|
const promptIndex = page.kind === 'task' ? page.blocks.findIndex(block => block.type === 'code' && block.language === 'prompt') : -1;
|
|
207
|
-
|
|
207
|
+
const jump = promptIndex >= 0 ? `<a class="text-action" href="#editorial-code-${promptIndex}">查看操作提示词 <span aria-hidden="true">↓</span></a>` : '';
|
|
208
|
+
return `<div class="page-heading"><h1>${escape(page.title)}</h1>${jump}${intro}</div>`;
|
|
208
209
|
}
|
|
210
|
+
const title = `<h1>${escape(page.title)}</h1>${intro}`;
|
|
209
211
|
const tasks = model.pages.filter(item => item.inPager);
|
|
210
212
|
const first = tasks[0];
|
|
211
213
|
const maintenance = tasks.find(item => item.role === 'maintenance' && item !== first);
|