Ctrl K
ComunidadGuías…

tests/blockRefs.test.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// Block references (shared/blockId.ts + shared/anchors.ts): the marker, the
// block a line belongs to, and the anchor table that `[[Note#^id]]` looks up.
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { blockRange, isBareBlockId, markdownBlock, mintBlockId, parseBlockId, stripBlockId, withBlockId } from "../shared/blockId.ts";
import { markdownAnchors, resolveAnchorIn } from "../shared/anchors.ts";

const NOTE = `---
title: x
---
# Title

First paragraph line one
line two ^para1

- item one ^it1
- item two
  wrapped ^it2
- item three

Second paragraph.
^lone

\`\`\`
code ^notanid
\`\`\`
`;

describe("a block id", () => {
  it("parses, strips and appends at the line's end", () => {
    assert.deepEqual(parseBlockId("some text ^abc-12"), { id: "abc-12", start: 9 });
    assert.equal(parseBlockId("a caret ^ in the middle"), null);
    assert.equal(stripBlockId("some text ^abc"), "some text");
    assert.equal(withBlockId("some text ^old", "new1"), "some text ^new1");
    assert.equal(withBlockId("", "x"), "^x");
    assert.equal(isBareBlockId("  ^abc  "), true);
  });
  it("mints six lowercase alphanumerics", () => {
    assert.match(mintBlockId(), /^[a-z0-9]{6}$/);
    assert.equal(mintBlockId(() => 0), "aaaaaa");
  });
});

describe("the block a line belongs to", () => {
  const lines = NOTE.split("\n");
  it("is the paragraph around it, walked up and down", () => {
    assert.deepEqual(blockRange(lines, 6), { start: 5, end: 7 });
    assert.deepEqual(blockRange(lines, 7), { start: 5, end: 7 });
  });
  it("is the list item with its wrapped continuation", () => {
    assert.deepEqual(blockRange(lines, 9), { start: 8, end: 9 });
    assert.deepEqual(blockRange(lines, 10), { start: 9, end: 11 });
  });
  it("is the block ABOVE a bare id line", () => {
    assert.deepEqual(blockRange(lines, 15), { start: 13, end: 15 });
    assert.equal(blockRange(lines, 5), null);
  });
  it("slices the block's markdown with the marker off", () => {
    assert.equal(markdownBlock(NOTE, 7), "First paragraph line one\nline two");
    assert.equal(markdownBlock(NOTE, 10), "- item two\n  wrapped");
    assert.equal(markdownBlock(NOTE, 15), "Second paragraph.");
  });
});

describe("block ranges, the corners", () => {
  it("is a quote's run of > lines, and the id comes off the last quoted line", () => {
    const md = "> one\n> two ^q1\n\nafter";
    assert.deepEqual(blockRange(md.split("\n"), 2), { start: 0, end: 2 });
    assert.equal(markdownBlock(md, 2), "> one\n> two");
  });
  it("registers ^Abc and ^abc once, the first spelling winning", () => {
    const anchors = markdownAnchors("a ^Abc\n\nb ^abc\n").filter((a) => a.kind === "block");
    assert.deepEqual(anchors.map((a) => a.id), ["^Abc"]);
  });
  it("does not read a heading's tail as an id", () => {
    assert.equal(markdownAnchors("# Title ^h1\n").some((a) => a.kind === "block"), false);
  });
});

describe("block anchors", () => {
  it("join the anchor table with the caret kept, titled by the block's text", () => {
    const anchors = markdownAnchors(NOTE);
    const blocks = anchors.filter((a) => a.kind === "block");
    assert.deepEqual(blocks.map((a) => [a.id, a.line]), [["^para1", 7], ["^it1", 9], ["^it2", 11], ["^lone", 15]]);
    assert.equal(blocks[0].title, "line two");
    assert.equal(blocks[1].title, "item one");
    assert.equal(blocks[3].title, "Second paragraph.");
    // inside a fence is code, not an address
    assert.equal(anchors.some((a) => a.id === "^notanid"), false);
    // the heading is still there
    assert.equal(anchors[0].id, "title");
  });
  it("resolves [[Note#^id]] the way findAnchor already resolves headings", () => {
    assert.equal(resolveAnchorIn("n.md", NOTE, "^it2")?.line, 11);
    assert.equal(resolveAnchorIn("n.md", NOTE, "^nope"), null);
  });
});