markdown-maker 1.10.2 → 1.10.4
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/.github/workflows/node.js.yml +21 -26
- package/.vscode/extensions.json +3 -0
- package/.vscode/settings.json +8 -3
- package/.vscode/snippets.code-snippets +6 -8
- package/bundle/cltool.d.ts +86 -0
- package/bundle/cltool.js +63 -0
- package/bundle/cltool.js.map +1 -0
- package/bundle/commands.d.ts +23 -0
- package/bundle/commands.js +303 -0
- package/bundle/commands.js.map +1 -0
- package/bundle/errors.d.ts +11 -0
- package/bundle/errors.js +51 -0
- package/bundle/errors.js.map +1 -0
- package/bundle/main.d.ts +6 -0
- package/bundle/main.js +152 -0
- package/bundle/main.js.map +1 -0
- package/bundle/parser.d.ts +35 -0
- package/bundle/parser.js +330 -0
- package/bundle/parser.js.map +1 -0
- package/bundle/templates/mathjax.d.ts +2 -0
- package/bundle/templates/mathjax.js +3 -0
- package/bundle/templates/mathjax.js.map +1 -0
- package/bundle/templates/presentation.d.ts +2 -0
- package/bundle/templates/presentation.js +3 -0
- package/bundle/templates/presentation.js.map +1 -0
- package/bundle/templates.d.ts +10 -0
- package/bundle/templates.js +23 -0
- package/bundle/templates.js.map +1 -0
- package/bundle/types.d.ts +28 -0
- package/bundle/types.js +15 -0
- package/bundle/types.js.map +1 -0
- package/bundle/version.d.ts +1 -0
- package/bundle/version.js +5 -0
- package/bundle/version.js.map +1 -0
- package/jest.config.js +7 -0
- package/package.json +42 -40
- package/src/cltool.ts +115 -72
- package/src/commands.ts +257 -241
- package/src/errors.ts +26 -0
- package/src/main.ts +114 -109
- package/src/parser.ts +378 -350
- package/src/templates.ts +5 -1
- package/src/types.ts +33 -0
- package/src/version.ts +1 -0
- package/tests/_test-util.ts +44 -0
- package/tests/advanced.spec.ts +102 -0
- package/tests/basic.spec.ts +68 -0
- package/tests/clargs.spec.ts +50 -0
- package/tests/errors.spec.ts +64 -0
- package/tests/html.spec.ts +23 -0
- package/tests/line.spec.ts +21 -0
- package/tests/marked.spec.ts +40 -0
- package/tests/target.spec.ts +41 -0
- package/tests/vars.spec.ts +45 -0
- package/tsconfig.json +66 -64
- package/prettierrc.yaml +0 -4
- package/test/advanced.test.js +0 -34
- package/test/basic.test.js +0 -67
- package/test/clargs.test.js +0 -51
- package/test/errors.test.js +0 -47
- package/test/hooks.js +0 -9
- package/test/hooks.test.js +0 -114
- package/test/html.test.js +0 -37
- package/test/line.test.js +0 -21
- package/test/marked.test.js +0 -43
- package/test/target.test.js +0 -43
- package/test/tester.test.js +0 -41
- package/test/vars.test.js +0 -49
package/src/commands.ts
CHANGED
@@ -4,293 +4,309 @@ import * as fs from "fs";
|
|
4
4
|
import templates, { new_template } from "./templates";
|
5
5
|
import requireRuntime from "require-runtime";
|
6
6
|
import * as nodeHtmlParser from "node-html-parser";
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
}
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
parse: [],
|
24
|
-
postparse: [],
|
7
|
+
import { HTMLElement } from "node-html-parser";
|
8
|
+
import crypto from "crypto";
|
9
|
+
import {
|
10
|
+
CommandGroupType,
|
11
|
+
CommandType,
|
12
|
+
TaggedElement,
|
13
|
+
TargetType,
|
14
|
+
} from "./types";
|
15
|
+
import { MDMError } from "./errors";
|
16
|
+
|
17
|
+
const salt = crypto.randomBytes(2).toString("hex");
|
18
|
+
|
19
|
+
export const commands: CommandGroupType = {
|
20
|
+
preparse: [],
|
21
|
+
parse: [],
|
22
|
+
postparse: [],
|
25
23
|
};
|
26
24
|
|
27
|
-
export enum CommandType {
|
28
|
-
PREPARSE,
|
29
|
-
PARSE,
|
30
|
-
POSTPARSE,
|
31
|
-
}
|
32
|
-
|
33
|
-
export enum TargetType {
|
34
|
-
HTML,
|
35
|
-
MARKDOWN,
|
36
|
-
}
|
37
|
-
|
38
25
|
export class Command {
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
26
|
+
validator: RegExp;
|
27
|
+
acter: (match: RegExpExecArray, parser: Parser) => string | void;
|
28
|
+
type: CommandType;
|
29
|
+
|
30
|
+
constructor(
|
31
|
+
validator: RegExp,
|
32
|
+
acter: (match: RegExpExecArray, parser: Parser) => string | void,
|
33
|
+
type: CommandType
|
34
|
+
) {
|
35
|
+
validator = new RegExp(validator.source, validator.flags);
|
36
|
+
this.validator = validator;
|
37
|
+
this.acter = acter;
|
38
|
+
this.type = type;
|
39
|
+
|
40
|
+
/* add this function to appropriate file */
|
41
|
+
switch (type) {
|
42
|
+
case CommandType.PARSE:
|
43
|
+
commands.parse.push(this);
|
44
|
+
break;
|
45
|
+
case CommandType.PREPARSE:
|
46
|
+
commands.preparse.push(this);
|
47
|
+
break;
|
48
|
+
case CommandType.POSTPARSE:
|
49
|
+
commands.postparse.push(this);
|
50
|
+
break;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
act(match: RegExpExecArray, parser: Parser) {
|
55
|
+
return this.acter(match, parser);
|
56
|
+
}
|
69
57
|
}
|
70
58
|
|
71
59
|
/* variable shorthand */
|
72
60
|
new Command(
|
73
|
-
|
74
|
-
|
75
|
-
|
61
|
+
/(\s|^)!<(.+)>/,
|
62
|
+
(match, parser) => `${match[1]}#mdvar<${match[2]}>`,
|
63
|
+
CommandType.PREPARSE
|
76
64
|
);
|
77
65
|
|
78
66
|
/* mddef */
|
79
67
|
new Command(
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
68
|
+
/#mddef< *(.+?) *= *(.+?) *>/ /* first .+ is lazy so as to not match following spaces */,
|
69
|
+
(match, parser) => {
|
70
|
+
parser.opts.defs[match[1]] = match[2].replace("_", " ");
|
71
|
+
},
|
72
|
+
CommandType.PARSE
|
85
73
|
);
|
86
74
|
|
87
75
|
/* mdvar */
|
88
76
|
new Command(
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
77
|
+
/#mdvar<(.+?)>/,
|
78
|
+
(match, parser) => {
|
79
|
+
let value = parser.opts.defs[match[1]];
|
80
|
+
if (!value && !parser.opts.allow_undefined)
|
81
|
+
throw new MDMError(`Undefined variable: ${match[1]}`, match);
|
82
|
+
return (value = value || `<${match[1]}>`);
|
83
|
+
},
|
84
|
+
CommandType.PARSE
|
97
85
|
);
|
98
86
|
|
99
87
|
/** mdinclude */
|
100
88
|
new Command(
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
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
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
parser.opts.depth--;
|
150
|
-
return blob;
|
151
|
-
},
|
152
|
-
CommandType.PARSE
|
89
|
+
/#mdinclude<([\w.\/-]+)(?:[,\s]+([\w]+))?>/,
|
90
|
+
(match, parser) => {
|
91
|
+
/* increment the current recursion depth */
|
92
|
+
parser.opts.depth++;
|
93
|
+
|
94
|
+
if (parser.opts.depth > parser.opts.max_depth) {
|
95
|
+
throw new MDMError("max depth exceeded!", match);
|
96
|
+
}
|
97
|
+
|
98
|
+
/* get the matching group */
|
99
|
+
let [_, name, condition] = match;
|
100
|
+
|
101
|
+
/* implement conditional imports */
|
102
|
+
if (condition && !parser.opts.args.includes(condition)) return;
|
103
|
+
|
104
|
+
const fsstat = fs.lstatSync(path.join(parser.wd, name));
|
105
|
+
if (fsstat.isDirectory()) {
|
106
|
+
/* check if a file with the same name of the
|
107
|
+
* exists in the folder */
|
108
|
+
|
109
|
+
const entry = path.join(parser.wd, name, `${name}.md`);
|
110
|
+
if (fs.existsSync(entry)) {
|
111
|
+
name = path.join(name, `${name}.md`);
|
112
|
+
} else {
|
113
|
+
throw new MDMError(
|
114
|
+
`No entry file found in folder "${name}". Looking for "${entry}"`,
|
115
|
+
match
|
116
|
+
);
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
const recursiveParser = parser.createChild(path.join(parser.wd, name));
|
121
|
+
|
122
|
+
/* keep the options the same */
|
123
|
+
recursiveParser.opts = parser.opts;
|
124
|
+
recursiveParser.parent = parser;
|
125
|
+
|
126
|
+
const fileType = path.extname(recursiveParser.file);
|
127
|
+
|
128
|
+
const blob =
|
129
|
+
fileType === ".md"
|
130
|
+
? recursiveParser.get(parser.opts.targetType)
|
131
|
+
: recursiveParser.raw;
|
132
|
+
|
133
|
+
parser.opts.depth--;
|
134
|
+
return blob;
|
135
|
+
},
|
136
|
+
CommandType.PARSE
|
153
137
|
);
|
154
138
|
|
155
139
|
/* mdlabel */
|
156
140
|
new Command(
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
141
|
+
/#mdlabel<(\d+),\s?(.+)>/,
|
142
|
+
(match, parser) => {
|
143
|
+
if (parser.opts.targetType !== TargetType.HTML) return "";
|
144
|
+
|
145
|
+
const level = Number.parseInt(match[1]);
|
146
|
+
const title = match[2];
|
147
|
+
const link = parser.titleId(title);
|
148
|
+
parser.opts.secs.push({ level, title });
|
149
|
+
return `<span id="${link}"></span>`;
|
150
|
+
},
|
151
|
+
CommandType.PREPARSE
|
168
152
|
);
|
169
153
|
|
170
154
|
/* mdref */
|
171
155
|
new Command(
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
156
|
+
/#mdref<(.+)>/,
|
157
|
+
|
158
|
+
(match, parser) => {
|
159
|
+
for (let i = 0; i < parser.opts.secs.length; i++) {
|
160
|
+
let { title } = parser.opts.secs[i];
|
161
|
+
if (title === match[1]) break;
|
162
|
+
|
163
|
+
if (i === parser.opts.secs.length - 1)
|
164
|
+
throw new MDMError(
|
165
|
+
`Reference to [${match[1]}] could not be resolved!`,
|
166
|
+
match
|
167
|
+
);
|
168
|
+
}
|
169
|
+
|
170
|
+
match[1] = match[1].replace("_", " ");
|
171
|
+
const link = parser.titleId(match[1]);
|
172
|
+
if (parser.opts.targetType === TargetType.HTML)
|
173
|
+
return `<a href="#${link}">${match[1]}</a>`;
|
174
|
+
else if (parser.opts.targetType === TargetType.MARKDOWN)
|
175
|
+
return `[${match[1]}](#${link})`;
|
176
|
+
},
|
177
|
+
CommandType.PARSE
|
193
178
|
);
|
194
179
|
|
195
180
|
/* mdtemplate */
|
196
181
|
new Command(
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
182
|
+
/#mdtemplate<(\w+?)>/,
|
183
|
+
(match, parser) => {
|
184
|
+
const template = match[1];
|
185
|
+
const replacement = templates[template];
|
186
|
+
|
187
|
+
if (replacement !== undefined) {
|
188
|
+
return replacement;
|
189
|
+
} else {
|
190
|
+
throw new MDMError(`Template \"${template}\" not found!`, match);
|
191
|
+
}
|
192
|
+
},
|
193
|
+
CommandType.PARSE
|
209
194
|
);
|
210
195
|
|
211
196
|
/* mdmaketoc */
|
212
197
|
new Command(
|
213
|
-
|
214
|
-
|
215
|
-
|
198
|
+
/#mdmaketoc(?:<>)?/,
|
199
|
+
(match, parser) => parser.get_toc(),
|
200
|
+
CommandType.POSTPARSE
|
216
201
|
);
|
217
202
|
|
218
|
-
/*
|
203
|
+
/* mdadvhook */
|
219
204
|
new Command(
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
205
|
+
/\#mdhook<(\w+)>([\w\W]+)\#mdendhook<\1>/m,
|
206
|
+
(match, parser) => {
|
207
|
+
if (!parser.opts.hooks[match[1]])
|
208
|
+
throw new MDMError(`No advanced hook found for ${match[1]}`, match);
|
209
|
+
|
210
|
+
const innerElements = match[2].trim();
|
211
|
+
|
212
|
+
/* Run the inner elements through the parser itself */
|
213
|
+
const innerParser = parser.createChild(innerElements);
|
214
|
+
|
215
|
+
/* parse the inner */
|
216
|
+
let innerBlob = innerParser.get(parser.opts.targetType).trim();
|
217
|
+
|
218
|
+
/* Find all tagged elements in inner */
|
219
|
+
/* and construct helper map */
|
220
|
+
const re = /<(\w+)::(\w+)([\s=\w\"\'-]*)>/g;
|
221
|
+
const map: { [key: string]: TaggedElement } = {};
|
222
|
+
for (let match of innerBlob.matchAll(re)) {
|
223
|
+
const args = Array.from(match[3].matchAll(/(\w+)=["'](.+?)["']/g));
|
224
|
+
const argsMap = Object.fromEntries(args.map((x) => x.slice(1)));
|
225
|
+
map[match[2]] = {
|
226
|
+
"html-tag": match[1],
|
227
|
+
"var-tag": match[2],
|
228
|
+
node: new nodeHtmlParser.HTMLElement(match[1], {}),
|
229
|
+
args: Object.fromEntries(
|
230
|
+
match[3]
|
231
|
+
.trim()
|
232
|
+
.split(" ")
|
233
|
+
.map((x) => x.split("="))
|
234
|
+
),
|
235
|
+
_raw: match[0],
|
236
|
+
};
|
237
|
+
}
|
238
|
+
|
239
|
+
/* Replace tagged elements in inner blob with their uuids */
|
240
|
+
for (let taggedElement of Object.values(map)) {
|
241
|
+
innerBlob = innerBlob.replace(
|
242
|
+
taggedElement._raw,
|
243
|
+
salt + taggedElement["var-tag"] + salt
|
244
|
+
);
|
245
|
+
}
|
246
|
+
|
247
|
+
/* Run the hook on the map*/
|
248
|
+
parser.opts.hooks[match[1]](map);
|
249
|
+
|
250
|
+
/* Replace the tagged elements with the modified nodes */
|
251
|
+
let output = innerBlob;
|
252
|
+
for (let taggedElement of Object.values(map)) {
|
253
|
+
output = output.replace(
|
254
|
+
salt + taggedElement["var-tag"] + salt,
|
255
|
+
taggedElement.node.toString()
|
256
|
+
);
|
257
|
+
}
|
258
|
+
|
259
|
+
return output;
|
260
|
+
},
|
261
|
+
CommandType.POSTPARSE
|
227
262
|
);
|
228
263
|
|
229
|
-
/* mdadvhook */
|
230
264
|
new Command(
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
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
|
265
|
+
/<(\w+)([\#\.\w]+)\n([\w\W]*?)>/,
|
266
|
+
(match, _) => {
|
267
|
+
const tag = match[1];
|
268
|
+
const tagline = match[2];
|
269
|
+
const id = tagline.match(/#(\w+)/)
|
270
|
+
? `id="${tagline.match(/#(\w+)/)[1]}"`
|
271
|
+
: "";
|
272
|
+
const cls = tagline.match(/\.(.+)/);
|
273
|
+
let cls_str = "";
|
274
|
+
if (cls) {
|
275
|
+
cls_str =
|
276
|
+
cls.length > 1 ? `class="${cls[1].replace(".", " ")}"` : "";
|
277
|
+
}
|
278
|
+
|
279
|
+
const content = match[3];
|
280
|
+
|
281
|
+
return `<${tag} ${id} ${cls_str}>${content.trim()}</${tag}>`;
|
282
|
+
},
|
283
|
+
CommandType.POSTPARSE
|
268
284
|
);
|
269
285
|
|
270
286
|
const loaded_extentions: fs.PathLike[] = [];
|
271
287
|
|
272
288
|
function load_extension(parser: Parser, file: fs.PathLike) {
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
289
|
+
// if (loaded_extentions.includes(file)) return;
|
290
|
+
if (fs.existsSync(file)) {
|
291
|
+
const extensions = requireRuntime(file);
|
292
|
+
loaded_extentions.push(file);
|
293
|
+
extensions.main(new_template, new_command);
|
294
|
+
|
295
|
+
if (parser.opts.verbose)
|
296
|
+
console.log(`Loaded extensions from ${file}`.yellow);
|
297
|
+
} else if (parser.opts.debug) {
|
298
|
+
console.log(`No extensions found at ${file}`.red);
|
299
|
+
}
|
284
300
|
}
|
285
301
|
|
286
302
|
export function load_extensions(parser: Parser) {
|
287
|
-
|
288
|
-
|
289
|
-
|
303
|
+
/* global extention */
|
304
|
+
const global_extensions_path = path.join(__dirname, "extensions.js");
|
305
|
+
load_extension(parser, global_extensions_path);
|
290
306
|
|
291
|
-
|
292
|
-
|
293
|
-
|
307
|
+
/* project extention */
|
308
|
+
const project_extensions_path = path.join(parser.wd_full, "extensions.js");
|
309
|
+
load_extension(parser, project_extensions_path);
|
294
310
|
}
|
295
311
|
|
296
312
|
/**
|
@@ -300,11 +316,11 @@ export function load_extensions(parser: Parser) {
|
|
300
316
|
* @param type When the command should be run. Can be `CommandType.PREPARSE`, `CommandType.PARSE`, or `CommandType.POSTPARSE`. Defaults to `CommandType.PARSE`.
|
301
317
|
*/
|
302
318
|
export function new_command(
|
303
|
-
|
304
|
-
|
305
|
-
|
319
|
+
regex: RegExp,
|
320
|
+
acter: (match: RegExpMatchArray, parser: Parser) => string,
|
321
|
+
type?: CommandType
|
306
322
|
) {
|
307
|
-
|
323
|
+
new Command(regex, acter, type || CommandType.PARSE);
|
308
324
|
}
|
309
325
|
|
310
326
|
export default { commands, load_extensions };
|
package/src/errors.ts
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
export class MDMNonParserError extends Error {
|
2
|
+
constructor(message: string) {
|
3
|
+
super(message);
|
4
|
+
Object.setPrototypeOf(this, MDMNonParserError.prototype);
|
5
|
+
}
|
6
|
+
}
|
7
|
+
|
8
|
+
export class MDMError extends Error {
|
9
|
+
match: RegExpMatchArray;
|
10
|
+
constructor(message: string, match: RegExpMatchArray) {
|
11
|
+
super(message);
|
12
|
+
Object.setPrototypeOf(this, MDMError.prototype);
|
13
|
+
|
14
|
+
this.match = match;
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
export class MDMWarning extends Error {
|
19
|
+
match?: RegExpMatchArray;
|
20
|
+
constructor(message: string, match?: RegExpMatchArray) {
|
21
|
+
super(message);
|
22
|
+
Object.setPrototypeOf(this, MDMWarning.prototype);
|
23
|
+
|
24
|
+
this.match = match;
|
25
|
+
}
|
26
|
+
}
|