Skip to content

Commit

Permalink
fix(ContentRendererMarkdown): recreate vNodes in render function
Browse files Browse the repository at this point in the history
  • Loading branch information
farnabaz committed Dec 7, 2022
1 parent 9258e5c commit 67a966e
Showing 1 changed file with 23 additions and 39 deletions.
62 changes: 23 additions & 39 deletions src/runtime/components/ContentRendererMarkdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { useRuntimeConfig, useRoute } from '#app'
import type { MarkdownNode, ParsedContentMeta } from '../types'
type CreateElement = typeof h
type ContentVNode = VNode | string
/**
* Default slot name
Expand Down Expand Up @@ -96,27 +95,19 @@ export default defineComponent({
// Resolve component if it's a Vue component
component = resolveVueComponent(component as string)
// Process children
const children = (body.children || []).map(child => renderNode(child, h, meta))
// Return Vue component
return h(
component as any,
{
...meta.component?.props,
...this.$attrs
},
{
default: createSlotFunction(children)
}
component as any,
{ ...meta.component?.props, ...this.$attrs },
renderSlots(body, h, meta, meta)
)
}
})
/**
* Render a markdown node
*/
function renderNode (node: MarkdownNode, h: CreateElement, documentMeta: ParsedContentMeta, parentScope: any = {}): ContentVNode {
function renderNode (node: MarkdownNode, h: CreateElement, documentMeta: ParsedContentMeta, parentScope: any = {}): VNode {
/**
* Render Text node
*/
Expand All @@ -138,14 +129,15 @@ function renderNode (node: MarkdownNode, h: CreateElement, documentMeta: ParsedC
}
const props = propsToData(node, documentMeta)
return h(
component as any,
props,
renderSlots(node, h, documentMeta, { ...parentScope, ...props })
)
}
function renderBinding (node: MarkdownNode, h: CreateElement, documentMeta: ParsedContentMeta, parentScope: any = {}): ContentVNode {
function renderBinding (node: MarkdownNode, h: CreateElement, documentMeta: ParsedContentMeta, parentScope: any = {}): VNode {
const data = {
...parentScope,
$route: () => useRoute(),
Expand All @@ -171,31 +163,37 @@ function renderBinding (node: MarkdownNode, h: CreateElement, documentMeta: Pars
/**
* Create slots from `node` template children.
*/
function renderSlots (node: MarkdownNode, h: CreateElement, documentMeta: ParsedContentMeta, parentProps: any): ContentVNode[] {
function renderSlots (node: MarkdownNode, h: CreateElement, documentMeta: ParsedContentMeta, parentProps: any): Record<string, () => VNode[]> {
const children: MarkdownNode[] = node.children || []
const slots: Record<string, Array<VNode | string>> = children.reduce((data, node) => {
const slotNodes: Record<string, MarkdownNode[]> = children.reduce((data, node) => {
if (!isTemplate(node)) {
data[DEFAULT_SLOT].push(renderNode(node, h, documentMeta, parentProps))
return data
}
if (isDefaultTemplate(node)) {
data[DEFAULT_SLOT].push(...(node.children || []).map(child => renderNode(child, h, documentMeta, parentProps)))
data[DEFAULT_SLOT].push(node)
return data
}
const slotName = getSlotName(node)
data[slotName] = (node.children || []).map(child => renderNode(child, h, documentMeta, parentProps))
data[slotName] = data[slotName] || []
// Append children to slot
data[slotName].push(...(node.children || []))
return data
}, {
[DEFAULT_SLOT]: [] as any[]
})
const slotEntries = Object.entries(slots).map(([name, vDom]) => ([name, createSlotFunction(vDom)]))
const slots = Object.entries(slotNodes).reduce((slots, [name, children]) => {
if (!children.length) { return slots }
slots[name] = () => {
const vNodes = children.map(child => renderNode(child, h, documentMeta, parentProps))
return mergeTextNodes(vNodes)
}
return slots
}, {} as Record<string, () => VNode[]>)
return Object.fromEntries(slotEntries)
return slots
}
/**
Expand Down Expand Up @@ -344,20 +342,6 @@ function getSlotName (node: MarkdownNode) {
return name || DEFAULT_SLOT
}
/**
* Create a factory function if there is a node in the list
*/
function createSlotFunction (nodes: Array<VNode | string>) {
return (nodes.length ? () => mergeTextNodes(nodes as VNode[]) : undefined)
}
/**
* Check if node is root
*/
function isDefaultTemplate (node: MarkdownNode) {
return isTemplate(node) && getSlotName(node) === DEFAULT_SLOT
}
/**
* Check if node is Vue template tag
*/
Expand Down

0 comments on commit 67a966e

Please sign in to comment.