import type { BlockLike } from './durableMarkdownBlocks' export const TOLARIA_CALLOUT_BLOCK_TYPE = 'tolariaCallout' export const TOLARIA_CALLOUT_KINDS = [ 'info', 'success', 'warning', 'danger', 'annotation', 'relationship', 'path', ] as const export type TolariaCalloutKind = typeof TOLARIA_CALLOUT_KINDS[number] const CALLOUT_MARKER_RE = /^\[!(info|success|warning|danger|annotation|relationship|path)\]\s*(.*)$/iu function isCalloutKind(value: unknown): value is TolariaCalloutKind { return typeof value === 'string' && TOLARIA_CALLOUT_KINDS.includes(value as TolariaCalloutKind) } function readTextOnlyContent(content: BlockLike['content']): string | null { if (!Array.isArray(content) || content.length === 0) return null let text = '' for (const item of content) { if (item.type !== 'text' || typeof item.text !== 'string') return null text += item.text } return text } function calloutMatchFromQuote(block: BlockLike) { if (block.type !== 'quote') return null const text = readTextOnlyContent(block.content) if (text === null) return null const match = CALLOUT_MARKER_RE.exec(text) if (!match) return null const kind = match[1]?.toLowerCase() if (!isCalloutKind(kind)) return null return { kind, text: match[2] ?? '', } } export function injectTolariaCalloutBlocks(blocks: unknown[]): unknown[] { return (blocks as BlockLike[]).map((block) => { const match = calloutMatchFromQuote(block) const children = Array.isArray(block.children) ? injectTolariaCalloutBlocks(block.children) as BlockLike[] : block.children if (!match) return { ...block, children } return { ...block, type: TOLARIA_CALLOUT_BLOCK_TYPE, props: { ...(block.props ?? {}), kind: match.kind, }, content: match.text ? [{ type: 'text', text: match.text, styles: {} }] : [], children, } }) } export function calloutKind(value: unknown): TolariaCalloutKind { return isCalloutKind(value) ? value : 'info' }