import React, { Fragment, type JSX } from 'react' import Link from 'next/link' import { IS_BOLD, IS_CODE, IS_ITALIC, IS_STRIKETHROUGH, IS_SUBSCRIPT, IS_SUPERSCRIPT, IS_UNDERLINE, } from './node-format' // Lexical 节点类型 interface LexicalNode { type: string format?: number text?: string tag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'ul' | 'ol' listType?: 'bullet' | 'number' | 'check' checked?: boolean value?: number children?: LexicalNode[] fields?: { linkType?: 'internal' | 'custom' url?: string newTab?: boolean doc?: { value?: { slug?: string } relationTo?: string } } language?: string version?: number } type Props = { nodes: LexicalNode[] } export function serializeLexical({ nodes }: Props): JSX.Element { return ( {nodes?.map((node, index): JSX.Element | null => { if (node == null) { return null } if (node.type === 'text') { let text = {node.text} const format = node.format || 0 if (format & IS_BOLD) { text = {text} } if (format & IS_ITALIC) { text = {text} } if (format & IS_STRIKETHROUGH) { text = ( {text} ) } if (format & IS_UNDERLINE) { text = ( {text} ) } if (format & IS_CODE) { text = {node.text} } if (format & IS_SUBSCRIPT) { text = {text} } if (format & IS_SUPERSCRIPT) { text = {text} } return text } // 处理子节点 const serializedChildrenFn = (node: LexicalNode): JSX.Element | null => { if (node.children == null) { return null } else { // 处理 checkbox list if (node?.type === 'list' && node?.listType === 'check') { for (const item of node.children) { if ('checked' in item) { if (!item?.checked) { item.checked = false } } } } return serializeLexical({ nodes: node.children }) } } const serializedChildren = 'children' in node ? serializedChildrenFn(node) : '' switch (node.type) { case 'linebreak': { return
} case 'paragraph': { return

{serializedChildren}

} case 'heading': { const Tag = node?.tag || 'h2' return {serializedChildren} } case 'list': { const Tag = node?.tag || 'ul' return {serializedChildren} } case 'listitem': { if (node?.checked != null) { return (
  • {serializedChildren}
  • ) } else { return (
  • {serializedChildren}
  • ) } } case 'quote': { return
    {serializedChildren}
    } case 'link': { const fields = node.fields if (fields?.linkType === 'internal' && fields?.doc?.value?.slug) { const href = fields.doc.relationTo === 'posts' ? `/posts/${fields.doc.value.slug}` : `/${fields.doc.value.slug}` return ( {serializedChildren} ) } return ( {serializedChildren} ) } case 'code': { // 代码块 return (
                    {serializedChildren}
                  
    ) } case 'horizontalrule': { return
    } default: // 如果有子节点,递归渲染 if (node.children) { return {serializedChildren} } return null } })}
    ) }