tests/footnotes.test.ts
Rama main · réplica de lectura del repositorio original.
// A note's footnotes as data (shared/footnotes.ts): the pane's list, the
// two hops' addresses, and the sidenote stacking.
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { footnotesOf, stackSidenotes } from "../shared/footnotes.ts";
describe("footnotesOf", () => {
it("lists references in reading order with their definitions and addresses", () => {
const md = [
"---",
"title: x [^0]",
"---",
"First claim.[^b] Second.[^a]",
"",
"[^a]: The a note.",
" continued here.",
"[^b]: The b note.",
].join("\n");
const notes = footnotesOf(md);
assert.deepEqual(notes.map((n) => n.label), ["b", "a"]);
assert.equal(notes[0].text, "The b note.");
assert.equal(notes[0].defLine, 8);
assert.deepEqual(notes[0].refs, [{ line: 4, col: 12 }]);
assert.equal(notes[1].text, "The a note. continued here.");
assert.equal(notes[1].defLine, 6);
assert.deepEqual(notes[1].refs, [{ line: 4, col: 24 }]);
});
it("keeps a definition nothing references, after the referenced ones", () => {
const notes = footnotesOf("Text[^1]\n\n[^stray]: lonely\n[^1]: one");
assert.deepEqual(notes.map((n) => n.label), ["1", "stray"]);
assert.deepEqual(notes[1].refs, []);
assert.equal(notes[1].text, "lonely");
});
it("reports a reference with no definition as empty text", () => {
const [n] = footnotesOf("Text[^gone]");
assert.equal(n.text, "");
assert.equal(n.defLine, null);
assert.equal(n.refs.length, 1);
});
it("ignores brackets inside code fences and code spans", () => {
const md = "```\n[^1]: in code\nx[^2]\n```\nsee `[^3]` and real[^4]\n\n[^4]: yes";
const notes = footnotesOf(md);
assert.deepEqual(notes.map((n) => n.label), ["4"]);
});
it("counts every reference to one label", () => {
const [n] = footnotesOf("a[^n] b[^n]\nc[^n]\n\n[^n]: thrice");
assert.equal(n.refs.length, 3);
assert.deepEqual(n.refs.map((r) => r.line), [1, 1, 2]);
});
it("answers nothing for a note with no footnotes", () => {
assert.deepEqual(footnotesOf("Just prose.\n\n- a list [x]"), []);
});
});
describe("stackSidenotes", () => {
it("leaves notes where they want to be when they do not collide", () => {
assert.deepEqual(stackSidenotes([{ want: 0, height: 20 }, { want: 100, height: 20 }], 8), [0, 100]);
});
it("pushes a colliding note under the one above, plus the gap", () => {
assert.deepEqual(
stackSidenotes([{ want: 0, height: 50 }, { want: 30, height: 20 }, { want: 60, height: 10 }], 8),
[0, 58, 86],
);
});
it("never moves a note up", () => {
assert.deepEqual(stackSidenotes([{ want: 200, height: 10 }, { want: 50, height: 10 }], 4), [200, 214]);
});
});