hdoc-tools 0.19.8 → 0.20.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.js CHANGED
@@ -1,361 +1,390 @@
1
- (function () {
2
- 'use strict';
3
-
4
- const express = require('express'),
5
- fs = require('fs'),
6
- path = require('path'),
7
- hdoc = require(path.join(__dirname, 'hdoc-module.js')),
8
- stream = require('stream');
9
-
10
- const yaml = require('js-yaml');
11
- const mdfm = require('markdown-it-front-matter');
12
-
13
- let port = 3000;
14
- let docId;
15
- let hdocbook_config,
16
- hdocbook_project,
17
- inline_content = {},
18
- global_source_path = '';
19
-
20
- exports.run = async function (ui_path, source_path) {
21
-
22
- global_source_path = source_path;
23
- for (let x = 0; x < process.argv.length; x++) {
24
- // First two arguments are command, and script
25
- if (x == 0 || x == 1)
26
- continue;
27
-
28
- if (process.argv[x] == '-port') {
29
- x++;
30
- if (x < process.argv.length) {
31
- port = process.argv[x];
32
- }
33
- }
34
- }
35
-
36
- console.log('Hornbill HDocBook Preview/Dev Server', '\r\n');
37
- console.log(' UI Root Path:', ui_path);
38
- console.log(' Document Path:', source_path, '\r\n');
39
- console.log(' Server Port:', port);
40
-
41
- if (fs.existsSync(path.join(source_path, 'hdocbook-project.json')) == false) {
42
- console.error("No hdocbook-project.json file found in working folder. Unable to continue.");
43
- return -1;
44
- }
45
-
46
- // In the root of the project there is a hdocbook.json file which includes
47
- // the id of the hdocbook we are working with
48
- const hdocbook_project_config_path = path.join(source_path, 'hdocbook-project.json');
49
-
50
- // Load the hdocbook config file
51
- try {
52
- hdocbook_project = require(hdocbook_project_config_path);
53
- } catch (e) {
54
- console.error(`\nFailed to load hdocbook-project.json:\n${e}\n`);
55
- process.exit(1);
56
- }
57
-
58
- // Get the ID of the hdocbook we are serving
59
- docId = hdocbook_project.docId;
60
-
61
- // Get inline content for nav
62
- const inline_path = path.join(source_path, docId, '_inline');
63
- let nav_inline = {};
64
- if (fs.existsSync(inline_path)) {
65
- const inline_files = fs.readdirSync(inline_path);
66
- nav_inline = {
67
- text: 'Inline Help Items',
68
- expand: true,
69
- inline: true,
70
- items: []
71
- };
72
- inline_files.forEach(file => {
73
- nav_inline.items.push({
74
- text: file.replace(path.extname(file), ''),
75
- link: `${docId}/_inline/${file.replace(path.extname(file), '')}`
76
- });
77
- });
78
- }
79
- // Get an express server instance
80
- var app = express();
81
-
82
- // Get the path of the book.json file
83
- const hdocbook_path = path.join(source_path, docId, 'hdocbook.json');
84
-
85
- // Pull in the book config file
86
- try {
87
- hdocbook_config = require(hdocbook_path);
88
- } catch (e) {
89
- console.error(`\nFailed to load hdocbook.json:${e}\n`);
90
- process.exit(1);
91
- }
92
-
93
- app.get('/_books/library.json', function (req, res) {
94
- let library = {
95
- books: [{
96
- docId: hdocbook_config.docId,
97
- title: hdocbook_config.title,
98
- nav_inline: nav_inline
99
- }]
100
- };
101
- res.setHeader('Content-Type', 'application/json');
102
- res.send(JSON.stringify(library, null, 3));
103
- });
104
-
105
- async function transform_markdown_and_send_html(req, res, file_path) {
106
-
107
- if (fs.existsSync(file_path)) {
108
- // we have a markdown representation of the requested HTML file, transform and return
109
- // it to the caller
110
-
111
- // Load markdown file
112
- let md_txt = hdoc.expand_variables(fs.readFileSync(file_path).toString(), docId);
113
-
114
- // Pull in external includes
115
- const includes_processed = await hdoc.process_includes(file_path, md_txt, global_source_path);
116
- md_txt = includes_processed.body;
117
- if (includes_processed.errors && includes_processed.errors.length > 0) {
118
- console.error(`Error(s) when processing includes in ${file_path}`);
119
- for (let i = 0; i < includes_processed.errors.length; i++) {
120
- console.error(includes_processed.errors[i]);
121
- }
122
- } else {
123
- if (includes_processed.success > 0) {
124
- console.log(`Includes injected into document: ${includes_processed.success}`);
125
- }
126
- }
127
-
128
- const md = require('markdown-it')({
129
- // enable everything
130
- html: true,
131
- linkify: true,
132
- typographer: true
133
- });
134
-
135
- md.linkify.set({
136
- fuzzyEmail: false,
137
- fuzzyLink: false,
138
- fuzzyIP: false
139
- });
140
- var frontmatter_content = "";
141
- md.use(mdfm, function (fm) {
142
- frontmatter_content = fm;
143
- });
144
-
145
- const tips = require(__dirname + '/custom_modules/tips.js');
146
- md.use(tips, {
147
- links: true
148
- });
149
-
150
- // Render markdown into HTML
151
- var html_txt = md.render(md_txt.toString());
152
-
153
- if (frontmatter_content.length) {
154
-
155
- const obj = yaml.load(frontmatter_content);
156
-
157
- const buff = Buffer.from(JSON.stringify(obj), 'utf-8');
158
-
159
- const base64 = buff.toString('base64');
160
-
161
- res.setHeader('X-frontmatter', base64);
162
- }
163
-
164
- res.setHeader('Content-Type', 'text/html');
165
- res.send(html_txt);
166
- return true;
167
- }
168
- return false;
169
- }
170
-
171
- function send_content_file(req, res, file_path, redirected = false) {
172
- let content_txt = hdoc.expand_variables(fs.readFileSync(file_path).toString(), docId);
173
- if (redirected)
174
- content_txt = `Redirected from ${redirected}\n\n${content_txt}`;
175
-
176
- let contentType = hdoc.content_type_for_ext(path.extname(file_path));
177
-
178
- if (path.extname(file_path) == '.md') {
179
- res.setHeader('Content-Disposition', 'inline');
180
- }
181
-
182
- res.setHeader('Content-Type', contentType);
183
-
184
- res.send(content_txt);
185
- }
186
-
187
- function send_file(req, res, file_path) {
188
- // Need to set the content type here??
189
- let contentType = hdoc.content_type_for_ext(path.extname(file_path));
190
- res.setHeader('Content-Type', contentType);
191
-
192
- const r = fs.createReadStream(file_path);
193
- const ps = new stream.PassThrough();
194
- stream.pipeline(
195
- r,
196
- ps,
197
- (err) => {
198
- if (err) {
199
- console.error(err); // No such file or any other kind of error
200
- return res.sendStatus(400).send('Unexpected error');
201
- }
202
- });
203
- ps.pipe(res);
204
- }
205
-
206
- function send_content_resource_404(req, res) {
207
- res.setHeader('Content-Type', 'text/html');
208
- res.status(404).send('Content resource not found');
209
- }
210
-
211
- // 1. If we request a file with a .html file extension, and that file DOES NOT exist,
212
- // we will look for the same file but with a .md extension. If we find that
213
- // corresponding markdown file, we will transform that markdown file to HTML and
214
- // return the HTML content
215
- //
216
- // 2. If we request a file, without any file extension then we will look for that file
217
- // with a .md extension, and if that file exists, we will transform that markdown
218
- // file to HTML and return that file.
219
- //
220
- // For all other requests, we are going to look on the filesystem. If we request
221
- // a specific file with its extension (including .md files), then we will simply
222
- // return the file verbatim as a static file.
223
- //
224
- // If we request a file without an extension and that file does not exist, we will
225
- // assume that is a folder, will append index.html and look for that file, if present
226
- // we will send it, if not present we will look for index.md, and if thats present
227
- // we will transform to HTML and return that
228
- //
229
- // Anything else in this handler will return a 404 error
230
-
231
- app.get('/_books/*', function (req, res) {
232
-
233
- let url = req.url.replace('/_books/', '/');
234
-
235
- console.log('URL Requested:', url);
236
-
237
- // Process redirect
238
- if (hdocbook_project.redirects && hdocbook_project.redirects instanceof Array && hdocbook_project.redirects.length > 0) {
239
- const source_url = url.indexOf('/') === 0 ? url : `/${url}`;
240
- hdocbook_project.redirects.forEach(function (redir) {
241
- redir.url = redir.url.indexOf('/') === 0 ? redir.url : `/${redir.url}`
242
- if (redir.url === source_url && redir.location && redir.location !== '') {
243
- url = `${redir.location}`;
244
- console.log(`Redirecting to ${url}`);
245
- }
246
- });
247
- }
248
-
249
- let file_path = path.join(source_path, url);
250
-
251
- if (path.extname(file_path) == '.html') {
252
- // 1a. check for html files, and send/transform as required
253
- if (fs.existsSync(file_path)) {
254
- // HTML file exists on disk, just return it verbatim
255
- res.setHeader('Content-Type', 'text/html');
256
- send_file(req, res, file_path);
257
- return true;
258
- }
259
- if (fs.existsSync(file_path.replace('.html', '.md'))) {
260
- if (transform_markdown_and_send_html(req, res, file_path.replace('.html', '.md'))) {
261
- return;
262
- }
263
- }
264
-
265
- } else if (path.extname(file_path) == '.md') {
266
- // If the markdown file exists, just send to caller as is
267
- if (fs.existsSync(file_path)) {
268
- send_content_file(req, res, file_path);
269
- return true;
270
- }
271
-
272
- } else if (path.extname(file_path).length == 0) {
273
- // 2. If we request a file, without any file extension
274
- if (fs.existsSync(file_path + '.md')) {
275
- if (transform_markdown_and_send_html(req, res, file_path + '.md')) {
276
- return;
277
- }
278
- } else if (fs.existsSync(path.join(file_path + 'index.md'))) {
279
- if (transform_markdown_and_send_html(req, res, path.join(file_path, 'index.md'))) {
280
- return;
281
- }
282
- } else if (fs.existsSync(path.join(file_path + 'index.html'))) {
283
- res.setHeader('Content-Type', 'text/html');
284
- send_content_file(req, res, path.join(file_path + 'index.html'));
285
- return;
286
- } else if (fs.existsSync(file_path + '/index.md')) {
287
- if (transform_markdown_and_send_html(req, res, file_path + '/index.md')) {
288
- return;
289
- }
290
- } else if (fs.existsSync(path.join(file_path + '/index.html'))) {
291
- res.setHeader('Content-Type', 'text/html');
292
- send_content_file(req, res, path.join(file_path + '/index.html'));
293
- return;
294
- } else if (fs.existsSync(path.join(file_path + '.html'))) {
295
- res.setHeader('Content-Type', 'text/html');
296
- send_content_file(req, res, path.join(file_path + '.html'));
297
- return;
298
- } else if (fs.existsSync(path.join(file_path + '.htm'))) {
299
- res.setHeader('Content-Type', 'text/html');
300
- send_content_file(req, res, path.join(file_path + '.htm'));
301
- return;
302
- }
303
- } else if (fs.existsSync(file_path)) {
304
- if (file_path.endsWith('hdocbook.json') || file_path.endsWith('hdocbook_project.json')) {
305
- try {
306
- // Read & parse file
307
- JSON.parse(fs.readFileSync(file_path));
308
- } catch (e) {
309
- console.error(`Error parsing hdocbook.json: ${e}`);
310
-
311
- }
312
- }
313
- send_file(req, res, file_path);
314
- return;
315
- }
316
-
317
- // Return a 404 error here
318
- send_content_resource_404(req, res);
319
- });
320
-
321
- // Catch all
322
- app.get('/*', function (req, res) {
323
-
324
- let segs = req.url.split('/');
325
-
326
- let ui_file_path = path.join(ui_path, req.url);
327
-
328
- // To support the SPA application behavior, if there is no file extension present, then
329
- // we simply return the /index.html file content to the client
330
- if (path.extname(ui_file_path).length == 0) {
331
- send_content_file(req, res, path.join(ui_path, 'index.html'));
332
- return;
333
- }
334
-
335
- // If the file exists, send it.
336
- if (fs.existsSync(ui_file_path) == true) {
337
- send_content_file(req, res, ui_file_path);
338
- return;
339
- }
340
-
341
- // All else fails, we have not file to return, so return a 404 error here
342
- send_content_resource_404(req, res);
343
- });
344
-
345
- var server = app.listen(port, '0.0.0.0', function () {
346
- var host = server.address().address;
347
- var port = server.address().port;
348
-
349
- console.log('Server listening at http://127.0.0.1:%s', port);
350
- console.log('Document source path is: ' + source_path);
351
-
352
- let _vars = ['{{DOC_ID}}', '{{BUILD_NUMBER}}', '{{BUILD_DATE}}'];
353
- console.log("Server Vars:");
354
- for (let x = 0; x < _vars.length; x++) {
355
- let name = _vars[x];
356
- console.log(" ", name, " = ", hdoc.expand_variables(name, docId));
357
- }
358
- });
359
-
360
- };
361
- })();
1
+ (() => {
2
+ const express = require("express");
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+ const hdoc = require(path.join(__dirname, "hdoc-module.js"));
6
+ const stream = require("node:stream");
7
+
8
+ const yaml = require("js-yaml");
9
+ const mdfm = require("markdown-it-front-matter");
10
+
11
+ let port = 3000;
12
+ let docId;
13
+ let hdocbook_config;
14
+ let hdocbook_project;
15
+ let global_source_path = "";
16
+
17
+ exports.run = async (ui_path, source_path) => {
18
+ global_source_path = source_path;
19
+ for (let x = 0; x < process.argv.length; x++) {
20
+ // First two arguments are command, and script
21
+ if (x === 0 || x === 1) continue;
22
+
23
+ if (process.argv[x].toLowerCase() === "-port") {
24
+ x++;
25
+ if (x < process.argv.length) {
26
+ port = process.argv[x];
27
+ }
28
+ }
29
+ }
30
+
31
+ console.log("Hornbill HDocBook Preview/Dev Server", "\r\n");
32
+ console.log(" UI Root Path:", ui_path);
33
+ console.log(" Document Path:", source_path, "\r\n");
34
+ console.log(" Server Port:", port);
35
+
36
+ if (!fs.existsSync(path.join(source_path, "hdocbook-project.json"))) {
37
+ console.error(
38
+ "No hdocbook-project.json file found in working folder. Unable to continue.",
39
+ );
40
+ return -1;
41
+ }
42
+
43
+ // In the root of the project there is a hdocbook.json file which includes
44
+ // the id of the hdocbook we are working with
45
+ const hdocbook_project_config_path = path.join(
46
+ source_path,
47
+ "hdocbook-project.json",
48
+ );
49
+
50
+ // Load the hdocbook config file
51
+ try {
52
+ hdocbook_project = require(hdocbook_project_config_path);
53
+ } catch (e) {
54
+ console.error(`\nFailed to load hdocbook-project.json:\n${e}\n`);
55
+ process.exit(1);
56
+ }
57
+
58
+ // Get the ID of the hdocbook we are serving
59
+ docId = hdocbook_project.docId;
60
+
61
+ // Get inline content for nav
62
+ const inline_path = path.join(source_path, docId, "_inline");
63
+ let nav_inline = {};
64
+ if (fs.existsSync(inline_path)) {
65
+ const inline_files = fs.readdirSync(inline_path);
66
+ nav_inline = {
67
+ text: "Inline Help Items",
68
+ expand: true,
69
+ inline: true,
70
+ items: [],
71
+ };
72
+ for (const file of inline_files) {
73
+ nav_inline.items.push({
74
+ text: file.replace(path.extname(file), ""),
75
+ link: `${docId}/_inline/${file.replace(path.extname(file), "")}`,
76
+ });
77
+ }
78
+ }
79
+ // Get an express server instance
80
+ const app = express();
81
+
82
+ // Get the path of the book.json file
83
+ const hdocbook_path = path.join(source_path, docId, "hdocbook.json");
84
+
85
+ // Pull in the book config file
86
+ try {
87
+ hdocbook_config = require(hdocbook_path);
88
+ } catch (e) {
89
+ console.error(`\nFailed to load hdocbook.json:${e}\n`);
90
+ process.exit(1);
91
+ }
92
+
93
+ app.get("/_books/library.json", (req, res) => {
94
+ const library = {
95
+ books: [
96
+ {
97
+ docId: hdocbook_config.docId,
98
+ title: hdocbook_config.title,
99
+ nav_inline: nav_inline,
100
+ },
101
+ ],
102
+ };
103
+ res.setHeader("Content-Type", "application/json");
104
+ res.send(JSON.stringify(library, null, 3));
105
+ });
106
+
107
+ 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
+ });
144
+
145
+ md.linkify.set({
146
+ fuzzyEmail: false,
147
+ fuzzyLink: false,
148
+ fuzzyIP: false,
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());
162
+
163
+ if (frontmatter_content.length) {
164
+ const obj = yaml.load(frontmatter_content);
165
+
166
+ const buff = Buffer.from(JSON.stringify(obj), "utf-8");
167
+
168
+ const base64 = buff.toString("base64");
169
+
170
+ res.setHeader("X-frontmatter", base64);
171
+ }
172
+
173
+ res.setHeader("Content-Type", "text/html");
174
+ res.send(html_txt);
175
+ return true;
176
+ }
177
+ return false;
178
+ }
179
+
180
+ function send_content_file(req, res, file_path, redirected = false) {
181
+ let content_txt = hdoc.expand_variables(
182
+ fs.readFileSync(file_path).toString(),
183
+ docId,
184
+ );
185
+ if (redirected)
186
+ content_txt = `Redirected from ${redirected}\n\n${content_txt}`;
187
+
188
+ const contentType = hdoc.content_type_for_ext(path.extname(file_path));
189
+
190
+ if (path.extname(file_path) === ".md") {
191
+ res.setHeader("Content-Disposition", "inline");
192
+ }
193
+
194
+ res.setHeader("Content-Type", contentType);
195
+
196
+ res.send(content_txt);
197
+ }
198
+
199
+ function send_file(req, res, file_path) {
200
+ // Need to set the content type here??
201
+ const contentType = hdoc.content_type_for_ext(path.extname(file_path));
202
+ res.setHeader("Content-Type", contentType);
203
+
204
+ const r = fs.createReadStream(file_path);
205
+ const ps = new stream.PassThrough();
206
+ stream.pipeline(r, ps, (err) => {
207
+ if (err) {
208
+ console.error(err); // No such file or any other kind of error
209
+ return res.sendStatus(400).send("Unexpected error");
210
+ }
211
+ });
212
+ ps.pipe(res);
213
+ }
214
+
215
+ function send_content_resource_404(req, res) {
216
+ res.setHeader("Content-Type", "text/html");
217
+ res.status(404).send("Content resource not found");
218
+ }
219
+
220
+ // 1. If we request a file with a .html file extension, and that file DOES NOT exist,
221
+ // we will look for the same file but with a .md extension. If we find that
222
+ // corresponding markdown file, we will transform that markdown file to HTML and
223
+ // return the HTML content
224
+ //
225
+ // 2. If we request a file, without any file extension then we will look for that file
226
+ // with a .md extension, and if that file exists, we will transform that markdown
227
+ // file to HTML and return that file.
228
+ //
229
+ // For all other requests, we are going to look on the filesystem. If we request
230
+ // a specific file with its extension (including .md files), then we will simply
231
+ // return the file verbatim as a static file.
232
+ //
233
+ // If we request a file without an extension and that file does not exist, we will
234
+ // assume that is a folder, will append index.html and look for that file, if present
235
+ // we will send it, if not present we will look for index.md, and if thats present
236
+ // we will transform to HTML and return that
237
+ //
238
+ // Anything else in this handler will return a 404 error
239
+
240
+ app.get("/_books/*", (req, res) => {
241
+ let url = req.url.replace("/_books/", "/");
242
+
243
+ console.log("URL Requested:", url);
244
+
245
+ // Process redirect
246
+ if (
247
+ hdocbook_project.redirects &&
248
+ Array.isArray(hdocbook_project.redirects) &&
249
+ hdocbook_project.redirects.length > 0
250
+ ) {
251
+ const source_url = url.indexOf("/") === 0 ? url : `/${url}`;
252
+ for (const redir of hdocbook_project.redirects) {
253
+ redir.url =
254
+ redir.url.indexOf("/") === 0 ? redir.url : `/${redir.url}`;
255
+ if (
256
+ redir.url === source_url &&
257
+ redir.location &&
258
+ redir.location !== ""
259
+ ) {
260
+ url = `${redir.location}`;
261
+ console.log(`Redirecting to ${url}`);
262
+ }
263
+ }
264
+ }
265
+
266
+ const file_path = path.join(source_path, url);
267
+
268
+ if (path.extname(file_path) === ".html") {
269
+ // 1a. check for html files, and send/transform as required
270
+ if (fs.existsSync(file_path)) {
271
+ // HTML file exists on disk, just return it verbatim
272
+ res.setHeader("Content-Type", "text/html");
273
+ send_file(req, res, file_path);
274
+ return true;
275
+ }
276
+ if (fs.existsSync(file_path.replace(".html", ".md"))) {
277
+ if (
278
+ transform_markdown_and_send_html(
279
+ req,
280
+ res,
281
+ file_path.replace(".html", ".md"),
282
+ )
283
+ ) {
284
+ return;
285
+ }
286
+ }
287
+ } else if (path.extname(file_path) === ".md") {
288
+ // If the markdown file exists, just send to caller as is
289
+ if (fs.existsSync(file_path)) {
290
+ send_content_file(req, res, file_path);
291
+ return true;
292
+ }
293
+ } else if (path.extname(file_path).length === 0) {
294
+ // 2. If we request a file, without any file extension
295
+ if (fs.existsSync(`${file_path}.md`)) {
296
+ if (transform_markdown_and_send_html(req, res, `${file_path}.md`)) {
297
+ return;
298
+ }
299
+ } else if (fs.existsSync(path.join(`${file_path}index.md`))) {
300
+ if (
301
+ transform_markdown_and_send_html(
302
+ req,
303
+ res,
304
+ path.join(file_path, "index.md"),
305
+ )
306
+ ) {
307
+ return;
308
+ }
309
+ } else if (fs.existsSync(path.join(`${file_path}index.html`))) {
310
+ res.setHeader("Content-Type", "text/html");
311
+ send_content_file(req, res, path.join(`${file_path}index.html`));
312
+ return;
313
+ } else if (fs.existsSync(`${file_path}/index.md`)) {
314
+ if (
315
+ transform_markdown_and_send_html(req, res, `${file_path}/index.md`)
316
+ ) {
317
+ return;
318
+ }
319
+ } else if (fs.existsSync(path.join(`${file_path}/index.html`))) {
320
+ res.setHeader("Content-Type", "text/html");
321
+ send_content_file(req, res, path.join(`${file_path}/index.html`));
322
+ return;
323
+ } else if (fs.existsSync(path.join(`${file_path}.html`))) {
324
+ res.setHeader("Content-Type", "text/html");
325
+ send_content_file(req, res, path.join(`${file_path}.html`));
326
+ return;
327
+ } else if (fs.existsSync(path.join(`${file_path}.htm`))) {
328
+ res.setHeader("Content-Type", "text/html");
329
+ send_content_file(req, res, path.join(`${file_path}.htm`));
330
+ return;
331
+ }
332
+ } else if (fs.existsSync(file_path)) {
333
+ if (
334
+ file_path.endsWith("hdocbook.json") ||
335
+ file_path.endsWith("hdocbook_project.json")
336
+ ) {
337
+ try {
338
+ // Read & parse file
339
+ JSON.parse(fs.readFileSync(file_path));
340
+ } catch (e) {
341
+ console.error(`Error parsing hdocbook.json: ${e}`);
342
+ }
343
+ }
344
+ send_file(req, res, file_path);
345
+ return;
346
+ }
347
+
348
+ // Return a 404 error here
349
+ send_content_resource_404(req, res);
350
+ });
351
+
352
+ // Catch all
353
+ app.get("/*", (req, res) => {
354
+ const segs = req.url.split("/");
355
+
356
+ const ui_file_path = path.join(ui_path, req.url);
357
+
358
+ // To support the SPA application behavior, if there is no file extension present, then
359
+ // we simply return the /index.html file content to the client
360
+ if (path.extname(ui_file_path).length === 0) {
361
+ send_content_file(req, res, path.join(ui_path, "index.html"));
362
+ return;
363
+ }
364
+
365
+ // If the file exists, send it.
366
+ if (fs.existsSync(ui_file_path)) {
367
+ send_content_file(req, res, ui_file_path);
368
+ return;
369
+ }
370
+
371
+ // All else fails, we have not file to return, so return a 404 error here
372
+ send_content_resource_404(req, res);
373
+ });
374
+
375
+ const server = app.listen(port, "0.0.0.0", () => {
376
+ const host = server.address().address;
377
+ const port = server.address().port;
378
+
379
+ console.log("Server listening at http://127.0.0.1:%s", port);
380
+ console.log(`Document source path is: ${source_path}`);
381
+
382
+ const _vars = ["{{DOC_ID}}", "{{BUILD_NUMBER}}", "{{BUILD_DATE}}"];
383
+ console.log("Server Vars:");
384
+ for (let x = 0; x < _vars.length; x++) {
385
+ const name = _vars[x];
386
+ console.log(" ", name, " = ", hdoc.expand_variables(name, docId));
387
+ }
388
+ });
389
+ };
390
+ })();