markdown-maker 1.10.0 → 1.10.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- "<node_internals>/**"
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.0",
4
- "description": "",
5
- "main": "src/cltool.ts",
3
+ "version": "1.10.2",
4
+ "description": "A superset-compiler for markdown using marked",
5
+ "main": "src/main.ts",
6
6
  "bin": {
7
- "mdparse": "build/cltool.js"
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 build/cltool.js document/main.md -o dist/bundle.md --debug",
30
- "debug": "node src/cltool.js -db document/main.md -o dist/bundle.md",
31
- "build": "npm run bundle && pkg --output bin/mdparse .",
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 Parser from "./parse";
6
- import { WebSocketServer } from "ws";
5
+ import { TargetType } from "./commands";
6
+ import Parser from "./parser";
7
7
 
8
8
  Colors.enable();
9
- const { ArgumentParser } = require("argparse"); /* for parsing clargs */
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: "Markdown bundler, with extra options. Extension file is loaded from ./extensions.js, if it exists",
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
- function main() {
70
- let clargs, fileargs;
71
- let server: WebSocketServer | undefined;
72
-
73
- /* Read config file or parse args from cmd-line */
74
- if (fs.existsSync(configFileName)) {
75
- let data: { [key: string]: string | boolean | number } = JSON.parse(fs.readFileSync(configFileName)).opts;
76
-
77
- let args: (string | number)[] = [];
78
- Object.entries(data).forEach(([key, value]) => {
79
- if (key != "src" && value !== false) {
80
- args.push("--" + key);
81
- }
82
- if (typeof value != "boolean") {
83
- args.push(value);
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
- const internalCooldown = 1000;
117
- function watcher(event, path) {
118
- const now = Date.now();
119
-
120
- if (!this.time) this.time = now;
121
-
122
- if (now - this.time < internalCooldown) return;
123
-
124
- console.log(path);
125
-
126
- console.log(`Detected change in ${path}...`);
127
-
128
- try {
129
- compile(clargs.src, clargs.output, () => {
130
- /* after compile, send refresh command to clients */
131
- server.clients.forEach((client) => {
132
- if (client.OPEN) client.send("refresh");
133
- });
134
- });
135
- } catch (e) {
136
- console.log(e.message);
137
- }
138
-
139
- this.time = now;
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 "./parse";
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.opts,
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
- 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";
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
- defs: {
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)) + beg + `[${title}](#${link})`;
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(), () => callback(htmlFileName));
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 traceback += `\n...on line ${p.line_num} in ${p.file}`.grey(15);
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 = classes.length > 0 ? `class="${classNames.join(" ")}"` : "";
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 */
@@ -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");