Files
racket-wiki/test/wiki-markdown.test.mjs
T
2026-09-07 22:41:33 +02:00

102 lines
4.8 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import {
applyImageWidthMarkup,
cmapMentionTarget,
escapeHtml,
expandNamespacedMarkdownLinks,
expandTodoMarkup,
expandWikiMentions,
extractCmapEmbeds,
normalizeMarkdownLinkDestinations,
protectCamelCaseWikiWords,
restoreCmapEmbeds
} from "../static/js/wiki/markdown.js";
test("Todo markup is escaped, numbered and left alone in fenced code", () => {
const markdown = "todo(<script>)\n```\ntodo(no change)\n```\ntodo(second)";
const expanded = expandTodoMarkup(markdown, "start", "Todo & note");
assert.match(expanded, /#todo\/start\/1/);
assert.match(expanded, /#todo\/start\/2/);
assert.match(expanded, /Todo &amp; note/);
assert.match(expanded, /&lt;script&gt;/);
assert.match(expanded, /```\ntodo\(no change\)\n```/);
});
test("image options add width and alignment to rendered image tags", () => {
assert.equal(
applyImageWidthMarkup('<img src="x.png"> { width=40% center }'),
'<img src="x.png" style="width: 40%" class="wiki-image-center">');
assert.equal(
applyImageWidthMarkup('<img class="existing" src="x.png"> { width=240 left float }'),
'<img class="existing wiki-image-float-left" src="x.png" style="width: 240px">');
});
test("explicit namespaced links become internal routes outside code", () => {
const markdown = "[Page](notes:roadmap)\n[CMap](cmap:architecture)\n```\n[Code](notes:keep)\n```";
assert.equal(
expandNamespacedMarkdownLinks(markdown),
"[Page](#/notes%3Aroadmap)\n[CMap](#cmap/architecture)\n```\n[Code](notes:keep)\n```");
});
test("link destinations with spaces are encoded without changing code", () => {
const markdown = "* [DOC](/uploads/review-zuidas-2026:appreciatie/1788796826-35348-Review ZuidasDok - Hans Dijkema - Beschouwing v3.docx)\n`[code](/uploads/page/file name.txt)`\n```\n[code](/uploads/page/file name.txt)\n```";
assert.equal(
normalizeMarkdownLinkDestinations(markdown),
"* [DOC](/uploads/review-zuidas-2026:appreciatie/1788796826-35348-Review%20ZuidasDok%20-%20Hans%20Dijkema%20-%20Beschouwing%20v3.docx)\n`[code](/uploads/page/file name.txt)`\n```\n[code](/uploads/page/file name.txt)\n```");
});
test("WikiWords use page and CMap catalogues without expanding protected text", () => {
const pages = [
{ slug: "homeopathie", namespace: "", pageSlug: "homeopathie", title: "Homeopathie Wiki" }
];
const conceptMaps = [{ slug: "architectuur", title: "Architectuur Kaart" }];
const markdown = "HomeopathieWiki en cmap:ArchitectuurKaart, maar `NieuwePagina` niet.";
assert.equal(
expandWikiMentions(markdown, pages, [], conceptMaps),
"[Homeopathie Wiki](#/homeopathie) en [Architectuur Kaart](#cmap/architectuur), maar `NieuwePagina` niet.");
});
test("an exclamation mark renders a WikiWord literally without becoming visible", () => {
const pages = [
{ slug: "homeopathie", namespace: "", pageSlug: "homeopathie", title: "Homeopathie Wiki" }
];
const conceptMaps = [{ slug: "architectuur", title: "Architectuur Kaart" }];
const markdown = "!HomeopathieWiki en !NieuwePagina en !cmap:ArchitectuurKaart.";
const expanded = expandWikiMentions(markdown, pages, [], conceptMaps);
assert.equal(expanded,
"&#72;omeopathieWiki en &#78;ieuwePagina en cmap:&#65;rchitectuurKaart.");
assert.equal(expandWikiMentions(expanded, pages, [], conceptMaps), expanded);
});
test("the WikiWord escape remains literal in protected Markdown", () => {
const markdown = "`!NieuwePagina` en [!NieuwePagina](https://example.com)";
assert.equal(expandWikiMentions(markdown, [], [], []), markdown);
});
test("protects unprotected CamelCase WikiWords without changing Markdown syntax", () => {
const markdown = "HomeopathieWiki and [ExistingLink](https://example.test)\n`CodeWord`\n!AlreadyLiteral\n IndentedCodeWord";
assert.equal(protectCamelCaseWikiWords(markdown),
"!HomeopathieWiki and [ExistingLink](https://example.test)\n`CodeWord`\n!AlreadyLiteral\n IndentedCodeWord");
});
test("ambiguous CMap mentions are not resolved", () => {
const conceptMaps = [
{ slug: "first", title: "Zelfde Kaart" },
{ slug: "second", title: "ZelfdeKaart" }
];
assert.equal(cmapMentionTarget("ZelfdeKaart", conceptMaps), null);
});
test("CMap embeds survive Markdown rendering through escaped placeholders", () => {
const extracted = extractCmapEmbeds("before\n{{cmap:architecture}}\n```\n{{cmap:code}}\n```");
assert.equal(extracted.embeds.length, 1);
assert.match(extracted.markdown, /RACKETWIKICMAPEMBED0TOKEN/);
assert.match(extracted.markdown, /\{\{cmap:code\}\}/);
assert.equal(
restoreCmapEmbeds("<p>RACKETWIKICMAPEMBED0TOKEN</p>", extracted.embeds, "Loading…"),
'<section class="rw-cmap-embed" data-cmap-reference="architecture"><div class="rw-cmap-embed-loading">Loading…</div></section>');
assert.equal(escapeHtml('<a href="x">&'), "&lt;a href=&quot;x&quot;&gt;&amp;");
});