78 lines
2 KiB
TypeScript
78 lines
2 KiB
TypeScript
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'
|
|
}
|