@iyulab/canopy-page 0.8.0 → 0.9.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 +16 -0
- package/README.md +3 -0
- package/dist/nav.d.ts +7 -0
- package/dist/nav.js +13 -4
- package/dist/site.js +14 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,22 @@ Notable changes to canopy-page. The format follows
|
|
|
7
7
|
The `settings.json` contract is what consuming projects plan their upgrades around, so changes
|
|
8
8
|
to it — its fields, its validation, and what the checks reject — are what this file is about.
|
|
9
9
|
|
|
10
|
+
## [0.9.0] — 2026-08-11
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`check` warns when a section's sidebar heading falls back to a raw directory name.** A
|
|
15
|
+
section with no `label` and no index page was already published this way — the fallback
|
|
16
|
+
itself is sound — but silently: the directory name it falls back to is a filesystem detail,
|
|
17
|
+
not a name an author chose, and there was previously no way to find out a sidebar's top-level
|
|
18
|
+
heading was about to read that way instead. `check`/`build` now report it as a warning (the
|
|
19
|
+
build still succeeds) naming the section and the label it fell back to.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- **Upgraded to canopy 0.10.0**, the release the heading custom-id syntax, the sidebar
|
|
24
|
+
active-page tint, and page-content typography build on.
|
|
25
|
+
|
|
10
26
|
## [0.8.0] — 2026-08-11
|
|
11
27
|
|
|
12
28
|
### Added
|
package/README.md
CHANGED
|
@@ -217,6 +217,9 @@ Warnings — reported, and the build continues:
|
|
|
217
217
|
- An `exclude` pattern that matched nothing, which usually means a path written from the wrong
|
|
218
218
|
place. Extension patterns are left alone: `*.tmp` in a site with no scratch files is a rule
|
|
219
219
|
about what may never ship, not a claim that something is there
|
|
220
|
+
- A section with no `label` and no index page, whose sidebar heading falls back to its own
|
|
221
|
+
directory name — a filesystem detail, not a name anyone chose. Add a `label`, or an index page
|
|
222
|
+
for the section to name itself
|
|
220
223
|
|
|
221
224
|
Checking reads the settings and each page. It never renders, so it is fast enough to sit at the
|
|
222
225
|
front of a pipeline, at the scale a product manual reaches. References inside fenced
|
package/dist/nav.d.ts
CHANGED
|
@@ -42,6 +42,13 @@ export interface NavTranslation {
|
|
|
42
42
|
orphans: string[];
|
|
43
43
|
/** Pages the settings place more than once. */
|
|
44
44
|
duplicates: string[];
|
|
45
|
+
/**
|
|
46
|
+
* Top-level section paths labeled by their own directory name because the
|
|
47
|
+
* settings file wrote no `label` and the section has no index page to name
|
|
48
|
+
* it instead — see `NavReport.rawSlugLabels` for why this is scoped to
|
|
49
|
+
* sections rather than every subdirectory that falls back the same way.
|
|
50
|
+
*/
|
|
51
|
+
rawSlugLabels: string[];
|
|
45
52
|
}
|
|
46
53
|
/**
|
|
47
54
|
* Turn settings plus the site's pages into the spec canopy builds from.
|
package/dist/nav.js
CHANGED
|
@@ -162,7 +162,10 @@ function translateSection(section, index, report) {
|
|
|
162
162
|
// Same rule as a derived directory: the page fronting a section names it, and
|
|
163
163
|
// only a section with no index page needs a name written for it here. A label
|
|
164
164
|
// in the settings file still wins — that is what writing one is for.
|
|
165
|
-
const
|
|
165
|
+
const usesRawSlugLabel = section.label === undefined && sectionIndex === undefined;
|
|
166
|
+
if (usesRawSlugLabel)
|
|
167
|
+
report.rawSlugLabels.push(section.path);
|
|
168
|
+
const label = section.label ?? (usesRawSlugLabel ? lastSegment(section.path) : undefined);
|
|
166
169
|
return {
|
|
167
170
|
...(label === undefined ? {} : { label }),
|
|
168
171
|
...(sectionIndex === undefined ? {} : { path: sectionIndex }),
|
|
@@ -191,14 +194,20 @@ function narrowTo(pages, index) {
|
|
|
191
194
|
export function translateNav(settings, index) {
|
|
192
195
|
const sections = settings.sections ?? [];
|
|
193
196
|
if (sections.length === 0) {
|
|
194
|
-
return { missing: [], orphans: [], duplicates: [] };
|
|
197
|
+
return { missing: [], orphans: [], duplicates: [], rawSlugLabels: [] };
|
|
195
198
|
}
|
|
196
199
|
const placements = new Map();
|
|
197
200
|
const missing = [];
|
|
201
|
+
const rawSlugLabels = [];
|
|
198
202
|
const place = (page) => {
|
|
199
203
|
placements.set(page, (placements.get(page) ?? 0) + 1);
|
|
200
204
|
};
|
|
201
|
-
const report = {
|
|
205
|
+
const report = {
|
|
206
|
+
missing,
|
|
207
|
+
place,
|
|
208
|
+
isPlaced: (page) => placements.has(page),
|
|
209
|
+
rawSlugLabels,
|
|
210
|
+
};
|
|
202
211
|
const items = sections.map((section) => translateSection(section, index, report));
|
|
203
212
|
// The root index is the site's home page: it is reached without navigation, so
|
|
204
213
|
// it is neither placed by a section nor counted as something nobody placed.
|
|
@@ -231,5 +240,5 @@ export function translateNav(settings, index) {
|
|
|
231
240
|
.filter(([, count]) => count > 1)
|
|
232
241
|
.map(([page]) => page)
|
|
233
242
|
.sort();
|
|
234
|
-
return { spec: { items }, missing, orphans, duplicates };
|
|
243
|
+
return { spec: { items }, missing, orphans, duplicates, rawSlugLabels };
|
|
235
244
|
}
|
package/dist/site.js
CHANGED
|
@@ -94,6 +94,20 @@ export function navFindings(nav) {
|
|
|
94
94
|
nav.orphans.map((page) => ` ${page}`).join("\n"),
|
|
95
95
|
});
|
|
96
96
|
}
|
|
97
|
+
for (const path of nav.rawSlugLabels) {
|
|
98
|
+
// Publishable either way — canopy-page's own fallback is sound, and the
|
|
99
|
+
// build is not wrong to use it. What is wrong is doing so silently: the
|
|
100
|
+
// directory name it falls back to is written for a filesystem, not a
|
|
101
|
+
// reader, and the author has no other way to find out their sidebar's
|
|
102
|
+
// top-level heading is about to read that way instead of a name they chose.
|
|
103
|
+
const slug = path.split("/").pop() ?? path;
|
|
104
|
+
findings.push({
|
|
105
|
+
level: "warning",
|
|
106
|
+
message: `settings: section "${path}" has no "label" and no index page, ` +
|
|
107
|
+
`so its sidebar heading falls back to the directory name "${slug}". ` +
|
|
108
|
+
'Add a "label", or an index page for the section to name itself',
|
|
109
|
+
});
|
|
110
|
+
}
|
|
97
111
|
return findings;
|
|
98
112
|
}
|
|
99
113
|
/** Print findings in the order given, and report whether any of them stops a build. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/canopy-page",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Authoring pipeline for documentation sites: one settings file, integrity checks, and a build.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -53,6 +53,6 @@
|
|
|
53
53
|
"vitest": "^4.1.9"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@iyulab/canopy": "^0.
|
|
56
|
+
"@iyulab/canopy": "^0.10.0"
|
|
57
57
|
}
|
|
58
58
|
}
|