1
Files
2025/tools/tests/markdown_links.test.js

97 lines
4.0 KiB
JavaScript

const test = require("node:test");
const assert = require("node:assert/strict");
const { Readable } = require("node:stream");
const {
collectMarkdownLinksFromStream,
extractLinksFromText,
sanitizeUrlCandidate,
} = require("../lib/markdown_links");
test("extractLinksFromText returns sanitized external URLs only once", () => {
const input =
"See [example](https://example.com) and <https://foo.com>. " +
"Autolink https://bar.com/path).\nDuplicate https://example.com!";
const urls = extractLinksFromText(input);
assert.deepStrictEqual(urls, ["https://example.com", "https://foo.com", "https://bar.com/path"]);
});
test("extractLinksFromText does not extend a markdown destination past the closing parenthesis", () => {
const input = "J'ai eu mon lot d'installations du couple [anope](https://www.anope.org/)/epona.";
const urls = extractLinksFromText(input);
assert.deepStrictEqual(urls, ["https://www.anope.org/"]);
});
test("collectMarkdownLinksFromStream preserves line numbers", async () => {
const content = [
"Intro line with no link",
"Markdown [link](https://docs.example.org/page).",
"Plain link https://news.example.net/article.",
"Trailing <https://portal.example.com/path> punctuation.",
"Markdown [link](https://docs.example.org/page(with more valid content)).",
"Le **[baume du Canada](https://fr.wikipedia.org/wiki/Baume_du_Canada)**",
"(_Theropoda [incertae sedis](https://fr.wikipedia.org/wiki/Incertae_sedis)_)",
"[CDN](https://fr.wikipedia.org/wiki/Réseau_de_diffusion_de_contenu)[^2].",
"(heu... [oui](https://github.com/opencart/opencart/tree/master/upload/system/storage/vendor)...)"
].join("\n");
const stream = Readable.from([content]);
const links = await collectMarkdownLinksFromStream(stream);
assert.deepStrictEqual(links, [
{ url: "https://docs.example.org/page", line: 2 },
{ url: "https://news.example.net/article", line: 3 },
{ url: "https://portal.example.com/path", line: 4 },
{ url: "https://docs.example.org/page(with more valid content)", line: 5 },
{ url: "https://fr.wikipedia.org/wiki/Baume_du_Canada", line: 6 },
{ url: "https://fr.wikipedia.org/wiki/Incertae_sedis", line: 7 },
{ url: "https://fr.wikipedia.org/wiki/Réseau_de_diffusion_de_contenu", line: 8 },
{ url: "https://github.com/opencart/opencart/tree/master/upload/system/storage/vendor", line: 9 },
]);
});
test("collectMarkdownLinksFromStream ignores inline code, fenced code blocks and indented code blocks", async () => {
const content = [
"Visible https://visible.example.com.",
"Inline code `https://inline.example.com` and normal https://normal.example.com.",
"",
"```yaml",
"uses: https://github.com/easingthemes/ssh-deploy@main",
"```",
"",
" https://indented.example.com",
"After code https://after.example.com.",
].join("\n");
const stream = Readable.from([content]);
const links = await collectMarkdownLinksFromStream(stream);
assert.deepStrictEqual(links, [
{ url: "https://visible.example.com", line: 1 },
{ url: "https://normal.example.com", line: 2 },
{ url: "https://after.example.com", line: 9 },
]);
});
test("collectMarkdownLinksFromStream ignores URLs in front matter entirely", async () => {
const content = [
"---",
"links:",
" # url: https://ignored.example.com",
" - url: https://included.example.com",
"---",
"Body with https://body.example.com link.",
].join("\n");
const stream = Readable.from([content]);
const links = await collectMarkdownLinksFromStream(stream);
assert.deepStrictEqual(links, [
{ url: "https://body.example.com", line: 6 },
]);
});
test("sanitizeUrlCandidate removes spurious trailing punctuation", () => {
const cases = [
["https://example.com).", "https://example.com"],
["https://example.com!\"", "https://example.com"],
["<https://example.com>", "https://example.com"],
];
for (const [input, expected] of cases) {
assert.equal(sanitizeUrlCandidate(input), expected);
}
});