Skip to content

Commit

Permalink
Now automatically includes file with same name as folder when mdinclu…
Browse files Browse the repository at this point in the history
…de'ing a directory
  • Loading branch information
blitzher committed Apr 24, 2024
1 parent ff6b4f1 commit 4f3b6fd
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 34 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
]
},
"scripts": {
"test": "mocha",
"test": "mocha --require test/hooks.js",
"test:yarn": "mocha",
"bundle": "tsc --project tsconfig.json",
"main": "node build/cltool.js document/main.md -o dist/bundle.md --debug",
Expand Down
51 changes: 30 additions & 21 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class Command {
constructor(
validator: RegExp,
acter: (match: RegExpMatchArray, parser: Parser) => string | void,
type: CommandType,
type: CommandType
) {
this.type = type;
this.validator = validator;
Expand Down Expand Up @@ -71,7 +71,7 @@ export class Command {
new Command(
/(\s|^)<(.+)>/,
(match, parser) => `${match[1]}#mdvar<${match[2]}>`,
CommandType.PREPARSE,
CommandType.PREPARSE
);

/* mddef */
Expand All @@ -80,7 +80,7 @@ new Command(
(match, parser) => {
parser.opts.defs[match[1]] = match[2].replace("_", " ");
},
CommandType.PARSE,
CommandType.PARSE
);

/* mdvar */
Expand All @@ -92,7 +92,7 @@ new Command(
throw new Error(`Undefined variable: ${match[1]}`);
return (value = value || `<${match[1]}>`);
},
CommandType.PARSE,
CommandType.PARSE
);

/** mdinclude */
Expand All @@ -107,17 +107,31 @@ new Command(
}

/* get the matching group */
const [_, name, condition] = match;
let [_, name, condition] = match;

/* implement conditional imports */
if (condition && !parser.opts.args.includes(condition)) return;

const fsstat = fs.lstatSync(path.join(parser.wd, name));
if (fsstat.isDirectory()) {
/* check if a file with the same name of the
* exists in the folder */

if (fs.existsSync(path.join(parser.wd, name, `${name}.md`))) {
name = path.join(name, `${name}.md`);
} else {
throw new Error(
`No entry file found in folder "${name}". Looking for "${name}.md"`
);
}
}

const recursiveParser = new Parser(
path.join(parser.wd, name),
parser.opts,
{
parent: parser,
},
}
);

/* keep the options the same */
Expand All @@ -134,7 +148,7 @@ new Command(
parser.opts.depth--;
return blob;
},
CommandType.PARSE,
CommandType.PARSE
);

/* mdlabel */
Expand All @@ -149,7 +163,7 @@ new Command(
parser.opts.secs.push({ level, title });
return `<span id="${link}"></span>`;
},
CommandType.PREPARSE,
CommandType.PREPARSE
);

/* mdref */
Expand All @@ -163,7 +177,7 @@ new Command(

if (i === parser.opts.secs.length - 1)
throw new Error(
`Reference to [${match[1]}] could not be resolved!`,
`Reference to [${match[1]}] could not be resolved!`
);
}

Expand All @@ -174,7 +188,7 @@ new Command(
else if (parser.opts.targetType === TargetType.MARKDOWN)
return `[${match[1]}](#${link})`;
},
CommandType.PARSE,
CommandType.PARSE
);

/* mdtemplate */
Expand All @@ -190,16 +204,16 @@ new Command(
throw new MDMError(`Template \"${template}\" not found!`, match);
}
},
CommandType.PARSE,
CommandType.PARSE
);

new Command(
/#mdmaketoc(?:<>)?/,
(match, parser) => parser.gen_toc(),
CommandType.POSTPARSE,
CommandType.POSTPARSE
);

const loaded_extentions: fs.PathLike[] = []
const loaded_extentions: fs.PathLike[] = [];

function load_extension(parser: Parser, file: fs.PathLike) {
if (loaded_extentions.includes(file)) return;
Expand All @@ -209,14 +223,9 @@ function load_extension(parser: Parser, file: fs.PathLike) {
extensions.main(new_template, new_command);

if (parser.opts.verbose)
console.log(
`Loaded extensions from ${file}`
.yellow,
);
console.log(`Loaded extensions from ${file}`.yellow);
} else if (parser.opts.debug) {
console.log(
`No extensions found at ${file}`.red,
);
console.log(`No extensions found at ${file}`.red);
}
}

Expand All @@ -239,7 +248,7 @@ export function load_extensions(parser: Parser) {
export function new_command(
regex: RegExp,
acter: (match: RegExpMatchArray, parser: Parser) => string,
type?: CommandType,
type?: CommandType
) {
new Command(regex, acter, type || CommandType.PARSE);
}
Expand Down
18 changes: 10 additions & 8 deletions test/advanced.test.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,37 @@
const util = require("./tester.test.js");

util.put(
"module.exports = {main: (new_template, new_command) => {new_template('hi', 'hello'); new_command(/#test_cmd/, (t,p) => 'yeet', 0);}};",
"extensions.js"
);
const putTemplate = () => {
util.put(
"module.exports = {main: (new_template, new_command) => {new_template('hi', 'hello'); new_command(/#test_cmd/, (t,p) => 'yeet', 0);}};",
"extensions.js"
);
};

describe("Use of templates", () => {
beforeEach(putTemplate);
it("should import presentation template as expected", () => {
putTemplate();
const output = new util.Parser("#mdtemplate<presentation>").get();
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>`;

util.assert.strictEqual(output, template + "\n\n");
});

it("should use custom templates from project extensions.js file", () => {
putTemplate();
util.put("#mdtemplate<hi>", "sample1.md");

util.assert.strictEqual(
new util.Parser("test/test-files/sample1.md").get(),
"hello\n\n"
);

/* make sure to remove after, to not mess with future tests */
});

it("should use custom commands from project extensions.js file", () => {
putTemplate();
util.put("#test_cmd", "sample1.md");

const parser = new util.Parser("test/test-files/sample1.md");
util.assert.strictEqual(parser.get(), "yeet\n\n");

/* make sure to remove after, to not mess with future tests */
});
});
11 changes: 11 additions & 0 deletions test/basic.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const path = require("path");
const util = require("./tester.test.js");

describe("Basic features", () => {
Expand Down Expand Up @@ -54,4 +55,14 @@ describe("Basic features", () => {

util.assert.strictEqual(parser.get(), "### Title\n[Title](#title)\n\n");
});
it("should include file with same name as folder when including a folder", () => {
util.put("#mdinclude<sample_fld>", "sample1.md");
util.putDir("sample_fld");
util.put("hello", util.path.join("sample_fld", "sample_fld.md"));

const parser = new util.Parser("test/test-files/sample1.md");
const output = parser.get();

util.assert.strictEqual(output, "hello\n\n");
});
});
24 changes: 23 additions & 1 deletion test/errors.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const { Parser } = require("marked");
const util = require("./tester.test.js");
const fs = require("fs");

describe("Error handling", () => {
it("should dissallow undefined templates", () => {
Expand All @@ -23,4 +23,26 @@ describe("Error handling", () => {

util.assert.strictEqual(e.message.replace(/(\\)+/g, "/"), answer);
});
it("should dissallow loading a folder without an entry file", () => {
util.put("#mdinclude<sample_fld>", "sample1.md");
util.putDir("sample_fld");

const parser = new util.Parser("test/test-files/sample1.md");

let e;
util.assert.throws(() => {
try {
parser.get();
} catch (_e) {
e = _e;
throw _e;
}
}, Error);

let answer =
'No entry file found in folder "sample_fld". Looking for "sample_fld.md"' +
"\n...on line 1 in test/test-files/sample1.md".grey(15);

util.assert.strictEqual(e.message.replace(/(\\)+/g, "/"), answer);
});
});
9 changes: 9 additions & 0 deletions test/hooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const fs = require("fs");

exports.mochaHooks = {
beforeEach(done) {
fs.rmdirSync("test/test-files", { recursive: true });
fs.mkdirSync("test/test-files");
done();
},
};
15 changes: 12 additions & 3 deletions test/tester.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
const fs = require("fs");
const assert = require("assert");
const Parser = require("../build/parse");


const path = require("path");

/* make folder for temporary files, if it doesn't exist */
if (
Expand All @@ -12,8 +11,16 @@ if (
fs.mkdirSync("test/test-files");
}

/**
* Create a new file under `test/test-files` with the given content.
* @param {string} text
* @param {string} file
*/
function put(text, file) {
fs.writeFileSync("test/test-files/" + file, text);
fs.writeFileSync(path.join("test", "test-files", file), text);
}
function putDir(name) {
fs.mkdirSync(path.join("test", "test-files", name));
}

const TargetType = {
Expand All @@ -24,7 +31,9 @@ const TargetType = {
module.exports = {
fs,
assert,
path,
Parser,
put,
putDir,
TargetType,
};

0 comments on commit 4f3b6fd

Please sign in to comment.