Given this Obsidian Callout custom entry:
export type ObsidianCalloutEntry = {
callout: {
type: string;
title?: InlineTypes[] | InlineTypes;
content: MarkdownEntry | MarkdownEntry[];
initialState?: 'expanded' | 'collapsed';
};
};
export const calloutRenderer: MarkdownRenderer = (
entry: ObsidianCalloutEntry,
options: RenderOptions
) => {
let titleContent = getTitleContent(entry);
let content = Array.isArray(entry.callout.content)
? entry.callout.content
: [entry.callout.content];
let initialState =
entry.callout.initialState === 'collapsed'
? '-'
: entry.callout.initialState === 'expanded'
? '+'
: '';
const blockquote: BlockquoteEntry = {
blockquote: [
{ p: [`[!${entry.callout.type}]${initialState}`, ...titleContent] },
...content,
],
};
return {
markdown: renderEntries([blockquote], { ...options),
blockLevel: true,
};
};
function getTitleContent(entry: ObsidianCalloutEntry): InlineTypes[] {
if (!entry.callout.title) {
return [];
}
const title = entry.callout.title;
let normalizedTitle = Array.isArray(title) ? title : [title];
return [' ', ...normalizedTitle];
}
The expected format of nested callouts is to append one additional layer of blockquote. So, a callout within a callout should look like this:
> [!info]+ Some Title Here
>
> > [!quote]+
> >
> > Here's a quote.
Instead, it looks like this:
> [!info]+ Some Title Here
>
> > > [!quote]+
> > >
> > > Here's a quote.
In general, this is because the callout implementation is calling renderEnties(), which is the established example in the docs.
The workaround is to update the callout renderer as follows:
return {
markdown: renderEntries([blockquote], { ...options, prefix: '' }),
blockLevel: true,
};
This works, but it feels awkward to do, and it's not obvious to an implementer of custom renderers which reuse existing renderers.
I'm not sure yet on a solution for this that will prevent headaches for custom entry authors, but I'm putting the issue here for now so it can be explored later.
Given this Obsidian Callout custom entry:
The expected format of nested callouts is to append one additional layer of blockquote. So, a callout within a callout should look like this:
Instead, it looks like this:
In general, this is because the callout implementation is calling
renderEnties(), which is the established example in the docs.The workaround is to update the callout renderer as follows:
This works, but it feels awkward to do, and it's not obvious to an implementer of custom renderers which reuse existing renderers.
I'm not sure yet on a solution for this that will prevent headaches for custom entry authors, but I'm putting the issue here for now so it can be explored later.