CLI for obsidian that doesn't require the obsidian desktop app to be open
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155import { describe, expect, test } from "vitest";import { parseMarkdownLinks } from "../src/markdown/markdown-links";import { parseMarkdown } from "../src/markdown/parser";import { parseWikilinks } from "../src/markdown/wikilinks";
// ---------------------------------------------------------------------------// Fenced code block exclusion// ---------------------------------------------------------------------------// Content inside fenced code blocks (``` ... ```) is not markdown — it is// literal text. Double brackets like [[0, 3]] inside a code block are// JavaScript array-of-arrays literals, not Obsidian wikilinks. Obsidian// itself does not render them as links. The parsers must skip code-block// content to avoid false positives.// ---------------------------------------------------------------------------
describe("parseWikilinks: ignores content inside fenced code blocks", () => { test("does not parse [[0, 3]] inside a ```typescript fenced block", () => { const source = [ "# Example", "", "```typescript", "// Fuse.js returns: indices: [[0, 3]]", "```", "", "See [[RealLink]] for details.", ].join("\n");
const wikilinks = parseWikilinks(source, lineOffsets(source));
expect(wikilinks).toHaveLength(1); expect(wikilinks[0]?.raw).toBe("[[RealLink]]"); expect(wikilinks[0]?.targetText).toBe("RealLink"); });
test("does not parse [[item]] inside an indented code block (4 spaces)", () => { // Obsidian itself treats 4-space-indented lines as code blocks in // reading mode, so [[item]] inside them should not be linked. const source = [ "# Notes", "", " const x = [[item]];", "", "Link to [[Target]].", ].join("\n");
const wikilinks = parseWikilinks(source, lineOffsets(source));
expect(wikilinks).toHaveLength(1); expect(wikilinks[0]?.raw).toBe("[[Target]]"); });
test("does not parse a wikilink inside a tilde-fenced block (~~~)", () => { const source = ["~~~", "Result: [[nested]]", "~~~", "", "[[Outside]]"].join( "\n", );
const wikilinks = parseWikilinks(source, lineOffsets(source));
expect(wikilinks).toHaveLength(1); expect(wikilinks[0]?.raw).toBe("[[Outside]]"); });
test("does not parse wikilinks across multiple lines in a code block", () => { const source = [ "```json", '{ "data": [[1, 2], [3, 4]] }', "```", "", "[[Legit]]", ].join("\n");
const wikilinks = parseWikilinks(source, lineOffsets(source));
expect(wikilinks).toHaveLength(1); expect(wikilinks[0]?.targetText).toBe("Legit"); });
test("does not parse wikilinks inside inline code (single backtick)", () => { const source = "Use `const arr = [[1, 2]]` only. See [[RealTarget]].";
const wikilinks = parseWikilinks(source, lineOffsets(source));
expect(wikilinks).toHaveLength(1); expect(wikilinks[0]?.raw).toBe("[[RealTarget]]"); });});
describe("parseMarkdownLinks: ignores content inside fenced code blocks", () => { test("does not parse [text](url) inside a fenced code block", () => { const source = [ "```markdown", "[Inside Block](https://example.com)", "```", "", "[Outside](https://real.com)", ].join("\n");
const links = parseMarkdownLinks(source, lineOffsets(source));
expect(links).toHaveLength(1); expect(links[0]?.target).toBe("https://real.com"); });});
describe("parseMarkdown: ignores wikilinks inside fenced code blocks (end-to-end)", () => { test("parseMarkdown strips code-block content before extracting wikilinks", () => { const source = [ "---", "title: Test", "---", "", "```typescript", "// indices: [[0, 3]]", "```", "", "See [[WorkingLink]] for more.", ].join("\n");
const result = parseMarkdown(source);
expect(result.wikilinks).toHaveLength(1); expect(result.wikilinks[0]?.raw).toBe("[[WorkingLink]]"); expect(result.wikilinks[0]?.targetText).toBe("WorkingLink"); });
test("parseMarkdown preserves a wikilink that appears both inside and outside code blocks (only the outside one)", () => { const source = [ "```", "[[Ambiguous]]", "```", "", "Link to [[Ambiguous]].", ].join("\n");
const result = parseMarkdown(source);
expect(result.wikilinks).toHaveLength(1); expect(result.wikilinks[0]?.targetText).toBe("Ambiguous"); });});
// ---------------------------------------------------------------------------// Helper// ---------------------------------------------------------------------------
function lineOffsets(source: string): number[] { const offsets = [0]; for (let i = 0; i < source.length; i++) { if (source[i] === "\n") { offsets.push(i + 1); } } return offsets;}