markdown-maker 1.7.11 → 1.9.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/.github/workflows/node.js.yml +13 -8
- package/README.md +1 -0
- package/doc/.mdmconfig.json +3 -2
- package/package.json +10 -8
- package/prettierrc.yaml +1 -1
- package/re-test.js +10 -0
- package/src/cltool.ts +35 -22
- package/src/commands.ts +145 -73
- package/src/parse.ts +103 -112
- package/src/templates/mathjax.js +3 -0
- package/src/templates/presentation.js +3 -0
- package/src/templates.ts +18 -0
- package/test/advanced.test.js +35 -0
- package/test/basic.test.js +4 -9
- package/test/clargs.test.js +2 -2
- package/test/errors.test.js +14 -53
- package/test/marked.test.js +43 -0
- package/test/target.test.js +2 -4
- package/test/tester.test.js +16 -14
- package/tsconfig.json +1 -1
- package/argparsetest.js +0 -11
- package/build/cltool.d.ts +0 -1
- package/build/cltool.js +0 -141
- package/build/commands.d.ts +0 -9
- package/build/commands.js +0 -140
- package/build/parse.d.ts +0 -57
- package/build/parse.js +0 -298
    
        package/src/parse.ts
    CHANGED
    
    | @@ -4,7 +4,7 @@ const path = require("path"); /* for handling file paths */ | |
| 4 4 | 
             
            import Colors = require("colors.ts"); /* for adding colours to strings */
         | 
| 5 5 | 
             
            Colors.enable();
         | 
| 6 6 | 
             
            const marked = require("marked");
         | 
| 7 | 
            -
             | 
| 7 | 
            +
            import { Command, commands, load_extensions, MDMError } from "./commands";
         | 
| 8 8 |  | 
| 9 9 | 
             
            enum TargetType {
         | 
| 10 10 | 
             
                HTML,
         | 
| @@ -18,6 +18,7 @@ class Parser { | |
| 18 18 | 
             
                parent?: Parser;
         | 
| 19 19 | 
             
                line_num: number;
         | 
| 20 20 | 
             
                wd: string;
         | 
| 21 | 
            +
                wd_full: string;
         | 
| 21 22 | 
             
                blobs: {
         | 
| 22 23 | 
             
                    [key: number]: string | undefined;
         | 
| 23 24 | 
             
                };
         | 
| @@ -36,8 +37,9 @@ class Parser { | |
| 36 37 | 
             
                    max_depth: number;
         | 
| 37 38 | 
             
                    use_underscore: boolean;
         | 
| 38 39 | 
             
                    toc_level: number;
         | 
| 39 | 
            -
                     | 
| 40 | 
            +
                    allow_undefined: boolean;
         | 
| 40 41 | 
             
                    html: boolean;
         | 
| 42 | 
            +
                    watch: boolean;
         | 
| 41 43 | 
             
                    targetType: TargetType | undefined;
         | 
| 42 44 | 
             
                    only_warn: boolean;
         | 
| 43 45 | 
             
                    parent?: Parser;
         | 
| @@ -65,6 +67,7 @@ class Parser { | |
| 65 67 |  | 
| 66 68 | 
             
                    this.line_num = 0;
         | 
| 67 69 | 
             
                    this.wd = path.dirname(filename);
         | 
| 70 | 
            +
                    this.wd_full = path.resolve(this.wd);
         | 
| 68 71 |  | 
| 69 72 | 
             
                    /* finished blob */
         | 
| 70 73 | 
             
                    this.blobs = {};
         | 
| @@ -80,8 +83,9 @@ class Parser { | |
| 80 83 | 
             
                        max_depth: 5,
         | 
| 81 84 | 
             
                        use_underscore: false,
         | 
| 82 85 | 
             
                        toc_level: 3,
         | 
| 83 | 
            -
                         | 
| 86 | 
            +
                        allow_undefined: false,
         | 
| 84 87 | 
             
                        html: false,
         | 
| 88 | 
            +
                        watch: false,
         | 
| 85 89 | 
             
                        targetType: undefined,
         | 
| 86 90 | 
             
                        only_warn: false,
         | 
| 87 91 | 
             
                        parent: undefined,
         | 
| @@ -107,6 +111,7 @@ class Parser { | |
| 107 111 | 
             
                 * preprocessing, parsing and postprocess
         | 
| 108 112 | 
             
                 **/
         | 
| 109 113 | 
             
                parse() {
         | 
| 114 | 
            +
                    load_extensions(this);
         | 
| 110 115 | 
             
                    if (this.opts.verbose || this.opts.debug) {
         | 
| 111 116 | 
             
                        console.log(
         | 
| 112 117 | 
             
                            Colors.colors(
         | 
| @@ -138,11 +143,10 @@ class Parser { | |
| 138 143 | 
             
                    return __blob;
         | 
| 139 144 | 
             
                }
         | 
| 140 145 |  | 
| 141 | 
            -
                mainparse(blob) {
         | 
| 146 | 
            +
                mainparse(blob: string) {
         | 
| 142 147 | 
             
                    if (this.opts.verbose || this.opts.debug) {
         | 
| 143 148 | 
             
                        console.debug(`beginning mainparse of '${this.file}'`.blue);
         | 
| 144 149 | 
             
                    }
         | 
| 145 | 
            -
                    let __blob = "";
         | 
| 146 150 |  | 
| 147 151 | 
             
                    /* main parser instance loop */
         | 
| 148 152 | 
             
                    blob.split("\n").forEach((line, lnum) => {
         | 
| @@ -157,17 +161,7 @@ class Parser { | |
| 157 161 |  | 
| 158 162 | 
             
                            /* implement toc level */
         | 
| 159 163 | 
             
                            let level = titleMatch[1].length;
         | 
| 160 | 
            -
             | 
| 161 | 
            -
                            /**
         | 
| 162 | 
            -
                             * parse elements of title
         | 
| 163 | 
            -
                             * such as variables */
         | 
| 164 | 
            -
                            let title = titleMatch[2]
         | 
| 165 | 
            -
                                .trim()
         | 
| 166 | 
            -
                                .split(" ")
         | 
| 167 | 
            -
                                .map((s) =>
         | 
| 168 | 
            -
                                    s.startsWith(Parser.TOKEN) ? this.parseToken(s) : s
         | 
| 169 | 
            -
                                )
         | 
| 170 | 
            -
                                .join("_");
         | 
| 164 | 
            +
                            let title = titleMatch[2];
         | 
| 171 165 |  | 
| 172 166 | 
             
                            this.opts.secs.push({ level, title });
         | 
| 173 167 |  | 
| @@ -175,101 +169,49 @@ class Parser { | |
| 175 169 | 
             
                                console.log("updated sections:", { level, title });
         | 
| 176 170 | 
             
                            }
         | 
| 177 171 | 
             
                        }
         | 
| 178 | 
            -
             | 
| 179 | 
            -
                        let __line_tokens = [];
         | 
| 180 | 
            -
                        /* split line into tokens */
         | 
| 181 | 
            -
                        line.split(" ").forEach((token) => {
         | 
| 182 | 
            -
                            /* if token is not #md token,
         | 
| 183 | 
            -
                             * just add it and continue */
         | 
| 184 | 
            -
                            if (token.startsWith(Parser.TOKEN)) {
         | 
| 185 | 
            -
                                token = this.parseToken(token);
         | 
| 186 | 
            -
                            }
         | 
| 187 | 
            -
             | 
| 188 | 
            -
                            __line_tokens.push(token);
         | 
| 189 | 
            -
                        });
         | 
| 190 | 
            -
                        /* put line back properly */
         | 
| 191 | 
            -
                        __blob += __line_tokens.join(" ") + "\n";
         | 
| 192 172 | 
             
                    });
         | 
| 193 173 |  | 
| 194 | 
            -
                    return  | 
| 195 | 
            -
                }
         | 
| 196 | 
            -
             | 
| 197 | 
            -
                parseToken(token) {
         | 
| 198 | 
            -
                    /* iterate over all commands,
         | 
| 199 | 
            -
                     * and if command is valid, execute it */
         | 
| 200 | 
            -
             | 
| 201 | 
            -
                    if (this.opts.verbose || this.opts.debug)
         | 
| 202 | 
            -
                        console.log("found mdtoken: " + token);
         | 
| 203 | 
            -
             | 
| 204 | 
            -
                    for (let i = 0; i < commands.parse.length; i++) {
         | 
| 205 | 
            -
                        const command = commands.parse[i];
         | 
| 206 | 
            -
             | 
| 207 | 
            -
                        if (command.valid(token, this)) {
         | 
| 208 | 
            -
                            return command.act(token, this);
         | 
| 209 | 
            -
                        }
         | 
| 210 | 
            -
                    }
         | 
| 211 | 
            -
             | 
| 212 | 
            -
                    /* check if the command is for later */
         | 
| 213 | 
            -
                    for (let i = 0; i < commands.postparse.length; i++) {
         | 
| 214 | 
            -
                        const command = commands.postparse[i];
         | 
| 215 | 
            -
             | 
| 216 | 
            -
                        if (command.valid(token, this)) {
         | 
| 217 | 
            -
                            return token;
         | 
| 218 | 
            -
                        }
         | 
| 219 | 
            -
                    }
         | 
| 220 | 
            -
             | 
| 221 | 
            -
                    throw new SyntaxError(`Unknown token: ${token}`);
         | 
| 174 | 
            +
                    return this.parse_commands(blob, commands.parse);
         | 
| 222 175 | 
             
                }
         | 
| 223 176 |  | 
| 224 | 
            -
                preprocess(blob) {
         | 
| 177 | 
            +
                preprocess(blob: string) {
         | 
| 225 178 | 
             
                    if (this.opts.verbose || this.opts.debug) {
         | 
| 226 179 | 
             
                        console.debug(`beginning preprocess of '${this.file}'`.blue);
         | 
| 227 180 | 
             
                    }
         | 
| 228 | 
            -
                    let __blob = "";
         | 
| 229 | 
            -
                    const lines = blob.split("\n");
         | 
| 230 | 
            -
             | 
| 231 | 
            -
                    lines.forEach((line) => {
         | 
| 232 | 
            -
                        let __line_tokens = [];
         | 
| 233 | 
            -
                        line.split(" ").forEach((token) => {
         | 
| 234 | 
            -
                            for (const command of commands.preparse) {
         | 
| 235 | 
            -
                                if (command.valid(token, this)) {
         | 
| 236 | 
            -
                                    token = command.act(token, this);
         | 
| 237 | 
            -
                                }
         | 
| 238 | 
            -
                            }
         | 
| 239 181 |  | 
| 240 | 
            -
             | 
| 241 | 
            -
                        });
         | 
| 242 | 
            -
                        __blob += __line_tokens.join(" ") + "\n";
         | 
| 243 | 
            -
                    });
         | 
| 244 | 
            -
                    return __blob;
         | 
| 182 | 
            +
                    return this.parse_commands(blob, commands.preparse);
         | 
| 245 183 | 
             
                }
         | 
| 246 184 |  | 
| 247 | 
            -
                postprocess(blob) {
         | 
| 185 | 
            +
                postprocess(blob: string) {
         | 
| 248 186 | 
             
                    if (this.opts.verbose || this.opts.debug) {
         | 
| 249 187 | 
             
                        console.debug(`beginning postprocess of '${this.file}'`.blue);
         | 
| 250 188 | 
             
                    }
         | 
| 251 | 
            -
                    let __blob = "";
         | 
| 252 | 
            -
                    const lines = blob.split("\n");
         | 
| 253 | 
            -
             | 
| 254 | 
            -
                    lines.forEach((line) => {
         | 
| 255 | 
            -
                        let __line_tokens = [];
         | 
| 256 | 
            -
                        line.split(" ").forEach((token) => {
         | 
| 257 | 
            -
                            // only look
         | 
| 258 | 
            -
             | 
| 259 | 
            -
                            for (const command of commands.postparse) {
         | 
| 260 | 
            -
                                if (command.valid(token, this)) {
         | 
| 261 | 
            -
                                    token = command.act(token, this);
         | 
| 262 | 
            -
                                }
         | 
| 263 | 
            -
                            }
         | 
| 264 189 |  | 
| 265 | 
            -
             | 
| 266 | 
            -
                        });
         | 
| 267 | 
            -
                        __blob += __line_tokens.join(" ") + "\n";
         | 
| 268 | 
            -
                    });
         | 
| 190 | 
            +
                    blob = this.parse_commands(blob, commands.postparse);
         | 
| 269 191 |  | 
| 270 192 | 
             
                    /* remove double empty lines */
         | 
| 271 | 
            -
                     | 
| 272 | 
            -
                     | 
| 193 | 
            +
                    blob = this.remove_double_blank_lines(blob);
         | 
| 194 | 
            +
                    blob = blob.trimEnd() + "\n\n";
         | 
| 195 | 
            +
                    return blob;
         | 
| 196 | 
            +
                }
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                parse_commands(blob: string, commands: Command[]) {
         | 
| 199 | 
            +
                    commands.forEach((command) => {
         | 
| 200 | 
            +
                        /* Add global flag to RegExp */
         | 
| 201 | 
            +
                        const re = new RegExp(
         | 
| 202 | 
            +
                            command.validator.source,
         | 
| 203 | 
            +
                            (command.validator.flags || "") + "g"
         | 
| 204 | 
            +
                        );
         | 
| 205 | 
            +
                        blob = blob.replace(re, (...args) => command.act(args, this) || "");
         | 
| 206 | 
            +
                    });
         | 
| 207 | 
            +
                    return blob;
         | 
| 208 | 
            +
                }
         | 
| 209 | 
            +
             | 
| 210 | 
            +
                parse_all_commands(blob: string, commands: { [key: string]: Command[] }) {
         | 
| 211 | 
            +
                    Object.keys(commands).forEach((key) => {
         | 
| 212 | 
            +
                        blob = this.parse_commands(blob, commands[key]);
         | 
| 213 | 
            +
                    });
         | 
| 214 | 
            +
                    return blob;
         | 
| 273 215 | 
             
                }
         | 
| 274 216 |  | 
| 275 217 | 
             
                titleId(title: string) {
         | 
| @@ -290,18 +232,22 @@ class Parser { | |
| 290 232 |  | 
| 291 233 | 
             
                    this.opts.secs.forEach((sec) => {
         | 
| 292 234 | 
             
                        if (sec.level > this.opts.toc_level) return;
         | 
| 293 | 
            -
                         | 
| 294 | 
            -
                         | 
| 235 | 
            +
                        let title = sec.title.replace(/_/g, " ");
         | 
| 236 | 
            +
                        title = this.parse_all_commands(title, commands);
         | 
| 237 | 
            +
                        const link = this.titleId(title);
         | 
| 295 238 |  | 
| 296 239 | 
             
                        let __line =
         | 
| 297 | 
            -
                            hor.repeat(Math.max(sec.level - 1, 0)) +
         | 
| 298 | 
            -
             | 
| 299 | 
            -
                            `[${title}](#${link})`;
         | 
| 240 | 
            +
                            hor.repeat(Math.max(sec.level - 1, 0)) + beg + `[${title}](#${link})`;
         | 
| 241 | 
            +
             | 
| 300 242 | 
             
                        __blob.push(__line);
         | 
| 301 243 | 
             
                    });
         | 
| 302 244 | 
             
                    return __blob.join("\n");
         | 
| 303 245 | 
             
                }
         | 
| 304 246 |  | 
| 247 | 
            +
                line_num_from_index(index: number) {
         | 
| 248 | 
            +
                    return this.raw.substring(0, index).split("\n").length + 1;
         | 
| 249 | 
            +
                }
         | 
| 250 | 
            +
             | 
| 305 251 | 
             
                remove_double_blank_lines(blob) {
         | 
| 306 252 | 
             
                    /* replace all triple newlines, and EOF by double newline */
         | 
| 307 253 | 
             
                    blob = blob.replace(/(\r\n|\n){3,}/g, "\n\n");
         | 
| @@ -310,25 +256,27 @@ class Parser { | |
| 310 256 | 
             
                }
         | 
| 311 257 |  | 
| 312 258 | 
             
                /* output the parsed document to bundle */
         | 
| 313 | 
            -
                to(bundleName,  | 
| 259 | 
            +
                to(bundleName: string, callback: (fileName: string) => void) {
         | 
| 314 260 | 
             
                    const dir = path.dirname(bundleName);
         | 
| 315 261 | 
             
                    var called = false;
         | 
| 316 | 
            -
                    if ( | 
| 262 | 
            +
                    if (callback === undefined) callback = () => {};
         | 
| 317 263 |  | 
| 318 264 | 
             
                    if (!fs.existsSync(dir)) {
         | 
| 319 | 
            -
                        fs.mkdirSync(dir);
         | 
| 265 | 
            +
                        fs.mkdirSync(dir, { recursive: true });
         | 
| 320 266 | 
             
                    }
         | 
| 321 267 | 
             
                    this.get(TargetType.MARKDOWN, (blob) => {
         | 
| 322 268 | 
             
                        fs.writeFile(bundleName, blob, () => {
         | 
| 323 | 
            -
                            if (! | 
| 324 | 
            -
             | 
| 269 | 
            +
                            if (!this.opts.html) {
         | 
| 270 | 
            +
                                callback(bundleName);
         | 
| 271 | 
            +
                                called = true;
         | 
| 272 | 
            +
                            }
         | 
| 325 273 | 
             
                        });
         | 
| 326 274 | 
             
                    });
         | 
| 327 275 |  | 
| 328 276 | 
             
                    if (this.opts.html) {
         | 
| 329 277 | 
             
                        const htmlFileName = bundleName.replace(".md", ".html");
         | 
| 330 278 | 
             
                        fs.writeFile(htmlFileName, this.html(), () => {
         | 
| 331 | 
            -
                            if (!called)  | 
| 279 | 
            +
                            if (!called) callback(htmlFileName);
         | 
| 332 280 | 
             
                            called = true;
         | 
| 333 281 | 
             
                        });
         | 
| 334 282 | 
             
                    }
         | 
| @@ -336,13 +284,18 @@ class Parser { | |
| 336 284 |  | 
| 337 285 | 
             
                html() {
         | 
| 338 286 | 
             
                    const htmlFormatted = marked(this.get(TargetType.HTML));
         | 
| 339 | 
            -
             | 
| 287 | 
            +
                    if (this.opts.watch) {
         | 
| 288 | 
            +
                        return (
         | 
| 289 | 
            +
                            `<script>w=new WebSocket("ws:localhost:7788");w.addEventListener("message",(e)=>{if(e.data=="refresh")location.reload();});</script>\n` +
         | 
| 290 | 
            +
                            htmlFormatted
         | 
| 291 | 
            +
                        );
         | 
| 292 | 
            +
                    }
         | 
| 340 293 | 
             
                    return htmlFormatted;
         | 
| 341 294 | 
             
                }
         | 
| 342 295 |  | 
| 343 | 
            -
                get(targetType | 
| 296 | 
            +
                get(targetType?: TargetType, callback?) {
         | 
| 344 297 | 
             
                    /* If target type is undefined, markdown is the default */
         | 
| 345 | 
            -
                    if (targetType  | 
| 298 | 
            +
                    if (targetType === undefined) targetType = TargetType.MARKDOWN;
         | 
| 346 299 | 
             
                    if (this.blobs[targetType]) {
         | 
| 347 300 | 
             
                        if (callback) {
         | 
| 348 301 | 
             
                            callback(this.blobs[targetType]);
         | 
| @@ -361,9 +314,11 @@ class Parser { | |
| 361 314 | 
             
                            let p: Parser = this;
         | 
| 362 315 |  | 
| 363 316 | 
             
                            do {
         | 
| 364 | 
            -
                                 | 
| 365 | 
            -
                                    p. | 
| 366 | 
            -
             | 
| 317 | 
            +
                                if (error instanceof MDMError)
         | 
| 318 | 
            +
                                    traceback += `\n...on line ${p.line_num_from_index(
         | 
| 319 | 
            +
                                        error.match.index
         | 
| 320 | 
            +
                                    )} in ${p.file}`.grey(15);
         | 
| 321 | 
            +
                                else traceback += `\n...on line ${p.line_num} in ${p.file}`.grey(15);
         | 
| 367 322 | 
             
                                if (p.parent) p = p.parent;
         | 
| 368 323 | 
             
                            } while (p.parent);
         | 
| 369 324 |  | 
| @@ -379,6 +334,42 @@ class Parser { | |
| 379 334 | 
             
                }
         | 
| 380 335 | 
             
            }
         | 
| 381 336 |  | 
| 337 | 
            +
            export function splice(
         | 
| 338 | 
            +
                str: string,
         | 
| 339 | 
            +
                startIndex: number,
         | 
| 340 | 
            +
                width: number,
         | 
| 341 | 
            +
                newSubStr: string
         | 
| 342 | 
            +
            ) {
         | 
| 343 | 
            +
                const start = str.slice(0, startIndex);
         | 
| 344 | 
            +
                const end = str.slice(startIndex + width);
         | 
| 345 | 
            +
                return start + newSubStr + end;
         | 
| 346 | 
            +
            }
         | 
| 347 | 
            +
             | 
| 348 | 
            +
            /* add extention to marked */
         | 
| 349 | 
            +
            marked.use({
         | 
| 350 | 
            +
                renderer: {
         | 
| 351 | 
            +
                    blockquote(quote) {
         | 
| 352 | 
            +
                        /* find the ending, and if not, return the default */
         | 
| 353 | 
            +
                        const ending = quote.match(/\{(.+)\}\s*<\/p>/);
         | 
| 354 | 
            +
                        if (!ending) return `<blockquote>${quote}</blockquote>`;
         | 
| 355 | 
            +
             | 
| 356 | 
            +
                        const args = ending[1].split(" ");
         | 
| 357 | 
            +
             | 
| 358 | 
            +
                        const classes = args.filter((arg) => arg.startsWith("."));
         | 
| 359 | 
            +
                        const id = args.filter((arg) => arg.startsWith("#"));
         | 
| 360 | 
            +
             | 
| 361 | 
            +
                        const classNames = classes.map((c) => c.slice(1));
         | 
| 362 | 
            +
                        const classText = classes.length > 0 ? `class="${classNames.join(" ")}"` : "";
         | 
| 363 | 
            +
                        const idText = id.length > 0 ? `id="${id[0].slice(1)}"` : "";
         | 
| 364 | 
            +
             | 
| 365 | 
            +
                        /* remove the ending from the quote */
         | 
| 366 | 
            +
                        quote = quote.replace(/\{(.+)\}\s*<\/p>/, "</p>");
         | 
| 367 | 
            +
             | 
| 368 | 
            +
                        return `<blockquote ${classText} ${idText}>\n${quote.trim()}</blockquote>`;
         | 
| 369 | 
            +
                    },
         | 
| 370 | 
            +
                },
         | 
| 371 | 
            +
            });
         | 
| 372 | 
            +
             | 
| 382 373 | 
             
            module.exports = Parser;
         | 
| 383 374 |  | 
| 384 375 | 
             
            export default Parser;
         | 
| @@ -0,0 +1,3 @@ | |
| 1 | 
            +
            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>`;
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module.exports = template;
         | 
    
        package/src/templates.ts
    ADDED
    
    | @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            const templates: { [key: string]: string } = {};
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            /**
         | 
| 4 | 
            +
             * Function to add a template to the templates object. Similar to definitions and variables, but reside as an extension.
         | 
| 5 | 
            +
             * @param name The name of the template
         | 
| 6 | 
            +
             * @param content The replacement string
         | 
| 7 | 
            +
             */
         | 
| 8 | 
            +
            export function new_template(name: string, content: string) {
         | 
| 9 | 
            +
                templates[name] = content;
         | 
| 10 | 
            +
            }
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            /* initialize default templates */
         | 
| 13 | 
            +
            const presentation_template = require("../src/templates/presentation.js");
         | 
| 14 | 
            +
            const mathjax_template = require("../src/templates/mathjax.js");
         | 
| 15 | 
            +
            new_template("presentation", presentation_template);
         | 
| 16 | 
            +
            new_template("mathjax", mathjax_template);
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            export default templates;
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            const util = require("./tester.test.js");
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            util.put(
         | 
| 4 | 
            +
                "module.exports = {main: (new_template, new_command) => {new_template('hi', 'hello'); new_command(/#test_cmd/, (t,p) => 'yeet', 0);}};",
         | 
| 5 | 
            +
                "extensions.js"
         | 
| 6 | 
            +
            );
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            describe("Use of templates", () => {
         | 
| 9 | 
            +
                it("should import presentation template as expected", () => {
         | 
| 10 | 
            +
                    const output = new util.Parser("#mdtemplate<presentation>").get();
         | 
| 11 | 
            +
                    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 | 
            +
             | 
| 13 | 
            +
                    util.assert.strictEqual(output, template + "\n\n");
         | 
| 14 | 
            +
                });
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                it("should use custom templates from project extensions.js file", () => {
         | 
| 17 | 
            +
                    util.put("#mdtemplate<hi>", "sample1.md");
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    util.assert.strictEqual(
         | 
| 20 | 
            +
                        new util.Parser("test/test-files/sample1.md").get(),
         | 
| 21 | 
            +
                        "hello\n\n"
         | 
| 22 | 
            +
                    );
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    /* make sure to remove after, to not mess with future tests */
         | 
| 25 | 
            +
                });
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                it("should use custom commands from project extensions.js file", () => {
         | 
| 28 | 
            +
                    util.put("#test_cmd", "sample1.md");
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    const parser = new util.Parser("test/test-files/sample1.md");
         | 
| 31 | 
            +
                    util.assert.strictEqual(parser.get(), "yeet\n\n");
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    /* make sure to remove after, to not mess with future tests */
         | 
| 34 | 
            +
                });
         | 
| 35 | 
            +
            });
         | 
    
        package/test/basic.test.js
    CHANGED
    
    | @@ -1,11 +1,6 @@ | |
| 1 1 | 
             
            const util = require("./tester.test.js");
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe("Basic features", () => {
         | 
| 4 | 
            -
                it("should raise an error if invalid token", () => {
         | 
| 5 | 
            -
                    util.assert.throws(() => {
         | 
| 6 | 
            -
                        const output = new util.Parser("#mdNON<>").get();
         | 
| 7 | 
            -
                    }, SyntaxError);
         | 
| 8 | 
            -
                });
         | 
| 9 4 | 
             
                it("should join two files with include", () => {
         | 
| 10 5 | 
             
                    util.put("hello\n#mdinclude<sample2.md>", "sample1.md");
         | 
| 11 6 | 
             
                    util.put("there", "sample2.md");
         | 
| @@ -35,12 +30,12 @@ describe("Basic features", () => { | |
| 35 30 | 
             
                    );
         | 
| 36 31 | 
             
                });
         | 
| 37 32 | 
             
                it("should allow variables in toc", () => {
         | 
| 38 | 
            -
                    const  | 
| 39 | 
            -
                        "#mddef<name=Foobar>\n# mr. #mdvar<name>\n#mdmaketoc<>"
         | 
| 40 | 
            -
                    );
         | 
| 33 | 
            +
                    const output = new util.Parser(
         | 
| 34 | 
            +
                        "#mddef<name= Foobar>\n# mr. #mdvar<name>\n#mdmaketoc<>"
         | 
| 35 | 
            +
                    ).get();
         | 
| 41 36 |  | 
| 42 37 | 
             
                    util.assert.strictEqual(
         | 
| 43 | 
            -
                         | 
| 38 | 
            +
                        output,
         | 
| 44 39 | 
             
                        "\n# mr. Foobar\n* [mr. Foobar](#mr-foobar)\n\n"
         | 
| 45 40 | 
             
                    );
         | 
| 46 41 | 
             
                });
         | 
    
        package/test/clargs.test.js
    CHANGED
    
    | @@ -20,14 +20,14 @@ describe("Command Line Arguments", () => { | |
| 20 20 | 
             
                });
         | 
| 21 21 | 
             
                it("--allow-undef should not throw when variable is not defined", () => {
         | 
| 22 22 | 
             
                    const output = new util.Parser("#mdvar<zum>", {
         | 
| 23 | 
            -
                         | 
| 23 | 
            +
                        allow_undefined: true,
         | 
| 24 24 | 
             
                    }).get();
         | 
| 25 25 |  | 
| 26 26 | 
             
                    util.assert.strictEqual(output, "<zum>\n\n");
         | 
| 27 27 | 
             
                });
         | 
| 28 28 | 
             
                describe("Conditional imports", () => {
         | 
| 29 29 | 
             
                    it("should be able to conditionally import documents", () => {
         | 
| 30 | 
            -
                        util.put("hello\n#mdinclude<sample2.md,YES>", "sample1.md");
         | 
| 30 | 
            +
                        util.put("hello\n#mdinclude<sample2.md, YES>", "sample1.md");
         | 
| 31 31 | 
             
                        util.put("there", "sample2.md");
         | 
| 32 32 |  | 
| 33 33 | 
             
                        const parser = new util.Parser("test/test-files/sample1.md");
         | 
    
        package/test/errors.test.js
    CHANGED
    
    | @@ -1,65 +1,26 @@ | |
| 1 | 
            +
            const { Parser } = require("marked");
         | 
| 1 2 | 
             
            const util = require("./tester.test.js");
         | 
| 2 3 |  | 
| 3 4 | 
             
            describe("Error handling", () => {
         | 
| 4 | 
            -
                it("should  | 
| 5 | 
            -
                    util.put(" | 
| 5 | 
            +
                it("should dissallow undefined templates", () => {
         | 
| 6 | 
            +
                    util.put("#mdtemplate<UNDEF>", "sample1.md");
         | 
| 6 7 |  | 
| 7 8 | 
             
                    const parser = new util.Parser("test/test-files/sample1.md");
         | 
| 8 9 |  | 
| 9 10 | 
             
                    let e;
         | 
| 10 | 
            -
                     | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
                             | 
| 16 | 
            -
                                e = _e;
         | 
| 17 | 
            -
                                throw _e;
         | 
| 18 | 
            -
                            }
         | 
| 11 | 
            +
                    util.assert.throws(() => {
         | 
| 12 | 
            +
                        try {
         | 
| 13 | 
            +
                            parser.get();
         | 
| 14 | 
            +
                        } catch (_e) {
         | 
| 15 | 
            +
                            e = _e;
         | 
| 16 | 
            +
                            throw _e;
         | 
| 19 17 | 
             
                        }
         | 
| 20 | 
            -
                    )
         | 
| 18 | 
            +
                    }, Error);
         | 
| 21 19 |  | 
| 22 | 
            -
                     | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
                     */
         | 
| 26 | 
            -
                    util.assert.strictEqual(
         | 
| 27 | 
            -
                        e.message,
         | 
| 28 | 
            -
                        "Unknown token: #mdNON" +
         | 
| 29 | 
            -
                        "\n...on line 4 in test/test-files/sample1.md".grey(15)
         | 
| 30 | 
            -
                    )
         | 
| 20 | 
            +
                    let answer =
         | 
| 21 | 
            +
                        'Template "UNDEF" not found!' +
         | 
| 22 | 
            +
                        "\n...on line 1 in test/test-files/sample1.md".grey(15);
         | 
| 31 23 |  | 
| 32 | 
            -
             | 
| 33 | 
            -
                it("should traceback across file includes", () => {
         | 
| 34 | 
            -
                    util.put("\n#mdinclude<sample2.md>", "sample1.md");
         | 
| 35 | 
            -
                    util.put("#mdNON", "sample2.md");
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                    const parser = new util.Parser("test/test-files/sample1.md");
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                    let e;
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                    /* should throw SyntaxError */
         | 
| 42 | 
            -
                    util.assert.throws(
         | 
| 43 | 
            -
                        /* run parser, but store error for further inspection */
         | 
| 44 | 
            -
                        () => {
         | 
| 45 | 
            -
                            try {
         | 
| 46 | 
            -
                                parser.get();
         | 
| 47 | 
            -
                            } catch (_e) {
         | 
| 48 | 
            -
                                e = _e;
         | 
| 49 | 
            -
                                throw _e;
         | 
| 50 | 
            -
                            }
         | 
| 51 | 
            -
                        },
         | 
| 52 | 
            -
                        SyntaxError
         | 
| 53 | 
            -
                    );
         | 
| 54 | 
            -
             | 
| 55 | 
            -
                    /* ...where the error message is the traceback on line 2 -> */
         | 
| 56 | 
            -
                    let answer = "Unknown token: #mdNON" +
         | 
| 57 | 
            -
                        "\n...on line 1 in test/test-files/sample2.md".grey(15) +
         | 
| 58 | 
            -
                        "\n...on line 2 in test/test-files/sample1.md".grey(15);
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                    util.assert.strictEqual(
         | 
| 61 | 
            -
                        e.message.replace(/(\\)+/g, "/"),
         | 
| 62 | 
            -
                        answer
         | 
| 63 | 
            -
                    );
         | 
| 24 | 
            +
                    util.assert.strictEqual(e.message.replace(/(\\)+/g, "/"), answer);
         | 
| 64 25 | 
             
                });
         | 
| 65 26 | 
             
            });
         | 
| @@ -0,0 +1,43 @@ | |
| 1 | 
            +
            const util = require("./tester.test.js");
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe("Marked extentions", () => {
         | 
| 4 | 
            +
                it("should add a single class to blockquotes", () => {
         | 
| 5 | 
            +
                    const parser = new util.Parser("> hello {.one}", {
         | 
| 6 | 
            +
                        use_underscore: true,
         | 
| 7 | 
            +
                        html: true,
         | 
| 8 | 
            +
                    });
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    const output = parser.html();
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    util.assert.strictEqual(
         | 
| 13 | 
            +
                        output,
         | 
| 14 | 
            +
                        '<blockquote class="one" >\n<p>hello </p></blockquote>'
         | 
| 15 | 
            +
                    );
         | 
| 16 | 
            +
                });
         | 
| 17 | 
            +
                it("should add multiple class to blockquotes", () => {
         | 
| 18 | 
            +
                    const parser = new util.Parser("> hello {.one .two}", {
         | 
| 19 | 
            +
                        use_underscore: true,
         | 
| 20 | 
            +
                        html: true,
         | 
| 21 | 
            +
                    });
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    const output = parser.html();
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    util.assert.strictEqual(
         | 
| 26 | 
            +
                        output,
         | 
| 27 | 
            +
                        '<blockquote class="one two" >\n<p>hello </p></blockquote>'
         | 
| 28 | 
            +
                    );
         | 
| 29 | 
            +
                });
         | 
| 30 | 
            +
                it("should add a single class and id to blockquotes", () => {
         | 
| 31 | 
            +
                    const parser = new util.Parser("> hello {.one #myid}", {
         | 
| 32 | 
            +
                        use_underscore: true,
         | 
| 33 | 
            +
                        html: true,
         | 
| 34 | 
            +
                    });
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    const output = parser.html();
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    util.assert.strictEqual(
         | 
| 39 | 
            +
                        output,
         | 
| 40 | 
            +
                        '<blockquote class="one" id="myid">\n<p>hello </p></blockquote>'
         | 
| 41 | 
            +
                    );
         | 
| 42 | 
            +
                });
         | 
| 43 | 
            +
            });
         | 
    
        package/test/target.test.js
    CHANGED
    
    | @@ -26,11 +26,9 @@ describe("Target specific functionality", () => { | |
| 26 26 | 
             
            			util.assert.strictEqual(md, '\n\n')
         | 
| 27 27 | 
             
            		});
         | 
| 28 28 | 
             
            		it("Should include #mdref to title elements in markdown", () => {
         | 
| 29 | 
            -
            			const  | 
| 29 | 
            +
            			const output = new util.Parser("# Some Title!\n#mdref<Some Title!>").get();
         | 
| 30 30 |  | 
| 31 | 
            -
            			 | 
| 32 | 
            -
             | 
| 33 | 
            -
            			util.assert.strictEqual(md, '# Some Title!\n[Some Title!](#some-title)\n\n')
         | 
| 31 | 
            +
            			util.assert.strictEqual(output, '# Some Title!\n[Some Title!](#some-title)\n\n')
         | 
| 34 32 | 
             
            		});
         | 
| 35 33 |  | 
| 36 34 | 
             
            	})
         | 
    
        package/test/tester.test.js
    CHANGED
    
    | @@ -1,28 +1,30 @@ | |
| 1 | 
            -
            const fs = require( | 
| 2 | 
            -
            const assert = require( | 
| 3 | 
            -
            const Parser = require( | 
| 1 | 
            +
            const fs = require("fs");
         | 
| 2 | 
            +
            const assert = require("assert");
         | 
| 3 | 
            +
            const Parser = require("../build/parse");
         | 
| 4 | 
            +
             | 
| 5 | 
            +
             | 
| 4 6 |  | 
| 5 7 | 
             
            /* make folder for temporary files, if it doesn't exist */
         | 
| 6 8 | 
             
            if (
         | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            +
                !fs.existsSync("test/test-files") ||
         | 
| 10 | 
            +
                !fs.lstatSync("test/test-files").isDirectory()
         | 
| 9 11 | 
             
            ) {
         | 
| 10 | 
            -
             | 
| 12 | 
            +
                fs.mkdirSync("test/test-files");
         | 
| 11 13 | 
             
            }
         | 
| 12 14 |  | 
| 13 15 | 
             
            function put(text, file) {
         | 
| 14 | 
            -
             | 
| 16 | 
            +
                fs.writeFileSync("test/test-files/" + file, text);
         | 
| 15 17 | 
             
            }
         | 
| 16 18 |  | 
| 17 19 | 
             
            const TargetType = {
         | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            +
                HTML: 0,
         | 
| 21 | 
            +
                MARKDOWN: 1,
         | 
| 20 22 | 
             
            };
         | 
| 21 23 |  | 
| 22 24 | 
             
            module.exports = {
         | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 25 | 
            +
                fs,
         | 
| 26 | 
            +
                assert,
         | 
| 27 | 
            +
                Parser,
         | 
| 28 | 
            +
                put,
         | 
| 29 | 
            +
                TargetType,
         | 
| 28 30 | 
             
            };
         | 
    
        package/tsconfig.json
    CHANGED
    
    | @@ -14,7 +14,7 @@ | |
| 14 14 | 
             
                    // "jsx": "preserve",                           /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
         | 
| 15 15 | 
             
                    "declaration": true /* Generates corresponding '.d.ts' file. */,
         | 
| 16 16 | 
             
                    // "declarationMap": true,                      /* Generates a sourcemap for each corresponding '.d.ts' file. */
         | 
| 17 | 
            -
                     | 
| 17 | 
            +
                    "sourceMap": true,                              /* Generates corresponding '.map' file. */
         | 
| 18 18 | 
             
                    // "outFile": "./",                             /* Concatenate and emit output to single file. */
         | 
| 19 19 | 
             
                    "outDir": "./build" /* Redirect output structure to the directory. */,
         | 
| 20 20 | 
             
                    // "rootDir": "./",                             /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
         | 
    
        package/argparsetest.js
    DELETED
    
    | @@ -1,11 +0,0 @@ | |
| 1 | 
            -
            const { ArgumentParser } = require("argparse");
         | 
| 2 | 
            -
            const argParser = new ArgumentParser();
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            argParser.add_argument("src");
         | 
| 5 | 
            -
            argParser.add_argument("-o", "--output");
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            console.log(process.argv);
         | 
| 8 | 
            -
             | 
| 9 | 
            -
            const args = argParser.parse_args(["-o", "output", "hi"]);
         | 
| 10 | 
            -
             | 
| 11 | 
            -
            console.log(args);
         |