Files
Momento/memento-note/lib/note-preview.ts

63 lines
1.9 KiB
TypeScript

import type { Note } from '@/lib/types'
const MD_IMG = /!\[[^\]]*\]\(([^)\s]+)\)/g
const HTML_IMG = /<img[^>]+src=["']([^"']+)["'][^>]*>/gi
/**
* Plain-text preview for list view (light markdown stripping).
*/
export function stripMarkdownPreview(raw: string, maxLen = 180): string {
if (!raw?.trim()) return ''
let t = raw
.replace(/^#{1,6}\s+/gm, '')
.replace(/```[\s\S]*?```/g, ' ')
.replace(/\*\*([^*]+)\*\*/g, '$1')
.replace(/\*([^*]+)\*/g, '$1')
.replace(/`([^`]+)`/g, '$1')
.replace(/\[(.+?)]\([^)]+\)/g, '$1')
.replace(/^\s*[-*+]\s+/gm, '')
.replace(/^\s*\d+\.\s+/gm, '')
.replace(/\n+/g, ' ')
.replace(/\s+/g, ' ')
.trim()
if (t.length > maxLen) {
return `${t.slice(0, maxLen).trim()}`
}
return t
}
export function getNoteDisplayTitle(note: { title: string | null; content: string; type: string }, untitled: string): string {
const title = note.title?.trim()
if (title) return title
if (note.type === 'checklist') {
const line = note.content?.split('\n').find((l) => l.trim())
if (line) return stripMarkdownPreview(line, 80) || untitled
}
const preview = stripMarkdownPreview(note.content || '', 100)
return preview || untitled
}
export function getNoteFeedImage(note: Note): string | null {
const first = note.images?.[0]?.trim()
if (first) return first
const content = note.content || ''
MD_IMG.lastIndex = 0
const md = MD_IMG.exec(content)
if (md?.[1]) return md[1]
HTML_IMG.lastIndex = 0
const html = HTML_IMG.exec(content)
if (html?.[1]) return html[1]
return null
}
/** Plain excerpt for collection cards (HTML + markdown noise stripped). */
export function getNotePlainExcerpt(note: Note, maxLen = 240): string {
let raw = note.content || ''
raw = raw.replace(/!\[[^\]]*\]\([^)]+\)/g, ' ')
raw = raw.replace(/<[^>]+>/g, ' ')
return stripMarkdownPreview(raw, maxLen)
}