hdoc-tools 0.8.21 → 0.8.23

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Hornbill Docs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,141 @@
1
+ (function () {
2
+ 'use strict';
3
+
4
+ const path = require('path'),
5
+ hdoc_index = require(path.join(__dirname, 'hdoc-db.js')),
6
+ database = require('better-sqlite3');
7
+
8
+ const db_schema = {
9
+ hdoc_index: [
10
+ 'relative_url UNINDEXED',
11
+ 'book_id',
12
+ 'book_audience UNINDEXED',
13
+ 'book_tags',
14
+ 'doc_title',
15
+ 'doc_content',
16
+ 'doc_preview UNINDEXED',
17
+ 'doc_family_id'
18
+ ],
19
+ hdoc_meta: [
20
+ 'doc_id INTEGER',
21
+ 'contributor_count INTEGER UNINDEXED',
22
+ 'edit_url UNINDEXED',
23
+ 'last_commit UNINDEXED'
24
+ ],
25
+ hdoc_contributors: [
26
+ 'doc_id INTEGER',
27
+ 'login',
28
+ 'name',
29
+ 'avatar UNINDEXED',
30
+ 'url UNINDEXED'
31
+ ]
32
+ };
33
+
34
+ exports.create_table = function (db, table, cols, virtual, fts5) {
35
+ const table_created = hdoc_index.create_table(db, table, cols, virtual, fts5);
36
+ if (table_created !== null) {
37
+ return `\nError creating table: ${table_created}`;
38
+ } else {
39
+ console.log(`\nTable created: ${table}`);
40
+ }
41
+ return null;
42
+ };
43
+
44
+ exports.create_db = function (db_path, doc_id) {
45
+ let response = {
46
+ error: null,
47
+ db: null
48
+ };
49
+ console.log('Performing SQlite index creation...');
50
+ let db_name = path.join(db_path, doc_id, 'index.db');
51
+ response.db = new database(db_name);
52
+ response.db.pragma('encoding="UTF-8"');
53
+ console.log(`\nDatabase created: ${db_name}`);
54
+
55
+ // Create tables
56
+ for (const key in db_schema) {
57
+ if (db_schema.hasOwnProperty(key)) {
58
+ const virtual = key === 'hdoc_index' ? true : false;
59
+ const fts5 = key === 'hdoc_index' ? true : false;
60
+ const table_created_error = this.create_table(response.db, key, db_schema[key], virtual, fts5);
61
+ if (table_created_error !== null) {
62
+ console.log(table_created_error);
63
+ }
64
+ }
65
+ }
66
+ return response;
67
+ };
68
+
69
+ exports.populate_index = function (db, doc_id, book_config, index_records, verbose = false) {
70
+ let response = {
71
+ success: false,
72
+ index_success_count: 0,
73
+ error: ''
74
+ };
75
+
76
+ if (!book_config.tags) book_config.tags = [];
77
+
78
+ for (let i = 0; i < index_records.length; i++) {
79
+ let index_path_name = index_records[i].relative_path.replace('\\', '/').replace(`${doc_id}/`, '');
80
+ index_path_name = index_path_name.replace(path.extname(index_records[i].relative_path), '');
81
+ const index_vals = [
82
+ index_path_name,
83
+ doc_id,
84
+ book_config.audience.join(','),
85
+ book_config.tags.join(','),
86
+ index_records[i].index_html.fm_props.title,
87
+ index_records[i].index_html.text,
88
+ index_records[i].index_html.preview,
89
+ book_config.productFamily
90
+ ];
91
+ const index_response = hdoc_index.insert_record(db, 'hdoc_index', db_schema.hdoc_index, index_vals);
92
+ if (!index_response.success) {
93
+ console.log(`Index record creation failed - ${doc_id}/${index_records[i].index_html.fm_props.title}: ${index_response.error}`);
94
+ continue;
95
+ }
96
+
97
+ // Now add metadata
98
+ const meta_vals = [
99
+ parseInt(index_response.row_id, 10),
100
+ index_records[i].metadata.contributor_count,
101
+ index_records[i].metadata.edit_url,
102
+ index_records[i].metadata.last_commit
103
+ ];
104
+ const meta_response = hdoc_index.insert_record(db, 'hdoc_meta', db_schema.hdoc_meta, meta_vals);
105
+ if (!meta_response.success) {
106
+ console.log(`Index metadata record creation failed - ${doc_id}/${index_response.row_id}/${index_records[i].index_html.fm_props.title}: ${meta_response.error}`);
107
+ continue;
108
+ }
109
+ if (verbose) {
110
+ console.log(`Inserted index record ${index_response.row_id}: ${doc_id} - ${index_records[i].index_html.fm_props.title}`);
111
+ console.log(`Inserted index metadata record for index ID: ${meta_response.row_id}`);
112
+ }
113
+
114
+ // Now add contributor records
115
+ for (let j = 0; j < index_records[i].contributors.length; j++) {
116
+ const contrib_vals = [
117
+ parseInt(index_response.row_id, 10),
118
+ index_records[i].contributors[j].login,
119
+ index_records[i].contributors[j].name,
120
+ index_records[i].contributors[j].avatar_url,
121
+ index_records[i].contributors[j].html_url
122
+ ];
123
+ const cont_response = hdoc_index.insert_record(db, 'hdoc_contributors', db_schema.hdoc_contributors, contrib_vals);
124
+ if (!cont_response.success) {
125
+ console.log(`Index document contributor record creation failed - ${doc_id}/${index_response.row_id}/${index_records[i].index_html.fm_props.title}: ${cont_response.error}`);
126
+ continue;
127
+ }
128
+ if (verbose) {
129
+ console.log(`Inserted document contributor recordL ${cont_response.row_id}`);
130
+ }
131
+ }
132
+
133
+ response.index_success_count++;
134
+
135
+ }
136
+ response.success = true;
137
+ console.log(`\nIndex Build Complete:`);
138
+ console.log(`${response.index_success_count} document index records created.`);
139
+ return response;
140
+ };
141
+ })();
package/hdoc-build.js CHANGED
@@ -1,32 +1,21 @@
1
1
  (function () {
2
2
  'use strict';
3
3
 
4
- const {
5
- createHash
6
- } = require('crypto'),
4
+ const crypto = require('crypto'),
7
5
  dree = require('dree'),
8
6
  fs = require('fs-extra'),
9
7
  mdfm = require('markdown-it-front-matter'),
10
8
  path = require('path'),
11
- Database = require('better-sqlite3'),
12
9
  URL = require("url").URL,
13
10
  validate = require(path.join(__dirname, 'hdoc-validate.js')),
14
11
  hdoc = require(path.join(__dirname, 'hdoc-module.js')),
12
+ hdoc_build_db = require(path.join(__dirname, 'hdoc-build-db.js')),
15
13
  hdoc_index = require(path.join(__dirname, 'hdoc-db.js')),
16
14
  zipper = require('zip-local');
17
15
 
18
16
  const h_tags_to_search = ['h1', 'h2', 'h3'],
19
- index_cols = [
20
- 'relative_url UNINDEXED',
21
- 'book_id',
22
- 'book_audience UNINDEXED',
23
- 'book_tags',
24
- 'doc_title',
25
- 'doc_content',
26
- 'doc_preview UNINDEXED',
27
- 'doc_family_id'
28
- ],
29
- doc_header_template_path = path.join(__dirname, 'templates', 'doc-header.html');
17
+ doc_header_template_path = path.join(__dirname, 'templates', 'doc-header.html'),
18
+ non_git_doc_header_template_path = path.join(__dirname, 'templates', 'doc-header-non-git.html');
30
19
 
31
20
  let bc = {}, // Breadcrumbs map
32
21
  book_read_time = 0,
@@ -35,6 +24,7 @@
35
24
  conversion_success = 0,
36
25
  conversion_failed = 0,
37
26
  doc_header_template = '',
27
+ doc_header_template_non_git = '',
38
28
  doc_id = '',
39
29
  git_token = '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', // Github fine-grained personal access token that has minimum read-only access to Hornbill Docs org repo content
40
30
  hdocbook_config = {},
@@ -47,16 +37,15 @@
47
37
  static_html_files = [],
48
38
  work_path_content = '';
49
39
 
50
- const transform_static_html = function (file_path) {
40
+ const transform_static_html = async function (file_path) {
51
41
  if (fs.existsSync(file_path.path)) {
52
42
  // Load HTML file
53
43
  let html_txt = fs.readFileSync(file_path.path, 'utf8');
54
44
  html_txt = html_txt.replace(/\r/gm, ''); // Remove CR's so we're just dealing with newlines
55
45
 
56
- let html_txt_updated = false;
57
-
58
46
  let fm_headers = [];
59
47
  let existing_fm_headers = false;
48
+ let doc_type = 'Article';
60
49
 
61
50
  // Check if we have a frontmatter comment
62
51
  const fm_header = hdoc.getHTMLFrontmatterHeader(html_txt);
@@ -85,10 +74,13 @@
85
74
 
86
75
  for (const key in fm_header.fm_properties) {
87
76
  if (fm_header.fm_properties.hasOwnProperty(key)) {
88
- fm_headers.push({
89
- id: key,
90
- value: fm_header.fm_properties[key]
91
- });
77
+ if (key === 'type') doc_type = fm_header.fm_properties[key];
78
+ else {
79
+ fm_headers.push({
80
+ id: key,
81
+ value: fm_header.fm_properties[key]
82
+ });
83
+ }
92
84
  }
93
85
  }
94
86
 
@@ -133,36 +125,93 @@
133
125
  });
134
126
  }
135
127
 
128
+ // Add doc type
129
+ fm_headers.push({
130
+ id: 'type',
131
+ value: doc_type
132
+ });
133
+
134
+ let metadata = {};
135
+
136
+ // Get contributor data from Github, if exists
137
+ let contribs = [];
138
+ if (hdocbook_config.publicSource && hdocbook_config.publicSource !== '' && hdocbook_config.publicSource.includes('github.com/Hornbill-Docs')) {
139
+ // Remove the first <h1>title</h1> from the HTML as we'll add that in the document header
140
+ html_txt = html_txt.replace(/(<h1.*?>)\s*.*\s*(.*<\/h1>)/, '');
141
+
142
+ const github_paths = hdoc.get_github_api_path(hdocbook_config.publicSource, file_path.relativePath);
143
+ const contributors = hdoc.get_github_contributors(github_paths.api_path, git_token);
144
+
145
+ if (!contributors.success) {
146
+ console.log(`Error retrieving contributors from Github: ${contributors.error}`);
147
+ } else {
148
+ metadata.last_commit = contributors.last_commit_date;
149
+ metadata.contributor_count = contributors.contributor_count;
150
+ metadata.edit_url = github_paths.edit_path;
151
+ contribs = contributors.contributors;
152
+ contributors.editPath = github_paths.edit_path;
153
+ fm_headers.push({
154
+ id: 'contributor-count',
155
+ value: contributors.contributor_count
156
+ });
157
+ fm_headers.push({
158
+ id: 'last-commit',
159
+ value: contributors.last_commit_date
160
+ });
161
+ const target_file = file_path.path.replace(path.extname(file_path.path), '._info.json');
162
+ delete contributors.success;
163
+ delete contributors.error;
164
+ contributors.editPath = github_paths.edit_path;
165
+ try {
166
+ fs.writeFileSync(target_file, JSON.stringify(contributors, null, 2));
167
+ } catch (err) {
168
+ console.log('Error writing:', target_file, '\n', err);
169
+ }
170
+ }
171
+ fm_headers.push({
172
+ id: 'edit-path',
173
+ value: github_paths.edit_path
174
+ });
175
+ }
176
+
177
+ let fm_header_content = '<!--[[FRONTMATTER\n';
136
178
  if (fm_headers.length > 0) {
137
- let fm_headers_content = '[[FRONTMATTER\n';
138
179
  for (let i = 0; i < fm_headers.length; i++) {
139
- fm_headers_content += `${fm_headers[i].id}: ${fm_headers[i].value}\n`;
180
+ fm_header_content += `${fm_headers[i].id}: ${fm_headers[i].value}\n`;
140
181
  }
141
- fm_headers_content += ']]';
182
+ fm_header_content += ']]-->';
142
183
 
143
184
  if (existing_fm_headers) {
144
- html_txt = html_txt.replace(fm_header.fm_header, fm_headers_content);
145
- html_txt_updated = true;
146
- } else {
147
- html_txt = `<!--${fm_headers_content}-->\n${html_txt}`;
148
- html_txt_updated = true;
185
+ html_txt = html_txt.replace('<!--' + fm_header.fm_header + '-->', '');
149
186
  }
150
187
  }
151
188
 
189
+ let doc_header = '';
190
+ if (hdocbook_config.publicSource.includes('github.com/Hornbill-Docs')) {
191
+ // Build doc header from template and frontmatter tags
192
+ doc_header = process_doc_header(fm_headers, file_path.relativePath, doc_header_template);
193
+ } else {
194
+ doc_header = process_doc_header(fm_headers, file_path.relativePath, doc_header_template_non_git);
195
+ }
196
+
197
+ html_txt = `${fm_header_content}\n${doc_header}\n${html_txt}`;
198
+
152
199
  index_records.push({
153
200
  relative_path: file_path.relativePath,
154
- index_html: hdoc_index.transform_html_for_index(html_txt)
201
+ index_html: hdoc_index.transform_html_for_index(html_txt),
202
+ metadata: metadata,
203
+ contributors: contribs
155
204
  });
156
- if (html_txt_updated) {
157
- // Save HTML into HTML file
158
- fs.writeFile(file_path.path, html_txt, function writeJSON(err) {
159
- if (err) return console.log('Error writing:', target_file, '\n', err);
160
- });
205
+ // Save HTML into HTML file
206
+ try {
207
+ fs.writeFileSync(file_path.path, html_txt);
208
+ } catch (err) {
209
+ console.log('Error writing:', target_file, '\n', err);
161
210
  }
162
211
  }
163
212
  };
164
213
 
165
- const transform_markdown_and_save_html = function (file_path) {
214
+ const transform_markdown_and_save_html = async function (file_path) {
166
215
  conversion_attempted++;
167
216
  if (fs.existsSync(file_path.path)) {
168
217
  // Load markdown file
@@ -226,7 +275,6 @@
226
275
  doc_title = fm_property[1].trim();
227
276
  }
228
277
  if (fm_property[0].trim() === 'type') {
229
- fm_contains_type = true;
230
278
  doc_type = fm_property[1].trim();
231
279
  }
232
280
  if (fm_property[0].trim() === 'reading-time') {
@@ -270,8 +318,10 @@
270
318
  value: read_time_mins
271
319
  });
272
320
  }
321
+ let metadata = {};
273
322
 
274
323
  // Get contributor data from Github, if exists
324
+ let contribs = [];
275
325
  if (hdocbook_config.publicSource && hdocbook_config.publicSource !== '' && hdocbook_config.publicSource.includes('github.com/Hornbill-Docs')) {
276
326
  // Remove the first <h1>title</h1> from the HTML as we'll add that in the document header
277
327
  html_txt = html_txt.replace(/(<h1.*?>)\s*.*\s*(.*<\/h1>)/, '');
@@ -282,6 +332,12 @@
282
332
  if (!contributors.success) {
283
333
  console.log(`Error retrieving contributors from Github: ${contributors.error}`);
284
334
  } else {
335
+ metadata.last_commit = contributors.last_commit_date;
336
+ metadata.contributor_count = contributors.contributor_count;
337
+ metadata.edit_url = github_paths.edit_path;
338
+ contribs = contributors.contributors;
339
+ contributors.editPath = github_paths.edit_path;
340
+
285
341
  fm_headers.push({
286
342
  id: 'contributor-count',
287
343
  value: contributors.contributor_count
@@ -290,25 +346,23 @@
290
346
  id: 'last-commit',
291
347
  value: contributors.last_commit_date
292
348
  });
349
+ const target_file = file_path.path.replace(path.extname(file_path.path), '._info.json');
350
+ delete contributors.success;
351
+ delete contributors.error;
352
+ contributors.editPath = github_paths.edit_path;
353
+ try {
354
+ fs.writeFileSync(target_file, JSON.stringify(contributors, null, 2));
355
+ } catch (err) {
356
+ console.log('Error writing:', target_file, '\n', err);
357
+ }
293
358
  }
294
359
  fm_headers.push({
295
360
  id: 'edit-path',
296
361
  value: github_paths.edit_path
297
362
  });
298
- const target_file = file_path.path.replace(path.extname(file_path.path), '._info.json');
299
- delete contributors.success;
300
- delete contributors.error;
301
- contributors.editPath = github_paths.edit_path;
302
- try {
303
- fs.writeFileSync(target_file, JSON.stringify(contributors, null, 2));
304
- } catch (err) {
305
- console.log('Error writing:', target_file, '\n', err);
306
- }
307
363
  }
308
364
 
309
-
310
- // Add frontmatter tags as comment to front of HTML
311
-
365
+ // Add frontmatter tags as comment
312
366
  let fm_header = '<!--[[FRONTMATTER\n';
313
367
  if (fm_headers.length > 0) {
314
368
  for (let i = 0; i < fm_headers.length; i++) {
@@ -316,29 +370,37 @@
316
370
  }
317
371
  }
318
372
  fm_header += ']]-->';
319
-
373
+
374
+ let doc_header = '';
320
375
  if (hdocbook_config.publicSource.includes('github.com/Hornbill-Docs')) {
321
376
  // Build doc header from template and frontmatter tags
322
- const doc_header = process_doc_header(fm_headers, file_path.relativePath);
323
- html_txt = `${fm_header}\n${doc_header}\n${html_txt}`;
377
+ doc_header = process_doc_header(fm_headers, file_path.relativePath, doc_header_template);
324
378
  } else {
325
- html_txt = `${fm_header}\n${html_txt}`;
379
+ // Build doc header from template and frontmatter tags
380
+ doc_header = process_doc_header(fm_headers, file_path.relativePath, doc_header_template_non_git);
326
381
  }
327
-
328
-
382
+ /*
383
+ const pdf_html = `${fm_header}\n${doc_header}\n${html_txt}`;
384
+ const pdf_file = file_path.path.replace(path.extname(file_path.path), '.pdf');
385
+ */
386
+ html_txt = `${fm_header}\n${doc_header}\n${html_txt}`;
329
387
 
330
388
  // Save HTML into HTML file
331
389
  const target_file = file_path.path.replace(path.extname(file_path.path), '.html');
332
390
  const relative_path = file_path.relativePath.replace(path.extname(file_path.path), '.html');
333
- fs.writeFile(target_file, html_txt, function writeJSON(err) {
334
- if (err) return console.log('Error writing:', target_file, '\n', err);
335
- });
391
+ try {
392
+ fs.writeFileSync(target_file, html_txt);
393
+ } catch (err) {
394
+ console.log('Error writing:', target_file, '\n', err);
395
+ }
336
396
 
337
397
  const index_details = hdoc_index.transform_html_for_index(html_txt);
338
398
 
339
399
  index_records.push({
340
400
  relative_path: relative_path,
341
- index_html: index_details
401
+ index_html: index_details,
402
+ metadata: metadata,
403
+ contributors: contribs
342
404
  });
343
405
 
344
406
  // Delete MD file from _work path
@@ -355,8 +417,8 @@
355
417
  return false;
356
418
  };
357
419
 
358
- const process_doc_header = function (fm_headers, doc_path) {
359
- let wip_doc_header = doc_header_template;
420
+ const process_doc_header = function (fm_headers, doc_path, template) {
421
+ let wip_doc_header = template;
360
422
 
361
423
  // Process fm_headers properties first
362
424
  for (let i = 0; i < fm_headers.length; i++) {
@@ -430,10 +492,7 @@
430
492
 
431
493
  const md5DreeOptions = {
432
494
  hash: true,
433
- hashAlgorithm: 'md5',
434
- hashEncoding: 'hex',
435
495
  normalize: true,
436
- size: true,
437
496
  sorted: true
438
497
  };
439
498
 
@@ -507,6 +566,10 @@
507
566
  for (let d = 0; d < nav_c.items.length; d++) {
508
567
  const nav_d = nav_c.items[d];
509
568
  if (nav_d.link) {
569
+ if (nav_d.link.includes('\\')) {
570
+ console.log(`Navigation items should not contain backslashes: ${nav_d.link}`);
571
+ process.exit(1);
572
+ }
510
573
  if (bc[nav_c.link]) {
511
574
  bc[nav_d.link] = bc[nav_c.link];
512
575
  } else {
@@ -529,7 +592,7 @@
529
592
  });
530
593
  }
531
594
  }
532
-
595
+
533
596
  }
534
597
  }
535
598
  }
@@ -540,11 +603,11 @@
540
603
  //console.log(JSON.stringify(bc, null, 2));
541
604
  };
542
605
 
543
- exports.run = function (source_path, verbose, github_api_token) {
606
+ exports.run = async function (source_path, verbose, github_api_token) {
544
607
  if (github_api_token !== '') {
545
608
  git_token = github_api_token;
546
609
  }
547
-
610
+
548
611
  // GERRY: The purpose of this function is to create a zip file containing the hdocbook content,
549
612
  // * Create a _work folder
550
613
  // * copy the hdocbook content to the work folder
@@ -591,9 +654,10 @@
591
654
  process.exit(1);
592
655
  }
593
656
 
594
- // Load document header template
657
+ // Load document header templates
595
658
  try {
596
659
  doc_header_template = fs.readFileSync(doc_header_template_path, 'utf8');
660
+ doc_header_template_non_git = fs.readFileSync(non_git_doc_header_template_path, 'utf8');
597
661
  } catch (err) {
598
662
  console.log(`Error reading document header template: ${err}`);
599
663
  process.exit(1);
@@ -605,15 +669,16 @@
605
669
  dree.scan(work_path, dreeOptions, build_file_callback);
606
670
 
607
671
  // Work through MD files and convert to HTML
608
- md_files.forEach(function (md_file) {
609
- transform_markdown_and_save_html(md_file);
610
- });
611
-
672
+ for (let i = 0; i < md_files.length; i++) {
673
+ await transform_markdown_and_save_html(md_files[i]);
674
+ }
675
+
612
676
  // Work through Static HTML files and add Frontmatter tags
613
- static_html_files.forEach(function (static_html_file) {
614
- transform_static_html(static_html_file);
615
- });
677
+ for (let i = 0; i < static_html_files.length; i++) {
678
+ await transform_static_html(static_html_files[i]);
679
+ }
616
680
 
681
+ // Output to console
617
682
  console.log(` MD files found: ${conversion_attempted}`);
618
683
  console.log(`Successfully converted to HTML: ${conversion_success}`);
619
684
  console.log(` Failed to convert: ${conversion_failed}\n`);
@@ -628,47 +693,18 @@
628
693
  process.exit(1);
629
694
  }
630
695
 
631
- // Now build the index
632
- console.log('Performing SQlite index creation...');
633
- let db_name = path.join(work_path, doc_id, 'index.db');
634
- const db = new Database(db_name);
635
- db.pragma('encoding="UTF-8"');
636
- console.log(`\nDatabase created: ${db_name}`);
637
-
638
- // Now add the table
639
- const table_name = 'hdoc_index';
640
- const table_created = hdoc_index.create_virtual_table(db, table_name, index_cols);
696
+ // Build the index
697
+ // Create the DB and tables
698
+ let db = hdoc_build_db.create_db(work_path, doc_id);
699
+ if (db.error && db.error !== null) {
700
+ console.log(db.error);
701
+ process.exit(1);
702
+ }
641
703
 
642
- if (table_created !== null) {
643
- console.log(`\nError creating table: ${table_created}`);
644
- } else {
645
- console.log(`\nVirtual table created: ${table_name}`);
646
- if (!hdocbook_config.tags) hdocbook_config.tags = [];
647
- let index_success_count = 0;
648
- for (let i = 0; i < index_records.length; i++) {
649
- let index_path_name = index_records[i].relative_path.replace('\\', '/').replace(`${doc_id}/`, '');
650
- index_path_name = index_path_name.replace(path.extname(index_records[i].relative_path), '');
651
- const index_vals = [
652
- index_path_name,
653
- doc_id,
654
- hdocbook_config.audience.join(','),
655
- hdocbook_config.tags.join(','),
656
- index_records[i].index_html.fm_props.title,
657
- index_records[i].index_html.text,
658
- index_records[i].index_html.preview,
659
- hdocbook_config.productFamily
660
- ];
661
- const index_response = hdoc_index.insert_record(db, table_name, index_cols, index_vals, doc_id, index_records[i].index_html.fm_props.title);
662
- if (!index_response.success) {
663
- console.log(`Index record creation failed - ${doc_id}/${index_records[i].index_html.fm_props.title}: ${index_response.error}`);
664
- continue;
665
- }
666
- index_success_count++;
667
- if (verbose) {
668
- console.log(`Inserted index record ${index_response.row_id}: ${doc_id} - ${index_records[i].index_html.fm_props.title}`);
669
- }
670
- }
671
- console.log(`\nIndex Build Complete: ${index_success_count} records created.`);
704
+ const index = hdoc_build_db.populate_index(db.db, doc_id, hdocbook_config, index_records, verbose);
705
+ if (!index.success) {
706
+ console.log(index.error);
707
+ process.exit(1);
672
708
  }
673
709
 
674
710
  // Now create MD5 hash of built content
@@ -682,7 +718,7 @@
682
718
  process.exit(1);
683
719
  }
684
720
 
685
- const hash = createHash("md5").update(concat_hash).digest("hex");
721
+ const hash = crypto.createHash("md5").update(concat_hash).digest("hex");
686
722
  const checksum_path = path.join(work_path_content, 'checksum.md5');
687
723
  try {
688
724
  fs.writeFileSync(checksum_path, hash);
package/hdoc-db.js CHANGED
@@ -5,9 +5,13 @@
5
5
  path = require('path'),
6
6
  hdoc = require(path.join(__dirname, 'hdoc-module.js'));
7
7
 
8
- exports.create_virtual_table = function (db, table_name, columns) {
9
- let create_sql = [];
10
- create_sql.push(`create VIRTUAL table ${table_name} USING fts5(`);
8
+ exports.create_table = function (db, table_name, columns, virtual, fts5) {
9
+ let create_sql = ['CREATE'];
10
+ if (virtual) create_sql.push('VIRTUAL');
11
+ create_sql.push('TABLE');
12
+ create_sql.push(table_name);
13
+ if (fts5) create_sql.push('USING fts5(');
14
+ else create_sql.push('(');
11
15
  for (let i = 0; i < columns.length; i++) {
12
16
  if (i !== 0) create_sql.push(`,${columns[i]}`);
13
17
  else create_sql.push(columns[i]);
@@ -21,7 +25,7 @@
21
25
  }
22
26
  };
23
27
 
24
- exports.insert_record = function (db, table, columns, values, book_id, doc_title) {
28
+ exports.insert_record = function (db, table, columns, values) {
25
29
  let response = {
26
30
  success: false,
27
31
  row_id: 0,
@@ -33,11 +37,11 @@
33
37
  let vals = 'VALUES (';
34
38
  for (let i = 0; i < columns.length; i++) {
35
39
  if (i === 0) {
36
- cols += `${columns[i].replace('UNINDEXED', '').trim()}`;
40
+ cols += `${columns[i].replace('UNINDEXED', '').replace('INTEGER', '').trim()}`;
37
41
  vals += '?';
38
42
  } else {
39
- cols += `,${columns[i].replace('UNINDEXED', '').trim()}`;
40
- vals += ',?';
43
+ cols += `, ${columns[i].replace('UNINDEXED', '').replace('INTEGER', '').trim()}`;
44
+ vals += ', ?';
41
45
  }
42
46
  }
43
47
  cols += ')';
@@ -46,7 +50,7 @@
46
50
  queryProps.push(vals);
47
51
 
48
52
  try {
49
- const stmt = db.prepare(queryProps.join('\n'));
53
+ const stmt = db.prepare(queryProps.join(' '));
50
54
  const info = stmt.run(values);
51
55
  response.row_id = info.lastInsertRowid;
52
56
  response.success = true;
package/hdoc-validate.js CHANGED
@@ -12,6 +12,7 @@ const parseLinkDestination = require('markdown-it/lib/helpers/parse_link_destina
12
12
 
13
13
  let errors = {},
14
14
  messages = {},
15
+ warnings = {},
15
16
  errorcount = 0,
16
17
  filecount = 0,
17
18
  htmlFiles = [];
@@ -58,11 +59,11 @@ const parseLinkDestination = require('markdown-it/lib/helpers/parse_link_destina
58
59
 
59
60
  // Replace /_books/ with /
60
61
  file_path = file_path.replace(path.sep + '_books' + path.sep, path.sep);
61
- if (!fs.existsSync(file_path) && !fs.existsSync(file_path + '.htm') && !fs.existsSync(file_path + '.html')) {
62
- errors[html_path.relativePath].push(`Book resource does not exist: ${file_path}`);
62
+ if (!fs.existsSync(file_path) && !fs.existsSync(file_path + path.sep + 'index.htm') && !fs.existsSync(file_path + 'index.html') && !fs.existsSync(file_path + '.htm') && !fs.existsSync(file_path + '.html')) {
63
+ errors[html_path.relativePath].push(`Book resource does not exist: ${relative_path}`);
63
64
  return false;
64
65
  } else {
65
- messages[html_path.relativePath].push(`Book resource exists: ${file_path}`);
66
+ messages[html_path.relativePath].push(`Book resource exists: ${relative_path}`);
66
67
  }
67
68
  return true;
68
69
  };
@@ -96,6 +97,7 @@ const parseLinkDestination = require('markdown-it/lib/helpers/parse_link_destina
96
97
  // Initiate maps for errors and verbose messages for HTML file
97
98
  errors[htmlFiles[i].relativePath] = [];
98
99
  messages[htmlFiles[i].relativePath] = [];
100
+ warnings[htmlFiles[i].relativePath] = [];
99
101
 
100
102
  const links = getLinks(htmlFiles[i]);
101
103
  if (links.length === 0) {
package/hdoc.js CHANGED
@@ -1,6 +1,6 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
- (function () {
3
+ (async function () {
4
4
  'use strict';
5
5
 
6
6
  const preRun = require('./validateNodeVer.js'),
@@ -71,7 +71,7 @@
71
71
  server.run(ui_path, source_path);
72
72
  } else if (command == 'build') {
73
73
  const builder = require(path.join(__dirname, 'hdoc-build.js'));
74
- builder.run(source_path, verbose, git_token);
74
+ await builder.run(source_path, verbose, git_token);
75
75
  } else if (command == 'stats') {
76
76
  const stats = require(path.join(__dirname, 'hdoc-stats.js'));
77
77
  stats.run(ui_path, source_path, verbose);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hdoc-tools",
3
- "version": "0.8.21",
3
+ "version": "0.8.23",
4
4
  "description": "Hornbill HDocBook Development Support Tool",
5
5
  "main": "hdoc.js",
6
6
  "bin": {
@@ -10,6 +10,7 @@
10
10
  "hdoc.js",
11
11
  "hdoc-db.js",
12
12
  "hdoc-build.js",
13
+ "hdoc-build-db.js",
13
14
  "hdoc-help.js",
14
15
  "hdoc-init.js",
15
16
  "hdoc-module.js",
@@ -38,10 +39,12 @@
38
39
  "highlight.js": "^11.6.0",
39
40
  "html-to-text": "^8.2.1",
40
41
  "js-yaml": "^4.1.0",
42
+ "jspdf": "^2.5.1",
41
43
  "markdown-it": "^13.0.1",
42
44
  "markdown-it-container": "^3.0.0",
43
45
  "markdown-it-front-matter": "^0.2.3",
44
46
  "multer": "^1.4.5-lts.1",
47
+ "pdf-creator-node": "^2.3.5",
45
48
  "prompt": "^1.3.0",
46
49
  "stream": "0.0.2",
47
50
  "sync-request": "^6.1.0",
@@ -0,0 +1,23 @@
1
+ <div class="document-header">
2
+ <div class="hb-container-horizontal">
3
+ <div class="hb-center-v hb-container-expand">
4
+ <ul class="ps-0 nav-bar-nav-list noeffects after-fslash overflow-ellipsis">{{breadcrumbs}}</ul>
5
+ </div>
6
+ <div class="toolbar-right hb-center-v">
7
+ <a class="toolbar-action documentation-menu-popper">
8
+ <i class="bi bi-three-dots-vertical"></i>
9
+ </a>
10
+ </div>
11
+ </div>
12
+
13
+ <h1>{{title}}</h1>
14
+
15
+ <div class="hb-container-horizontal">
16
+ <div class="hb-center-v hb-container-expand">
17
+ <ul class="ps-0 nav-bar-nav-list noeffects after-bullets overflow-ellipsis text-light-2">
18
+ <li class="ps-0 mt-0 nav-bar-item">{{doc-type}}</li>
19
+ <li class="ps-0 mt-0 nav-bar-item">{{reading-time}} minutes to read</li>
20
+ </ul>
21
+ </div>
22
+ </div>
23
+ </div>