markdown-maker 1.10.0 → 1.10.2
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/.vscode/launch.json +4 -22
- package/package.json +14 -37
- package/src/cltool.ts +48 -106
- package/src/commands.ts +56 -2
- package/src/main.ts +122 -0
- package/src/{parse.ts → parser.ts} +39 -38
- package/test/advanced.test.js +0 -3
- package/test/basic.test.js +0 -1
- package/test/errors.test.js +0 -1
- package/test/hooks.js +1 -1
- package/test/hooks.test.js +114 -0
- package/test/line.test.js +2 -4
- package/test/target.test.js +40 -32
- package/test/tester.test.js +4 -2
- package/test/vars.test.js +22 -30
- package/tsconfig.json +2 -2
- package/build/cltool.d.ts +0 -1
- package/build/cltool.js +0 -161
- package/build/cltool.js.map +0 -1
- package/build/commands.d.ts +0 -43
- package/build/commands.js +0 -223
- package/build/commands.js.map +0 -1
- package/build/parse.d.ts +0 -65
- package/build/parse.js +0 -281
- package/build/parse.js.map +0 -1
- package/build/templates.d.ts +0 -10
- package/build/templates.js +0 -20
- package/build/templates.js.map +0 -1
- package/doc/.mdmconfig.json +0 -7
- package/doc/main.md +0 -2
- package/doc/other.md +0 -1
- package/re-test.js +0 -10
package/.vscode/launch.json
CHANGED
@@ -4,31 +4,13 @@
|
|
4
4
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
5
5
|
"version": "0.2.0",
|
6
6
|
"configurations": [
|
7
|
-
{
|
8
|
-
"name": "Compile main",
|
9
|
-
"request": "launch",
|
10
|
-
"runtimeArgs": [
|
11
|
-
"run-script",
|
12
|
-
"main"
|
13
|
-
],
|
14
|
-
"runtimeExecutable": "npm",
|
15
|
-
"skipFiles": [
|
16
|
-
"<node_internals>/**"
|
17
|
-
],
|
18
|
-
"type": "pwa-node"
|
19
|
-
},
|
20
7
|
{
|
21
8
|
"name": "Run test",
|
22
9
|
"request": "launch",
|
23
|
-
"runtimeArgs": [
|
24
|
-
"run-script",
|
25
|
-
"test"
|
26
|
-
],
|
10
|
+
"runtimeArgs": ["run-script", "test"],
|
27
11
|
"runtimeExecutable": "npm",
|
28
|
-
"skipFiles": [
|
29
|
-
|
30
|
-
],
|
31
|
-
"type": "pwa-node"
|
12
|
+
"skipFiles": ["<node_internals>/**"],
|
13
|
+
"type": "node"
|
32
14
|
}
|
33
15
|
]
|
34
|
-
}
|
16
|
+
}
|
package/package.json
CHANGED
@@ -1,64 +1,41 @@
|
|
1
1
|
{
|
2
2
|
"name": "markdown-maker",
|
3
|
-
"version": "1.10.
|
4
|
-
"description": "",
|
5
|
-
"main": "src/
|
3
|
+
"version": "1.10.2",
|
4
|
+
"description": "A superset-compiler for markdown using marked",
|
5
|
+
"main": "src/main.ts",
|
6
6
|
"bin": {
|
7
|
-
"mdparse": "
|
8
|
-
},
|
9
|
-
"pkg": {
|
10
|
-
"assets": [
|
11
|
-
"node_modules/argparse/*",
|
12
|
-
"node_modules/chokidar/*",
|
13
|
-
"node_modules/colors/*",
|
14
|
-
"node_modules/colors./*",
|
15
|
-
"node_modules/marked/*",
|
16
|
-
"build/cltool.js",
|
17
|
-
"src/templates/*"
|
18
|
-
],
|
19
|
-
"targets": [
|
20
|
-
"node12-macos-x64",
|
21
|
-
"node12-win-x64",
|
22
|
-
"node12-linux-x64"
|
23
|
-
]
|
7
|
+
"mdparse": "bundle/main.js"
|
24
8
|
},
|
25
9
|
"scripts": {
|
26
10
|
"test": "mocha --require test/hooks.js",
|
27
11
|
"test:yarn": "mocha",
|
28
12
|
"bundle": "tsc --project tsconfig.json",
|
29
|
-
"main": "node
|
30
|
-
"debug": "node src/
|
31
|
-
"
|
32
|
-
"build:yarn": "yarn bundle && pkg --output bin/mdparse .",
|
33
|
-
"clear": "rm -rf dist",
|
34
|
-
"premac-deploy": "npm run build",
|
35
|
-
"mac-deploy": "mv bin/mdparse-macos ~/Documents/commands/mdparse",
|
36
|
-
"prewin-deploy": "npm run build",
|
37
|
-
"win-deploy": "mv bin/mdparse-win.exe ../../commands/mdparse.exe",
|
13
|
+
"main": "node bundle/main.js document/main.md -o dist/bundle.md --debug",
|
14
|
+
"debug": "node src/main.js -db document/main.md -o dist/bundle.md",
|
15
|
+
"clear": "rm -rf bundle bin",
|
38
16
|
"pretest": "npm run bundle",
|
39
|
-
"pretest:yarn": "yarn bundle"
|
40
|
-
"prepare": "npm run build"
|
17
|
+
"pretest:yarn": "yarn bundle"
|
41
18
|
},
|
42
19
|
"keywords": [],
|
43
20
|
"author": "blitzher",
|
44
21
|
"license": "MIT",
|
45
22
|
"dependencies": {
|
46
|
-
"@types/chokidar": "^2.1.3",
|
47
|
-
"@types/colors": "^1.2.1",
|
48
|
-
"@types/node": "^15.6.1",
|
49
|
-
"@types/ws": "^8.5.3",
|
50
23
|
"argparse": "^2.0.1",
|
51
24
|
"chokidar": "^3.5.1",
|
52
|
-
"colors": "^1.4.0",
|
53
25
|
"colors.ts": "^1.0.20",
|
54
26
|
"marked": "^2.0.1",
|
27
|
+
"node-html-parser": "^6.1.13",
|
55
28
|
"require-runtime": "^2.0.0",
|
56
29
|
"ws": "^8.8.1"
|
57
30
|
},
|
58
31
|
"devDependencies": {
|
32
|
+
"@types/argparse": "^2.0.16",
|
33
|
+
"@types/chokidar": "^2.1.3",
|
34
|
+
"@types/colors": "^1.2.1",
|
35
|
+
"@types/node": "^15.6.1",
|
36
|
+
"@types/ws": "^8.5.3",
|
59
37
|
"cloc": "^2.7.0",
|
60
38
|
"mocha": "^8.3.1",
|
61
|
-
"pkg": "^4.4.9",
|
62
39
|
"prettier": "^2.3.0",
|
63
40
|
"typescript": "^4.3.2"
|
64
41
|
}
|
package/src/cltool.ts
CHANGED
@@ -2,21 +2,19 @@ const fs = require("fs"); /* for handling reading of files */
|
|
2
2
|
const path = require("path"); /* for handling file paths */
|
3
3
|
|
4
4
|
import Colors = require("colors.ts"); /* for adding colours to strings */
|
5
|
-
import
|
6
|
-
import
|
5
|
+
import { TargetType } from "./commands";
|
6
|
+
import Parser from "./parser";
|
7
7
|
|
8
8
|
Colors.enable();
|
9
|
-
|
9
|
+
import { ArgumentParser } from "argparse"; /* for parsing clargs */
|
10
10
|
const { version } = require("../package.json"); /* package version number */
|
11
|
-
const choki = require("chokidar");
|
12
11
|
|
13
12
|
export const argParser = new ArgumentParser({
|
14
|
-
description:
|
13
|
+
description:
|
14
|
+
"Markdown bundler, with extra options. Extension file is loaded from ./extensions.js, if it exists",
|
15
15
|
prog: "mdparse",
|
16
16
|
});
|
17
17
|
|
18
|
-
const configFileName = ".mdmconfig.json";
|
19
|
-
|
20
18
|
//#region command line args
|
21
19
|
argParser.add_argument("src", {
|
22
20
|
help: "file to be parsed. If this is a directory, it looks for entry point in the directory, see --entry",
|
@@ -66,103 +64,47 @@ argParser.add_argument("--allow-undefined", "-A", {
|
|
66
64
|
});
|
67
65
|
//#endregion
|
68
66
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
/* We skip [0] and [1], as it is the binary and source file, even when compiled*/
|
88
|
-
for (let i = 2; i < process.argv.length; i++) args.push(process.argv[i]);
|
89
|
-
|
90
|
-
clargs = argParser.parse_args(args);
|
91
|
-
} else {
|
92
|
-
clargs = argParser.parse_args();
|
93
|
-
}
|
94
|
-
|
95
|
-
/* if src is init, create config file and exit */
|
96
|
-
if (clargs.src == "init") {
|
97
|
-
const template = fs.readFileSync(path.join(__dirname, "..", "src", "templates", "configTemplate.json"));
|
98
|
-
fs.writeFileSync(configFileName, template);
|
99
|
-
fs.writeFileSync("main.md", "# Main\n");
|
100
|
-
return;
|
101
|
-
}
|
102
|
-
|
103
|
-
/* helper method for calling parser */
|
104
|
-
const compile = (source, output, cb?) => {
|
105
|
-
/* load data from file, if it exists,
|
106
|
-
* otherwise, interpret as string */
|
107
|
-
|
108
|
-
const parser = new Parser(source, clargs);
|
109
|
-
parser.to(output, (file) => {
|
110
|
-
console.log(`Compiled ${file}`.green);
|
111
|
-
if (cb) cb();
|
112
|
-
});
|
113
|
-
return parser;
|
67
|
+
export type CLArgs = {
|
68
|
+
src: string;
|
69
|
+
output: string;
|
70
|
+
verbose: boolean;
|
71
|
+
debug: boolean;
|
72
|
+
max_depth: number;
|
73
|
+
entry: string;
|
74
|
+
watch: boolean;
|
75
|
+
use_underscore: boolean;
|
76
|
+
toc_level: number;
|
77
|
+
html: boolean;
|
78
|
+
allow_undefined: boolean;
|
79
|
+
};
|
80
|
+
|
81
|
+
export type ParserOptions = {
|
82
|
+
defs: {
|
83
|
+
[key: string]: string;
|
114
84
|
};
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
/* in case source is a directory, look for entry in directory */
|
143
|
-
if (fs.existsSync(clargs.src) && fs.lstatSync(clargs.src).isDirectory()) {
|
144
|
-
clargs.src = path.join(clargs.src, clargs.entry);
|
145
|
-
}
|
146
|
-
|
147
|
-
if (clargs.debug) console.dir(clargs);
|
148
|
-
|
149
|
-
/* compile once */
|
150
|
-
if (!clargs.watch) compile(clargs.src, clargs.output);
|
151
|
-
/* watch the folder and recompile on change */
|
152
|
-
else {
|
153
|
-
const srcDirName = path.dirname(clargs.src);
|
154
|
-
console.log(`Watching ${srcDirName} for changes...`.yellow);
|
155
|
-
server = new WebSocketServer({ port: 7788 });
|
156
|
-
|
157
|
-
const _watcher = choki.watch(srcDirName).on("all", watcher);
|
158
|
-
try {
|
159
|
-
compile(clargs.src, clargs.output);
|
160
|
-
} catch (e) {
|
161
|
-
console.log(e.message);
|
162
|
-
}
|
163
|
-
}
|
164
|
-
|
165
|
-
}
|
166
|
-
|
167
|
-
/* main entrypoint */
|
168
|
-
if (require.main === module) main();
|
85
|
+
secs: {
|
86
|
+
level: number;
|
87
|
+
title: string;
|
88
|
+
}[];
|
89
|
+
args: string[];
|
90
|
+
depth: number;
|
91
|
+
verbose: boolean;
|
92
|
+
debug: boolean;
|
93
|
+
max_depth: number;
|
94
|
+
use_underscore: boolean;
|
95
|
+
toc_level: number;
|
96
|
+
allow_undefined: boolean;
|
97
|
+
html: boolean;
|
98
|
+
watch: boolean;
|
99
|
+
targetType: TargetType | undefined;
|
100
|
+
only_warn: boolean;
|
101
|
+
parent?: Parser;
|
102
|
+
hooks: { [key: string]: () => string };
|
103
|
+
adv_hooks: {
|
104
|
+
[key: string]: (
|
105
|
+
tree: HTMLElement,
|
106
|
+
map: { [tag: string]: HTMLElement }
|
107
|
+
) => HTMLElement;
|
108
|
+
};
|
109
|
+
isFileCallback: (s: string) => false | string;
|
110
|
+
};
|
package/src/commands.ts
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
import * as path from "path";
|
2
|
-
import Parser from "./
|
2
|
+
import Parser from "./parser";
|
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;
|
@@ -128,7 +129,7 @@ new Command(
|
|
128
129
|
|
129
130
|
const recursiveParser = new Parser(
|
130
131
|
path.join(parser.wd, name),
|
131
|
-
parser.
|
132
|
+
parser.clargs,
|
132
133
|
{
|
133
134
|
parent: parser,
|
134
135
|
}
|
@@ -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/main.ts
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
import path from "path";
|
2
|
+
import { WebSocketServer } from "ws";
|
3
|
+
import Parser from "./parser";
|
4
|
+
import * as fs from "fs";
|
5
|
+
const choki = require("chokidar");
|
6
|
+
|
7
|
+
import { argParser, CLArgs as CommmandLineArgs, ParserOptions } from "./cltool";
|
8
|
+
const configFileName = ".mdmconfig.json";
|
9
|
+
|
10
|
+
function main() {
|
11
|
+
let clargs: CommmandLineArgs;
|
12
|
+
let server: WebSocketServer | undefined;
|
13
|
+
|
14
|
+
/* Read config file or parse args from cmd-line */
|
15
|
+
if (fs.existsSync(configFileName)) {
|
16
|
+
let data: CommmandLineArgs = JSON.parse(
|
17
|
+
fs.readFileSync(configFileName).toString()
|
18
|
+
).opts;
|
19
|
+
|
20
|
+
let args: (string | number)[] = [];
|
21
|
+
Object.entries(data).forEach(([key, value]) => {
|
22
|
+
if (key != "src" && value !== false) {
|
23
|
+
args.push("--" + key);
|
24
|
+
}
|
25
|
+
if (typeof value != "boolean") {
|
26
|
+
args.push(value);
|
27
|
+
}
|
28
|
+
});
|
29
|
+
|
30
|
+
/* We skip [0] and [1], as it is the binary and source file, even when compiled*/
|
31
|
+
for (let i = 2; i < process.argv.length; i++)
|
32
|
+
args.push(process.argv[i]);
|
33
|
+
|
34
|
+
clargs = argParser.parse_args(args.map((x) => x.toString()));
|
35
|
+
} else {
|
36
|
+
clargs = argParser.parse_args();
|
37
|
+
}
|
38
|
+
|
39
|
+
/* if src is init, create config file and exit */
|
40
|
+
if (clargs.src == "init") {
|
41
|
+
const template = fs.readFileSync(
|
42
|
+
path.join(
|
43
|
+
__dirname,
|
44
|
+
"..",
|
45
|
+
"src",
|
46
|
+
"templates",
|
47
|
+
"configTemplate.json"
|
48
|
+
)
|
49
|
+
);
|
50
|
+
fs.writeFileSync(configFileName, template);
|
51
|
+
fs.writeFileSync("main.md", "# Main\n");
|
52
|
+
return;
|
53
|
+
}
|
54
|
+
|
55
|
+
/* helper method for calling parser */
|
56
|
+
const compile = (source, output, cb?) => {
|
57
|
+
/* load data from file, if it exists,
|
58
|
+
* otherwise, interpret as string */
|
59
|
+
|
60
|
+
const parser = new Parser(source, clargs);
|
61
|
+
parser.to(output, (file) => {
|
62
|
+
console.log(`Compiled ${file}`.green);
|
63
|
+
if (cb) cb();
|
64
|
+
});
|
65
|
+
return parser;
|
66
|
+
};
|
67
|
+
|
68
|
+
const internalCooldown = 1000;
|
69
|
+
function watcher(event, path) {
|
70
|
+
const now = Date.now();
|
71
|
+
|
72
|
+
if (!this.time) this.time = now;
|
73
|
+
|
74
|
+
if (now - this.time < internalCooldown) return;
|
75
|
+
|
76
|
+
console.log(path);
|
77
|
+
|
78
|
+
console.log(`Detected change in ${path}...`);
|
79
|
+
|
80
|
+
try {
|
81
|
+
compile(clargs.src, clargs.output, () => {
|
82
|
+
/* after compile, send refresh command to clients */
|
83
|
+
server.clients.forEach((client) => {
|
84
|
+
if (client.OPEN) client.send("refresh");
|
85
|
+
});
|
86
|
+
});
|
87
|
+
} catch (e) {
|
88
|
+
console.log(e.message);
|
89
|
+
}
|
90
|
+
|
91
|
+
this.time = now;
|
92
|
+
}
|
93
|
+
|
94
|
+
/* in case source is a directory, look for entry in directory */
|
95
|
+
if (fs.existsSync(clargs.src) && fs.lstatSync(clargs.src).isDirectory()) {
|
96
|
+
clargs.src = path.join(clargs.src, clargs.entry);
|
97
|
+
}
|
98
|
+
|
99
|
+
if (clargs.debug) console.dir(clargs);
|
100
|
+
|
101
|
+
/* compile once */
|
102
|
+
if (!clargs.watch) compile(clargs.src, clargs.output);
|
103
|
+
/* watch the folder and recompile on change */ else {
|
104
|
+
const srcDirName = path.dirname(clargs.src);
|
105
|
+
console.log(`Watching ${srcDirName} for changes...`.yellow);
|
106
|
+
server = new WebSocketServer({ port: 7788 });
|
107
|
+
|
108
|
+
const _watcher = choki.watch(srcDirName).on("all", watcher);
|
109
|
+
try {
|
110
|
+
compile(clargs.src, clargs.output);
|
111
|
+
} catch (e) {
|
112
|
+
console.log(e.message);
|
113
|
+
}
|
114
|
+
}
|
115
|
+
}
|
116
|
+
export default {
|
117
|
+
Parser,
|
118
|
+
};
|
119
|
+
/* main entrypoint */
|
120
|
+
if (require.main === module) {
|
121
|
+
main();
|
122
|
+
}
|
@@ -1,10 +1,12 @@
|
|
1
|
-
|
2
|
-
|
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
|
-
|
6
|
+
import marked from "marked";
|
7
|
+
|
7
8
|
import { Command, commands, load_extensions, MDMError } from "./commands";
|
9
|
+
import { argParser, CLArgs as CommandLineArgs, ParserOptions } from "./cltool";
|
8
10
|
|
9
11
|
enum TargetType {
|
10
12
|
HTML,
|
@@ -22,36 +24,15 @@ class Parser {
|
|
22
24
|
blobs: {
|
23
25
|
[key: number]: string | undefined;
|
24
26
|
};
|
25
|
-
opts:
|
26
|
-
|
27
|
-
[key: string]: string;
|
28
|
-
};
|
29
|
-
secs: {
|
30
|
-
level: number;
|
31
|
-
title: string;
|
32
|
-
}[];
|
33
|
-
args: string[];
|
34
|
-
depth: number;
|
35
|
-
verbose: boolean;
|
36
|
-
debug: boolean;
|
37
|
-
max_depth: number;
|
38
|
-
use_underscore: boolean;
|
39
|
-
toc_level: number;
|
40
|
-
allow_undefined: boolean;
|
41
|
-
html: boolean;
|
42
|
-
watch: boolean;
|
43
|
-
targetType: TargetType | undefined;
|
44
|
-
only_warn: boolean;
|
45
|
-
parent?: Parser;
|
46
|
-
isFileCallback: (s: string) => false | string;
|
47
|
-
};
|
27
|
+
opts: ParserOptions;
|
28
|
+
clargs: CommandLineArgs;
|
48
29
|
raw: string;
|
49
30
|
|
50
31
|
static TOKEN = "#md";
|
51
32
|
|
52
33
|
constructor(
|
53
|
-
filename,
|
54
|
-
clargs,
|
34
|
+
filename: string,
|
35
|
+
clargs?: CommandLineArgs,
|
55
36
|
opts?: {
|
56
37
|
parent?: Parser;
|
57
38
|
isFileCallback?: (s: string) => false | string;
|
@@ -73,6 +54,7 @@ class Parser {
|
|
73
54
|
this.blobs = {};
|
74
55
|
|
75
56
|
/* all options */
|
57
|
+
this.clargs = clargs;
|
76
58
|
this.opts = {
|
77
59
|
defs: {},
|
78
60
|
secs: [],
|
@@ -89,6 +71,8 @@ class Parser {
|
|
89
71
|
targetType: undefined,
|
90
72
|
only_warn: false,
|
91
73
|
parent: undefined,
|
74
|
+
hooks: {},
|
75
|
+
adv_hooks: {},
|
92
76
|
isFileCallback: (f) => {
|
93
77
|
if (!fs.existsSync(f)) return false;
|
94
78
|
return fs.readFileSync(f, "utf-8") + "\n";
|
@@ -96,7 +80,7 @@ class Parser {
|
|
96
80
|
};
|
97
81
|
|
98
82
|
if (!clargs) {
|
99
|
-
clargs =
|
83
|
+
clargs = argParser.parse_args([filename]);
|
100
84
|
}
|
101
85
|
|
102
86
|
/* append all commandline arguments to this */
|
@@ -237,13 +221,27 @@ class Parser {
|
|
237
221
|
const link = this.titleId(title);
|
238
222
|
|
239
223
|
let __line =
|
240
|
-
hor.repeat(Math.max(sec.level - 1, 0)) +
|
224
|
+
hor.repeat(Math.max(sec.level - 1, 0)) +
|
225
|
+
beg +
|
226
|
+
`[${title}](#${link})`;
|
241
227
|
|
242
228
|
__blob.push(__line);
|
243
229
|
});
|
244
230
|
return __blob.join("\n");
|
245
231
|
}
|
246
232
|
|
233
|
+
add_hook(name: string, hook: () => string) {
|
234
|
+
if (this.opts.hooks[name] != undefined)
|
235
|
+
throw new Error(`Hook ${name} already exists!`);
|
236
|
+
this.opts.hooks[name] = hook;
|
237
|
+
}
|
238
|
+
|
239
|
+
add_adv_hook(name: string, hook: (tree: HTMLElement) => HTMLElement) {
|
240
|
+
if (this.opts.hooks[name] != undefined)
|
241
|
+
throw new Error(`Hook ${name} already exists!`);
|
242
|
+
this.opts.adv_hooks[name] = hook;
|
243
|
+
}
|
244
|
+
|
247
245
|
line_num_from_index(index: number) {
|
248
246
|
return this.raw.substring(0, index).split("\n").length + 1;
|
249
247
|
}
|
@@ -258,7 +256,7 @@ class Parser {
|
|
258
256
|
/* output the parsed document to bundle */
|
259
257
|
to(bundleName: string, callback: (fileName: string) => void) {
|
260
258
|
const dir = path.dirname(bundleName);
|
261
|
-
if (callback === undefined) callback = () => {
|
259
|
+
if (callback === undefined) callback = () => {};
|
262
260
|
|
263
261
|
if (!fs.existsSync(dir)) {
|
264
262
|
fs.mkdirSync(dir, { recursive: true });
|
@@ -268,11 +266,11 @@ class Parser {
|
|
268
266
|
this.get(TargetType.MARKDOWN, (blob) => {
|
269
267
|
fs.writeFile(bundleName, blob, () => callback(bundleName));
|
270
268
|
});
|
271
|
-
}
|
272
|
-
|
273
|
-
else {
|
269
|
+
} else {
|
274
270
|
const htmlFileName = bundleName.replace(".md", ".html");
|
275
|
-
fs.writeFile(htmlFileName, this.html(), () =>
|
271
|
+
fs.writeFile(htmlFileName, this.html(), () =>
|
272
|
+
callback(htmlFileName)
|
273
|
+
);
|
276
274
|
}
|
277
275
|
}
|
278
276
|
|
@@ -301,7 +299,7 @@ class Parser {
|
|
301
299
|
let blob = this.parse();
|
302
300
|
this.opts.targetType = undefined;
|
303
301
|
if (callback) callback(blob);
|
304
|
-
return blob
|
302
|
+
return blob;
|
305
303
|
} catch (error) {
|
306
304
|
/* Compile a traceback of error */
|
307
305
|
let traceback = "";
|
@@ -312,7 +310,9 @@ class Parser {
|
|
312
310
|
traceback += `\n...on line ${p.line_num_from_index(
|
313
311
|
error.match.index
|
314
312
|
)} in ${p.file}`.grey(15);
|
315
|
-
else
|
313
|
+
else
|
314
|
+
traceback +=
|
315
|
+
`\n...on line ${p.line_num} in ${p.file}`.grey(15);
|
316
316
|
if (p.parent) p = p.parent;
|
317
317
|
} while (p.parent);
|
318
318
|
|
@@ -353,7 +353,8 @@ marked.use({
|
|
353
353
|
const id = args.filter((arg) => arg.startsWith("#"));
|
354
354
|
|
355
355
|
const classNames = classes.map((c) => c.slice(1));
|
356
|
-
const classText =
|
356
|
+
const classText =
|
357
|
+
classes.length > 0 ? `class="${classNames.join(" ")}"` : "";
|
357
358
|
const idText = id.length > 0 ? `id="${id[0].slice(1)}"` : "";
|
358
359
|
|
359
360
|
/* remove the ending from the quote */
|
package/test/advanced.test.js
CHANGED
@@ -10,7 +10,6 @@ const putTemplate = () => {
|
|
10
10
|
describe("Use of templates", () => {
|
11
11
|
beforeEach(putTemplate);
|
12
12
|
it("should import presentation template as expected", () => {
|
13
|
-
putTemplate();
|
14
13
|
const output = new util.Parser("#mdtemplate<presentation>").get();
|
15
14
|
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>`;
|
16
15
|
|
@@ -18,7 +17,6 @@ describe("Use of templates", () => {
|
|
18
17
|
});
|
19
18
|
|
20
19
|
it("should use custom templates from project extensions.js file", () => {
|
21
|
-
putTemplate();
|
22
20
|
util.put("#mdtemplate<hi>", "sample1.md");
|
23
21
|
|
24
22
|
util.assert.strictEqual(
|
@@ -28,7 +26,6 @@ describe("Use of templates", () => {
|
|
28
26
|
});
|
29
27
|
|
30
28
|
it("should use custom commands from project extensions.js file", () => {
|
31
|
-
putTemplate();
|
32
29
|
util.put("#test_cmd", "sample1.md");
|
33
30
|
|
34
31
|
const parser = new util.Parser("test/test-files/sample1.md");
|