hdoc-tools 0.40.0 → 0.41.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/hdoc-build.js +58 -0
- package/hdoc-serve.js +94 -64
- package/hdoc-validate.js +1 -1
- package/package.json +4 -2
- package/templates/mermaid-theme.yaml +28 -0
package/hdoc-build.js
CHANGED
@@ -13,6 +13,9 @@
|
|
13
13
|
const archiver = require("archiver");
|
14
14
|
const xmlFormat = require("xml-formatter");
|
15
15
|
|
16
|
+
const { execSync } = require("child_process");
|
17
|
+
const tmp = require("tmp");
|
18
|
+
|
16
19
|
const h_tags_to_search = ["h1", "h2", "h3"];
|
17
20
|
const image_extensions = ["png", "svg", "jpg"];
|
18
21
|
const doc_header_template_path = path.join(
|
@@ -35,6 +38,13 @@
|
|
35
38
|
"templates",
|
36
39
|
"pdf-header-non-git.html",
|
37
40
|
);
|
41
|
+
|
42
|
+
const mermaid_theme_path = path.resolve(
|
43
|
+
__dirname,
|
44
|
+
"templates",
|
45
|
+
"mermaid-theme.yaml",
|
46
|
+
);
|
47
|
+
|
38
48
|
const pdf_template_path = path.join(__dirname, "templates", "pdf");
|
39
49
|
const ui_css_path = path.join(__dirname, "ui", "css");
|
40
50
|
const pdf_template_file_path = path.join(pdf_template_path, "template.html");
|
@@ -52,6 +62,7 @@
|
|
52
62
|
const md_files_delete = [];
|
53
63
|
const redirects = {};
|
54
64
|
const static_html_files = [];
|
65
|
+
const mermaid_failures = [];
|
55
66
|
|
56
67
|
let bc = {}; // Breadcrumbs map
|
57
68
|
let book_read_time = 0;
|
@@ -508,6 +519,38 @@
|
|
508
519
|
html: true,
|
509
520
|
linkify: true,
|
510
521
|
typographer: true,
|
522
|
+
highlight: function (str, lang) {
|
523
|
+
if (lang === "mermaid") {
|
524
|
+
try {
|
525
|
+
const tmpInput = tmp.fileSync({ postfix: ".mmd" });
|
526
|
+
const tmpOutput = tmp.fileSync({ postfix: ".svg" });
|
527
|
+
|
528
|
+
if (!str.startsWith('---')) {
|
529
|
+
str = '---\n' + fs.readFileSync(mermaid_theme_path, {encoding: 'utf-8'}) + `\n---\n${str}`;
|
530
|
+
}
|
531
|
+
|
532
|
+
fs.writeFileSync(tmpInput.name, str);
|
533
|
+
|
534
|
+
const cmd = `${__dirname}/node_modules/.bin/mmdc -i "${tmpInput.name}" -o "${tmpOutput.name}" --quiet --backgroundColor transparent`;
|
535
|
+
console.log(`Generating Inline Mermaid SVG found in: ${file_path.relativePath}`);
|
536
|
+
execSync(cmd);
|
537
|
+
|
538
|
+
if (!fs.existsSync(tmpOutput.name)) {
|
539
|
+
throw new Error("mmdc did not generate output");
|
540
|
+
}
|
541
|
+
|
542
|
+
const svg = fs.readFileSync(tmpOutput.name, "utf8");
|
543
|
+
|
544
|
+
tmpInput.removeCallback();
|
545
|
+
tmpOutput.removeCallback();
|
546
|
+
|
547
|
+
return `<div class="text-body">${svg}</div>`;
|
548
|
+
} catch (err) {
|
549
|
+
mermaid_failures.push({path: file_path.relativePath, error: err.message});
|
550
|
+
return ``;
|
551
|
+
}
|
552
|
+
}
|
553
|
+
}
|
511
554
|
});
|
512
555
|
md.linkify.set({
|
513
556
|
fuzzyEmail: false,
|
@@ -1396,6 +1439,21 @@
|
|
1396
1439
|
console.log(` PDF Files Created: ${pdf_created}\n`);
|
1397
1440
|
}
|
1398
1441
|
|
1442
|
+
|
1443
|
+
if (mermaid_failures.length > 0) {
|
1444
|
+
console.log("\r\n-----------------------");
|
1445
|
+
console.log(" Validation Output ");
|
1446
|
+
console.log("-----------------------");
|
1447
|
+
console.log(
|
1448
|
+
`\n${mermaid_failures.length} errors found when processing markdown SVG generation:\n`,
|
1449
|
+
);
|
1450
|
+
for (const key in mermaid_failures) {
|
1451
|
+
console.error(` - ${mermaid_failures[key].path}:\n${mermaid_failures[key].error}`);
|
1452
|
+
}
|
1453
|
+
console.log("\n");
|
1454
|
+
process.exit(1);
|
1455
|
+
}
|
1456
|
+
|
1399
1457
|
// Validate content
|
1400
1458
|
const validation_success = await hdoc_validate.run(
|
1401
1459
|
work_path,
|
package/hdoc-serve.js
CHANGED
@@ -6,7 +6,16 @@
|
|
6
6
|
const stream = require("node:stream");
|
7
7
|
|
8
8
|
const yaml = require("js-yaml");
|
9
|
-
const mdfm = require("markdown-it-front-matter");
|
9
|
+
const mdfm = require("markdown-it-front-matter");
|
10
|
+
|
11
|
+
const { execSync } = require("child_process");
|
12
|
+
const tmp = require("tmp");
|
13
|
+
|
14
|
+
const mermaid_theme_path = path.resolve(
|
15
|
+
__dirname,
|
16
|
+
"templates",
|
17
|
+
"mermaid-theme.yaml",
|
18
|
+
);
|
10
19
|
|
11
20
|
let port = 3000;
|
12
21
|
let docId;
|
@@ -105,78 +114,98 @@
|
|
105
114
|
});
|
106
115
|
|
107
116
|
async function transform_markdown_and_send_html(req, res, file_path) {
|
108
|
-
if (fs.existsSync(file_path))
|
109
|
-
// we have a markdown representation of the requested HTML file, transform and return
|
110
|
-
// it to the caller
|
111
|
-
|
112
|
-
// Load markdown file
|
113
|
-
let md_txt = hdoc.expand_variables(
|
114
|
-
fs.readFileSync(file_path).toString(),
|
115
|
-
docId,
|
116
|
-
);
|
117
|
-
|
118
|
-
// Pull in external includes
|
119
|
-
const includes_processed = await hdoc.process_includes(
|
120
|
-
file_path,
|
121
|
-
md_txt,
|
122
|
-
global_source_path,
|
123
|
-
);
|
124
|
-
md_txt = includes_processed.body;
|
125
|
-
if (includes_processed.errors && includes_processed.errors.length > 0) {
|
126
|
-
console.error(`Error(s) when processing includes in ${file_path}`);
|
127
|
-
for (let i = 0; i < includes_processed.errors.length; i++) {
|
128
|
-
console.error(includes_processed.errors[i]);
|
129
|
-
}
|
130
|
-
} else {
|
131
|
-
if (includes_processed.success > 0) {
|
132
|
-
console.log(
|
133
|
-
`Includes injected into document: ${includes_processed.success}`,
|
134
|
-
);
|
135
|
-
}
|
136
|
-
}
|
137
|
-
|
138
|
-
const md = require("markdown-it")({
|
139
|
-
// enable everything
|
140
|
-
html: true,
|
141
|
-
linkify: true,
|
142
|
-
typographer: true,
|
143
|
-
});
|
117
|
+
if (!fs.existsSync(file_path)) return false;
|
144
118
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
});
|
150
|
-
let frontmatter_content = "";
|
151
|
-
md.use(mdfm, (fm) => {
|
152
|
-
frontmatter_content = fm;
|
153
|
-
});
|
154
|
-
|
155
|
-
const tips = require(`${__dirname}/custom_modules/tips.js`);
|
156
|
-
md.use(tips, {
|
157
|
-
links: true,
|
158
|
-
});
|
159
|
-
|
160
|
-
// Render markdown into HTML
|
161
|
-
const html_txt = md.render(md_txt.toString());
|
119
|
+
let md_txt = hdoc.expand_variables(
|
120
|
+
fs.readFileSync(file_path).toString(),
|
121
|
+
docId,
|
122
|
+
);
|
162
123
|
|
163
|
-
|
164
|
-
|
124
|
+
const includes_processed = await hdoc.process_includes(
|
125
|
+
file_path,
|
126
|
+
md_txt,
|
127
|
+
global_source_path,
|
128
|
+
);
|
129
|
+
md_txt = includes_processed.body;
|
130
|
+
const md = require("markdown-it")({
|
131
|
+
html: true,
|
132
|
+
linkify: true,
|
133
|
+
typographer: true,
|
134
|
+
highlight: function (str, lang) {
|
135
|
+
if (lang === "mermaid") {
|
136
|
+
try {
|
137
|
+
const tmpInput = tmp.fileSync({ postfix: ".mmd" });
|
138
|
+
const tmpOutput = tmp.fileSync({ postfix: ".svg" });
|
139
|
+
|
140
|
+
if (!str.startsWith('---')) {
|
141
|
+
str = '---\n' + fs.readFileSync(mermaid_theme_path, {encoding: 'utf-8'}) + `\n---\n${str}`;
|
142
|
+
}
|
143
|
+
|
144
|
+
fs.writeFileSync(tmpInput.name, str);
|
145
|
+
|
146
|
+
const cmd = `${__dirname}/node_modules/.bin/mmdc -i "${tmpInput.name}" -o "${tmpOutput.name}" --quiet --backgroundColor transparent`;
|
147
|
+
console.log(`Generating Inline Mermaid SVG found in: ${file_path}`);
|
148
|
+
execSync(cmd);
|
149
|
+
|
150
|
+
if (!fs.existsSync(tmpOutput.name)) {
|
151
|
+
throw new Error("mmdc did not generate output");
|
152
|
+
}
|
153
|
+
|
154
|
+
const svg = fs.readFileSync(tmpOutput.name, "utf8");
|
155
|
+
|
156
|
+
tmpInput.removeCallback();
|
157
|
+
tmpOutput.removeCallback();
|
158
|
+
|
159
|
+
return `<div class="text-body">${svg}</div>`;
|
160
|
+
} catch (err) {
|
161
|
+
return `<div class="alert alert-danger mb-0 text-break"
|
162
|
+
role="alert"
|
163
|
+
data-bs-toggle="collapse"
|
164
|
+
data-bs-target="#alertContent"
|
165
|
+
aria-expanded="false"
|
166
|
+
aria-controls="alertContent">
|
167
|
+
<div>
|
168
|
+
<strong>Error!</strong> Mermaid was unable to generate the SVG expected here. Click for more details
|
169
|
+
</div>
|
170
|
+
<div class="collapse mt-3" id="alertContent">
|
171
|
+
<p class="mb-0 text-break">
|
172
|
+
${err.message}
|
173
|
+
</p>
|
174
|
+
</div>
|
175
|
+
</div>`;
|
176
|
+
}
|
177
|
+
}
|
178
|
+
}
|
179
|
+
});
|
180
|
+
md.linkify.set({
|
181
|
+
fuzzyEmail: false,
|
182
|
+
fuzzyLink: false,
|
183
|
+
fuzzyIP: false,
|
184
|
+
});
|
165
185
|
|
166
|
-
|
186
|
+
let frontmatter_content = "";
|
187
|
+
md.use(mdfm, (fm) => {
|
188
|
+
frontmatter_content = fm;
|
189
|
+
});
|
167
190
|
|
168
|
-
|
191
|
+
const tips = require(`${__dirname}/custom_modules/tips.js`);
|
192
|
+
md.use(tips, { links: true });
|
169
193
|
|
170
|
-
|
171
|
-
}
|
194
|
+
const html_txt = md.render(md_txt.toString());
|
172
195
|
|
173
|
-
|
174
|
-
|
175
|
-
|
196
|
+
if (frontmatter_content.length) {
|
197
|
+
const obj = yaml.load(frontmatter_content);
|
198
|
+
const buff = Buffer.from(JSON.stringify(obj), "utf-8");
|
199
|
+
const base64 = buff.toString("base64");
|
200
|
+
res.setHeader("X-frontmatter", base64);
|
176
201
|
}
|
177
|
-
|
202
|
+
|
203
|
+
res.setHeader("Content-Type", "text/html");
|
204
|
+
res.send(html_txt);
|
205
|
+
return true;
|
178
206
|
}
|
179
207
|
|
208
|
+
|
180
209
|
function send_content_file(req, res, file_path, redirected = false) {
|
181
210
|
let content_txt = hdoc.expand_variables(
|
182
211
|
fs.readFileSync(file_path).toString(),
|
@@ -386,4 +415,5 @@
|
|
386
415
|
}
|
387
416
|
});
|
388
417
|
};
|
418
|
+
|
389
419
|
})();
|
package/hdoc-validate.js
CHANGED
@@ -474,8 +474,8 @@ const e = require("express");
|
|
474
474
|
|
475
475
|
for (let i = 0; i < links.length; i++) {
|
476
476
|
// Validate that link is a valid URL first
|
477
|
-
if (exclude_links[links[i]]) continue;
|
478
477
|
console.log(` - ${links[i]}`);
|
478
|
+
if (exclude_links[links[i]]) continue;
|
479
479
|
if (global_links_checked.includes(links[i])) continue;
|
480
480
|
global_links_checked.push(links[i]);
|
481
481
|
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "hdoc-tools",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.41.1",
|
4
4
|
"description": "Hornbill HDocBook Development Support Tool",
|
5
5
|
"main": "hdoc.js",
|
6
6
|
"bin": {
|
@@ -51,10 +51,12 @@
|
|
51
51
|
"markdown-it": "14.1.0",
|
52
52
|
"markdown-it-container": "^4.0.0",
|
53
53
|
"markdown-it-front-matter": "^0.2.4",
|
54
|
+
"@mermaid-js/mermaid-cli": "11.6.0",
|
54
55
|
"mime-types": "^2.1.35",
|
55
56
|
"prompt": "^1.3.0",
|
56
|
-
"puppeteer": "^
|
57
|
+
"puppeteer": "^23.11.1",
|
57
58
|
"stream": "0.0.3",
|
59
|
+
"tmp": "^0.2.3",
|
58
60
|
"true-case-path": "^2.2.1",
|
59
61
|
"words-count": "^2.0.2",
|
60
62
|
"xml-formatter": "^3.6.2"
|
@@ -0,0 +1,28 @@
|
|
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
|