markdown-maker 1.10.0 → 1.10.1

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markdown-maker",
3
- "version": "1.10.0",
3
+ "version": "1.10.1",
4
4
  "description": "",
5
5
  "main": "src/cltool.ts",
6
6
  "bin": {
@@ -52,6 +52,7 @@
52
52
  "colors": "^1.4.0",
53
53
  "colors.ts": "^1.0.20",
54
54
  "marked": "^2.0.1",
55
+ "node-html-parser": "^6.1.13",
55
56
  "require-runtime": "^2.0.0",
56
57
  "ws": "^8.8.1"
57
58
  },
package/src/commands.ts CHANGED
@@ -3,6 +3,7 @@ import Parser from "./parse";
3
3
  import * as fs from "fs";
4
4
  import templates, { new_template } from "./templates";
5
5
  import requireRuntime from "require-runtime";
6
+ import * as nodeHtmlParser from "node-html-parser";
6
7
 
7
8
  export class MDMError extends Error {
8
9
  match: RegExpMatchArray;
@@ -207,12 +208,65 @@ new Command(
207
208
  CommandType.PARSE
208
209
  );
209
210
 
211
+ /* mdmaketoc */
210
212
  new Command(
211
213
  /#mdmaketoc(?:<>)?/,
212
214
  (match, parser) => parser.gen_toc(),
213
215
  CommandType.POSTPARSE
214
216
  );
215
217
 
218
+ /* basic mdhook */
219
+ new Command(
220
+ /#mdhook<(\w+)>/,
221
+ (match, parser) => {
222
+ if (parser.opts.hooks[match[1]]) {
223
+ return parser.opts.hooks[match[1]]();
224
+ }
225
+ },
226
+ CommandType.POSTPARSE
227
+ );
228
+
229
+ /* mdadvhook */
230
+ new Command(
231
+ /\#mdadvhook<(\w+)>([\w\W]+?)\#mdendhook/,
232
+ (match, parser) => {
233
+ if (parser.opts.adv_hooks[match[1]]) {
234
+ const innerElements = match[2].trim();
235
+ /* Find tagNames in innerElements */
236
+ const re = /<(\w+)[\s=\w\"\'-]*>/g;
237
+ const tags = [];
238
+ innerElements.match(re)?.forEach((tag) => {
239
+ tags.push(tag.slice(1, -1).split(" ")[0]);
240
+ });
241
+ /* Evil type hack */
242
+ const root = nodeHtmlParser.parse(innerElements, {
243
+ voidTag: {
244
+ tags,
245
+ closingSlash: true,
246
+ },
247
+ }) as any as HTMLElement;
248
+
249
+ const helper = (node: HTMLElement) => {
250
+ /* */
251
+ const map: { [tag: string]: HTMLElement } = {};
252
+ for (let tag of tags) {
253
+ const el = node.getElementsByTagName(tag)[0];
254
+ const dataTag = el.toString().match(/data-tag="([\w-]+)"/);
255
+ if (!dataTag || dataTag[1] == undefined) continue;
256
+ el.tagName = dataTag[1];
257
+ el.removeAttribute("data-tag");
258
+ map[tag] = el;
259
+ }
260
+ return map;
261
+ };
262
+
263
+ const hooked = parser.opts.adv_hooks[match[1]](root, helper(root));
264
+ return hooked.toString();
265
+ }
266
+ },
267
+ CommandType.POSTPARSE
268
+ );
269
+
216
270
  const loaded_extentions: fs.PathLike[] = [];
217
271
 
218
272
  function load_extension(parser: Parser, file: fs.PathLike) {
package/src/parse.ts CHANGED
@@ -1,9 +1,10 @@
1
- const fs = require("fs"); /* for handling reading of files */
2
- const path = require("path"); /* for handling file paths */
1
+ import fs from "fs"; /* for handling reading of files */
2
+ import path from "path"; /* for handling file paths */
3
3
 
4
4
  import Colors = require("colors.ts"); /* for adding colours to strings */
5
5
  Colors.enable();
6
- const marked = require("marked");
6
+ import marked from "marked";
7
+
7
8
  import { Command, commands, load_extensions, MDMError } from "./commands";
8
9
 
9
10
  enum TargetType {
@@ -43,6 +44,13 @@ class Parser {
43
44
  targetType: TargetType | undefined;
44
45
  only_warn: boolean;
45
46
  parent?: Parser;
47
+ hooks: { [key: string]: () => string };
48
+ adv_hooks: {
49
+ [key: string]: (
50
+ tree: HTMLElement,
51
+ map: { [tag: string]: HTMLElement }
52
+ ) => HTMLElement;
53
+ };
46
54
  isFileCallback: (s: string) => false | string;
47
55
  };
48
56
  raw: string;
@@ -89,6 +97,8 @@ class Parser {
89
97
  targetType: undefined,
90
98
  only_warn: false,
91
99
  parent: undefined,
100
+ hooks: {},
101
+ adv_hooks: {},
92
102
  isFileCallback: (f) => {
93
103
  if (!fs.existsSync(f)) return false;
94
104
  return fs.readFileSync(f, "utf-8") + "\n";
@@ -237,13 +247,27 @@ class Parser {
237
247
  const link = this.titleId(title);
238
248
 
239
249
  let __line =
240
- hor.repeat(Math.max(sec.level - 1, 0)) + beg + `[${title}](#${link})`;
250
+ hor.repeat(Math.max(sec.level - 1, 0)) +
251
+ beg +
252
+ `[${title}](#${link})`;
241
253
 
242
254
  __blob.push(__line);
243
255
  });
244
256
  return __blob.join("\n");
245
257
  }
246
258
 
259
+ add_hook(name: string, hook: () => string) {
260
+ if (this.opts.hooks[name] != undefined)
261
+ throw new Error(`Hook ${name} already exists!`);
262
+ this.opts.hooks[name] = hook;
263
+ }
264
+
265
+ add_adv_hook(name: string, hook: (tree: HTMLElement) => HTMLElement) {
266
+ if (this.opts.hooks[name] != undefined)
267
+ throw new Error(`Hook ${name} already exists!`);
268
+ this.opts.adv_hooks[name] = hook;
269
+ }
270
+
247
271
  line_num_from_index(index: number) {
248
272
  return this.raw.substring(0, index).split("\n").length + 1;
249
273
  }
@@ -258,7 +282,7 @@ class Parser {
258
282
  /* output the parsed document to bundle */
259
283
  to(bundleName: string, callback: (fileName: string) => void) {
260
284
  const dir = path.dirname(bundleName);
261
- if (callback === undefined) callback = () => { };
285
+ if (callback === undefined) callback = () => {};
262
286
 
263
287
  if (!fs.existsSync(dir)) {
264
288
  fs.mkdirSync(dir, { recursive: true });
@@ -268,11 +292,11 @@ class Parser {
268
292
  this.get(TargetType.MARKDOWN, (blob) => {
269
293
  fs.writeFile(bundleName, blob, () => callback(bundleName));
270
294
  });
271
- }
272
-
273
- else {
295
+ } else {
274
296
  const htmlFileName = bundleName.replace(".md", ".html");
275
- fs.writeFile(htmlFileName, this.html(), () => callback(htmlFileName));
297
+ fs.writeFile(htmlFileName, this.html(), () =>
298
+ callback(htmlFileName)
299
+ );
276
300
  }
277
301
  }
278
302
 
@@ -301,7 +325,7 @@ class Parser {
301
325
  let blob = this.parse();
302
326
  this.opts.targetType = undefined;
303
327
  if (callback) callback(blob);
304
- return blob
328
+ return blob;
305
329
  } catch (error) {
306
330
  /* Compile a traceback of error */
307
331
  let traceback = "";
@@ -312,7 +336,9 @@ class Parser {
312
336
  traceback += `\n...on line ${p.line_num_from_index(
313
337
  error.match.index
314
338
  )} in ${p.file}`.grey(15);
315
- else traceback += `\n...on line ${p.line_num} in ${p.file}`.grey(15);
339
+ else
340
+ traceback +=
341
+ `\n...on line ${p.line_num} in ${p.file}`.grey(15);
316
342
  if (p.parent) p = p.parent;
317
343
  } while (p.parent);
318
344
 
@@ -353,7 +379,8 @@ marked.use({
353
379
  const id = args.filter((arg) => arg.startsWith("#"));
354
380
 
355
381
  const classNames = classes.map((c) => c.slice(1));
356
- const classText = classes.length > 0 ? `class="${classNames.join(" ")}"` : "";
382
+ const classText =
383
+ classes.length > 0 ? `class="${classNames.join(" ")}"` : "";
357
384
  const idText = id.length > 0 ? `id="${id[0].slice(1)}"` : "";
358
385
 
359
386
  /* remove the ending from the quote */
@@ -1,4 +1,3 @@
1
- const path = require("path");
2
1
  const util = require("./tester.test.js");
3
2
 
4
3
  describe("Basic features", () => {
@@ -1,5 +1,4 @@
1
1
  const util = require("./tester.test.js");
2
- const fs = require("fs");
3
2
 
4
3
  describe("Error handling", () => {
5
4
  it("should dissallow undefined templates", () => {
package/test/hooks.js CHANGED
@@ -2,7 +2,7 @@ const fs = require("fs");
2
2
 
3
3
  exports.mochaHooks = {
4
4
  beforeEach(done) {
5
- fs.rmdirSync("test/test-files", { recursive: true });
5
+ fs.rmSync("test/test-files", { recursive: true });
6
6
  fs.mkdirSync("test/test-files");
7
7
  done();
8
8
  },
@@ -0,0 +1,114 @@
1
+ const util = require("./tester.test.js");
2
+
3
+ describe("Use of markdown hooks for SSR", () => {
4
+ it("should allow a simple hook to be used", () => {
5
+ util.put("#mdhook<test>", "sample1.md");
6
+
7
+ const parser = new util.Parser("test/test-files/sample1.md");
8
+ parser.add_hook("test", () => "hello");
9
+ const output = parser.get();
10
+
11
+ util.assert.strictEqual(output, "hello\n\n");
12
+ });
13
+ it("should allow advanced hooks to be used", () => {
14
+ util.put(
15
+ "#mdadvhook<test>\n<b>Bold</b>\n<p>Paragraph</p>\n#mdendhook",
16
+ "sample1.md"
17
+ );
18
+
19
+ const replacer = (arg) => {
20
+ const elem = new util.html.HTMLElement("p", {});
21
+ elem.set_content("complete");
22
+ return elem;
23
+ };
24
+
25
+ const parser = new util.Parser("test/test-files/sample1.md");
26
+ parser.opts.allow_undefined = true;
27
+ parser.add_adv_hook("test", replacer);
28
+ const output = parser.get();
29
+
30
+ util.assert.strictEqual(output, "<p>complete</p>\n\n");
31
+ });
32
+ it("should allow for hooks to be used in HTML", () => {
33
+ util.put("<html><body>#mdhook<test></body></html>", "sample1.html");
34
+
35
+ const parser = new util.Parser("test/test-files/sample1.html");
36
+ parser.opts.allow_undefined = true;
37
+ parser.add_hook("test", () => "hello");
38
+ const output = parser.get();
39
+
40
+ util.assert.strictEqual(output, "<html><body>hello</body></html>\n\n");
41
+ });
42
+ it("should allow for hooks to be used in HTML with advanced hooks", () => {
43
+ util.put(
44
+ "<html><body>#mdadvhook<test>\n<b>Bold</b>\n<p>Paragraph</p>\n#mdendhook</body></html>",
45
+ "sample1.html"
46
+ );
47
+
48
+ const replacer = (arg) => {
49
+ const elem = new util.html.HTMLElement("p", {});
50
+ elem.set_content("complete");
51
+ return elem;
52
+ };
53
+
54
+ const parser = new util.Parser("test/test-files/sample1.html");
55
+ parser.opts.allow_undefined = true;
56
+ parser.add_adv_hook("test", replacer);
57
+ const output = parser.get();
58
+
59
+ util.assert.strictEqual(
60
+ output,
61
+ "<html><body><p>complete</p></body></html>\n\n"
62
+ );
63
+ });
64
+ it("should allow for extracting a node from the document as a template manually with ids", () => {
65
+ util.put(
66
+ `<html><body>#mdadvhook<template><name id="b"></name><class id="p"></class>#mdendhook</body></html>`,
67
+ "sample1.html"
68
+ );
69
+
70
+ const replacer = (elem) => {
71
+ const nameElem = elem.getElementsByTagName("name")[0];
72
+ nameElem.tagName = nameElem.id;
73
+ nameElem.removeAttribute("id");
74
+ nameElem.set_content("bold");
75
+ const classElem = elem.getElementsByTagName("class")[0];
76
+ classElem.tagName = classElem.id;
77
+ classElem.removeAttribute("id");
78
+ classElem.set_content("paragraph");
79
+ return elem;
80
+ };
81
+
82
+ const parser = new util.Parser("test/test-files/sample1.html");
83
+ parser.opts.allow_undefined = true;
84
+ parser.add_adv_hook("template", replacer);
85
+ const output = parser.get();
86
+
87
+ util.assert.strictEqual(
88
+ output,
89
+ "<html><body><b>bold</b><p>paragraph</p></body></html>\n\n"
90
+ );
91
+ });
92
+ it("should allow for extracting a node from the document as a template using map and data-tags", () => {
93
+ util.put(
94
+ `<html><body>#mdadvhook<template><name data-tag="b"></name><class data-tag="p"></class>#mdendhook</body></html>`,
95
+ "sample1.html"
96
+ );
97
+
98
+ const replacer = (elem, map) => {
99
+ map["name"].set_content("bold");
100
+ map["class"].set_content("paragraph");
101
+ return elem;
102
+ };
103
+
104
+ const parser = new util.Parser("test/test-files/sample1.html");
105
+ parser.opts.allow_undefined = true;
106
+ parser.add_adv_hook("template", replacer);
107
+ const output = parser.get();
108
+
109
+ util.assert.strictEqual(
110
+ output,
111
+ "<html><body><b>bold</b><p>paragraph</p></body></html>\n\n"
112
+ );
113
+ });
114
+ });
package/test/line.test.js CHANGED
@@ -3,7 +3,7 @@ const util = require("./tester.test");
3
3
  describe("Managing blank lines", () => {
4
4
  it("should always end with 2 blank lines, even with no input", () => {
5
5
  const output = new util.Parser("").get();
6
- util.assert.strictEqual(output, "\n\n")
6
+ util.assert.strictEqual(output, "\n\n");
7
7
  });
8
8
 
9
9
  it("should reduce blank lines to 2", () => {
@@ -16,8 +16,6 @@ describe("Managing blank lines", () => {
16
16
 
17
17
  it("should allow words when removing blank lines", () => {
18
18
  const output = new util.Parser("hii\n\n\n").get();
19
- util.assert.strictEqual(output, "hii\n\n")
19
+ util.assert.strictEqual(output, "hii\n\n");
20
20
  });
21
21
  });
22
-
23
-
@@ -1,35 +1,43 @@
1
1
  const util = require("./tester.test.js");
2
2
 
3
3
  describe("Target specific functionality", () => {
4
-
5
- describe("HTML", () => {
6
- it("Should include `#mdlabel` command, when compiling HTML", () => {
7
- const parser = new util.Parser("#mdlabel<0,Cool!>");
8
- const html = parser.get(util.TargetType.HTML);
9
-
10
- util.assert.strictEqual(html, '<span id="cool"></span>\n\n')
11
- });
12
-
13
- it("Should link to sections with #mdref", () => {
14
- const parser = new util.Parser("#mdlabel<0,Cool!>\n#mdlabel<1,coolzz>\n#mdref<Cool!>");
15
- const html = parser.get(util.TargetType.HTML);
16
-
17
- util.assert.strictEqual(html, '<span id="cool"></span>\n<span id="coolzz"></span>\n<a href="#cool">Cool!</a>\n\n');
18
- })
19
- });
20
-
21
- describe("Markdown", () => {
22
- it("Should not include `#mdlabel` command, when compiling Markdown", () => {
23
- const parser = new util.Parser("#mdlabel<0,Cool!>");
24
-
25
- const md = parser.get(util.TargetType.MARKDOWN);
26
- util.assert.strictEqual(md, '\n\n')
27
- });
28
- it("Should include #mdref to title elements in markdown", () => {
29
- const output = new util.Parser("# Some Title!\n#mdref<Some Title!>").get();
30
-
31
- util.assert.strictEqual(output, '# Some Title!\n[Some Title!](#some-title)\n\n')
32
- });
33
-
34
- })
35
- });
4
+ describe("HTML", () => {
5
+ it("Should include `#mdlabel` command, when compiling HTML", () => {
6
+ const parser = new util.Parser("#mdlabel<0,Cool!>");
7
+ const html = parser.get(util.TargetType.HTML);
8
+
9
+ util.assert.strictEqual(html, '<span id="cool"></span>\n\n');
10
+ });
11
+
12
+ it("Should link to sections with #mdref", () => {
13
+ const parser = new util.Parser(
14
+ "#mdlabel<0,Cool!>\n#mdlabel<1,coolzz>\n#mdref<Cool!>"
15
+ );
16
+ const html = parser.get(util.TargetType.HTML);
17
+
18
+ util.assert.strictEqual(
19
+ html,
20
+ '<span id="cool"></span>\n<span id="coolzz"></span>\n<a href="#cool">Cool!</a>\n\n'
21
+ );
22
+ });
23
+ });
24
+
25
+ describe("Markdown", () => {
26
+ it("Should not include `#mdlabel` command, when compiling Markdown", () => {
27
+ const parser = new util.Parser("#mdlabel<0,Cool!>");
28
+
29
+ const md = parser.get(util.TargetType.MARKDOWN);
30
+ util.assert.strictEqual(md, "\n\n");
31
+ });
32
+ it("Should include #mdref to title elements in markdown", () => {
33
+ const output = new util.Parser(
34
+ "# Some Title!\n#mdref<Some Title!>"
35
+ ).get();
36
+
37
+ util.assert.strictEqual(
38
+ output,
39
+ "# Some Title!\n[Some Title!](#some-title)\n\n"
40
+ );
41
+ });
42
+ });
43
+ });
@@ -2,6 +2,7 @@ const fs = require("fs");
2
2
  const assert = require("assert");
3
3
  const Parser = require("../build/parse");
4
4
  const path = require("path");
5
+ const html = require("node-html-parser");
5
6
 
6
7
  /* make folder for temporary files, if it doesn't exist */
7
8
  if (
@@ -29,8 +30,9 @@ const TargetType = {
29
30
  };
30
31
 
31
32
  module.exports = {
32
- fs,
33
33
  assert,
34
+ fs,
35
+ html,
34
36
  path,
35
37
  Parser,
36
38
  put,
package/test/vars.test.js CHANGED
@@ -1,57 +1,49 @@
1
- const util = require("./tester.test");
1
+ const util = require("./tester.test.js");
2
2
 
3
3
  describe("Use variables", () => {
4
- it('should replace var with the value', () => {
4
+ it("should replace var with the value", () => {
5
5
  const output = new util.Parser("#mddef<hi=yo>\n#mdvar<hi>").get();
6
6
 
7
- util.assert.strictEqual(output, "\nyo\n\n")
7
+ util.assert.strictEqual(output, "\nyo\n\n");
8
8
  });
9
- it('should use variable shorthand', () => {
9
+ it("should use variable shorthand", () => {
10
10
  const output = new util.Parser("#mddef<hi=yo>\n<hi>").get();
11
11
 
12
- util.assert.strictEqual(output, "\nyo\n\n")
12
+ util.assert.strictEqual(output, "\nyo\n\n");
13
13
  });
14
- it('should use variables across files', () => {
14
+ it("should use variables across files", () => {
15
15
  util.put("#mddef<hi=yo>\n#mdinclude<sample2.md>", "sample1.md");
16
16
  util.put("<hi>", "sample2.md");
17
17
 
18
18
  const output = new util.Parser("test/test-files/sample1.md").get();
19
19
 
20
- util.assert.strictEqual(output, "\nyo\n\n")
21
- })
22
- it('should throw if undefined variable', () => {
23
-
20
+ util.assert.strictEqual(output, "\nyo\n\n");
21
+ });
22
+ it("should throw if undefined variable", () => {
24
23
  const parser = new util.Parser("<yo>");
25
24
 
26
25
  let e;
27
26
  /* should throw an error */
28
- util.assert.throws(
29
- () => {
30
- try {
31
- parser.get();
32
- } catch (_e) {
33
- e = _e;
34
- throw _e;
35
- }
27
+ util.assert.throws(() => {
28
+ try {
29
+ parser.get();
30
+ } catch (_e) {
31
+ e = _e;
32
+ throw _e;
36
33
  }
37
- );
38
-
39
-
40
-
34
+ });
41
35
  });
42
36
 
43
- it('should preserve whatever comes after', () => {
37
+ it("should preserve whatever comes after", () => {
44
38
  const output = new util.Parser("#mddef<hi=yo>\n<hi>,").get();
45
39
  util.assert.strictEqual(output, "\nyo,\n\n");
46
40
  });
47
41
 
48
- it('should replace underscore with space', () => {
49
- const output = new util.Parser("#mddef<name=Mr_Sir>\n#mdvar<name>").get();
42
+ it("should replace underscore with space", () => {
43
+ const output = new util.Parser(
44
+ "#mddef<name=Mr_Sir>\n#mdvar<name>"
45
+ ).get();
50
46
 
51
- util.assert.strictEqual(output, "\nMr Sir\n\n")
47
+ util.assert.strictEqual(output, "\nMr Sir\n\n");
52
48
  });
53
-
54
49
  });
55
-
56
-
57
-
package/build/cltool.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare const argParser: any;