UNPKG

@lobehub/ui

Version:

Lobe UI is an open-source UI component library for building AIGC web apps

1 lines 7.48 kB
{"version":3,"file":"hastTableToMarkdown.mjs","names":[],"sources":["../../../../src/Markdown/components/MarkdownTable/hastTableToMarkdown.ts"],"sourcesContent":["type HastNode = {\n children?: HastNode[];\n properties?: Record<string, any>;\n tagName?: string;\n type: string;\n value?: string;\n};\n\nconst escapeCell = (text: string) => text.replaceAll('|', '\\\\|').replaceAll(/\\r?\\n/g, '<br>');\n\nconst matchAlign = (source: string): 'center' | 'left' | 'right' | null => {\n if (source.includes('center')) return 'center';\n if (source.includes('right')) return 'right';\n if (source.includes('left')) return 'left';\n return null;\n};\n\nconst readAlign = (node: HastNode | undefined): 'center' | 'left' | 'right' | null => {\n const style = node?.properties?.style;\n const align = node?.properties?.align;\n const styleStr = typeof style === 'string' ? style.toLowerCase() : '';\n const alignStr = typeof align === 'string' ? align.toLowerCase() : '';\n // Prefer the inline style hint (more specific) but fall back to the\n // explicit `align` attribute when style has no alignment keyword —\n // otherwise an unrelated style like `color: red` would suppress\n // `align=\"right\"`.\n return matchAlign(styleStr) ?? matchAlign(alignStr);\n};\n\n// CommonMark code-span rule: open and close with N backticks where N is\n// longer than any run of consecutive backticks inside the content. If the\n// content starts or ends with a backtick, pad with a single space on each\n// side (the parser strips one space when both sides are padded).\nconst encodeInlineCode = (text: string): string => {\n let longestRun = 0;\n const runs = text.match(/`+/g);\n if (runs) for (const run of runs) longestRun = Math.max(longestRun, run.length);\n const fence = '`'.repeat(longestRun + 1);\n const needsPad = text.startsWith('`') || text.endsWith('`');\n const body = needsPad ? ` ${text} ` : text;\n return `${fence}${body}${fence}`;\n};\n\nconst renderInline = (node: HastNode): string => {\n if (node.type === 'text') return node.value ?? '';\n if (node.type !== 'element') return '';\n\n const inner = (node.children ?? []).map((child) => renderInline(child)).join('');\n\n switch (node.tagName) {\n case 'br': {\n return '<br>';\n }\n case 'code': {\n return encodeInlineCode(inner);\n }\n case 'strong':\n case 'b': {\n return `**${inner}**`;\n }\n case 'em':\n case 'i': {\n return `*${inner}*`;\n }\n case 'del':\n case 's': {\n return `~~${inner}~~`;\n }\n case 'a': {\n const href = node.properties?.href;\n return href ? `[${inner}](${href})` : inner;\n }\n case 'img': {\n const src = node.properties?.src ?? '';\n const alt = node.properties?.alt ?? '';\n return `![${alt}](${src})`;\n }\n default: {\n return inner;\n }\n }\n};\n\nconst renderCell = (cell: HastNode): string => escapeCell(renderInline(cell)).trim();\n\nconst findChild = (node: HastNode | undefined, tag: string): HastNode | undefined =>\n node?.children?.find((child) => child.type === 'element' && child.tagName === tag);\n\nconst findAllChildren = (node: HastNode | undefined, tag: string): HastNode[] =>\n (node?.children ?? []).filter((child) => child.type === 'element' && child.tagName === tag);\n\nconst getRowCells = (row: HastNode): HastNode[] =>\n (row.children ?? []).filter(\n (child) => child.type === 'element' && (child.tagName === 'th' || child.tagName === 'td'),\n );\n\nconst alignToDivider = (align: 'center' | 'left' | 'right' | null): string => {\n switch (align) {\n case 'center': {\n return ':---:';\n }\n case 'left': {\n return ':---';\n }\n case 'right': {\n return '---:';\n }\n default: {\n return '---';\n }\n }\n};\n\nexport const hastTableToMarkdown = (node: HastNode | undefined): string => {\n if (!node) return '';\n\n const thead = findChild(node, 'thead');\n const tbody = findChild(node, 'tbody');\n\n const headerRow = findChild(thead, 'tr');\n const headerCells = headerRow ? getRowCells(headerRow) : [];\n\n const bodyRows = findAllChildren(tbody, 'tr');\n const columnCount = Math.max(\n headerCells.length,\n ...bodyRows.map((row) => getRowCells(row).length),\n );\n\n if (columnCount === 0) return '';\n\n const headerTexts = Array.from({ length: columnCount }, (_, i) =>\n headerCells[i] ? renderCell(headerCells[i]) : '',\n );\n\n const aligns = Array.from({ length: columnCount }, (_, i) => readAlign(headerCells[i]));\n\n const headerLine = `| ${headerTexts.join(' | ')} |`;\n const dividerLine = `| ${aligns.map((a) => alignToDivider(a)).join(' | ')} |`;\n const bodyLines = bodyRows.map((row) => {\n const cells = getRowCells(row);\n const texts = Array.from({ length: columnCount }, (_, i) =>\n cells[i] ? renderCell(cells[i]) : '',\n );\n return `| ${texts.join(' | ')} |`;\n });\n\n return [headerLine, dividerLine, ...bodyLines].join('\\n');\n};\n"],"mappings":"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"}