const PREVIEW_MARKDOWN_RE = /\[Preview:[^\]]+\]\((?#preview[:/][^)]+)\)/gi export function stripPreviewTargets(text: string): string { return text .replace(PREVIEW_MARKDOWN_RE, '') .replace(/[ \t]+\n/g, '\n') .replace(/\n{3,}/g, '\n\n') .trim() } export function extractPreviewTargets(text: string): string[] { const targets: string[] = [] const seen = new Set() for (const match of text.matchAll(PREVIEW_MARKDOWN_RE)) { const target = previewTargetFromMarkdownHref(match.groups?.href) if (target && !seen.has(target)) { seen.add(target) targets.push(target) } } return targets } export function previewMarkdownHref(target: string): string { return `#preview/${encodeURIComponent(target)}` } export function previewTargetFromMarkdownHref(href?: string): string | null { if (!href?.startsWith('#preview:') && !href?.startsWith('#preview/')) { return null } try { return decodeURIComponent(href.slice('#preview'.length + 1)) } catch { return null } } export function previewName(target: string): string { try { const url = new URL(target) if (url.protocol === 'file:') { return decodeURIComponent(url.pathname).split(/[\\/]/).filter(Boolean).pop() || target } const file = url.pathname.split('/').filter(Boolean).pop() return file || url.host } catch { return target.split(/[\\/]/).filter(Boolean).pop() || target } } export function previewDisplayLabel(target: string): string { const escaped = previewName(target).replace(/[[\]\\]/g, '\\$&') return `Preview: ${escaped}` }