hdoc-tools 0.19.7 → 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 -1503
- 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/ui/js/doc.hornbill.js
CHANGED
@@ -1,659 +1,708 @@
|
|
1
|
-
//-- DOM/URL EVENTS
|
2
|
-
//-- THIS CONTROLS NAVIGATION
|
3
|
-
//-- loaded in index.html
|
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
|
-
function
|
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
|
-
//-- create items to stick in toc from current loaded content
|
213
|
-
//-- searches for H2,H3
|
214
|
-
function generateTableOfContentsFromDoc() {
|
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
|
-
function
|
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
|
-
function
|
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
|
-
|
1
|
+
//-- DOM/URL EVENTS
|
2
|
+
//-- THIS CONTROLS NAVIGATION
|
3
|
+
//-- loaded in index.html
|
4
|
+
|
5
|
+
let jqContentContainer = null;
|
6
|
+
let jqDocumentHeader = null;
|
7
|
+
let jqLeftNav = null;
|
8
|
+
const global = { stateParams: {}, lastLayoutClass: "" };
|
9
|
+
|
10
|
+
const docAppMethods = {
|
11
|
+
setSessionInfo: function (info) {
|
12
|
+
this.docApp.userSession = info;
|
13
|
+
},
|
14
|
+
|
15
|
+
showInlineDocumentList: function (ev) {
|
16
|
+
if (ev) {
|
17
|
+
ev.stopImmediatePropagation();
|
18
|
+
ev.preventDefault();
|
19
|
+
}
|
20
|
+
this.docApp.showInlineDocumentsMarkup = true;
|
21
|
+
this.$forceUpdate();
|
22
|
+
},
|
23
|
+
popupInlineDocument: function (ev, navSectionItem) {
|
24
|
+
if (ev) {
|
25
|
+
ev.stopImmediatePropagation();
|
26
|
+
ev.preventDefault();
|
27
|
+
}
|
28
|
+
|
29
|
+
$("#inlineModal").modal("show");
|
30
|
+
this.docApp.inlinePopupDocumentHref = navSectionItem.link;
|
31
|
+
},
|
32
|
+
switchViewTheme: () => {
|
33
|
+
if (ThemePreference)
|
34
|
+
document.documentElement.classList.remove(ThemePreference);
|
35
|
+
|
36
|
+
if (ThemePreference === "dark") {
|
37
|
+
ThemePreference = "light";
|
38
|
+
} else {
|
39
|
+
ThemePreference = "dark";
|
40
|
+
}
|
41
|
+
|
42
|
+
localStorage.setItem("hdocbook-theme-appearance", ThemePreference);
|
43
|
+
document.documentElement.classList.add(ThemePreference);
|
44
|
+
},
|
45
|
+
renderNavigation: function () {
|
46
|
+
this.docApp.navSections = this.docApp.book.navigation.items; //-- show be an array of nav groups
|
47
|
+
},
|
48
|
+
toggleMobileMenu: () => {
|
49
|
+
const isOpen = $(".mobile-menu-btn").data("isopen");
|
50
|
+
if (isOpen) {
|
51
|
+
$(".DocSidebar").removeClass("open");
|
52
|
+
} else {
|
53
|
+
$(".DocSidebar").addClass("open");
|
54
|
+
}
|
55
|
+
//-- store new mode
|
56
|
+
$(".mobile-menu-btn").data("isopen", !isOpen);
|
57
|
+
},
|
58
|
+
resetMobileMenu: (ev) => {
|
59
|
+
if (
|
60
|
+
ev &&
|
61
|
+
($(ev.srcElement).hasClass("mobile-menu-btn")[0] ||
|
62
|
+
$(ev.srcElement).closest(".mobile-menu-btn")[0])
|
63
|
+
) {
|
64
|
+
//-- skp as have clikc no menu btn
|
65
|
+
} else {
|
66
|
+
$(".mobile-menu-btn").data("isopen", false);
|
67
|
+
$(".DocSidebar").removeClass("open");
|
68
|
+
}
|
69
|
+
},
|
70
|
+
};
|
71
|
+
|
72
|
+
//--
|
73
|
+
//-- user clicked back or forwards
|
74
|
+
window.addEventListener("popstate", (event) => {
|
75
|
+
const loadUrl = new URL(event.target.location.href);
|
76
|
+
loadContentUrl(loadUrl.pathname + loadUrl.hash, {}, false, true);
|
77
|
+
});
|
78
|
+
|
79
|
+
//--- GLOBAL FUNCTIONS
|
80
|
+
function removeTrailingSlash(str) {
|
81
|
+
return str.endsWith("/") ? str.slice(0, -1) : str;
|
82
|
+
}
|
83
|
+
function removeStartingSlash(str) {
|
84
|
+
return str.startsWith("/") ? str.slice(1, str.length) : str;
|
85
|
+
|
86
|
+
//if(linkRef.indexOf("/")===0)linkRef = linkRef.replace("/","");
|
87
|
+
}
|
88
|
+
|
89
|
+
function toSeoUrl(url) {
|
90
|
+
return (
|
91
|
+
url
|
92
|
+
.toString() // Convert to string
|
93
|
+
.normalize("NFD") // Change diacritics
|
94
|
+
// biome-ignore lint/suspicious/noMisleadingCharacterClass: Ignoring this as it's required
|
95
|
+
.replace(/[\u0300-\u036f]/g, "") // Remove illegal characters
|
96
|
+
.replace(/\s+/g, "-") // Change whitespace to dashes
|
97
|
+
.toLowerCase() // Change to lowercase
|
98
|
+
.replace(/&/g, "-and-") // Replace ampersand
|
99
|
+
.replace(/[^a-z0-9\-]/g, "") // Remove anything that is not a letter, number or dash
|
100
|
+
.replace(/-+/g, "-") // Remove duplicate dashes
|
101
|
+
.replace(/^-*/, "") // Remove starting dashes
|
102
|
+
.replace(/-*$/, "")
|
103
|
+
); // Remove trailing dashes
|
104
|
+
}
|
105
|
+
|
106
|
+
function listenForHrefClicks() {
|
107
|
+
//-- trap all link click events - we want to handle links so can cancel and load content ourselves
|
108
|
+
$("A")
|
109
|
+
.off("click")
|
110
|
+
.on("click", function (ev) {
|
111
|
+
if (this.href) {
|
112
|
+
const checkUrl = new URL(this.href);
|
113
|
+
|
114
|
+
view.resetMobileMenu();
|
115
|
+
|
116
|
+
//-- clicking on a hash tag header link element - so jsut scroll to element
|
117
|
+
if (`${checkUrl.origin}/` === siteBaseLocation) {
|
118
|
+
//-- if a url that is part of this doc site then handle loading content inline else let link do whatever (i.e. its an external link)
|
119
|
+
ev.stopImmediatePropagation();
|
120
|
+
ev.preventDefault();
|
121
|
+
|
122
|
+
//-- do we need to scroll into view element on this page
|
123
|
+
if (
|
124
|
+
checkUrl.hash &&
|
125
|
+
getAnchorFromHash(checkUrl.hash, "faq-toc-item")
|
126
|
+
) {
|
127
|
+
const eleAnc = getAnchorFromHash(checkUrl.hash, "faq-toc-item");
|
128
|
+
if (eleAnc[0]?.scrollIntoView) eleAnc[0].scrollIntoView();
|
129
|
+
|
130
|
+
if (checkUrl.pathname === "/") {
|
131
|
+
//-- going to element on current page so just update current browser url with new #
|
132
|
+
const currUrl = new URL(document.location.href);
|
133
|
+
currUrl.hash = checkUrl.hash;
|
134
|
+
if (currUrl.href !== document.location.href)
|
135
|
+
window.history.pushState(null, null, currUrl); //-- user has clicked a link so we want to add state to history so we can click back
|
136
|
+
} else if (ele.href !== document.location.href) {
|
137
|
+
window.history.pushState(null, null, this.href); //-- user has clicked a link so we want to add state to history so we can click back
|
138
|
+
}
|
139
|
+
} else {
|
140
|
+
loadContentUrl(this.getAttribute("href"), false, false);
|
141
|
+
}
|
142
|
+
return false;
|
143
|
+
}
|
144
|
+
//-- if not part of this website then always open in new tab as considered an external site
|
145
|
+
this.setAttribute("target", "_blank");
|
146
|
+
}
|
147
|
+
});
|
148
|
+
}
|
149
|
+
|
150
|
+
//-- return t/f is the element is actually visible on the screen
|
151
|
+
function elementIsOnVisibleScreen(oEle) {
|
152
|
+
const item = oEle.getBoundingClientRect();
|
153
|
+
return (
|
154
|
+
item.top >= 0 &&
|
155
|
+
item.left >= 0 &&
|
156
|
+
item.bottom <=
|
157
|
+
(window.innerHeight || document.documentElement.clientHeight) &&
|
158
|
+
item.right <= (window.innerWidth || document.documentElement.clientWidth)
|
159
|
+
);
|
160
|
+
}
|
161
|
+
|
162
|
+
//-- based on content url highlight match navigation menu item
|
163
|
+
function highlightNavigationLinkFromUrl(matchLinkHref) {
|
164
|
+
const clean_matchLinkHref = removeStartingSlash(matchLinkHref).split("#")[0]; //-- remvoe # link
|
165
|
+
$("a.DocLink").removeClass("active");
|
166
|
+
|
167
|
+
const arrItems = document.querySelectorAll("a.DocLink");
|
168
|
+
|
169
|
+
for (let x = 0; x < arrItems.length; x++) {
|
170
|
+
const el = arrItems[x];
|
171
|
+
let checkUrl = null;
|
172
|
+
try {
|
173
|
+
checkUrl = new URL(el.href);
|
174
|
+
} catch (e) {
|
175
|
+
//hslDocLog.log("BAD navigation menu item found",el);
|
176
|
+
}
|
177
|
+
|
178
|
+
if (checkUrl) {
|
179
|
+
const testCurrPath = removeStartingSlash(checkUrl.pathname);
|
180
|
+
if (
|
181
|
+
testCurrPath === clean_matchLinkHref ||
|
182
|
+
testCurrPath.indexOf(clean_matchLinkHref) === 0 ||
|
183
|
+
clean_matchLinkHref.indexOf(
|
184
|
+
`${removeStartingSlash(checkUrl.pathname)}/`,
|
185
|
+
) === 0
|
186
|
+
) {
|
187
|
+
//-- exact match
|
188
|
+
$(el).addClass("active");
|
189
|
+
if (!elementIsOnVisibleScreen(el)) el.scrollIntoView();
|
190
|
+
return false; //break out
|
191
|
+
}
|
192
|
+
}
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
function getAnchorFromHash(strHash, strHasClass) {
|
197
|
+
try {
|
198
|
+
let strSelector = toSeoUrl(strHash.replace("#", ""));
|
199
|
+
if (strHasClass) strSelector += `.${strHasClass}`;
|
200
|
+
|
201
|
+
const jqEle = $(`#${strSelector}`);
|
202
|
+
if (jqEle[0]) {
|
203
|
+
return jqEle;
|
204
|
+
}
|
205
|
+
return null;
|
206
|
+
} catch (e) {
|
207
|
+
hslDocLog.log(`Get document anchor element by hash failed [${strHash}]`, e);
|
208
|
+
return null;
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
//-- create items to stick in toc from current loaded content
|
213
|
+
//-- searches for H2,H3
|
214
|
+
function generateTableOfContentsFromDoc() {
|
215
|
+
const container = jqContentContainer[0];
|
216
|
+
if (container) {
|
217
|
+
const currUrl = new URL(document.location.href);
|
218
|
+
view.docApp.tableOfContents = [];
|
219
|
+
for (let i = 2; i <= 3; i++) {
|
220
|
+
const headers = container.getElementsByTagName(`h${i}`);
|
221
|
+
for (let j = 0; j < headers.length; j++) {
|
222
|
+
const jqCurrHeader = $(headers[j]);
|
223
|
+
//-- only process headers that do not have this class
|
224
|
+
if (!jqCurrHeader.hasClass("no-auto-anchor"))
|
225
|
+
jqCurrHeader.addClass("faq-toc-item");
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
const headersTocItem = container.getElementsByClassName("faq-toc-item");
|
230
|
+
for (let k = 0; k < headersTocItem.length; k++) {
|
231
|
+
const item = headersTocItem[k];
|
232
|
+
const strLabel = $.trim(item.innerText);
|
233
|
+
if (strLabel) {
|
234
|
+
const seoSafeId = toSeoUrl(strLabel); //-- will use SEO to set in url so can scroll to element from url
|
235
|
+
const linkUrl = `${currUrl.pathname}#${seoSafeId}`;
|
236
|
+
item.id = seoSafeId;
|
237
|
+
|
238
|
+
view.docApp.tableOfContents.push({
|
239
|
+
ele: item,
|
240
|
+
eleText: strLabel,
|
241
|
+
tagName: item.tagName,
|
242
|
+
href: linkUrl,
|
243
|
+
});
|
244
|
+
|
245
|
+
//-- add link icon to header (using seo id)
|
246
|
+
$(item).append(
|
247
|
+
"<a class='header-anchor'><i class='bi bi-link'></i></a>",
|
248
|
+
);
|
249
|
+
$(item).find("a").attr("href", linkUrl);
|
250
|
+
}
|
251
|
+
}
|
252
|
+
}
|
253
|
+
}
|
254
|
+
|
255
|
+
function loadContentUrl(
|
256
|
+
linkRef,
|
257
|
+
fromPageRefresh,
|
258
|
+
fromPopState,
|
259
|
+
fromBook = true,
|
260
|
+
) {
|
261
|
+
//-- clear table of contents
|
262
|
+
view.docApp.tableOfContents = [];
|
263
|
+
let clean_linkRef = linkRef;
|
264
|
+
if (clean_linkRef.indexOf(`${window.location.origin}/`) === 0) {
|
265
|
+
clean_linkRef = clean_linkRef.replace(`${window.location.origin}/`, "");
|
266
|
+
}
|
267
|
+
|
268
|
+
//-- remove trailing / if has one
|
269
|
+
clean_linkRef = removeTrailingSlash(clean_linkRef);
|
270
|
+
//-- remove starting / if link starts with it
|
271
|
+
clean_linkRef = removeStartingSlash(clean_linkRef);
|
272
|
+
|
273
|
+
//-- update url in browser
|
274
|
+
if (fromBook)
|
275
|
+
setBrowserViewUrl(clean_linkRef, {}, fromPageRefresh, fromPopState);
|
276
|
+
//-- destroy any existing content children and events properly
|
277
|
+
jqContentContainer.empty();
|
278
|
+
jqDocumentHeader.find(".document-title").empty();
|
279
|
+
|
280
|
+
//-- for now just load whatever the href prop is (we can add actions to perform specific processing and then load content based on element atts etc)
|
281
|
+
let frontmatterData = {};
|
282
|
+
let booksLinkRef = clean_linkRef;
|
283
|
+
if (fromBook) {
|
284
|
+
booksLinkRef = clean_linkRef.includes("_books/")
|
285
|
+
? clean_linkRef
|
286
|
+
: `_books/${clean_linkRef}`;
|
287
|
+
}
|
288
|
+
fetch(booksLinkRef)
|
289
|
+
.then((response) => {
|
290
|
+
if (response.headers.has("X-frontmatter")) {
|
291
|
+
frontmatterData = response.headers.get("X-frontmatter");
|
292
|
+
frontmatterData = JSON.parse(atob(frontmatterData));
|
293
|
+
}
|
294
|
+
return response.text();
|
295
|
+
})
|
296
|
+
.then((html) => {
|
297
|
+
jqContentContainer.html(html);
|
298
|
+
|
299
|
+
//-- remove previous layoutclass if have one
|
300
|
+
if (global.lastLayoutClass) {
|
301
|
+
$("#DocContent").removeClass(global.lastLayoutClass);
|
302
|
+
global.lastLayoutClass = "";
|
303
|
+
}
|
304
|
+
|
305
|
+
//-- if have layoutclass add it to content container - this is so we can specify table list view sizes etc
|
306
|
+
if (frontmatterData.layout) {
|
307
|
+
$("#DocContent").addClass(frontmatterData.layout);
|
308
|
+
global.lastLayoutClass = frontmatterData.layout;
|
309
|
+
}
|
310
|
+
|
311
|
+
//--generate toc for all layouts that have h2/h3
|
312
|
+
view.docApp.keepTocLayout = frontmatterData.layout === "article-no-toc";
|
313
|
+
if (
|
314
|
+
!frontmatterData.layout ||
|
315
|
+
frontmatterData.layout === "article" ||
|
316
|
+
frontmatterData.layout === "article-toc"
|
317
|
+
) {
|
318
|
+
view.docApp.keepTocLayout = true;
|
319
|
+
generateTableOfContentsFromDoc();
|
320
|
+
}
|
321
|
+
|
322
|
+
//-- find any <tabs> and andd a bootstrap tab item strip
|
323
|
+
$("#DocContent")
|
324
|
+
.find("tabs")
|
325
|
+
.each((idx, el) => {
|
326
|
+
const tabClass = el.getAttribute("tabstyle");
|
327
|
+
let tabMarkup = "<ul class='nav nav-tabs'>";
|
328
|
+
//-- for each tab we need to create a tab link
|
329
|
+
$(el)
|
330
|
+
.find("tab")
|
331
|
+
.each((idx, aTab) => {
|
332
|
+
const activeClass = idx === 0 ? " active" : "";
|
333
|
+
tabMarkup += `<li class='nav-item c-pointer' contentidx='${idx}'><span class='nav-link${activeClass}'>${aTab.getAttribute("name")}</span></li>`;
|
334
|
+
|
335
|
+
//-- hide the tab element if it is not the active one (first)
|
336
|
+
if (idx > 0) $(aTab).addClass("d-none");
|
337
|
+
});
|
338
|
+
|
339
|
+
tabMarkup += "</ul>";
|
340
|
+
//-- inject markup
|
341
|
+
$(el).prepend(tabMarkup).find(".nav.nav-tabs").addClass(tabClass);
|
342
|
+
|
343
|
+
//-- add event handler for switching tab items
|
344
|
+
$(el)
|
345
|
+
.find("li")
|
346
|
+
.off("click")
|
347
|
+
.on("click", function () {
|
348
|
+
const contentIdx = this.getAttribute("contentidx");
|
349
|
+
const tabsContainer = $(this).closest("tabs").eq(0);
|
350
|
+
const tabs = tabsContainer.find("tab");
|
351
|
+
|
352
|
+
//-- hide other tab content and show this tabs content
|
353
|
+
tabs.addClass("d-none");
|
354
|
+
tabs.eq(contentIdx - 0).removeClass("d-none");
|
355
|
+
|
356
|
+
//-- set clicked tab item to active
|
357
|
+
tabsContainer.find(".nav-link").removeClass("active");
|
358
|
+
$(this).find(".nav-link").addClass("active");
|
359
|
+
});
|
360
|
+
});
|
361
|
+
|
362
|
+
//-- do any code highlighting
|
363
|
+
if (hljs) {
|
364
|
+
for (const el of document.querySelectorAll("pre code")) {
|
365
|
+
hljs.highlightBlock(el);
|
366
|
+
}
|
367
|
+
} else {
|
368
|
+
hslDocLog.log(
|
369
|
+
"code highlighting js could not be loaded. code block highlighting will not be enabled",
|
370
|
+
);
|
371
|
+
}
|
372
|
+
|
373
|
+
//-- show copy button by any code blocks
|
374
|
+
const options = {
|
375
|
+
contentSelector: ".injected-document-content",
|
376
|
+
// Delay in ms used for `setTimeout` before badging is applied
|
377
|
+
// Use if you need to time highlighting and badge application
|
378
|
+
// since the badges need to be applied afterwards.
|
379
|
+
// 0 - direct execution (ie. you handle timing
|
380
|
+
loadDelay: 0,
|
381
|
+
|
382
|
+
// CSS class(es) used to render the copy icon.
|
383
|
+
copyIconClass: "bi bi-clipboard",
|
384
|
+
// CSS class(es) used to render the done icon.
|
385
|
+
checkIconClass: "bi bi-clipboard-check --htl-c-brand",
|
386
|
+
|
387
|
+
// intercept text copying - passed in text return text out
|
388
|
+
onBeforeCodeCopied: (text) => text,
|
389
|
+
};
|
390
|
+
|
391
|
+
highlightJsBadge(options);
|
392
|
+
|
393
|
+
//-- get first H1 and put it into our header section header
|
394
|
+
const docHeader = jqContentContainer.find("H1").eq(0);
|
395
|
+
jqDocumentHeader.find(".document-title").append(docHeader);
|
396
|
+
|
397
|
+
setGitHubBookUrl(clean_linkRef);
|
398
|
+
|
399
|
+
//-- make sure selected link parents are set to .expand=true
|
400
|
+
if (expandNavParentSectionBySelectedLinkHref(clean_linkRef)) {
|
401
|
+
view.updateCounter++;
|
402
|
+
view.$nextTick(() => {
|
403
|
+
//-- find any navigation links that match url and highlight
|
404
|
+
// listenForHrefClicks();
|
405
|
+
highlightNavigationLinkFromUrl(clean_linkRef);
|
406
|
+
|
407
|
+
//-- scroll to element that match hash (if have one)
|
408
|
+
if (document.location.hash) {
|
409
|
+
const gotoEle = getAnchorFromHash(document.location.hash);
|
410
|
+
if (gotoEle) gotoEle[0].scrollIntoView();
|
411
|
+
}
|
412
|
+
});
|
413
|
+
view.$forceUpdate();
|
414
|
+
}
|
415
|
+
|
416
|
+
listenForHrefClicks();
|
417
|
+
});
|
418
|
+
}
|
419
|
+
|
420
|
+
function setGitHubBookUrl(linkRef) {
|
421
|
+
let bookRef = linkRef.split(siteBaseLocation);
|
422
|
+
bookRef = bookRef[1] ? bookRef[1] : bookRef[0];
|
423
|
+
const bookId = bookRef.split("/")[0];
|
424
|
+
view.docApp.documentGithubUrl = `https://github.com/Hornbill-Docs/${bookId}/blob/main/${bookRef}.md`;
|
425
|
+
//--https://github.com/Hornbill-Docs/hdoc-guide/blob/main/hdoc-guide/overview.md
|
426
|
+
}
|
427
|
+
|
428
|
+
function loadBookDefaultLink() {
|
429
|
+
$(".DocLink.link").first().click();
|
430
|
+
}
|
431
|
+
|
432
|
+
function findFirstClickableBookLink(findByLinkRef, currentNavSection) {
|
433
|
+
let currNav = currentNavSection;
|
434
|
+
if (currNav === undefined) currNav = view.docApp.navSections;
|
435
|
+
|
436
|
+
for (let x = 0; x < currNav.length; x++) {
|
437
|
+
if (currNav[x].items) {
|
438
|
+
const clickableItem = findFirstClickableBookLink(
|
439
|
+
findByLinkRef,
|
440
|
+
currNav[x].items,
|
441
|
+
);
|
442
|
+
if (clickableItem) {
|
443
|
+
return clickableItem;
|
444
|
+
}
|
445
|
+
} else if (currNav[x].link) {
|
446
|
+
if (findByLinkRef) {
|
447
|
+
if (
|
448
|
+
removeStartingSlash(removeTrailingSlash(currNav[x].link)) ===
|
449
|
+
findByLinkRef
|
450
|
+
)
|
451
|
+
return currNav[x].link;
|
452
|
+
} else {
|
453
|
+
return currNav[x].link;
|
454
|
+
}
|
455
|
+
}
|
456
|
+
}
|
457
|
+
}
|
458
|
+
|
459
|
+
function expandNavParentSectionBySelectedLinkHref(
|
460
|
+
findByLinkRef,
|
461
|
+
currentNavSection,
|
462
|
+
) {
|
463
|
+
let currNav = currentNavSection;
|
464
|
+
if (currNav === undefined) {
|
465
|
+
view.docApp.bookBreadCrumb = []; //-- reset bread crumb
|
466
|
+
currNav = view.docApp.navSections;
|
467
|
+
}
|
468
|
+
|
469
|
+
for (let x = 0; x < currNav.length; x++) {
|
470
|
+
if (currNav[x].items) {
|
471
|
+
const res = expandNavParentSectionBySelectedLinkHref(
|
472
|
+
findByLinkRef.split("#")[0],
|
473
|
+
currNav[x].items,
|
474
|
+
);
|
475
|
+
if (res) {
|
476
|
+
currNav[x].expand = true;
|
477
|
+
view.docApp.bookBreadCrumb.unshift({
|
478
|
+
title: currNav[x].text,
|
479
|
+
link: currNav[x].items[0].link,
|
480
|
+
});
|
481
|
+
return res;
|
482
|
+
}
|
483
|
+
} else {
|
484
|
+
//-- check item to see if it matches url
|
485
|
+
if (
|
486
|
+
removeStartingSlash(removeTrailingSlash(currNav[x].link)) ===
|
487
|
+
findByLinkRef.split("#")[0]
|
488
|
+
) {
|
489
|
+
return true;
|
490
|
+
}
|
491
|
+
}
|
492
|
+
}
|
493
|
+
}
|
494
|
+
|
495
|
+
function old_expandNavParentSectionBySelectedLinkHref(
|
496
|
+
findByLinkRef,
|
497
|
+
currentNavSection,
|
498
|
+
) {
|
499
|
+
let currNav = currentNavSection;
|
500
|
+
if (currNav === undefined) currNav = view.docApp.navSections;
|
501
|
+
|
502
|
+
for (let x = 0; x < currNav.length; x++) {
|
503
|
+
if (currNav[x].items) {
|
504
|
+
const res = expandNavParentSectionBySelectedLinkHref(
|
505
|
+
findByLinkRef.split("#")[0],
|
506
|
+
currNav[x].items,
|
507
|
+
);
|
508
|
+
if (res) {
|
509
|
+
currNav[x].expand = true;
|
510
|
+
return res;
|
511
|
+
}
|
512
|
+
} else {
|
513
|
+
//-- check item to see if it matches url
|
514
|
+
if (
|
515
|
+
removeStartingSlash(removeTrailingSlash(currNav[x].link)) ===
|
516
|
+
findByLinkRef.split("#")[0]
|
517
|
+
) {
|
518
|
+
return true;
|
519
|
+
}
|
520
|
+
}
|
521
|
+
}
|
522
|
+
}
|
523
|
+
|
524
|
+
let lastUrlDynamicallySet = "";
|
525
|
+
function setBrowserViewUrl(
|
526
|
+
strHrefToLoad,
|
527
|
+
viewData,
|
528
|
+
fromPageRefresh,
|
529
|
+
fromPopState,
|
530
|
+
) {
|
531
|
+
const urlToSet = `${window.location.origin}/${strHrefToLoad}`;
|
532
|
+
const url = new URL(urlToSet);
|
533
|
+
|
534
|
+
//-- remove any old params
|
535
|
+
for (const strKey in global.stateParams) {
|
536
|
+
url.searchParams.delete(strKey);
|
537
|
+
}
|
538
|
+
|
539
|
+
//-- now set new data params in url
|
540
|
+
for (const strKey in viewData) {
|
541
|
+
url.searchParams.set(strKey, viewData[strKey]);
|
542
|
+
}
|
543
|
+
|
544
|
+
//-- store global params
|
545
|
+
global.stateParams = viewData;
|
546
|
+
|
547
|
+
if (!fromPageRefresh) {
|
548
|
+
if (fromPopState) {
|
549
|
+
//-- so user has clicked on a link - always add entry
|
550
|
+
window.history.pushState(null, null, url); //-- add entry
|
551
|
+
} else {
|
552
|
+
if (lastUrlDynamicallySet) {
|
553
|
+
if (lastUrlDynamicallySet !== strHrefToLoad) {
|
554
|
+
window.history.pushState(null, null, url); //-- add entry
|
555
|
+
} else {
|
556
|
+
window.history.replaceState(null, null, url); //-- user has refreshed page or jsut visited page
|
557
|
+
}
|
558
|
+
} else {
|
559
|
+
window.history.replaceState(null, null, url); //-- user has clicked a link so we want to add state to history so we can click back
|
560
|
+
}
|
561
|
+
}
|
562
|
+
}
|
563
|
+
lastUrlDynamicallySet = strHrefToLoad;
|
564
|
+
}
|
565
|
+
|
566
|
+
async function fetchContentFile(strFilePath) {
|
567
|
+
return await fetch(strFilePath)
|
568
|
+
.then((response) => response.text())
|
569
|
+
.then((fileContent) => {
|
570
|
+
return fileContent;
|
571
|
+
});
|
572
|
+
}
|
573
|
+
|
574
|
+
async function fetchJsonFile(strFilePath) {
|
575
|
+
return await fetch(strFilePath)
|
576
|
+
.then((response) => response.json())
|
577
|
+
.then((jsonObject) => {
|
578
|
+
return jsonObject;
|
579
|
+
});
|
580
|
+
}
|
581
|
+
|
582
|
+
//-- THE INIT APP CALLED FROM index.html
|
583
|
+
//$(".document-body").attr("v-pre", "");
|
584
|
+
|
585
|
+
const view = new Vue({
|
586
|
+
el: "#vDocDevApp",
|
587
|
+
data: {
|
588
|
+
userSession: {},
|
589
|
+
updateCounter: 0,
|
590
|
+
bookId: "",
|
591
|
+
docApp: {
|
592
|
+
error: "",
|
593
|
+
inlinePopupDocumentHref: "",
|
594
|
+
showInlineDocumentsMarkup: false,
|
595
|
+
keepTocLayout: false,
|
596
|
+
book: {},
|
597
|
+
navSections: [],
|
598
|
+
inlineDocumentItems: [],
|
599
|
+
tableOfContents: [],
|
600
|
+
bookBreadCrumb: [],
|
601
|
+
},
|
602
|
+
},
|
603
|
+
methods: docAppMethods,
|
604
|
+
directives: {
|
605
|
+
somedirectivename: {
|
606
|
+
bind(el, binding, vnode) {
|
607
|
+
//-- do something when created on element
|
608
|
+
},
|
609
|
+
},
|
610
|
+
},
|
611
|
+
mounted: () => {},
|
612
|
+
});
|
613
|
+
|
614
|
+
//-- repeatable conmponent for nav sections
|
615
|
+
Vue.component("nav-section-component", {
|
616
|
+
props: ["asection"],
|
617
|
+
template: "#nav-section-template",
|
618
|
+
methods: {
|
619
|
+
toggleNavCollapse: function (navSection) {
|
620
|
+
navSection.expand = !navSection.expand;
|
621
|
+
this.$forceUpdate();
|
622
|
+
},
|
623
|
+
},
|
624
|
+
});
|
625
|
+
|
626
|
+
const hslDocLog = {
|
627
|
+
_entry: [],
|
628
|
+
log: function (strMessage, varData) {
|
629
|
+
if (varData !== undefined) console.log(strMessage, varData);
|
630
|
+
else console.log(strMessage);
|
631
|
+
|
632
|
+
this._entry.push({ msg: strMessage, data: varData });
|
633
|
+
},
|
634
|
+
dump: function () {
|
635
|
+
for (let x = 0; x < this._entry.length; x++) {
|
636
|
+
console.log(this._entry[x].msg, this._entry[x].data || null);
|
637
|
+
}
|
638
|
+
},
|
639
|
+
};
|
640
|
+
|
641
|
+
async function intialiseApp() {
|
642
|
+
// set theme switch
|
643
|
+
$(".theme-switch-checkbox").prop("checked", ThemePreference === "dark");
|
644
|
+
|
645
|
+
jqDocumentHeader = $(".injected-document-content .document-header");
|
646
|
+
jqContentContainer = $(".injected-document-content .document-body");
|
647
|
+
//jqContentContainer = $(".injected-document-content");
|
648
|
+
jqLeftNav = $("#DocSidebarNav");
|
649
|
+
|
650
|
+
await fetchJsonFile("_books/library.json")
|
651
|
+
.then((data) => {
|
652
|
+
// Get docbook library list
|
653
|
+
view.docApp.library = data;
|
654
|
+
view.docId = view.docApp.library.books[0].docId;
|
655
|
+
})
|
656
|
+
.then(() => {
|
657
|
+
// Get hdocbook.json
|
658
|
+
fetchJsonFile(`_books/${view.docId}/hdocbook.json`)
|
659
|
+
.then((data) => {
|
660
|
+
view.docApp.book = data;
|
661
|
+
view.bookId = data.docId;
|
662
|
+
view.docApp.title = data.title || "";
|
663
|
+
view.docApp.description = data.description || "";
|
664
|
+
|
665
|
+
view.docApp.inlineDocumentItems = [];
|
666
|
+
view.docApp.inlinePopupDocumentHref = "";
|
667
|
+
view.docApp.showInlineDocumentsMarkup = false;
|
668
|
+
view.docApp.hasInlinePopupDocuments =
|
669
|
+
!!view.docApp.library.books[0].nav_inline?.items?.length;
|
670
|
+
if (view.docApp.hasInlinePopupDocuments) {
|
671
|
+
view.docApp.inlineDocumentItems =
|
672
|
+
view.docApp.library.books[0].nav_inline.items;
|
673
|
+
view.docApp.book.navigation.items.push(
|
674
|
+
view.docApp.library.books[0].nav_inline,
|
675
|
+
);
|
676
|
+
}
|
677
|
+
|
678
|
+
//-- now render out the nav menu
|
679
|
+
view.renderNavigation();
|
680
|
+
|
681
|
+
setTimeout(() => {
|
682
|
+
listenForHrefClicks();
|
683
|
+
|
684
|
+
//-- check if url is not root - in which case we need to load content for url
|
685
|
+
let initialLoadContentHref = window.location.href.replace(
|
686
|
+
`${window.location.origin}/`,
|
687
|
+
"",
|
688
|
+
);
|
689
|
+
initialLoadContentHref = findFirstClickableBookLink(
|
690
|
+
initialLoadContentHref,
|
691
|
+
);
|
692
|
+
|
693
|
+
if (initialLoadContentHref) {
|
694
|
+
//-- find the link we are going to show and make sure parent/s are set to .expand=true
|
695
|
+
loadContentUrl(initialLoadContentHref, true, false);
|
696
|
+
} else {
|
697
|
+
hslDocLog.log("initial first view link to load is not present");
|
698
|
+
}
|
699
|
+
|
700
|
+
$(".hb-hidden").removeClass("hb-hidden");
|
701
|
+
}, 200);
|
702
|
+
})
|
703
|
+
.catch((data) => {
|
704
|
+
view.docApp.error = data;
|
705
|
+
$(".hb-hidden").removeClass("hb-hidden");
|
706
|
+
});
|
707
|
+
});
|
708
|
+
}
|