import { test } from 'node:test'; import assert from 'node:assert/strict'; import { createRequire } from 'node:module'; import { parseMarkdown } from '../src/lib/markdown.js'; import { linkHeading, matchesHeading } from '../src/lib/links.js'; import { sectionOf } from '../src/lib/embed.js'; const require = createRequire(import.meta.url); const { renameHeadingRefs, matchesHeading: matchesOnDisk, linkHeading: linkHeadingOnDisk } = require('../electron/links.cjs'); test('heading text inside a link: unsafe characters become spaces, matching ignores case and spacing', () => { assert.equal(linkHeading('C# [tips] | ^x'), 'C tips x'); assert.equal(linkHeading(' Plain heading '), 'Plain heading'); assert.equal(linkHeading('# | ^'), ''); assert.ok(matchesHeading('goals', 'Goals')); assert.ok(matchesHeading('Q3 GOALS', ' q3 goals ')); assert.ok(matchesHeading('C tips', 'C# [tips]'), 'the link-safe spelling of a heading finds it'); assert.ok(matchesHeading('C# [tips]', 'C# [tips]')); assert.ok(!matchesHeading('', 'Goals') && !matchesHeading('Goal', 'Goals')); // the disk side follows the same rules for (const [a, b] of [['goals', 'Goals'], ['C tips', 'C# [tips]'], ['Goal', 'Goals']]) assert.equal(matchesOnDisk(a, b), matchesHeading(a, b)); assert.equal(linkHeadingOnDisk('C# [tips] | ^x'), linkHeading('C# [tips] | ^x')); // a section can be found by either spelling const blocks = parseMarkdown('## C# [tips]\n\ntext\n\n## Next\n'); assert.equal(sectionOf(blocks, 'C tips').length, 2); }); test('renaming a heading re-points [[Page#Heading]] links and embeds, and nothing else', () => { const P = (id, body) => ({ id, title: id.split('/').pop(), parent: null, exists: true, body }); const pages = [P('Plan', '# Goals'), P('Archive/Plan', '# Goals'), P('Notes', '')]; const body = 'See [[Plan#Goals]], [[plan#GOALS|the goals]], ![[Plan#goals]], [[Plan#Goals#Sub]], [[Plan#Other]], [[Archive/Plan#Goals]], [[#Goals]], [[Plan]], `[[Plan#Goals]]`.'; const r = renameHeadingRefs(body, pages, 'Plan', 'Goals', 'Q3 [goals] | new #1'); assert.equal(r.count, 3); assert.equal(r.body, 'See [[Plan#Q3 goals new 1]], [[plan#Q3 goals new 1|the goals]], ![[Plan#Q3 goals new 1]], [[Plan#Goals#Sub]], [[Plan#Other]], [[Archive/Plan#Goals]], [[#Goals]], [[Plan]], `[[Plan#Goals]]`.'); assert.equal(renameHeadingRefs('nothing [[Plan#X]]', pages, 'Plan', 'Goals', 'New'), null); assert.equal(renameHeadingRefs(body, pages, 'Plan', 'Goals', '# | ^'), null, 'a name with nothing usable is not written'); // a link written with the link-safe spelling of the old heading follows too const unsafe = renameHeadingRefs('[[Plan#C tips]]', [P('Plan', '')], 'Plan', 'C# [tips]', 'New'); assert.equal(unsafe.body, '[[Plan#New]]'); });