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