2026-02-22 12:02:29 +01:00
import { describe , it , expect } from 'vitest'
2026-03-11 22:38:25 +01:00
import { preProcessWikilinks , injectWikilinks , restoreWikilinksInBlocks , splitFrontmatter , countWords , extractOutgoingLinks , extractBacklinkContext , extractSnippet } from './wikilinks'
2026-02-22 12:02:29 +01:00
2026-02-23 08:53:43 +01:00
interface TestBlock {
type ? : string
text? : string
content? : TestBlock [ ]
children? : TestBlock [ ]
props? : Record < string , string >
href? : string
[ key : string ] : unknown
}
2026-02-22 17:51:04 +01:00
2026-02-22 12:02:29 +01:00
describe ( 'preProcessWikilinks' , ( ) = > {
it ( 'replaces [[target]] with placeholder tokens' , ( ) = > {
const result = preProcessWikilinks ( 'See [[My Note]] for details' )
expect ( result ) . toContain ( 'WIKILINK:My Note' )
expect ( result ) . not . toContain ( '[[My Note]]' )
} )
it ( 'handles aliases [[note|alias]]' , ( ) = > {
const result = preProcessWikilinks ( 'Link to [[project/my-project|My Project]]' )
expect ( result ) . toContain ( 'WIKILINK:project/my-project|My Project' )
} )
it ( 'handles multiple wikilinks' , ( ) = > {
const result = preProcessWikilinks ( 'See [[A]] and [[B]]' )
expect ( result ) . toContain ( 'WIKILINK:A' )
expect ( result ) . toContain ( 'WIKILINK:B' )
} )
it ( 'returns unchanged text when no wikilinks' , ( ) = > {
const input = 'No links here'
expect ( preProcessWikilinks ( input ) ) . toBe ( input )
} )
it ( 'handles empty string' , ( ) = > {
expect ( preProcessWikilinks ( '' ) ) . toBe ( '' )
} )
} )
describe ( 'injectWikilinks' , ( ) = > {
const WL_START = '\u2039WIKILINK:'
const WL_END = '\u203A'
it ( 'converts placeholder text nodes into wikilink nodes' , ( ) = > {
const blocks = [ {
content : [
{ type : 'text' , text : ` before ${ WL_START } My Note ${ WL_END } after ` } ,
] ,
} ]
2026-02-23 08:53:43 +01:00
const result = injectWikilinks ( blocks ) as TestBlock [ ]
2026-02-22 12:02:29 +01:00
expect ( result [ 0 ] . content ) . toHaveLength ( 3 )
2026-02-23 08:53:43 +01:00
expect ( result [ 0 ] . content ! [ 0 ] ) . toEqual ( { type : 'text' , text : 'before ' } )
expect ( result [ 0 ] . content ! [ 1 ] ) . toEqual ( {
2026-02-22 12:02:29 +01:00
type : 'wikilink' ,
props : { target : 'My Note' } ,
content : undefined ,
} )
2026-02-23 08:53:43 +01:00
expect ( result [ 0 ] . content ! [ 2 ] ) . toEqual ( { type : 'text' , text : ' after' } )
2026-02-22 12:02:29 +01:00
} )
it ( 'handles multiple wikilinks in one text node' , ( ) = > {
const blocks = [ {
content : [
{ type : 'text' , text : ` ${ WL_START } A ${ WL_END } and ${ WL_START } B ${ WL_END } ` } ,
] ,
} ]
2026-02-23 08:53:43 +01:00
const result = injectWikilinks ( blocks ) as TestBlock [ ]
const wikilinkNodes = result [ 0 ] . content ! . filter ( ( n : TestBlock ) = > n . type === 'wikilink' )
2026-02-22 12:02:29 +01:00
expect ( wikilinkNodes ) . toHaveLength ( 2 )
2026-02-23 08:53:43 +01:00
expect ( wikilinkNodes [ 0 ] . props ! . target ) . toBe ( 'A' )
expect ( wikilinkNodes [ 1 ] . props ! . target ) . toBe ( 'B' )
2026-02-22 12:02:29 +01:00
} )
it ( 'passes through non-text content items unchanged' , ( ) = > {
const blocks = [ {
content : [
{ type : 'link' , text : 'some link' , href : 'http://example.com' } ,
] ,
} ]
2026-02-23 08:53:43 +01:00
const result = injectWikilinks ( blocks ) as TestBlock [ ]
expect ( result [ 0 ] . content ! [ 0 ] . type ) . toBe ( 'link' )
2026-02-22 12:02:29 +01:00
} )
it ( 'recursively processes children blocks' , ( ) = > {
const blocks = [ {
content : [ ] ,
children : [ {
content : [
{ type : 'text' , text : ` See ${ WL_START } Nested ${ WL_END } ` } ,
] ,
} ] ,
} ]
2026-02-23 08:53:43 +01:00
const result = injectWikilinks ( blocks ) as TestBlock [ ]
const childContent = result [ 0 ] . children ! [ 0 ] . content !
2026-02-22 12:02:29 +01:00
expect ( childContent ) . toHaveLength ( 2 )
expect ( childContent [ 1 ] . type ) . toBe ( 'wikilink' )
2026-02-23 08:53:43 +01:00
expect ( childContent [ 1 ] . props ! . target ) . toBe ( 'Nested' )
2026-02-22 12:02:29 +01:00
} )
it ( 'handles blocks without content or children' , ( ) = > {
const blocks = [ { type : 'heading' , props : { level : 1 } } ]
2026-02-23 08:53:43 +01:00
const result = injectWikilinks ( blocks as unknown [ ] ) as TestBlock [ ]
2026-02-22 12:02:29 +01:00
expect ( result ) . toEqual ( blocks )
} )
it ( 'handles text node that starts with wikilink' , ( ) = > {
const blocks = [ {
content : [
{ type : 'text' , text : ` ${ WL_START } First ${ WL_END } text ` } ,
] ,
} ]
2026-02-23 08:53:43 +01:00
const result = injectWikilinks ( blocks ) as TestBlock [ ]
expect ( result [ 0 ] . content ! [ 0 ] . type ) . toBe ( 'wikilink' )
expect ( result [ 0 ] . content ! [ 0 ] . props ! . target ) . toBe ( 'First' )
expect ( result [ 0 ] . content ! [ 1 ] . text ) . toBe ( ' text' )
2026-02-22 12:02:29 +01:00
} )
it ( 'handles text node that ends with wikilink' , ( ) = > {
const blocks = [ {
content : [
{ type : 'text' , text : ` text ${ WL_START } Last ${ WL_END } ` } ,
] ,
} ]
2026-02-23 08:53:43 +01:00
const result = injectWikilinks ( blocks ) as TestBlock [ ]
expect ( result [ 0 ] . content ! [ 0 ] . text ) . toBe ( 'text ' )
expect ( result [ 0 ] . content ! [ 1 ] . type ) . toBe ( 'wikilink' )
2026-02-22 12:02:29 +01:00
} )
} )
describe ( 'splitFrontmatter' , ( ) = > {
it ( 'splits YAML frontmatter from body' , ( ) = > {
const content = '---\ntitle: Hello\n---\n\n# Hello\n'
const [ fm , body ] = splitFrontmatter ( content )
expect ( fm ) . toBe ( '---\ntitle: Hello\n---\n' )
expect ( body ) . toBe ( '\n# Hello\n' )
} )
it ( 'returns empty frontmatter when none present' , ( ) = > {
const content = '# No Frontmatter'
const [ fm , body ] = splitFrontmatter ( content )
expect ( fm ) . toBe ( '' )
expect ( body ) . toBe ( '# No Frontmatter' )
} )
it ( 'returns empty frontmatter when closing --- is missing' , ( ) = > {
const content = '---\ntitle: Hello\nNo closing'
const [ fm , body ] = splitFrontmatter ( content )
expect ( fm ) . toBe ( '' )
expect ( body ) . toBe ( content )
} )
it ( 'handles frontmatter followed by immediate content' , ( ) = > {
const content = '---\ntitle: Hello\n---\nContent'
const [ fm , body ] = splitFrontmatter ( content )
expect ( fm ) . toBe ( '---\ntitle: Hello\n---\n' )
expect ( body ) . toBe ( 'Content' )
} )
2026-02-24 12:19:21 +01:00
it ( 'ignores dashes inside frontmatter values' , ( ) = > {
const content = '---\ntitle: "A --- B"\ntype: Note\n---\n\nBody text'
const [ fm , body ] = splitFrontmatter ( content )
expect ( fm ) . toBe ( '---\ntitle: "A --- B"\ntype: Note\n---\n' )
expect ( body ) . toBe ( '\nBody text' )
} )
2026-02-22 12:02:29 +01:00
} )
describe ( 'countWords' , ( ) = > {
it ( 'counts words in body text, stripping frontmatter' , ( ) = > {
const content = '---\ntitle: Hello\n---\n\nThis is a test note with seven words.'
expect ( countWords ( content ) ) . toBe ( 8 )
} )
it ( 'strips markdown formatting characters' , ( ) = > {
const content = '---\ntitle: Test\n---\n\n# Heading\n\n**bold** and *italic*'
const count = countWords ( content )
expect ( count ) . toBeGreaterThan ( 0 )
} )
it ( 'returns 0 for empty body' , ( ) = > {
const content = '---\ntitle: Hello\n---\n'
expect ( countWords ( content ) ) . toBe ( 0 )
} )
it ( 'returns 0 for empty string' , ( ) = > {
expect ( countWords ( '' ) ) . toBe ( 0 )
} )
it ( 'returns 0 for content that is only frontmatter' , ( ) = > {
const content = '---\ntitle: Hello\nstatus: Active\n---\n'
expect ( countWords ( content ) ) . toBe ( 0 )
} )
it ( 'handles content without frontmatter' , ( ) = > {
const content = 'Hello world this is four words plus three'
expect ( countWords ( content ) ) . toBe ( 8 )
} )
2026-02-24 12:19:21 +01:00
it ( 'excludes long frontmatter with many keys from count' , ( ) = > {
const content = [
'---' ,
'type: Note' ,
'workspace: personal' ,
'notion_id: 63aeb735-e6f4-4a32-b7b6-d34276a26dee' ,
'status: Active' ,
'owner: Luca Rossi' ,
'tags: [Tauri, React, TypeScript]' ,
'belongs_to:' ,
' - "[[quarter/q1-2026]]"' ,
'related_to:' ,
' - "[[topic/software-development]]"' ,
'---' ,
'' ,
'# My Note' ,
'' ,
'Only these five words count.' ,
] . join ( '\n' )
2026-02-24 23:40:08 +01:00
// Title "# My Note" is excluded from word count
// Body: "Only these five words count." = 5 words
expect ( countWords ( content ) ) . toBe ( 5 )
2026-02-24 12:19:21 +01:00
} )
it ( 'ignores frontmatter values containing dashes' , ( ) = > {
const content = [
'---' ,
'title: "Something --- More"' ,
'type: Note' ,
'---' ,
'' ,
'Body words here.' ,
] . join ( '\n' )
expect ( countWords ( content ) ) . toBe ( 3 )
} )
it ( 'handles frontmatter with horizontal rule in body' , ( ) = > {
const content = [
'---' ,
'type: Note' ,
'---' ,
'' ,
'# Title' ,
'' ,
'Before the rule.' ,
'' ,
'---' ,
'' ,
'After the rule.' ,
] . join ( '\n' )
2026-02-24 23:40:08 +01:00
// Title "# Title" is excluded; body: Before, the, rule., After, the, rule. = 6
expect ( countWords ( content ) ) . toBe ( 6 )
2026-02-24 12:19:21 +01:00
} )
it ( 'returns 0 when content is only frontmatter with no trailing body' , ( ) = > {
const content = '---\ntitle: Hello\nstatus: Active\ntags: [a, b, c]\n---'
expect ( countWords ( content ) ) . toBe ( 0 )
} )
2026-02-24 23:40:08 +01:00
it ( 'excludes title heading from word count' , ( ) = > {
const content = '---\ntitle: Hello World\n---\n\n# Hello World\n\nThree body words.'
expect ( countWords ( content ) ) . toBe ( 3 )
} )
it ( 'counts correctly when no title heading is present' , ( ) = > {
const content = '---\ntitle: Test\n---\n\nFour words in body.'
expect ( countWords ( content ) ) . toBe ( 4 )
} )
it ( 'excludes wikilinks from word count' , ( ) = > {
const content = '---\ntitle: Test\n---\n\n# Test\n\nSee [[My Note]] for details.'
// Title excluded, wikilink excluded: See, for, details. = 3
expect ( countWords ( content ) ) . toBe ( 3 )
} )
it ( 'excludes multiple wikilinks from word count' , ( ) = > {
const content = 'Check [[note-a]] and [[note-b]] here.'
// wikilinks excluded: Check, and, here. = 3
expect ( countWords ( content ) ) . toBe ( 3 )
} )
it ( 'returns 0 for note with only title and no body' , ( ) = > {
const content = '---\ntitle: Empty\n---\n\n# Empty\n'
expect ( countWords ( content ) ) . toBe ( 0 )
} )
it ( 'does not strip ## or ### subheadings as title' , ( ) = > {
const content = '---\ntitle: Test\n---\n\n## Subheading\n\nBody text here.'
// ## is not a title heading; "Subheading" counts: Subheading, Body, text, here. = 4
expect ( countWords ( content ) ) . toBe ( 4 )
} )
2026-02-22 12:02:29 +01:00
} )
2026-02-23 14:48:21 +01:00
describe ( 'restoreWikilinksInBlocks' , ( ) = > {
it ( 'converts wikilink nodes back to [[target]] text' , ( ) = > {
const blocks = [ {
content : [
{ type : 'text' , text : 'See ' } ,
{ type : 'wikilink' , props : { target : 'My Note' } , content : undefined } ,
{ type : 'text' , text : ' for details' } ,
] ,
} ]
const result = restoreWikilinksInBlocks ( blocks ) as TestBlock [ ]
expect ( result [ 0 ] . content ) . toHaveLength ( 3 )
expect ( result [ 0 ] . content ! [ 0 ] ) . toEqual ( { type : 'text' , text : 'See ' } )
expect ( result [ 0 ] . content ! [ 1 ] ) . toEqual ( { type : 'text' , text : '[[My Note]]' } )
expect ( result [ 0 ] . content ! [ 2 ] ) . toEqual ( { type : 'text' , text : ' for details' } )
} )
it ( 'handles multiple wikilinks in one block' , ( ) = > {
const blocks = [ {
content : [
{ type : 'wikilink' , props : { target : 'A' } , content : undefined } ,
{ type : 'text' , text : ' and ' } ,
{ type : 'wikilink' , props : { target : 'B' } , content : undefined } ,
] ,
} ]
const result = restoreWikilinksInBlocks ( blocks ) as TestBlock [ ]
expect ( result [ 0 ] . content ! [ 0 ] ) . toEqual ( { type : 'text' , text : '[[A]]' } )
expect ( result [ 0 ] . content ! [ 1 ] ) . toEqual ( { type : 'text' , text : ' and ' } )
expect ( result [ 0 ] . content ! [ 2 ] ) . toEqual ( { type : 'text' , text : '[[B]]' } )
} )
it ( 'recursively processes children blocks' , ( ) = > {
const blocks = [ {
content : [ ] ,
children : [ {
content : [
{ type : 'wikilink' , props : { target : 'Nested' } , content : undefined } ,
] ,
} ] ,
} ]
const result = restoreWikilinksInBlocks ( blocks ) as TestBlock [ ]
expect ( result [ 0 ] . children ! [ 0 ] . content ! [ 0 ] ) . toEqual ( { type : 'text' , text : '[[Nested]]' } )
} )
it ( 'passes through non-wikilink content unchanged' , ( ) = > {
const blocks = [ {
content : [
{ type : 'text' , text : 'plain text' } ,
{ type : 'link' , text : 'a link' , href : 'http://example.com' } ,
] ,
} ]
const result = restoreWikilinksInBlocks ( blocks ) as TestBlock [ ]
expect ( result [ 0 ] . content ! [ 0 ] ) . toEqual ( { type : 'text' , text : 'plain text' } )
expect ( result [ 0 ] . content ! [ 1 ] ) . toEqual ( { type : 'link' , text : 'a link' , href : 'http://example.com' } )
} )
it ( 'handles blocks without content' , ( ) = > {
const blocks = [ { type : 'heading' , props : { level : 1 } } ]
const result = restoreWikilinksInBlocks ( blocks as unknown [ ] ) as TestBlock [ ]
expect ( result [ 0 ] . type ) . toBe ( 'heading' )
} )
it ( 'is the inverse of injectWikilinks for simple cases' , ( ) = > {
const WL_START = '\u2039WIKILINK:'
const WL_END = '\u203A'
// Start with placeholder text
const blocks = [ {
content : [
{ type : 'text' , text : ` before ${ WL_START } Target ${ WL_END } after ` } ,
] ,
} ]
// inject → restore should produce [[Target]] text
const injected = injectWikilinks ( blocks ) as TestBlock [ ]
const restored = restoreWikilinksInBlocks ( injected ) as TestBlock [ ]
// Find the text that was the wikilink
const texts = restored [ 0 ] . content ! . map ( n = > n . text ) . join ( '' )
expect ( texts ) . toContain ( '[[Target]]' )
} )
} )
2026-02-25 15:04:49 +01:00
describe ( 'extractOutgoingLinks' , ( ) = > {
it ( 'extracts simple wikilink targets' , ( ) = > {
const content = 'See [[My Note]] for details.'
expect ( extractOutgoingLinks ( content ) ) . toEqual ( [ 'My Note' ] )
} )
it ( 'extracts alias wikilinks (target only)' , ( ) = > {
const content = 'Link to [[project/my-project|My Project]] here.'
expect ( extractOutgoingLinks ( content ) ) . toEqual ( [ 'project/my-project' ] )
} )
it ( 'extracts multiple wikilinks sorted and deduplicated' , ( ) = > {
const content = 'See [[B]] and [[A]] and [[B]] again.'
expect ( extractOutgoingLinks ( content ) ) . toEqual ( [ 'A' , 'B' ] )
} )
it ( 'returns empty array for content with no wikilinks' , ( ) = > {
expect ( extractOutgoingLinks ( 'No links here' ) ) . toEqual ( [ ] )
} )
it ( 'returns empty array for empty string' , ( ) = > {
expect ( extractOutgoingLinks ( '' ) ) . toEqual ( [ ] )
} )
it ( 'extracts wikilinks from frontmatter values' , ( ) = > {
const content = '---\nbelongs_to:\n - "[[quarter/q1-2026]]"\n---\n\n# Title\n'
expect ( extractOutgoingLinks ( content ) ) . toEqual ( [ 'quarter/q1-2026' ] )
} )
it ( 'handles wikilinks in various positions' , ( ) = > {
const content = '[[First]] middle [[Second]] end [[Third]]'
expect ( extractOutgoingLinks ( content ) ) . toEqual ( [ 'First' , 'Second' , 'Third' ] )
} )
it ( 'ignores empty wikilinks' , ( ) = > {
const content = 'Text [[]] and [[Valid]]'
expect ( extractOutgoingLinks ( content ) ) . toEqual ( [ 'Valid' ] )
} )
} )
2026-03-02 02:01:24 +01:00
describe ( 'extractBacklinkContext' , ( ) = > {
const targets = new Set ( [ 'My Note' ] )
it ( 'extracts the paragraph containing a matching wikilink' , ( ) = > {
const content = '---\ntitle: Test\n---\n\n# Test\n\nFirst paragraph.\n\nThis references [[My Note]] in context.\n\nThird paragraph.'
const result = extractBacklinkContext ( content , targets )
expect ( result ) . toBe ( 'This references [[My Note]] in context.' )
} )
it ( 'returns null when no matching wikilink found' , ( ) = > {
const content = '---\ntitle: Test\n---\n\n# Test\n\nNo links here.'
expect ( extractBacklinkContext ( content , targets ) ) . toBeNull ( )
} )
it ( 'returns null for empty content' , ( ) = > {
expect ( extractBacklinkContext ( '' , targets ) ) . toBeNull ( )
} )
it ( 'truncates long paragraphs with ellipsis' , ( ) = > {
const longPara = 'A' . repeat ( 100 ) + ' [[My Note]] ' + 'B' . repeat ( 100 )
const content = ` --- \ ntitle: X \ n--- \ n \ n# X \ n \ n ${ longPara } `
const result = extractBacklinkContext ( content , targets , 50 )
expect ( result ) . not . toBeNull ( )
expect ( result ! . length ) . toBe ( 50 )
expect ( result ! . endsWith ( '\u2026' ) ) . toBe ( true )
} )
it ( 'matches path-based wikilinks via last segment' , ( ) = > {
const content = '---\ntitle: Test\n---\n\n# Test\n\nSee [[project/My Note]] for details.'
const result = extractBacklinkContext ( content , targets )
expect ( result ) . toBe ( 'See [[project/My Note]] for details.' )
} )
it ( 'matches aliased wikilinks [[target|display]]' , ( ) = > {
const content = '---\ntitle: Test\n---\n\n# Test\n\nCheck [[My Note|the note]] here.'
const result = extractBacklinkContext ( content , targets )
expect ( result ) . toBe ( 'Check [[My Note|the note]] here.' )
} )
it ( 'skips frontmatter and title heading' , ( ) = > {
const content = '---\ntitle: My Note\n---\n\n# My Note\n\nBody text with [[My Note]] link.'
const result = extractBacklinkContext ( content , targets )
expect ( result ) . toBe ( 'Body text with [[My Note]] link.' )
} )
it ( 'collapses internal whitespace' , ( ) = > {
const content = '---\ntitle: X\n---\n\n# X\n\nMultiple spaces\nand newline with [[My Note]] link.'
const result = extractBacklinkContext ( content , targets )
expect ( result ) . toBe ( 'Multiple spaces and newline with [[My Note]] link.' )
} )
it ( 'returns first matching paragraph when multiple match' , ( ) = > {
const content = '---\ntitle: X\n---\n\n# X\n\nFirst [[My Note]] mention.\n\nSecond [[My Note]] mention.'
const result = extractBacklinkContext ( content , targets )
expect ( result ) . toBe ( 'First [[My Note]] mention.' )
} )
it ( 'does not return paragraph when maxLength is respected' , ( ) = > {
const content = '---\ntitle: X\n---\n\n# X\n\nShort [[My Note]].'
const result = extractBacklinkContext ( content , targets , 200 )
expect ( result ) . toBe ( 'Short [[My Note]].' )
} )
} )
2026-03-11 22:38:25 +01:00
describe ( 'extractSnippet' , ( ) = > {
it ( 'extracts first paragraph after frontmatter and title' , ( ) = > {
const content = '---\ntype: Note\n---\n\n# My Note\n\nThis is the first paragraph of content.\n\n## Section Two\n\nMore content here.'
const snippet = extractSnippet ( content )
expect ( snippet ) . toContain ( 'This is the first paragraph' )
expect ( snippet ) . toContain ( 'More content here' )
} )
it ( 'strips markdown formatting (bold, italic, code)' , ( ) = > {
const content = '# Title\n\nSome **bold** and *italic* and `code` text.'
expect ( extractSnippet ( content ) ) . toBe ( 'Some bold and italic and code text.' )
} )
it ( 'strips markdown links, keeps display text' , ( ) = > {
const content = '# Title\n\nSee [this link](https://example.com) and [[wiki link]].'
const snippet = extractSnippet ( content )
expect ( snippet ) . toContain ( 'this link' )
expect ( snippet ) . not . toContain ( 'https://example.com' )
expect ( snippet ) . toContain ( 'wiki link' )
expect ( snippet ) . not . toContain ( '[[' )
} )
it ( 'uses display text from aliased wikilinks' , ( ) = > {
const content = '# Title\n\nDiscussed in [[meetings/standup|standup]] today.'
expect ( extractSnippet ( content ) ) . toBe ( 'Discussed in standup today.' )
} )
it ( 'truncates long content to ~160 chars with ellipsis' , ( ) = > {
const content = ` # Title \ n \ n ${ 'word ' . repeat ( 100 ) } `
const snippet = extractSnippet ( content )
expect ( snippet . length ) . toBeLessThanOrEqual ( 165 )
expect ( snippet ) . toMatch ( /\.\.\.$/ )
} )
it ( 'returns empty string for note with only title' , ( ) = > {
const content = '---\ntype: Note\n---\n\n# Just a Title\n'
expect ( extractSnippet ( content ) ) . toBe ( '' )
} )
it ( 'skips code fence delimiters' , ( ) = > {
const content = '# Title\n\n```rust\nfn main() {}\n```\n\nReal content here.'
const snippet = extractSnippet ( content )
expect ( snippet ) . not . toContain ( '```' )
expect ( snippet ) . toContain ( 'Real content here' )
} )
2026-03-16 04:33:35 +01:00
it ( 'falls back to sub-heading text when no paragraph content' , ( ) = > {
2026-03-11 22:38:25 +01:00
const content = '# Title\n\n## Section One\n\n### Sub Section\n'
2026-03-16 04:33:35 +01:00
expect ( extractSnippet ( content ) ) . toBe ( 'Section One Sub Section' )
} )
it ( 'falls back to sub-headings for headings-and-rules-only notes' , ( ) = > {
const content = '---\ntype: Project\n---\n# My Project\n\n## Description\n\n---\n\n## Key Results\n\n---\n'
expect ( extractSnippet ( content ) ) . toBe ( 'Description Key Results' )
} )
it ( 'prefers paragraph content over sub-heading fallback' , ( ) = > {
const content = '# Title\n\n## Section One\n\nActual paragraph content.\n\n## Section Two\n'
expect ( extractSnippet ( content ) ) . toMatch ( /^Actual paragraph content/ )
2026-03-11 22:38:25 +01:00
} )
it ( 'handles content without frontmatter or title' , ( ) = > {
const content = 'Just plain text content without any heading.'
expect ( extractSnippet ( content ) ) . toBe ( 'Just plain text content without any heading.' )
} )
it ( 'skips horizontal rules' , ( ) = > {
const content = '# Title\n\n---\n\nContent after rule.'
expect ( extractSnippet ( content ) ) . toBe ( 'Content after rule.' )
} )
it ( 'handles strikethrough' , ( ) = > {
const content = '# Title\n\n~~deleted~~ text remains.'
expect ( extractSnippet ( content ) ) . toBe ( 'deleted text remains.' )
} )
it ( 'extracts snippet from project-template note with body text' , ( ) = > {
const content = [
'---' , 'type: Project' , 'status: Active' , '---' , '' ,
'# Ship MVP of Tolaria' , '' ,
'## Objective' , '' ,
'Ship the minimum viable product for Tolaria marketplace.' , '' ,
'## Key Results' , '' ,
'- 100 beta users signed up' ,
] . join ( '\n' )
const snippet = extractSnippet ( content )
expect ( snippet ) . toContain ( 'Ship the minimum viable product' )
} )
2026-03-16 02:59:43 +01:00
it ( 'strips list markers from bullet items' , ( ) = > {
const content = '# Title\n\n* First bullet\n* Second bullet\n- Dash item'
2026-03-11 22:38:25 +01:00
const snippet = extractSnippet ( content )
2026-03-16 02:59:43 +01:00
expect ( snippet ) . toBe ( 'First bullet Second bullet Dash item' )
} )
it ( 'strips ordered list markers' , ( ) = > {
const content = '# Title\n\n1. First step\n2. Second step\n3. Third step'
const snippet = extractSnippet ( content )
expect ( snippet ) . toBe ( 'First step Second step Third step' )
} )
it ( 'handles mixed headings and bullet lists (real-world format)' , ( ) = > {
const content = '---\ntype: Project\nstatus: Active\n---\n# Migrate newsletter\n\n### 1) Goal one\n\n* Migration is successful\n\n### 2) Goal two\n\n* No regressions on open rate'
const snippet = extractSnippet ( content )
expect ( snippet ) . toMatch ( /^Migration is successful/ )
expect ( snippet ) . toContain ( 'No regressions on open rate' )
} )
it ( 'trims leading/trailing whitespace from snippet' , ( ) = > {
const content = '# Title\n\n Some text with spaces \n'
const snippet = extractSnippet ( content )
expect ( snippet ) . toBe ( 'Some text with spaces' )
2026-03-11 22:38:25 +01:00
} )
it ( 'includes code content lines (not fences) in snippet' , ( ) = > {
const content = '# Title\n\n```\nfn main() {}\n```\n\nSome text.'
const snippet = extractSnippet ( content )
expect ( snippet ) . toContain ( 'fn main()' )
expect ( snippet ) . toContain ( 'Some text.' )
} )
} )