hdoc-tools 0.5.1 → 0.6.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 +16 -13
- package/hdoc-init.js +36 -0
- package/hdoc-serve.js +363 -367
- package/hdoc-stats.js +146 -0
- package/hdoc.js +84 -89
- package/package.json +8 -2
- package/ui/js/doc.hornbill.js +9 -9
package/hdoc-build.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
'use strict';
|
|
1
3
|
|
|
2
|
-
exports.run = function(ui_path, source_path, md) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
4
|
+
exports.run = function(ui_path, source_path, md) {
|
|
5
|
+
|
|
6
|
+
// GERRY: The purpose of this function is to create a zip file containing the hdocbook content,
|
|
7
|
+
// * Create a _work folder
|
|
8
|
+
// * copy the hdocbook content to the work folder
|
|
9
|
+
// * Render all markdown into side-by-side HTML file
|
|
10
|
+
// * Replace SERVER_VARS embedded in documents with the right base path, version information etc.
|
|
11
|
+
// * Build an index (sqlite FTS5) by extracting text from all HTML content in the work
|
|
12
|
+
// folder, conceptually we are making a little mini website crawler to index all of the content
|
|
13
|
+
// within the book.
|
|
14
|
+
// * Package everything up into a ZIP file, ready for the build controller to package and publish
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
+
console.log("Build is not yet implemented");
|
|
17
|
+
};
|
|
18
|
+
})();
|
package/hdoc-init.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const prompt = require('prompt');
|
|
5
|
+
|
|
6
|
+
const properties = [{
|
|
7
|
+
name: 'documentId',
|
|
8
|
+
validator: /^[a-z-]+$/,
|
|
9
|
+
warning: 'Document ID must only contain lower case letters and dashes'
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
name: 'title'
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: 'initialVersion',
|
|
16
|
+
validator: /^[a-z-]+$/,
|
|
17
|
+
warning: 'Document ID must only contain lower case letters and dashes'
|
|
18
|
+
}
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
exports.run = function (ui_path, source_path, md) {
|
|
22
|
+
|
|
23
|
+
// GERRY: The init function should create a new starting point HDocBook folder structure
|
|
24
|
+
// ready to run the preview server and start editing.
|
|
25
|
+
//
|
|
26
|
+
// The init function should prompt for the ID of the doc book, title and initial version, then
|
|
27
|
+
// create the required files and folders. Its possible to just create a template and copy
|
|
28
|
+
// those files into place, with a few variable replacements.
|
|
29
|
+
//
|
|
30
|
+
//
|
|
31
|
+
|
|
32
|
+
console.log("Init is not yet implemented");
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
};
|
|
36
|
+
})();
|
package/hdoc-serve.js
CHANGED
|
@@ -1,367 +1,363 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
console.log("Document source path is: " + source_path);
|
|
365
|
-
})
|
|
366
|
-
|
|
367
|
-
}
|
|
1
|
+
(function () {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
var path = require('path');
|
|
6
|
+
const stream = require('stream');
|
|
7
|
+
var express = require('express');
|
|
8
|
+
|
|
9
|
+
exports.run = function (ui_path, source_path, md) {
|
|
10
|
+
|
|
11
|
+
console.log("Hornbill HDocBook Preview/Dev Server", "\r\n");
|
|
12
|
+
console.log(" Server Path:", __dirname);
|
|
13
|
+
console.log(" UI Root Path:", ui_path);
|
|
14
|
+
console.log(" Document Path:", source_path, "\r\n");
|
|
15
|
+
|
|
16
|
+
// Get an express server instance
|
|
17
|
+
var app = express();
|
|
18
|
+
|
|
19
|
+
// In the root of the project there is a hdocbook.json file which includes
|
|
20
|
+
// the id of the hdocbook we are working with
|
|
21
|
+
const hdocbook_project_config_path = path.join(source_path, "hdocbook-project.json");
|
|
22
|
+
|
|
23
|
+
// Load the hdocbook config file
|
|
24
|
+
var hdocbook_project = require(hdocbook_project_config_path);
|
|
25
|
+
|
|
26
|
+
// Get the ID of the hdocbook we are serving
|
|
27
|
+
var docId = hdocbook_project.docId;
|
|
28
|
+
|
|
29
|
+
// Get the path of the book.json file
|
|
30
|
+
const hdocbook_path = path.join(source_path, docId, "hdocbook.json");
|
|
31
|
+
|
|
32
|
+
// Pull in the book config file
|
|
33
|
+
var hdocbook_config = require(hdocbook_path);
|
|
34
|
+
var hdocbook_mtime = fs.statSync(hdocbook_path).mtime;
|
|
35
|
+
|
|
36
|
+
app.get('/content/library.json', function (req, res) {
|
|
37
|
+
let library = {
|
|
38
|
+
books: [{
|
|
39
|
+
docId: hdocbook_config.docId,
|
|
40
|
+
title: hdocbook_config.title
|
|
41
|
+
}]
|
|
42
|
+
};
|
|
43
|
+
res.setHeader("Content-Type", "application/json");
|
|
44
|
+
res.send(JSON.stringify(library, null, 3));
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
function content_type_for_ext(ext) {
|
|
49
|
+
switch (ext) {
|
|
50
|
+
case ".z":
|
|
51
|
+
return "application/x-compress";
|
|
52
|
+
case ".tgz":
|
|
53
|
+
return "application/x-compressed";
|
|
54
|
+
case ".gz":
|
|
55
|
+
return "application/x-gzip";
|
|
56
|
+
case ".zip":
|
|
57
|
+
return "application/x-zip-compressed";
|
|
58
|
+
case ".xml":
|
|
59
|
+
return "application/xml";
|
|
60
|
+
case ".bmp":
|
|
61
|
+
return "image/bmp";
|
|
62
|
+
case ".gif":
|
|
63
|
+
return "image/gif";
|
|
64
|
+
case ".jpg":
|
|
65
|
+
return "image/jpeg";
|
|
66
|
+
case ".png":
|
|
67
|
+
return "image/png";
|
|
68
|
+
case ".tiff":
|
|
69
|
+
return "image/tiff";
|
|
70
|
+
case ".ico":
|
|
71
|
+
return "image/x-icon";
|
|
72
|
+
case ".png":
|
|
73
|
+
return "image/png";
|
|
74
|
+
case ".svg":
|
|
75
|
+
return "image/svg+xml";
|
|
76
|
+
case ".css":
|
|
77
|
+
return "text/css";
|
|
78
|
+
case ".htm":
|
|
79
|
+
case ".html":
|
|
80
|
+
return "text/html";
|
|
81
|
+
case ".txt":
|
|
82
|
+
return "text/plain";
|
|
83
|
+
case ".md":
|
|
84
|
+
return "text/plain";
|
|
85
|
+
case ".json":
|
|
86
|
+
return "application/json";
|
|
87
|
+
case ".js":
|
|
88
|
+
return "application/javascript";
|
|
89
|
+
default:
|
|
90
|
+
return "application/octet-stream";
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function expand_variables(text) {
|
|
95
|
+
// For debug mode our base path is our root??
|
|
96
|
+
text = text.replaceAll("{{BASE_PATH}}", "/" + docId);
|
|
97
|
+
text = text.replaceAll("{{BUILD_NUMBER}}", "0");
|
|
98
|
+
|
|
99
|
+
let build_date = new Date().toISOString();
|
|
100
|
+
build_date = build_date.replace('T', ' ');
|
|
101
|
+
build_date = build_date.substring(0, 19);
|
|
102
|
+
|
|
103
|
+
text = text.replaceAll("{{BUILD_DATE}}", build_date);
|
|
104
|
+
return text;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function transform_markdown_and_send_html(req, res, file_path) {
|
|
108
|
+
|
|
109
|
+
if (fs.existsSync(file_path)) {
|
|
110
|
+
// we have a markdown representation of the requested HTML file, transform and return
|
|
111
|
+
// it to the caller
|
|
112
|
+
|
|
113
|
+
// Load markdown file
|
|
114
|
+
let md_txt = expand_variables(fs.readFileSync(file_path).toString());
|
|
115
|
+
|
|
116
|
+
// Render markdown into HTML
|
|
117
|
+
let frontmatter_content = "";
|
|
118
|
+
var html_txt = md.render(md_txt.toString());
|
|
119
|
+
|
|
120
|
+
if (frontmatter_content.length) {
|
|
121
|
+
|
|
122
|
+
const obj = yaml.load(frontmatter_content);
|
|
123
|
+
|
|
124
|
+
const buff = Buffer.from(JSON.stringify(obj), 'utf-8');
|
|
125
|
+
|
|
126
|
+
const base64 = buff.toString('base64');
|
|
127
|
+
|
|
128
|
+
res.setHeader("X-frontmatter", base64);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
res.setHeader("Content-Type", "text/html");
|
|
132
|
+
res.send(html_txt);
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function send_content_file(req, res, file_path) {
|
|
139
|
+
let content_txt = expand_variables(fs.readFileSync(file_path).toString());
|
|
140
|
+
|
|
141
|
+
let contentType = content_type_for_ext(path.extname(file_path));
|
|
142
|
+
|
|
143
|
+
if (path.extname(file_path) == ".md") {
|
|
144
|
+
res.setHeader("Content-Disposition", "inline");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
res.setHeader("Content-Type", contentType);
|
|
148
|
+
|
|
149
|
+
res.send(content_txt);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function send_file(req, res, file_path) {
|
|
153
|
+
// Need to set the content type here??
|
|
154
|
+
let contentType = content_type_for_ext(path.extname(file_path));
|
|
155
|
+
res.setHeader("Content-Type", contentType);
|
|
156
|
+
|
|
157
|
+
const r = fs.createReadStream(file_path);
|
|
158
|
+
const ps = new stream.PassThrough();
|
|
159
|
+
stream.pipeline(
|
|
160
|
+
r,
|
|
161
|
+
ps,
|
|
162
|
+
(err) => {
|
|
163
|
+
if (err) {
|
|
164
|
+
console.log(err); // No such file or any other kind of error
|
|
165
|
+
return res.sendStatus(400).send("Unexpected error");
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
ps.pipe(res);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function send_content_resource_404(req, res) {
|
|
172
|
+
res.setHeader("Content-Type", "text/html");
|
|
173
|
+
res.status(404).send("Content resource not found");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// 1. If we request a file with a .html file extension, and that file DOES NOT exist,
|
|
177
|
+
// we will look for the same file but with a .md extension. If we find that
|
|
178
|
+
// corresponding markdown file, we will transform that markdown file to HTML and
|
|
179
|
+
// return the HTML content
|
|
180
|
+
//
|
|
181
|
+
// 2. If we request a file, without any file extension then we will look for that file
|
|
182
|
+
// with a .md extension, and if that file exists, we will transform that markdown
|
|
183
|
+
// file to HTML and return that file.
|
|
184
|
+
//
|
|
185
|
+
// For all other requests, we are going to look on the filesystem. If we request
|
|
186
|
+
// a specific file with its extension (including .md files), then we will simply
|
|
187
|
+
// return the file verbatim as a static file.
|
|
188
|
+
//
|
|
189
|
+
// If we request a file without an extension and that file does not exist, we will
|
|
190
|
+
// assume that is a folder, will append index.html and look for that file, if present
|
|
191
|
+
// we will send it, if not present we will look for index.md, and if thats present
|
|
192
|
+
// we will transform to HTML and return that
|
|
193
|
+
//
|
|
194
|
+
// Anything else in this handler will return a 404 error
|
|
195
|
+
|
|
196
|
+
app.get('/content/*', function (req, res) {
|
|
197
|
+
|
|
198
|
+
let url = req.url;
|
|
199
|
+
|
|
200
|
+
let segs = url.split('/');
|
|
201
|
+
|
|
202
|
+
if (segs.length == 4 && segs[1] == "content" && segs[3] == "book.json") {
|
|
203
|
+
// Special case of a virtual file here, we need to check the book ID and
|
|
204
|
+
// if its our book, send the json
|
|
205
|
+
if (hdocbook_config.docId == segs[2]) {
|
|
206
|
+
res.setHeader("Content-Type", "application/json");
|
|
207
|
+
res.send(JSON.stringify(hdocbook_config, null, 3));
|
|
208
|
+
} else {
|
|
209
|
+
// Return a 404 error here
|
|
210
|
+
res.setHeader("Content-Type", "text/html");
|
|
211
|
+
res.status(404).send("Specified bookId " + segs[2] + " not found");
|
|
212
|
+
}
|
|
213
|
+
return;
|
|
214
|
+
} else if (segs.length == 3 && segs[1] == "content" && segs[2] == "index.json") {
|
|
215
|
+
// For development mode, we always have an index with one book in it, the one being developed
|
|
216
|
+
if (hdocbook_config) {
|
|
217
|
+
let index = {
|
|
218
|
+
books: [{
|
|
219
|
+
docId: hdocbook_config.docId,
|
|
220
|
+
title: hdocbook_config.title,
|
|
221
|
+
description: hdocbook_config.description,
|
|
222
|
+
version: hdocbook_config.version
|
|
223
|
+
}]
|
|
224
|
+
};
|
|
225
|
+
res.setHeader("Content-Type", "application/json");
|
|
226
|
+
res.send(JSON.stringify(index, null, 3));
|
|
227
|
+
} else {
|
|
228
|
+
// Return a 404 error here
|
|
229
|
+
res.setHeader("Content-Type", "text/html");
|
|
230
|
+
res.status(404).send("Specified bookId " + segs[2] + " not found");
|
|
231
|
+
}
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
url = url.replace("/content/", "/");
|
|
236
|
+
|
|
237
|
+
console.log("URL Requested: ", url);
|
|
238
|
+
|
|
239
|
+
let file_path = path.join(source_path, url);
|
|
240
|
+
let ui_file_path = path.join(ui_path, url);
|
|
241
|
+
|
|
242
|
+
// If the requested file is found in the UI folder
|
|
243
|
+
if (url == "/") {
|
|
244
|
+
if (fs.existsSync(path.join(ui_file_path, "index.html"))) {
|
|
245
|
+
// We want the index.html, send it here
|
|
246
|
+
send_file(req, res, path.join(ui_file_path, "index.html"));
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
// Return a 404 error here
|
|
250
|
+
send_content_resource_404(req, res);
|
|
251
|
+
return;
|
|
252
|
+
} else if (fs.existsSync(ui_file_path)) {
|
|
253
|
+
// File is found in the UI folder, that takes priority, send the file
|
|
254
|
+
send_file(req, res, ui_file_path);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (path.extname(file_path) == ".html") {
|
|
259
|
+
// 1a. check for html files, and send/transform as required
|
|
260
|
+
if (fs.existsSync(file_path)) {
|
|
261
|
+
// HTML file exists on disk, just return it verbatim
|
|
262
|
+
res.setHeader("Content-Type", "text/html");
|
|
263
|
+
send_file(req, res, file_path);
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (fs.existsSync(file_path.replace(".html", ".md"))) {
|
|
268
|
+
if (transform_markdown_and_send_html(req, res, file_path.replace(".html", ".md"))) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
} else if (path.extname(file_path) == ".md") {
|
|
273
|
+
// If the markdown file exists, just send to caller as is
|
|
274
|
+
if (fs.existsSync(file_path)) {
|
|
275
|
+
send_content_file(req, res, file_path);
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
} else if (path.extname(file_path).length == 0) {
|
|
279
|
+
// 2. If we request a file, without any file extension
|
|
280
|
+
if (fs.existsSync(file_path + ".md")) {
|
|
281
|
+
if (transform_markdown_and_send_html(req, res, file_path + ".md")) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
} else if (fs.existsSync(path.join(file_path + "index.md"))) {
|
|
285
|
+
if (transform_markdown_and_send_html(req, res, path.join(file_path, "index.md"))) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
} else if (fs.existsSync(path.join(file_path + "index.html"))) {
|
|
289
|
+
res.setHeader("Content-Type", "text/html");
|
|
290
|
+
send_content_file(req, res, path.join(file_path + "index.html"));
|
|
291
|
+
return;
|
|
292
|
+
} else if (fs.existsSync(file_path + "/index.md")) {
|
|
293
|
+
if (transform_markdown_and_send_html(req, res, file_path + "/index.md")) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
} else if (fs.existsSync(path.join(file_path + "/index.html"))) {
|
|
297
|
+
res.setHeader("Content-Type", "text/html");
|
|
298
|
+
send_content_file(req, res, path.join(file_path + "/index.html"));
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
} else if (fs.existsSync(file_path)) {
|
|
302
|
+
send_file(req, res, file_path);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Return a 404 error here
|
|
307
|
+
send_content_resource_404(req, res);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// Catch all
|
|
311
|
+
app.get('/*', function (req, res) {
|
|
312
|
+
|
|
313
|
+
let segs = req.url.split('/');
|
|
314
|
+
|
|
315
|
+
if (segs.length > 3 && segs[2] == "content") {
|
|
316
|
+
// In this case we are looking for static content within the book
|
|
317
|
+
|
|
318
|
+
// Create the file path
|
|
319
|
+
let url = req.url.replace("/content/", "/");
|
|
320
|
+
let file_path = path.join(source_path, url);
|
|
321
|
+
|
|
322
|
+
// If the file exists, send it.
|
|
323
|
+
if (fs.existsSync(file_path) == true) {
|
|
324
|
+
send_file(req, res, file_path);
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// All else fails, we have not file to return, so return a 404 error here
|
|
329
|
+
send_content_resource_404(req, res);
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
let ui_file_path = path.join(ui_path, req.url);
|
|
334
|
+
|
|
335
|
+
console.log("URL Root: ", req.url);
|
|
336
|
+
|
|
337
|
+
// To support the SPA application behavior, if there is no file extension present, then
|
|
338
|
+
// we simply return the /index.html file content to the client
|
|
339
|
+
if (path.extname(ui_file_path).length == 0) {
|
|
340
|
+
send_content_file(req, res, path.join(ui_path, "index.html"));
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// If the file exists, send it.
|
|
345
|
+
if (fs.existsSync(ui_file_path) == true) {
|
|
346
|
+
send_content_file(req, res, ui_file_path);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// All else fails, we have not file to return, so return a 404 error here
|
|
351
|
+
send_content_resource_404(req, res);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
var server = app.listen(3000, "0.0.0.0", function () {
|
|
355
|
+
var host = server.address().address;
|
|
356
|
+
var port = server.address().port;
|
|
357
|
+
|
|
358
|
+
console.log("Server listening at http://%s:%s", host, port);
|
|
359
|
+
console.log("Document source path is: " + source_path);
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
};
|
|
363
|
+
})();
|
package/hdoc-stats.js
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
|
|
2
|
+
(function () {
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
// Required modules
|
|
6
|
+
const { STATUS_CODES } = require('http');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const dree = require('dree');
|
|
9
|
+
const html2text = require('html-to-text');
|
|
10
|
+
const { markdownToTxt } = require('markdown-to-txt');
|
|
11
|
+
const wordsCount = require('words-count').default;
|
|
12
|
+
|
|
13
|
+
// Regex to remove Hornbill-specific tags
|
|
14
|
+
const hbMDTagRegex = /(:{3}[ ]note)|(:{3}[ ]tip)|(:{3}[ ]important)|(:{3}[ ]caution)|(:{3}[ ]warning)|(:{3})/g;
|
|
15
|
+
|
|
16
|
+
let stats = {
|
|
17
|
+
totalMDFiles: 0,
|
|
18
|
+
totalStaticHTMLFiles: 0,
|
|
19
|
+
totalWordCount: 0,
|
|
20
|
+
mdFiles: {},
|
|
21
|
+
staticHTMLFiles: {}
|
|
22
|
+
};
|
|
23
|
+
// File callback for scan
|
|
24
|
+
const fileCallback = function(element) {
|
|
25
|
+
if (element.extension === 'md' ) {
|
|
26
|
+
|
|
27
|
+
// Read markdown file as string
|
|
28
|
+
const md = fs.readFileSync(element.path, 'utf8');
|
|
29
|
+
|
|
30
|
+
// Strip out standard MD tags
|
|
31
|
+
let text = markdownToTxt(md);
|
|
32
|
+
|
|
33
|
+
// Strip out any Hornbill Docs specific markdown tags
|
|
34
|
+
text = text.replaceAll(hbMDTagRegex, '');
|
|
35
|
+
|
|
36
|
+
// Do the wordcount and add to status
|
|
37
|
+
const wordCount = wordsCount(text);
|
|
38
|
+
stats.totalWordCount += wordCount;
|
|
39
|
+
stats.mdFiles[element.relativePath] = {
|
|
40
|
+
wordCount: wordCount,
|
|
41
|
+
sizeInBytes: element.sizeInBytes
|
|
42
|
+
};
|
|
43
|
+
stats.totalMDFiles++;
|
|
44
|
+
} else {
|
|
45
|
+
// file must be html
|
|
46
|
+
const mdFilePath = element.path.slice(0, element.path.lastIndexOf('.')) + '.md';
|
|
47
|
+
if (!fs.existsSync(mdFilePath)) {
|
|
48
|
+
//Do we have a matching MD file - if not, then word count the HTML
|
|
49
|
+
stats.totalStaticHTMLFiles++;
|
|
50
|
+
const html = fs.readFileSync(element.path, 'utf8');
|
|
51
|
+
const text = html2text.convert(html, {
|
|
52
|
+
wordwrap: null
|
|
53
|
+
});
|
|
54
|
+
const wordCount = wordsCount(text);
|
|
55
|
+
stats.totalWordCount += wordCount;
|
|
56
|
+
stats.staticHTMLFiles[element.relativePath] = {
|
|
57
|
+
wordCount: wordCount,
|
|
58
|
+
sizeInBytes: element.sizeInBytes
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const dreeOptions = {
|
|
65
|
+
descendants: true,
|
|
66
|
+
depth: 10,
|
|
67
|
+
extensions: ['md','html','htm'],
|
|
68
|
+
hash: false,
|
|
69
|
+
normalize: true,
|
|
70
|
+
size: true,
|
|
71
|
+
sizeInBytes: true,
|
|
72
|
+
stat: false,
|
|
73
|
+
symbolicLinks: false
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
exports.run = function(ui_path, source_path, md, verbose = false) {
|
|
77
|
+
|
|
78
|
+
// GERRY: The stats here are needed to support content development. The idea is to count all of the ]
|
|
79
|
+
// words in a HDocBook so we know the size of the book, this helps with 3rd party involvement where
|
|
80
|
+
// we generally need to know the word count of the content in order to get a quote for things like
|
|
81
|
+
// copy editing. reviewing and translations.
|
|
82
|
+
//
|
|
83
|
+
// For each .md file, and for each static .HTML file (that is html files that we have not generated) we
|
|
84
|
+
// should do a word count, excluding MD or HTML tags
|
|
85
|
+
console.log('Hornbill HDocBook Stats', '\r\n');
|
|
86
|
+
|
|
87
|
+
// STEVE: Get the docId (book root) from the hdocbook-project.json
|
|
88
|
+
// From there, loop through looking for:
|
|
89
|
+
// * HTML files without a matching MD, and word count those
|
|
90
|
+
// * MD files, and word count those
|
|
91
|
+
|
|
92
|
+
const project_json_path = source_path + '/hdocbook-project.json';
|
|
93
|
+
|
|
94
|
+
if (!fs.existsSync(project_json_path)) {
|
|
95
|
+
// Book config does not exist
|
|
96
|
+
console.error('Required project file does not exist: ', project_json_path);
|
|
97
|
+
return;
|
|
98
|
+
} else {
|
|
99
|
+
// Book config exists - load book details
|
|
100
|
+
let book_details;
|
|
101
|
+
try {
|
|
102
|
+
book_details = JSON.parse(fs.readFileSync(project_json_path, 'utf8'));
|
|
103
|
+
} catch (e) {
|
|
104
|
+
console.error('Error reading book configuration: ', e);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Scan content path directory, send file info to callback for processing
|
|
109
|
+
dree.scan(source_path + '/' + book_details.docId, dreeOptions, fileCallback);
|
|
110
|
+
|
|
111
|
+
if (verbose) {
|
|
112
|
+
// Output verbose stats
|
|
113
|
+
|
|
114
|
+
// Output information about all markdown files in the book
|
|
115
|
+
console.log('--------------');
|
|
116
|
+
console.log(' Markdown ');
|
|
117
|
+
console.log('--------------');
|
|
118
|
+
for (const key in stats.mdFiles) {
|
|
119
|
+
if (stats.mdFiles.hasOwnProperty(key)) {
|
|
120
|
+
console.log('Relative Path: ', key);
|
|
121
|
+
console.log(' Word Count: ', stats.mdFiles[key].wordCount);
|
|
122
|
+
console.log('File Size (B): ', stats.mdFiles[key].sizeInBytes, '\r\n');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Output information about all static HTML in the book
|
|
127
|
+
console.log('---------------');
|
|
128
|
+
console.log(' Static HTML ');
|
|
129
|
+
console.log('---------------');
|
|
130
|
+
for (const key in stats.staticHTMLFiles) {
|
|
131
|
+
if (stats.staticHTMLFiles.hasOwnProperty(key)) {
|
|
132
|
+
console.log('Relative Path: ', key);
|
|
133
|
+
console.log(' Word Count: ', stats.staticHTMLFiles[key].wordCount);
|
|
134
|
+
console.log('File Size (B): ', stats.staticHTMLFiles[key].sizeInBytes, '\r\n');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Output stats
|
|
140
|
+
console.log(' Total Book Word Count: ' + stats.totalWordCount);
|
|
141
|
+
console.log(' Markdown Files: ' + stats.totalMDFiles);
|
|
142
|
+
console.log(' Static HTML Files: ' + stats.totalStaticHTMLFiles + '\r\n');
|
|
143
|
+
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
})();
|
package/hdoc.js
CHANGED
|
@@ -1,94 +1,89 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
frontmatter_content
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
3
|
+
(function () {
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
var path = require('path');
|
|
8
|
+
const stream = require('stream');
|
|
9
|
+
const yaml = require('js-yaml');
|
|
10
|
+
const mdfm = require('markdown-it-front-matter');
|
|
11
|
+
var hljs = require('highlight.js'); // https://highlightjs.org/
|
|
12
|
+
const md = require('markdown-it')({
|
|
13
|
+
// enable everything
|
|
14
|
+
html: true,
|
|
15
|
+
linkify: true,
|
|
16
|
+
typographer: true,
|
|
17
|
+
// highlight: function (str, lang) {
|
|
18
|
+
// if (lang && hljs.getLanguage(lang)) {
|
|
19
|
+
// try {
|
|
20
|
+
// return hljs.highlight(lang, str, true).value;
|
|
21
|
+
// } catch (__) {}
|
|
22
|
+
// }
|
|
23
|
+
// }
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
var frontmatter_content;
|
|
27
|
+
md.use(mdfm, function (fm) {
|
|
28
|
+
frontmatter_content = fm;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const tips = require(__dirname + '/custom_modules/tips.js');
|
|
32
|
+
|
|
33
|
+
md.use(tips, {
|
|
34
|
+
links: true
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Default source path to working directory
|
|
38
|
+
let source_path = process.cwd();
|
|
39
|
+
let ui_path = path.join(__dirname, "ui");
|
|
40
|
+
|
|
41
|
+
var command = ""; // Our command to run
|
|
42
|
+
|
|
43
|
+
// Get options from command args
|
|
44
|
+
for (let x = 0; x < process.argv.length; x++) {
|
|
45
|
+
// First two arguments are command, and script
|
|
46
|
+
if (x == 0 || x == 1)
|
|
47
|
+
continue;
|
|
48
|
+
// Third argument is command
|
|
49
|
+
if (x == 2) {
|
|
50
|
+
command = process.argv[x];
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (process.argv[x] == "-path") {
|
|
55
|
+
x++;
|
|
56
|
+
if (x < process.argv.length) {
|
|
57
|
+
source_path = process.argv[x];
|
|
58
|
+
}
|
|
59
|
+
} else if (process.argv[x] == "-ui-path") {
|
|
60
|
+
x++;
|
|
61
|
+
if (x < process.argv.length) {
|
|
62
|
+
ui_path = process.argv[x];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
51
65
|
}
|
|
52
66
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
console.log("Hornbill HDocBook Tools v0.1", "\r\n");
|
|
68
|
+
console.log(" Server Path:", __dirname);
|
|
69
|
+
console.log(" Document Path:", source_path, "\r\n");
|
|
70
|
+
|
|
71
|
+
if (command == "serve") {
|
|
72
|
+
const server = require(path.join(__dirname, "hdoc-serve.js"));
|
|
73
|
+
server.run(ui_path, source_path, md);
|
|
74
|
+
} else if (command == "build") {
|
|
75
|
+
const builder = require(path.join(__dirname, "hdoc-build.js"));
|
|
76
|
+
builder.run(ui_path, source_path, md);
|
|
77
|
+
} else if (command == "stats") {
|
|
78
|
+
const stats = require(path.join(__dirname, "hdoc-stats.js"));
|
|
79
|
+
stats.run(ui_path, source_path, md);
|
|
80
|
+
} else if (command == "statsv") {
|
|
81
|
+
const stats = require(path.join(__dirname, "hdoc-stats.js"));
|
|
82
|
+
stats.run(ui_path, source_path, md, true);
|
|
83
|
+
} else if (command == "init") {
|
|
84
|
+
const init = require(path.join(__dirname, "hdoc-init.js"));
|
|
85
|
+
init.run(ui_path, source_path, md);
|
|
86
|
+
} else {
|
|
87
|
+
console.log("Unknown command: " + command);
|
|
65
88
|
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
console.log("Hornbill HDocBook Tools v0.1", "\r\n");
|
|
69
|
-
console.log(" Server Path:", __dirname);
|
|
70
|
-
console.log(" Document Path:", source_path, "\r\n");
|
|
71
|
-
|
|
72
|
-
if(command == "serve") {
|
|
73
|
-
const server = require(path.join(__dirname, "hdoc-serve.js"));
|
|
74
|
-
|
|
75
|
-
server.run(ui_path, source_path, md);
|
|
76
|
-
} else if(command == "build") {
|
|
77
|
-
|
|
78
|
-
const builder = require(path.join(__dirname, "hdoc-build.js"));
|
|
79
|
-
|
|
80
|
-
builder.run(ui_path, source_path, md);
|
|
81
|
-
} else if(command == "stats") {
|
|
82
|
-
|
|
83
|
-
const stats = require(path.join(__dirname, "hdoc-stats.js"));
|
|
84
|
-
|
|
85
|
-
stats.run(ui_path, source_path, md);
|
|
86
|
-
} else if(command == "init") {
|
|
87
|
-
|
|
88
|
-
const init = require(path.join(__dirname, "hdoc-init.js"));
|
|
89
|
-
|
|
90
|
-
init.run(ui_path, source_path, md);
|
|
91
|
-
} else {
|
|
92
|
-
console.log("Unknown command: " + command);
|
|
93
|
-
}
|
|
94
|
-
|
|
89
|
+
})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hdoc-tools",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Hornbill HDocBook Development Support Tool",
|
|
5
5
|
"main": "hdoc.js",
|
|
6
6
|
"bin": {
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"hdoc.js",
|
|
11
11
|
"hdoc-serve.js",
|
|
12
|
+
"hdoc-stats.js",
|
|
13
|
+
"hdoc-init.js",
|
|
12
14
|
"hdoc-build.js",
|
|
13
15
|
"ui",
|
|
14
16
|
"custom_modules"
|
|
@@ -21,15 +23,19 @@
|
|
|
21
23
|
"dependencies": {
|
|
22
24
|
"body-parser": "^1.20.1",
|
|
23
25
|
"cookie-parser": "^1.4.6",
|
|
26
|
+
"dree": "^3.4.2",
|
|
24
27
|
"express": "^4.18.2",
|
|
25
28
|
"hdoc-tools": "^0.1.0",
|
|
26
29
|
"highlight.js": "^11.6.0",
|
|
27
30
|
"html-to-text": "^8.2.1",
|
|
28
31
|
"js-yaml": "^4.1.0",
|
|
32
|
+
"lodash": "^4.17.21",
|
|
29
33
|
"markdown-it": "^13.0.1",
|
|
30
34
|
"markdown-it-container": "^3.0.0",
|
|
31
35
|
"markdown-it-front-matter": "^0.2.3",
|
|
36
|
+
"markdown-to-txt": "^2.0.1",
|
|
32
37
|
"multer": "^1.4.5-lts.1",
|
|
33
|
-
"stream": "0.0.2"
|
|
38
|
+
"stream": "0.0.2",
|
|
39
|
+
"words-count": "^2.0.2"
|
|
34
40
|
}
|
|
35
41
|
}
|
package/ui/js/doc.hornbill.js
CHANGED
|
@@ -9,18 +9,18 @@ var global = {stateParams:{},lastLayoutClass:""};
|
|
|
9
9
|
var docAppMethods = {
|
|
10
10
|
switchViewTheme:function()
|
|
11
11
|
{
|
|
12
|
-
if(ThemePreference)document.documentElement.classList.remove(ThemePreference)
|
|
12
|
+
if(ThemePreference)document.documentElement.classList.remove(ThemePreference);
|
|
13
13
|
|
|
14
14
|
if(ThemePreference === 'dark')
|
|
15
15
|
{
|
|
16
16
|
ThemePreference = 'light';
|
|
17
17
|
}
|
|
18
18
|
else{
|
|
19
|
-
ThemePreference = 'dark'
|
|
19
|
+
ThemePreference = 'dark';
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
localStorage.setItem('hdocbook-theme-appearance',ThemePreference)
|
|
23
|
-
document.documentElement.classList.add(ThemePreference)
|
|
22
|
+
localStorage.setItem('hdocbook-theme-appearance',ThemePreference);
|
|
23
|
+
document.documentElement.classList.add(ThemePreference);
|
|
24
24
|
},
|
|
25
25
|
renderNavigation:function()
|
|
26
26
|
{
|
|
@@ -146,7 +146,7 @@ function highlightNavigationLinkFromUrl(matchLinkHref)
|
|
|
146
146
|
}
|
|
147
147
|
catch(e)
|
|
148
148
|
{
|
|
149
|
-
console.log("BAD navigation menu item found",el.href)
|
|
149
|
+
console.log("BAD navigation menu item found",el.href);
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
if(checkUrl)
|
|
@@ -371,7 +371,7 @@ function setBrowserViewUrl(strHrefToLoad,viewData,fromPageRefresh,fromPopState)
|
|
|
371
371
|
}
|
|
372
372
|
|
|
373
373
|
//-- store global params
|
|
374
|
-
global.stateParams = viewData
|
|
374
|
+
global.stateParams = viewData;
|
|
375
375
|
|
|
376
376
|
if(!fromPopState)
|
|
377
377
|
{
|
|
@@ -479,7 +479,7 @@ async function intialiseApp() {
|
|
|
479
479
|
//-- we are loading root so select for link
|
|
480
480
|
loadBookDefaultLink();
|
|
481
481
|
}
|
|
482
|
-
},200)
|
|
483
|
-
})
|
|
484
|
-
})
|
|
482
|
+
},200);
|
|
483
|
+
});
|
|
484
|
+
});
|
|
485
485
|
}
|