hdoc-tools 0.9.53 → 0.9.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/hdoc-build.js CHANGED
@@ -203,11 +203,7 @@
203
203
  delete contributors.success;
204
204
  delete contributors.error;
205
205
  contributors.editPath = github_paths.edit_path;
206
- try {
207
- fs.writeFileSync(target_file, JSON.stringify(contributors, null, 2));
208
- } catch (err) {
209
- console.log('Error writing:', target_file, '\n', err);
210
- }
206
+
211
207
  }
212
208
  fm_headers.push({
213
209
  id: 'edit-path',
@@ -229,7 +225,7 @@
229
225
 
230
226
  let doc_header = '';
231
227
  let pdf_header = '';
232
- if (hdocbook_config.publicSource.includes('github.com/Hornbill-Docs')) {
228
+ if (hdocbook_config.publicSource && hdocbook_config.publicSource.includes('github.com/Hornbill-Docs')) {
233
229
  // Build doc header from template and frontmatter tags
234
230
  doc_header = process_doc_header(fm_headers, file_path.relativePath, doc_header_template);
235
231
  if (pdf_enable && !pdf_path_excluded(file_path.relativePath)) pdf_header = process_doc_header(fm_headers, file_path.relativePath, pdf_header_template);
@@ -439,7 +435,7 @@
439
435
 
440
436
  let doc_header = '';
441
437
  let pdf_header = '';
442
- if (hdocbook_config.publicSource.includes('github.com/Hornbill-Docs')) {
438
+ if (hdocbook_config.publicSource && hdocbook_config.publicSource.includes('github.com/Hornbill-Docs')) {
443
439
  // Build doc header from template and frontmatter tags
444
440
  doc_header = process_doc_header(fm_headers, file_path.relativePath, doc_header_template);
445
441
  if (pdf_enable && !pdf_path_excluded(file_path.relativePath)) pdf_header = process_doc_header(fm_headers, file_path.relativePath, pdf_header_template);
@@ -633,7 +629,7 @@
633
629
  process.exit(1);
634
630
  }
635
631
 
636
- if (hdocbook_config.publicSource.endsWith('.git')) hdocbook_config.publicSource = hdocbook_config.publicSource.substring(0, hdocbook_config.publicSource.length - 4);
632
+ if (hdocbook_config.publicSource && hdocbook_config.publicSource.endsWith('.git')) hdocbook_config.publicSource = hdocbook_config.publicSource.substring(0, hdocbook_config.publicSource.length - 4);
637
633
 
638
634
  console.log(`Loading product families...`);
639
635
  const prods = await hdoc.load_product_families();
package/hdoc-module.js CHANGED
@@ -222,12 +222,15 @@
222
222
  };
223
223
 
224
224
  exports.get_github_api_path = function (repo, relative_path) {
225
- repo = repo.endsWith('/') ? repo.slice(0, -1) : repo;
226
- let github_paths = {};
227
- github_paths.api_path = repo.replace('https://github.com/', 'https://api.github.com/repos/');
228
- github_paths.api_path += '/commits?path=/' + relative_path.replace('\\\\', '/').replace('\\', '/');
229
- github_paths.edit_path = repo + '/blob/main/' + relative_path.replace('\\\\', '/').replace('\\', '/');
230
- return github_paths;
225
+ if (repo) {
226
+ repo = repo.endsWith('/') ? repo.slice(0, -1) : repo;
227
+ let github_paths = {};
228
+ github_paths.api_path = repo.replace('https://github.com/', 'https://api.github.com/repos/');
229
+ github_paths.api_path += '/commits?path=/' + relative_path.replace('\\\\', '/').replace('\\', '/');
230
+ github_paths.edit_path = repo + '/blob/main/' + relative_path.replace('\\\\', '/').replace('\\', '/');
231
+ return github_paths;
232
+ }
233
+ return '';
231
234
  };
232
235
 
233
236
  exports.get_github_contributors = async function (github_url, github_api_token) {
package/hdoc-stats.js CHANGED
@@ -1,31 +1,31 @@
1
1
 
2
2
  (function () {
3
3
  'use strict';
4
-
4
+
5
5
  // Required modules
6
6
  // /const { STATUS_CODES } = require('http');
7
7
  const fs = require('fs'),
8
- path = require('path'),
9
- dree = require('dree'),
10
- html2text = require('html-to-text'),
11
- wordsCount = require('words-count').default;
12
-
8
+ path = require('path'),
9
+ dree = require('dree'),
10
+ html2text = require('html-to-text'),
11
+ wordsCount = require('words-count').default;
12
+
13
13
  // Regex to remove Hornbill-specific tags
14
14
  const hbMDTagRegex = /(:{3}[ ]note)|(:{3}[ ]tip)|(:{3}[ ]important)|(:{3}[ ]caution)|(:{3}[ ]warning)|(:{3})/g;
15
-
15
+
16
16
  let stats = {
17
17
  totalMDFiles: 0,
18
18
  totalStaticHTMLFiles: 0,
19
19
  totalWordCount: 0,
20
20
  mdFiles: {},
21
- staticHTMLFiles: {}
21
+ staticHTMLFiles: {}
22
22
  };
23
23
 
24
24
  let markdownFiles = [];
25
25
 
26
26
  // File callback for scan
27
- const fileCallback = function(element) {
28
- if (element.extension === 'md' ) {
27
+ const fileCallback = function (element) {
28
+ if (element.extension === 'md') {
29
29
  markdownFiles.push(element);
30
30
  stats.totalMDFiles++;
31
31
  } else {
@@ -51,7 +51,7 @@
51
51
  const dreeOptions = {
52
52
  descendants: true,
53
53
  depth: 10,
54
- extensions: ['md','html','htm'],
54
+ extensions: ['md', 'html', 'htm'],
55
55
  hash: false,
56
56
  normalize: true,
57
57
  size: true,
@@ -60,8 +60,8 @@
60
60
  symbolicLinks: false
61
61
  };
62
62
 
63
- exports.run = function(ui_path, source_path, verbose = false) {
64
-
63
+ exports.run = function (ui_path, source_path, verbose = false) {
64
+
65
65
  // GERRY: The stats here are needed to support content development. The idea is to count all of the ]
66
66
  // words in a HDocBook so we know the size of the book, this helps with 3rd party involvement where
67
67
  // we generally need to know the word count of the content in order to get a quote for things like
@@ -69,12 +69,12 @@
69
69
  //
70
70
  // For each .md file, and for each static .HTML file (that is html files that we have not generated) we
71
71
  // should do a word count, excluding MD or HTML tags
72
-
72
+
73
73
  // STEVE: Get the docId (book root) from the hdocbook-project.json
74
74
  // From there, loop through looking for:
75
75
  // * HTML files without a matching MD, and word count those
76
76
  // * MD files, and word count those
77
-
77
+
78
78
 
79
79
  console.log('Hornbill HDocBook Stats : verbose=' + verbose, '\r\n');
80
80
 
@@ -112,7 +112,7 @@
112
112
 
113
113
  // Scan content path directory, send file info to callback for processing
114
114
  dree.scan(bookPath, dreeOptions, fileCallback);
115
- markdownFiles.forEach(function(element){
115
+ markdownFiles.forEach(function (element) {
116
116
  // Load markdown file
117
117
  let md_txt = fs.readFileSync(element.path, 'utf8');
118
118
 
@@ -120,7 +120,7 @@
120
120
  const text = html2text.convert(html_txt, {
121
121
  wordwrap: null
122
122
  });
123
-
123
+
124
124
  // Do the wordcount and add to status
125
125
  const wordCount = wordsCount(text);
126
126
  stats.totalWordCount += wordCount;
package/hdoc-validate.js CHANGED
@@ -29,6 +29,19 @@
29
29
  exclude_spellcheck = {},
30
30
  exclude_h1_count = {};
31
31
 
32
+ const excludeLink = async function (url) {
33
+ if (exclude_links[url]) return true;
34
+
35
+ for (let key in exclude_links) {
36
+ if (key.endsWith('*')) {
37
+ key = key.substring(0, key.length - 1);
38
+ if (url.startsWith(key)) return true;
39
+ }
40
+ }
41
+
42
+ return false;
43
+ };
44
+
32
45
  const spellcheckContent = async function (sourceFile, excludes) {
33
46
  let spelling_errors = {};
34
47
  let words = [];
@@ -168,7 +181,7 @@
168
181
  messages[htmlFile.relativePath].push(`Link is a properly formatted external URL: ${links[i]}`);
169
182
 
170
183
  // Skip if it's the auto-generated edit url, as these could be part of a private repo which would return a 404
171
- if (links[i] === hdoc.get_github_api_path(hdocbook_config.publicSource, htmlFile.relativePath).edit_path.replace(path.extname(htmlFile.relativePath), '.md')) {
184
+ if (hdocbook_config.publicSource !== undefined && links[i] === hdoc.get_github_api_path(hdocbook_config.publicSource, htmlFile.relativePath).edit_path.replace(path.extname(htmlFile.relativePath), '.md')) {
172
185
  continue;
173
186
  }
174
187
 
@@ -177,9 +190,11 @@
177
190
  }
178
191
 
179
192
  // Skip if the link is excluded in the project config
180
- if (exclude_links[links[i]]) {
193
+ if (excludeLink(links[i])) {
194
+ messages[htmlFile.relativePath].push(`Skipping link validation for: ${links[i]}`);
181
195
  continue;
182
196
  }
197
+
183
198
  if (links[i].toLowerCase().includes('docs.hornbill.com') || links[i].toLowerCase().includes('docs-internal.hornbill.com')) {
184
199
  errors[htmlFile.relativePath].push(`Links to Hornbill Docs should rooted and not fully-qualified: ${links[i]}`);
185
200
  continue;
@@ -359,6 +374,20 @@
359
374
  val_prod_error += `\n - ${prods_supported[i]}`
360
375
  }
361
376
  meta_errors.push(val_prod_error)
377
+ }
378
+
379
+ if (hdocbook_config.publicSource && hdocbook_config.publicSource !== '') {
380
+ // Validate publicSource
381
+ if (hdocbook_config.publicSource.toLowerCase() === '--publicsource--') {
382
+ meta_errors.push(`Value for publicSource in book metadata is set to its default template value`);
383
+ } else {
384
+ // Check URL exists
385
+ if (!hdocbook_config.publicSource.startsWith('https://github.com') && !hdocbook_config.publicSource.startsWith('https://api.github.com')) {
386
+ meta_errors.push(`Value for publicSource in book metadata is not a recognised GitHub URL: ${hdocbook_config.publicSource}`);
387
+ } else {
388
+ //
389
+ }
390
+ }
362
391
 
363
392
  }
364
393
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hdoc-tools",
3
- "version": "0.9.53",
3
+ "version": "0.9.55",
4
4
  "description": "Hornbill HDocBook Development Support Tool",
5
5
  "main": "hdoc.js",
6
6
  "bin": {
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#ffffff" class="bi bi-person-circle" viewBox="0 0 16 16">
2
+ <path d="M11 6a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/>
3
+ <path fill-rule="evenodd" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm8-7a7 7 0 0 0-5.468 11.37C3.242 11.226 4.805 10 8 10s4.757 1.225 5.468 2.37A7 7 0 0 0 8 1z"/>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person-circle" viewBox="0 0 16 16">
2
+ <path d="M11 6a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/>
3
+ <path fill-rule="evenodd" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm8-7a7 7 0 0 0-5.468 11.37C3.242 11.226 4.805 10 8 10s4.757 1.225 5.468 2.37A7 7 0 0 0 8 1z"/>
4
+ </svg>
@@ -202,13 +202,57 @@
202
202
  {
203
203
  padding:10px;
204
204
  border: 1px solid var(--htl-c-divider-light);
205
+ border-color: var(--htl-c-divider-light)!important;
205
206
  border-top-width: 0px;
206
207
  }
207
208
 
209
+ .lh-normal
210
+ {
211
+ line-height:normal;
212
+ }
213
+ .lh-3
214
+ {
215
+ line-height:3;
216
+ }
217
+ .fs-12
218
+ {
219
+ font-size:12px;
220
+ }
221
+ /* user profile stuff */
222
+ .dark .userprofile
223
+ {
224
+ background-color: var(--htl-c-bg);
225
+
226
+ }
227
+
228
+ .dark .userprofile .dropdown-menu
229
+ {
230
+ background-color: var(--htl-c-bg);
231
+ border-color: var(--htl-c-divider-light)!important;
232
+ }
233
+
234
+ .userprofile .dropdown-menu
235
+ {
236
+ min-width:max-content;
237
+ color:inherit;
238
+ }
239
+
240
+ .userprofile .dropdown-toggle::after
241
+ {
242
+ display:none;
243
+ }
244
+ .userprofile .svg-prof
245
+ {
246
+ border-radius: 50%;
247
+ }
248
+ .dark .userprofile .svg-prof
249
+ {
250
+ /*filter: invert(2);*/
251
+
252
+ }
208
253
 
209
254
  /* theme switcher */
210
255
  .theme-switch {
211
- margin-top:60%;
212
256
  position:relative;
213
257
  display: inline-block;
214
258
  width: 30px;
package/ui/index.html CHANGED
@@ -13,7 +13,9 @@
13
13
  <meta name="viewport" content="width=device-width,initial-scale=1">
14
14
  <meta name="description" content="Internal documentation for the Hornbill ESP Platform">
15
15
 
16
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.9.1/font/bootstrap-icons.css">
16
+
17
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
18
+
17
19
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
18
20
  <script src="https://code.jquery.com/jquery-3.6.1.min.js" integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"></script>
19
21
  <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous"></script>
@@ -146,13 +148,43 @@
146
148
  -->
147
149
  </div>
148
150
  <div class="toolbar-right hb-center-v">
149
- <!-- theme switch -->
150
- <label class="theme-switch" >
151
- <input class="theme-switch-checkbox" type="checkbox" v-on:change="switchViewTheme()">
152
- <span class="slider round">
151
+
152
+ <!-- theme switch -->
153
+ <label class="theme-switch" >
154
+ <input class="theme-switch-checkbox" type="checkbox" v-on:change="switchViewTheme()">
155
+ <span class="slider round">
156
+ </span>
157
+ </label>
158
+ </div>
159
+ <div v-if="docApp.userSession" class="toolbar-right hb-center-v">
160
+ <!-- user info -->
161
+ <div class="userprofile dropdown">
162
+ <span class="dropdown-toggle" role="button" data-bs-toggle="dropdown" aria-expanded="false">
163
+ <img class="svg-prof" v-bind:src="docApp.userSession.profileImage" style="width:32;height:32;"></img>
153
164
  </span>
154
- </label>
165
+ <ul class="dropdown-menu p-0">
166
+
167
+
155
168
 
169
+ <div class="panel-header border-0 position-relative">
170
+ <div class="position-relative">
171
+ <div class="text-center fw-bolder lh-3">{{docApp.userSession.userId}}</div>
172
+ <div style="height:20px"></div>
173
+ </div>
174
+ <div class="position-absolute top-100 start-50 translate-middle">
175
+ <img class="svg-prof" v-bind:src="docApp.userSession.profileImage" style="width:64px;height:64px;"></img>
176
+ </div>
177
+ </div>
178
+ <div class="panel-content border-0 border-top p-3 pt-5 fw-light lh-normal">
179
+ <div class="text-center fw-bolder p-1">{{docApp.userSession.userName}}</div>
180
+ <div class="text-center fw-bolder p-1 fs-12">{{docApp.userSession.email}}</div>
181
+ </div>
182
+ <div class="panel-content p-3 border-0 border-top fw-light lh-normal">
183
+ <div class="lh-normal fs-12"><i class="bi bi-database-lock"></i> <span style="display:inline-block;width:48px">Issuer</span> : {{docApp.userSession.issuerInstance}}</div>
184
+ <div class="lh-normal fs-12" v-bind:title="docApp.userSession.expiresDateTime"><i class="bi bi-hourglass-split"></i> <span style="display:inline-block;width:48px">Expires</span> : {{new Date(docApp.userSession.validUntil).toLocaleDateString()}}</div>
185
+ </div>
186
+ </ul>
187
+ </div>
156
188
  </div>
157
189
  </div>
158
190
 
@@ -8,6 +8,11 @@ var jqLeftNav = null;
8
8
  var global = {stateParams:{},lastLayoutClass:""};
9
9
 
10
10
  var docAppMethods = {
11
+ setSessionInfo:function(info)
12
+ {
13
+ let self = this;
14
+ self.docApp.userSession = info;
15
+ },
11
16
  switchViewTheme:function()
12
17
  {
13
18
  if(ThemePreference)document.documentElement.classList.remove(ThemePreference);
@@ -151,12 +156,12 @@ function highlightNavigationLinkFromUrl(matchLinkHref)
151
156
  }
152
157
  catch(e)
153
158
  {
154
- //console.log("BAD navigation menu item found",el);
159
+ //hslDocLog.log("BAD navigation menu item found",el);
155
160
  }
156
161
 
157
162
  if(checkUrl)
158
163
  {
159
- //console.log(checkUrl.pathname,matchLinkHref)
164
+ //hslDocLog.log(checkUrl.pathname,matchLinkHref)
160
165
  let testCurrPath = removeStartingSlash(checkUrl.pathname);
161
166
  if(testCurrPath===matchLinkHref)
162
167
  {
@@ -200,7 +205,7 @@ function getAnchorFromHash(strHash,strHasClass)
200
205
  }
201
206
  catch(e)
202
207
  {
203
- console.log("Get document anchor element by hash failed ["+strHash+"]",e);
208
+ hslDocLog.log("Get document anchor element by hash failed ["+strHash+"]",e);
204
209
  return null;
205
210
  }
206
211
 
@@ -356,7 +361,7 @@ function loadContentUrl(linkRef,fromPageRefresh,fromPopState)
356
361
  }
357
362
  else
358
363
  {
359
- console.log("code highlighting js could not be loaded. code block highlighting will not be enabled");
364
+ hslDocLog.log("code highlighting js could not be loaded. code block highlighting will not be enabled");
360
365
  }
361
366
 
362
367
  //-- show copy button by any code blocks
@@ -578,7 +583,7 @@ $(".document-body").attr("v-pre","");
578
583
 
579
584
  var view = new Vue({
580
585
  el: '#vDocDevApp',
581
- data: {updateCounter:0,bookId:"", docApp:{keepTocLayout:false,book:{},navSections:[],tableOfContents:[],bookBreadCrumb:[]}},
586
+ data: {userSession:{},updateCounter:0,bookId:"", docApp:{keepTocLayout:false,book:{},navSections:[],tableOfContents:[],bookBreadCrumb:[]}},
582
587
  methods:docAppMethods,
583
588
  directives: {
584
589
  somedirectivename: {
@@ -607,6 +612,24 @@ Vue.component('nav-section-component', {
607
612
  });
608
613
 
609
614
 
615
+ var hslDocLog={
616
+ _entry:[],
617
+ log:function(strMessage,varData)
618
+ {
619
+ if(varData!==undefined) console.log(strMessage,varData)
620
+ else console.log(strMessage);
621
+
622
+ this._entry.push({msg:strMessage,data:varData})
623
+ },
624
+ dump:function()
625
+ {
626
+ for(let x=0;x<this._entry.length;x++)
627
+ {
628
+ console.log(this._entry[x].msg,this._entry[x].data || null);
629
+ }
630
+ }
631
+ }
632
+
610
633
  async function intialiseApp() {
611
634
 
612
635
  // set theme switch
@@ -617,6 +640,33 @@ async function intialiseApp() {
617
640
  //jqContentContainer = $(".injected-document-content");
618
641
  jqLeftNav = $("#DocSidebarNav");
619
642
 
643
+
644
+ //-- get session info
645
+ let dummyResponse = {
646
+ "type": "user",
647
+ "userId": "doom-guy",
648
+ "userName": "Doom Guy",
649
+ "email": "doomguy@hornbill.com",
650
+ "profileImage": "https://www.writeups.org/wp-content/uploads/Doomguy-doom-portrait-featured-sprite.jpg",
651
+ "issuerDomain": ".hornbill.com",
652
+ "issuerInstance": "hornbill",
653
+ "validUntil": "2023-07-30 06:33:49Z"
654
+ }
655
+ dummyResponse.expiresDateTime = new Date(dummyResponse.validUntil).toLocaleDateString() + ' ' + new Date(dummyResponse.validUntil).toLocaleTimeString();
656
+
657
+ fetchJsonFile("_api/session/").then(function(sessionData)
658
+ {
659
+ hslDocLog.log("Hornbill docs get session data response",sessionData)
660
+ if(sessionData && sessionData.type==="user")
661
+ {
662
+ hslDocLog.log("Hornbill docs set session set expires date time to browser locale")
663
+ sessionData.expiresDateTime = new Date(sessionData.validUntil).toLocaleDateString() + ' ' + new Date(sessionData.validUntil).toLocaleTimeString();
664
+ hslDocLog.log("Hornbill docs update vue session object model",sessionData);
665
+ view.setSessionInfo(sessionData);
666
+ }
667
+ });
668
+ //-- eof session stuff
669
+
620
670
  await fetchJsonFile("_books/library.json").then(function(data){
621
671
 
622
672
  // Get docbook library list
@@ -652,7 +702,7 @@ async function intialiseApp() {
652
702
  }
653
703
  else
654
704
  {
655
- console.log("initial first view link to laod is not present");
705
+ hslDocLog.log("initial first view link to laod is not present");
656
706
  }
657
707
 
658
708
  $(".hb-hidden").removeClass("hb-hidden");