hdoc-tools 0.60.1 → 0.62.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.
Files changed (55) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +89 -75
  3. package/hdoc-build-db.js +275 -275
  4. package/hdoc-build-embeddings.js +202 -202
  5. package/hdoc-build-pdf.js +232 -232
  6. package/hdoc-build.js +14 -6
  7. package/hdoc-bump.js +4 -2
  8. package/hdoc-content-routes.js +143 -83
  9. package/hdoc-create.js +110 -108
  10. package/hdoc-db.js +114 -114
  11. package/hdoc-help.js +60 -60
  12. package/hdoc-init.js +103 -68
  13. package/hdoc-install-browser.js +145 -145
  14. package/hdoc-mermaid.js +204 -204
  15. package/hdoc-module.js +1102 -1079
  16. package/hdoc-serve.js +13 -7
  17. package/hdoc-stats.js +9 -9
  18. package/hdoc-validate-config.js +355 -329
  19. package/hdoc-validate-interbook.js +321 -0
  20. package/hdoc-validate.js +1231 -1158
  21. package/hdoc-ver.js +4 -2
  22. package/hdoc.js +12 -11
  23. package/npm-shrinkwrap.json +2 -2
  24. package/package.json +13 -2
  25. package/schemas/hdocbook-project.schema.json +20 -0
  26. package/schemas/hdocbook.schema.json +6 -2
  27. package/templates/doc-header-non-git.html +19 -19
  28. package/templates/doc-header.html +26 -26
  29. package/templates/init/.github/workflows/hdocbuild_onpull.yml +16 -16
  30. package/templates/init/.github/workflows/hdocbuild_onpush.yml +15 -15
  31. package/templates/init/LICENSE +21 -21
  32. package/templates/init/README.md +9 -9
  33. package/templates/init/_hdocbook/index.md +4 -4
  34. package/templates/init/gitignore +8 -8
  35. package/templates/init/resources/README.md +2 -2
  36. package/templates/pdf/css/custom-block.css +90 -90
  37. package/templates/pdf/css/fonts.css +221 -221
  38. package/templates/pdf/css/hdocs-pdf.css +495 -495
  39. package/templates/pdf/css/vars.css +404 -404
  40. package/templates/pdf/template-footer.html +19 -19
  41. package/templates/pdf/template-header.html +37 -37
  42. package/templates/pdf/template.html +20 -20
  43. package/templates/pdf-header-non-git.html +12 -12
  44. package/templates/pdf-header.html +16 -16
  45. package/ui/content/invalid-hdocbook-json.html +6 -6
  46. package/ui/content/invalid-hdocbook-json.md +7 -7
  47. package/ui/css/theme-default/styles/components/content.css +124 -124
  48. package/ui/css/theme-default/styles/components/sidebar.css +182 -182
  49. package/ui/css/theme-default/styles/htldoc.layouts.css +310 -310
  50. package/ui/index.html +419 -419
  51. package/ui/js/doc.hornbill.js +31 -44
  52. package/ui/js/mermaid-theme.json +27 -0
  53. package/hdoc-build-onyx.js +0 -134
  54. package/templates/mermaid-theme.yaml +0 -28
  55. package/templates/pdf/fonts/inter-cyrillic copy.woff2 +0 -0
@@ -7,36 +7,14 @@ let jqDocumentHeader = null;
7
7
  let jqLeftNav = null;
8
8
  const global = { stateParams: {}, lastLayoutClass: "" };
9
9
 
10
- //-- Mermaid client-side rendering config — mirrors templates/mermaid-theme.yaml.
11
- //-- (PDFs are still rendered to SVG server-side by hdoc build; this is HTML-only.)
12
- const HB_MERMAID_CONFIG = {
13
- startOnLoad: false,
14
- theme: "base",
15
- themeVariables: {
16
- background: "transparent",
17
- fontSize: "14px",
18
- primaryColor: "#85D2FF",
19
- primaryColorLight: "#85D2FF",
20
- primaryColorDark: "#0065CB",
21
- secondaryColor: "#219BFF",
22
- secondaryColorLight: "#85D2FF",
23
- secondaryColorDark: "#0C4C8C",
24
- tertiaryColor: "#219BFF",
25
- tertiaryColorLight: "#85D2FF",
26
- tertiaryColorDark: "#0C4C8C",
27
- lineColor: "#808080",
28
- border1: "#606060",
29
- textColor: "#A0A0A0",
30
- titleColor: "#A0A0A0",
31
- labelColor: "#404040",
32
- loopTextColor: "#A0A0A0",
33
- nodeTextColor: "#404040",
34
- labelTextColor: "#404040",
35
- pieSectionTextColor: "#404040",
36
- nodeBorder: "#219BFF",
37
- nodeBg: "transparent",
38
- },
39
- };
10
+ //-- Mermaid theme lives in js/mermaid-theme.json — the SINGLE source shared
11
+ //-- with the server-side PDF SVG bake (hdoc build reads the same file). Fetch
12
+ //-- failure falls back to the plain base theme rather than blocking rendering.
13
+ function hbFetchMermaidTheme() {
14
+ return fetch("js/mermaid-theme.json") //-- resolves against <base href>
15
+ .then((r) => (r.ok ? r.json() : null))
16
+ .catch(() => null);
17
+ }
40
18
 
41
19
  //-- Lazy-load the Mermaid bundle (~3MB) only when a page actually contains a
42
20
  //-- diagram. Resolves to window.mermaid, initialised once.
@@ -44,20 +22,29 @@ let hbMermaidLoadPromise = null;
44
22
  function hbLoadMermaid() {
45
23
  if (window.mermaid) return Promise.resolve(window.mermaid);
46
24
  if (hbMermaidLoadPromise) return hbMermaidLoadPromise;
47
- hbMermaidLoadPromise = new Promise((resolve, reject) => {
48
- const el = document.createElement("script");
49
- el.src = "js/mermaid.min.js"; //-- resolves against <base href> (site root)
50
- el.onload = () => {
51
- try {
52
- window.mermaid.initialize(HB_MERMAID_CONFIG);
53
- resolve(window.mermaid);
54
- } catch (e) {
55
- reject(e);
56
- }
57
- };
58
- el.onerror = () => reject(new Error("failed to load js/mermaid.min.js"));
59
- document.head.appendChild(el);
60
- });
25
+ hbMermaidLoadPromise = hbFetchMermaidTheme().then(
26
+ (theme) =>
27
+ new Promise((resolve, reject) => {
28
+ const el = document.createElement("script");
29
+ el.src = "js/mermaid.min.js"; //-- resolves against <base href> (site root)
30
+ el.onload = () => {
31
+ try {
32
+ window.mermaid.initialize(
33
+ Object.assign(
34
+ { startOnLoad: false },
35
+ theme || { theme: "base" },
36
+ ),
37
+ );
38
+ resolve(window.mermaid);
39
+ } catch (e) {
40
+ reject(e);
41
+ }
42
+ };
43
+ el.onerror = () =>
44
+ reject(new Error("failed to load js/mermaid.min.js"));
45
+ document.head.appendChild(el);
46
+ }),
47
+ );
61
48
  return hbMermaidLoadPromise;
62
49
  }
63
50
 
@@ -0,0 +1,27 @@
1
+ {
2
+ "theme": "base",
3
+ "themeVariables": {
4
+ "background": "transparent",
5
+ "fontSize": "14px",
6
+ "primaryColor": "#85D2FF",
7
+ "primaryColorLight": "#85D2FF",
8
+ "primaryColorDark": "#0065CB",
9
+ "secondaryColor": "#219BFF",
10
+ "secondaryColorLight": "#85D2FF",
11
+ "secondaryColorDark": "#0C4C8C",
12
+ "tertiaryColor": "#219BFF",
13
+ "tertiaryColorLight": "#85D2FF",
14
+ "tertiaryColorDark": "#0C4C8C",
15
+ "lineColor": "#808080",
16
+ "border1": "#606060",
17
+ "textColor": "#A0A0A0",
18
+ "titleColor": "#A0A0A0",
19
+ "labelColor": "#404040",
20
+ "loopTextColor": "#A0A0A0",
21
+ "nodeTextColor": "#404040",
22
+ "labelTextColor": "#404040",
23
+ "pieSectionTextColor": "#404040",
24
+ "nodeBorder": "#219BFF",
25
+ "nodeBg": "transparent"
26
+ }
27
+ }
@@ -1,134 +0,0 @@
1
- (() => {
2
- const fs = require("node:fs");
3
- const path = require("node:path");
4
-
5
- // Replicates the URL normalisation logic from populate_index so page keys match.
6
- function to_page_path(file) {
7
- let p = file.relative_path.replaceAll("\\", "/");
8
- if (
9
- p.endsWith("/index.md") ||
10
- p.endsWith("/index.html") ||
11
- p.endsWith("/index.htm")
12
- ) {
13
- p = p.substring(0, p.lastIndexOf("/"));
14
- }
15
- return `/${p.replace(path.extname(file.relative_path), "")}`;
16
- }
17
-
18
- // Groups index_records into one entry per page, preserving section order.
19
- function build_pages(index_records) {
20
- const pages = new Map();
21
- for (const file of index_records) {
22
- if (file.inline) continue;
23
- const page_path = to_page_path(file);
24
- if (!pages.has(page_path)) {
25
- pages.set(page_path, {
26
- page_path,
27
- title: file.index_html.fm_props.title || "",
28
- keywords: file.keywords || "",
29
- status: file.status || "release",
30
- lastmod: file.lastmod || null,
31
- sections: [],
32
- });
33
- }
34
- const text = (file.index_html.text || "").trim();
35
- if (text) pages.get(page_path).sections.push(text);
36
- }
37
- return Array.from(pages.values());
38
- }
39
-
40
- // Returns an ISO 8601 string, or null if the value is absent or unparseable.
41
- function safe_iso(value) {
42
- if (!value) return null;
43
- const d = new Date(value);
44
- return Number.isNaN(d.getTime()) ? null : d.toISOString();
45
- }
46
-
47
- exports.populate_onyx_index = (
48
- work_path_content,
49
- doc_id,
50
- book_config,
51
- index_records,
52
- base_url = "",
53
- verbose = false,
54
- ) => {
55
- const response = {
56
- success: false,
57
- document_count: 0,
58
- error: "",
59
- };
60
-
61
- const pages = build_pages(index_records);
62
- const canonical_base = base_url.replace(/\/$/, "");
63
- const metadata_entries = [];
64
-
65
- for (const page of pages) {
66
- // e.g. onyx/getting-started/index.txt or onyx/reference/api.txt
67
- const txt_rel = `_onyx${page.page_path}.txt`;
68
- const txt_abs = path.join(work_path_content, txt_rel);
69
-
70
- fs.mkdirSync(path.dirname(txt_abs), { recursive: true });
71
-
72
- // Plain-text body: title, keywords hint, then each section separated by
73
- // a blank line so Onyx's chunker sees natural paragraph boundaries.
74
- const lines = [];
75
- if (page.title) lines.push(page.title, "");
76
- if (page.keywords) lines.push(`Keywords: ${page.keywords}`, "");
77
- for (const section of page.sections) {
78
- lines.push(section, "");
79
- }
80
-
81
- try {
82
- fs.writeFileSync(txt_abs, lines.join("\n").trimEnd(), "utf8");
83
- } catch (e) {
84
- response.error = `Failed to write ${txt_rel}: ${e.message}`;
85
- return response;
86
- }
87
-
88
- if (verbose) console.log(`Onyx: wrote ${txt_rel}`);
89
-
90
- const entry = {
91
- filename: txt_rel.replaceAll("\\", "/"),
92
- link: canonical_base
93
- ? `${canonical_base}${page.page_path}`
94
- : page.page_path,
95
- primary_owners: [],
96
- secondary_owners: [],
97
- metadata: {
98
- book_id: doc_id,
99
- product_family: book_config.productFamily || "",
100
- audience: Array.isArray(book_config.audience)
101
- ? book_config.audience.join(",")
102
- : "",
103
- tags: Array.isArray(book_config.tags)
104
- ? book_config.tags.join(",")
105
- : "",
106
- status: page.status,
107
- },
108
- };
109
- const updated_at = safe_iso(page.lastmod);
110
- if (updated_at) entry.doc_updated_at = updated_at;
111
- metadata_entries.push(entry);
112
-
113
- response.document_count++;
114
- }
115
-
116
- const meta_path = path.join(work_path_content, ".onyx_metadata.json");
117
- try {
118
- fs.writeFileSync(
119
- meta_path,
120
- JSON.stringify(metadata_entries, null, 2),
121
- "utf8",
122
- );
123
- } catch (e) {
124
- response.error = `Failed to write .onyx_metadata.json: ${e.message}`;
125
- return response;
126
- }
127
-
128
- response.success = true;
129
- console.log(
130
- `\nOnyx Index Build Complete: ${response.document_count} document records created.`,
131
- );
132
- return response;
133
- };
134
- })();
@@ -1,28 +0,0 @@
1
- config:
2
- theme: 'base'
3
- themeVariables:
4
- background: transparent
5
- fontSize: 14px
6
- primaryColor: "#85D2FF" # Medium blue
7
- primaryColorLight: "#85D2FF" # Light accent blue
8
- primaryColorDark: "#0065CB" # Medium-dark blue
9
-
10
- secondaryColor: "#219BFF" # Medium blue
11
- secondaryColorLight: "#85D2FF" # Light accent blue
12
- secondaryColorDark: "#0C4C8C" # Medium-dark blue
13
-
14
- tertiaryColor: "#219BFF" # Medium blue
15
- tertiaryColorLight: "#85D2FF" # Light accent blue
16
- tertiaryColorDark: "#0C4C8C" # Medium-dark blue
17
-
18
- lineColor: "#808080" # Medium grey for lines
19
- border1: "#606060" # Darker grey for borders
20
- textColor: "#A0A0A0" # Light grey text (visible on both)
21
- titleColor: "#A0A0A0"
22
- labelColor: "#404040"
23
- loopTextColor: "#A0A0A0"
24
- nodeTextColor: "#404040"
25
- labelTextColor: "#404040"
26
- pieSectionTextColor: "#404040"
27
- nodeBorder: "#219BFF" # Match node border to primary blue
28
- nodeBg: transparent