hdoc-tools 0.8.12 → 0.8.14
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 +244 -37
- package/hdoc-module.js +69 -0
- package/hdoc-stats.js +2 -2
- package/hdoc.js +8 -4
- package/package.json +1 -1
- package/templates/doc-header.html +30 -0
- package/ui/css/theme-default/styles/base.css +4 -1
package/hdoc-build.js
CHANGED
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
const {
|
|
5
5
|
createHash
|
|
6
|
-
} = require('crypto'),
|
|
7
|
-
lutimesSync
|
|
8
|
-
} = require('fs'),
|
|
6
|
+
} = require('crypto'),
|
|
9
7
|
dree = require('dree'),
|
|
10
8
|
fs = require('fs-extra'),
|
|
11
9
|
mdfm = require('markdown-it-front-matter'),
|
|
@@ -27,22 +25,27 @@
|
|
|
27
25
|
'doc_content',
|
|
28
26
|
'doc_preview UNINDEXED',
|
|
29
27
|
'doc_family_id'
|
|
30
|
-
]
|
|
28
|
+
],
|
|
29
|
+
doc_header_template_path = path.join(__dirname, 'templates', 'doc-header.html');
|
|
31
30
|
|
|
32
|
-
let
|
|
31
|
+
let bc = {}, // Breadcrumbs map
|
|
32
|
+
book_read_time = 0,
|
|
33
|
+
built_file_hashes = [],
|
|
34
|
+
conversion_attempted = 0,
|
|
33
35
|
conversion_success = 0,
|
|
34
36
|
conversion_failed = 0,
|
|
37
|
+
doc_header_template = '',
|
|
38
|
+
doc_id = '',
|
|
39
|
+
git_token = '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', // Github fine-grained personal access token that has minimum read-only access to Hornbill Docs org repo content
|
|
40
|
+
hdocbook_config = {},
|
|
41
|
+
hdocbook_project,
|
|
35
42
|
includes_found = 0,
|
|
36
43
|
includes_success = 0,
|
|
37
44
|
includes_failed = 0,
|
|
38
|
-
|
|
39
|
-
hdocbook_project,
|
|
40
|
-
docId = '',
|
|
45
|
+
index_records = [],
|
|
41
46
|
md_files = [],
|
|
42
47
|
static_html_files = [],
|
|
43
|
-
|
|
44
|
-
work_path_content = '',
|
|
45
|
-
built_file_hashes = [];
|
|
48
|
+
work_path_content = '';
|
|
46
49
|
|
|
47
50
|
const transform_static_html = function (file_path) {
|
|
48
51
|
if (fs.existsSync(file_path.path)) {
|
|
@@ -205,7 +208,9 @@
|
|
|
205
208
|
let fm_content = frontmatter_content.split(/\r?\n/);
|
|
206
209
|
|
|
207
210
|
let fm_contains_title = false,
|
|
208
|
-
fm_contains_reading_time = false
|
|
211
|
+
fm_contains_reading_time = false,
|
|
212
|
+
doc_title = '',
|
|
213
|
+
doc_type = 'Article';
|
|
209
214
|
|
|
210
215
|
if (fm_content.length >= 0) {
|
|
211
216
|
fm_content.forEach(function (fm_prop) {
|
|
@@ -218,6 +223,11 @@
|
|
|
218
223
|
|
|
219
224
|
if (fm_property[0].trim() === 'title') {
|
|
220
225
|
fm_contains_title = true;
|
|
226
|
+
doc_title = fm_property[1].trim();
|
|
227
|
+
}
|
|
228
|
+
if (fm_property[0].trim() === 'type') {
|
|
229
|
+
fm_contains_type = true;
|
|
230
|
+
doc_type = fm_property[1].trim();
|
|
221
231
|
}
|
|
222
232
|
if (fm_property[0].trim() === 'reading-time') {
|
|
223
233
|
book_read_time += parseInt(fm_property[1].trim(), 10);
|
|
@@ -227,6 +237,12 @@
|
|
|
227
237
|
});
|
|
228
238
|
}
|
|
229
239
|
|
|
240
|
+
// Add doc type
|
|
241
|
+
fm_headers.push({
|
|
242
|
+
id: 'type',
|
|
243
|
+
value: doc_type
|
|
244
|
+
});
|
|
245
|
+
|
|
230
246
|
// Does frontmatter tag contain a title property
|
|
231
247
|
if (!fm_contains_title) {
|
|
232
248
|
// Frontmatter tags don't contain a title property - go pull the first one from the html heading tags
|
|
@@ -238,12 +254,16 @@
|
|
|
238
254
|
id: 'title',
|
|
239
255
|
value: html_heading[0].children[0].data.trim()
|
|
240
256
|
});
|
|
257
|
+
doc_title = html_heading[0].children[0].data.trim();
|
|
241
258
|
} else {
|
|
242
259
|
// No header tag, no frontmatter title, output a warning
|
|
243
260
|
console.log(`No frontmatter title property, or h1, h2 or h3 header tags detected in ${file_path}`);
|
|
244
261
|
}
|
|
245
262
|
}
|
|
246
263
|
|
|
264
|
+
// Remove the first <h1>title</h1> from the HTML as we'll ass that in the document header
|
|
265
|
+
html_txt = html_txt.replace(/(<h1.*?>)\s*.*\s*(.*<\/h1>)/, '');
|
|
266
|
+
|
|
247
267
|
// Does frontmatter tag contain a reading-time property
|
|
248
268
|
if (!fm_contains_reading_time) {
|
|
249
269
|
const read_time_mins = hdoc.get_html_read_time(html_txt);
|
|
@@ -254,15 +274,51 @@
|
|
|
254
274
|
});
|
|
255
275
|
}
|
|
256
276
|
|
|
257
|
-
//
|
|
277
|
+
// Get contributor data from Github, if exists
|
|
278
|
+
if (hdocbook_config.publicSource && hdocbook_config.publicSource !== '') {
|
|
279
|
+
const github_paths = hdoc.get_github_api_path(hdocbook_config.publicSource, file_path.relativePath);
|
|
280
|
+
const contributors = hdoc.get_github_contributors(github_paths.api_path, git_token);
|
|
281
|
+
if (!contributors.success) {
|
|
282
|
+
console.log(`Error retrieving contributors from Github: ${contributors.error}`);
|
|
283
|
+
} else {
|
|
284
|
+
fm_headers.push({
|
|
285
|
+
id: 'contributor-count',
|
|
286
|
+
value: contributors.contributor_count
|
|
287
|
+
});
|
|
288
|
+
fm_headers.push({
|
|
289
|
+
id: 'last-commit',
|
|
290
|
+
value: contributors.last_commit_date
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
fm_headers.push({
|
|
294
|
+
id: 'edit-path',
|
|
295
|
+
value: github_paths.edit_path
|
|
296
|
+
});
|
|
297
|
+
const target_file = file_path.path.replace(path.extname(file_path.path), '._info.json');
|
|
298
|
+
delete contributors.success;
|
|
299
|
+
delete contributors.error;
|
|
300
|
+
contributors.editPath = github_paths.edit_path;
|
|
301
|
+
try {
|
|
302
|
+
fs.writeFileSync(target_file, JSON.stringify(contributors, null, 2));
|
|
303
|
+
} catch (err) {
|
|
304
|
+
console.log('Error writing:', target_file, '\n', err);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Build doc header from template and frontmatter tags
|
|
309
|
+
const doc_header = process_doc_header(fm_headers, file_path.relativePath);
|
|
310
|
+
|
|
311
|
+
// Add frontmatter tags as comment to front of HTML
|
|
312
|
+
|
|
313
|
+
let fm_header = '<!--[[FRONTMATTER\n';
|
|
258
314
|
if (fm_headers.length > 0) {
|
|
259
|
-
let fm_header = '<!--[[FRONTMATTER\n';
|
|
260
315
|
for (let i = 0; i < fm_headers.length; i++) {
|
|
261
316
|
fm_header += `${fm_headers[i].id}: ${fm_headers[i].value}\n`;
|
|
262
317
|
}
|
|
263
|
-
fm_header += ']]-->';
|
|
264
|
-
html_txt = `${fm_header}\n${html_txt}`;
|
|
265
318
|
}
|
|
319
|
+
fm_header += ']]-->';
|
|
320
|
+
|
|
321
|
+
html_txt = `${fm_header}\n${doc_header}\n${html_txt}`;
|
|
266
322
|
|
|
267
323
|
// Save HTML into HTML file
|
|
268
324
|
const target_file = file_path.path.replace(path.extname(file_path.path), '.html');
|
|
@@ -292,6 +348,46 @@
|
|
|
292
348
|
return false;
|
|
293
349
|
};
|
|
294
350
|
|
|
351
|
+
const process_doc_header = function (fm_headers, doc_path) {
|
|
352
|
+
let wip_doc_header = doc_header_template;
|
|
353
|
+
|
|
354
|
+
// Process fm_headers properties first
|
|
355
|
+
for (let i = 0; i < fm_headers.length; i++) {
|
|
356
|
+
switch (fm_headers[i].id) {
|
|
357
|
+
case 'title':
|
|
358
|
+
wip_doc_header = wip_doc_header.replaceAll('{{title}}', fm_headers[i].value);
|
|
359
|
+
break;
|
|
360
|
+
case 'reading-time':
|
|
361
|
+
wip_doc_header = wip_doc_header.replaceAll('{{reading-time}}', fm_headers[i].value);
|
|
362
|
+
break;
|
|
363
|
+
case 'contributor-count':
|
|
364
|
+
wip_doc_header = wip_doc_header.replaceAll('{{contributor-count}}', fm_headers[i].value);
|
|
365
|
+
break;
|
|
366
|
+
case 'type':
|
|
367
|
+
wip_doc_header = wip_doc_header.replaceAll('{{doc-type}}', fm_headers[i].value);
|
|
368
|
+
break;
|
|
369
|
+
case 'edit-path':
|
|
370
|
+
wip_doc_header = wip_doc_header.replaceAll('{{edit-url}}', fm_headers[i].value);
|
|
371
|
+
break;
|
|
372
|
+
case 'last-commit':
|
|
373
|
+
const last_commit_date = new Date(fm_headers[i].value).toDateString();
|
|
374
|
+
wip_doc_header = wip_doc_header.replaceAll('{{last-update}}', last_commit_date);
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Now sort out breadcrumbs
|
|
380
|
+
const logical_path = doc_path.replace(path.extname(doc_path), '');
|
|
381
|
+
const bc_for_path = bc[logical_path];
|
|
382
|
+
let bc_tags = '\n';
|
|
383
|
+
for (let i = 0; i < bc_for_path.length - 1; i++) {
|
|
384
|
+
bc_tags += `\t\t\t\t<li class="mt-0 nav-bar-item"><a href="${bc_for_path[i].link}" class="ps-0 pe-0 text-decoration-none">${bc_for_path[i].text}</a></li>\n`;
|
|
385
|
+
}
|
|
386
|
+
bc_tags += '\t\t\t';
|
|
387
|
+
wip_doc_header = wip_doc_header.replaceAll('{{breadcrumbs}}', bc_tags);
|
|
388
|
+
return wip_doc_header;
|
|
389
|
+
};
|
|
390
|
+
|
|
295
391
|
// File callback for build scan
|
|
296
392
|
const build_file_callback = function (element) {
|
|
297
393
|
if (element.extension === 'md') {
|
|
@@ -330,7 +426,111 @@
|
|
|
330
426
|
sorted: true
|
|
331
427
|
};
|
|
332
428
|
|
|
333
|
-
|
|
429
|
+
const build_breadcrumbs = function (nav_items) {
|
|
430
|
+
console.log('Processing navigation breadcrumbs...\n');
|
|
431
|
+
// Steve - need to rework this to use recursion, as it's hard-coded for a maximum of 4 levels deep right now
|
|
432
|
+
for (let a = 0; a < nav_items.length; a++) {
|
|
433
|
+
const nav_a = nav_items[a];
|
|
434
|
+
const parent_a = nav_a.text;
|
|
435
|
+
if (nav_a.link) {
|
|
436
|
+
if (nav_a.link.includes('\\')) {
|
|
437
|
+
console.log(`Navigation items should not contain backslashes: ${nav_a.link}`);
|
|
438
|
+
process.exit(1);
|
|
439
|
+
}
|
|
440
|
+
bc[nav_a.link] = [{
|
|
441
|
+
text: nav_a.text,
|
|
442
|
+
link: nav_a.link
|
|
443
|
+
}];
|
|
444
|
+
}
|
|
445
|
+
if (nav_a.items) {
|
|
446
|
+
for (let b = 0; b < nav_a.items.length; b++) {
|
|
447
|
+
const nav_b = nav_a.items[b];
|
|
448
|
+
const parent_b = nav_b.text;
|
|
449
|
+
if (nav_b.link) {
|
|
450
|
+
if (nav_b.link.includes('\\')) {
|
|
451
|
+
console.log(`Navigation items should not contain backslashes: ${nav_b.link}`);
|
|
452
|
+
process.exit(1);
|
|
453
|
+
}
|
|
454
|
+
if (bc[nav_a.link]) {
|
|
455
|
+
bc[nav_b.link] = bc[nav_a.link];
|
|
456
|
+
} else {
|
|
457
|
+
bc[nav_b.link] = [{
|
|
458
|
+
text: parent_a,
|
|
459
|
+
link: nav_a.items[0].link
|
|
460
|
+
}];
|
|
461
|
+
}
|
|
462
|
+
bc[nav_b.link].push({
|
|
463
|
+
text: nav_b.text,
|
|
464
|
+
link: nav_b.link
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
if (nav_b.items) {
|
|
469
|
+
for (let c = 0; c < nav_b.items.length; c++) {
|
|
470
|
+
const nav_c = nav_b.items[c];
|
|
471
|
+
const parent_c = nav_c.text;
|
|
472
|
+
if (nav_c.link) {
|
|
473
|
+
if (nav_c.link.includes('\\')) {
|
|
474
|
+
console.log(`Navigation items should not contain backslashes: ${nav_c.link}`);
|
|
475
|
+
process.exit(1);
|
|
476
|
+
}
|
|
477
|
+
if (bc[nav_b.link]) {
|
|
478
|
+
bc[nav_c.link] = bc[nav_b.link];
|
|
479
|
+
} else {
|
|
480
|
+
bc[nav_c.link] = [{
|
|
481
|
+
text: parent_a,
|
|
482
|
+
link: nav_a.items[0].link
|
|
483
|
+
}];
|
|
484
|
+
bc[nav_c.link].push({
|
|
485
|
+
text: parent_b,
|
|
486
|
+
link: nav_b.items[0].link
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
bc[nav_c.link].push({
|
|
490
|
+
text: nav_c.text,
|
|
491
|
+
link: nav_c.link
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (nav_c.items) {
|
|
496
|
+
for (let d = 0; d < nav_c.items.length; d++) {
|
|
497
|
+
const nav_d = nav_c.items[d];
|
|
498
|
+
if (nav_d.link) {
|
|
499
|
+
if (bc[nav_c.link]) {
|
|
500
|
+
bc[nav_d.link] = bc[nav_c.link];
|
|
501
|
+
} else {
|
|
502
|
+
bc[nav_d.link] = [{
|
|
503
|
+
text: parent_a,
|
|
504
|
+
link: nav_a.items[0].link
|
|
505
|
+
}];
|
|
506
|
+
bc[nav_d.link].push({
|
|
507
|
+
text: parent_b,
|
|
508
|
+
link: nav_b.items[0].link
|
|
509
|
+
});
|
|
510
|
+
bc[nav_d.link].push({
|
|
511
|
+
text: parent_c,
|
|
512
|
+
link: nav_c.items[0].link
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
bc[nav_d.link].push({
|
|
516
|
+
text: nav_d.text,
|
|
517
|
+
link: nav_d.link
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
}
|
|
529
|
+
//console.log(JSON.stringify(bc, null, 2));
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
exports.run = function (source_path, verbose, github_api_token) {
|
|
533
|
+
git_token = github_api_token;
|
|
334
534
|
// GERRY: The purpose of this function is to create a zip file containing the hdocbook content,
|
|
335
535
|
// * Create a _work folder
|
|
336
536
|
// * copy the hdocbook content to the work folder
|
|
@@ -348,20 +548,19 @@
|
|
|
348
548
|
// use the docId to get the book config
|
|
349
549
|
const hdocbook_project_config_path = path.join(source_path, 'hdocbook-project.json');
|
|
350
550
|
hdocbook_project = require(hdocbook_project_config_path);
|
|
551
|
+
doc_id = hdocbook_project.docId;
|
|
351
552
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
const book_path = path.join(source_path, docId),
|
|
553
|
+
const book_path = path.join(source_path, doc_id),
|
|
355
554
|
hdocbook_path = path.join(book_path, 'hdocbook.json'),
|
|
356
|
-
hdocbook_config = require(hdocbook_path),
|
|
357
555
|
work_path = path.join(source_path, '_work'),
|
|
358
|
-
work_hdocbook_path = path.join(work_path,
|
|
556
|
+
work_hdocbook_path = path.join(work_path, doc_id, 'hdocbook.json');
|
|
359
557
|
|
|
360
|
-
|
|
558
|
+
hdocbook_config = require(hdocbook_path);
|
|
559
|
+
|
|
560
|
+
console.log(`Building: ${doc_id} v${hdocbook_config.version}...\n`);
|
|
361
561
|
|
|
362
|
-
|
|
363
|
-
work_path_content = path.join(work_path, docId);
|
|
364
562
|
// Make _work folder to copy everything into
|
|
563
|
+
work_path_content = path.join(work_path, doc_id);
|
|
365
564
|
if (fs.existsSync(work_path)) {
|
|
366
565
|
fs.rmSync(work_path, {
|
|
367
566
|
recursive: true,
|
|
@@ -370,14 +569,24 @@
|
|
|
370
569
|
}
|
|
371
570
|
fs.mkdirSync(work_path);
|
|
372
571
|
|
|
373
|
-
// Copy files from book into _work-
|
|
572
|
+
// Copy files from book into _work-doc_id folder
|
|
374
573
|
try {
|
|
375
|
-
fs.copySync(path.join(source_path,
|
|
574
|
+
fs.copySync(path.join(source_path, doc_id), work_path_content);
|
|
376
575
|
} catch (e) {
|
|
377
576
|
console.error('Error copying from source_path:\n', e);
|
|
378
577
|
process.exit(1);
|
|
379
578
|
}
|
|
380
579
|
|
|
580
|
+
// Load document header template
|
|
581
|
+
try {
|
|
582
|
+
doc_header_template = fs.readFileSync(doc_header_template_path, 'utf8');
|
|
583
|
+
} catch (err) {
|
|
584
|
+
console.log(`Error reading document header template: ${err}`);
|
|
585
|
+
process.exit(1);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
build_breadcrumbs(hdocbook_config.navigation.items);
|
|
589
|
+
|
|
381
590
|
// Get a list of MD files in work_path
|
|
382
591
|
dree.scan(work_path, dreeOptions, build_file_callback);
|
|
383
592
|
|
|
@@ -391,25 +600,23 @@
|
|
|
391
600
|
transform_static_html(static_html_file);
|
|
392
601
|
});
|
|
393
602
|
|
|
394
|
-
|
|
395
603
|
console.log(` MD files found: ${conversion_attempted}`);
|
|
396
604
|
console.log(`Successfully converted to HTML: ${conversion_success}`);
|
|
397
605
|
console.log(` Failed to convert: ${conversion_failed}\n`);
|
|
398
606
|
console.log(` Includes Found: ${includes_found}`);
|
|
399
607
|
console.log(` Includes Success: ${includes_success}`);
|
|
400
608
|
console.log(` Includes Failed: ${includes_failed}\n`);
|
|
401
|
-
|
|
402
609
|
console.log(` Static HTML Files Found: ${static_html_files.length}\n`);
|
|
403
610
|
|
|
404
611
|
// Validate content
|
|
405
|
-
const validation_success = validate.run(work_path,
|
|
612
|
+
const validation_success = validate.run(work_path, doc_id, verbose);
|
|
406
613
|
if (!validation_success) {
|
|
407
614
|
process.exit(1);
|
|
408
615
|
}
|
|
409
616
|
|
|
410
617
|
// Now build the index
|
|
411
618
|
console.log('Performing SQlite index creation...');
|
|
412
|
-
let db_name = path.join(work_path,
|
|
619
|
+
let db_name = path.join(work_path, doc_id, 'index.db');
|
|
413
620
|
const db = new Database(db_name);
|
|
414
621
|
db.pragma('encoding="UTF-8"');
|
|
415
622
|
console.log(`\nDatabase created: ${db_name}`);
|
|
@@ -425,11 +632,11 @@
|
|
|
425
632
|
if (!hdocbook_config.tags) hdocbook_config.tags = [];
|
|
426
633
|
let index_success_count = 0;
|
|
427
634
|
for (let i = 0; i < index_records.length; i++) {
|
|
428
|
-
let index_path_name = index_records[i].relative_path.replace('\\', '/').replace(`${
|
|
635
|
+
let index_path_name = index_records[i].relative_path.replace('\\', '/').replace(`${doc_id}/`, '');
|
|
429
636
|
index_path_name = index_path_name.replace(path.extname(index_records[i].relative_path), '');
|
|
430
637
|
const index_vals = [
|
|
431
638
|
index_path_name,
|
|
432
|
-
|
|
639
|
+
doc_id,
|
|
433
640
|
hdocbook_config.audience.join(','),
|
|
434
641
|
hdocbook_config.tags.join(','),
|
|
435
642
|
index_records[i].index_html.fm_props.title,
|
|
@@ -437,14 +644,14 @@
|
|
|
437
644
|
index_records[i].index_html.preview,
|
|
438
645
|
hdocbook_config.productFamily
|
|
439
646
|
];
|
|
440
|
-
const index_response = hdoc_index.insert_record(db, table_name, index_cols, index_vals,
|
|
647
|
+
const index_response = hdoc_index.insert_record(db, table_name, index_cols, index_vals, doc_id, index_records[i].index_html.fm_props.title);
|
|
441
648
|
if (!index_response.success) {
|
|
442
|
-
console.log(`Index record creation failed - ${
|
|
649
|
+
console.log(`Index record creation failed - ${doc_id}/${index_records[i].index_html.fm_props.title}: ${index_response.error}`);
|
|
443
650
|
continue;
|
|
444
651
|
}
|
|
445
652
|
index_success_count++;
|
|
446
653
|
if (verbose) {
|
|
447
|
-
console.log(`Inserted index record ${index_response.row_id}: ${
|
|
654
|
+
console.log(`Inserted index record ${index_response.row_id}: ${doc_id} - ${index_records[i].index_html.fm_props.title}`);
|
|
448
655
|
}
|
|
449
656
|
}
|
|
450
657
|
console.log(`\nIndex Build Complete: ${index_success_count} records created.`);
|
|
@@ -483,7 +690,7 @@
|
|
|
483
690
|
}
|
|
484
691
|
|
|
485
692
|
try {
|
|
486
|
-
const zip_path = path.join(work_path,
|
|
693
|
+
const zip_path = path.join(work_path, doc_id + '.zip');
|
|
487
694
|
zipper.sync.zip(work_path_content).compress().save(zip_path);
|
|
488
695
|
console.log(`\nZIP Creation Success: ${zip_path}\n`);
|
|
489
696
|
console.log('Build Complete\n');
|
package/hdoc-module.js
CHANGED
|
@@ -213,4 +213,73 @@
|
|
|
213
213
|
if (read_time === 0) read_time = 1;
|
|
214
214
|
return read_time;
|
|
215
215
|
};
|
|
216
|
+
|
|
217
|
+
exports.get_github_api_path = function(repo, relative_path) {
|
|
218
|
+
repo = repo.endsWith('/') ? repo.slice(0, -1) : repo;
|
|
219
|
+
let github_paths = {};
|
|
220
|
+
github_paths.api_path = repo.replace('https://github.com/', 'https://api.github.com/repos/');
|
|
221
|
+
github_paths.api_path += '/commits?path=/' + relative_path.replace('\\\\', '/').replace('\\', '/');
|
|
222
|
+
github_paths.edit_path = repo + '/blob/main/' + relative_path.replace('\\\\', '/').replace('\\', '/');
|
|
223
|
+
return github_paths;
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
exports.get_github_contributors = function(github_url, github_api_token) {
|
|
227
|
+
let response = {
|
|
228
|
+
success: false,
|
|
229
|
+
error: '',
|
|
230
|
+
contributors: [],
|
|
231
|
+
contributor_count: 0,
|
|
232
|
+
last_commit_date:''
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
let contributors = {};
|
|
236
|
+
|
|
237
|
+
let request_options = {
|
|
238
|
+
headers: {
|
|
239
|
+
'User-Agent': 'HornbillDocsBuild',
|
|
240
|
+
'Cache-Control': 'no-cache',
|
|
241
|
+
'Host': 'api.github.com',
|
|
242
|
+
'Accept': 'application/json'
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
if (github_api_token !== '') {
|
|
246
|
+
request_options.headers.authorization = `Bearer ${github_api_token}`;
|
|
247
|
+
}
|
|
248
|
+
const github_response = request('GET', github_url, request_options);
|
|
249
|
+
|
|
250
|
+
if (github_response.statusCode === 200) {
|
|
251
|
+
response.success = true;
|
|
252
|
+
let commits = github_response.getBody('UTF8');
|
|
253
|
+
commits = JSON.parse(commits);
|
|
254
|
+
commits.forEach(function(commit){
|
|
255
|
+
if (commit.committer.type.toLowerCase() === 'user' && commit.committer.login.toLowerCase() !== 'web-flow') {
|
|
256
|
+
if (!contributors[commit.committer.id]) {
|
|
257
|
+
response.contributor_count++;
|
|
258
|
+
contributors[commit.committer.id] = {
|
|
259
|
+
login: commit.committer.login,
|
|
260
|
+
avatar_url: commit.committer.avatar_url,
|
|
261
|
+
html_url: commit.committer.html_url,
|
|
262
|
+
name: commit.commit.committer.name
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
if (response.last_commit_date !== '') {
|
|
266
|
+
const new_commit_date = new Date(commit.commit.committer.date);
|
|
267
|
+
const exist_commit_date = new Date(response.last_commit_date);
|
|
268
|
+
if (new_commit_date > exist_commit_date) response.last_commit_date = commit.commit.committer.date;
|
|
269
|
+
} else {
|
|
270
|
+
response.last_commit_date = commit.commit.committer.date;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
for (const key in contributors) {
|
|
275
|
+
if (contributors.hasOwnProperty(key)) {
|
|
276
|
+
response.contributors.push(contributors[key]);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
} else {
|
|
280
|
+
response.error = `Unexpected Status ${github_response.statusCode}. ${JSON.parse(github_response.body.toString('utf8')).message}`;
|
|
281
|
+
}
|
|
282
|
+
return response;
|
|
283
|
+
};
|
|
284
|
+
|
|
216
285
|
})();
|
package/hdoc-stats.js
CHANGED
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
symbolicLinks: false
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
-
exports.run = function(ui_path, source_path,
|
|
63
|
+
exports.run = function(ui_path, source_path, verbose = false) {
|
|
64
64
|
|
|
65
65
|
// GERRY: The stats here are needed to support content development. The idea is to count all of the ]
|
|
66
66
|
// words in a HDocBook so we know the size of the book, this helps with 3rd party involvement where
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
// * MD files, and word count those
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
console.log('Hornbill HDocBook Stats', '\r\n');
|
|
79
|
+
console.log('Hornbill HDocBook Stats : verbose=' + verbose, '\r\n');
|
|
80
80
|
|
|
81
81
|
const project_json_path = path.join(source_path, 'hdocbook-project.json');
|
|
82
82
|
|
package/hdoc.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
(function () {
|
|
4
4
|
'use strict';
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
// Default source path to working directory
|
|
26
26
|
let source_path = process.cwd();
|
|
27
27
|
let ui_path = path.join(__dirname, 'ui');
|
|
28
|
-
|
|
28
|
+
let git_token = '';
|
|
29
29
|
let command = '', // Our command to run
|
|
30
30
|
verbose = false;
|
|
31
31
|
|
|
@@ -50,12 +50,16 @@
|
|
|
50
50
|
if (x < process.argv.length) {
|
|
51
51
|
ui_path = process.argv[x];
|
|
52
52
|
}
|
|
53
|
+
} else if (process.argv[x] == '-git-token') {
|
|
54
|
+
x++;
|
|
55
|
+
if (x < process.argv.length) {
|
|
56
|
+
git_token = process.argv[x];
|
|
57
|
+
}
|
|
53
58
|
}
|
|
54
59
|
|
|
55
60
|
if (process.argv[x] === '-v') {
|
|
56
61
|
verbose = true;
|
|
57
62
|
}
|
|
58
|
-
|
|
59
63
|
}
|
|
60
64
|
|
|
61
65
|
console.log('Hornbill HDocBook Tools v' + getHdocPackageVersion(packageFile), '\r\n');
|
|
@@ -67,7 +71,7 @@
|
|
|
67
71
|
server.run(ui_path, source_path);
|
|
68
72
|
} else if (command == 'build') {
|
|
69
73
|
const builder = require(path.join(__dirname, 'hdoc-build.js'));
|
|
70
|
-
builder.run(source_path, verbose);
|
|
74
|
+
builder.run(source_path, verbose, git_token);
|
|
71
75
|
} else if (command == 'stats') {
|
|
72
76
|
const stats = require(path.join(__dirname, 'hdoc-stats.js'));
|
|
73
77
|
stats.run(ui_path, source_path, verbose);
|
package/package.json
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<div class="document-header">
|
|
2
|
+
<div class="hb-container-horizontal">
|
|
3
|
+
<div class="hb-center-v hb-container-expand">
|
|
4
|
+
<ul class="ps-0 nav-bar-nav-list noeffects after-fslash overflow-ellipsis">{{breadcrumbs}}</ul>
|
|
5
|
+
</div>
|
|
6
|
+
<div class="toolbar-right hb-center-v">
|
|
7
|
+
<a target="_blank" class="toolbar-action" href="{{edit-url}}">
|
|
8
|
+
<i class="bi bi-pencil"></i>
|
|
9
|
+
</a>
|
|
10
|
+
<a class="toolbar-action documentation-menu-popper">
|
|
11
|
+
<i class="bi bi-three-dots-vertical"></i>
|
|
12
|
+
</a>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<h1>{{title}}</h1>
|
|
17
|
+
|
|
18
|
+
<div class="hb-container-horizontal">
|
|
19
|
+
<div class="hb-center-v hb-container-expand">
|
|
20
|
+
<ul class="ps-0 nav-bar-nav-list noeffects after-bullets overflow-ellipsis text-light-2">
|
|
21
|
+
<li class="ps-0 mt-0 nav-bar-item">{{doc-type}}</li>
|
|
22
|
+
<li class="ps-0 mt-0 nav-bar-item">{{last-update}}</li>
|
|
23
|
+
<li class="ps-0 mt-0 nav-bar-item">{{reading-time}} minutes to read</li>
|
|
24
|
+
<li class="ps-0 mt-0 nav-bar-item">
|
|
25
|
+
<a class="link c-pointer" data-bs-toggle="modal" data-bs-target="#contributersModal">{{contributor-count}} contributors</a>
|
|
26
|
+
</li>
|
|
27
|
+
</ul>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|