Automerge backed Markdown editor for the Atmosphere
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156// src/plugin/__tests__/parse-linktext.test.ts/** * Documented Obsidian utility: * https://docs.obsidian.md/Reference/TypeScript+API/parseLinktext * * Real-world repro: obsidian42-strange-new-worlds calls parseLinktext() * inside its CM6 ViewPlugin to split a wiki-link into path + subpath. * Without an export the ViewPlugin throws on construction. */import { describe, it, expect } from 'vitest'import { parseLinktext, getLinkpath, stripHeading, stripHeadingForLink } from '../obsidian-stubs'
describe('parseLinktext', () => { it('returns the full path when no subpath fragment is present', () => { expect(parseLinktext('My Note')).toEqual({ path: 'My Note', subpath: '' }) })
it('splits at the first # for heading anchors and retains the leading #', () => { expect(parseLinktext('My Note#Section')).toEqual({ path: 'My Note', subpath: '#Section', }) })
it('handles block-id anchors (#^id) by keeping the leading hash', () => { expect(parseLinktext('Note#^abc123')).toEqual({ path: 'Note', subpath: '#^abc123', }) })
it('returns empty path when linktext starts with #', () => { // Plugins use this for "fragment within current file" links. expect(parseLinktext('#Heading')).toEqual({ path: '', subpath: '#Heading' }) })
it('handles paths containing a slash', () => { expect(parseLinktext('folder/Note#Section')).toEqual({ path: 'folder/Note', subpath: '#Section', }) })
it('handles empty linktext', () => { expect(parseLinktext('')).toEqual({ path: '', subpath: '' }) })})
describe('getLinkpath', () => { // Documented Obsidian utility: // https://docs.obsidian.md/Reference/TypeScript+API/getLinkpath // Converts linktext to linkpath (strips subpath fragment).
it('returns the full path when no subpath fragment is present', () => { expect(getLinkpath('My Note')).toBe('My Note') })
it('strips heading anchor from linktext', () => { expect(getLinkpath('My Note#Section')).toBe('My Note') })
it('strips block-id anchor from linktext', () => { expect(getLinkpath('Note#^abc123')).toBe('Note') })
it('returns empty string when linktext starts with #', () => { expect(getLinkpath('#Heading')).toBe('') })
it('handles paths containing a slash', () => { expect(getLinkpath('folder/Note#Section')).toBe('folder/Note') })
it('handles empty linktext', () => { expect(getLinkpath('')).toBe('') })})
describe('stripHeading', () => { // Documented Obsidian utility: // https://docs.obsidian.md/Reference/TypeScript+API/stripHeading // SNW calls stripHeading() in its CM6 ViewPlugin to display heading labels.
it('strips leading hashes and the trailing space', () => { expect(stripHeading('## Section title')).toBe('Section title') })
it('strips wikilink markers, keeping the visible label', () => { expect(stripHeading('# See [[Other Note|the link]]')).toBe('See the link') })
it('strips bold/italic emphasis markers', () => { expect(stripHeading('# **Bold** and _italic_ heading')).toBe('Bold and italic heading') })
it('returns the input trimmed if no markdown markers are present', () => { expect(stripHeading(' Plain heading ')).toBe('Plain heading') })
it('handles empty string', () => { expect(stripHeading('')).toBe('') })})
describe('stripHeadingForLink', () => { // Documented Obsidian utility: // https://docs.obsidian.md/Reference/TypeScript+API/stripHeadingForLink // Prepares headings for linking by stripping out special characters // that could break links. Differs from stripHeading which normalizes // for matching, not for safe link construction.
it('strips pipe character used for link aliases', () => { expect(stripHeadingForLink('Heading|with|pipes')).toBe('Headingwithpipes') })
it('strips square brackets used in wikilinks', () => { expect(stripHeadingForLink('Heading [with] brackets')).toBe('Heading with brackets') })
it('strips hash character used for heading anchors', () => { expect(stripHeadingForLink('Heading#with#hashes')).toBe('Headingwithhashes') })
it('strips backslash escape character', () => { expect(stripHeadingForLink('Heading\\with\\escapes')).toBe('Headingwithescapes') })
it('strips caret used for block references', () => { expect(stripHeadingForLink('Heading^with^carets')).toBe('Headingwithcarets') })
it('strips multiple special characters at once', () => { expect(stripHeadingForLink('My [Heading|Alias]#section')).toBe('My HeadingAliassection') })
it('preserves normal text', () => { expect(stripHeadingForLink('Normal Heading')).toBe('Normal Heading') })
it('handles empty string', () => { expect(stripHeadingForLink('')).toBe('') })
it('returns empty string when input is only special characters', () => { expect(stripHeadingForLink('|#^[]\\|')).toBe('') })
it('preserves unicode characters', () => { expect(stripHeadingForLink('日本語 Heading #test')).toBe('日本語 Heading test') })
it('preserves whitespace (does not trim)', () => { expect(stripHeadingForLink(' Heading ')).toBe(' Heading ') })})