hdoc-tools 0.9.18 → 0.9.20
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/README.md +5 -3
- package/hdoc-build.js +3 -2
- package/hdoc-module.js +16 -1
- package/hdoc-validate.js +69 -46
- package/package.json +2 -1
package/README.md
CHANGED
@@ -41,13 +41,15 @@ If the -v switch is provided, then more verbose output is output, which includes
|
|
41
41
|
|
42
42
|
Performs a local build of the book, validates the links and static content are present and correct and outputs as a ZIP file.
|
43
43
|
|
44
|
-
If the -v switch is provided, then more verbose output is provided, which includes a list of all HTML files created and checked for embedded links and static content.
|
44
|
+
If the -v switch is provided, then a more verbose output is provided, which includes a list of all HTML files created and checked for embedded links and static content.
|
45
45
|
|
46
|
-
|
46
|
+
Use the --set-version argument to set the version number of the built book.
|
47
|
+
|
48
|
+
### validate
|
47
49
|
|
48
50
|
Performs a minimum local build of the book, then validates the links and static content are present and correct.
|
49
51
|
|
50
|
-
If the -v switch is provided, then more verbose output is provided, which includes a list of all HTML files created and checked for embedded links and static content.
|
52
|
+
If the -v switch is provided, then a more verbose output is provided, which includes a list of all HTML files created and checked for embedded links and static content.
|
51
53
|
|
52
54
|
Use the --set-version argument to set the version number of the built book.
|
53
55
|
|
package/hdoc-build.js
CHANGED
@@ -724,7 +724,7 @@
|
|
724
724
|
const validation_success = await hdoc_validate.run(work_path, doc_id, verbose, hdocbook_config, hdocbook_project, bc);
|
725
725
|
if (!validation_success) {
|
726
726
|
const end_time = Date.now();
|
727
|
-
console.log(
|
727
|
+
console.log(`\nTime Taken: ${get_duration(start_time, end_time)}\n`);
|
728
728
|
process.exit(1);
|
729
729
|
}
|
730
730
|
|
@@ -737,9 +737,10 @@
|
|
737
737
|
console.log(`Error deleting ${md_files_delete[i]}: ${e}`);
|
738
738
|
}
|
739
739
|
}
|
740
|
-
|
740
|
+
|
741
741
|
// Add book read timing to the hdocbook.json
|
742
742
|
hdocbook_config.readingTime = Math.ceil(book_read_time + ((book_read_time / 100) * 10));
|
743
|
+
hdocbook_config.navigation.items = hdoc.strip_drafts(hdocbook_config.navigation.items);
|
743
744
|
try {
|
744
745
|
fs.writeFileSync(work_hdocbook_path, JSON.stringify(hdocbook_config, null, 2));
|
745
746
|
console.log('\nhdocbook.json update success:', work_hdocbook_path);
|
package/hdoc-module.js
CHANGED
@@ -290,7 +290,22 @@
|
|
290
290
|
return response;
|
291
291
|
};
|
292
292
|
|
293
|
-
|
293
|
+
exports.strip_drafts = function (nav_items) {
|
294
|
+
let return_nav = nav_items;
|
295
|
+
recurse_nav(return_nav);
|
296
|
+
return return_nav;
|
297
|
+
};
|
298
|
+
const recurse_nav = function(nav_items) {
|
299
|
+
for (const key in nav_items) {
|
300
|
+
if (nav_items[key].draft) {
|
301
|
+
nav_items.splice(key, 1);
|
302
|
+
recurse_nav(nav_items);
|
303
|
+
} else if (nav_items[key].items) {
|
304
|
+
recurse_nav(nav_items[key].items);
|
305
|
+
}
|
306
|
+
}
|
307
|
+
};
|
308
|
+
|
294
309
|
exports.build_breadcrumbs = function (nav_items) {
|
295
310
|
let bc = {};
|
296
311
|
// Steve - need to rework this to use recursion, as it's hard-coded for a maximum of 4 levels deep right now
|
package/hdoc-validate.js
CHANGED
@@ -8,17 +8,18 @@
|
|
8
8
|
https = require('https'),
|
9
9
|
path = require('path'),
|
10
10
|
hdoc = require(path.join(__dirname, 'hdoc-module.js')),
|
11
|
-
translator = require('american-british-english-translator')
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
11
|
+
translator = require('american-british-english-translator'),
|
12
|
+
{ trueCasePathSync } = require('true-case-path');
|
13
|
+
|
14
|
+
const agent = new https.Agent({
|
15
|
+
rejectUnauthorized: false
|
16
|
+
}),
|
17
|
+
spellcheck_options = {
|
18
|
+
british: true,
|
19
|
+
spelling: true
|
20
|
+
},
|
21
|
+
regex_nav_paths = /[a-z0-9-\/]+/g;
|
22
|
+
|
22
23
|
let prod_families = {},
|
23
24
|
prods_supported = [];
|
24
25
|
|
@@ -31,9 +32,11 @@
|
|
31
32
|
exclude_links = {},
|
32
33
|
exclude_spellcheck = {};
|
33
34
|
|
34
|
-
const load_product_families = async function() {
|
35
|
+
const load_product_families = async function () {
|
35
36
|
try {
|
36
|
-
const prods = await axios.get('https://docs.hornbill.com/_books/products.json', {
|
37
|
+
const prods = await axios.get('https://docs.hornbill.com/_books/products.json', {
|
38
|
+
httpsAgent: agent
|
39
|
+
});
|
37
40
|
if (prods.status === 200) {
|
38
41
|
prod_families = prods.data;
|
39
42
|
for (let i = 0; i < prod_families.products.length; i++) {
|
@@ -51,9 +54,9 @@
|
|
51
54
|
|
52
55
|
const spellcheckContent = async function (sourceFile, excludes) {
|
53
56
|
const text = fs.readFileSync(sourceFile.path, 'utf8');
|
54
|
-
const source_path = sourceFile.relativePath.replace('.'+sourceFile.extension, '');
|
57
|
+
const source_path = sourceFile.relativePath.replace('.' + sourceFile.extension, '');
|
55
58
|
const translate_output = translator.translate(text, spellcheck_options);
|
56
|
-
if(Object.keys(translate_output).length){
|
59
|
+
if (Object.keys(translate_output).length) {
|
57
60
|
|
58
61
|
for (const key in translate_output) {
|
59
62
|
if (translate_output.hasOwnProperty(key)) {
|
@@ -70,11 +73,11 @@
|
|
70
73
|
}
|
71
74
|
}
|
72
75
|
}
|
73
|
-
}
|
76
|
+
}
|
74
77
|
}
|
75
78
|
};
|
76
79
|
|
77
|
-
const checkNavigation = async function (
|
80
|
+
const checkNavigation = async function (source_path, flat_nav) {
|
78
81
|
let nav_errors = [];
|
79
82
|
for (const key in flat_nav) {
|
80
83
|
if (flat_nav.hasOwnProperty(key)) {
|
@@ -82,15 +85,33 @@
|
|
82
85
|
const invalid_chars = key.replace(regex_nav_paths, '');
|
83
86
|
if (invalid_chars !== '') {
|
84
87
|
nav_errors.push(`Navigation path [${key}] contains the following invalid characters: [${[...invalid_chars].join('] [')}]`);
|
85
|
-
}
|
86
|
-
|
87
|
-
//Validate path
|
88
|
+
}
|
89
|
+
|
90
|
+
// Validate path exists - key should be a html file at this point
|
91
|
+
let file_exists = true;
|
92
|
+
let file_name = path.join(source_path, key + '.html');
|
93
|
+
if (!fs.existsSync(file_name)) {
|
94
|
+
file_name = path.join(source_path, key + '.htm');
|
95
|
+
if (!fs.existsSync(file_name)) {
|
96
|
+
file_exists = false;
|
97
|
+
nav_errors.push(`Navigation path [${key}] file does not exist.`);
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
if (file_exists) {
|
102
|
+
const true_file = trueCasePathSync(file_name);
|
103
|
+
if (true_file !== file_name) {
|
104
|
+
nav_errors.push(`Navigation path [${key}] does not match filename case [${path.basename(true_file)}].`);
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
// Validate path
|
88
109
|
const paths = key.split('/');
|
89
110
|
for (let i = 0; i < paths.length; i++) {
|
90
111
|
const path_words = paths[i].split('-');
|
91
112
|
for (let j = 0; j < path_words.length; j++) {
|
92
113
|
const translate_output = translator.translate(path_words[j], spellcheck_options);
|
93
|
-
if(Object.keys(translate_output).length){
|
114
|
+
if (Object.keys(translate_output).length) {
|
94
115
|
for (const spell_val in translate_output) {
|
95
116
|
if (translate_output.hasOwnProperty(spell_val)) {
|
96
117
|
for (const spelling in translate_output[spell_val][0]) {
|
@@ -108,7 +129,7 @@
|
|
108
129
|
for (let i = 0; i < flat_nav[key].length; i++) {
|
109
130
|
if (flat_nav[key][i].link === key) {
|
110
131
|
const translate_output = translator.translate(flat_nav[key][i].text, spellcheck_options);
|
111
|
-
if(Object.keys(translate_output).length){
|
132
|
+
if (Object.keys(translate_output).length) {
|
112
133
|
for (const spell_val in translate_output) {
|
113
134
|
if (translate_output.hasOwnProperty(spell_val)) {
|
114
135
|
for (let j = 0; j < translate_output[spell_val].length; j++) {
|
@@ -163,7 +184,9 @@
|
|
163
184
|
}
|
164
185
|
|
165
186
|
try {
|
166
|
-
await axios.get(links[i], {
|
187
|
+
await axios.get(links[i], {
|
188
|
+
httpsAgent: agent
|
189
|
+
});
|
167
190
|
messages[htmlFile.relativePath].push(`Link is a valid external URL: ${links[i]}`);
|
168
191
|
} catch (e) {
|
169
192
|
// Handle errors
|
@@ -197,15 +220,17 @@
|
|
197
220
|
const checkTags = async function (htmlFile) {
|
198
221
|
const htmlBody = fs.readFileSync(htmlFile.path, 'utf8');
|
199
222
|
const $ = cheerio.load(htmlBody);
|
200
|
-
|
223
|
+
|
201
224
|
const h1_tags = $('h1').map(function () {
|
202
225
|
return $(this);
|
203
226
|
}).get();
|
227
|
+
|
204
228
|
if (h1_tags.length && h1_tags.length > 1) {
|
229
|
+
//console.log("PATH: ", htmlFile.path); //hdoc-guide/hdocbook/markdown.html
|
205
230
|
let error_msg = `${h1_tags.length} <h1> tags found in content: `;
|
206
231
|
for (let i = 0; i < h1_tags.length; i++) {
|
207
|
-
error_msg
|
208
|
-
if (i <
|
232
|
+
error_msg += h1_tags[i].text();
|
233
|
+
if (i < h1_tags.length - 1) error_msg += '; ';
|
209
234
|
}
|
210
235
|
errors[htmlFile.relativePath].push(error_msg);
|
211
236
|
}
|
@@ -214,7 +239,7 @@
|
|
214
239
|
const dreeOptions = {
|
215
240
|
descendants: true,
|
216
241
|
depth: 10,
|
217
|
-
extensions: ['htm', 'html','md'],
|
242
|
+
extensions: ['htm', 'html', 'md'],
|
218
243
|
hash: false,
|
219
244
|
normalize: true,
|
220
245
|
size: false,
|
@@ -324,7 +349,7 @@
|
|
324
349
|
for (let i = 0; i < prod_families.products.length; i++) {
|
325
350
|
if (prod_families.products[i].id === hdocbook_config.productFamily) {
|
326
351
|
valid_product = true;
|
327
|
-
}
|
352
|
+
}
|
328
353
|
}
|
329
354
|
if (!valid_product) {
|
330
355
|
let val_prod_error = `Incorrect productFamily: ${hdocbook_config.productFamily}. Supported values:`;
|
@@ -332,18 +357,17 @@
|
|
332
357
|
val_prod_error += `\n - ${prods_supported[i]}`
|
333
358
|
}
|
334
359
|
meta_errors.push(val_prod_error)
|
335
|
-
|
360
|
+
|
336
361
|
}
|
337
362
|
|
338
363
|
// Check navigation spellings
|
339
|
-
const nav_errors = await checkNavigation(
|
364
|
+
const nav_errors = await checkNavigation(source_path, nav_items);
|
340
365
|
if (nav_errors.length > 0) meta_errors.push(...nav_errors);
|
341
366
|
|
342
367
|
if (meta_errors.length > 0) {
|
343
368
|
console.log('\r\n-----------------------');
|
344
369
|
console.log(' Validation Output ');
|
345
370
|
console.log('-----------------------');
|
346
|
-
console.log()
|
347
371
|
console.log(`\r\n${meta_errors.length} Validation Errors Found\r\n`);
|
348
372
|
for (let i = 0; i < meta_errors.length; i++) {
|
349
373
|
console.log(`- ${meta_errors[i]}`);
|
@@ -353,12 +377,12 @@
|
|
353
377
|
|
354
378
|
if (hdocbook_project.validation) {
|
355
379
|
if (hdocbook_project.validation.exclude_links && hdocbook_project.validation.exclude_links instanceof Array) {
|
356
|
-
hdocbook_project.validation.exclude_links.forEach(function(excl_link) {
|
357
|
-
|
358
|
-
|
380
|
+
hdocbook_project.validation.exclude_links.forEach(function (excl_link) {
|
381
|
+
exclude_links[excl_link] = true;
|
382
|
+
});
|
359
383
|
}
|
360
384
|
if (hdocbook_project.validation.exclude_spellcheck && hdocbook_project.validation.exclude_spellcheck instanceof Array) {
|
361
|
-
hdocbook_project.validation.exclude_spellcheck.forEach(function(excl_sc) {
|
385
|
+
hdocbook_project.validation.exclude_spellcheck.forEach(function (excl_sc) {
|
362
386
|
exclude_spellcheck[excl_sc.document_path] = excl_sc.words;
|
363
387
|
});
|
364
388
|
}
|
@@ -437,21 +461,20 @@
|
|
437
461
|
console.log('\r\n-----------------------');
|
438
462
|
console.log(' Validation Output ');
|
439
463
|
console.log('-----------------------');
|
440
|
-
|
441
|
-
for (const key in errors) {
|
442
|
-
if (errors.hasOwnProperty(key) && errors[key].length > 0) {
|
443
|
-
console.log(`\r\n${errors[key].length} error(s) in ${key}`);
|
444
|
-
for (let i = 0; i < errors[key].length; i++) {
|
445
|
-
console.log(` - ${errors[key][i]}`);
|
446
|
-
errorcount++;
|
447
|
-
}
|
448
|
-
}
|
449
|
-
}
|
450
|
-
|
451
464
|
if (errorcount > 0) {
|
452
465
|
console.log(`\r\n${errorcount} Validation Errors Found\r\n`);
|
466
|
+
for (const key in errors) {
|
467
|
+
if (errors.hasOwnProperty(key) && errors[key].length > 0) {
|
468
|
+
console.log(`\r\n${errors[key].length} error(s) in ${key}`);
|
469
|
+
for (let i = 0; i < errors[key].length; i++) {
|
470
|
+
console.log(` - ${errors[key][i]}`);
|
471
|
+
errorcount++;
|
472
|
+
}
|
473
|
+
}
|
474
|
+
}
|
453
475
|
return false;
|
454
476
|
}
|
477
|
+
|
455
478
|
console.log(`\r\nNo Validation Errors Found!\r\n`);
|
456
479
|
return true;
|
457
480
|
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "hdoc-tools",
|
3
|
-
"version": "0.9.
|
3
|
+
"version": "0.9.20",
|
4
4
|
"description": "Hornbill HDocBook Development Support Tool",
|
5
5
|
"main": "hdoc.js",
|
6
6
|
"bin": {
|
@@ -52,6 +52,7 @@
|
|
52
52
|
"prompt": "^1.3.0",
|
53
53
|
"puppeteer": "^19.8.0",
|
54
54
|
"stream": "0.0.2",
|
55
|
+
"true-case-path": "^2.2.1",
|
55
56
|
"words-count": "^2.0.2",
|
56
57
|
"zip-a-folder": "^1.1.5"
|
57
58
|
}
|