hdoc-tools 0.9.29 → 0.9.31
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 +54 -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
@@ -33,6 +33,7 @@
|
|
33
33
|
conversion_attempted = 0,
|
34
34
|
conversion_success = 0,
|
35
35
|
conversion_failed = 0,
|
36
|
+
css_templates = [],
|
36
37
|
doc_header_template = '',
|
37
38
|
doc_header_template_non_git = '',
|
38
39
|
pdf_created = 0,
|
@@ -54,6 +55,7 @@
|
|
54
55
|
work_path_content = '',
|
55
56
|
verbose = false;
|
56
57
|
|
58
|
+
|
57
59
|
const pdf_path_excluded = function (relative_path) {
|
58
60
|
if (!hdocbook_project.pdfGeneration || hdocbook_project.pdfGeneration.exclude_paths === undefined) {
|
59
61
|
return false;
|
@@ -241,7 +243,7 @@
|
|
241
243
|
|
242
244
|
// Generate PDF file from HTML
|
243
245
|
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);
|
246
|
+
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
247
|
}
|
246
248
|
if (pdf_size > 0) pdf_created++;
|
247
249
|
|
@@ -452,7 +454,7 @@
|
|
452
454
|
|
453
455
|
// Generate PDF file from HTML
|
454
456
|
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);
|
457
|
+
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
458
|
}
|
457
459
|
if (pdf_size > 0) pdf_created++;
|
458
460
|
html_txt = `${fm_header}\n${doc_header}\n${html_txt}`;
|
@@ -606,7 +608,9 @@
|
|
606
608
|
if (!validate && hdocbook_project.pdfGeneration !== undefined && hdocbook_project.pdfGeneration.enable !== undefined) {
|
607
609
|
pdf_enable = hdocbook_project.pdfGeneration.enable;
|
608
610
|
}
|
609
|
-
|
611
|
+
|
612
|
+
console.log(`Loading hdocbook config...`);
|
613
|
+
|
610
614
|
const book_path = path.join(source_path, doc_id),
|
611
615
|
hdocbook_path = path.join(book_path, 'hdocbook.json'),
|
612
616
|
work_path = path.join(source_path, '_work'),
|
@@ -624,6 +628,20 @@
|
|
624
628
|
|
625
629
|
if (hdocbook_config.publicSource.endsWith('.git')) hdocbook_config.publicSource = hdocbook_config.publicSource.substring(0, hdocbook_config.publicSource.length - 4);
|
626
630
|
|
631
|
+
console.log('Caching CSS for PDF generation...');
|
632
|
+
const css_files = [
|
633
|
+
path.join(pdf_template_path, 'css', 'custom-block.css'),
|
634
|
+
path.join(pdf_template_path, 'css', 'hdocs-pdf.css'),
|
635
|
+
path.join(pdf_template_path, 'css', 'vars.css')
|
636
|
+
];
|
637
|
+
for (let i = 0; i < css_files.length; i++) {
|
638
|
+
try {
|
639
|
+
css_templates.push(fs.readFileSync(css_files[i], 'utf8'));
|
640
|
+
} catch (e) {
|
641
|
+
console.log(`Error reading file [${css_files[i]}]: ${e}`);
|
642
|
+
}
|
643
|
+
}
|
644
|
+
|
627
645
|
console.log(`Building: ${doc_id} v${hdocbook_config.version}...\n`);
|
628
646
|
|
629
647
|
// Make _work folder to copy everything into
|
@@ -637,6 +655,7 @@
|
|
637
655
|
fs.mkdirSync(work_path);
|
638
656
|
|
639
657
|
// Copy files from book into _work-doc_id folder
|
658
|
+
console.log(`Copying content into work folder...`);
|
640
659
|
try {
|
641
660
|
fs.copySync(path.join(source_path, doc_id), work_path_content);
|
642
661
|
} catch (e) {
|
@@ -644,7 +663,9 @@
|
|
644
663
|
process.exit(1);
|
645
664
|
}
|
646
665
|
|
647
|
-
//
|
666
|
+
// Create MD5 hash of content before build
|
667
|
+
console.log(`Creating Hash...`);
|
668
|
+
|
648
669
|
dree.scan(work_path_content, md5DreeOptions, hash_callback);
|
649
670
|
let concat_hash = '|';
|
650
671
|
for (let i = 0; i < built_file_hashes.length; i++) {
|
@@ -660,13 +681,14 @@
|
|
660
681
|
const checksum_path = path.join(work_path_content, 'checksum.md5');
|
661
682
|
try {
|
662
683
|
fs.writeFileSync(checksum_path, hash);
|
663
|
-
console.log('
|
684
|
+
console.log('Hash file creation success:', checksum_path);
|
664
685
|
} catch (e) {
|
665
686
|
console.log('\nError creating', checksum_path, ':', e);
|
666
687
|
process.exit(1);
|
667
688
|
}
|
668
689
|
|
669
690
|
// Load document header templates
|
691
|
+
console.log(`Loading templates...`);
|
670
692
|
try {
|
671
693
|
doc_header_template = fs.readFileSync(doc_header_template_path, 'utf8');
|
672
694
|
doc_header_template_non_git = fs.readFileSync(non_git_doc_header_template_path, 'utf8');
|
@@ -686,27 +708,36 @@
|
|
686
708
|
process.exit(1);
|
687
709
|
}
|
688
710
|
}
|
689
|
-
console.log(
|
711
|
+
console.log(`Processing navigation breadcrumbs...`);
|
690
712
|
bc = hdoc.build_breadcrumbs(hdocbook_config.navigation.items);
|
691
713
|
|
692
|
-
console.log(
|
714
|
+
console.log(`Processing content...`);
|
693
715
|
// Get a list of MD files in work_path
|
694
716
|
dree.scan(work_path, dreeOptions, build_file_callback);
|
695
717
|
|
696
718
|
if (pdf_enable) {
|
697
|
-
// Create a Chromium browser instance
|
719
|
+
// Create a Chromium browser instance generate PDFs with
|
698
720
|
browser = await puppeteer.launch({headless: 'new'});
|
699
721
|
}
|
700
722
|
|
701
723
|
// Work through MD files and convert to HTML
|
724
|
+
let mdPromiseArray = [];
|
702
725
|
for (let i = 0; i < md_files.length; i++) {
|
703
|
-
|
726
|
+
mdPromiseArray.push(md_files[i]);
|
704
727
|
}
|
728
|
+
await Promise.all(mdPromiseArray.map(async (file) => {
|
729
|
+
await transform_markdown_and_save_html(file);
|
730
|
+
}));
|
705
731
|
|
706
732
|
// Work through Static HTML files and add Frontmatter tags
|
733
|
+
let htmlPromiseArray = [];
|
707
734
|
for (let i = 0; i < static_html_files.length; i++) {
|
708
|
-
|
735
|
+
htmlPromiseArray.push(static_html_files[i]);
|
709
736
|
}
|
737
|
+
await Promise.all(htmlPromiseArray.map(async (file) => {
|
738
|
+
await transform_static_html(file);
|
739
|
+
}));
|
740
|
+
|
710
741
|
|
711
742
|
if (pdf_enable) {
|
712
743
|
// Close the Chromium browser instance
|
@@ -734,14 +765,17 @@
|
|
734
765
|
}
|
735
766
|
|
736
767
|
// Delete markdown files
|
768
|
+
console.log(`Performing Markdown Cleanup`);
|
769
|
+
|
770
|
+
let filePromiseArray = [];
|
737
771
|
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
|
-
}
|
772
|
+
filePromiseArray.push(md_files_delete[i]);
|
744
773
|
}
|
774
|
+
await Promise.all(filePromiseArray.map(async (file) => {
|
775
|
+
fs.unlink(file, (err => {
|
776
|
+
if (err) console.log(`Error deleting ${file}: ${e}`);
|
777
|
+
}));
|
778
|
+
}));
|
745
779
|
|
746
780
|
// Add book read timing to the hdocbook.json
|
747
781
|
hdocbook_config.readingTime = Math.ceil(book_read_time + ((book_read_time / 100) * 10));
|
@@ -756,6 +790,7 @@
|
|
756
790
|
|
757
791
|
// Build the index
|
758
792
|
// Create the DB and tables
|
793
|
+
console.log(`Building the Index`);
|
759
794
|
let db = hdoc_build_db.create_db(work_path, doc_id);
|
760
795
|
if (db.error && db.error !== null) {
|
761
796
|
console.log(db.error);
|
@@ -767,6 +802,9 @@
|
|
767
802
|
console.log(index.error);
|
768
803
|
process.exit(1);
|
769
804
|
}
|
805
|
+
if (verbose) {
|
806
|
+
console.log(`Index Build Complete`);
|
807
|
+
}
|
770
808
|
|
771
809
|
if (!validate) {
|
772
810
|
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');
|