markdown-maker 1.9.1 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- package/.github/workflows/node.js.yml +1 -1
- package/build/cltool.d.ts +1 -0
- package/build/cltool.js +161 -0
- package/build/cltool.js.map +1 -0
- package/build/commands.d.ts +43 -0
- package/build/commands.js +223 -0
- package/build/commands.js.map +1 -0
- package/build/parse.d.ts +65 -0
- package/build/parse.js +281 -0
- package/build/parse.js.map +1 -0
- package/build/templates.d.ts +10 -0
- package/build/templates.js +20 -0
- package/build/templates.js.map +1 -0
- package/package.json +3 -3
- package/src/cltool.ts +11 -3
- package/src/commands.ts +44 -40
- package/src/parse.ts +23 -34
- package/src/templates/configTemplate.json +13 -0
- package/test/advanced.test.js +10 -8
- package/test/basic.test.js +11 -0
- package/test/errors.test.js +23 -1
- package/test/hooks.js +9 -0
- package/test/tester.test.js +12 -3
package/src/parse.ts
CHANGED
@@ -55,7 +55,7 @@ class Parser {
|
|
55
55
|
opts?: {
|
56
56
|
parent?: Parser;
|
57
57
|
isFileCallback?: (s: string) => false | string;
|
58
|
-
}
|
58
|
+
}
|
59
59
|
) {
|
60
60
|
/* this.working_directory */
|
61
61
|
this.file = filename;
|
@@ -116,8 +116,8 @@ class Parser {
|
|
116
116
|
console.log(
|
117
117
|
Colors.colors(
|
118
118
|
"magenta",
|
119
|
-
"parsing " + this.file + ": depth=" + this.opts.depth
|
120
|
-
)
|
119
|
+
"parsing " + this.file + ": depth=" + this.opts.depth
|
120
|
+
)
|
121
121
|
);
|
122
122
|
}
|
123
123
|
|
@@ -200,7 +200,7 @@ class Parser {
|
|
200
200
|
/* Add global flag to RegExp */
|
201
201
|
const re = new RegExp(
|
202
202
|
command.validator.source,
|
203
|
-
(command.validator.flags || "") + "g"
|
203
|
+
(command.validator.flags || "") + "g"
|
204
204
|
);
|
205
205
|
blob = blob.replace(re, (...args) => command.act(args, this) || "");
|
206
206
|
});
|
@@ -237,9 +237,7 @@ class Parser {
|
|
237
237
|
const link = this.titleId(title);
|
238
238
|
|
239
239
|
let __line =
|
240
|
-
hor.repeat(Math.max(sec.level - 1, 0)) +
|
241
|
-
beg +
|
242
|
-
`[${title}](#${link})`;
|
240
|
+
hor.repeat(Math.max(sec.level - 1, 0)) + beg + `[${title}](#${link})`;
|
243
241
|
|
244
242
|
__blob.push(__line);
|
245
243
|
});
|
@@ -260,27 +258,21 @@ class Parser {
|
|
260
258
|
/* output the parsed document to bundle */
|
261
259
|
to(bundleName: string, callback: (fileName: string) => void) {
|
262
260
|
const dir = path.dirname(bundleName);
|
263
|
-
|
264
|
-
if (callback === undefined) callback = () => {};
|
261
|
+
if (callback === undefined) callback = () => { };
|
265
262
|
|
266
263
|
if (!fs.existsSync(dir)) {
|
267
|
-
fs.mkdirSync(dir);
|
264
|
+
fs.mkdirSync(dir, { recursive: true });
|
268
265
|
}
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
called = true;
|
274
|
-
}
|
266
|
+
|
267
|
+
if (!this.opts.html) {
|
268
|
+
this.get(TargetType.MARKDOWN, (blob) => {
|
269
|
+
fs.writeFile(bundleName, blob, () => callback(bundleName));
|
275
270
|
});
|
276
|
-
}
|
271
|
+
}
|
277
272
|
|
278
|
-
|
273
|
+
else {
|
279
274
|
const htmlFileName = bundleName.replace(".md", ".html");
|
280
|
-
fs.writeFile(htmlFileName, this.html(), () =>
|
281
|
-
if (!called) callback(htmlFileName);
|
282
|
-
called = true;
|
283
|
-
});
|
275
|
+
fs.writeFile(htmlFileName, this.html(), () => callback(htmlFileName));
|
284
276
|
}
|
285
277
|
}
|
286
278
|
|
@@ -295,7 +287,7 @@ class Parser {
|
|
295
287
|
return htmlFormatted;
|
296
288
|
}
|
297
289
|
|
298
|
-
get(targetType?: TargetType, callback
|
290
|
+
get(targetType?: TargetType, callback?: (blob: string) => void): string {
|
299
291
|
/* If target type is undefined, markdown is the default */
|
300
292
|
if (targetType === undefined) targetType = TargetType.MARKDOWN;
|
301
293
|
if (this.blobs[targetType]) {
|
@@ -309,26 +301,24 @@ class Parser {
|
|
309
301
|
let blob = this.parse();
|
310
302
|
this.opts.targetType = undefined;
|
311
303
|
if (callback) callback(blob);
|
312
|
-
return blob
|
304
|
+
return blob
|
313
305
|
} catch (error) {
|
306
|
+
/* Compile a traceback of error */
|
314
307
|
let traceback = "";
|
315
|
-
|
316
308
|
let p: Parser = this;
|
317
309
|
|
318
310
|
do {
|
319
311
|
if (error instanceof MDMError)
|
320
312
|
traceback += `\n...on line ${p.line_num_from_index(
|
321
|
-
error.match.index
|
313
|
+
error.match.index
|
322
314
|
)} in ${p.file}`.grey(15);
|
323
|
-
else
|
324
|
-
traceback +=
|
325
|
-
`\n...on line ${p.line_num} in ${p.file}`.grey(15);
|
315
|
+
else traceback += `\n...on line ${p.line_num} in ${p.file}`.grey(15);
|
326
316
|
if (p.parent) p = p.parent;
|
327
317
|
} while (p.parent);
|
328
318
|
|
329
319
|
error.message += traceback;
|
330
320
|
|
331
|
-
/* only interested in stacktrace
|
321
|
+
/* only interested in node stacktrace when debugging */
|
332
322
|
if (!this.opts.debug) error.stack = "";
|
333
323
|
|
334
324
|
if (this.opts.only_warn) console.error(error);
|
@@ -342,14 +332,14 @@ export function splice(
|
|
342
332
|
str: string,
|
343
333
|
startIndex: number,
|
344
334
|
width: number,
|
345
|
-
newSubStr: string
|
335
|
+
newSubStr: string
|
346
336
|
) {
|
347
337
|
const start = str.slice(0, startIndex);
|
348
338
|
const end = str.slice(startIndex + width);
|
349
339
|
return start + newSubStr + end;
|
350
340
|
}
|
351
341
|
|
352
|
-
/* add extention to marked */
|
342
|
+
/* add extention to marked for classed blockquotes*/
|
353
343
|
marked.use({
|
354
344
|
renderer: {
|
355
345
|
blockquote(quote) {
|
@@ -363,8 +353,7 @@ marked.use({
|
|
363
353
|
const id = args.filter((arg) => arg.startsWith("#"));
|
364
354
|
|
365
355
|
const classNames = classes.map((c) => c.slice(1));
|
366
|
-
const classText =
|
367
|
-
classes.length > 0 ? `class="${classNames.join(" ")}"` : "";
|
356
|
+
const classText = classes.length > 0 ? `class="${classNames.join(" ")}"` : "";
|
368
357
|
const idText = id.length > 0 ? `id="${id[0].slice(1)}"` : "";
|
369
358
|
|
370
359
|
/* remove the ending from the quote */
|
package/test/advanced.test.js
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
const util = require("./tester.test.js");
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
const putTemplate = () => {
|
4
|
+
util.put(
|
5
|
+
"module.exports = {main: (new_template, new_command) => {new_template('hi', 'hello'); new_command(/#test_cmd/, (t,p) => 'yeet', 0);}};",
|
6
|
+
"extensions.js"
|
7
|
+
);
|
8
|
+
};
|
7
9
|
|
8
10
|
describe("Use of templates", () => {
|
11
|
+
beforeEach(putTemplate);
|
9
12
|
it("should import presentation template as expected", () => {
|
13
|
+
putTemplate();
|
10
14
|
const output = new util.Parser("#mdtemplate<presentation>").get();
|
11
15
|
const template = `<style>html {width: 100vw;height: 100vh;}.slide {padding: 5%;border-radius: 25px;margin: 0;}div > .slide-num {position: absolute;top: 12.5%;right: 15%;/* font-size: 150%; */}body {margin: 5% 15%;}img {max-width: 100%;max-height: 40vh;}</style><script>document.addEventListener("DOMContentLoaded", () => {let current_slide = 0;const all_slides = document.querySelectorAll("div.slide");const num_slides = all_slides.length;all_slides.forEach((slide) => {const num_elem = document.createElement("p");num_elem.classList.add("slide-num");slide.appendChild(num_elem);});onkeydown = (ev) => {if (ev.key == "ArrowRight" && current_slide < all_slides.length - 1)update_slide(++current_slide);else if (ev.key == "ArrowLeft" && current_slide > 0)update_slide(--current_slide);};const update_slide = (index) => {all_slides.forEach((slide) => (slide.style.display = "none"));all_slides[current_slide].style.display = "block";all_slides[current_slide].lastChild.textContent = \`\${current_slide + 1} / \${num_slides}\`;};update_slide(current_slide);});</script>`;
|
12
16
|
|
@@ -14,22 +18,20 @@ describe("Use of templates", () => {
|
|
14
18
|
});
|
15
19
|
|
16
20
|
it("should use custom templates from project extensions.js file", () => {
|
21
|
+
putTemplate();
|
17
22
|
util.put("#mdtemplate<hi>", "sample1.md");
|
18
23
|
|
19
24
|
util.assert.strictEqual(
|
20
25
|
new util.Parser("test/test-files/sample1.md").get(),
|
21
26
|
"hello\n\n"
|
22
27
|
);
|
23
|
-
|
24
|
-
/* make sure to remove after, to not mess with future tests */
|
25
28
|
});
|
26
29
|
|
27
30
|
it("should use custom commands from project extensions.js file", () => {
|
31
|
+
putTemplate();
|
28
32
|
util.put("#test_cmd", "sample1.md");
|
29
33
|
|
30
34
|
const parser = new util.Parser("test/test-files/sample1.md");
|
31
35
|
util.assert.strictEqual(parser.get(), "yeet\n\n");
|
32
|
-
|
33
|
-
/* make sure to remove after, to not mess with future tests */
|
34
36
|
});
|
35
37
|
});
|
package/test/basic.test.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
const path = require("path");
|
1
2
|
const util = require("./tester.test.js");
|
2
3
|
|
3
4
|
describe("Basic features", () => {
|
@@ -54,4 +55,14 @@ describe("Basic features", () => {
|
|
54
55
|
|
55
56
|
util.assert.strictEqual(parser.get(), "### Title\n[Title](#title)\n\n");
|
56
57
|
});
|
58
|
+
it("should include file with same name as folder when including a folder", () => {
|
59
|
+
util.put("#mdinclude<sample_fld>", "sample1.md");
|
60
|
+
util.putDir("sample_fld");
|
61
|
+
util.put("hello", util.path.join("sample_fld", "sample_fld.md"));
|
62
|
+
|
63
|
+
const parser = new util.Parser("test/test-files/sample1.md");
|
64
|
+
const output = parser.get();
|
65
|
+
|
66
|
+
util.assert.strictEqual(output, "hello\n\n");
|
67
|
+
});
|
57
68
|
});
|
package/test/errors.test.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
const { Parser } = require("marked");
|
2
1
|
const util = require("./tester.test.js");
|
2
|
+
const fs = require("fs");
|
3
3
|
|
4
4
|
describe("Error handling", () => {
|
5
5
|
it("should dissallow undefined templates", () => {
|
@@ -23,4 +23,26 @@ describe("Error handling", () => {
|
|
23
23
|
|
24
24
|
util.assert.strictEqual(e.message.replace(/(\\)+/g, "/"), answer);
|
25
25
|
});
|
26
|
+
it("should dissallow loading a folder without an entry file", () => {
|
27
|
+
util.put("#mdinclude<sample_fld>", "sample1.md");
|
28
|
+
util.putDir("sample_fld");
|
29
|
+
|
30
|
+
const parser = new util.Parser("test/test-files/sample1.md");
|
31
|
+
|
32
|
+
let e;
|
33
|
+
util.assert.throws(() => {
|
34
|
+
try {
|
35
|
+
parser.get();
|
36
|
+
} catch (_e) {
|
37
|
+
e = _e;
|
38
|
+
throw _e;
|
39
|
+
}
|
40
|
+
}, Error);
|
41
|
+
|
42
|
+
let answer =
|
43
|
+
'No entry file found in folder "sample_fld". Looking for "sample_fld.md"' +
|
44
|
+
"\n...on line 1 in test/test-files/sample1.md".grey(15);
|
45
|
+
|
46
|
+
util.assert.strictEqual(e.message.replace(/(\\)+/g, "/"), answer);
|
47
|
+
});
|
26
48
|
});
|
package/test/hooks.js
ADDED
package/test/tester.test.js
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
const fs = require("fs");
|
2
2
|
const assert = require("assert");
|
3
3
|
const Parser = require("../build/parse");
|
4
|
-
|
5
|
-
|
4
|
+
const path = require("path");
|
6
5
|
|
7
6
|
/* make folder for temporary files, if it doesn't exist */
|
8
7
|
if (
|
@@ -12,8 +11,16 @@ if (
|
|
12
11
|
fs.mkdirSync("test/test-files");
|
13
12
|
}
|
14
13
|
|
14
|
+
/**
|
15
|
+
* Create a new file under `test/test-files` with the given content.
|
16
|
+
* @param {string} text
|
17
|
+
* @param {string} file
|
18
|
+
*/
|
15
19
|
function put(text, file) {
|
16
|
-
fs.writeFileSync("test
|
20
|
+
fs.writeFileSync(path.join("test", "test-files", file), text);
|
21
|
+
}
|
22
|
+
function putDir(name) {
|
23
|
+
fs.mkdirSync(path.join("test", "test-files", name));
|
17
24
|
}
|
18
25
|
|
19
26
|
const TargetType = {
|
@@ -24,7 +31,9 @@ const TargetType = {
|
|
24
31
|
module.exports = {
|
25
32
|
fs,
|
26
33
|
assert,
|
34
|
+
path,
|
27
35
|
Parser,
|
28
36
|
put,
|
37
|
+
putDir,
|
29
38
|
TargetType,
|
30
39
|
};
|