hdoc-tools 0.20.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/hdoc-build-db.js CHANGED
@@ -1,260 +1,262 @@
1
- (() => {
2
- const path = require("node:path");
3
- const hdoc_index = require(path.join(__dirname, "hdoc-db.js"));
4
- const database = require("better-sqlite3");
5
-
6
- const db_schema = {
7
- hdoc_index: [
8
- "resource_url UNINDEXED",
9
- "book_id",
10
- "book_audience UNINDEXED",
11
- "book_tags",
12
- "doc_title",
13
- "doc_content",
14
- "doc_preview UNINDEXED",
15
- "doc_family_id",
16
- "doc_md5_hash UNINDEXED",
17
- "doc_lastmod",
18
- ],
19
- hdoc_meta: [
20
- "resource_url",
21
- "book_id",
22
- "contributor_count INTEGER UNINDEXED",
23
- "edit_url UNINDEXED",
24
- "last_commit UNINDEXED",
25
- "pdf_size INTEGER UNINDEXED",
26
- ],
27
- hdoc_contributors: [
28
- "resource_url",
29
- "book_id",
30
- "login",
31
- "name",
32
- "avatar UNINDEXED",
33
- "url UNINDEXED",
34
- ],
35
- hdoc_redirects: [
36
- "resource_url",
37
- "location_url",
38
- "http_code INTEGER UNINDEXED",
39
- ],
40
- };
41
-
42
- exports.create_table = (db, table, cols, virtual, fts5) => {
43
- const table_created = hdoc_index.create_table(
44
- db,
45
- table,
46
- cols,
47
- virtual,
48
- fts5,
49
- );
50
- if (table_created !== null) {
51
- return `\nError creating table: ${table_created}`;
52
- }
53
- console.log(`\nTable created: ${table}`);
54
- return null;
55
- };
56
-
57
- exports.create_db = function (db_path, doc_id) {
58
- const response = {
59
- error: null,
60
- db: null,
61
- };
62
- console.log("\nPerforming SQlite index creation...");
63
- const db_name = path.join(db_path, doc_id, "index.db");
64
- response.db = new database(db_name);
65
- response.db.pragma('encoding="UTF-8"');
66
- console.log(`\nDatabase created: ${db_name}`);
67
-
68
- // Create tables
69
- for (const key in db_schema) {
70
- if (Object.hasOwn(db_schema, key)) {
71
- const virtual = key === "hdoc_index";
72
- const fts5 = key === "hdoc_index";
73
- const table_created_error = this.create_table(
74
- response.db,
75
- key,
76
- db_schema[key],
77
- virtual,
78
- fts5,
79
- );
80
- if (table_created_error !== null) {
81
- console.error(table_created_error);
82
- }
83
- }
84
- }
85
- return response;
86
- };
87
-
88
- exports.populate_redirects = (db, redirect_records, verbose = false) => {
89
- const response = {
90
- success: true,
91
- errors: [],
92
- index_success_count: 0,
93
- };
94
-
95
- for (let i = 0; i < redirect_records.length; i++) {
96
- const index_vals = [
97
- redirect_records[i].url,
98
- redirect_records[i].location ? redirect_records[i].location : "",
99
- redirect_records[i].code,
100
- ];
101
- const index_response = hdoc_index.insert_record(
102
- db,
103
- "hdoc_redirects",
104
- db_schema.hdoc_redirects,
105
- index_vals,
106
- );
107
- if (!index_response.success) {
108
- response.success = false;
109
- response.errors.push(
110
- `Redirect record creation failed - ${redirect_records[i].url}: ${index_response.error}`,
111
- );
112
- } else {
113
- response.index_success_count++;
114
- }
115
- }
116
- console.log(
117
- `\nRedirect Index Build Complete: ${response.index_success_count} document records created.`,
118
- );
119
- return response;
120
- };
121
-
122
- exports.populate_index = async (
123
- db,
124
- doc_id,
125
- book_config,
126
- index_records,
127
- verbose = false,
128
- ) => {
129
- const response = {
130
- success: false,
131
- index_success_count: 0,
132
- error: "",
133
- };
134
-
135
- if (!book_config.tags) book_config.tags = [];
136
-
137
- const indexPromises = [];
138
- for (let i = 0; i < index_records.length; i++) {
139
- indexPromises.push(index_records[i]);
140
- }
141
- let curr_file = "";
142
- await Promise.all(
143
- indexPromises.map(async (file) => {
144
- let index_path_name = file.relative_path.replaceAll("\\", "/");
145
- if (
146
- index_path_name.endsWith("/index.md") ||
147
- index_path_name.endsWith("/index.html") ||
148
- index_path_name.endsWith("/index.htm")
149
- ) {
150
- index_path_name = index_path_name.substring(
151
- 0,
152
- index_path_name.lastIndexOf("/"),
153
- );
154
- }
155
- index_path_name = `/${index_path_name.replace(path.extname(file.relative_path), "")}`;
156
-
157
- let index_response = {
158
- success: true,
159
- row_id: 0,
160
- };
161
- let index_content_path = index_path_name;
162
- if (file.index_html.id !== null)
163
- index_content_path += `#${file.index_html.id}`;
164
- if (!file.inline) {
165
- const index_vals = [
166
- index_content_path,
167
- doc_id,
168
- book_config.audience.join(","),
169
- book_config.tags.join(","),
170
- file.index_html.fm_props.title,
171
- file.index_html.text,
172
- file.index_html.preview,
173
- book_config.productFamily,
174
- file.md5,
175
- file.lastmod,
176
- ];
177
- index_response = hdoc_index.insert_record(
178
- db,
179
- "hdoc_index",
180
- db_schema.hdoc_index,
181
- index_vals,
182
- );
183
- }
184
- if (!index_response.success) {
185
- console.error(
186
- `Index record creation failed - ${doc_id}/${file.index_html.fm_props.title}: ${index_response.error}`,
187
- );
188
- } else {
189
- if (curr_file === index_path_name) return;
190
- curr_file = index_path_name;
191
- // Now add metadata
192
- const meta_vals = [
193
- index_path_name,
194
- doc_id,
195
- file.metadata.contributor_count,
196
- file.metadata.edit_url,
197
- file.metadata.last_commit,
198
- file.pdf_size,
199
- ];
200
- const meta_response = await hdoc_index.insert_record(
201
- db,
202
- "hdoc_meta",
203
- db_schema.hdoc_meta,
204
- meta_vals,
205
- );
206
- if (!meta_response.success) {
207
- console.error(
208
- `Index metadata record creation failed - ${doc_id}/${index_response.row_id}/${file.index_html.fm_props.title}: ${meta_response.error}`,
209
- );
210
- } else {
211
- if (verbose) {
212
- console.log(
213
- `Inserted index record ${index_response.row_id}: ${doc_id} - ${file.index_html.fm_props.title}`,
214
- );
215
- console.log(
216
- `Inserted index metadata record for index ID: ${meta_response.row_id}`,
217
- );
218
- }
219
-
220
- // Now add contributor records
221
- for (let j = 0; j < file.contributors.length; j++) {
222
- const contrib_vals = [
223
- index_path_name,
224
- doc_id,
225
- file.contributors[j].login,
226
- file.contributors[j].name,
227
- file.contributors[j].avatar_url,
228
- file.contributors[j].html_url,
229
- ];
230
- const cont_response = await hdoc_index.insert_record(
231
- db,
232
- "hdoc_contributors",
233
- db_schema.hdoc_contributors,
234
- contrib_vals,
235
- );
236
- if (!cont_response.success) {
237
- console.error(
238
- `Index document contributor record creation failed - ${doc_id}/${index_response.row_id}/${file.index_html.fm_props.title}: ${cont_response.error}`,
239
- );
240
- continue;
241
- }
242
- if (verbose) {
243
- console.log(
244
- `Inserted document contributor record ${cont_response.row_id}`,
245
- );
246
- }
247
- }
248
- response.index_success_count++;
249
- }
250
- }
251
- }),
252
- );
253
-
254
- response.success = true;
255
- console.log(
256
- `\nIndex Build Complete: ${response.index_success_count} document index records created.`,
257
- );
258
- return response;
259
- };
260
- })();
1
+ (() => {
2
+ const path = require("node:path");
3
+ const hdoc_index = require(path.join(__dirname, "hdoc-db.js"));
4
+ const database = require("better-sqlite3");
5
+
6
+ const db_schema = {
7
+ hdoc_index: [
8
+ "resource_url UNINDEXED",
9
+ "book_id",
10
+ "book_audience UNINDEXED",
11
+ "book_tags",
12
+ "doc_title",
13
+ "doc_content",
14
+ "doc_preview UNINDEXED",
15
+ "doc_family_id",
16
+ "doc_md5_hash UNINDEXED",
17
+ "doc_lastmod",
18
+ "doc_status",
19
+ ],
20
+ hdoc_meta: [
21
+ "resource_url",
22
+ "book_id",
23
+ "contributor_count INTEGER UNINDEXED",
24
+ "edit_url UNINDEXED",
25
+ "last_commit UNINDEXED",
26
+ "pdf_size INTEGER UNINDEXED",
27
+ ],
28
+ hdoc_contributors: [
29
+ "resource_url",
30
+ "book_id",
31
+ "login",
32
+ "name",
33
+ "avatar UNINDEXED",
34
+ "url UNINDEXED",
35
+ ],
36
+ hdoc_redirects: [
37
+ "resource_url",
38
+ "location_url",
39
+ "http_code INTEGER UNINDEXED",
40
+ ],
41
+ };
42
+
43
+ exports.create_table = (db, table, cols, virtual, fts5) => {
44
+ const table_created = hdoc_index.create_table(
45
+ db,
46
+ table,
47
+ cols,
48
+ virtual,
49
+ fts5,
50
+ );
51
+ if (table_created !== null) {
52
+ return `\nError creating table: ${table_created}`;
53
+ }
54
+ console.log(`\nTable created: ${table}`);
55
+ return null;
56
+ };
57
+
58
+ exports.create_db = function (db_path, doc_id) {
59
+ const response = {
60
+ error: null,
61
+ db: null,
62
+ };
63
+ console.log("\nPerforming SQlite index creation...");
64
+ const db_name = path.join(db_path, doc_id, "index.db");
65
+ response.db = new database(db_name);
66
+ response.db.pragma('encoding="UTF-8"');
67
+ console.log(`\nDatabase created: ${db_name}`);
68
+
69
+ // Create tables
70
+ for (const key in db_schema) {
71
+ if (Object.hasOwn(db_schema, key)) {
72
+ const virtual = key === "hdoc_index";
73
+ const fts5 = key === "hdoc_index";
74
+ const table_created_error = this.create_table(
75
+ response.db,
76
+ key,
77
+ db_schema[key],
78
+ virtual,
79
+ fts5,
80
+ );
81
+ if (table_created_error !== null) {
82
+ console.error(table_created_error);
83
+ }
84
+ }
85
+ }
86
+ return response;
87
+ };
88
+
89
+ exports.populate_redirects = (db, redirect_records, verbose = false) => {
90
+ const response = {
91
+ success: true,
92
+ errors: [],
93
+ index_success_count: 0,
94
+ };
95
+
96
+ for (let i = 0; i < redirect_records.length; i++) {
97
+ const index_vals = [
98
+ redirect_records[i].url,
99
+ redirect_records[i].location ? redirect_records[i].location : "",
100
+ redirect_records[i].code,
101
+ ];
102
+ const index_response = hdoc_index.insert_record(
103
+ db,
104
+ "hdoc_redirects",
105
+ db_schema.hdoc_redirects,
106
+ index_vals,
107
+ );
108
+ if (!index_response.success) {
109
+ response.success = false;
110
+ response.errors.push(
111
+ `Redirect record creation failed - ${redirect_records[i].url}: ${index_response.error}`,
112
+ );
113
+ } else {
114
+ response.index_success_count++;
115
+ }
116
+ }
117
+ console.log(
118
+ `\nRedirect Index Build Complete: ${response.index_success_count} document records created.`,
119
+ );
120
+ return response;
121
+ };
122
+
123
+ exports.populate_index = async (
124
+ db,
125
+ doc_id,
126
+ book_config,
127
+ index_records,
128
+ verbose = false,
129
+ ) => {
130
+ const response = {
131
+ success: false,
132
+ index_success_count: 0,
133
+ error: "",
134
+ };
135
+
136
+ if (!book_config.tags) book_config.tags = [];
137
+
138
+ const indexPromises = [];
139
+ for (let i = 0; i < index_records.length; i++) {
140
+ indexPromises.push(index_records[i]);
141
+ }
142
+ let curr_file = "";
143
+ await Promise.all(
144
+ indexPromises.map(async (file) => {
145
+ let index_path_name = file.relative_path.replaceAll("\\", "/");
146
+ if (
147
+ index_path_name.endsWith("/index.md") ||
148
+ index_path_name.endsWith("/index.html") ||
149
+ index_path_name.endsWith("/index.htm")
150
+ ) {
151
+ index_path_name = index_path_name.substring(
152
+ 0,
153
+ index_path_name.lastIndexOf("/"),
154
+ );
155
+ }
156
+ index_path_name = `/${index_path_name.replace(path.extname(file.relative_path), "")}`;
157
+
158
+ let index_response = {
159
+ success: true,
160
+ row_id: 0,
161
+ };
162
+ let index_content_path = index_path_name;
163
+ if (file.index_html.id !== null)
164
+ index_content_path += `#${file.index_html.id}`;
165
+ if (!file.inline) {
166
+ const index_vals = [
167
+ index_content_path,
168
+ doc_id,
169
+ book_config.audience.join(","),
170
+ book_config.tags.join(","),
171
+ file.index_html.fm_props.title,
172
+ file.index_html.text,
173
+ file.index_html.preview,
174
+ book_config.productFamily,
175
+ file.md5,
176
+ file.lastmod,
177
+ file.status,
178
+ ];
179
+ index_response = hdoc_index.insert_record(
180
+ db,
181
+ "hdoc_index",
182
+ db_schema.hdoc_index,
183
+ index_vals,
184
+ );
185
+ }
186
+ if (!index_response.success) {
187
+ console.error(
188
+ `Index record creation failed - ${doc_id}/${file.index_html.fm_props.title}: ${index_response.error}`,
189
+ );
190
+ } else {
191
+ if (curr_file === index_path_name) return;
192
+ curr_file = index_path_name;
193
+ // Now add metadata
194
+ const meta_vals = [
195
+ index_path_name,
196
+ doc_id,
197
+ file.metadata.contributor_count,
198
+ file.metadata.edit_url,
199
+ file.metadata.last_commit,
200
+ file.pdf_size,
201
+ ];
202
+ const meta_response = await hdoc_index.insert_record(
203
+ db,
204
+ "hdoc_meta",
205
+ db_schema.hdoc_meta,
206
+ meta_vals,
207
+ );
208
+ if (!meta_response.success) {
209
+ console.error(
210
+ `Index metadata record creation failed - ${doc_id}/${index_response.row_id}/${file.index_html.fm_props.title}: ${meta_response.error}`,
211
+ );
212
+ } else {
213
+ if (verbose) {
214
+ console.log(
215
+ `Inserted index record ${index_response.row_id}: ${doc_id} - ${file.index_html.fm_props.title}`,
216
+ );
217
+ console.log(
218
+ `Inserted index metadata record for index ID: ${meta_response.row_id}`,
219
+ );
220
+ }
221
+
222
+ // Now add contributor records
223
+ for (let j = 0; j < file.contributors.length; j++) {
224
+ const contrib_vals = [
225
+ index_path_name,
226
+ doc_id,
227
+ file.contributors[j].login,
228
+ file.contributors[j].name,
229
+ file.contributors[j].avatar_url,
230
+ file.contributors[j].html_url,
231
+ ];
232
+ const cont_response = await hdoc_index.insert_record(
233
+ db,
234
+ "hdoc_contributors",
235
+ db_schema.hdoc_contributors,
236
+ contrib_vals,
237
+ );
238
+ if (!cont_response.success) {
239
+ console.error(
240
+ `Index document contributor record creation failed - ${doc_id}/${index_response.row_id}/${file.index_html.fm_props.title}: ${cont_response.error}`,
241
+ );
242
+ continue;
243
+ }
244
+ if (verbose) {
245
+ console.log(
246
+ `Inserted document contributor record ${cont_response.row_id}`,
247
+ );
248
+ }
249
+ }
250
+ response.index_success_count++;
251
+ }
252
+ }
253
+ }),
254
+ );
255
+
256
+ response.success = true;
257
+ console.log(
258
+ `\nIndex Build Complete: ${response.index_success_count} document index records created.`,
259
+ );
260
+ return response;
261
+ };
262
+ })();
package/hdoc-build.js CHANGED
@@ -5,7 +5,6 @@
5
5
  const mdfm = require("markdown-it-front-matter");
6
6
  const path = require("node:path");
7
7
  const puppeteer = require("puppeteer");
8
- const URL = require("node:url").URL;
9
8
  const hdoc_validate = require(path.join(__dirname, "hdoc-validate.js"));
10
9
  const hdoc = require(path.join(__dirname, "hdoc-module.js"));
11
10
  const hdoc_build_db = require(path.join(__dirname, "hdoc-build-db.js"));
@@ -45,6 +44,7 @@
45
44
 
46
45
  const built_file_hashes = [];
47
46
  const css_templates = [];
47
+ const draft_links = [];
48
48
  const errors_filename = [];
49
49
  const index_records = [];
50
50
  const md_files = [];
@@ -119,9 +119,18 @@
119
119
 
120
120
  // Check if we have a frontmatter comment
121
121
  const fm_header = hdoc.getHTMLFrontmatterHeader(html_txt);
122
+
123
+ let rel_path = file_path.relativePath.replace(path.extname(file_path.relativePath), '');
124
+ if (rel_path.endsWith('/index')) rel_path = rel_path.substring(0, rel_path.length - 6);
125
+ const is_draft = draft_links.indexOf(rel_path) !== -1;
126
+
127
+ let fm_status = false;
122
128
  if (Object.keys(fm_header.fm_properties).length > 0) {
123
129
  existing_fm_headers = true;
124
130
 
131
+ if (fm_header.fm_properties?.status) {
132
+ fm_status = true;
133
+ }
125
134
  // We have some frontmatter headers, check if title is one of them
126
135
  let fm_title_found = false;
127
136
  if (
@@ -268,6 +277,14 @@
268
277
  value: doc_type,
269
278
  });
270
279
 
280
+ // Add status if we don't have one defined and the nav tree defines the document as draft
281
+ if (!fm_status && is_draft) {
282
+ fm_headers.push({
283
+ id: "status",
284
+ value: "draft"
285
+ });
286
+ }
287
+
271
288
  const metadata = {};
272
289
 
273
290
  // Remove the first <h1>title</h1> from the HTML as we'll add that in the document header
@@ -443,6 +460,7 @@
443
460
  md5: file_path.hash,
444
461
  lastmod: last_commit !== null ? last_commit : file_path.hb_lastmod,
445
462
  inline: inline_content,
463
+ status: index_data.fm_props.status ? index_data.fm_props.status : 'release',
446
464
  });
447
465
  }
448
466
 
@@ -506,7 +524,6 @@
506
524
  });
507
525
 
508
526
  // Tidy up ```json and ```xml code tags
509
-
510
527
  if (md_txt.includes("```json") || md_txt.includes("```xml"))
511
528
  md_txt = tidy_code_tags(md_txt, file_path.relativePath);
512
529
 
@@ -523,6 +540,11 @@
523
540
  let doc_title = "";
524
541
  let doc_type = "Article";
525
542
 
543
+ let rel_path = file_path.relativePath.replace(path.extname(file_path.relativePath), '');
544
+ if (rel_path.endsWith('/index')) rel_path = rel_path.substring(0, rel_path.length - 6);
545
+ const is_draft = draft_links.indexOf(rel_path) !== -1;
546
+ let fm_status = false;
547
+
526
548
  if (fm_content.length >= 0) {
527
549
  for (fm_prop of fm_content) {
528
550
  const fm_id = fm_prop.slice(0, fm_prop.indexOf(":"));
@@ -543,6 +565,9 @@
543
565
  fm_contains_title = true;
544
566
  doc_title = fm_val.trim();
545
567
  }
568
+ if (fm_id.trim() === "status") {
569
+ fm_status = true;
570
+ }
546
571
  if (fm_id.trim() === "type") {
547
572
  doc_type = fm_val.trim();
548
573
  }
@@ -563,6 +588,14 @@
563
588
  value: doc_type,
564
589
  });
565
590
 
591
+ // Add status if we don't have one defined and the nav tree defines the document as draft
592
+ if (!fm_status && is_draft) {
593
+ fm_headers.push({
594
+ id: "status",
595
+ value: "draft"
596
+ });
597
+ }
598
+
566
599
  // Does frontmatter tag contain a title property
567
600
  if (!fm_contains_title) {
568
601
  // Frontmatter tags don't contain a title property - go pull the first one from the html heading tags
@@ -791,7 +824,6 @@
791
824
  }
792
825
 
793
826
  const index_data = hdoc_index.transform_html_for_index(html_txt);
794
-
795
827
  for (section of index_data.sections) {
796
828
  index_records.push({
797
829
  relative_path: relative_path,
@@ -807,6 +839,7 @@
807
839
  md5: file_path.hash,
808
840
  lastmod: last_commit !== null ? last_commit : file_path.hb_lastmod,
809
841
  inline: inline_content,
842
+ status: index_data.fm_props.status ? index_data.fm_props.status : 'release',
810
843
  });
811
844
  }
812
845
 
@@ -1269,6 +1302,10 @@
1269
1302
  }
1270
1303
  console.log("Processing navigation breadcrumbs...");
1271
1304
  const bc_build = hdoc.build_breadcrumbs(hdocbook_config.navigation.items);
1305
+
1306
+ console.log("Getting list of draft links to exclude from the build...");
1307
+ draft_links.push(...hdoc.get_draft_links(hdocbook_config.navigation.items));
1308
+
1272
1309
  if (bc_build.errors.length > 0) {
1273
1310
  console.log("\r\n-----------------------");
1274
1311
  console.log(" Validation Output ");
@@ -1282,6 +1319,7 @@
1282
1319
  }
1283
1320
  bc = bc_build.bc;
1284
1321
  console.log("Processing content...");
1322
+
1285
1323
  // Get a list of MD files in work_path
1286
1324
  dree.scan(work_path, dreeOptions, build_file_callback);
1287
1325
 
@@ -1355,6 +1393,7 @@
1355
1393
  prods_supported,
1356
1394
  gen_exclude,
1357
1395
  redirects,
1396
+ draft_links,
1358
1397
  );
1359
1398
  if (!validation_success) {
1360
1399
  const end_time = Date.now();