hdoc-tools 0.65.0 → 0.66.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/hdoc-serve-validate.js +31 -3
- package/hdoc-toc.js +24 -8
- package/package.json +1 -1
package/hdoc-serve-validate.js
CHANGED
|
@@ -329,10 +329,20 @@ exports.validate_page = async (args) => {
|
|
|
329
329
|
const warnings = [];
|
|
330
330
|
const skipped = [];
|
|
331
331
|
|
|
332
|
-
//
|
|
333
|
-
//
|
|
332
|
+
// _inline pages get the build pipeline's relaxed rules: no filename
|
|
333
|
+
// convention, fully-qualified Hornbill Docs links allowed, and links
|
|
334
|
+
// need not be root-relative.
|
|
335
|
+
const is_inline = rel.includes("/_inline/");
|
|
336
|
+
|
|
337
|
+
// 1) filename convention (mirrors hdoc-build.js; _inline and *_ext.md
|
|
338
|
+
// files are exempt, as in the full build)
|
|
334
339
|
const stem = path.basename(rel).replace(/\.md$/i, "");
|
|
335
|
-
if (
|
|
340
|
+
if (
|
|
341
|
+
!is_inline &&
|
|
342
|
+
!stem.endsWith("_ext") &&
|
|
343
|
+
!DOC_FILENAME_RE.test(stem) &&
|
|
344
|
+
stem !== "index"
|
|
345
|
+
) {
|
|
336
346
|
errors.push(
|
|
337
347
|
`Filename does not meet naming standards (^[a-z]+[-a-z0-9]+$): ${path.basename(rel)}`,
|
|
338
348
|
);
|
|
@@ -422,6 +432,18 @@ exports.validate_page = async (args) => {
|
|
|
422
432
|
lower.includes("docs.hornbill.com") ||
|
|
423
433
|
lower.includes("docs-internal.hornbill.com")
|
|
424
434
|
) {
|
|
435
|
+
// _inline content is embedded in the app, so fully-qualified
|
|
436
|
+
// docs links are permitted there (build behavior); whether a
|
|
437
|
+
// docs-internal link is allowed depends on the repo being
|
|
438
|
+
// private, which only the full validate knows
|
|
439
|
+
if (is_inline) {
|
|
440
|
+
skipped.push(
|
|
441
|
+
lower.includes("docs-internal.hornbill.com")
|
|
442
|
+
? `docs-internal link not checked (public-repo rule runs in full validate): ${href}`
|
|
443
|
+
: `Hornbill Docs link not checked (run a full validate): ${href}`,
|
|
444
|
+
);
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
425
447
|
errors.push(
|
|
426
448
|
`Hornbill Docs links should not be fully-qualified: ${href}`,
|
|
427
449
|
);
|
|
@@ -433,6 +455,12 @@ exports.validate_page = async (args) => {
|
|
|
433
455
|
}
|
|
434
456
|
|
|
435
457
|
if (!href.startsWith("/")) {
|
|
458
|
+
// the root-relative rule does not apply inside _inline (build
|
|
459
|
+
// behavior); the target cannot be resolved the same way, so skip
|
|
460
|
+
if (is_inline) {
|
|
461
|
+
skipped.push(`Relative link not checked (inline content): ${href}`);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
436
464
|
errors.push(
|
|
437
465
|
`Root relative links should start with a forward-slash: ${href}`,
|
|
438
466
|
);
|
package/hdoc-toc.js
CHANGED
|
@@ -263,8 +263,13 @@ class TocModel {
|
|
|
263
263
|
if (segs.includes("..") || segs.includes(".")) {
|
|
264
264
|
throw new Error("Invalid path");
|
|
265
265
|
}
|
|
266
|
-
|
|
267
|
-
|
|
266
|
+
// Special "_" folders are off-limits, with one exception: _inline
|
|
267
|
+
// directly under the book root holds real, editable inline-help pages
|
|
268
|
+
// (they render in serve/build and are exempt from the nav tree).
|
|
269
|
+
for (let i = 0; i < segs.length; i++) {
|
|
270
|
+
if (segs[i].startsWith("_") && !(i === 1 && segs[i] === "_inline")) {
|
|
271
|
+
throw new Error("Cannot operate inside special (_) folders");
|
|
272
|
+
}
|
|
268
273
|
}
|
|
269
274
|
if (!dir && exts) {
|
|
270
275
|
const lower = norm.toLowerCase();
|
|
@@ -293,32 +298,43 @@ class TocModel {
|
|
|
293
298
|
return set;
|
|
294
299
|
}
|
|
295
300
|
|
|
296
|
-
// Every file on disk under the book (excluding "_" folders
|
|
301
|
+
// Every file on disk under the book (excluding "_" folders, except _inline
|
|
302
|
+
// at the book root — those are real inline-help pages), each tagged with
|
|
297
303
|
// its kind (page/image/other). Pages also carry a linked flag (in nav or not).
|
|
298
304
|
list_files() {
|
|
299
305
|
const linked = this.linked_files();
|
|
300
306
|
const root = path.join(this.source_path, this.docId);
|
|
301
307
|
const files = [];
|
|
302
308
|
const dirs = [];
|
|
303
|
-
const walk = (absDir) => {
|
|
309
|
+
const walk = (absDir, in_inline) => {
|
|
304
310
|
for (const e of fs.readdirSync(absDir, { withFileTypes: true })) {
|
|
305
|
-
if (e.name.startsWith("_"))
|
|
311
|
+
if (e.name.startsWith("_")) {
|
|
312
|
+
// _inline at the book root is editable content; every other
|
|
313
|
+
// _ entry stays hidden (and blocked by _safe_rel)
|
|
314
|
+
if (!(absDir === root && e.name === "_inline" && e.isDirectory()))
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
306
317
|
const abs = path.join(absDir, e.name);
|
|
307
318
|
const rel = path.relative(this.source_path, abs).split(path.sep).join("/");
|
|
319
|
+
const inline = in_inline || e.name === "_inline";
|
|
308
320
|
if (e.isDirectory()) {
|
|
309
321
|
dirs.push(rel);
|
|
310
|
-
walk(abs);
|
|
322
|
+
walk(abs, inline);
|
|
311
323
|
} else {
|
|
312
324
|
const kind = kind_of(e.name);
|
|
313
325
|
files.push({
|
|
314
326
|
file: rel,
|
|
315
327
|
kind,
|
|
316
|
-
|
|
328
|
+
// _inline pages are referenced from app help contexts, never
|
|
329
|
+
// the contents tree — report them linked so the unlinked
|
|
330
|
+
// badge/filter stays meaningful
|
|
331
|
+
linked:
|
|
332
|
+
kind === "page" ? (inline ? true : linked.has(rel)) : false,
|
|
317
333
|
});
|
|
318
334
|
}
|
|
319
335
|
}
|
|
320
336
|
};
|
|
321
|
-
if (fs.existsSync(root)) walk(root);
|
|
337
|
+
if (fs.existsSync(root)) walk(root, false);
|
|
322
338
|
files.sort((a, b) => a.file.localeCompare(b.file));
|
|
323
339
|
dirs.sort((a, b) => a.localeCompare(b));
|
|
324
340
|
return { docId: this.docId, dirs, files };
|