tiptap-markdown-react 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ReportContent-B7okwVW0.js → ReportContent-Cb67MCs9.js} +291 -14
- package/dist/ReportContent-Cb67MCs9.js.map +1 -0
- package/dist/ReportContentWithCharts-B-K-EiAG.js +2164 -0
- package/dist/ReportContentWithCharts-B-K-EiAG.js.map +1 -0
- package/dist/components/ImageAlignTools.d.ts +2 -2
- package/dist/components/ImageCropStage.d.ts +18 -0
- package/dist/components/ImageLightbox.d.ts +12 -0
- package/dist/{extractToc-B50WvHao.js → extractToc-H9otRa3G.js} +10 -188
- package/dist/extractToc-H9otRa3G.js.map +1 -0
- package/dist/icons/index.d.ts +14 -0
- package/dist/imageCrop.d.ts +50 -0
- package/dist/imageCrop.dom.test.d.ts +1 -0
- package/dist/imageCropLayout.d.ts +38 -0
- package/dist/imageMarkdown.d.ts +49 -9
- package/dist/imagePreview.d.ts +49 -0
- package/dist/imagePreview.dom.test.d.ts +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +878 -563
- package/dist/index.js.map +1 -1
- package/dist/labels.d.ts +24 -0
- package/dist/reader.js +2 -2
- package/dist/resetImageSize.d.ts +2 -1
- package/dist/server.js +4 -4
- package/dist/style-inline.css +723 -404
- package/dist/style.css +723 -404
- package/package.json +1 -1
- package/dist/ReportContent-B7okwVW0.js.map +0 -1
- package/dist/ReportContentWithCharts-DHdD1BaH.js +0 -1322
- package/dist/ReportContentWithCharts-DHdD1BaH.js.map +0 -1
- package/dist/extractToc-B50WvHao.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tiptap-markdown-react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "A batteries-included, self-styled Markdown WYSIWYG editor and reader suite built on Tiptap v3. Markdown in/out, SSR/static rendering, table of contents, themeable via CSS variables.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ReportContent-B7okwVW0.js","sources":["../src/citationUtils.ts","../src/chart/columnMatching.ts","../src/chart/types.ts","../src/chart/parse.ts","../src/ReportContent.tsx"],"sourcesContent":["import type { JSONContent } from '@tiptap/core';\n\nexport interface SourceRef {\n /** 与 markdown `[^n]` 中的 n 对齐(字符串,如 `\"1\"`)。 */\n index: string;\n url?: string;\n title?: string;\n /** 原文片段等;库本身不渲染 Popover,留给消费方。 */\n excerpt?: string;\n}\n\nfunction escapeAttr(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/\"/g, '"')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n\n/**\n * 将 markdown 中能匹配到 `sources` 的 `[^n]` 换成带 data-* 的\n * `<span class=\"citation-ref\">`(**不是** `<sup>`,避免被 Superscript 吃掉、\n * 也避免视觉上标)。未匹配的 `[^n]` 原样保留,留给 CitationRef tokenizer。\n *\n * 浏览器端 @tiptap/markdown 可解析内联 HTML;server 端无 DOMParser 时请改用\n * {@link applyCitationSources}(先 parse 再补 attrs)。\n */\nexport function enrichMarkdownCitations(\n markdown: string,\n sources: SourceRef[],\n): string {\n if (!sources.length) return markdown;\n\n return markdown.replace(/\\[\\^(\\d+)\\]/g, (match, num: string) => {\n const source = sources.find((s) => s.index === num);\n if (!source) return match;\n\n const attrs = [`class=\"citation-ref\"`, `data-index=\"${num}\"`];\n if (source.url) attrs.push(`data-url=\"${escapeAttr(source.url)}\"`);\n if (source.title) attrs.push(`data-title=\"${escapeAttr(source.title)}\"`);\n\n if (source.url) {\n return `<span ${attrs.join(' ')}><a href=\"${escapeAttr(source.url)}\" title=\"${escapeAttr(source.title || '')}\" target=\"_blank\" rel=\"noopener\">${num}</a></span>`;\n }\n return `<span ${attrs.join(' ')}>${num}</span>`;\n });\n}\n\nfunction patchCitationNode(\n node: JSONContent,\n byIndex: Map<string, SourceRef>,\n): JSONContent {\n if (node.type === 'citationRef') {\n const index = String(node.attrs?.index ?? '');\n const source = byIndex.get(index);\n if (!source) return node;\n return {\n ...node,\n attrs: {\n ...node.attrs,\n index,\n url: source.url ?? node.attrs?.url ?? null,\n title: source.title ?? node.attrs?.title ?? null,\n },\n };\n }\n\n if (!node.content?.length) return node;\n return {\n ...node,\n content: node.content.map((child) => patchCitationNode(child, byIndex)),\n };\n}\n\n/**\n * 在已 parse 的 Tiptap JSON 上,按 `sources` 给 `citationRef` 节点补 url/title。\n * SSR / 无 DOMParser 环境的首选路径。\n */\nexport function applyCitationSources(\n doc: JSONContent,\n sources: SourceRef[],\n): JSONContent {\n if (!sources.length) return doc;\n const byIndex = new Map(sources.map((s) => [s.index, s]));\n return patchCitationNode(doc, byIndex);\n}\n\n/** 单条脚注定义行:行首 0–3 空格 + `[^数字]:`。 */\nconst FOOTNOTE_DEF_RE = /^ {0,3}\\[\\^(\\d+)\\]:[ \\t]?(.*)$/;\n\n/** 内联链接:`[文本](url)`。URL 支持 `<...>` 包裹(可含空格)或一层配对括号(维基百科式)。 */\nconst MD_LINK_RE =\n /\\[([^\\]]*)\\]\\(\\s*(?:<([^<>]*)>|((?:[^()\\s]|\\([^()]*\\))+)(?:[ \\t]+\"[^\"]*\")?)\\s*\\)/;\nconst MD_LINK_RE_G = new RegExp(MD_LINK_RE.source, 'g');\n\n/** 把定义内容压成纯文本(链接只留文本),供 excerpt 与 title 兜底。 */\nfunction flattenFootnoteContent(content: string): string {\n return content\n .replace(\n MD_LINK_RE_G,\n (_match, text: string, angleUrl: string, plainUrl: string) =>\n text || angleUrl || plainUrl || '',\n )\n .trim();\n}\n\nexport interface ExtractedFootnotes {\n /** 剥离定义行后的正文(首尾与多余空行已收敛)。 */\n markdown: string;\n /** 解析出的来源列表,同一 label 重复定义取首次。 */\n sources: SourceRef[];\n}\n\n/**\n * 把 markdown 中的 GFM 脚注定义行(`[^n]: …`)抽成 {@link SourceRef} 并从正文剥离。\n *\n * 与 {@link enrichMarkdownCitations} / {@link applyCitationSources} 同属脚注一族:\n * 它们消费 `sources` 处理 `[^n]` 标记这一半,本函数生产 `sources`、处理定义行\n * 另一半——不剥离,定义行会以普通段落渲染;不抽取,标记没有 url/title 可补。\n * 典型用法(纯字符串变换,流式每帧重算也便宜):\n *\n * ```ts\n * const { markdown: body, sources } = extractFootnoteSources(raw);\n * // <MarkdownPreview markdown={body} sources={sources} … />\n * ```\n *\n * 规则与边界:\n * - label 仅支持数字,与 enrich / CitationRef tokenizer 的 `\\[\\^(\\d+)\\]` 一致;\n * 非数字定义行不识别、原样留在正文;\n * - 围栏代码块(``` / ~~~,判定与 {@link stabilizeMarkdown} 一致)内的定义行跳过;\n * 缩进代码块不识别(已知限制);\n * - 续行:紧跟定义的缩进(≥4 空格或 Tab)非空行并入内容,空行结束定义;\n * - 内容中第一个内联链接取作 url、链接文本作 title;excerpt 取纯文本全文;\n * 无链接时 title 取纯文本首行;\n * - 流式半行(如 `[^1]: [原文](htt`)按 best-effort 解析,下一帧自愈。\n */\nexport function extractFootnoteSources(markdown: string): ExtractedFootnotes {\n if (!markdown || !markdown.includes('[^')) {\n return { markdown, sources: [] };\n }\n\n const lines = markdown.split('\\n');\n const bodyLines: string[] = [];\n const sources: SourceRef[] = [];\n const seen = new Set<string>();\n let removed = false;\n\n let inFence = false;\n let fenceChar = '`';\n let fenceLen = 3;\n\n for (let i = 0; i < lines.length; i += 1) {\n const line = lines[i];\n\n const fence = line.match(/^(`{3,}|~{3,})/);\n if (fence) {\n const char = fence[1][0];\n if (!inFence) {\n inFence = true;\n fenceChar = char;\n fenceLen = fence[1].length;\n } else if (\n char === fenceChar &&\n fence[1].length >= fenceLen &&\n /^[`~]+\\s*$/.test(line)\n ) {\n inFence = false;\n }\n bodyLines.push(line);\n continue;\n }\n if (inFence) {\n bodyLines.push(line);\n continue;\n }\n\n const def = FOOTNOTE_DEF_RE.exec(line);\n if (!def) {\n bodyLines.push(line);\n continue;\n }\n removed = true;\n\n const parts = [def[2]];\n let j = i + 1;\n while (\n j < lines.length &&\n lines[j].trim() &&\n /^(?: {4,}|\\t)/.test(lines[j])\n ) {\n parts.push(lines[j].trim());\n j += 1;\n }\n i = j - 1;\n\n const index = def[1];\n if (seen.has(index)) continue;\n seen.add(index);\n\n const content = parts.join('\\n');\n const link = MD_LINK_RE.exec(content);\n const source: SourceRef = { index };\n if (link) {\n const url = link[2] ?? link[3];\n if (url) source.url = url;\n const text = link[1]?.trim();\n if (text) source.title = text;\n }\n const plain = flattenFootnoteContent(content);\n if (plain) {\n source.excerpt = plain;\n if (!source.title) source.title = plain.split('\\n')[0];\n }\n sources.push(source);\n }\n\n if (!removed) {\n return { markdown, sources: [] };\n }\n\n return {\n markdown: bodyLines\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .replace(/^\\n+/, '')\n .replace(/\\s+$/, ''),\n sources,\n };\n}\n","/**\n * Loose header ↔ config field matching for chart data tables.\n * Zero runtime deps beyond string/regex.\n */\n\nconst TRAILING_UNIT_SUFFIX_PATTERN = /^(\\s*[((][^))]+[))])+\\s*$/;\n\n/** Exact match, or column = field + parenthetical unit suffix. */\nexport function columnKeyMatchesConfiguredField(\n columnKey: string,\n configuredField: string,\n): boolean {\n const ck = (columnKey || '').trim();\n const f = (configuredField || '').trim();\n if (!ck || !f) return false;\n if (ck === f) return true;\n if (!ck.startsWith(f)) return false;\n const rest = ck.slice(f.length);\n return rest === '' || TRAILING_UNIT_SUFFIX_PATTERN.test(rest);\n}\n\n/**\n * Resolve configured x/y name to a real column dataIndex.\n * Returns original field when no match (caller decides degrade).\n */\nexport function resolveChartAxisFieldToColumnKey(\n configuredField: string | undefined,\n columnKeys: string[],\n): string | undefined {\n if (configuredField === undefined || configuredField === null) {\n return configuredField;\n }\n const f = configuredField.trim();\n if (!f) return configuredField;\n const keySet = new Set(columnKeys);\n if (keySet.has(f)) return f;\n const hit = columnKeys.find((k) => columnKeyMatchesConfiguredField(k, f));\n return hit ?? configuredField;\n}\n\nexport function normalizeChartConfigAxisFields<\n T extends { x?: string; y?: string; groupBy?: string; filterBy?: string; colorLegend?: string; sortBy?: string },\n>(cfg: T, columnKeys: string[]): T {\n return {\n ...cfg,\n ...(cfg.x !== undefined\n ? { x: resolveChartAxisFieldToColumnKey(cfg.x, columnKeys) }\n : {}),\n ...(cfg.y !== undefined\n ? { y: resolveChartAxisFieldToColumnKey(cfg.y, columnKeys) }\n : {}),\n ...(cfg.groupBy !== undefined\n ? { groupBy: resolveChartAxisFieldToColumnKey(cfg.groupBy, columnKeys) }\n : {}),\n ...(cfg.filterBy !== undefined\n ? {\n filterBy: resolveChartAxisFieldToColumnKey(cfg.filterBy, columnKeys),\n }\n : {}),\n ...(cfg.colorLegend !== undefined\n ? {\n colorLegend: resolveChartAxisFieldToColumnKey(\n cfg.colorLegend,\n columnKeys,\n ),\n }\n : {}),\n ...(cfg.sortBy !== undefined\n ? { sortBy: resolveChartAxisFieldToColumnKey(cfg.sortBy, columnKeys) }\n : {}),\n };\n}\n","/** MVP chart types (subset). */\nexport const MVP_CHART_TYPES = [\n 'line',\n 'bar',\n 'column',\n 'pie',\n 'donut',\n 'area',\n] as const;\n\nexport type MvpChartType = (typeof MVP_CHART_TYPES)[number];\n\nexport function isMvpChartType(value: unknown): value is MvpChartType {\n return (\n typeof value === 'string' &&\n (MVP_CHART_TYPES as readonly string[]).includes(value)\n );\n}\n\n/**\n * Flat chart config (author / LLM form).\n * `subgraphBy` is accepted but ignored in v1.\n */\nexport interface ChartConfig {\n chartType: string;\n x?: string;\n y?: string;\n title?: string;\n height?: number;\n dataTime?: string;\n groupBy?: string;\n filterBy?: string;\n colorLegend?: string;\n sortBy?: string;\n subgraphBy?: string;\n [key: string]: unknown;\n}\n\nexport interface ChartColumn {\n title: string;\n dataIndex: string;\n}\n\n/** Normalized payload stored on the TipTap chart node. */\nexport interface ChartPayload {\n config: ChartConfig[];\n columns: ChartColumn[];\n dataSource: Record<string, unknown>[];\n}\n\n/** Optional host override for Chart.js colors / fonts. */\nexport interface ChartTheme {\n backgroundColor?: string;\n textColor?: string;\n gridColor?: string;\n borderColor?: string;\n fontFamily?: string;\n palette?: string[];\n}\n","import { normalizeChartConfigAxisFields } from './columnMatching';\nimport {\n isMvpChartType,\n type ChartColumn,\n type ChartConfig,\n type ChartPayload,\n type MvpChartType,\n} from './types';\n\nconst CHART_COMMENT_RE = /^<!--\\s*(\\[[\\s\\S]*?\\]|\\{[\\s\\S]*?\\})\\s*-->\\s*$/;\n\n/** GFM table: header + separator + optional body rows. */\nconst GFM_TABLE_BLOCK_RE =\n /^\\|(.+)\\|\\s*\\n\\|([-:\\s|]+)\\|\\s*\\n((?:\\|.*\\|\\s*\\n?)*)/;\n\nfunction splitRow(line: string): string[] {\n const trimmed = line.trim();\n const inner =\n trimmed.startsWith('|') && trimmed.endsWith('|')\n ? trimmed.slice(1, -1)\n : trimmed;\n return inner.split('|').map((c) => c.trim());\n}\n\nfunction isSeparatorRow(line: string): boolean {\n const cells = splitRow(line);\n return cells.length > 0 && cells.every((c) => /^:?-+:?$/.test(c));\n}\n\nfunction coerceCell(raw: string): string | number {\n const t = raw.trim();\n if (t === '') return t;\n const normalized = t.replace(/,/g, '');\n if (/^[-+]?(\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?$/.test(normalized)) {\n const n = Number(normalized);\n if (!Number.isNaN(n)) return n;\n }\n return t;\n}\n\n/** Parse a GFM markdown table into columns + rows. */\nexport function parseGfmTable(markdown: string): {\n columns: ChartColumn[];\n dataSource: Record<string, unknown>[];\n rawLength: number;\n} | null {\n const match = GFM_TABLE_BLOCK_RE.exec(markdown);\n if (!match) return null;\n const headerLine = `|${match[1]}|`;\n const sepLine = `|${match[2]}|`;\n if (!isSeparatorRow(sepLine)) return null;\n\n const headers = splitRow(headerLine);\n if (headers.length === 0 || headers.every((h) => !h)) return null;\n\n const columns: ChartColumn[] = headers.map((h) => ({\n title: h,\n dataIndex: h,\n }));\n\n const body = match[3] ?? '';\n const dataSource: Record<string, unknown>[] = [];\n for (const line of body.split('\\n')) {\n if (!line.trim()) continue;\n if (!line.includes('|')) continue;\n const cells = splitRow(line);\n if (cells.length === 0) continue;\n const row: Record<string, unknown> = {};\n headers.forEach((h, i) => {\n row[h] = coerceCell(cells[i] ?? '');\n });\n dataSource.push(row);\n }\n\n return {\n columns,\n dataSource,\n rawLength: match[0].length,\n };\n}\n\nfunction looksLikeChartCommentJson(parsed: unknown): boolean {\n if (Array.isArray(parsed)) {\n return parsed.some(\n (c) =>\n c &&\n typeof c === 'object' &&\n 'chartType' in (c as object) &&\n typeof (c as ChartConfig).chartType === 'string',\n );\n }\n if (parsed && typeof parsed === 'object') {\n const o = parsed as Record<string, unknown>;\n if (Array.isArray(o.config)) return true;\n if (typeof o.chartType === 'string') return true;\n }\n return false;\n}\n\n/** Unwrap comment JSON into a flat config list (may include non-MVP types). */\nexport function unwrapChartConfigs(raw: unknown): ChartConfig[] | null {\n if (raw == null) return null;\n if (Array.isArray(raw)) {\n return raw.filter(\n (c): c is ChartConfig =>\n !!c && typeof c === 'object' && typeof (c as ChartConfig).chartType === 'string',\n );\n }\n if (typeof raw !== 'object') return null;\n const o = raw as Record<string, unknown>;\n if (Array.isArray(o.config)) {\n return unwrapChartConfigs(o.config);\n }\n if (typeof o.chartType === 'string') {\n return [o as ChartConfig];\n }\n return null;\n}\n\nfunction inferPieAxes(\n cfg: ChartConfig,\n columns: ChartColumn[],\n): ChartConfig {\n if (cfg.x && cfg.y) return cfg;\n if (columns.length < 2) return cfg;\n return {\n ...cfg,\n x: cfg.x ?? columns[0].dataIndex,\n y: cfg.y ?? columns[1].dataIndex,\n };\n}\n\nfunction axisExists(field: string | undefined, keys: string[]): boolean {\n if (!field) return false;\n return keys.includes(field);\n}\n\n/**\n * Keep only MVP chart configs that have resolvable axes.\n * Returns null when nothing left (caller should leave as plain table).\n */\nexport function normalizeChartPayload(\n configs: ChartConfig[],\n columns: ChartColumn[],\n dataSource: Record<string, unknown>[],\n): ChartPayload | null {\n const keys = columns.map((c) => c.dataIndex);\n const normalized: ChartConfig[] = [];\n\n for (const raw of configs) {\n if (!isMvpChartType(raw.chartType)) continue;\n let cfg = normalizeChartConfigAxisFields({ ...raw }, keys);\n const type = cfg.chartType as MvpChartType;\n if (type === 'pie' || type === 'donut') {\n cfg = inferPieAxes(cfg, columns);\n }\n if (!axisExists(cfg.x, keys) || !axisExists(cfg.y, keys)) continue;\n // v1: ignore subgraphBy\n if (cfg.subgraphBy) {\n const { subgraphBy: _drop, ...rest } = cfg;\n cfg = rest;\n }\n normalized.push(cfg);\n }\n\n if (normalized.length === 0) return null;\n return { config: normalized, columns, dataSource };\n}\n\n/** Parse ```chart / ```json-chart / ```tmr-chart fence body JSON. */\nexport function parseChartFenceBody(body: string): ChartPayload | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(body.trim());\n } catch {\n return null;\n }\n if (!parsed || typeof parsed !== 'object') return null;\n const o = parsed as Record<string, unknown>;\n\n // Full form\n if (Array.isArray(o.columns) || Array.isArray(o.dataSource)) {\n const configs = unwrapChartConfigs(o.config ?? o) ?? [];\n const columns = (o.columns as ChartColumn[]) ?? [];\n const dataSource =\n (o.dataSource as Record<string, unknown>[]) ??\n (o.data as Record<string, unknown>[]) ??\n [];\n if (!columns.length) {\n // Simple { chartType, x, y, data }\n if (Array.isArray(o.data) && typeof o.chartType === 'string') {\n const simpleCols: ChartColumn[] = [\n { title: String(o.x ?? 'x'), dataIndex: 'x' },\n { title: String(o.y ?? 'y'), dataIndex: 'y' },\n ];\n const rows = (o.data as unknown[]).map((item) => {\n if (item && typeof item === 'object') return item as Record<string, unknown>;\n return {};\n });\n return normalizeChartPayload(\n [{ chartType: String(o.chartType), x: 'x', y: 'y', title: o.title as string | undefined }],\n simpleCols,\n rows,\n );\n }\n return null;\n }\n const colObjs: ChartColumn[] = columns.map((c) =>\n typeof c === 'string'\n ? { title: c, dataIndex: c }\n : {\n title: String((c as ChartColumn).title ?? (c as ChartColumn).dataIndex),\n dataIndex: String((c as ChartColumn).dataIndex ?? (c as ChartColumn).title),\n },\n );\n return normalizeChartPayload(configs, colObjs, dataSource);\n }\n\n const configs = unwrapChartConfigs(parsed);\n if (!configs) return null;\n return null;\n}\n\n/**\n * Try to parse leading `<!-- chart json -->` + GFM table from `src`.\n * Returns payload + `raw`(`src` 里被消费掉的**精确前缀**,调用方按 `raw.length`\n * 跳过这一段), or null.\n */\nexport function tryParseCommentTableChart(\n src: string,\n): { payload: ChartPayload; raw: string } | null {\n const trimmedStart = src.replace(/^\\s*/, '');\n const offset = src.length - trimmedStart.length;\n if (!trimmedStart.startsWith('<!--')) return null;\n\n const endComment = trimmedStart.indexOf('-->');\n if (endComment < 0) return null;\n const commentBlock = trimmedStart.slice(0, endComment + 3);\n const cm = CHART_COMMENT_RE.exec(commentBlock.trim());\n if (!cm) return null;\n\n let json: unknown;\n try {\n json = JSON.parse(cm[1]);\n } catch {\n return null;\n }\n if (!looksLikeChartCommentJson(json)) return null;\n\n const configs = unwrapChartConfigs(json);\n if (!configs || configs.length === 0) return null;\n // All table-only → not a chart\n if (configs.every((c) => c.chartType === 'table')) return null;\n\n const afterCommentRaw = trimmedStart.slice(endComment + 3);\n // 注释与表格之间隔空行时折成一个 \\n 再解析(表格内容本身不受影响)。\n const afterComment = afterCommentRaw.replace(/^\\s*\\n/, '\\n');\n const tableStart = afterComment.search(/\\|/);\n if (tableStart < 0) return null;\n const beforeTable = afterComment.slice(0, tableStart);\n if (beforeTable.replace(/\\s/g, '') !== '') return null;\n\n const tableMd = afterComment.slice(tableStart);\n const table = parseGfmTable(tableMd);\n if (!table) return null;\n\n const payload = normalizeChartPayload(\n configs,\n table.columns,\n table.dataSource,\n );\n if (!payload) return null;\n\n // 表格起点要在**原文**里定位:折过的 afterComment 比原文短,拿它当基准会让\n // raw 短掉那几个空行字符,调用方按 raw.length 切 src 就会多吃掉后一个字符\n // —— 表格是最后一块时,被吃掉的正是表格收尾的 `|`。\n const tableStartInSrc = afterCommentRaw.search(/\\|/);\n const raw = src.slice(\n 0,\n offset + commentBlock.length + tableStartInSrc + table.rawLength,\n );\n\n return { payload, raw };\n}\n\n/** Serialize payload to flat comment + GFM table (author form). */\nexport function serializeChartPayload(payload: ChartPayload): string {\n const flat =\n payload.config.length === 1 ? payload.config[0] : payload.config;\n const comment = `<!-- ${JSON.stringify(flat)} -->`;\n const headers = payload.columns.map((c) => c.title);\n const keys = payload.columns.map((c) => c.dataIndex);\n const header = `| ${headers.join(' | ')} |`;\n const sep = `| ${headers.map(() => '---').join(' | ')} |`;\n const rows = payload.dataSource.map((row) => {\n const cells = keys.map((k) => {\n const v = row[k];\n if (v == null) return '';\n return String(v);\n });\n return `| ${cells.join(' | ')} |`;\n });\n return [comment, '', header, sep, ...rows].join('\\n');\n}\n\n/**\n * Replace valid comment+table chart pairs with ```tmr-chart fences\n * so TipTap markdown can tokenize a single fence.\n */\nexport function normalizeChartMarkdown(markdown: string): string {\n if (!markdown) return markdown;\n let rest = markdown;\n let out = '';\n\n while (rest.length > 0) {\n const idx = rest.indexOf('<!--');\n if (idx < 0) {\n out += rest;\n break;\n }\n out += rest.slice(0, idx);\n const attempt = tryParseCommentTableChart(rest.slice(idx));\n if (!attempt) {\n // Skip this comment opener without consuming as chart\n out += '<!--';\n rest = rest.slice(idx + 4);\n continue;\n }\n const fenceBody = JSON.stringify({\n config: attempt.payload.config,\n columns: attempt.payload.columns,\n dataSource: attempt.payload.dataSource,\n });\n out += `\\`\\`\\`tmr-chart\\n${fenceBody}\\n\\`\\`\\``;\n rest = rest.slice(idx + attempt.raw.length);\n // Preserve a newline after fence if original had trailing content\n if (rest.startsWith('\\n')) {\n /* keep */\n } else if (rest.length > 0) {\n out += '\\n';\n }\n }\n\n return out;\n}\n","import type { HTMLAttributes } from 'react';\nimport styles from './styles/content.module.css';\n\nexport interface ReportContentProps extends HTMLAttributes<HTMLDivElement> {\n /** `renderReportHtml(...).html` 产出的正文 HTML 字符串。 */\n html: string;\n}\n\n/**\n * 只读静态正文渲染(RSC / SSR 安全,无 client 代码、无编辑器实例)。\n *\n * 把 `renderReportHtml` 产出的 HTML 注入容器,并套上与编辑器 / 只读预览**同一个\n * 规范正文类**,保证「编辑所见 = 预览所见 = 发布后读者所见」。\n * 用于阅读页首屏直出(SEO 可见),无需 JS 即可显示。\n */\nexport function ReportContent({ html, className, ...rest }: ReportContentProps) {\n return (\n <div\n {...rest}\n className={\n className ? `${styles.editorContent} ${className}` : styles.editorContent\n }\n dangerouslySetInnerHTML={{ __html: html }}\n />\n );\n}\n"],"names":["configs"],"mappings":"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"}
|