96 lines
3.2 KiB
JavaScript
96 lines
3.2 KiB
JavaScript
// Standalone test for the Obsidian-style wikilink plugin.
|
|
// Run with: node tests/run-wikilinks-test.mjs
|
|
import MarkdownIt from "markdown-it";
|
|
import fs from "fs";
|
|
import { bundleForTest } from "./helpers/bundle.mjs";
|
|
|
|
const { mod, cleanupBundle } = await bundleForTest({
|
|
name: "folio-wikilinks",
|
|
entryPoints: ["src/renderer/wikilinks.ts"],
|
|
});
|
|
const { wikilinkPlugin } = mod;
|
|
|
|
const chapters = [
|
|
{ id: "introduction-1", title: "Introduction" },
|
|
{ id: "money-2", title: "Money" },
|
|
];
|
|
|
|
function makeMd() {
|
|
const md = new MarkdownIt({ html: false, linkify: true, typographer: true });
|
|
md.use(wikilinkPlugin, { chapters });
|
|
return md;
|
|
}
|
|
|
|
let failures = 0;
|
|
function ok(cond, msg) {
|
|
if (cond) console.log(" ok -", msg);
|
|
else {
|
|
failures++;
|
|
console.error("FAIL -", msg);
|
|
}
|
|
}
|
|
|
|
const md = makeMd();
|
|
|
|
// basic wikilink resolves by title (case-insensitive)
|
|
const html1 = md.render("See [[Introduction]] for details.");
|
|
ok(
|
|
html1.includes('<a href="folio:chapter/introduction-1" class="wikilink internal">Introduction</a>'),
|
|
"wikilink resolves by title -> internal link with chapter id"
|
|
);
|
|
|
|
// wikilink resolves by id
|
|
const html2 = md.render("Link to [[introduction-1]] too.");
|
|
ok(
|
|
html2.includes('href="folio:chapter/introduction-1"') &&
|
|
html2.includes("class=\"wikilink internal\""),
|
|
"wikilink resolves by chapter id"
|
|
);
|
|
|
|
// label-only match: title takes priority over id
|
|
const html2b = md.render("[[Money]]");
|
|
ok(html2b.includes('href="folio:chapter/money-2"'), "title match wins over id when both plausible");
|
|
|
|
// missing wikilink renders as missing
|
|
const html3 = md.render("A [[Nonexistent]] thing.");
|
|
ok(
|
|
html3.includes('href="#"') && html3.includes('class="wikilink missing"'),
|
|
"unresolved wikilink renders as missing"
|
|
);
|
|
|
|
// alias / label syntax [[target|label]]
|
|
const html4 = md.render("[[Introduction|custom label]]");
|
|
ok(
|
|
html4.includes('href="folio:chapter/introduction-1"') &&
|
|
html4.includes(">custom label<"),
|
|
"alias syntax renders custom label pointing at resolved target"
|
|
);
|
|
|
|
// alias of a missing target is still missing
|
|
const html5 = md.render("[[Nope|shown]]");
|
|
ok(
|
|
html5.includes('class="wikilink missing"') && html5.includes(">shown<"),
|
|
"alias of missing target renders missing with alias label"
|
|
);
|
|
|
|
// regression: standard markdown links still work alongside wikilinks
|
|
const html6 = md.render("[external](https://example.com) and [[Introduction]]");
|
|
ok(html6.includes('<a href="https://example.com">external</a>'), "standard link still renders");
|
|
ok(html6.includes('href="folio:chapter/introduction-1"'), "wikilink renders next to standard link");
|
|
|
|
// regression: bold/italic still parse
|
|
const html7 = md.render("**bold** and [[Introduction]]");
|
|
ok(html7.includes("<strong>bold</strong>"), "emphasis still parses with wikilinks present");
|
|
|
|
// nested brackets are not treated as wikilinks
|
|
const html8 = md.render("not a [[a [[b]] c]] wikilink");
|
|
ok(!html8.includes('class="wikilink"'), "nested brackets not parsed as wikilink");
|
|
|
|
// empty [[ ]] is not a wikilink
|
|
const html9 = md.render("empty [[] here");
|
|
ok(!html9.includes('class="wikilink"'), "empty wikilink target not parsed");
|
|
|
|
cleanupBundle();
|
|
|
|
console.log("\nWikilink tests: " + (failures === 0 ? "ALL PASSED" : failures + " FAILED"));
|
|
process.exit(failures === 0 ? 0 : 1);
|