"use strict"; const assert = require("node:assert/strict"); const {zrequire} = require("./lib/namespace.cjs"); const {run_test} = require("./lib/test.cjs"); const fenced_code = zrequire("fenced_code"); // Check the default behavior of fenced code blocks // works properly before Markdown is initialized. run_test("fenced_block_defaults", () => { const input = "\n```\nfenced code\n```\n\nand then after\n"; const expected = '\n\n
fenced code\n';
const footer = "`;
}
// Before initialize(), the lang string itself is used.
assert.equal(
fenced_code.wrap_code("x = 1", "mylang"),
header_with_lang("mylang") + "x = 1\n" + footer,
);
// After initialize(), known languages use pretty_name.
fenced_code.initialize({
langs: {
python: {priority: 1, pretty_name: "Python"},
js: {priority: 2, pretty_name: "JavaScript"},
},
});
assert.equal(
fenced_code.wrap_code("x = 1", "python"),
header_with_lang("Python") + "x = 1\n" + footer,
);
assert.equal(
fenced_code.wrap_code("var x;", "js"),
header_with_lang("JavaScript") + "var x;\n" + footer,
);
// Unknown language still works after initialize.
assert.equal(
fenced_code.wrap_code("fn main() {}", "rust"),
header_with_lang("rust") + "fn main() {}\n" + footer,
);
// Language with HTML special chars is escaped.
assert.equal(
fenced_code.wrap_code("code", 'a"c'),
header_with_lang("a<b>"c") + "code\n" + footer,
);
});
run_test("process_fenced_code_quote", () => {
const input = "```quote\nhello world\nline two\n```";
const output = fenced_code.process_fenced_code(input);
assert.equal(output, "\n> hello world\n> line two\n\n");
});
run_test("process_fenced_code_math", () => {
// Valid LaTeX renders via KaTeX.
const input = "```math\nx^2\n```";
const output = fenced_code.process_fenced_code(input);
assert.ok(output.includes("katex"));
// Invalid LaTeX produces a tex-error span.
const bad_input = "```math\n\\invalid{}{}{}\n```";
const bad_output = fenced_code.process_fenced_code(bad_input);
assert.ok(bad_output.includes("tex-error"));
});
run_test("process_fenced_code_spoiler", () => {
const stashed = [];
fenced_code.set_stash_func((text) => {
stashed.push(text);
return "STASHED";
});
const input = "```spoiler Click to reveal\nhidden content\n```";
const output = fenced_code.process_fenced_code(input);
assert.ok(output.includes("Click to reveal"));
assert.ok(output.includes("hidden content"));
assert.ok(stashed.some((s) => s.includes("spoiler-block")));
// Restore the default no-op stash func.
fenced_code.set_stash_func((text) => text);
});
run_test("process_fenced_code_tilde_fence", () => {
const input = "~~~\ntilde fenced\n~~~";
const output = fenced_code.process_fenced_code(input);
assert.equal(
output,
'\ntilde fenced\n
\n\n',
);
});
run_test("process_fenced_code_language_specifier", () => {
fenced_code.initialize({
langs: {
python: {priority: 1, pretty_name: "Python"},
},
});
const input = "```python\nprint('hello')\n```";
const output = fenced_code.process_fenced_code(input);
assert.ok(output.includes('data-code-language="Python"'));
assert.ok(output.includes("print('hello')"));
});
run_test("process_fenced_code_unclosed", () => {
// An unclosed code block should auto-close at EOF.
const input = "before\n```\nunclosed code";
const output = fenced_code.process_fenced_code(input);
assert.equal(
output,
'before\n\nunclosed code\n
\n\n',
);
});