hdoc-tools 0.1.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/custom_modules/tips.js +69 -0
- package/hdoc-build.js +5 -0
- package/hdoc-serve.js +366 -0
- package/hdoc.js +86 -0
- package/package.json +29 -0
- package/ui/css/images/hornbill-logo-full.svg +92 -0
- package/ui/css/theme-default/fonts/inter-cyrillic-ext.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-cyrillic.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-greek-ext.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-greek.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-italic-cyrillic-ext.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-italic-cyrillic.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-italic-greek-ext.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-italic-greek.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-italic-latin-ext.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-italic-latin.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-italic-vietnamese.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-latin-ext.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-latin.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-roman-cyrillic-ext.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-roman-cyrillic.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-roman-greek-ext.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-roman-greek.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-roman-latin-ext.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-roman-latin.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-roman-vietnamese.woff2 +0 -0
- package/ui/css/theme-default/fonts/inter-vietnamese.woff2 +0 -0
- package/ui/css/theme-default/styles/base.css +225 -0
- package/ui/css/theme-default/styles/components/content.css +82 -0
- package/ui/css/theme-default/styles/components/custom-block.css +90 -0
- package/ui/css/theme-default/styles/components/htl-doc.css +711 -0
- package/ui/css/theme-default/styles/components/sidebar.css +178 -0
- package/ui/css/theme-default/styles/fonts.css +221 -0
- package/ui/css/theme-default/styles/htldoc.layouts.css +244 -0
- package/ui/css/theme-default/styles/vars.css +393 -0
- package/ui/index.html +230 -0
- package/ui/js/doc.hornbill.js +485 -0
- package/ui/js/highlightjs/LICENSE +24 -0
- package/ui/js/highlightjs/highlight.pack.js +2 -0
- package/ui/js/highlightjs/styles/brown-paper.css +64 -0
- package/ui/js/highlightjs/styles/brown-papersq.png +0 -0
- package/ui/js/highlightjs/styles/codepen-embed.css +60 -0
- package/ui/js/highlightjs/styles/color-brewer.css +71 -0
- package/ui/js/highlightjs/styles/darcula.css +77 -0
- package/ui/js/highlightjs/styles/dark.css +63 -0
- package/ui/js/highlightjs/styles/darkula.css +6 -0
- package/ui/js/highlightjs/styles/default.css +99 -0
- package/ui/js/highlightjs/styles/dracula.css +76 -0
- package/ui/js/highlightjs/styles/far.css +71 -0
- package/ui/js/highlightjs/styles/foundation.css +88 -0
- package/ui/js/highlightjs/styles/github-gist.css +71 -0
- package/ui/js/highlightjs/styles/github-mm.css +71 -0
- package/ui/js/highlightjs/styles/github.css +99 -0
- package/ui/js/highlightjs/styles/googlecode.css +89 -0
- package/ui/js/highlightjs/styles/grayscale.css +101 -0
- package/ui/js/highlightjs/styles/idea.css +97 -0
- package/ui/js/highlightjs/styles/ir-black.css +73 -0
- package/ui/js/highlightjs/styles/kavadocs.css +71 -0
- package/ui/js/highlightjs/styles/kavadocsdark.css +120 -0
- package/ui/js/highlightjs/styles/kimbie.dark.css +74 -0
- package/ui/js/highlightjs/styles/kimbie.light.css +74 -0
- package/ui/js/highlightjs/styles/magula.css +70 -0
- package/ui/js/highlightjs/styles/mono-blue.css +59 -0
- package/ui/js/highlightjs/styles/monokai-sublime.css +83 -0
- package/ui/js/highlightjs/styles/monokai.css +70 -0
- package/ui/js/highlightjs/styles/obsidian.css +88 -0
- package/ui/js/highlightjs/styles/paraiso-dark.css +72 -0
- package/ui/js/highlightjs/styles/paraiso-light.css +72 -0
- package/ui/js/highlightjs/styles/railscasts.css +106 -0
- package/ui/js/highlightjs/styles/rainbow.css +85 -0
- package/ui/js/highlightjs/styles/solarized-dark.css +84 -0
- package/ui/js/highlightjs/styles/solarized-light.css +84 -0
- package/ui/js/highlightjs/styles/sunburst.css +102 -0
- package/ui/js/highlightjs/styles/twilight.css +97 -0
- package/ui/js/highlightjs/styles/vs.css +68 -0
- package/ui/js/highlightjs/styles/vs2015.css +117 -0
- package/ui/js/highlightjs/styles/xcode.css +104 -0
- package/ui/js/highlightjs/styles/zenburn.css +80 -0
- package/ui/js/highlightjs-badge.js +443 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// GS: based on markdown-it-tips extension but customized for our specific needs
|
|
4
|
+
|
|
5
|
+
var container = require('markdown-it-container');
|
|
6
|
+
|
|
7
|
+
module.exports = function md_tip_plugin(md, options) {
|
|
8
|
+
var containerOpenCount = 0;
|
|
9
|
+
var links = options ? options.links : true;
|
|
10
|
+
init();
|
|
11
|
+
return;
|
|
12
|
+
|
|
13
|
+
function icon_from_type(name) {
|
|
14
|
+
switch (name) {
|
|
15
|
+
case "note": return { class: "bi bi-exclamation-circle", title: "Note" };
|
|
16
|
+
case "tip": return { class: "bi bi-lightbulb", title: "Tip" };
|
|
17
|
+
case "important": return { class: "bi bi-megaphone", title: "Important" };
|
|
18
|
+
case "caution": return { class: "bi bi-x-circle", title: "Caution" };
|
|
19
|
+
case "warning": return { class: "bi bi-exclamation-triangle", title: "Warning" };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function setupContainer(name) {
|
|
24
|
+
md.use(container, name, {
|
|
25
|
+
render: function (tokens, idx) {
|
|
26
|
+
if (tokens[idx].nesting === 1) {
|
|
27
|
+
containerOpenCount += 1;
|
|
28
|
+
let inf = icon_from_type(name);
|
|
29
|
+
return '<div class="hdoc-alert alert-icon-' + name + '">\n<p class="hdoc-alert-title"><span class="' + inf.class + '"></span>' + inf.title + '</p>\n';
|
|
30
|
+
} else {
|
|
31
|
+
containerOpenCount -= 1;
|
|
32
|
+
return '</div>\n';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function isContainerOpen() {
|
|
39
|
+
return containerOpenCount > 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function selfRender(tokens, idx, options, env, self) {
|
|
43
|
+
return self.renderToken(tokens, idx, options);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function setupLinks() {
|
|
47
|
+
var defaultRender = md.renderer.rules.link_open || selfRender;
|
|
48
|
+
|
|
49
|
+
md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
|
|
50
|
+
if (isContainerOpen()) {
|
|
51
|
+
tokens[idx].attrPush(['class', 'md-tip-link']);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return defaultRender(tokens, idx, options, env, self);
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function init() {
|
|
59
|
+
setupContainer('note');
|
|
60
|
+
setupContainer('tip');
|
|
61
|
+
setupContainer('important');
|
|
62
|
+
setupContainer('caution');
|
|
63
|
+
setupContainer('warning');
|
|
64
|
+
|
|
65
|
+
if (links) {
|
|
66
|
+
setupLinks();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
package/hdoc-build.js
ADDED
package/hdoc-serve.js
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
var path = require('path');
|
|
3
|
+
const stream = require('stream');
|
|
4
|
+
var express = require('express');
|
|
5
|
+
|
|
6
|
+
exports.run = function(ui_path, source_path, md) {
|
|
7
|
+
console.log("Hornbill HDocBook Preview/Dev Server", "\r\n");
|
|
8
|
+
console.log(" Server Path:", __dirname);
|
|
9
|
+
console.log(" UI Root Path:", ui_path);
|
|
10
|
+
console.log(" Document Path:", source_path, "\r\n");
|
|
11
|
+
|
|
12
|
+
// Get an express server instance
|
|
13
|
+
var app = express();
|
|
14
|
+
|
|
15
|
+
// In the root of the project there is a hdocbook.json file which includes
|
|
16
|
+
// the id of the hdocbook we are working with
|
|
17
|
+
const hdocbook_project_config_path = path.join(source_path, "hdocbook-project.json");
|
|
18
|
+
|
|
19
|
+
// Load the hdocbook config file
|
|
20
|
+
var hdocbook_project = require(hdocbook_project_config_path);
|
|
21
|
+
|
|
22
|
+
// Get the ID of the hdocbook we are serving
|
|
23
|
+
var docId = hdocbook_project.docId;
|
|
24
|
+
|
|
25
|
+
// Get the path of the book.json file
|
|
26
|
+
const hdocbook_path = path.join(source_path, docId, "hdocbook.json");
|
|
27
|
+
|
|
28
|
+
// Pull in the book config file
|
|
29
|
+
var hdocbook_config = require(hdocbook_path);
|
|
30
|
+
var hdocbook_mtime = fs.statSync(hdocbook_path).mtime;
|
|
31
|
+
|
|
32
|
+
app.get('/content/library.json', function (req, res) {
|
|
33
|
+
let library = {
|
|
34
|
+
books: [
|
|
35
|
+
{
|
|
36
|
+
docId: hdocbook_config.docId,
|
|
37
|
+
title: hdocbook_config.title
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
res.setHeader("Content-Type", "application/json");
|
|
42
|
+
res.send(JSON.stringify(library, null, 3));
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
function content_type_for_ext(ext) {
|
|
47
|
+
switch (ext)
|
|
48
|
+
{
|
|
49
|
+
case ".z":
|
|
50
|
+
return "application/x-compress";
|
|
51
|
+
case ".tgz":
|
|
52
|
+
return "application/x-compressed";
|
|
53
|
+
case ".gz":
|
|
54
|
+
return "application/x-gzip";
|
|
55
|
+
case ".zip":
|
|
56
|
+
return "application/x-zip-compressed";
|
|
57
|
+
case ".xml":
|
|
58
|
+
return "application/xml";
|
|
59
|
+
case ".bmp":
|
|
60
|
+
return "image/bmp";
|
|
61
|
+
case ".gif":
|
|
62
|
+
return "image/gif";
|
|
63
|
+
case ".jpg":
|
|
64
|
+
return "image/jpeg";
|
|
65
|
+
case ".png":
|
|
66
|
+
return "image/png";
|
|
67
|
+
case ".tiff":
|
|
68
|
+
return "image/tiff";
|
|
69
|
+
case ".ico":
|
|
70
|
+
return "image/x-icon";
|
|
71
|
+
case ".png":
|
|
72
|
+
return "image/png";
|
|
73
|
+
case ".svg":
|
|
74
|
+
return "image/svg+xml";
|
|
75
|
+
case ".css":
|
|
76
|
+
return "text/css";
|
|
77
|
+
case ".htm":
|
|
78
|
+
case ".html":
|
|
79
|
+
return "text/html";
|
|
80
|
+
case ".txt":
|
|
81
|
+
return "text/plain";
|
|
82
|
+
case ".md":
|
|
83
|
+
return "text/plain";
|
|
84
|
+
case ".json":
|
|
85
|
+
return "application/json";
|
|
86
|
+
case ".js":
|
|
87
|
+
return "application/javascript";
|
|
88
|
+
default:
|
|
89
|
+
return "application/octet-stream";
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function expand_variables(text) {
|
|
94
|
+
// For debug mode our base path is our root??
|
|
95
|
+
text = text.replaceAll("{{BASE_PATH}}", "/" + docId);
|
|
96
|
+
text = text.replaceAll("{{BUILD_NUMBER}}", "0");
|
|
97
|
+
|
|
98
|
+
let build_date = new Date().toISOString();
|
|
99
|
+
build_date = build_date.replace('T', ' ');
|
|
100
|
+
build_date = build_date.substring(0,19);
|
|
101
|
+
|
|
102
|
+
text = text.replaceAll("{{BUILD_DATE}}", build_date);
|
|
103
|
+
return text;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function transform_markdown_and_send_html(req, res, file_path) {
|
|
107
|
+
|
|
108
|
+
if(fs.existsSync(file_path)) {
|
|
109
|
+
// we have a markdown representation of the requested HTML file, transform and return
|
|
110
|
+
// it to the caller
|
|
111
|
+
|
|
112
|
+
// Load markdown file
|
|
113
|
+
let md_txt = expand_variables(fs.readFileSync(file_path).toString());
|
|
114
|
+
|
|
115
|
+
// Render markdown into HTML
|
|
116
|
+
frontmatter_content = "";
|
|
117
|
+
var html_txt = md.render(md_txt.toString());
|
|
118
|
+
|
|
119
|
+
if(frontmatter_content.length) {
|
|
120
|
+
|
|
121
|
+
const obj = yaml.load(frontmatter_content);
|
|
122
|
+
|
|
123
|
+
const buff = Buffer.from(JSON.stringify(obj), 'utf-8');
|
|
124
|
+
|
|
125
|
+
const base64 = buff.toString('base64');
|
|
126
|
+
|
|
127
|
+
res.setHeader("X-frontmatter", base64);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
res.setHeader("Content-Type", "text/html");
|
|
131
|
+
res.send(html_txt);
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function send_content_file(req, res, file_path) {
|
|
138
|
+
let content_txt = expand_variables(fs.readFileSync(file_path).toString());
|
|
139
|
+
|
|
140
|
+
let contentType = content_type_for_ext(path.extname(file_path));
|
|
141
|
+
|
|
142
|
+
if(path.extname(file_path) == ".md") {
|
|
143
|
+
res.setHeader("Content-Disposition", "inline");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
res.setHeader("Content-Type", contentType);
|
|
147
|
+
|
|
148
|
+
res.send(content_txt);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function send_file(req, res, file_path) {
|
|
152
|
+
// Need to set the content type here??
|
|
153
|
+
let contentType = content_type_for_ext(path.extname(file_path));
|
|
154
|
+
res.setHeader("Content-Type", contentType);
|
|
155
|
+
|
|
156
|
+
const r = fs.createReadStream(file_path)
|
|
157
|
+
const ps = new stream.PassThrough()
|
|
158
|
+
stream.pipeline(
|
|
159
|
+
r,
|
|
160
|
+
ps,
|
|
161
|
+
(err) => {
|
|
162
|
+
if (err) {
|
|
163
|
+
console.log(err) // No such file or any other kind of error
|
|
164
|
+
return res.sendStatus(400).send("Unexpected error");
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
ps.pipe(res)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function send_content_resource_404(req, res) {
|
|
171
|
+
res.setHeader("Content-Type", "text/html");
|
|
172
|
+
res.status(404).send("Content resource not found");
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// 1. If we request a file with a .html file extension, and that file DOES NOT exist,
|
|
176
|
+
// we will look for the same file but with a .md extension. If we find that
|
|
177
|
+
// corresponding markdown file, we will transform that markdown file to HTML and
|
|
178
|
+
// return the HTML content
|
|
179
|
+
//
|
|
180
|
+
// 2. If we request a file, without any file extension then we will look for that file
|
|
181
|
+
// with a .md extension, and if that file exists, we will transform that markdown
|
|
182
|
+
// file to HTML and return that file.
|
|
183
|
+
//
|
|
184
|
+
// For all other requests, we are going to look on the filesystem. If we request
|
|
185
|
+
// a specific file with its extension (including .md files), then we will simply
|
|
186
|
+
// return the file verbatum as a static file.
|
|
187
|
+
//
|
|
188
|
+
// If we request a file without an extension and that file does not exist, we will
|
|
189
|
+
// assume that is a folder, will append index.html and look for that file, if present
|
|
190
|
+
// we will send it, if not present we will look for index.md, and if thats present
|
|
191
|
+
// we will transform to HTML and return that
|
|
192
|
+
//
|
|
193
|
+
// Anything else in this handler will return a 404 error
|
|
194
|
+
|
|
195
|
+
app.get('/content/*', function (req, res) {
|
|
196
|
+
|
|
197
|
+
let url = req.url;
|
|
198
|
+
|
|
199
|
+
let segs = url.split('/');
|
|
200
|
+
|
|
201
|
+
if(segs.length == 4 && segs[1] == "content" && segs[3] == "book.json") {
|
|
202
|
+
// Special case of a virtual file here, we need to check the book ID and
|
|
203
|
+
// if its our book, send the json
|
|
204
|
+
if(hdocbook_config.docId == segs[2]) {
|
|
205
|
+
res.setHeader("Content-Type", "application/json");
|
|
206
|
+
res.send(JSON.stringify(hdocbook_config, null, 3));
|
|
207
|
+
} else {
|
|
208
|
+
// Return a 404 error here
|
|
209
|
+
res.setHeader("Content-Type", "text/html");
|
|
210
|
+
res.status(404).send("Specified bookId " + segs[2] + " not found");
|
|
211
|
+
}
|
|
212
|
+
return;
|
|
213
|
+
} else if (segs.length == 3 && segs[1] == "content" && segs[2] == "index.json") {
|
|
214
|
+
// For development mode, we always have an index with one book in it, the one being developed
|
|
215
|
+
if (hdocbook_config) {
|
|
216
|
+
let index = {
|
|
217
|
+
books: [
|
|
218
|
+
{
|
|
219
|
+
docId: hdocbook_config.docId,
|
|
220
|
+
title: hdocbook_config.title,
|
|
221
|
+
description: hdocbook_config.description,
|
|
222
|
+
version: hdocbook_config.version
|
|
223
|
+
}
|
|
224
|
+
]
|
|
225
|
+
};
|
|
226
|
+
res.setHeader("Content-Type", "application/json");
|
|
227
|
+
res.send(JSON.stringify(index, null, 3));
|
|
228
|
+
} else {
|
|
229
|
+
// Return a 404 error here
|
|
230
|
+
res.setHeader("Content-Type", "text/html");
|
|
231
|
+
res.status(404).send("Specified bookId " + segs[2] + " not found");
|
|
232
|
+
}
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
url = url.replace("/content/", "/");
|
|
237
|
+
|
|
238
|
+
console.log("URL Requested: ", url);
|
|
239
|
+
|
|
240
|
+
let file_path = path.join(source_path, url);
|
|
241
|
+
let ui_file_path = path.join(ui_path, url);
|
|
242
|
+
|
|
243
|
+
// If the requested file is found in the UI folder
|
|
244
|
+
if(url == "/")
|
|
245
|
+
{
|
|
246
|
+
if(fs.existsSync(path.join(ui_file_path, "index.html"))) {
|
|
247
|
+
// We want the index.html, send it here
|
|
248
|
+
send_file(req, res, path.join(ui_file_path, "index.html"));
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
// Return a 404 error here
|
|
252
|
+
send_content_resource_404(req, res);
|
|
253
|
+
return;
|
|
254
|
+
} else if(fs.existsSync(ui_file_path)) {
|
|
255
|
+
// File is found in the UI folder, that takes priority, send the file
|
|
256
|
+
send_file(req, res, ui_file_path);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if(path.extname(file_path) == ".html") {
|
|
261
|
+
// 1a. check for html files, and send/transform as required
|
|
262
|
+
if(fs.existsSync(file_path)) {
|
|
263
|
+
// HTML file exists on disk, just return it verbatum
|
|
264
|
+
res.setHeader("Content-Type", "text/html");
|
|
265
|
+
send_file(req, res, file_path);
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if(fs.existsSync(file_path.replace(".html", ".md"))){
|
|
270
|
+
if(transform_markdown_and_send_html(req, res, file_path.replace(".html", ".md"))) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
} else if(path.extname(file_path) == ".md") {
|
|
275
|
+
// If the markdown file exists, just send to caller as is
|
|
276
|
+
if(fs.existsSync(file_path)) {
|
|
277
|
+
send_content_file(req, res, file_path);
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
} else if(path.extname(file_path).length == 0)
|
|
281
|
+
{
|
|
282
|
+
// 2. If we request a file, without any file extension
|
|
283
|
+
if(fs.existsSync(file_path + ".md")) {
|
|
284
|
+
if(transform_markdown_and_send_html(req, res, file_path + ".md")) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
} else if(fs.existsSync(path.join(file_path + "index.md"))) {
|
|
288
|
+
if(transform_markdown_and_send_html(req, res, path.join(file_path, "index.md"))) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
} else if(fs.existsSync(path.join(file_path + "index.html"))) {
|
|
292
|
+
console.log("jdhsfkjhdkjfhjkshdkfjhkjsdf", file_path);
|
|
293
|
+
res.setHeader("Content-Type", "text/html");
|
|
294
|
+
send_content_file(req, res, path.join(file_path + "index.html"));
|
|
295
|
+
return;
|
|
296
|
+
} else if(fs.existsSync(file_path + "/index.md")) {
|
|
297
|
+
if(transform_markdown_and_send_html(req, res, file_path + "/index.md")) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
} else if(fs.existsSync(path.join(file_path + "/index.html"))) {
|
|
301
|
+
res.setHeader("Content-Type", "text/html");
|
|
302
|
+
send_content_file(req, res, path.join(file_path + "/index.html"));
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
} else if(fs.existsSync(file_path)) {
|
|
306
|
+
send_file(req, res, file_path);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Return a 404 error here
|
|
311
|
+
send_content_resource_404(req, res);
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
// Cacth all
|
|
315
|
+
app.get('/*', function (req, res) {
|
|
316
|
+
|
|
317
|
+
let segs = req.url.split('/');
|
|
318
|
+
|
|
319
|
+
if(segs.length > 3 && segs[2] == "content") {
|
|
320
|
+
// In this case we are looking for static content within the book
|
|
321
|
+
|
|
322
|
+
// Creat the file path
|
|
323
|
+
let url = req.url.replace("/content/", "/");
|
|
324
|
+
let file_path = path.join(source_path, url);
|
|
325
|
+
|
|
326
|
+
// If the file exists, send it.
|
|
327
|
+
if(fs.existsSync(file_path) == true) {
|
|
328
|
+
send_file(req, res, file_path);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// All else fails, we have not file to return, so return a 404 error here
|
|
333
|
+
send_content_resource_404(req, res);
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
let ui_file_path = path.join(ui_path, req.url);
|
|
338
|
+
|
|
339
|
+
console.log("URL Root: ", req.url);
|
|
340
|
+
|
|
341
|
+
// To suport the SPA application behaviour, if there is no file extension present, then
|
|
342
|
+
// we simply return the /index.html file content to the client
|
|
343
|
+
if(path.extname(ui_file_path).length == 0) {
|
|
344
|
+
send_content_file(req, res, path.join(ui_path, "index.html"));
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// If the file exists, send it.
|
|
349
|
+
if(fs.existsSync(ui_file_path) == true) {
|
|
350
|
+
send_content_file(req, res, ui_file_path);
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// All else fails, we have not file to return, so return a 404 error here
|
|
355
|
+
send_content_resource_404(req, res);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
var server = app.listen(3000, "0.0.0.0", function () {
|
|
359
|
+
var host = server.address().address
|
|
360
|
+
var port = server.address().port
|
|
361
|
+
|
|
362
|
+
console.log("Server listening at http://%s:%s", host, port)
|
|
363
|
+
console.log("Document source path is: " + source_path);
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
}
|
package/hdoc.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
const stream = require('stream');
|
|
6
|
+
const yaml = require('js-yaml');
|
|
7
|
+
const mdfm = require('markdown-it-front-matter');
|
|
8
|
+
var hljs = require('highlight.js') // https://highlightjs.org/
|
|
9
|
+
const md = require('markdown-it') ({
|
|
10
|
+
// enable everything
|
|
11
|
+
html: true,
|
|
12
|
+
linkify: true,
|
|
13
|
+
typographer: true,
|
|
14
|
+
// highlight: function (str, lang) {
|
|
15
|
+
// if (lang && hljs.getLanguage(lang)) {
|
|
16
|
+
// try {
|
|
17
|
+
// return hljs.highlight(lang, str, true).value;
|
|
18
|
+
// } catch (__) {}
|
|
19
|
+
// }
|
|
20
|
+
// }
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
var frontmatter_content;
|
|
24
|
+
md.use(mdfm, function(fm) {
|
|
25
|
+
frontmatter_content = fm;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const tips = require(__dirname + '/custom_modules/tips.js');
|
|
29
|
+
|
|
30
|
+
md.use(tips, {links: true});
|
|
31
|
+
|
|
32
|
+
// Default source path to working directory
|
|
33
|
+
const source_path = process.cwd();
|
|
34
|
+
const ui_path = path.join(__dirname, "ui");
|
|
35
|
+
|
|
36
|
+
var command = ""; // Our command to run
|
|
37
|
+
|
|
38
|
+
const commands = {
|
|
39
|
+
"serve": {},
|
|
40
|
+
"build": {}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Get options from command args
|
|
44
|
+
for(x = 0; x < process.argv.length; x++)
|
|
45
|
+
{
|
|
46
|
+
// First two arguments are command, and script
|
|
47
|
+
if(x == 0 || x == 1)
|
|
48
|
+
continue;
|
|
49
|
+
// Third argument is command
|
|
50
|
+
if(x == 2) {
|
|
51
|
+
command = process.argv[x];
|
|
52
|
+
// Is command allowed
|
|
53
|
+
if(commands[command] === undefined)
|
|
54
|
+
throw "The specified command '" + command + "' is not known\r\n";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if(process.argv[x] == "-path") {
|
|
58
|
+
x++;
|
|
59
|
+
if(x < process.argv.length)
|
|
60
|
+
{
|
|
61
|
+
source_path = process.argv[x];
|
|
62
|
+
}
|
|
63
|
+
} else if(process.argv[x] == "-ui-path") {
|
|
64
|
+
x++;
|
|
65
|
+
if(x < process.argv.length)
|
|
66
|
+
{
|
|
67
|
+
ui_path = process.argv[x];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
console.log("Hornbill HDocBook Tools v0.1", "\r\n");
|
|
73
|
+
console.log(" Server Path:", __dirname);
|
|
74
|
+
console.log(" Document Path:", source_path, "\r\n");
|
|
75
|
+
|
|
76
|
+
if(command == "serve") {
|
|
77
|
+
const server = require(path.join(__dirname, "hdoc-serve.js"));
|
|
78
|
+
|
|
79
|
+
server.run(ui_path, source_path, md);
|
|
80
|
+
} else if(command == "build") {
|
|
81
|
+
|
|
82
|
+
const builder = require(path.join(__dirname, "hdoc-build.js"));
|
|
83
|
+
|
|
84
|
+
builder.run(ui_path, source_path, md);
|
|
85
|
+
}
|
|
86
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hdoc-tools",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Hornbill HDocBook Development Support Tool",
|
|
5
|
+
"main": "hdoc.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"hdoc": "./hdoc.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"hdoc.js", "hdoc-serve.js", "hdoc-build.js", "ui", "custom_modules"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
14
|
+
},
|
|
15
|
+
"author": "Hornbill Technologies Ltd",
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"body-parser": "^1.20.1",
|
|
19
|
+
"cookie-parser": "^1.4.6",
|
|
20
|
+
"express": "^4.18.2",
|
|
21
|
+
"highlight.js": "^11.6.0",
|
|
22
|
+
"js-yaml": "^4.1.0",
|
|
23
|
+
"markdown-it": "^13.0.1",
|
|
24
|
+
"markdown-it-container": "^3.0.0",
|
|
25
|
+
"markdown-it-front-matter": "^0.2.3",
|
|
26
|
+
"multer": "^1.4.5-lts.1",
|
|
27
|
+
"stream": "0.0.2"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
3
|
+
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
4
|
+
viewBox="0 0 2053.3 283.5" style="enable-background:new 0 0 2053.3 283.5;" xml:space="preserve">
|
|
5
|
+
<style type="text/css">
|
|
6
|
+
.st0{fill:#224287;}
|
|
7
|
+
.st1{fill:#5CB77C;}
|
|
8
|
+
.st2{fill:#2991D0;}
|
|
9
|
+
.st3{fill:#C71051;}
|
|
10
|
+
.st4{fill:#F2892B;}
|
|
11
|
+
</style>
|
|
12
|
+
<g>
|
|
13
|
+
<g>
|
|
14
|
+
<path class="st0" d="M358.4,234.7V48.2c0-3.6,2-5.6,5.6-5.6h16.2c3.6,0,5.6,2,5.6,5.6v78.7h126.6V48.2c0-3.6,2-5.6,5.6-5.6h16.5
|
|
15
|
+
c3.6,0,5.6,2,5.6,5.6v186.5c0,3.6-2,5.6-5.6,5.6H518c-3.6,0-5.6-2-5.6-5.6v-82.3H385.9v82.3c0,3.6-2,5.6-5.6,5.6H364
|
|
16
|
+
C360.4,240.3,358.4,238.3,358.4,234.7z"/>
|
|
17
|
+
<path class="st0" d="M599.8,172.3v-61.3c0-43.7,18.2-68.3,66.4-68.3h70.3c48.2,0,66.4,24.6,66.4,68.3v61.3c0,43.4-18.2,68-66.4,68
|
|
18
|
+
h-70.3C618,240.3,599.8,215.7,599.8,172.3z M736.4,213.7c28.3,0,38.9-9,38.9-40.6v-63c0-31.9-10.4-40.9-38.9-40.9h-70.3
|
|
19
|
+
c-28.3,0-38.9,9-38.9,40.9v63c0,31.6,10.9,40.6,38.9,40.6H736.4z"/>
|
|
20
|
+
<path class="st0" d="M1003,178.7l38.4,54.9c2.5,3.6,0.8,6.7-3.6,6.7h-19.3c-2.8,0-5-1.1-6.7-3.6l-37.5-55.2h-84.3v53.2
|
|
21
|
+
c0,3.6-2,5.6-5.6,5.6H868c-3.6,0-5.6-2-5.6-5.6V48.2c0-3.6,2-5.6,5.6-5.6h101.4c58.8,0,78.4,21.6,78.4,68.3v3.4
|
|
22
|
+
C1047.8,150.1,1036.6,171.7,1003,178.7z M1020.1,111.2c0-34.4-12.9-42-52.4-42h-77.8v86h77.8c39.2,0,52.4-7.3,52.4-41.2V111.2z"/>
|
|
23
|
+
<path class="st0" d="M1105.2,234.7V48.2c0-3.6,2-5.6,5.6-5.6h17.6c2.8,0,5.3,1.1,7,3.4l127.4,154.3v-152c0-3.6,2-5.6,5.6-5.6h16.2
|
|
24
|
+
c3.6,0,5.6,2,5.6,5.6v186.5c0,3.6-2,5.6-5.6,5.6h-18.2c-2.8,0-5.3-1.1-7-3.4L1132.6,83.5v151.2c0,3.6-2,5.6-5.6,5.6h-16.2
|
|
25
|
+
C1107.2,240.3,1105.2,238.3,1105.2,234.7z"/>
|
|
26
|
+
<path class="st0" d="M1353.6,234.7V48.2c0-3.6,2-5.6,5.6-5.6h107.2c47.3,0,66.4,17.1,66.6,53.2v2.8c0,27.4-12.9,36.4-24.4,42
|
|
27
|
+
c11.8,5.6,25.8,16.5,25.8,45.1v2.5c0,35.8-18.8,52.1-66.1,52.1h-109.2C1355.5,240.3,1353.6,238.3,1353.6,234.7z M1472,128.3
|
|
28
|
+
c21.3,0,32.8-5.9,32.8-26.3v-3.9c0-21.6-12-28.8-39.8-28.8h-84v59.1H1472z M1467,214c27.4,0,39.5-6.7,39.5-28.3v-3.6
|
|
29
|
+
c0-21-11.8-29.4-33.6-29.4H1381V214H1467z"/>
|
|
30
|
+
<path class="st0" d="M1592.7,234.7V48.2c0-3.6,2-5.6,5.6-5.6h16.2c3.6,0,5.6,2,5.6,5.6v186.5c0,3.6-2,5.6-5.6,5.6h-16.2
|
|
31
|
+
C1594.6,240.3,1592.7,238.3,1592.7,234.7z"/>
|
|
32
|
+
<path class="st0" d="M1683.4,234.7V48.2c0-3.6,2-5.6,5.6-5.6h16.2c3.6,0,5.6,2,5.6,5.6v165.5h127.4c3.6,0,5.6,2,5.6,5.6v15.4
|
|
33
|
+
c0,3.6-2,5.6-5.6,5.6H1689C1685.4,240.3,1683.4,238.3,1683.4,234.7z"/>
|
|
34
|
+
<path class="st0" d="M1892.8,234.7V48.2c0-3.6,2-5.6,5.6-5.6h16.2c3.6,0,5.6,2,5.6,5.6v165.5h127.4c3.6,0,5.6,2,5.6,5.6v15.4
|
|
35
|
+
c0,3.6-2,5.6-5.6,5.6h-149.2C1894.8,240.3,1892.8,238.3,1892.8,234.7z"/>
|
|
36
|
+
</g>
|
|
37
|
+
<g>
|
|
38
|
+
<g>
|
|
39
|
+
<g>
|
|
40
|
+
<path class="st1" d="M185.1,251.3c0,0,0,0.1,0,0.1C185.1,251.3,185.1,251.3,185.1,251.3z"/>
|
|
41
|
+
</g>
|
|
42
|
+
<g>
|
|
43
|
+
<path class="st1" d="M187.4,246.9c0.1-0.2,0.3-0.4,0.4-0.6C187.7,246.5,187.5,246.7,187.4,246.9z"/>
|
|
44
|
+
</g>
|
|
45
|
+
<g>
|
|
46
|
+
<path class="st1" d="M186.5,248.5c-0.1,0.2-0.2,0.4-0.3,0.6C186.2,248.9,186.3,248.7,186.5,248.5z"/>
|
|
47
|
+
</g>
|
|
48
|
+
</g>
|
|
49
|
+
</g>
|
|
50
|
+
<g>
|
|
51
|
+
<path class="st2" d="M111.3,35.1c-4.6,5.4-10.6,9.2-16.9,10.6c-6.2,1.4-12.2,0.3-16.9-2.9c-12.2,16.7-22.2,59.9-10.6,97.6
|
|
52
|
+
c0.4,1.4,2.3,1.5,3,0.2c0,0,5.5-99.8,113.2-93c1.4,0.1,2.2-1.5,1.4-2.6c-25.9-33.3-62.6-29.5-65.6-29.5
|
|
53
|
+
C118.8,22.2,116.2,29.2,111.3,35.1z"/>
|
|
54
|
+
<ellipse transform="matrix(0.7049 -0.7093 0.7093 0.7049 12.0913 71.5212)" class="st2" cx="92" cy="21.2" rx="23.8" ry="18.2"/>
|
|
55
|
+
</g>
|
|
56
|
+
<g>
|
|
57
|
+
<g>
|
|
58
|
+
<path class="st3" d="M23.8,173.1c0,0-0.1,0-0.1,0C23.8,173.1,23.8,173.1,23.8,173.1z"/>
|
|
59
|
+
<path class="st3" d="M28.2,175.5c0.2,0.1,0.4,0.3,0.6,0.4C28.6,175.7,28.4,175.6,28.2,175.5z"/>
|
|
60
|
+
<path class="st4" d="M35.1,172.6c5.4,4.6,9.2,10.6,10.6,16.9c1.4,6.2,0.3,12.2-2.9,16.9c16.7,12.2,59.9,22.2,97.6,10.6
|
|
61
|
+
c1.4-0.4,1.5-2.3,0.2-3c0,0-99.8-5.5-93-113.2c0.1-1.4-1.5-2.2-2.6-1.4c-33.3,25.9-29.5,62.6-29.5,65.6
|
|
62
|
+
C22.2,165,29.2,167.7,35.1,172.6z"/>
|
|
63
|
+
<path class="st3" d="M26.6,174.5c-0.2-0.1-0.4-0.2-0.6-0.4C26.2,174.3,26.4,174.4,26.6,174.5z"/>
|
|
64
|
+
</g>
|
|
65
|
+
|
|
66
|
+
<ellipse transform="matrix(0.7049 -0.7093 0.7093 0.7049 -129.8393 71.6899)" class="st4" cx="21.2" cy="191.9" rx="18.2" ry="23.8"/>
|
|
67
|
+
</g>
|
|
68
|
+
<g>
|
|
69
|
+
<g>
|
|
70
|
+
<path class="st1" d="M173.2,248.4c4.6-5.4,10.6-9.2,16.9-10.6c6.2-1.4,12.2-0.3,16.9,2.9c12.2-16.7,22.2-59.9,10.6-97.6
|
|
71
|
+
c-0.4-1.4-2.3-1.5-3-0.2c0,0-5.5,99.8-113.2,93c-1.4-0.1-2.2,1.5-1.4,2.6c25.9,33.3,62.6,29.5,65.6,29.5
|
|
72
|
+
C165.6,261.3,168.2,254.2,173.2,248.4z"/>
|
|
73
|
+
</g>
|
|
74
|
+
<g>
|
|
75
|
+
|
|
76
|
+
<ellipse transform="matrix(0.7049 -0.7093 0.7093 0.7049 -129.2198 213.9002)" class="st1" cx="192.4" cy="262.2" rx="23.8" ry="18.2"/>
|
|
77
|
+
</g>
|
|
78
|
+
</g>
|
|
79
|
+
<g>
|
|
80
|
+
<g>
|
|
81
|
+
<path class="st3" d="M259.6,110c0,0,0.1,0,0.1,0C259.7,110.1,259.7,110.1,259.6,110z"/>
|
|
82
|
+
<path class="st3" d="M255.2,107.7c-0.2-0.1-0.4-0.3-0.6-0.4C254.8,107.4,255,107.6,255.2,107.7z"/>
|
|
83
|
+
<path class="st3" d="M248.4,110.6c-5.4-4.6-9.2-10.6-10.6-16.9c-1.4-6.2-0.3-12.2,2.9-16.9c-16.7-12.2-59.9-22.2-97.6-10.6
|
|
84
|
+
c-1.4,0.4-1.5,2.3-0.2,3c0,0,99.8,5.5,93,113.2c-0.1,1.4,1.5,2.2,2.6,1.4c33.3-25.9,29.5-62.6,29.5-65.6
|
|
85
|
+
C261.3,118.1,254.2,115.5,248.4,110.6z"/>
|
|
86
|
+
<path class="st3" d="M256.8,108.7c0.2,0.1,0.4,0.2,0.6,0.4C257.2,108.9,257,108.8,256.8,108.7z"/>
|
|
87
|
+
</g>
|
|
88
|
+
|
|
89
|
+
<ellipse transform="matrix(0.7049 -0.7093 0.7093 0.7049 12.6367 212.9606)" class="st3" cx="262.2" cy="91.3" rx="18.2" ry="23.8"/>
|
|
90
|
+
</g>
|
|
91
|
+
</g>
|
|
92
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|