hdoc-tools 0.7.11 → 0.7.13

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.
package/hdoc-build.js CHANGED
@@ -4,7 +4,8 @@
4
4
  const fs = require('fs-extra'),
5
5
  path = require('path'),
6
6
  dree = require('dree'),
7
- zipper = require('zip-local');
7
+ zipper = require('zip-local'),
8
+ validate = require(path.join(__dirname, 'hdoc-validate.js'));
8
9
 
9
10
  let conversion_attempted = 0,
10
11
  conversion_success = 0,
@@ -47,7 +48,7 @@
47
48
  return false;
48
49
  }
49
50
 
50
- // File callback for scan
51
+ // File callbacks for scans
51
52
  const fileCallback = function (element) {
52
53
  md_files.push(element.path);
53
54
  };
@@ -58,13 +59,13 @@
58
59
  extensions: ['md'],
59
60
  hash: false,
60
61
  normalize: true,
61
- size: true,
62
- sizeInBytes: true,
62
+ size: false,
63
+ sizeInBytes: false,
63
64
  stat: false,
64
65
  symbolicLinks: false
65
66
  };
66
67
 
67
- exports.run = function (source_path, md) {
68
+ exports.run = function (source_path, md, verbose) {
68
69
  // GERRY: The purpose of this function is to create a zip file containing the hdocbook content,
69
70
  // * Create a _work folder
70
71
  // * copy the hdocbook content to the work folder
@@ -80,14 +81,14 @@
80
81
 
81
82
  // Load the hdocbook-project.json file to get the docId
82
83
  // use the docId to get the book config
83
- const hdocbook_project_config_path = path.join(source_path, 'hdocbook-project.json'),
84
- hdocbook_project = require(hdocbook_project_config_path);
84
+ const hdocbook_project_config_path = path.join(source_path, 'hdocbook-project.json'),
85
+ hdocbook_project = require(hdocbook_project_config_path);
85
86
 
86
87
  docId = hdocbook_project.docId;
87
88
 
88
- const book_path = path.join(source_path, docId),
89
- hdocbook_path = path.join(book_path, 'hdocbook.json'),
90
- hdocbook_config = require(hdocbook_path);
89
+ const book_path = path.join(source_path, docId),
90
+ hdocbook_path = path.join(book_path, 'hdocbook.json'),
91
+ hdocbook_config = require(hdocbook_path);
91
92
 
92
93
  console.log(`Building: ${docId} v${hdocbook_config.version}...\r\n`);
93
94
 
@@ -105,10 +106,6 @@
105
106
  // Copy files from book into _work-docId folder
106
107
  try {
107
108
  fs.copySync(path.join(source_path, docId), path.join(work_path, docId));
108
- //fs.copyFileSync(path.join(source_path, 'hdocbook-project.json'), path.join(work_path, 'hdocbook-project.json'));
109
- //fs.copyFileSync(path.join(source_path, 'LICENSE'), path.join(work_path, 'LICENSE'));
110
- //fs.copyFileSync(path.join(source_path, 'README.md'), path.join(work_path, 'README.md'));
111
- //fs.copyFileSync(path.join(source_path, 'package.json'), path.join(work_path, 'package.json'));
112
109
  } catch (e) {
113
110
  console.error('Error copying from source_path:\r\n', e);
114
111
  process.exit(1);
@@ -116,6 +113,7 @@
116
113
 
117
114
  // Get a list of MD files in work_path
118
115
  dree.scan(work_path, dreeOptions, fileCallback);
116
+
119
117
  // Work through MD files and convert to HTML
120
118
  md_files.forEach(function (md_file) {
121
119
  transform_markdown_and_save_html(md_file, md);
@@ -124,11 +122,16 @@
124
122
  console.log(`Successfully converted to HTML: ${conversion_success}`);
125
123
  console.log(` Failed to convert: ${conversion_failed}`);
126
124
 
125
+ console.log(`\r\nValidating paths in generated HTML files`);
126
+ const validation_success = validate.run(work_path, verbose);
127
+ if (!validation_success) {
128
+ process.exit(1);
129
+ }
130
+
127
131
  const zip_path = path.join(work_path, docId + '.zip');
128
132
  zipper.sync.zip(path.join(work_path, docId)).compress().save(zip_path);
129
133
 
130
- console.log(` ZIP Creation Success: ${zip_path}\r\n`);
134
+ console.log(`ZIP Creation Success: ${zip_path}\r\n`);
131
135
  console.log('Build Complete\r\n');
132
-
133
136
  };
134
137
  })();
@@ -0,0 +1,147 @@
1
+ const parseLinkDestination = require('markdown-it/lib/helpers/parse_link_destination');
2
+
3
+ (function () {
4
+ 'use strict';
5
+
6
+ const cheerio = require('cheerio'),
7
+ dree = require('dree'),
8
+ fs = require('fs'),
9
+ path = require('path'),
10
+ URL = require("url").URL;
11
+
12
+ let errors = {},
13
+ messages = {},
14
+ errorcount = 0,
15
+ filecount = 0;
16
+
17
+ const stringIsAValidUrl = (s) => {
18
+ try {
19
+ new URL(s);
20
+ return true;
21
+ } catch (err) {
22
+ return false;
23
+ }
24
+ };
25
+
26
+ const checkLinks = function (source_path, htmlFile, links) {
27
+ for (let i = 0; i < links.length; i++) {
28
+
29
+ // Validate that link is a valid URL first
30
+ if (!stringIsAValidUrl(links[i])) {
31
+
32
+ // Could be a relative path, check
33
+ const fileExists = doesFileExist(source_path, htmlFile, links[i]);
34
+ if (!fileExists) {
35
+ errorcount++;
36
+ }
37
+ } else {
38
+ messages[htmlFile.relativePath].push(`Link is valid External URL: ${links[i]}`);
39
+ }
40
+ }
41
+ };
42
+
43
+ const dreeOptions = {
44
+ descendants: true,
45
+ depth: 10,
46
+ extensions: ['htm', 'html'],
47
+ hash: false,
48
+ normalize: true,
49
+ size: false,
50
+ sizeInBytes: false,
51
+ stat: false,
52
+ symbolicLinks: false
53
+ };
54
+
55
+ let htmlFiles = [];
56
+
57
+ // File callbacks for html file scan
58
+ const fileCallback = function (element) {
59
+ filecount++;
60
+ htmlFiles.push(element);
61
+ };
62
+
63
+ const doesFileExist = function (source_path, html_path, relative_path) {
64
+ // Remove explicit anchor links
65
+ let file_path = path.join(source_path, relative_path.split('#')[0]);
66
+
67
+ if (!fs.existsSync(file_path) && !fs.existsSync(file_path + '.htm') && !fs.existsSync(file_path + '.html')) {
68
+ errors[html_path.relativePath].push(`Book resource does not exist: ${file_path}`);
69
+ return false;
70
+ } else {
71
+ messages[html_path.relativePath].push(`Book resource exists: ${file_path}`);
72
+ }
73
+ return true;
74
+ };
75
+
76
+ // Takes a dree element, returns an object with a pair of arrays
77
+ const getLinks = function (file) {
78
+ messages[file.relativePath].push('Parsing HTML file');
79
+ const htmlBody = fs.readFileSync(file.path, 'utf8');
80
+ let links = [];
81
+ const $ = cheerio.load(htmlBody);
82
+ const hrefs = $('a').map(function (i) {
83
+ return $(this).attr('href');
84
+ }).get();
85
+ const srcs = $('img').map(function (i) {
86
+ return $(this).attr('src');
87
+ }).get();
88
+ links.push(...hrefs);
89
+ links.push(...srcs);
90
+ return links;
91
+ };
92
+
93
+
94
+ exports.run = function (source_path, verbose) {
95
+ // Get a list of HTML files in source_path
96
+ dree.scan(source_path, dreeOptions, fileCallback);
97
+
98
+ for (let i = 0; i < htmlFiles.length; i++) {
99
+
100
+ // Initiate maps for errors and verbose messages for HTML file
101
+ errors[htmlFiles[i].relativePath] = [];
102
+ messages[htmlFiles[i].relativePath] = [];
103
+
104
+ const links = getLinks(htmlFiles[i]);
105
+ if (links.length === 0) {
106
+ messages[htmlFiles[i].relativePath].push('No links found in file');
107
+ } else {
108
+ checkLinks(source_path, htmlFiles[i], links);
109
+ }
110
+
111
+ }
112
+ if (errorcount === 0) {
113
+ console.log('\r\n---------------');
114
+ console.log(' No Errors ');
115
+ console.log('---------------\r\n');
116
+ } else {
117
+ console.log('\r\n------------');
118
+ console.log(' Errors ');
119
+ console.log('------------');
120
+
121
+ for (const key in errors) {
122
+ if (errors.hasOwnProperty(key) && errors[key].length > 0) {
123
+ console.log(`\r\n${errors[key].length} error(s) in ${key}`);
124
+ for (let i = 0; i < errors[key].length; i++) {
125
+ console.log(` - ${errors[key][i]}`);
126
+ }
127
+ }
128
+ }
129
+ }
130
+
131
+ if (verbose) {
132
+ console.log('\r\n-------------');
133
+ console.log(' Verbose ');
134
+ console.log('-------------');
135
+ for (const key in messages) {
136
+ if (messages.hasOwnProperty(key) && messages[key].length > 0) {
137
+ console.log(`\r\nMessage output for ${key}`);
138
+ for (let i = 0; i < messages[key].length; i++) {
139
+ console.log(` - ${messages[key][i]}`);
140
+ }
141
+ }
142
+ }
143
+ }
144
+ console.log(`\r\nValidation Errors Found: ${errorcount}\r\n`);
145
+ return errorcount === 0 ? true : false;
146
+ };
147
+ })();
package/hdoc.js CHANGED
@@ -94,7 +94,7 @@ const { createCipheriv } = require('crypto');
94
94
  server.run(ui_path, source_path, md);
95
95
  } else if (command == 'build') {
96
96
  const builder = require(path.join(__dirname, 'hdoc-build.js'));
97
- builder.run(source_path, md);
97
+ builder.run(source_path, md, verbose);
98
98
  } else if (command == 'stats') {
99
99
  const stats = require(path.join(__dirname, 'hdoc-stats.js'));
100
100
  stats.run(ui_path, source_path, md, verbose);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hdoc-tools",
3
- "version": "0.7.11",
3
+ "version": "0.7.13",
4
4
  "description": "Hornbill HDocBook Development Support Tool",
5
5
  "main": "hdoc.js",
6
6
  "bin": {
@@ -13,6 +13,7 @@
13
13
  "hdoc-init.js",
14
14
  "hdoc-serve.js",
15
15
  "hdoc-stats.js",
16
+ "hdoc-validate.js",
16
17
  "validateNodeVer.js",
17
18
  "ui",
18
19
  "custom_modules",
@@ -26,6 +27,7 @@
26
27
  "license": "ISC",
27
28
  "dependencies": {
28
29
  "body-parser": "^1.20.1",
30
+ "cheerio": "^1.0.0-rc.12",
29
31
  "cookie-parser": "^1.4.6",
30
32
  "dree": "^3.4.2",
31
33
  "express": "^4.18.2",