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/custom_modules/tips.js +88 -86
- package/hdoc-build-db.js +260 -198
- package/hdoc-build-pdf.js +219 -173
- package/hdoc-build.js +1480 -1505
- package/hdoc-bump.js +123 -109
- package/hdoc-create.js +108 -95
- package/hdoc-db.js +97 -125
- package/hdoc-help.js +48 -51
- package/hdoc-init.js +181 -147
- package/hdoc-module.js +708 -723
- package/hdoc-serve.js +390 -361
- package/hdoc-stats.js +187 -184
- package/hdoc-validate.js +956 -717
- package/hdoc-ver.js +43 -43
- package/hdoc.js +142 -124
- package/package.json +60 -60
- package/templates/init/_hdocbook/hdocbook.json +23 -23
- package/templates/init/hdocbook-project.json +10 -10
- package/templates/init/package.json +8 -10
- package/ui/js/doc.hornbill.js +708 -659
- package/validateNodeVer.js +17 -14
package/hdoc-build.js
CHANGED
@@ -1,1505 +1,1480 @@
|
|
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
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1450
|
-
|
1451
|
-
|
1452
|
-
|
1453
|
-
|
1454
|
-
|
1455
|
-
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
1460
|
-
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
console.log(`Build Completed: ${new Date().toLocaleString()}\n`);
|
1482
|
-
} catch (e) {
|
1483
|
-
console.error("\nError creating ZIP: " + e);
|
1484
|
-
}
|
1485
|
-
} else {
|
1486
|
-
console.log("\nValidation Complete\n");
|
1487
|
-
}
|
1488
|
-
const end_time = Date.now();
|
1489
|
-
console.log(`Time Taken: ${get_duration(start_time, end_time)}\n`);
|
1490
|
-
};
|
1491
|
-
|
1492
|
-
const get_duration = function (start, end) {
|
1493
|
-
const total_time = new Date(end - start).toISOString().slice(11, 19);
|
1494
|
-
const duration_arr = total_time.split(":");
|
1495
|
-
let duration = "";
|
1496
|
-
if (parseInt(duration_arr[0], 10) > 0) {
|
1497
|
-
duration += parseInt(duration_arr[0], 10) + "h ";
|
1498
|
-
}
|
1499
|
-
if (duration !== "" || parseInt(duration_arr[1], 10)) {
|
1500
|
-
duration += parseInt(duration_arr[1], 10) + "m ";
|
1501
|
-
}
|
1502
|
-
duration += parseInt(duration_arr[2], 10) + "s";
|
1503
|
-
return duration;
|
1504
|
-
};
|
1505
|
-
})();
|
1
|
+
(() => {
|
2
|
+
const crypto = require("node:crypto");
|
3
|
+
const dree = require("dree");
|
4
|
+
const fs = require("fs-extra");
|
5
|
+
const mdfm = require("markdown-it-front-matter");
|
6
|
+
const path = require("node:path");
|
7
|
+
const puppeteer = require("puppeteer");
|
8
|
+
const URL = require("node:url").URL;
|
9
|
+
const hdoc_validate = require(path.join(__dirname, "hdoc-validate.js"));
|
10
|
+
const hdoc = require(path.join(__dirname, "hdoc-module.js"));
|
11
|
+
const hdoc_build_db = require(path.join(__dirname, "hdoc-build-db.js"));
|
12
|
+
const hdoc_build_pdf = require(path.join(__dirname, "hdoc-build-pdf.js"));
|
13
|
+
const hdoc_index = require(path.join(__dirname, "hdoc-db.js"));
|
14
|
+
const archiver = require("archiver");
|
15
|
+
const xmlFormat = require("xml-formatter");
|
16
|
+
|
17
|
+
const h_tags_to_search = ["h1", "h2", "h3"];
|
18
|
+
const image_extensions = ["png", "svg", "jpg"];
|
19
|
+
const doc_header_template_path = path.join(
|
20
|
+
__dirname,
|
21
|
+
"templates",
|
22
|
+
"doc-header.html",
|
23
|
+
);
|
24
|
+
const non_git_doc_header_template_path = path.join(
|
25
|
+
__dirname,
|
26
|
+
"templates",
|
27
|
+
"doc-header-non-git.html",
|
28
|
+
);
|
29
|
+
const pdf_header_template_path = path.join(
|
30
|
+
__dirname,
|
31
|
+
"templates",
|
32
|
+
"pdf-header.html",
|
33
|
+
);
|
34
|
+
const non_git_pdf_header_template_path = path.join(
|
35
|
+
__dirname,
|
36
|
+
"templates",
|
37
|
+
"pdf-header-non-git.html",
|
38
|
+
);
|
39
|
+
const pdf_template_path = path.join(__dirname, "templates", "pdf");
|
40
|
+
const ui_css_path = path.join(__dirname, "ui", "css");
|
41
|
+
const pdf_template_file_path = path.join(pdf_template_path, "template.html");
|
42
|
+
const regex_version = /^[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,6}$/;
|
43
|
+
const h1_pattern = /(<h1.*?>)\s*.*\s*(.*<\/h1>)/;
|
44
|
+
const regex_filename = /^[a-z]+-{0,1}([-a-z0-9]+)*$/;
|
45
|
+
|
46
|
+
const built_file_hashes = [];
|
47
|
+
const css_templates = [];
|
48
|
+
const errors_filename = [];
|
49
|
+
const index_records = [];
|
50
|
+
const md_files = [];
|
51
|
+
const md_files_delete = [];
|
52
|
+
const redirects = {};
|
53
|
+
const static_html_files = [];
|
54
|
+
|
55
|
+
let bc = {}; // Breadcrumbs map
|
56
|
+
let book_read_time = 0;
|
57
|
+
let browser = {};
|
58
|
+
let conversion_attempted = 0;
|
59
|
+
let conversion_success = 0;
|
60
|
+
let conversion_failed = 0;
|
61
|
+
let doc_header_template = "";
|
62
|
+
let doc_header_template_non_git = "";
|
63
|
+
let global_source_path = "";
|
64
|
+
let pdf_created = 0;
|
65
|
+
let pdf_enable = false;
|
66
|
+
let pdf_header_template = "";
|
67
|
+
let pdf_header_template_non_git = "";
|
68
|
+
let pdf_template = "";
|
69
|
+
let prod_families = {};
|
70
|
+
let prods_supported = [];
|
71
|
+
let doc_id = "";
|
72
|
+
let git_token =
|
73
|
+
"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"; // Github fine-grained personal access token that has minimum read-only access to Hornbill Docs metadata
|
74
|
+
let hdocbook_config = {};
|
75
|
+
let hdocbook_project;
|
76
|
+
let includes_found = 0;
|
77
|
+
let includes_success = 0;
|
78
|
+
let includes_failed = 0;
|
79
|
+
let work_path_content = "";
|
80
|
+
let verbose = false;
|
81
|
+
|
82
|
+
const pdf_path_excluded = (relative_path) => {
|
83
|
+
if (
|
84
|
+
!hdocbook_project.pdfGeneration ||
|
85
|
+
hdocbook_project.pdfGeneration.exclude_paths === undefined
|
86
|
+
) {
|
87
|
+
return false;
|
88
|
+
}
|
89
|
+
let clean_rel_path = relative_path;
|
90
|
+
if (relative_path.startsWith("/")) {
|
91
|
+
clean_rel_path = clean_rel_path.slice(1, clean_rel_path.length);
|
92
|
+
}
|
93
|
+
for (
|
94
|
+
let i = 0;
|
95
|
+
i < hdocbook_project.pdfGeneration.exclude_paths.length;
|
96
|
+
i++
|
97
|
+
) {
|
98
|
+
const exclude_path = hdocbook_project.pdfGeneration.exclude_paths[i];
|
99
|
+
if (clean_rel_path === exclude_path) return true;
|
100
|
+
if (exclude_path.at(-1) === "*") {
|
101
|
+
if (clean_rel_path.startsWith(exclude_path.slice(0, -1))) {
|
102
|
+
return true;
|
103
|
+
}
|
104
|
+
}
|
105
|
+
}
|
106
|
+
return false;
|
107
|
+
};
|
108
|
+
|
109
|
+
const transform_static_html = async (file_path) => {
|
110
|
+
if (fs.existsSync(file_path.path)) {
|
111
|
+
// Load HTML file
|
112
|
+
let html_txt = fs.readFileSync(file_path.path, "utf8");
|
113
|
+
html_txt = html_txt.replace(/\r/gm, ""); // Remove CR's so we're just dealing with newlines
|
114
|
+
|
115
|
+
const fm_headers = [];
|
116
|
+
let existing_fm_headers = false;
|
117
|
+
let doc_type = "Article";
|
118
|
+
let doc_title = "";
|
119
|
+
|
120
|
+
// Check if we have a frontmatter comment
|
121
|
+
const fm_header = hdoc.getHTMLFrontmatterHeader(html_txt);
|
122
|
+
if (Object.keys(fm_header.fm_properties).length > 0) {
|
123
|
+
existing_fm_headers = true;
|
124
|
+
|
125
|
+
// We have some frontmatter headers, check if title is one of them
|
126
|
+
let fm_title_found = false;
|
127
|
+
if (
|
128
|
+
fm_header.fm_properties &&
|
129
|
+
fm_header.fm_properties.title !== undefined
|
130
|
+
) {
|
131
|
+
// We have a title - but does the title have a value
|
132
|
+
if (fm_header.fm_properties.title === "") {
|
133
|
+
// No value - remove title from the properties map so we don't end up with 2 title properties, one empty and one with a value
|
134
|
+
fm_header.fm_properties.title = undefined;
|
135
|
+
} else {
|
136
|
+
// We have a value for the title property
|
137
|
+
fm_title_found = true;
|
138
|
+
doc_title = fm_header.fm_properties.title.trim();
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
// Is reading-time in the fm headers?
|
143
|
+
if (fm_header.fm_properties["reading-time"] === undefined) {
|
144
|
+
const read_time_mins = hdoc.get_html_read_time(html_txt);
|
145
|
+
book_read_time += read_time_mins;
|
146
|
+
fm_header.fm_properties["reading-time"] = read_time_mins;
|
147
|
+
}
|
148
|
+
|
149
|
+
for (const key in fm_header.fm_properties) {
|
150
|
+
if (Object.hasOwn(fm_header.fm_properties, key)) {
|
151
|
+
if (key === "type") doc_type = fm_header.fm_properties[key];
|
152
|
+
else {
|
153
|
+
fm_headers.push({
|
154
|
+
id: key,
|
155
|
+
value: fm_header.fm_properties[key],
|
156
|
+
});
|
157
|
+
}
|
158
|
+
}
|
159
|
+
}
|
160
|
+
|
161
|
+
if (
|
162
|
+
!fm_title_found &&
|
163
|
+
file_path.name !== "description_ext.md" &&
|
164
|
+
file_path.name !== "article_ext.md"
|
165
|
+
) {
|
166
|
+
// No frontmatter title found in properties
|
167
|
+
// Go get title from h tags in html
|
168
|
+
const html_heading = hdoc.getFirstHTMLHeading(
|
169
|
+
html_txt,
|
170
|
+
h_tags_to_search,
|
171
|
+
);
|
172
|
+
|
173
|
+
if (html_heading?.[0]?.children?.[0]?.data) {
|
174
|
+
// We've found a heading tag, add that as a title to the existing frontmatter properties
|
175
|
+
fm_headers.push({
|
176
|
+
id: "title",
|
177
|
+
value: html_heading[0].children[0].data,
|
178
|
+
});
|
179
|
+
doc_title = html_heading[0].children[0].data;
|
180
|
+
} else {
|
181
|
+
// No header tag, no frontmatter title, output a warning
|
182
|
+
console.info(
|
183
|
+
`[WARNING] No frontmatter title property, or ${h_tags_to_search.join(
|
184
|
+
", ",
|
185
|
+
)} tags detected in ${file_path.path}`,
|
186
|
+
);
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
// Do we have a description header?
|
191
|
+
if (
|
192
|
+
fm_header.fm_properties &&
|
193
|
+
fm_header.fm_properties.description !== undefined
|
194
|
+
) {
|
195
|
+
if (fm_header.fm_properties.description === "") {
|
196
|
+
const html_p_tag = hdoc.getFirstHTMLHeading(html_txt, ["p"]);
|
197
|
+
if (html_p_tag?.[0]?.children?.[0]?.data) {
|
198
|
+
fm_headers.push({
|
199
|
+
id: "description",
|
200
|
+
value:
|
201
|
+
`${doc_title}: ${html_p_tag[0].children[0].data.split(".")[0]}.`.trim(),
|
202
|
+
});
|
203
|
+
}
|
204
|
+
} else {
|
205
|
+
fm_headers.push({
|
206
|
+
id: "description",
|
207
|
+
value: fm_header.fm_properties.description.trim(),
|
208
|
+
});
|
209
|
+
}
|
210
|
+
} else {
|
211
|
+
const html_p_tag = hdoc.getFirstHTMLHeading(html_txt, ["p"]);
|
212
|
+
if (html_p_tag?.[0]?.children?.[0]?.data) {
|
213
|
+
fm_headers.push({
|
214
|
+
id: "description",
|
215
|
+
value:
|
216
|
+
`${doc_title}: ${html_p_tag[0].children[0].data.split(".")[0]}.`.trim(),
|
217
|
+
});
|
218
|
+
}
|
219
|
+
}
|
220
|
+
} else {
|
221
|
+
// We have no frontmatter headers, get and build one from the html headings
|
222
|
+
const html_heading = hdoc.getFirstHTMLHeading(
|
223
|
+
html_txt,
|
224
|
+
h_tags_to_search,
|
225
|
+
);
|
226
|
+
let doc_title = "";
|
227
|
+
// Add the title
|
228
|
+
if (html_heading?.[0]?.children?.[0]?.data) {
|
229
|
+
// We've found a heading tag, add that as a title to the frontmatter content
|
230
|
+
fm_headers.push({
|
231
|
+
id: "title",
|
232
|
+
value: html_heading[0].children[0].data,
|
233
|
+
});
|
234
|
+
doc_title = html_heading[0].children[0].data;
|
235
|
+
} else if (
|
236
|
+
file_path.name !== "description_ext.md" &&
|
237
|
+
file_path.name !== "article_ext.md"
|
238
|
+
) {
|
239
|
+
// No header tag, no frontmatter title, output a warning
|
240
|
+
console.info(
|
241
|
+
`[WARNING] No frontmatter title property, or ${h_tags_to_search.join(
|
242
|
+
", ",
|
243
|
+
)} tags detected in ${file_path.path}`,
|
244
|
+
);
|
245
|
+
}
|
246
|
+
|
247
|
+
// Add the reading time
|
248
|
+
const read_time_mins = hdoc.get_html_read_time(html_txt);
|
249
|
+
book_read_time += read_time_mins;
|
250
|
+
fm_headers.push({
|
251
|
+
id: "reading-time",
|
252
|
+
value: read_time_mins,
|
253
|
+
});
|
254
|
+
|
255
|
+
const html_p_tag = hdoc.getFirstHTMLHeading(html_txt, ["p"]);
|
256
|
+
if (html_p_tag?.[0]?.children?.[0]?.data) {
|
257
|
+
fm_headers.push({
|
258
|
+
id: "description",
|
259
|
+
value:
|
260
|
+
`${doc_title}: ${html_p_tag[0].children[0].data.split(".")[0]}.`.trim(),
|
261
|
+
});
|
262
|
+
}
|
263
|
+
}
|
264
|
+
|
265
|
+
// Add doc type
|
266
|
+
fm_headers.push({
|
267
|
+
id: "type",
|
268
|
+
value: doc_type,
|
269
|
+
});
|
270
|
+
|
271
|
+
const metadata = {};
|
272
|
+
|
273
|
+
// Remove the first <h1>title</h1> from the HTML as we'll add that in the document header
|
274
|
+
let html_h1 = h1_pattern.exec(html_txt);
|
275
|
+
if (html_h1?.[0])
|
276
|
+
html_h1 = html_h1[0].replace(/(<h1.*?>)/, "").replace(/(<\/h1>)/, "");
|
277
|
+
|
278
|
+
html_txt = html_txt.replace(h1_pattern, "");
|
279
|
+
|
280
|
+
// Get contributor data from Github, if exists
|
281
|
+
let contribs = [];
|
282
|
+
let last_commit = null;
|
283
|
+
if (
|
284
|
+
hdocbook_config.publicSource &&
|
285
|
+
hdocbook_config.publicSource !== "" &&
|
286
|
+
hdocbook_config.publicSource.includes("github.com/Hornbill-Docs")
|
287
|
+
) {
|
288
|
+
const github_paths = hdoc.get_github_api_path(
|
289
|
+
hdocbook_config.publicSource,
|
290
|
+
file_path.relativePath,
|
291
|
+
);
|
292
|
+
const contributors = hdoc.get_github_contributors(
|
293
|
+
github_paths.api_path,
|
294
|
+
git_token,
|
295
|
+
);
|
296
|
+
|
297
|
+
if (!contributors.success) {
|
298
|
+
console.error(
|
299
|
+
`Error retrieving contributors from Github: ${contributors.error}`,
|
300
|
+
);
|
301
|
+
} else {
|
302
|
+
last_commit = contributors.last_commit_date;
|
303
|
+
metadata.last_commit = contributors.last_commit_date;
|
304
|
+
metadata.contributor_count = contributors.contributor_count;
|
305
|
+
metadata.edit_url = github_paths.edit_path;
|
306
|
+
contribs = contributors.contributors;
|
307
|
+
contributors.editPath = github_paths.edit_path;
|
308
|
+
fm_headers.push({
|
309
|
+
id: "contributor-count",
|
310
|
+
value: contributors.contributor_count,
|
311
|
+
});
|
312
|
+
fm_headers.push({
|
313
|
+
id: "last-commit",
|
314
|
+
value: contributors.last_commit_date,
|
315
|
+
});
|
316
|
+
const target_file = file_path.path.replace(
|
317
|
+
path.extname(file_path.path),
|
318
|
+
"._info.json",
|
319
|
+
);
|
320
|
+
contributors.success = undefined;
|
321
|
+
contributors.error = undefined;
|
322
|
+
contributors.editPath = github_paths.edit_path;
|
323
|
+
}
|
324
|
+
fm_headers.push({
|
325
|
+
id: "edit-path",
|
326
|
+
value: github_paths.edit_path,
|
327
|
+
});
|
328
|
+
}
|
329
|
+
|
330
|
+
if (pdf_enable && !pdf_path_excluded(file_path.relativePath)) {
|
331
|
+
fm_headers.push({
|
332
|
+
id: "pdf-path",
|
333
|
+
value: file_path.relativePath.replace(
|
334
|
+
path.extname(file_path.relativePath),
|
335
|
+
".pdf",
|
336
|
+
),
|
337
|
+
});
|
338
|
+
}
|
339
|
+
|
340
|
+
let fm_header_content = "<!--[[FRONTMATTER\n";
|
341
|
+
if (fm_headers.length > 0) {
|
342
|
+
for (let i = 0; i < fm_headers.length; i++) {
|
343
|
+
fm_header_content += `${fm_headers[i].id}: ${fm_headers[i].value}\n`;
|
344
|
+
}
|
345
|
+
fm_header_content += "]]-->";
|
346
|
+
|
347
|
+
if (existing_fm_headers) {
|
348
|
+
html_txt = html_txt.replace(`<!--${fm_header.fm_header}-->`, "");
|
349
|
+
}
|
350
|
+
}
|
351
|
+
|
352
|
+
let doc_header = "";
|
353
|
+
let pdf_header = "";
|
354
|
+
const inline_content = file_path.relativePath.startsWith(
|
355
|
+
`${hdocbook_config.docId}/_inline/`,
|
356
|
+
);
|
357
|
+
if (hdocbook_config.publicSource?.includes("github.com/Hornbill-Docs")) {
|
358
|
+
// Build doc header from template and frontmatter tags
|
359
|
+
if (!inline_content)
|
360
|
+
doc_header = process_doc_header(
|
361
|
+
fm_headers,
|
362
|
+
file_path.relativePath,
|
363
|
+
doc_header_template,
|
364
|
+
html_h1,
|
365
|
+
);
|
366
|
+
|
367
|
+
if (pdf_enable && !pdf_path_excluded(file_path.relativePath))
|
368
|
+
pdf_header = process_doc_header(
|
369
|
+
fm_headers,
|
370
|
+
file_path.relativePath,
|
371
|
+
pdf_header_template,
|
372
|
+
html_h1,
|
373
|
+
);
|
374
|
+
} else {
|
375
|
+
if (!inline_content)
|
376
|
+
doc_header = process_doc_header(
|
377
|
+
fm_headers,
|
378
|
+
file_path.relativePath,
|
379
|
+
doc_header_template_non_git,
|
380
|
+
html_h1,
|
381
|
+
);
|
382
|
+
|
383
|
+
if (pdf_enable && !pdf_path_excluded(file_path.relativePath))
|
384
|
+
pdf_header = process_doc_header(
|
385
|
+
fm_headers,
|
386
|
+
file_path.relativePath,
|
387
|
+
pdf_header_template_non_git,
|
388
|
+
html_h1,
|
389
|
+
);
|
390
|
+
}
|
391
|
+
|
392
|
+
let pdf_size = 0;
|
393
|
+
if (pdf_enable && !pdf_path_excluded(file_path.relativePath)) {
|
394
|
+
let pdf_txt = await hdoc_build_pdf.process_images(file_path, html_txt);
|
395
|
+
pdf_txt = `${pdf_header}\n${pdf_txt}`;
|
396
|
+
|
397
|
+
// Generate PDF file from HTML
|
398
|
+
const pdf_file_path = file_path.path.replace(
|
399
|
+
path.extname(file_path.path),
|
400
|
+
".pdf",
|
401
|
+
);
|
402
|
+
pdf_size = await hdoc_build_pdf.generate_pdf(
|
403
|
+
browser,
|
404
|
+
pdf_template_path,
|
405
|
+
pdf_template,
|
406
|
+
hdocbook_config,
|
407
|
+
pdf_txt,
|
408
|
+
pdf_file_path,
|
409
|
+
css_templates,
|
410
|
+
verbose,
|
411
|
+
);
|
412
|
+
}
|
413
|
+
if (pdf_size > 0) pdf_created++;
|
414
|
+
|
415
|
+
// Wrap h2 and h3 tags, plus content, in id'd divs
|
416
|
+
html_txt = hdoc.wrapHContent(html_txt);
|
417
|
+
|
418
|
+
if (inline_content) html_txt = `${fm_header_content}\n${html_txt}`;
|
419
|
+
else html_txt = `${fm_header_content}\n${doc_header}\n${html_txt}`;
|
420
|
+
|
421
|
+
let relative_path = file_path.relativePath;
|
422
|
+
if (
|
423
|
+
!bc[relative_path.replace(".html", "")] &&
|
424
|
+
bc[relative_path.replace("/index.html", "")]
|
425
|
+
) {
|
426
|
+
relative_path = relative_path.replace("/index.html", "");
|
427
|
+
}
|
428
|
+
|
429
|
+
const index_data = hdoc_index.transform_html_for_index(html_txt);
|
430
|
+
|
431
|
+
for (const section of index_data.sections) {
|
432
|
+
index_records.push({
|
433
|
+
relative_path: relative_path,
|
434
|
+
index_html: {
|
435
|
+
fm_props: index_data.fm_props,
|
436
|
+
text: section.text,
|
437
|
+
preview: section.preview,
|
438
|
+
id: section.id ? section.id : null,
|
439
|
+
},
|
440
|
+
metadata: metadata,
|
441
|
+
contributors: contribs,
|
442
|
+
pdf_size: pdf_size,
|
443
|
+
md5: file_path.hash,
|
444
|
+
lastmod: last_commit !== null ? last_commit : file_path.hb_lastmod,
|
445
|
+
inline: inline_content,
|
446
|
+
});
|
447
|
+
}
|
448
|
+
|
449
|
+
// Save HTML into HTML file
|
450
|
+
try {
|
451
|
+
fs.writeFileSync(file_path.path, html_txt);
|
452
|
+
} catch (err) {
|
453
|
+
console.error("Error writing:", target_file, "\n", err);
|
454
|
+
}
|
455
|
+
}
|
456
|
+
};
|
457
|
+
|
458
|
+
const transform_markdown_and_save_html = async (file_path) => {
|
459
|
+
conversion_attempted++;
|
460
|
+
|
461
|
+
if (fs.existsSync(file_path.path)) {
|
462
|
+
// Load markdown file
|
463
|
+
let md_txt = hdoc.expand_variables(
|
464
|
+
fs.readFileSync(file_path.path, "utf8"),
|
465
|
+
);
|
466
|
+
|
467
|
+
// Pull in external includes
|
468
|
+
const includes_processed = await hdoc.process_includes(
|
469
|
+
file_path.path,
|
470
|
+
md_txt,
|
471
|
+
global_source_path,
|
472
|
+
);
|
473
|
+
md_txt = includes_processed.body.toString();
|
474
|
+
includes_found += includes_processed.found;
|
475
|
+
includes_success += includes_processed.success;
|
476
|
+
includes_failed += includes_processed.failed;
|
477
|
+
if (includes_processed.errors.length > 0) {
|
478
|
+
for (let i = 0; i < includes_processed.errors.length; i++) {
|
479
|
+
console.error(includes_processed.errors[i]);
|
480
|
+
}
|
481
|
+
}
|
482
|
+
|
483
|
+
// One markdown parser per file. Seems wrong, but doesn't work with a global one once past the first md file
|
484
|
+
// Steve - revisit this
|
485
|
+
const md = require("markdown-it")({
|
486
|
+
html: true,
|
487
|
+
linkify: true,
|
488
|
+
typographer: true,
|
489
|
+
});
|
490
|
+
md.linkify.set({
|
491
|
+
fuzzyEmail: false,
|
492
|
+
fuzzyLink: false,
|
493
|
+
fuzzyIP: false,
|
494
|
+
});
|
495
|
+
|
496
|
+
// Process Frontmatter tags
|
497
|
+
let frontmatter_content = "";
|
498
|
+
md.use(mdfm, (fm) => {
|
499
|
+
frontmatter_content = fm;
|
500
|
+
});
|
501
|
+
|
502
|
+
// Process tips
|
503
|
+
const tips = require(`${__dirname}/custom_modules/tips.js`);
|
504
|
+
md.use(tips, {
|
505
|
+
links: true,
|
506
|
+
});
|
507
|
+
|
508
|
+
// Tidy up ```json and ```xml code tags
|
509
|
+
|
510
|
+
if (md_txt.includes("```json") || md_txt.includes("```xml"))
|
511
|
+
md_txt = tidy_code_tags(md_txt, file_path.relativePath);
|
512
|
+
|
513
|
+
// Render markdown into HTML
|
514
|
+
let html_txt = md.render(md_txt);
|
515
|
+
|
516
|
+
// Prepare frontmatter headers
|
517
|
+
const fm_headers = [];
|
518
|
+
const fm_content = frontmatter_content.split(/\r?\n/);
|
519
|
+
|
520
|
+
let fm_contains_title = false;
|
521
|
+
let fm_contains_reading_time = false;
|
522
|
+
let fm_contains_description = false;
|
523
|
+
let doc_title = "";
|
524
|
+
let doc_type = "Article";
|
525
|
+
|
526
|
+
if (fm_content.length >= 0) {
|
527
|
+
for (fm_prop of fm_content) {
|
528
|
+
const fm_id = fm_prop.slice(0, fm_prop.indexOf(":"));
|
529
|
+
const fm_val = fm_prop.slice(fm_prop.indexOf(":") + 1);
|
530
|
+
|
531
|
+
if (
|
532
|
+
fm_id &&
|
533
|
+
fm_id.trim().length > 0 &&
|
534
|
+
fm_val &&
|
535
|
+
fm_val.trim().length > 0
|
536
|
+
) {
|
537
|
+
fm_headers.push({
|
538
|
+
id: fm_id.trim(),
|
539
|
+
value: fm_val.trim(),
|
540
|
+
});
|
541
|
+
|
542
|
+
if (fm_id.trim() === "title") {
|
543
|
+
fm_contains_title = true;
|
544
|
+
doc_title = fm_val.trim();
|
545
|
+
}
|
546
|
+
if (fm_id.trim() === "type") {
|
547
|
+
doc_type = fm_val.trim();
|
548
|
+
}
|
549
|
+
if (fm_id.trim() === "reading-time") {
|
550
|
+
book_read_time += Number.parseInt(fm_val.trim(), 10);
|
551
|
+
fm_contains_reading_time = true;
|
552
|
+
}
|
553
|
+
if (fm_id.trim() === "description") {
|
554
|
+
fm_contains_description = true;
|
555
|
+
}
|
556
|
+
}
|
557
|
+
}
|
558
|
+
}
|
559
|
+
|
560
|
+
// Add doc type
|
561
|
+
fm_headers.push({
|
562
|
+
id: "type",
|
563
|
+
value: doc_type,
|
564
|
+
});
|
565
|
+
|
566
|
+
// Does frontmatter tag contain a title property
|
567
|
+
if (!fm_contains_title) {
|
568
|
+
// Frontmatter tags don't contain a title property - go pull the first one from the html heading tags
|
569
|
+
const html_heading = hdoc.getFirstHTMLHeading(
|
570
|
+
html_txt,
|
571
|
+
h_tags_to_search,
|
572
|
+
);
|
573
|
+
|
574
|
+
if (html_heading?.[0]?.children?.[0]?.data) {
|
575
|
+
// We've found a heading tag, add that as a title to the frontmatter content
|
576
|
+
fm_headers.push({
|
577
|
+
id: "title",
|
578
|
+
value: html_heading[0].children[0].data.trim(),
|
579
|
+
});
|
580
|
+
doc_title = html_heading[0].children[0].data.trim();
|
581
|
+
} else if (
|
582
|
+
file_path.name !== "description_ext.md" &&
|
583
|
+
file_path.name !== "article_ext.md"
|
584
|
+
) {
|
585
|
+
// No header tag, no frontmatter title, output a warning
|
586
|
+
console.info(
|
587
|
+
`[WARNING] No frontmatter title property, or h1, h2 or h3 header tags detected in ${file_path.path}`,
|
588
|
+
);
|
589
|
+
}
|
590
|
+
}
|
591
|
+
|
592
|
+
// Does frontmatter contain a description header, generate one if not
|
593
|
+
if (!fm_contains_description) {
|
594
|
+
const html_p_tag = hdoc.getFirstHTMLHeading(html_txt, ["p"]);
|
595
|
+
if (html_p_tag?.[0]?.children?.[0]?.data) {
|
596
|
+
fm_headers.push({
|
597
|
+
id: "description",
|
598
|
+
value:
|
599
|
+
`${doc_title}: ${html_p_tag[0].children[0].data.split(".")[0]}.`.trim(),
|
600
|
+
});
|
601
|
+
}
|
602
|
+
}
|
603
|
+
|
604
|
+
// Does frontmatter tag contain a reading-time property
|
605
|
+
if (!fm_contains_reading_time) {
|
606
|
+
const read_time_mins = hdoc.get_html_read_time(html_txt);
|
607
|
+
book_read_time += read_time_mins;
|
608
|
+
fm_headers.push({
|
609
|
+
id: "reading-time",
|
610
|
+
value: read_time_mins,
|
611
|
+
});
|
612
|
+
}
|
613
|
+
const metadata = {};
|
614
|
+
|
615
|
+
// Remove the first <h1>title</h1> from the HTML as we'll add that in the document header
|
616
|
+
let html_h1 = h1_pattern.exec(html_txt);
|
617
|
+
if (html_h1?.[0])
|
618
|
+
html_h1 = html_h1[0].replace(/(<h1.*?>)/, "").replace(/(<\/h1>)/, "");
|
619
|
+
|
620
|
+
html_txt = html_txt.replace(h1_pattern, "");
|
621
|
+
|
622
|
+
// Get contributor data from Github, if exists
|
623
|
+
let contribs = [];
|
624
|
+
let last_commit = null;
|
625
|
+
if (
|
626
|
+
hdocbook_config.publicSource &&
|
627
|
+
hdocbook_config.publicSource !== "" &&
|
628
|
+
hdocbook_config.publicSource.includes("github.com/Hornbill-Docs")
|
629
|
+
) {
|
630
|
+
const github_paths = hdoc.get_github_api_path(
|
631
|
+
hdocbook_config.publicSource,
|
632
|
+
file_path.relativePath,
|
633
|
+
);
|
634
|
+
const contributors = await hdoc.get_github_contributors(
|
635
|
+
github_paths.api_path,
|
636
|
+
git_token,
|
637
|
+
hdocbook_config.publicSource,
|
638
|
+
);
|
639
|
+
|
640
|
+
if (!contributors.success) {
|
641
|
+
console.error(
|
642
|
+
`Error retrieving contributors from Github: ${contributors.error}`,
|
643
|
+
);
|
644
|
+
} else {
|
645
|
+
last_commit = contributors.last_commit_date;
|
646
|
+
metadata.last_commit = contributors.last_commit_date;
|
647
|
+
metadata.contributor_count = contributors.contributor_count;
|
648
|
+
metadata.edit_url = github_paths.edit_path;
|
649
|
+
contribs = contributors.contributors;
|
650
|
+
contributors.editPath = github_paths.edit_path;
|
651
|
+
|
652
|
+
fm_headers.push({
|
653
|
+
id: "contributor-count",
|
654
|
+
value: contributors.contributor_count,
|
655
|
+
});
|
656
|
+
fm_headers.push({
|
657
|
+
id: "last-commit",
|
658
|
+
value: contributors.last_commit_date,
|
659
|
+
});
|
660
|
+
const target_file = file_path.path.replace(
|
661
|
+
path.extname(file_path.path),
|
662
|
+
"._info.json",
|
663
|
+
);
|
664
|
+
contributors.success = undefined;
|
665
|
+
contributors.error = undefined;
|
666
|
+
contributors.editPath = github_paths.edit_path;
|
667
|
+
try {
|
668
|
+
fs.writeFileSync(
|
669
|
+
target_file,
|
670
|
+
JSON.stringify(contributors, null, 2),
|
671
|
+
);
|
672
|
+
} catch (err) {
|
673
|
+
console.error("Error writing:", target_file, "\n", err);
|
674
|
+
}
|
675
|
+
}
|
676
|
+
fm_headers.push({
|
677
|
+
id: "edit-path",
|
678
|
+
value: github_paths.edit_path,
|
679
|
+
});
|
680
|
+
}
|
681
|
+
|
682
|
+
if (pdf_enable && !pdf_path_excluded(file_path.relativePath)) {
|
683
|
+
fm_headers.push({
|
684
|
+
id: "pdf-path",
|
685
|
+
value: file_path.relativePath.replace(
|
686
|
+
path.extname(file_path.relativePath),
|
687
|
+
".pdf",
|
688
|
+
),
|
689
|
+
});
|
690
|
+
}
|
691
|
+
|
692
|
+
// Add frontmatter tags as comment
|
693
|
+
let fm_header = "<!--[[FRONTMATTER\n";
|
694
|
+
if (fm_headers.length > 0) {
|
695
|
+
for (let i = 0; i < fm_headers.length; i++) {
|
696
|
+
fm_header += `${fm_headers[i].id}: ${fm_headers[i].value}\n`;
|
697
|
+
}
|
698
|
+
}
|
699
|
+
fm_header += "]]-->";
|
700
|
+
|
701
|
+
let doc_header = "";
|
702
|
+
let pdf_header = "";
|
703
|
+
const inline_content = file_path.relativePath.startsWith(
|
704
|
+
`${hdocbook_config.docId}/_inline/`,
|
705
|
+
);
|
706
|
+
if (hdocbook_config.publicSource?.includes("github.com/Hornbill-Docs")) {
|
707
|
+
// Build doc header from template and frontmatter tags
|
708
|
+
if (!inline_content)
|
709
|
+
doc_header = process_doc_header(
|
710
|
+
fm_headers,
|
711
|
+
file_path.relativePath,
|
712
|
+
doc_header_template,
|
713
|
+
html_h1,
|
714
|
+
);
|
715
|
+
|
716
|
+
if (pdf_enable && !pdf_path_excluded(file_path.relativePath))
|
717
|
+
pdf_header = process_doc_header(
|
718
|
+
fm_headers,
|
719
|
+
file_path.relativePath,
|
720
|
+
pdf_header_template,
|
721
|
+
html_h1,
|
722
|
+
);
|
723
|
+
} else {
|
724
|
+
// Build doc header from template and frontmatter tags
|
725
|
+
if (!inline_content)
|
726
|
+
doc_header = process_doc_header(
|
727
|
+
fm_headers,
|
728
|
+
file_path.relativePath,
|
729
|
+
doc_header_template_non_git,
|
730
|
+
html_h1,
|
731
|
+
);
|
732
|
+
|
733
|
+
if (pdf_enable && !pdf_path_excluded(file_path.relativePath))
|
734
|
+
pdf_header = process_doc_header(
|
735
|
+
fm_headers,
|
736
|
+
file_path.relativePath,
|
737
|
+
pdf_header_template_non_git,
|
738
|
+
html_h1,
|
739
|
+
);
|
740
|
+
}
|
741
|
+
|
742
|
+
let pdf_size = 0;
|
743
|
+
if (pdf_enable && !pdf_path_excluded(file_path.relativePath)) {
|
744
|
+
let pdf_txt = await hdoc_build_pdf.process_images(file_path, html_txt);
|
745
|
+
pdf_txt = `${pdf_header}\n${pdf_txt}`;
|
746
|
+
|
747
|
+
// Generate PDF file from HTML
|
748
|
+
const pdf_file_path = file_path.path.replace(
|
749
|
+
path.extname(file_path.path),
|
750
|
+
".pdf",
|
751
|
+
);
|
752
|
+
pdf_size = await hdoc_build_pdf.generate_pdf(
|
753
|
+
browser,
|
754
|
+
pdf_template_path,
|
755
|
+
pdf_template,
|
756
|
+
hdocbook_config,
|
757
|
+
pdf_txt,
|
758
|
+
pdf_file_path,
|
759
|
+
css_templates,
|
760
|
+
verbose,
|
761
|
+
);
|
762
|
+
}
|
763
|
+
if (pdf_size > 0) pdf_created++;
|
764
|
+
|
765
|
+
// Wrap h2 and h3 tags, plus content, in id'd divs
|
766
|
+
html_txt = hdoc.wrapHContent(html_txt);
|
767
|
+
|
768
|
+
if (inline_content) html_txt = `${fm_header}\n${html_txt}`;
|
769
|
+
else html_txt = `${fm_header}\n${doc_header}\n${html_txt}`;
|
770
|
+
|
771
|
+
// Save HTML into HTML file
|
772
|
+
const target_file = file_path.path.replace(
|
773
|
+
path.extname(file_path.path),
|
774
|
+
".html",
|
775
|
+
);
|
776
|
+
let relative_path = file_path.relativePath.replace(
|
777
|
+
path.extname(file_path.path),
|
778
|
+
".html",
|
779
|
+
);
|
780
|
+
try {
|
781
|
+
fs.writeFileSync(target_file, html_txt);
|
782
|
+
} catch (err) {
|
783
|
+
console.error("Error writing:", target_file, "\n", err);
|
784
|
+
}
|
785
|
+
|
786
|
+
if (
|
787
|
+
!bc[relative_path.replace(".html", "")] &&
|
788
|
+
bc[relative_path.replace("/index.html", "")]
|
789
|
+
) {
|
790
|
+
relative_path = relative_path.replace("/index.html", "");
|
791
|
+
}
|
792
|
+
|
793
|
+
const index_data = hdoc_index.transform_html_for_index(html_txt);
|
794
|
+
|
795
|
+
for (section of index_data.sections) {
|
796
|
+
index_records.push({
|
797
|
+
relative_path: relative_path,
|
798
|
+
index_html: {
|
799
|
+
fm_props: index_data.fm_props,
|
800
|
+
text: section.text,
|
801
|
+
preview: section.preview,
|
802
|
+
id: section.id ? section.id : null,
|
803
|
+
},
|
804
|
+
metadata: metadata,
|
805
|
+
contributors: contribs,
|
806
|
+
pdf_size: pdf_size,
|
807
|
+
md5: file_path.hash,
|
808
|
+
lastmod: last_commit !== null ? last_commit : file_path.hb_lastmod,
|
809
|
+
inline: inline_content,
|
810
|
+
});
|
811
|
+
}
|
812
|
+
|
813
|
+
// Add MD file to delete queue
|
814
|
+
md_files_delete.push(file_path.path);
|
815
|
+
|
816
|
+
conversion_success++;
|
817
|
+
return true;
|
818
|
+
}
|
819
|
+
conversion_failed++;
|
820
|
+
console.error("MD file does not exist:", file_path.path);
|
821
|
+
return false;
|
822
|
+
};
|
823
|
+
|
824
|
+
const tidy_code_tags = (markdown, file) => {
|
825
|
+
let clean_markdown = markdown;
|
826
|
+
const json_to_tidy = clean_markdown.match(/```json[\r\n](\s|.)*?```/g);
|
827
|
+
if (json_to_tidy && json_to_tidy.length > 0) {
|
828
|
+
for (let i = 0; i < json_to_tidy.length; i++) {
|
829
|
+
if (json_to_tidy[i] !== "") {
|
830
|
+
let json_tidy = json_to_tidy[i]
|
831
|
+
.replace("```json", "")
|
832
|
+
.replace("```", "");
|
833
|
+
try {
|
834
|
+
json_tidy = JSON.stringify(JSON.parse(json_tidy), null, 2);
|
835
|
+
} catch (e) {
|
836
|
+
console.info(
|
837
|
+
`[WARNING] Could not tidy JSON in file [${file}]: ${e}`,
|
838
|
+
);
|
839
|
+
}
|
840
|
+
clean_markdown = clean_markdown.replace(
|
841
|
+
json_to_tidy[i],
|
842
|
+
`\`\`\`json\n${json_tidy}\n\`\`\``,
|
843
|
+
);
|
844
|
+
}
|
845
|
+
}
|
846
|
+
}
|
847
|
+
|
848
|
+
const xml_to_tidy = clean_markdown.match(/```xml[\r\n](\s|.)*?```/g);
|
849
|
+
if (xml_to_tidy && xml_to_tidy.length > 0) {
|
850
|
+
for (let i = 0; i < xml_to_tidy.length; i++) {
|
851
|
+
if (xml_to_tidy[i] !== "") {
|
852
|
+
const xml_tidy = xml_to_tidy[i]
|
853
|
+
.replace("```xml", "")
|
854
|
+
.replace("```", "");
|
855
|
+
let new_xml_string = xml_tidy;
|
856
|
+
try {
|
857
|
+
new_xml_string = xmlFormat(xml_tidy, {
|
858
|
+
indentation: " ",
|
859
|
+
collapseContent: true,
|
860
|
+
lineSeparator: "\n",
|
861
|
+
});
|
862
|
+
} catch (e) {
|
863
|
+
console.info(
|
864
|
+
`[WARNING] Could not tidy XML in file [${file}]: ${e}`,
|
865
|
+
);
|
866
|
+
}
|
867
|
+
clean_markdown = clean_markdown.replace(
|
868
|
+
xml_to_tidy[i],
|
869
|
+
`\`\`\`xml\n${new_xml_string}\n\`\`\``,
|
870
|
+
);
|
871
|
+
}
|
872
|
+
}
|
873
|
+
}
|
874
|
+
return clean_markdown;
|
875
|
+
};
|
876
|
+
|
877
|
+
const process_doc_header = (fm_headers, doc_path, template, h1) => {
|
878
|
+
let wip_doc_header = template;
|
879
|
+
let used_h1 = false;
|
880
|
+
if (h1 && h1 !== "") {
|
881
|
+
wip_doc_header = wip_doc_header.replaceAll("{{title}}", h1);
|
882
|
+
used_h1 = true;
|
883
|
+
}
|
884
|
+
// Process fm_headers properties first
|
885
|
+
for (let i = 0; i < fm_headers.length; i++) {
|
886
|
+
switch (fm_headers[i].id) {
|
887
|
+
case "title":
|
888
|
+
if (!used_h1)
|
889
|
+
wip_doc_header = wip_doc_header.replaceAll(
|
890
|
+
"{{title}}",
|
891
|
+
fm_headers[i].value,
|
892
|
+
);
|
893
|
+
break;
|
894
|
+
case "reading-time":
|
895
|
+
wip_doc_header = wip_doc_header.replaceAll(
|
896
|
+
"{{reading-time}}",
|
897
|
+
fm_headers[i].value,
|
898
|
+
);
|
899
|
+
break;
|
900
|
+
case "contributor-count":
|
901
|
+
wip_doc_header = wip_doc_header.replaceAll(
|
902
|
+
"{{contributor-count}}",
|
903
|
+
fm_headers[i].value,
|
904
|
+
);
|
905
|
+
break;
|
906
|
+
case "type":
|
907
|
+
wip_doc_header = wip_doc_header.replaceAll(
|
908
|
+
"{{doc-type}}",
|
909
|
+
fm_headers[i].value,
|
910
|
+
);
|
911
|
+
break;
|
912
|
+
case "edit-path":
|
913
|
+
wip_doc_header = wip_doc_header.replaceAll(
|
914
|
+
"{{edit-url}}",
|
915
|
+
fm_headers[i].value,
|
916
|
+
);
|
917
|
+
break;
|
918
|
+
case "last-commit": {
|
919
|
+
let last_commit_date = fm_headers[i].value;
|
920
|
+
if (last_commit_date !== "No Commit Date Available") {
|
921
|
+
last_commit_date = new Date(fm_headers[i].value).toDateString();
|
922
|
+
}
|
923
|
+
wip_doc_header = wip_doc_header.replaceAll(
|
924
|
+
"{{last-update}}",
|
925
|
+
last_commit_date,
|
926
|
+
);
|
927
|
+
break;
|
928
|
+
}
|
929
|
+
default:
|
930
|
+
break;
|
931
|
+
}
|
932
|
+
}
|
933
|
+
|
934
|
+
// Now sort out breadcrumbs
|
935
|
+
const logical_path = doc_path.replace(path.extname(doc_path), "");
|
936
|
+
const bc_for_path = bc[logical_path];
|
937
|
+
let bc_tags = "\n";
|
938
|
+
if (bc_for_path) {
|
939
|
+
for (let i = 0; i < bc_for_path.length - 1; i++) {
|
940
|
+
let bc_link = "/";
|
941
|
+
if (redirects[bc_for_path[i].link]) {
|
942
|
+
if (redirects[bc_for_path[i].link].location) {
|
943
|
+
bc_link += redirects[bc_for_path[i].link].location;
|
944
|
+
}
|
945
|
+
} else {
|
946
|
+
if (bc_for_path[i].link) {
|
947
|
+
bc_link = bc_for_path[i].link.startsWith("/")
|
948
|
+
? bc_for_path[i].link
|
949
|
+
: `/${bc_for_path[i].link}`;
|
950
|
+
} else {
|
951
|
+
bc_link = "";
|
952
|
+
}
|
953
|
+
}
|
954
|
+
if (bc_link !== "") {
|
955
|
+
bc_tags += `\t\t\t\t<li class="mt-0 nav-bar-item"><a href="${bc_link}" class="ps-0 pe-0 text-decoration-none">${bc_for_path[i].text}</a></li>\n`;
|
956
|
+
} else {
|
957
|
+
bc_tags += `\t\t\t\t<li class="mt-0 nav-bar-item">${bc_for_path[i].text}</li>\n`;
|
958
|
+
}
|
959
|
+
}
|
960
|
+
} else {
|
961
|
+
if (verbose) {
|
962
|
+
console.info(
|
963
|
+
`[WARNING] Path is not present in navigation items: ${logical_path}`,
|
964
|
+
);
|
965
|
+
}
|
966
|
+
}
|
967
|
+
bc_tags += "\t\t\t";
|
968
|
+
wip_doc_header = wip_doc_header.replaceAll("{{breadcrumbs}}", bc_tags);
|
969
|
+
return wip_doc_header;
|
970
|
+
};
|
971
|
+
|
972
|
+
// File callback for build scan
|
973
|
+
const build_file_callback = (element) => {
|
974
|
+
if (element.extension === "md") {
|
975
|
+
element.hb_source_path = path.join(
|
976
|
+
global_source_path,
|
977
|
+
element.relativePath,
|
978
|
+
);
|
979
|
+
const fstats = fs.statSync(element.hb_source_path);
|
980
|
+
element.hb_lastmod = `${fstats.mtime.toISOString().slice(0, 19)}Z`;
|
981
|
+
md_files.push(element);
|
982
|
+
} else {
|
983
|
+
// File is html, see if there's a matching md file and if there is then ignore the html
|
984
|
+
const md_path = element.path.replace(path.extname(element.path), ".md");
|
985
|
+
if (fs.existsSync(md_path)) {
|
986
|
+
return;
|
987
|
+
}
|
988
|
+
element.hb_source_path = path.join(
|
989
|
+
global_source_path,
|
990
|
+
element.relativePath,
|
991
|
+
);
|
992
|
+
const fstats = fs.statSync(element.hb_source_path);
|
993
|
+
element.hb_lastmod = `${fstats.mtime.toISOString().slice(0, 19)}Z`;
|
994
|
+
static_html_files.push(element);
|
995
|
+
}
|
996
|
+
};
|
997
|
+
|
998
|
+
// File & folder callback for MD5 hash of built content
|
999
|
+
const hash_callback = (element) => {
|
1000
|
+
if (element.extension !== "db") {
|
1001
|
+
built_file_hashes.push({
|
1002
|
+
path: element.relativePath,
|
1003
|
+
hash: element.hash,
|
1004
|
+
});
|
1005
|
+
}
|
1006
|
+
};
|
1007
|
+
|
1008
|
+
// File scan callback for filename validation
|
1009
|
+
const filename_validation_callback = (element) => {
|
1010
|
+
if (element.relativePath.startsWith("_inline/")) return;
|
1011
|
+
if (element.name.toLowerCase() === ".ds_store") return;
|
1012
|
+
if (
|
1013
|
+
element.name === "article_ext.md" ||
|
1014
|
+
element.name === "description_ext.md"
|
1015
|
+
)
|
1016
|
+
return;
|
1017
|
+
if (image_extensions.includes(element.extension)) return;
|
1018
|
+
const file_no_ext = element.name.replace(`.${element.extension}`, "");
|
1019
|
+
if (!file_no_ext.match(regex_filename))
|
1020
|
+
errors_filename.push(element.relativePath);
|
1021
|
+
};
|
1022
|
+
|
1023
|
+
const dreeOptions = {
|
1024
|
+
hash: true,
|
1025
|
+
extensions: ["md", "html", "htm"],
|
1026
|
+
normalize: true,
|
1027
|
+
stat: true,
|
1028
|
+
};
|
1029
|
+
|
1030
|
+
const dreeOptionsAllFiles = {
|
1031
|
+
descendants: true,
|
1032
|
+
excludeEmptyDirectories: true,
|
1033
|
+
hash: false,
|
1034
|
+
normalize: true,
|
1035
|
+
size: false,
|
1036
|
+
sizeInBytes: false,
|
1037
|
+
symbolicLinks: false,
|
1038
|
+
};
|
1039
|
+
|
1040
|
+
const md5DreeOptions = {
|
1041
|
+
hash: true,
|
1042
|
+
normalize: true,
|
1043
|
+
sorted: true,
|
1044
|
+
};
|
1045
|
+
|
1046
|
+
exports.run = async (
|
1047
|
+
source_path,
|
1048
|
+
verbose_output,
|
1049
|
+
github_api_token,
|
1050
|
+
validate,
|
1051
|
+
gen_exclude,
|
1052
|
+
build_version = "",
|
1053
|
+
) => {
|
1054
|
+
if (github_api_token !== "") {
|
1055
|
+
git_token = github_api_token;
|
1056
|
+
}
|
1057
|
+
global_source_path = source_path;
|
1058
|
+
verbose = verbose_output;
|
1059
|
+
|
1060
|
+
const start_time = Date.now();
|
1061
|
+
// GERRY: The purpose of this function is to create a zip file containing the hdocbook content,
|
1062
|
+
// * Create a _work folder
|
1063
|
+
// * copy the hdocbook content to the work folder
|
1064
|
+
// * Render all markdown into side-by-side HTML file
|
1065
|
+
// * Replace SERVER_VARS embedded in documents with the right version information etc.
|
1066
|
+
// * Build an index (sqlite FTS5) by extracting text from all HTML content in the work
|
1067
|
+
// folder, conceptually we are making a little mini website crawler to index all of the content
|
1068
|
+
// within the book.
|
1069
|
+
// * Package everything up into a ZIP file, ready for the build controller to package and publish
|
1070
|
+
|
1071
|
+
console.log("Hornbill HDocBook Build", "\n");
|
1072
|
+
console.log(" Document Path:", source_path, "\n");
|
1073
|
+
const build_start_dt = new Date().toLocaleString();
|
1074
|
+
|
1075
|
+
// Load the hdocbook-project.json file to get the docId
|
1076
|
+
// use the docId to get the book config
|
1077
|
+
const hdocbook_project_config_path = path.join(
|
1078
|
+
source_path,
|
1079
|
+
"hdocbook-project.json",
|
1080
|
+
);
|
1081
|
+
try {
|
1082
|
+
hdocbook_project = require(hdocbook_project_config_path);
|
1083
|
+
} catch (e) {
|
1084
|
+
console.error("File not found: hdocbook-project.json\n");
|
1085
|
+
console.error(
|
1086
|
+
"hdoc build/validate needs to be run in the root of a HDoc Book.\n",
|
1087
|
+
);
|
1088
|
+
process.exit(1);
|
1089
|
+
}
|
1090
|
+
doc_id = hdocbook_project.docId;
|
1091
|
+
|
1092
|
+
if (
|
1093
|
+
!validate &&
|
1094
|
+
hdocbook_project.pdfGeneration !== undefined &&
|
1095
|
+
hdocbook_project.pdfGeneration.enable !== undefined
|
1096
|
+
) {
|
1097
|
+
pdf_enable = hdocbook_project.pdfGeneration.enable;
|
1098
|
+
}
|
1099
|
+
|
1100
|
+
if (
|
1101
|
+
hdocbook_project.redirects &&
|
1102
|
+
Array.isArray(hdocbook_project.redirects)
|
1103
|
+
) {
|
1104
|
+
for (let i = 0; i < hdocbook_project.redirects.length; i++) {
|
1105
|
+
const redirect_key =
|
1106
|
+
hdocbook_project.redirects[i].url.indexOf("/") === 0
|
1107
|
+
? hdocbook_project.redirects[i].url.substring(1)
|
1108
|
+
: hdocbook_project.redirects[i].url;
|
1109
|
+
redirects[redirect_key] = hdocbook_project.redirects[i];
|
1110
|
+
}
|
1111
|
+
}
|
1112
|
+
|
1113
|
+
console.log("Loading hdocbook config...");
|
1114
|
+
|
1115
|
+
const book_path = path.join(source_path, doc_id);
|
1116
|
+
const hdocbook_path = path.join(book_path, "hdocbook.json");
|
1117
|
+
const work_path = path.join(source_path, "_work");
|
1118
|
+
const work_hdocbook_path = path.join(work_path, doc_id, "hdocbook.json");
|
1119
|
+
|
1120
|
+
hdocbook_config = require(hdocbook_path);
|
1121
|
+
if (build_version !== "") {
|
1122
|
+
if (build_version.match(regex_version)) {
|
1123
|
+
hdocbook_config.version = build_version;
|
1124
|
+
} else {
|
1125
|
+
console.info(
|
1126
|
+
`\n[WARNING] Argument build version [${build_version}] does not match expected pattern, defaulting to version specified in book [${hdocbook_config.version}]\n`,
|
1127
|
+
);
|
1128
|
+
}
|
1129
|
+
}
|
1130
|
+
|
1131
|
+
if (!hdocbook_config.version.match(regex_version)) {
|
1132
|
+
console.error(
|
1133
|
+
`ERROR: Version number does not match required format - ${hdocbook_config.version}\n`,
|
1134
|
+
);
|
1135
|
+
process.exit(1);
|
1136
|
+
}
|
1137
|
+
|
1138
|
+
if (hdocbook_config.publicSource?.endsWith(".git"))
|
1139
|
+
hdocbook_config.publicSource = hdocbook_config.publicSource.substring(
|
1140
|
+
0,
|
1141
|
+
hdocbook_config.publicSource.length - 4,
|
1142
|
+
);
|
1143
|
+
|
1144
|
+
console.log("Loading product families...");
|
1145
|
+
const prods = await hdoc.load_product_families();
|
1146
|
+
if (!prods.success) {
|
1147
|
+
console.error(`${prods.errors}\n`);
|
1148
|
+
process.exit(1);
|
1149
|
+
} else {
|
1150
|
+
prod_families = prods.prod_families;
|
1151
|
+
prods_supported = prods.prods_supported;
|
1152
|
+
}
|
1153
|
+
|
1154
|
+
if (!validate) {
|
1155
|
+
console.log("Caching CSS for PDF generation...");
|
1156
|
+
const css_files = [
|
1157
|
+
path.join(pdf_template_path, "css", "custom-block.css"),
|
1158
|
+
path.join(pdf_template_path, "css", "hdocs-pdf.css"),
|
1159
|
+
path.join(pdf_template_path, "css", "vars.css"),
|
1160
|
+
path.join(
|
1161
|
+
ui_css_path,
|
1162
|
+
"theme-default",
|
1163
|
+
"styles",
|
1164
|
+
"components",
|
1165
|
+
"api-doc.css",
|
1166
|
+
),
|
1167
|
+
];
|
1168
|
+
for (let i = 0; i < css_files.length; i++) {
|
1169
|
+
try {
|
1170
|
+
css_templates.push(fs.readFileSync(css_files[i], "utf8"));
|
1171
|
+
} catch (e) {
|
1172
|
+
console.error(`Error reading file[${css_files[i]}]: ${e}`);
|
1173
|
+
}
|
1174
|
+
}
|
1175
|
+
}
|
1176
|
+
|
1177
|
+
// Validate all filenames first
|
1178
|
+
console.log("Validating book filenames meet kebab-case requirements...");
|
1179
|
+
dree.scan(book_path, dreeOptionsAllFiles, filename_validation_callback);
|
1180
|
+
if (errors_filename.length > 0) {
|
1181
|
+
console.log("\r\n-----------------------");
|
1182
|
+
console.log(" Validation Output ");
|
1183
|
+
console.log("-----------------------");
|
1184
|
+
console.error(
|
1185
|
+
`${errors_filename.length} files do not meet filename requirements:`,
|
1186
|
+
);
|
1187
|
+
console.error(` - ${errors_filename.join("\n - ")}`);
|
1188
|
+
console.log();
|
1189
|
+
process.exit(1);
|
1190
|
+
}
|
1191
|
+
|
1192
|
+
console.log(`Building: ${doc_id} v${hdocbook_config.version}...\n`);
|
1193
|
+
|
1194
|
+
// Make _work folder to copy everything into
|
1195
|
+
work_path_content = path.join(work_path, doc_id);
|
1196
|
+
if (fs.existsSync(work_path)) {
|
1197
|
+
fs.rmSync(work_path, {
|
1198
|
+
recursive: true,
|
1199
|
+
force: true,
|
1200
|
+
});
|
1201
|
+
}
|
1202
|
+
fs.mkdirSync(work_path);
|
1203
|
+
|
1204
|
+
const file_filter = (src) => {
|
1205
|
+
return !src.toLowerCase().endsWith(".ds_store");
|
1206
|
+
};
|
1207
|
+
|
1208
|
+
// Copy files from book into _work-doc_id folder
|
1209
|
+
console.log("Copying content into work folder...");
|
1210
|
+
try {
|
1211
|
+
fs.copySync(path.join(source_path, doc_id), work_path_content, {
|
1212
|
+
filter: file_filter,
|
1213
|
+
});
|
1214
|
+
} catch (e) {
|
1215
|
+
console.error("Error copying from source_path:\n", e);
|
1216
|
+
process.exit(1);
|
1217
|
+
}
|
1218
|
+
|
1219
|
+
// Create MD5 hash of content before build
|
1220
|
+
console.log("Creating Hash...");
|
1221
|
+
|
1222
|
+
dree.scan(work_path_content, md5DreeOptions, hash_callback);
|
1223
|
+
let concat_hash = "|";
|
1224
|
+
for (let i = 0; i < built_file_hashes.length; i++) {
|
1225
|
+
concat_hash += `${built_file_hashes[i].path}:${built_file_hashes[i].hash}|`;
|
1226
|
+
}
|
1227
|
+
if (concat_hash === "|") {
|
1228
|
+
console.error("No hash of content has been returned.");
|
1229
|
+
process.exit(1);
|
1230
|
+
}
|
1231
|
+
|
1232
|
+
// Create hash and write file
|
1233
|
+
const hash = crypto.createHash("md5").update(concat_hash).digest("hex");
|
1234
|
+
const checksum_path = path.join(work_path_content, "checksum.md5");
|
1235
|
+
try {
|
1236
|
+
fs.writeFileSync(checksum_path, hash);
|
1237
|
+
console.log("Hash file creation success:", checksum_path);
|
1238
|
+
} catch (e) {
|
1239
|
+
console.error("\nError creating", checksum_path, ":", e);
|
1240
|
+
process.exit(1);
|
1241
|
+
}
|
1242
|
+
|
1243
|
+
// Load document header templates
|
1244
|
+
console.log("Loading templates...");
|
1245
|
+
try {
|
1246
|
+
doc_header_template = fs.readFileSync(doc_header_template_path, "utf8");
|
1247
|
+
doc_header_template_non_git = fs.readFileSync(
|
1248
|
+
non_git_doc_header_template_path,
|
1249
|
+
"utf8",
|
1250
|
+
);
|
1251
|
+
pdf_header_template = fs.readFileSync(pdf_header_template_path, "utf8");
|
1252
|
+
pdf_header_template_non_git = fs.readFileSync(
|
1253
|
+
non_git_pdf_header_template_path,
|
1254
|
+
"utf8",
|
1255
|
+
);
|
1256
|
+
} catch (err) {
|
1257
|
+
console.error(`Error reading document header template: ${err}`);
|
1258
|
+
process.exit(1);
|
1259
|
+
}
|
1260
|
+
|
1261
|
+
if (pdf_enable) {
|
1262
|
+
// Load PDF templates
|
1263
|
+
try {
|
1264
|
+
pdf_template = fs.readFileSync(pdf_template_file_path, "utf8");
|
1265
|
+
} catch (err) {
|
1266
|
+
console.error(`Error reading PDF template: ${err}`);
|
1267
|
+
process.exit(1);
|
1268
|
+
}
|
1269
|
+
}
|
1270
|
+
console.log("Processing navigation breadcrumbs...");
|
1271
|
+
const bc_build = hdoc.build_breadcrumbs(hdocbook_config.navigation.items);
|
1272
|
+
if (bc_build.errors.length > 0) {
|
1273
|
+
console.log("\r\n-----------------------");
|
1274
|
+
console.log(" Validation Output ");
|
1275
|
+
console.log("-----------------------");
|
1276
|
+
console.log(
|
1277
|
+
`\n${bc_build.errors.length} errors found when processing navigation:\n`,
|
1278
|
+
);
|
1279
|
+
console.error(` - ${bc_build.errors.join("\n\n - ")}`);
|
1280
|
+
console.log("\n");
|
1281
|
+
process.exit(1);
|
1282
|
+
}
|
1283
|
+
bc = bc_build.bc;
|
1284
|
+
console.log("Processing content...");
|
1285
|
+
// Get a list of MD files in work_path
|
1286
|
+
dree.scan(work_path, dreeOptions, build_file_callback);
|
1287
|
+
|
1288
|
+
if (pdf_enable) {
|
1289
|
+
// Create a Chromium browser instance generate PDFs with
|
1290
|
+
browser = await puppeteer.launch({ headless: "shell" });
|
1291
|
+
}
|
1292
|
+
|
1293
|
+
// Work through MD files and convert to HTML
|
1294
|
+
const mdPromiseArray = [];
|
1295
|
+
for (let i = 0; i < md_files.length; i++) {
|
1296
|
+
mdPromiseArray.push(md_files[i]);
|
1297
|
+
}
|
1298
|
+
const chunkSize = 8;
|
1299
|
+
for (let i = 0; i < mdPromiseArray.length; i += chunkSize) {
|
1300
|
+
const chunk = mdPromiseArray.slice(i, i + chunkSize);
|
1301
|
+
// do whatever
|
1302
|
+
await Promise.all(
|
1303
|
+
chunk.map(async (file) => {
|
1304
|
+
await transform_markdown_and_save_html(file);
|
1305
|
+
}),
|
1306
|
+
);
|
1307
|
+
}
|
1308
|
+
|
1309
|
+
// Work through Static HTML files and add Frontmatter tags
|
1310
|
+
const htmlPromiseArray = [];
|
1311
|
+
for (let i = 0; i < static_html_files.length; i++) {
|
1312
|
+
htmlPromiseArray.push(static_html_files[i]);
|
1313
|
+
}
|
1314
|
+
for (let i = 0; i < htmlPromiseArray.length; i += chunkSize) {
|
1315
|
+
const chunk = htmlPromiseArray.slice(i, i + chunkSize);
|
1316
|
+
await Promise.all(
|
1317
|
+
chunk.map(async (file) => {
|
1318
|
+
await transform_static_html(file);
|
1319
|
+
}),
|
1320
|
+
);
|
1321
|
+
}
|
1322
|
+
|
1323
|
+
if (pdf_enable) {
|
1324
|
+
// Close the Chromium browser instance
|
1325
|
+
await browser.close();
|
1326
|
+
}
|
1327
|
+
|
1328
|
+
// Output to console
|
1329
|
+
console.log(`\n MD files found: ${conversion_attempted}`);
|
1330
|
+
console.log(`Successfully converted to HTML: ${conversion_success}`);
|
1331
|
+
if (conversion_failed > 0)
|
1332
|
+
console.error(` Failed to convert: ${conversion_failed}\n`);
|
1333
|
+
else console.log(` Failed to convert: ${conversion_failed}\n`);
|
1334
|
+
console.log(` Includes Found: ${includes_found}`);
|
1335
|
+
console.log(` Includes Success: ${includes_success}`);
|
1336
|
+
if (includes_failed > 0)
|
1337
|
+
console.error(` Includes Failed: ${includes_failed}\n`);
|
1338
|
+
else console.log(` Includes Failed: ${includes_failed}\n`);
|
1339
|
+
console.log(
|
1340
|
+
` Static HTML Files Found: ${static_html_files.length}\n`,
|
1341
|
+
);
|
1342
|
+
if (!validate) {
|
1343
|
+
console.log(` PDF Files Created: ${pdf_created}\n`);
|
1344
|
+
}
|
1345
|
+
|
1346
|
+
// Validate content
|
1347
|
+
const validation_success = await hdoc_validate.run(
|
1348
|
+
work_path,
|
1349
|
+
doc_id,
|
1350
|
+
verbose,
|
1351
|
+
hdocbook_config,
|
1352
|
+
hdocbook_project,
|
1353
|
+
bc,
|
1354
|
+
prod_families,
|
1355
|
+
prods_supported,
|
1356
|
+
gen_exclude,
|
1357
|
+
redirects,
|
1358
|
+
);
|
1359
|
+
if (!validation_success) {
|
1360
|
+
const end_time = Date.now();
|
1361
|
+
console.log(`\nTime Taken: ${get_duration(start_time, end_time)}\n`);
|
1362
|
+
process.exit(1);
|
1363
|
+
}
|
1364
|
+
|
1365
|
+
// Delete markdown files
|
1366
|
+
console.log("Performing Markdown Cleanup");
|
1367
|
+
|
1368
|
+
const filePromiseArray = [];
|
1369
|
+
for (let i = 0; i < md_files_delete.length; i++) {
|
1370
|
+
filePromiseArray.push(md_files_delete[i]);
|
1371
|
+
}
|
1372
|
+
await Promise.all(
|
1373
|
+
filePromiseArray.map(async (file) => {
|
1374
|
+
fs.unlink(file, (err) => {
|
1375
|
+
if (err) console.error(`Error deleting ${file}: ${e}`);
|
1376
|
+
});
|
1377
|
+
}),
|
1378
|
+
);
|
1379
|
+
|
1380
|
+
// Add book read timing to the hdocbook.json
|
1381
|
+
hdocbook_config.readingTime = Math.ceil(
|
1382
|
+
book_read_time + (book_read_time / 100) * 10,
|
1383
|
+
);
|
1384
|
+
hdocbook_config.navigation.items = hdoc.strip_drafts(
|
1385
|
+
hdocbook_config.navigation.items,
|
1386
|
+
);
|
1387
|
+
try {
|
1388
|
+
fs.writeFileSync(
|
1389
|
+
work_hdocbook_path,
|
1390
|
+
JSON.stringify(hdocbook_config, null, 2),
|
1391
|
+
);
|
1392
|
+
console.log("\nhdocbook.json update success:", work_hdocbook_path);
|
1393
|
+
} catch (e) {
|
1394
|
+
console.error("\nError creating", work_hdocbook_path, ":", e);
|
1395
|
+
process.exit(1);
|
1396
|
+
}
|
1397
|
+
|
1398
|
+
// Build the index
|
1399
|
+
// Create the DB and tables
|
1400
|
+
console.log("Building the Index");
|
1401
|
+
const db = hdoc_build_db.create_db(work_path, doc_id);
|
1402
|
+
if (db.error && db.error !== null) {
|
1403
|
+
console.error(db.error);
|
1404
|
+
process.exit(1);
|
1405
|
+
}
|
1406
|
+
// Populate primary index tables
|
1407
|
+
const index = await hdoc_build_db.populate_index(
|
1408
|
+
db.db,
|
1409
|
+
doc_id,
|
1410
|
+
hdocbook_config,
|
1411
|
+
index_records,
|
1412
|
+
verbose,
|
1413
|
+
);
|
1414
|
+
if (!index.success) {
|
1415
|
+
console.error(index.error);
|
1416
|
+
process.exit(1);
|
1417
|
+
}
|
1418
|
+
|
1419
|
+
// Populate redirect index table records
|
1420
|
+
if (
|
1421
|
+
hdocbook_project.redirects &&
|
1422
|
+
Array.isArray(hdocbook_project.redirects) &&
|
1423
|
+
hdocbook_project.redirects.length > 0
|
1424
|
+
) {
|
1425
|
+
const redirects_index = hdoc_build_db.populate_redirects(
|
1426
|
+
db.db,
|
1427
|
+
hdocbook_project.redirects,
|
1428
|
+
verbose,
|
1429
|
+
);
|
1430
|
+
if (!redirects_index.success) {
|
1431
|
+
for (let i = 0; i < index.errors.length; i++) {
|
1432
|
+
console.error(index.errors[i]);
|
1433
|
+
}
|
1434
|
+
process.exit(1);
|
1435
|
+
}
|
1436
|
+
}
|
1437
|
+
|
1438
|
+
if (!validate) {
|
1439
|
+
try {
|
1440
|
+
const zip_path = path.join(work_path, `${doc_id}.zip`);
|
1441
|
+
|
1442
|
+
const output = fs.createWriteStream(zip_path);
|
1443
|
+
const archive = archiver("zip");
|
1444
|
+
archive.on("error", (err) => {
|
1445
|
+
throw err;
|
1446
|
+
});
|
1447
|
+
archive.pipe(output);
|
1448
|
+
|
1449
|
+
// append files from a sub-directory, putting its contents at the root of archive
|
1450
|
+
archive.directory(work_path_content, false);
|
1451
|
+
archive.finalize();
|
1452
|
+
|
1453
|
+
//await zip(work_path_content, zip_path);
|
1454
|
+
console.log(`\nZIP Creation Success: ${zip_path}\n`);
|
1455
|
+
console.log(" Build Started:", build_start_dt);
|
1456
|
+
console.log(`Build Completed: ${new Date().toLocaleString()}\n`);
|
1457
|
+
} catch (e) {
|
1458
|
+
console.error(`\nError creating ZIP: ${e}`);
|
1459
|
+
}
|
1460
|
+
} else {
|
1461
|
+
console.log("\nValidation Complete\n");
|
1462
|
+
}
|
1463
|
+
const end_time = Date.now();
|
1464
|
+
console.log(`Time Taken: ${get_duration(start_time, end_time)}\n`);
|
1465
|
+
};
|
1466
|
+
|
1467
|
+
const get_duration = (start, end) => {
|
1468
|
+
const total_time = new Date(end - start).toISOString().slice(11, 19);
|
1469
|
+
const duration_arr = total_time.split(":");
|
1470
|
+
let duration = "";
|
1471
|
+
if (Number.parseInt(duration_arr[0], 10) > 0) {
|
1472
|
+
duration += `${Number.parseInt(duration_arr[0], 10)}h `;
|
1473
|
+
}
|
1474
|
+
if (duration !== "" || Number.parseInt(duration_arr[1], 10)) {
|
1475
|
+
duration += `${Number.parseInt(duration_arr[1], 10)}m `;
|
1476
|
+
}
|
1477
|
+
duration += `${Number.parseInt(duration_arr[2], 10)}s`;
|
1478
|
+
return duration;
|
1479
|
+
};
|
1480
|
+
})();
|