Problem
MarkdownExtension.transformInline can transform InlineNode[], but the InlineNode union has no custom component node. The existing ComponentNode is block-only because its children are BlockNode[].
This leaves a gap for inline application UI such as mentions, channels, custom emoji, and embedded assets:
- an extension can detect and transform the syntax;
- the HTML renderer has the extension-level
renderHtml hook;
- framework renderers use a closed switch over the built-in inline node types;
- the React
components map can replace emitted tags, but an extension cannot emit a typed custom inline tag.
Consumers must therefore misuse a built-in node such as ImageNode or LinkNode, encode data in sentinel properties, and recover it through the component map. The other option is to replace the framework renderer. The first approach gives non-image or non-link content incorrect semantics; the second loses the benefit of the provided renderer.
Suggested API direction
One option is an inline equivalent of ComponentNode, for example:
interface InlineComponentNode {
type: 'inlineComponent'
name: string
attributes: Record<string, string>
children: InlineNode[]
tagName?: string
properties?: Record<string, string>
}
It could be added to InlineNode and rendered through the existing framework components map, in the same way that block ComponentNode is handled.
Another option is a framework renderer extension hook that can return custom output for an inline node before the built-in renderer handles it.
Example use case
const mentionExtension: MarkdownExtension = {
name: 'mentions',
transformInline(nodes) {
return transformMentions(nodes, mention => ({
type: 'inlineComponent',
name: 'mention',
tagName: 'mention',
attributes: { id: mention.id },
children: [{ type: 'text', value: mention.label }],
}))
},
}
<Markdown
extensions={[mentionExtension]}
components={{ mention: Mention }}
>
{source}
</Markdown>
The important part is a typed way for transformInline to produce portable custom inline output that React and other framework renderers can render without raw HTML or built-in-node semantic workarounds.
Problem
MarkdownExtension.transformInlinecan transformInlineNode[], but theInlineNodeunion has no custom component node. The existingComponentNodeis block-only because its children areBlockNode[].This leaves a gap for inline application UI such as mentions, channels, custom emoji, and embedded assets:
renderHtmlhook;componentsmap can replace emitted tags, but an extension cannot emit a typed custom inline tag.Consumers must therefore misuse a built-in node such as
ImageNodeorLinkNode, encode data in sentinel properties, and recover it through the component map. The other option is to replace the framework renderer. The first approach gives non-image or non-link content incorrect semantics; the second loses the benefit of the provided renderer.Suggested API direction
One option is an inline equivalent of
ComponentNode, for example:It could be added to
InlineNodeand rendered through the existing frameworkcomponentsmap, in the same way that blockComponentNodeis handled.Another option is a framework renderer extension hook that can return custom output for an inline node before the built-in renderer handles it.
Example use case
The important part is a typed way for
transformInlineto produce portable custom inline output that React and other framework renderers can render without raw HTML or built-in-node semantic workarounds.