hdoc-tools 0.9.29 → 0.9.30
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 +50 -47
- package/hdoc-build-pdf.js +19 -34
- package/hdoc-build.js +56 -16
- package/hdoc-db.js +1 -1
- package/hdoc-validate.js +32 -24
- package/package.json +1 -1
package/hdoc-build-db.js
CHANGED
@@ -79,68 +79,71 @@
|
|
79
79
|
|
80
80
|
if (!book_config.tags) book_config.tags = [];
|
81
81
|
|
82
|
+
let indexPromises = [];
|
82
83
|
for (let i = 0; i < index_records.length; i++) {
|
83
|
-
|
84
|
-
|
84
|
+
indexPromises.push(index_records[i]);
|
85
|
+
}
|
86
|
+
await Promise.all(indexPromises.map(async (file) => {
|
87
|
+
let index_path_name = file.relative_path.replace('\\', '/');
|
88
|
+
index_path_name = '/' + index_path_name.replace(path.extname(file.relative_path), '');
|
85
89
|
const index_vals = [
|
86
90
|
index_path_name,
|
87
91
|
doc_id,
|
88
92
|
book_config.audience.join(','),
|
89
93
|
book_config.tags.join(','),
|
90
|
-
|
91
|
-
|
92
|
-
|
94
|
+
file.index_html.fm_props.title,
|
95
|
+
file.index_html.text,
|
96
|
+
file.index_html.preview,
|
93
97
|
book_config.productFamily,
|
94
|
-
|
98
|
+
file.md5
|
95
99
|
];
|
96
|
-
const index_response =
|
100
|
+
const index_response = hdoc_index.insert_record(db, 'hdoc_index', db_schema.hdoc_index, index_vals);
|
97
101
|
if (!index_response.success) {
|
98
|
-
console.log(`Index record creation failed - ${doc_id}/${
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
// Now add metadata
|
103
|
-
const meta_vals = [
|
104
|
-
index_path_name,
|
105
|
-
doc_id,
|
106
|
-
index_records[i].metadata.contributor_count,
|
107
|
-
index_records[i].metadata.edit_url,
|
108
|
-
index_records[i].metadata.last_commit,
|
109
|
-
index_records[i].pdf_size
|
110
|
-
];
|
111
|
-
const meta_response = await hdoc_index.insert_record(db, 'hdoc_meta', db_schema.hdoc_meta, meta_vals);
|
112
|
-
if (!meta_response.success) {
|
113
|
-
console.log(`Index metadata record creation failed - ${doc_id}/${index_response.row_id}/${index_records[i].index_html.fm_props.title}: ${meta_response.error}`);
|
114
|
-
continue;
|
115
|
-
}
|
116
|
-
if (verbose) {
|
117
|
-
console.log(`Inserted index record ${index_response.row_id}: ${doc_id} - ${index_records[i].index_html.fm_props.title}`);
|
118
|
-
console.log(`Inserted index metadata record for index ID: ${meta_response.row_id}`);
|
119
|
-
}
|
120
|
-
|
121
|
-
// Now add contributor records
|
122
|
-
for (let j = 0; j < index_records[i].contributors.length; j++) {
|
123
|
-
const contrib_vals = [
|
102
|
+
console.log(`Index record creation failed - ${doc_id}/${file.index_html.fm_props.title}: ${index_response.error}`);
|
103
|
+
} else {
|
104
|
+
// Now add metadata
|
105
|
+
const meta_vals = [
|
124
106
|
index_path_name,
|
125
107
|
doc_id,
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
108
|
+
file.metadata.contributor_count,
|
109
|
+
file.metadata.edit_url,
|
110
|
+
file.metadata.last_commit,
|
111
|
+
file.pdf_size
|
130
112
|
];
|
131
|
-
const
|
132
|
-
if (!
|
133
|
-
console.log(`Index
|
134
|
-
|
113
|
+
const meta_response = await hdoc_index.insert_record(db, 'hdoc_meta', db_schema.hdoc_meta, meta_vals);
|
114
|
+
if (!meta_response.success) {
|
115
|
+
console.log(`Index metadata record creation failed - ${doc_id}/${index_response.row_id}/${file.index_html.fm_props.title}: ${meta_response.error}`);
|
116
|
+
} else {
|
117
|
+
if (verbose) {
|
118
|
+
console.log(`Inserted index record ${index_response.row_id}: ${doc_id} - ${file.index_html.fm_props.title}`);
|
119
|
+
console.log(`Inserted index metadata record for index ID: ${meta_response.row_id}`);
|
120
|
+
}
|
121
|
+
|
122
|
+
// Now add contributor records
|
123
|
+
for (let j = 0; j < file.contributors.length; j++) {
|
124
|
+
const contrib_vals = [
|
125
|
+
index_path_name,
|
126
|
+
doc_id,
|
127
|
+
file.contributors[j].login,
|
128
|
+
file.contributors[j].name,
|
129
|
+
file.contributors[j].avatar_url,
|
130
|
+
file.contributors[j].html_url
|
131
|
+
];
|
132
|
+
const cont_response = await hdoc_index.insert_record(db, 'hdoc_contributors', db_schema.hdoc_contributors, contrib_vals);
|
133
|
+
if (!cont_response.success) {
|
134
|
+
console.log(`Index document contributor record creation failed - ${doc_id}/${index_response.row_id}/${file.index_html.fm_props.title}: ${cont_response.error}`);
|
135
|
+
continue;
|
136
|
+
}
|
137
|
+
if (verbose) {
|
138
|
+
console.log(`Inserted document contributor recordL ${cont_response.row_id}`);
|
139
|
+
}
|
140
|
+
}
|
141
|
+
response.index_success_count++;
|
135
142
|
}
|
136
|
-
if (verbose) {
|
137
|
-
console.log(`Inserted document contributor recordL ${cont_response.row_id}`);
|
138
|
-
}
|
139
143
|
}
|
140
144
|
|
141
|
-
|
142
|
-
|
143
|
-
}
|
145
|
+
}));
|
146
|
+
|
144
147
|
response.success = true;
|
145
148
|
console.log(`\nIndex Build Complete: ${response.index_success_count} document index records created.`);
|
146
149
|
return response;
|
package/hdoc-build-pdf.js
CHANGED
@@ -9,20 +9,10 @@
|
|
9
9
|
path = require('path'),
|
10
10
|
hdoc = require(path.join(__dirname, 'hdoc-module.js'));
|
11
11
|
|
12
|
-
|
13
|
-
extensions: ['css'],
|
14
|
-
normalize: true,
|
15
|
-
};
|
16
|
-
|
17
|
-
let css_files = [],
|
18
|
-
hb_logo = '',
|
12
|
+
let hb_logo = '',
|
19
13
|
footer = '',
|
20
14
|
header = '';
|
21
15
|
|
22
|
-
const file_callback = function (element) {
|
23
|
-
css_files.push(element.path);
|
24
|
-
};
|
25
|
-
|
26
16
|
const get_footer = function (template_path) {
|
27
17
|
let footer_content = null;
|
28
18
|
try {
|
@@ -109,9 +99,11 @@
|
|
109
99
|
return html_source;
|
110
100
|
};
|
111
101
|
|
112
|
-
exports.generate_pdf = async function (browser, pdf_template_path, pdf_template_content, book_config, html_source, target_file, verbose = false) {
|
113
|
-
if (verbose) console.log(`Generating PDF: ${target_file}`);
|
102
|
+
exports.generate_pdf = async function (browser, pdf_template_path, pdf_template_content, book_config, html_source, target_file, css_templates, verbose = false) {
|
114
103
|
let pdf_size = 0;
|
104
|
+
|
105
|
+
//dree.scan(pdf_template_path, dree_options_css, file_callback_css);
|
106
|
+
|
115
107
|
// Cache footer
|
116
108
|
if (footer === '') footer = get_footer(pdf_template_path);
|
117
109
|
|
@@ -135,37 +127,28 @@
|
|
135
127
|
|
136
128
|
html_source = pdf_template_content.replace('{{book_title}}', book_config.title).replace('{{document_content}}', html_source);
|
137
129
|
|
138
|
-
// Create a new page
|
139
130
|
const page = await browser.newPage();
|
140
131
|
|
132
|
+
// To reflect CSS used for screens instead of print
|
133
|
+
await page.emulateMediaType('screen');
|
134
|
+
|
141
135
|
// Set HTML content from HTML source
|
142
136
|
await page.setContent(html_source, {
|
143
137
|
waitUntil: 'domcontentloaded'
|
144
138
|
});
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
for (let i = 0; i < css_files.length; i++) {
|
155
|
-
await page.addStyleTag({
|
156
|
-
path: css_files[i]
|
157
|
-
});
|
139
|
+
for (let i = 0; i < css_templates.length; i++) {
|
140
|
+
try {
|
141
|
+
await page.addStyleTag({
|
142
|
+
content: css_templates[i]
|
143
|
+
});
|
144
|
+
} catch (e) {
|
145
|
+
console.log(`Error applying template for [${target_file}]: ${e}`);
|
146
|
+
}
|
158
147
|
}
|
159
148
|
|
160
149
|
try {
|
161
150
|
const pdf_gen = await page.pdf({
|
162
151
|
path: target_file,
|
163
|
-
margin: {
|
164
|
-
top: '30px',
|
165
|
-
right: '35px',
|
166
|
-
bottom: '80px',
|
167
|
-
left: '35px'
|
168
|
-
},
|
169
152
|
printBackground: true,
|
170
153
|
format: 'A4',
|
171
154
|
displayHeaderFooter: true,
|
@@ -178,7 +161,9 @@
|
|
178
161
|
left: "30px"
|
179
162
|
}
|
180
163
|
});
|
181
|
-
|
164
|
+
let currdate = new Date;
|
165
|
+
let datetime = currdate.toISOString();
|
166
|
+
if (verbose) console.log(`[${datetime}] PDF generation success: ${target_file}`);
|
182
167
|
|
183
168
|
pdf_size = pdf_gen.byteLength;
|
184
169
|
} catch (err) {
|
package/hdoc-build.js
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
const { files } = require('jszip');
|
2
|
+
|
1
3
|
(function () {
|
2
4
|
'use strict';
|
3
5
|
|
@@ -33,6 +35,7 @@
|
|
33
35
|
conversion_attempted = 0,
|
34
36
|
conversion_success = 0,
|
35
37
|
conversion_failed = 0,
|
38
|
+
css_templates = [],
|
36
39
|
doc_header_template = '',
|
37
40
|
doc_header_template_non_git = '',
|
38
41
|
pdf_created = 0,
|
@@ -54,6 +57,7 @@
|
|
54
57
|
work_path_content = '',
|
55
58
|
verbose = false;
|
56
59
|
|
60
|
+
|
57
61
|
const pdf_path_excluded = function (relative_path) {
|
58
62
|
if (!hdocbook_project.pdfGeneration || hdocbook_project.pdfGeneration.exclude_paths === undefined) {
|
59
63
|
return false;
|
@@ -241,7 +245,7 @@
|
|
241
245
|
|
242
246
|
// Generate PDF file from HTML
|
243
247
|
const pdf_file_path = file_path.path.replace(path.extname(file_path.path), '.pdf');
|
244
|
-
pdf_size = await hdoc_build_pdf.generate_pdf(browser, pdf_template_path, pdf_template, hdocbook_config, pdf_txt, pdf_file_path, verbose);
|
248
|
+
pdf_size = await hdoc_build_pdf.generate_pdf(browser, pdf_template_path, pdf_template, hdocbook_config, pdf_txt, pdf_file_path, css_templates, verbose);
|
245
249
|
}
|
246
250
|
if (pdf_size > 0) pdf_created++;
|
247
251
|
|
@@ -452,7 +456,7 @@
|
|
452
456
|
|
453
457
|
// Generate PDF file from HTML
|
454
458
|
const pdf_file_path = file_path.path.replace(path.extname(file_path.path), '.pdf');
|
455
|
-
pdf_size = await hdoc_build_pdf.generate_pdf(browser, pdf_template_path, pdf_template, hdocbook_config, pdf_txt, pdf_file_path, verbose);
|
459
|
+
pdf_size = await hdoc_build_pdf.generate_pdf(browser, pdf_template_path, pdf_template, hdocbook_config, pdf_txt, pdf_file_path, css_templates, verbose);
|
456
460
|
}
|
457
461
|
if (pdf_size > 0) pdf_created++;
|
458
462
|
html_txt = `${fm_header}\n${doc_header}\n${html_txt}`;
|
@@ -606,7 +610,9 @@
|
|
606
610
|
if (!validate && hdocbook_project.pdfGeneration !== undefined && hdocbook_project.pdfGeneration.enable !== undefined) {
|
607
611
|
pdf_enable = hdocbook_project.pdfGeneration.enable;
|
608
612
|
}
|
609
|
-
|
613
|
+
|
614
|
+
console.log(`Loading hdocbook config...`);
|
615
|
+
|
610
616
|
const book_path = path.join(source_path, doc_id),
|
611
617
|
hdocbook_path = path.join(book_path, 'hdocbook.json'),
|
612
618
|
work_path = path.join(source_path, '_work'),
|
@@ -624,6 +630,20 @@
|
|
624
630
|
|
625
631
|
if (hdocbook_config.publicSource.endsWith('.git')) hdocbook_config.publicSource = hdocbook_config.publicSource.substring(0, hdocbook_config.publicSource.length - 4);
|
626
632
|
|
633
|
+
console.log('Caching CSS for PDF generation...');
|
634
|
+
const css_files = [
|
635
|
+
path.join(pdf_template_path, 'css', 'custom-block.css'),
|
636
|
+
path.join(pdf_template_path, 'css', 'hdocs-pdf.css'),
|
637
|
+
path.join(pdf_template_path, 'css', 'vars.css')
|
638
|
+
];
|
639
|
+
for (let i = 0; i < css_files.length; i++) {
|
640
|
+
try {
|
641
|
+
css_templates.push(fs.readFileSync(css_files[i], 'utf8'));
|
642
|
+
} catch (e) {
|
643
|
+
console.log(`Error reading file [${css_files[i]}]: ${e}`);
|
644
|
+
}
|
645
|
+
}
|
646
|
+
|
627
647
|
console.log(`Building: ${doc_id} v${hdocbook_config.version}...\n`);
|
628
648
|
|
629
649
|
// Make _work folder to copy everything into
|
@@ -637,6 +657,7 @@
|
|
637
657
|
fs.mkdirSync(work_path);
|
638
658
|
|
639
659
|
// Copy files from book into _work-doc_id folder
|
660
|
+
console.log(`Copying content into work folder...`);
|
640
661
|
try {
|
641
662
|
fs.copySync(path.join(source_path, doc_id), work_path_content);
|
642
663
|
} catch (e) {
|
@@ -644,7 +665,9 @@
|
|
644
665
|
process.exit(1);
|
645
666
|
}
|
646
667
|
|
647
|
-
//
|
668
|
+
// Create MD5 hash of content before build
|
669
|
+
console.log(`Creating Hash...`);
|
670
|
+
|
648
671
|
dree.scan(work_path_content, md5DreeOptions, hash_callback);
|
649
672
|
let concat_hash = '|';
|
650
673
|
for (let i = 0; i < built_file_hashes.length; i++) {
|
@@ -660,13 +683,14 @@
|
|
660
683
|
const checksum_path = path.join(work_path_content, 'checksum.md5');
|
661
684
|
try {
|
662
685
|
fs.writeFileSync(checksum_path, hash);
|
663
|
-
console.log('
|
686
|
+
console.log('Hash file creation success:', checksum_path);
|
664
687
|
} catch (e) {
|
665
688
|
console.log('\nError creating', checksum_path, ':', e);
|
666
689
|
process.exit(1);
|
667
690
|
}
|
668
691
|
|
669
692
|
// Load document header templates
|
693
|
+
console.log(`Loading templates...`);
|
670
694
|
try {
|
671
695
|
doc_header_template = fs.readFileSync(doc_header_template_path, 'utf8');
|
672
696
|
doc_header_template_non_git = fs.readFileSync(non_git_doc_header_template_path, 'utf8');
|
@@ -686,27 +710,36 @@
|
|
686
710
|
process.exit(1);
|
687
711
|
}
|
688
712
|
}
|
689
|
-
console.log(
|
713
|
+
console.log(`Processing navigation breadcrumbs...`);
|
690
714
|
bc = hdoc.build_breadcrumbs(hdocbook_config.navigation.items);
|
691
715
|
|
692
|
-
console.log(
|
716
|
+
console.log(`Processing content...`);
|
693
717
|
// Get a list of MD files in work_path
|
694
718
|
dree.scan(work_path, dreeOptions, build_file_callback);
|
695
719
|
|
696
720
|
if (pdf_enable) {
|
697
|
-
// Create a Chromium browser instance
|
721
|
+
// Create a Chromium browser instance generate PDFs with
|
698
722
|
browser = await puppeteer.launch({headless: 'new'});
|
699
723
|
}
|
700
724
|
|
701
725
|
// Work through MD files and convert to HTML
|
726
|
+
let mdPromiseArray = [];
|
702
727
|
for (let i = 0; i < md_files.length; i++) {
|
703
|
-
|
728
|
+
mdPromiseArray.push(md_files[i]);
|
704
729
|
}
|
730
|
+
await Promise.all(mdPromiseArray.map(async (file) => {
|
731
|
+
await transform_markdown_and_save_html(file);
|
732
|
+
}));
|
705
733
|
|
706
734
|
// Work through Static HTML files and add Frontmatter tags
|
735
|
+
let htmlPromiseArray = [];
|
707
736
|
for (let i = 0; i < static_html_files.length; i++) {
|
708
|
-
|
737
|
+
htmlPromiseArray.push(static_html_files[i]);
|
709
738
|
}
|
739
|
+
await Promise.all(htmlPromiseArray.map(async (file) => {
|
740
|
+
await transform_static_html(file);
|
741
|
+
}));
|
742
|
+
|
710
743
|
|
711
744
|
if (pdf_enable) {
|
712
745
|
// Close the Chromium browser instance
|
@@ -734,14 +767,17 @@
|
|
734
767
|
}
|
735
768
|
|
736
769
|
// Delete markdown files
|
770
|
+
console.log(`Performing Markdown Cleanup`);
|
771
|
+
|
772
|
+
let filePromiseArray = [];
|
737
773
|
for (let i = 0; i < md_files_delete.length; i++) {
|
738
|
-
|
739
|
-
try {
|
740
|
-
fs.unlinkSync(md_files_delete[i]);
|
741
|
-
} catch (e) {
|
742
|
-
console.log(`Error deleting ${md_files_delete[i]}: ${e}`);
|
743
|
-
}
|
774
|
+
filePromiseArray.push(md_files_delete[i]);
|
744
775
|
}
|
776
|
+
await Promise.all(filePromiseArray.map(async (file) => {
|
777
|
+
fs.unlink(file, (err => {
|
778
|
+
if (err) console.log(`Error deleting ${file}: ${e}`);
|
779
|
+
}));
|
780
|
+
}));
|
745
781
|
|
746
782
|
// Add book read timing to the hdocbook.json
|
747
783
|
hdocbook_config.readingTime = Math.ceil(book_read_time + ((book_read_time / 100) * 10));
|
@@ -756,6 +792,7 @@
|
|
756
792
|
|
757
793
|
// Build the index
|
758
794
|
// Create the DB and tables
|
795
|
+
console.log(`Building the Index`);
|
759
796
|
let db = hdoc_build_db.create_db(work_path, doc_id);
|
760
797
|
if (db.error && db.error !== null) {
|
761
798
|
console.log(db.error);
|
@@ -767,6 +804,9 @@
|
|
767
804
|
console.log(index.error);
|
768
805
|
process.exit(1);
|
769
806
|
}
|
807
|
+
if (verbose) {
|
808
|
+
console.log(`Index Build Complete`);
|
809
|
+
}
|
770
810
|
|
771
811
|
if (!validate) {
|
772
812
|
try {
|
package/hdoc-db.js
CHANGED
package/hdoc-validate.js
CHANGED
@@ -405,51 +405,59 @@
|
|
405
405
|
|
406
406
|
// Do spellchecking on markdown files
|
407
407
|
let md_files_spellchecked = {};
|
408
|
+
let mdPromiseArray = [];
|
408
409
|
for (let i = 0; i < md_to_validate.length; i++) {
|
409
|
-
|
410
|
-
errors[md_to_validate[i].relativePath] = [];
|
411
|
-
messages[md_to_validate[i].relativePath] = [];
|
412
|
-
warnings[md_to_validate[i].relativePath] = [];
|
413
|
-
|
414
|
-
await spellcheckContent(md_to_validate[i], exclude_spellcheck);
|
415
|
-
md_files_spellchecked[md_to_validate[i].relativePath.replace('.' + md_to_validate[i].extension, '')] = true;
|
410
|
+
mdPromiseArray.push(md_to_validate[i]);
|
416
411
|
}
|
412
|
+
await Promise.all(mdPromiseArray.map(async (file) => {
|
413
|
+
//await transform_markdown_and_save_html(file);
|
414
|
+
// Initiate maps for errors and verbose messages for markdown file
|
415
|
+
errors[file.relativePath] = [];
|
416
|
+
messages[file.relativePath] = [];
|
417
|
+
warnings[file.relativePath] = [];
|
418
|
+
|
419
|
+
await spellcheckContent(file, exclude_spellcheck);
|
420
|
+
md_files_spellchecked[file.relativePath.replace('.' + file.extension, '')] = true;
|
421
|
+
}));
|
417
422
|
|
418
423
|
// Perform rest of validation against HTML files
|
419
424
|
let listContent = '';
|
425
|
+
let htmlPromiseArray = [];
|
420
426
|
for (let i = 0; i < html_to_validate.length; i++) {
|
421
|
-
|
427
|
+
htmlPromiseArray.push(html_to_validate[i]);
|
428
|
+
}
|
429
|
+
await Promise.all(mdPromiseArray.map(async (file) => {
|
422
430
|
// Initiate maps for errors and verbose messages for HTML file
|
423
|
-
errors[
|
424
|
-
messages[
|
425
|
-
warnings[
|
431
|
+
errors[file.relativePath] = [];
|
432
|
+
messages[file.relativePath] = [];
|
433
|
+
warnings[file.relativePath] = [];
|
426
434
|
|
427
435
|
// Check for British spellings in static HTML content
|
428
|
-
if (!md_files_spellchecked[
|
429
|
-
await spellcheckContent(
|
436
|
+
if (!md_files_spellchecked[file.relativePath.replace('.' + file.extension, '')]) {
|
437
|
+
await spellcheckContent(file, exclude_spellcheck);
|
430
438
|
}
|
431
439
|
|
432
|
-
const links = getLinks(
|
440
|
+
const links = getLinks(file);
|
433
441
|
if (links.href.length === 0) {
|
434
|
-
messages[
|
442
|
+
messages[file.relativePath].push('No links found in file');
|
435
443
|
} else {
|
436
|
-
await checkLinks(source_path,
|
444
|
+
await checkLinks(source_path, file, links.href, hdocbook_config);
|
437
445
|
}
|
438
446
|
if (links.img.length === 0) {
|
439
|
-
messages[
|
447
|
+
messages[file.relativePath].push('No images found in file');
|
440
448
|
} else {
|
441
|
-
await checkImages(source_path,
|
449
|
+
await checkImages(source_path, file, links.img);
|
442
450
|
}
|
443
451
|
|
444
452
|
// Check for multiple H1 tags
|
445
|
-
await checkTags(
|
453
|
+
await checkTags(file);
|
446
454
|
|
447
455
|
// Build list content for Google
|
448
|
-
listContent += `/${
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
456
|
+
listContent += `/${file.relativePath.replace(path.extname(file.relativePath), '')}`;
|
457
|
+
listContent += '\r\n';
|
458
|
+
}));
|
459
|
+
|
460
|
+
|
453
461
|
try {
|
454
462
|
// Write list
|
455
463
|
const listFile = path.join(source_path, doc_id, 'links.txt');
|