Ctrl K
ComunidadGuías…

tests/caret.test.ts

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

Archivo original ↗Preguntar a KiBot
// Where the caret lands when a note is opened (client/editor/caretHome.ts).
//
// THE FINDING (v1.8 UX audit, F9): every note opened with the caret on the
// phantom blank line between the properties card and the H1. It is a gap —
// nothing to read there, nothing to continue — and it draws as an empty
// paragraph at the top of the document, on every note in the vault, forever.
//
// The rule it became is small and total, and it has to stay both: the ONE
// thing it must never do is land inside the frontmatter, because that is the
// raw-YAML bug (livePreview.ts::interactedField) arriving through the other
// door.

import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { afterFrontmatter, caretHome } from "../client/editor/caretHome.ts";

const fm = (body: string): string => `---\ntitle: A note\ntags: [x]\n---\n${body}`;

describe("caret home", () => {
  it("parks at the END of the H1, not on the blank line above it", () => {
    const doc = fm("\n# The title\n\nProse.\n");
    const at = caretHome("Note.md", doc);
    assert.equal(doc.slice(0, at).endsWith("# The title"), true);
    assert.equal(doc[at], "\n");
  });

  it("skips any number of blank lines under the fence", () => {
    const doc = fm("\n\n\n# Title\n");
    assert.equal(doc.slice(0, caretHome("Note.md", doc)).endsWith("# Title"), true);
  });

  it("takes the heading at any level, and only a real ATX heading", () => {
    const h3 = fm("\n### Deep\n");
    assert.equal(h3.slice(0, caretHome("Note.md", h3)).endsWith("### Deep"), true);
    // "#tag" is not a heading: no space after the hashes.
    const tagged = fm("\n#daily and some prose\n");
    assert.equal(caretHome("Note.md", tagged), tagged.indexOf("#daily"));
  });

  it("a note that opens with a fence (a Media card) parks on the blank line ABOVE it, never on or after the card", () => {
    const doc = fm("\n```tracker\ntitle: X\nprogress: 1/14\n```\n");
    assert.equal(caretHome("Media/Books/X.md", doc), afterFrontmatter("Media/Books/X.md", doc));
    // No blank line to park on: after the closing fence, where prose goes.
    const tight = fm("```tracker\ntitle: X\n```\n\nProse after.\n");
    assert.equal(tight.slice(caretHome("Note.md", tight)), "\nProse after.\n");
  });

  it("a headingless note opens at the START of its prose, never at the end", () => {
    const doc = fm("\nFirst line.\n\nSecond paragraph.\n");
    assert.equal(caretHome("Note.md", doc), doc.indexOf("First line."));
  });

  it("a note that is only frontmatter opens at the document end — it is waiting to be written", () => {
    const doc = fm("\n\n");
    assert.equal(caretHome("Note.md", doc), doc.length);
    assert.equal(caretHome("Note.md", "---\ntitle: A\n---\n"), 4 + 9 + 4);
  });

  it("NEVER lands inside the frontmatter — the raw-YAML bug's other door", () => {
    for (const body of ["", "\n", "\n\n\n", "\n# H\n", "\nprose\n", "\n- a list\n"]) {
      const doc = fm(body);
      assert.ok(
        caretHome("Note.md", doc) >= afterFrontmatter("Note.md", doc),
        `caret inside the fence for body ${JSON.stringify(body)}`,
      );
    }
  });

  it("a note with no frontmatter answers 0 — nothing to step over", () => {
    assert.equal(caretHome("Note.md", "# Title\n\nProse.\n"), 0);
    assert.equal(caretHome("Note.md", ""), 0);
  });

  it("reads a .tex note's comment-block frontmatter, not a YAML fence", () => {
    const tex = "%---%\n% title: Paper\n%---%\n\n\\section{One}\n";
    const at = caretHome("Paper.tex", tex);
    assert.ok(at >= tex.indexOf("\\section"), "landed before the LaTeX body");
    // The `\section` line is not an ATX heading, so it is the line's START.
    assert.equal(at, tex.indexOf("\\section"));
  });

  it("is total: no input throws, and the answer is always inside the document", () => {
    for (const doc of ["", "---", "---\n", "---\nnot closed", "---\n---", "\n\n\n", "---\na: 1\n---"]) {
      const at = caretHome("Note.md", doc);
      assert.ok(at >= 0 && at <= doc.length, `out of range for ${JSON.stringify(doc)}`);
    }
  });
});