tiptap-markdown-react 1.2.1 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiptap-markdown-react",
3
- "version": "1.2.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, '&amp;')\n .replace(/\"/g, '&quot;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\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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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ReportContentWithCharts-BMpzNVsX.js","sources":["../src/labels.ts","../src/i18n/zh.ts","../src/i18n/index.ts","../src/chart/mapData.ts","../src/chart/theme.ts","../src/chart/renderChart.ts","../src/toc/scrollToTocHeading.ts","../src/components/EditorToc.tsx","../src/hooks/useIsMobile.ts","../src/toc/readTocItems.ts","../src/citationDom.ts","../src/components/CitationInteractive.tsx","../src/components/ContentOutline.tsx","../src/components/ReaderReportContent.tsx","../src/components/ReportContentInteractive.tsx","../src/components/ChartMount.tsx","../src/components/ReportContentWithCharts.tsx"],"sourcesContent":["/**\n * UI 文案类型与英文默认。语言包在 `src/i18n`:宿主传 `locale`,不传单条文案。\n */\n\nexport interface ToolbarLabels {\n undo: string;\n redo: string;\n style: string;\n normalText: string;\n /** 传入层级,返回如 \"Heading 2\"。 */\n headingLabel: (level: number) => string;\n fontSize: string;\n fontSizeDefault: string;\n bold: string;\n italic: string;\n underline: string;\n strike: string;\n code: string;\n textColor: string;\n highlight: string;\n colorNone: string;\n colorTheme: string;\n scriptMenu: string;\n scriptNormal: string;\n superscript: string;\n subscript: string;\n link: string;\n /** 段落对齐下拉:触发器 title / aria-label。 */\n align: string;\n alignLeft: string;\n alignCenter: string;\n alignRight: string;\n alignJustify: string;\n /** 缩进下拉:触发器 + 增加 / 减少两项。 */\n indent: string;\n indentIncrease: string;\n indentDecrease: string;\n /** 行高下拉:触发器 + 「默认」项(其余按数字直显)。 */\n lineHeight: string;\n lineHeightDefault: string;\n /**\n * 链接浮层输入框的占位与无障碍名(原 `window.prompt` 的提示语,现在落到输入框上)。\n */\n linkPrompt: string;\n /** 链接浮层「应用」按钮的 title / aria-label。 */\n linkApply: string;\n /** 链接浮层「在新窗口打开」按钮的 title / aria-label。 */\n linkOpen: string;\n /** 链接浮层「移除链接」按钮的 title / aria-label。 */\n linkRemove: string;\n /** 链接浮层:地址被编辑器拒绝时的提示(落在输入框 title 上)。 */\n linkInvalid: string;\n image: string;\n imageUploadFailed: string;\n /** 图片对齐工具条(悬停图片时浮现)的 aria-label。 */\n imageAlign: string;\n /** 左对齐按钮的 title / aria-label。 */\n imageAlignLeft: string;\n /** 居中对齐按钮的 title / aria-label。 */\n imageAlignCenter: string;\n /** 右对齐按钮的 title / aria-label。 */\n imageAlignRight: string;\n /** 图片描述(图注)按钮的 title / aria-label。 */\n imageCaption: string;\n /** 描述输入框的占位与无障碍名。 */\n imageCaptionPlaceholder: string;\n /** Markdown 文件导入失败(与图片上传共用 onError 回调时,便于宿主区分文案)。 */\n importMarkdownFailed: string;\n /** 主栏导入下拉触发器上的短文案(对齐 style / fontSize)。 */\n importDocument: string;\n /** 导入触发器 title / aria-label。 */\n importDocumentHint: string;\n /** 未传 importMenuItems、但传了 onImportDocument + importAccept 时的第二项。 */\n importDocumentOther: string;\n /** 导入进行中的按钮 title。 */\n importDocumentBusy: string;\n /** 光标占位:上传阶段,传入 0–100。 */\n importDocumentUploading: (percent: number) => string;\n /** 光标占位:转换阶段,不要百分比。 */\n importDocumentConverting: string;\n /** 非 Markdown 文件导入失败(onError 的 source === 'import')。 */\n importDocumentFailed: string;\n blockquote: string;\n /** 折叠块(官方 Details)。工具栏按钮 title / aria-label。 */\n details: string;\n bulletList: string;\n orderedList: string;\n /** 有序列表旁的编号格式下拉:触发器 title / aria-label。 */\n numberingFormat: string;\n taskList: string;\n more: string;\n /**\n * 工具栏的搜索入口(放大镜按钮,落在 More 之后):title 与 aria-label。\n * 只在宿主传了 `onSearch` 时才渲染——它只是入口,条子本身归编辑器\n * (`<MarkdownWysiwygEditor>`),点击后由宿主调 `handle.openFind()`。\n */\n search: string;\n codeBlock: string;\n hr: string;\n /** 导入下拉里的 Markdown 项。 */\n importMarkdown: string;\n tableInsert: string;\n /** 行手柄的 title / aria-label(鼠标悬停单元格时出现在行的左缘)。 */\n tableRowMenu: string;\n /** 列手柄的 title / aria-label(悬停时出现在表格上方、对齐该列)。 */\n tableColumnMenu: string;\n /** 表格菜单:清空选中行 / 列 / 单元格矩形里的内容(保留单元格与表头)。 */\n tableClearContent: string;\n /** 表格菜单:把选中单元格的样式属性复位(列宽、对齐等;不动合并结构)。 */\n tableResetCellStyles: string;\n /** 表格底边 `+` 手柄(末尾追加一行)的 title / aria-label。 */\n tableAppendRow: string;\n /** 表格右边 `+` 手柄(末尾追加一列)的 title / aria-label。 */\n tableAppendColumn: string;\n /** 网格选择器底部尺寸文案,如 \"3 × 4\"。参数顺序:列、行。 */\n tableSizeSelected: (cols: number, rows: number) => string;\n tableAddColumnBefore: string;\n tableAddColumnAfter: string;\n tableDeleteColumn: string;\n tableAddRowBefore: string;\n tableAddRowAfter: string;\n tableDeleteRow: string;\n /** 多格选区:在左侧插入 N 列。 */\n tableAddColumnBeforeN: (n: number) => string;\n /** 多格选区:在右侧插入 N 列。 */\n tableAddColumnAfterN: (n: number) => string;\n /** 多格选区:删除 N 列。 */\n tableDeleteColumnN: (n: number) => string;\n /** 多格选区:在上方插入 N 行。 */\n tableAddRowBeforeN: (n: number) => string;\n /** 多格选区:在下方插入 N 行。 */\n tableAddRowAfterN: (n: number) => string;\n /** 多格选区:删除 N 行。 */\n tableDeleteRowN: (n: number) => string;\n tableDeleteTable: string;\n inlineMath: string;\n blockMath: string;\n mathPlaceholder: string;\n mathDone: string;\n mathCancel: string;\n mathNewInline: string;\n mathNewBlock: string;\n}\n\n/** 斜杠菜单(键入 / 唤起的块级插入弹窗)文案。 */\nexport interface SlashMenuLabels {\n /** 弹窗 aria-label。 */\n menuLabel: string;\n /** 分组标题:文本块。 */\n groupText: string;\n /** 分组标题:列表。 */\n groupList: string;\n /** 分组标题:结构 / 高级块。 */\n groupAdvanced: string;\n normalText: string;\n headingLabel: (level: number) => string;\n bulletList: string;\n orderedList: string;\n taskList: string;\n blockquote: string;\n details: string;\n codeBlock: string;\n divider: string;\n table: string;\n inlineMath: string;\n blockMath: string;\n}\n\nexport interface ChartLabels {\n /** Tab label when config has no title. */\n tabLabel: (chartType: string, index: number) => string;\n done: string;\n cancel: string;\n configLabel: string;\n tableLabel: string;\n /** Modal dialog title. */\n editTitle: string;\n}\n\nexport const defaultChartLabels: ChartLabels = {\n tabLabel: (chartType, index) => `${chartType} ${index + 1}`,\n done: 'Done',\n cancel: 'Cancel',\n configLabel: 'Chart config (JSON)',\n tableLabel: 'Data table (Markdown)',\n editTitle: 'Edit chart',\n};\n\nexport const defaultToolbarLabels: ToolbarLabels = {\n undo: 'Undo',\n redo: 'Redo',\n style: 'Style',\n normalText: 'Normal text',\n headingLabel: (level) => `Heading ${level}`,\n fontSize: 'Font size',\n fontSizeDefault: 'Default',\n bold: 'Bold',\n italic: 'Italic',\n underline: 'Underline',\n strike: 'Strikethrough',\n code: 'Inline code',\n textColor: 'Text color',\n highlight: 'Highlight',\n colorNone: 'None',\n colorTheme: 'THEME',\n scriptMenu: 'Superscript / Subscript',\n scriptNormal: 'Normal',\n superscript: 'Superscript',\n subscript: 'Subscript',\n link: 'Link',\n align: 'Alignment',\n alignLeft: 'Align left',\n alignCenter: 'Align center',\n alignRight: 'Align right',\n alignJustify: 'Justify',\n indent: 'Indent',\n indentIncrease: 'Increase indent',\n indentDecrease: 'Decrease indent',\n lineHeight: 'Line height',\n lineHeightDefault: 'Default',\n linkPrompt: 'Enter URL',\n linkApply: 'Apply link',\n linkOpen: 'Open in new window',\n linkRemove: 'Remove link',\n linkInvalid: 'The editor rejected this address',\n image: 'Image',\n imageUploadFailed: 'Image upload failed',\n imageAlign: 'Image alignment',\n imageAlignLeft: 'Align left',\n imageAlignCenter: 'Align center',\n imageAlignRight: 'Align right',\n imageCaption: 'Caption',\n imageCaptionPlaceholder: 'Add a caption…',\n importMarkdownFailed: 'Markdown import failed',\n importDocument: 'Import',\n importDocumentHint: 'Import a file',\n importDocumentOther: 'Document',\n importDocumentBusy: 'Importing…',\n importDocumentUploading: (percent) => `Uploading ${percent}%`,\n importDocumentConverting: 'Converting…',\n importDocumentFailed: 'Import failed',\n blockquote: 'Blockquote',\n details: 'Toggle',\n bulletList: 'Bullet list',\n orderedList: 'Ordered list',\n numberingFormat: 'Numbering format',\n taskList: 'Task list',\n more: 'More',\n search: 'Find & replace',\n codeBlock: 'Code block',\n hr: 'Divider',\n importMarkdown: 'Markdown',\n tableInsert: 'Insert table',\n tableRowMenu: 'Row actions',\n tableColumnMenu: 'Column actions',\n tableClearContent: 'Clear content',\n tableResetCellStyles: 'Reset cell styles',\n tableAppendRow: 'Add row',\n tableAppendColumn: 'Add column',\n tableSizeSelected: (cols, rows) => `${cols} × ${rows}`,\n tableAddColumnBefore: 'Add column before',\n tableAddColumnAfter: 'Add column after',\n tableDeleteColumn: 'Delete column',\n tableAddRowBefore: 'Add row before',\n tableAddRowAfter: 'Add row after',\n tableDeleteRow: 'Delete row',\n tableAddColumnBeforeN: (n) => `Add ${n} columns before`,\n tableAddColumnAfterN: (n) => `Add ${n} columns after`,\n tableDeleteColumnN: (n) => `Delete ${n} columns`,\n tableAddRowBeforeN: (n) => `Add ${n} rows before`,\n tableAddRowAfterN: (n) => `Add ${n} rows after`,\n tableDeleteRowN: (n) => `Delete ${n} rows`,\n tableDeleteTable: 'Delete table',\n inlineMath: 'Inline equation',\n blockMath: 'Block equation',\n mathPlaceholder: 'E = mc^2',\n mathDone: 'Done',\n mathCancel: 'Cancel',\n mathNewInline: 'New equation',\n mathNewBlock: 'Add a TeX equation',\n};\n\n/**\n * 块拖拽手柄和它的菜单。悬停块时出现在左侧,拖动重排,点击出菜单。\n */\nexport interface BlockDragLabels {\n /** 拖拽手柄的 title / aria-label。 */\n dragHandle: string;\n /** 菜单 aria-label。 */\n menuLabel: string;\n /** 「转成」分组标题。 */\n turnInto: string;\n paragraph: string;\n headingLabel: (level: number) => string;\n bulletList: string;\n orderedList: string;\n taskList: string;\n blockquote: string;\n codeBlock: string;\n copy: string;\n duplicate: string;\n resetFormatting: string;\n downloadImage: string;\n delete: string;\n}\n\nexport const defaultBlockDragLabels: BlockDragLabels = {\n dragHandle: 'Drag to move',\n menuLabel: 'Block actions',\n turnInto: 'Turn into',\n paragraph: 'Normal text',\n headingLabel: (level) => `Heading ${level}`,\n bulletList: 'Bullet list',\n orderedList: 'Ordered list',\n taskList: 'Task list',\n blockquote: 'Blockquote',\n codeBlock: 'Code block',\n copy: 'Copy',\n duplicate: 'Duplicate',\n resetFormatting: 'Reset formatting',\n downloadImage: 'Download image',\n delete: 'Delete',\n};\n\nexport const defaultSlashMenuLabels: SlashMenuLabels = {\n menuLabel: 'Insert block',\n groupText: 'Text',\n groupList: 'Lists',\n groupAdvanced: 'Advanced',\n normalText: 'Normal text',\n headingLabel: (level) => `Heading ${level}`,\n bulletList: 'Bullet list',\n orderedList: 'Ordered list',\n taskList: 'Task list',\n blockquote: 'Blockquote',\n details: 'Toggle',\n codeBlock: 'Code block',\n divider: 'Divider',\n table: 'Table',\n inlineMath: 'Inline equation',\n blockMath: 'Block equation',\n};\n\n/** 快捷键抽屉面板(键位 + Markdown 触发写法对照)文案。 */\nexport interface ShortcutLabels {\n /** 抽屉标题。 */\n panelTitle: string;\n /** 关闭按钮 aria / title。 */\n close: string;\n /** 三列表头:格式 / 快捷键 / Markdown。 */\n colFormat: string;\n colShortcut: string;\n colMarkdown: string;\n /** 分组标题。 */\n formatGroup: string;\n insertGroup: string;\n editGroup: string;\n bold: string;\n italic: string;\n strike: string;\n underline: string;\n inlineCode: string;\n highlight: string;\n headingLabel: (level: number) => string;\n paragraph: string;\n blockquote: string;\n bulletList: string;\n orderedList: string;\n taskList: string;\n codeBlock: string;\n divider: string;\n undo: string;\n redo: string;\n hardBreak: string;\n findReplace: string;\n /** 段落对齐四条(官方 TextAlign 的默认键位)。 */\n alignLeft: string;\n alignCenter: string;\n alignRight: string;\n alignJustify: string;\n /** 图片上传占位块(Mod+Shift+I)。 */\n imageUpload: string;\n /** 智能标点:直引号收成弯引号。 */\n smartQuote: string;\n /** 智能标点:`...` 收成省略号。 */\n ellipsis: string;\n /** 智能标点:`--` 收成破折号。 */\n emDash: string;\n /** 表情:`:smile:` 这类短码。 */\n emoji: string;\n}\n\nexport const defaultShortcutLabels: ShortcutLabels = {\n panelTitle: 'Shortcuts',\n close: 'Close',\n colFormat: 'Format',\n colShortcut: 'Shortcut',\n colMarkdown: 'Markdown',\n formatGroup: 'Formatting',\n insertGroup: 'Insert',\n editGroup: 'Editing',\n bold: 'Bold',\n italic: 'Italic',\n strike: 'Strikethrough',\n underline: 'Underline',\n inlineCode: 'Inline code',\n highlight: 'Highlight',\n headingLabel: (level) => `Heading ${level}`,\n paragraph: 'Normal text',\n blockquote: 'Blockquote',\n bulletList: 'Bullet list',\n orderedList: 'Ordered list',\n taskList: 'Task list',\n codeBlock: 'Code block',\n divider: 'Divider',\n undo: 'Undo',\n redo: 'Redo',\n hardBreak: 'Hard break',\n findReplace: 'Find & replace',\n alignLeft: 'Align left',\n alignCenter: 'Align center',\n alignRight: 'Align right',\n alignJustify: 'Justify',\n imageUpload: 'Upload image',\n smartQuote: 'Smart quotes',\n ellipsis: 'Ellipsis',\n emDash: 'Em dash',\n emoji: 'Emoji',\n};\n\n/** 全文统计(官方 CharacterCount)文案。 */\nexport interface CharacterCountLabels {\n /** 统计条的无障碍名。 */\n label: string;\n /** 字符数,如 \"128 characters\"。 */\n characters: (count: number) => string;\n /** 词数,如 \"24 words\"。 */\n words: (count: number) => string;\n}\n\nexport const defaultCharacterCountLabels: CharacterCountLabels = {\n label: 'Document statistics',\n characters: (count) =>\n `${count} ${count === 1 ? 'character' : 'characters'}`,\n words: (count) => `${count} ${count === 1 ? 'word' : 'words'}`,\n};\n\n/** 表情建议列表(键入 `:` 唤起)文案。 */\nexport interface EmojiSuggestionLabels {\n /** 弹窗 aria-label。 */\n menuLabel: string;\n}\n\nexport const defaultEmojiSuggestionLabels: EmojiSuggestionLabels = {\n menuLabel: 'Emoji',\n};\n\n/** 链接编辑浮层(`<LinkPopover>`)文案。 */\nexport interface LinkPopoverLabels {\n /** 输入框占位与无障碍名,也是浮层的 aria-label。 */\n field: string;\n apply: string;\n open: string;\n remove: string;\n /** 地址被编辑器拒绝时的提示(落在输入框 title 上)。 */\n invalid: string;\n}\n\nexport const defaultLinkPopoverLabels: LinkPopoverLabels = {\n field: 'Enter URL',\n apply: 'Apply link',\n open: 'Open in new window',\n remove: 'Remove link',\n invalid: 'The editor rejected this address',\n};\n\nexport interface ColorPaletteLabels {\n none: string;\n theme: string;\n}\n\nexport const defaultColorPaletteLabels: ColorPaletteLabels = {\n none: 'None',\n theme: 'THEME',\n};\n\nexport interface TocLabels {\n title: string;\n expand: string;\n collapse: string;\n}\n\nexport const defaultTocLabels: TocLabels = {\n title: 'Contents',\n expand: 'Expand',\n collapse: 'Collapse',\n};\n\nexport interface CodeBlockLabels {\n autoDetect: string;\n delete: string;\n /** 只读态:复制代码内容。 */\n copy: string;\n /** 只读态:展开超出限高的代码块。 */\n expand: string;\n /** 只读态:收起已展开的代码块。 */\n collapse: string;\n /** 语言选择器的 aria-label。 */\n language: string;\n}\n\nexport const defaultCodeBlockLabels: CodeBlockLabels = {\n autoDetect: 'Auto-detect',\n delete: 'Delete code block',\n copy: 'Copy code',\n expand: 'Expand code',\n collapse: 'Collapse code',\n language: 'Code language',\n};\n\nexport interface CommentLabels {\n open: string;\n resolved: string;\n dismissed: string;\n outdated: string;\n ambiguous: string;\n partial: string;\n gutterTitle: string;\n}\n\nexport const defaultCommentLabels: CommentLabels = {\n open: 'Open',\n resolved: 'Resolved',\n dismissed: 'Dismissed',\n outdated: 'Outdated',\n ambiguous: 'Ambiguous',\n partial: 'Partially matched',\n gutterTitle: 'Comment',\n};\n\nexport interface FindLabels {\n /** 查找输入框的占位与无障碍名,也用作浮动条的 aria-label。 */\n find: string;\n /** 替换输入框的占位与无障碍名。 */\n replace: string;\n next: string;\n previous: string;\n replaceOne: string;\n replaceAll: string;\n close: string;\n caseSensitive: string;\n wholeWord: string;\n useRegex: string;\n /** 计数文案。无结果时 current 传 0;有结果但还没定位到某一条(currentIndex 为 null)时也是 0。 */\n counter: (current: number, total: number) => string;\n /** 正则模式下模式非法(RE2 不支持 lookaround / backreference 等,见官方扩展)。 */\n invalidRegex: string;\n /** 只读态提示:可查不可换。 */\n readOnly: string;\n}\n\nexport const defaultFindLabels: FindLabels = {\n find: 'Find',\n replace: 'Replace with',\n next: 'Next match',\n previous: 'Previous match',\n replaceOne: 'Replace',\n replaceAll: 'Replace all',\n close: 'Close',\n caseSensitive: 'Match case',\n wholeWord: 'Whole word',\n useRegex: 'Use regular expression',\n counter: (current, total) => `${current} / ${total}`,\n invalidRegex: 'Invalid pattern',\n readOnly: 'Read-only',\n};\n\n/** 图片上传占位块(`<MarkdownWysiwygEditor imageUpload={{…}}>`)文案。 */\nexport interface ImageUploadLabels {\n /** 空态主文案前半(下划线强调,对齐官方的 \"Click to upload\"),如 `Click to upload`。 */\n dropzoneClick: string;\n /** 空态主文案后半,如 ` or drag and drop`(中文可写成「,或拖拽到此处」)。 */\n dropzoneRest: string;\n /** 空态副文案:数量与单文件体积上限;`maxSizeMb` 为 null 表示未设上限。 */\n dropzoneLimits: (limit: number, maxSizeMb: number | null) => string;\n /** 多文件排队时的标题,参数为文件数。 */\n uploadingCount: (count: number) => string;\n /** 清空全部排队文件的按钮。 */\n clearAll: string;\n /** 单个文件行的移除按钮(title / aria-label)。 */\n remove: string;\n /** 文件行上传失败时的状态文字(替掉体积位置)。 */\n failed: string;\n /** 上传成功后写入图片 alt / title 的兜底(文件名去扩展名后为空时)。 */\n fallbackAlt: string;\n}\n\nexport const defaultImageUploadLabels: ImageUploadLabels = {\n dropzoneClick: 'Click to upload',\n dropzoneRest: ' or drag and drop',\n dropzoneLimits: (limit, maxSizeMb) => {\n const count = `Maximum ${limit} file${limit === 1 ? '' : 's'}`;\n return maxSizeMb == null ? `${count}.` : `${count}, ${maxSizeMb}MB each.`;\n },\n uploadingCount: (count) => `Uploading ${count} files`,\n clearAll: 'Clear all',\n remove: 'Remove',\n failed: 'Upload failed',\n fallbackAlt: 'image',\n};\n","import type { LocaleBundle } from './types';\n\n/** 内置中文。键必须齐全,宿主不能再补单条。 */\nexport const zh: LocaleBundle = {\n toolbar: {\n undo: '撤销',\n redo: '重做',\n style: '样式',\n normalText: '正文',\n headingLabel: (level) => `标题 ${level}`,\n fontSize: '字号',\n fontSizeDefault: '默认',\n bold: '加粗',\n italic: '斜体',\n underline: '下划线',\n strike: '删除线',\n code: '行内代码',\n textColor: '文字颜色',\n highlight: '高亮',\n colorNone: '无',\n colorTheme: '主题色',\n scriptMenu: '上标 / 下标',\n scriptNormal: '常规',\n superscript: '上标',\n subscript: '下标',\n link: '链接',\n align: '对齐',\n alignLeft: '左对齐',\n alignCenter: '居中',\n alignRight: '右对齐',\n alignJustify: '两端对齐',\n indent: '缩进',\n indentIncrease: '增加缩进',\n indentDecrease: '减少缩进',\n lineHeight: '行高',\n lineHeightDefault: '默认',\n linkPrompt: '输入链接地址',\n linkApply: '应用链接',\n linkOpen: '在新窗口打开',\n linkRemove: '移除链接',\n linkInvalid: '编辑器不接受这个地址',\n image: '图片',\n imageUploadFailed: '图片上传失败',\n imageAlign: '图片对齐',\n imageAlignLeft: '左对齐',\n imageAlignCenter: '居中',\n imageAlignRight: '右对齐',\n imageCaption: '图片描述',\n imageCaptionPlaceholder: '添加描述…',\n importMarkdownFailed: 'Markdown 导入失败',\n importDocument: '导入',\n importDocumentHint: '导入文件',\n importDocumentOther: '文档',\n importDocumentBusy: '正在导入…',\n importDocumentUploading: (percent) => `上传中 ${percent}%`,\n importDocumentConverting: '正在转换…',\n importDocumentFailed: '导入失败',\n blockquote: '引用',\n details: '折叠块',\n bulletList: '无序列表',\n orderedList: '有序列表',\n numberingFormat: '编号格式',\n taskList: '任务列表',\n more: '更多',\n search: '查找替换',\n codeBlock: '代码块',\n hr: '分隔线',\n importMarkdown: 'Markdown',\n tableInsert: '插入表格',\n tableRowMenu: '行操作',\n tableColumnMenu: '列操作',\n tableClearContent: '清空内容',\n tableResetCellStyles: '重置单元格样式',\n tableAppendRow: '添加行',\n tableAppendColumn: '添加列',\n tableSizeSelected: (cols, rows) => `${cols} × ${rows}`,\n tableAddColumnBefore: '在左侧插入列',\n tableAddColumnAfter: '在右侧插入列',\n tableDeleteColumn: '删除列',\n tableAddRowBefore: '在上方插入行',\n tableAddRowAfter: '在下方插入行',\n tableDeleteRow: '删除行',\n tableAddColumnBeforeN: (n) => `在左侧插入 ${n} 列`,\n tableAddColumnAfterN: (n) => `在右侧插入 ${n} 列`,\n tableDeleteColumnN: (n) => `删除 ${n} 列`,\n tableAddRowBeforeN: (n) => `在上方插入 ${n} 行`,\n tableAddRowAfterN: (n) => `在下方插入 ${n} 行`,\n tableDeleteRowN: (n) => `删除 ${n} 行`,\n tableDeleteTable: '删除表格',\n inlineMath: '行内公式',\n blockMath: '块级公式',\n mathPlaceholder: 'E = mc^2',\n mathDone: '完成',\n mathCancel: '取消',\n mathNewInline: '新建公式',\n mathNewBlock: '插入 TeX 公式',\n },\n slashMenu: {\n menuLabel: '插入块',\n groupText: '文本',\n groupList: '列表',\n groupAdvanced: '高级',\n normalText: '正文',\n headingLabel: (level) => `标题 ${level}`,\n bulletList: '无序列表',\n orderedList: '有序列表',\n taskList: '任务列表',\n blockquote: '引用',\n details: '折叠块',\n codeBlock: '代码块',\n divider: '分隔线',\n table: '表格',\n inlineMath: '行内公式',\n blockMath: '块级公式',\n },\n chart: {\n tabLabel: (chartType, index) => `${chartType} ${index + 1}`,\n done: '完成',\n cancel: '取消',\n configLabel: '图表配置(JSON)',\n tableLabel: '数据表(Markdown)',\n editTitle: '编辑图表',\n },\n blockDrag: {\n dragHandle: '拖动以移动',\n menuLabel: '块操作',\n turnInto: '转换成',\n paragraph: '正文',\n headingLabel: (level) => `标题 ${level}`,\n bulletList: '无序列表',\n orderedList: '有序列表',\n taskList: '任务列表',\n blockquote: '引用',\n codeBlock: '代码块',\n copy: '复制',\n duplicate: '再制一份',\n resetFormatting: '清除格式',\n downloadImage: '下载图片',\n delete: '删除',\n },\n shortcut: {\n panelTitle: '快捷键',\n close: '关闭',\n colFormat: '格式',\n colShortcut: '快捷键',\n colMarkdown: 'Markdown',\n formatGroup: '格式',\n insertGroup: '插入',\n editGroup: '编辑',\n bold: '加粗',\n italic: '斜体',\n strike: '删除线',\n underline: '下划线',\n inlineCode: '行内代码',\n highlight: '高亮',\n headingLabel: (level) => `标题 ${level}`,\n paragraph: '正文',\n blockquote: '引用',\n bulletList: '无序列表',\n orderedList: '有序列表',\n taskList: '任务列表',\n codeBlock: '代码块',\n divider: '分隔线',\n undo: '撤销',\n redo: '重做',\n hardBreak: '硬换行',\n findReplace: '查找替换',\n alignLeft: '左对齐',\n alignCenter: '居中',\n alignRight: '右对齐',\n alignJustify: '两端对齐',\n imageUpload: '上传图片',\n smartQuote: '智能引号',\n ellipsis: '省略号',\n emDash: '破折号',\n emoji: '表情',\n },\n characterCount: {\n label: '字数统计',\n characters: (count) => `${count} 字符`,\n words: (count) => `${count} 词`,\n },\n emoji: {\n menuLabel: '表情',\n },\n link: {\n field: '输入链接地址',\n apply: '应用链接',\n open: '在新窗口打开',\n remove: '移除链接',\n invalid: '编辑器不接受这个地址',\n },\n palette: {\n none: '无',\n theme: '主题色',\n },\n toc: {\n title: '目录',\n expand: '展开',\n collapse: '收起',\n },\n codeBlock: {\n autoDetect: '自动识别',\n delete: '删除代码块',\n copy: '复制代码',\n expand: '展开代码',\n collapse: '收起代码',\n language: '代码语言',\n },\n find: {\n find: '查找',\n replace: '替换为',\n next: '下一处',\n previous: '上一处',\n replaceOne: '替换',\n replaceAll: '全部替换',\n close: '关闭',\n caseSensitive: '区分大小写',\n wholeWord: '全词匹配',\n useRegex: '正则表达式',\n counter: (current, total) => `${current} / ${total}`,\n invalidRegex: '正则无效',\n readOnly: '只读',\n },\n imageUpload: {\n dropzoneClick: '点击上传',\n dropzoneRest: ',或拖拽到此处',\n dropzoneLimits: (limit, maxSizeMb) => {\n const count = `最多 ${limit} 个文件`;\n return maxSizeMb == null ? `${count}。` : `${count},每个 ${maxSizeMb}MB。`;\n },\n uploadingCount: (count) => `正在上传 ${count} 个文件`,\n clearAll: '全部清除',\n remove: '移除',\n failed: '上传失败',\n fallbackAlt: '图片',\n },\n};\n","import {\n defaultBlockDragLabels,\n defaultCharacterCountLabels,\n defaultChartLabels,\n defaultCodeBlockLabels,\n defaultColorPaletteLabels,\n defaultEmojiSuggestionLabels,\n defaultFindLabels,\n defaultImageUploadLabels,\n defaultLinkPopoverLabels,\n defaultShortcutLabels,\n defaultSlashMenuLabels,\n defaultTocLabels,\n defaultToolbarLabels,\n} from '../labels';\nimport type { LocaleBundle, LocaleCode } from './types';\nimport { zh } from './zh';\n\nexport type { LocaleBundle, LocaleCode } from './types';\n\nconst en: LocaleBundle = {\n toolbar: defaultToolbarLabels,\n slashMenu: defaultSlashMenuLabels,\n chart: defaultChartLabels,\n blockDrag: defaultBlockDragLabels,\n shortcut: defaultShortcutLabels,\n characterCount: defaultCharacterCountLabels,\n emoji: defaultEmojiSuggestionLabels,\n link: defaultLinkPopoverLabels,\n palette: defaultColorPaletteLabels,\n toc: defaultTocLabels,\n codeBlock: defaultCodeBlockLabels,\n find: defaultFindLabels,\n imageUpload: defaultImageUploadLabels,\n};\n\nconst bundles: Record<LocaleCode, LocaleBundle> = { en, zh };\n\n/** 取一份完整文案。未知语言回落英文。 */\nexport function getLocaleBundle(locale: LocaleCode = 'en'): LocaleBundle {\n return bundles[locale] ?? en;\n}\n","import type { ChartConfig, ChartPayload } from './types';\n\nexport interface ChartJsPoint {\n x: string | number;\n y: number;\n category?: string;\n type?: string;\n}\n\nfunction toNumber(value: unknown): number {\n if (typeof value === 'number' && !Number.isNaN(value)) return value;\n if (typeof value === 'string') {\n const n = Number(value.replace(/,/g, ''));\n if (!Number.isNaN(n)) return n;\n }\n return 0;\n}\n\n/**\n * Map table rows to flat chart points for one config.\n * colorLegend → series `type`; groupBy stored as category (no UI filter in v1).\n */\nexport function mapChartDataItems(\n config: ChartConfig,\n dataSource: Record<string, unknown>[],\n): ChartJsPoint[] {\n const xKey = config.x!;\n const yKey = config.y!;\n const legendKey = config.colorLegend;\n const groupKey = config.groupBy;\n\n let rows = [...dataSource];\n const sortKey = config.sortBy;\n if (sortKey) {\n rows.sort((a, b) => {\n const av = a[sortKey];\n const bv = b[sortKey];\n if (typeof av === 'number' && typeof bv === 'number') return av - bv;\n return String(av ?? '').localeCompare(String(bv ?? ''), undefined, {\n numeric: true,\n });\n });\n }\n\n return rows.map((row) => {\n const point: ChartJsPoint = {\n x: row[xKey] as string | number,\n y: toNumber(row[yKey]),\n };\n if (legendKey) point.type = String(row[legendKey] ?? '');\n if (groupKey) point.category = String(row[groupKey] ?? '');\n return point;\n });\n}\n\nexport interface BuiltChartData {\n labels: string[];\n datasets: {\n label: string;\n data: number[];\n }[];\n isCartesian: boolean;\n}\n\n/** Build Chart.js labels/datasets for one active config. */\nexport function buildChartJsData(\n config: ChartConfig,\n payload: Pick<ChartPayload, 'dataSource'>,\n): BuiltChartData {\n const points = mapChartDataItems(config, payload.dataSource);\n const type = config.chartType;\n const isCartesian = !['pie', 'donut'].includes(type);\n\n if (!isCartesian) {\n return {\n labels: points.map((p) => String(p.x)),\n datasets: [\n {\n label: config.title || config.y || 'value',\n data: points.map((p) => p.y),\n },\n ],\n isCartesian: false,\n };\n }\n\n const seriesKeys = new Set<string>();\n for (const p of points) {\n seriesKeys.add(p.type || config.title || config.y || 'series');\n }\n const seriesList = [...seriesKeys];\n const labelSet: string[] = [];\n for (const p of points) {\n const lab = String(p.x);\n if (!labelSet.includes(lab)) labelSet.push(lab);\n }\n\n const datasets = seriesList.map((series) => ({\n label: series,\n data: labelSet.map((lab) => {\n const hit = points.find(\n (p) =>\n String(p.x) === lab &&\n (p.type || config.title || config.y || 'series') === series,\n );\n return hit ? hit.y : 0;\n }),\n }));\n\n return { labels: labelSet, datasets, isCartesian: true };\n}\n","import type { ChartTheme } from './types';\n\nconst DEFAULT_PALETTE = [\n '#3b82f6',\n '#10b981',\n '#f59e0b',\n '#ef4444',\n '#8b5cf6',\n '#06b6d4',\n '#ec4899',\n '#84cc16',\n];\n\nfunction readCssVar(\n el: HTMLElement | null,\n name: string,\n fallback: string,\n): string {\n if (!el || typeof getComputedStyle === 'undefined') return fallback;\n const v = getComputedStyle(el).getPropertyValue(name).trim();\n return v || fallback;\n}\n\n/** Resolve theme from --tmr-* CSS variables + optional host override. */\nexport function resolveChartTheme(\n host: HTMLElement | null,\n override?: ChartTheme | null,\n): Required<\n Pick<\n ChartTheme,\n | 'backgroundColor'\n | 'textColor'\n | 'gridColor'\n | 'borderColor'\n | 'fontFamily'\n | 'palette'\n >\n> {\n const base = {\n backgroundColor: readCssVar(host, '--tmr-bg', '#ffffff'),\n textColor: readCssVar(host, '--tmr-fg', '#1f2937'),\n gridColor: readCssVar(host, '--tmr-border', '#e5e7eb'),\n borderColor: readCssVar(host, '--tmr-border', '#e5e7eb'),\n fontFamily: readCssVar(\n host,\n '--tmr-font',\n 'ui-sans-serif, system-ui, sans-serif',\n ),\n palette: DEFAULT_PALETTE,\n };\n if (!override) return base;\n return {\n backgroundColor: override.backgroundColor ?? base.backgroundColor,\n textColor: override.textColor ?? base.textColor,\n gridColor: override.gridColor ?? base.gridColor,\n borderColor: override.borderColor ?? base.borderColor,\n fontFamily: override.fontFamily ?? base.fontFamily,\n palette:\n override.palette && override.palette.length > 0\n ? override.palette\n : base.palette,\n };\n}\n","import {\n ArcElement,\n BarController,\n BarElement,\n CategoryScale,\n Chart,\n DoughnutController,\n Filler,\n Legend,\n LineController,\n LineElement,\n LinearScale,\n PieController,\n PointElement,\n Tooltip,\n type ChartConfiguration,\n type ChartType,\n} from 'chart.js';\nimport { buildChartJsData } from './mapData';\nimport { resolveChartTheme } from './theme';\nimport type { ChartConfig, ChartPayload, ChartTheme } from './types';\n\nlet registered = false;\n\nfunction ensureRegister() {\n if (registered) return;\n if (typeof window === 'undefined') return;\n Chart.register(\n CategoryScale,\n LinearScale,\n PointElement,\n LineElement,\n BarElement,\n ArcElement,\n LineController,\n BarController,\n PieController,\n DoughnutController,\n Filler,\n Legend,\n Tooltip,\n );\n registered = true;\n}\n\nfunction toChartJsType(chartType: string): ChartType {\n switch (chartType) {\n case 'bar':\n return 'bar';\n case 'column':\n return 'bar';\n case 'line':\n return 'line';\n case 'area':\n return 'line';\n case 'pie':\n return 'pie';\n case 'donut':\n return 'doughnut';\n default:\n return 'bar';\n }\n}\n\nexport interface RenderChartOptions {\n canvas: HTMLCanvasElement;\n config: ChartConfig;\n payload: Pick<ChartPayload, 'dataSource' | 'columns'>;\n theme?: ChartTheme | null;\n /** Existing instance to update in place (streaming). */\n chart?: Chart | null;\n}\n\nexport function renderOrUpdateChart({\n canvas,\n config,\n payload,\n theme,\n chart,\n}: RenderChartOptions): Chart | null {\n if (typeof window === 'undefined') return null;\n ensureRegister();\n\n const host = canvas.parentElement;\n const colors = resolveChartTheme(host, theme);\n const built = buildChartJsData(config, payload);\n const jsType = toChartJsType(config.chartType);\n const isBarHorizontal = config.chartType === 'bar';\n const isArea = config.chartType === 'area';\n\n const datasets = built.datasets.map((ds, i) => {\n const color = colors.palette[i % colors.palette.length];\n if (!built.isCartesian) {\n return {\n ...ds,\n backgroundColor: built.labels.map(\n (_, j) => colors.palette[j % colors.palette.length],\n ),\n borderWidth: 0,\n };\n }\n return {\n ...ds,\n backgroundColor: isArea ? `${color}33` : color,\n borderColor: color,\n borderWidth: 2,\n fill: isArea,\n tension: 0.25,\n };\n });\n\n const configuration: ChartConfiguration = {\n type: jsType,\n data: {\n labels: built.labels,\n datasets,\n },\n options: {\n indexAxis: isBarHorizontal ? 'y' : 'x',\n responsive: true,\n maintainAspectRatio: false,\n plugins: {\n legend: {\n display: built.datasets.length > 1 || !built.isCartesian,\n labels: {\n color: colors.textColor,\n font: { family: colors.fontFamily },\n },\n },\n title: { display: false },\n tooltip: {\n titleFont: { family: colors.fontFamily },\n bodyFont: { family: colors.fontFamily },\n },\n },\n scales: built.isCartesian\n ? {\n x: {\n ticks: {\n color: colors.textColor,\n font: { family: colors.fontFamily },\n },\n grid: { color: colors.gridColor },\n border: { color: colors.borderColor },\n },\n y: {\n ticks: {\n color: colors.textColor,\n font: { family: colors.fontFamily },\n },\n grid: { color: colors.gridColor },\n border: { color: colors.borderColor },\n },\n }\n : undefined,\n },\n };\n\n if (chart) {\n (chart.config as { type: ChartType }).type = jsType;\n chart.data.labels = configuration.data.labels;\n chart.data.datasets = configuration.data.datasets as never;\n chart.options = configuration.options as never;\n chart.update('none');\n return chart;\n }\n\n return new Chart(canvas, configuration);\n}\n\nexport function destroyChart(chart: Chart | null | undefined) {\n chart?.destroy();\n}\n","/**\n * 目录点击 → 平滑滚到对应标题。\n *\n * 不依赖浏览器 `scrollTo({behavior:'smooth'})` / `scrollIntoView({behavior:'smooth'})`——\n * 在 flex + overflow 嵌套布局下(父级 `overflow:hidden`、自身 `flex:1; overflow-y:auto`),\n * Chrome 的 compositor 驱动 smooth scroll 会静默失效。\n *\n * 改用 `requestAnimationFrame` + easeOutCubic 缓动,直接操作 `scrollTop`,\n * 主线程一次性 400ms 动画,点击触发的单次滚动无感知性能差异。\n *\n * 尊重 `prefers-reduced-motion: reduce`——此时瞬间跳转,无动画。\n */\n\n/** 缓动:easeOutCubic。t ∈ [0, 1]。 */\nfunction easeOutCubic(t: number): number {\n return 1 - (1 - t) * (1 - t) * (1 - t);\n}\n\n/**\n * 平滑滚动(或瞬间跳转)到指定 `data-toc-id` 的标题。\n *\n * @param headingId - TOC item 的 id,对应 DOM 上 `data-toc-id` 属性值\n * @param scrollContainer - 滚动容器(如 `.scrollArea`)\n * @param options - `duration`:动画时长 ms,默认 400\n */\nexport function scrollToTocHeading(\n headingId: string,\n scrollContainer: HTMLElement,\n options?: { duration?: number },\n): void {\n const el = scrollContainer.querySelector<HTMLElement>(\n `[data-toc-id=\"${CSS.escape(headingId)}\"]`,\n );\n if (!el) return;\n\n const startTop = scrollContainer.scrollTop;\n const rootRect = scrollContainer.getBoundingClientRect();\n const elRect = el.getBoundingClientRect();\n const targetTop = startTop + (elRect.top - rootRect.top);\n\n // prefers-reduced-motion:瞬间跳转\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {\n scrollContainer.scrollTop = targetTop;\n return;\n }\n\n // 手动平滑滚动\n const duration = options?.duration ?? 400;\n const start = performance.now();\n const animate = () => {\n const t = Math.min((performance.now() - start) / duration, 1);\n scrollContainer.scrollTop = startTop + (targetTop - startTop) * easeOutCubic(t);\n if (t < 1) requestAnimationFrame(animate);\n };\n requestAnimationFrame(animate);\n}\n","'use client';\n\nimport { useEffect, useRef, useState, type CSSProperties } from 'react';\nimport { getLocaleBundle, type LocaleCode } from '../i18n';\nimport styles from '../styles/editorToc.module.css';\nimport type { TocItem } from '../toc/extractToc';\nimport { scrollToTocHeading } from '../toc/scrollToTocHeading';\n\n/** 短横线宽度:层级越高越长。 */\nfunction barWidth(level: number): number {\n if (level <= 1) return 20;\n if (level === 2) return 14;\n if (level === 3) return 10;\n return 6;\n}\n\n/**\n * 最近的可滚动祖先。限高但还没溢出的容器也算(内容变长后由它滚)。\n * 都没有时用文档滚动根。\n */\nfunction findScrollParent(start: HTMLElement): HTMLElement {\n let node: HTMLElement | null = start.parentElement;\n while (node && node !== document.documentElement) {\n const style = getComputedStyle(node);\n const overflowY = style.overflowY;\n const canScroll =\n overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay';\n if (\n canScroll &&\n (node.scrollHeight > node.clientHeight + 1 || style.maxHeight !== 'none')\n ) {\n return node;\n }\n node = node.parentElement;\n }\n return (document.scrollingElement as HTMLElement) ?? document.documentElement;\n}\n\nfunction isViewportScroller(node: HTMLElement): boolean {\n return (\n node === document.documentElement ||\n node === document.body ||\n node === document.scrollingElement\n );\n}\n\nexport interface EditorTocProps {\n items: TocItem[];\n /** 编辑器正文根节点,用来找标题和滚动容器。 */\n editorDom: HTMLElement;\n locale?: LocaleCode;\n}\n\n/**\n * 编辑器内目录(Notion 式,贴在左缘)。\n * 收起是一列短横线;悬停或聚焦向右展开标题,点击滚到对应标题。\n */\nexport function EditorToc({ items, editorDom, locale = 'en' }: EditorTocProps) {\n const t = getLocaleBundle(locale).toc;\n const [open, setOpen] = useState(false);\n const [activeId, setActiveId] = useState(items[0]?.id ?? '');\n const [roving, setRoving] = useState(0);\n const navRef = useRef<HTMLElement>(null);\n const itemRefs = useRef<Array<HTMLButtonElement | null>>([]);\n const hideTimer = useRef<number | null>(null);\n /** 点击后先钉住这一项。正文不够长、滚不到激活线时,滚动监听不能把它盖掉。 */\n const pinnedId = useRef<string | null>(null);\n const pinScroll = useRef<number | null>(null);\n const pinTimer = useRef<number | null>(null);\n\n const clearHide = () => {\n if (hideTimer.current !== null) {\n window.clearTimeout(hideTimer.current);\n hideTimer.current = null;\n }\n };\n\n const show = () => {\n clearHide();\n setOpen(true);\n };\n\n const hideSoon = () => {\n clearHide();\n hideTimer.current = window.setTimeout(() => {\n hideTimer.current = null;\n if (navRef.current?.contains(document.activeElement)) return;\n setOpen(false);\n }, 80);\n };\n\n useEffect(\n () => () => {\n clearHide();\n if (pinTimer.current !== null) window.clearTimeout(pinTimer.current);\n },\n [],\n );\n\n // 视口上半区里最靠上的标题为当前章节;都离开上半区时,取已经滚过去的最后一个。\n useEffect(() => {\n const headings = items\n .map((item) =>\n editorDom.querySelector<HTMLElement>(\n `[data-toc-id=\"${CSS.escape(item.id)}\"]`,\n ),\n )\n .filter((el): el is HTMLElement => el !== null);\n if (!headings.length) return;\n\n const scrollParent = findScrollParent(editorDom);\n const viewport = isViewportScroller(scrollParent);\n const visible = new Set<Element>();\n\n const scrollPos = () =>\n viewport ? window.scrollY : scrollParent.scrollTop;\n\n const apply = () => {\n const pos = scrollPos();\n if (pinnedId.current) {\n const lockedAt = pinScroll.current;\n if (lockedAt === null || Math.abs(pos - lockedAt) <= 2) {\n setActiveId(pinnedId.current);\n return;\n }\n pinnedId.current = null;\n pinScroll.current = null;\n }\n\n const maxScroll = viewport\n ? Math.max(\n 0,\n (document.scrollingElement?.scrollHeight ?? 0) - window.innerHeight,\n )\n : Math.max(0, scrollParent.scrollHeight - scrollParent.clientHeight);\n // 已经滚到底、后面没有更多正文时,当前项是视口里最靠下的标题。\n if (maxScroll > 1 && pos >= maxScroll - 2) {\n const rootBottom = viewport\n ? window.innerHeight\n : scrollParent.getBoundingClientRect().bottom;\n let lastInView: HTMLElement | null = null;\n for (const heading of headings) {\n if (heading.getBoundingClientRect().top < rootBottom - 8) {\n lastInView = heading;\n }\n }\n const id = (lastInView ?? headings[headings.length - 1]).getAttribute(\n 'data-toc-id',\n );\n if (id) setActiveId(id);\n return;\n }\n\n const rootTop = viewport ? 0 : scrollParent.getBoundingClientRect().top;\n let best: HTMLElement | null = null;\n let bestTop = Infinity;\n for (const el of visible) {\n const top = (el as HTMLElement).getBoundingClientRect().top;\n if (top < bestTop) {\n bestTop = top;\n best = el as HTMLElement;\n }\n }\n if (!best) {\n let last: HTMLElement | null = null;\n for (const heading of headings) {\n if (heading.getBoundingClientRect().top <= rootTop + 12) last = heading;\n }\n best = last ?? headings[0];\n }\n const id = best.getAttribute('data-toc-id');\n if (id) setActiveId(id);\n };\n\n const observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting) visible.add(entry.target);\n else visible.delete(entry.target);\n }\n apply();\n },\n {\n root: viewport ? null : scrollParent,\n rootMargin: '0px 0px -60% 0px',\n threshold: [0, 1],\n },\n );\n for (const heading of headings) observer.observe(heading);\n\n const onScroll = () => apply();\n const scrollTarget: HTMLElement | Window = viewport ? window : scrollParent;\n scrollTarget.addEventListener('scroll', onScroll, { passive: true });\n apply();\n\n return () => {\n observer.disconnect();\n scrollTarget.removeEventListener('scroll', onScroll);\n };\n }, [items, editorDom]);\n\n // 目录没被键盘占用时,下一个 Tab 落在当前章节上。\n useEffect(() => {\n if (navRef.current?.contains(document.activeElement)) return;\n const index = items.findIndex((item) => item.id === activeId);\n if (index >= 0) setRoving(index);\n }, [activeId, items]);\n\n useEffect(() => {\n if (!open || !activeId) return;\n const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n navRef.current\n ?.querySelector(`[data-toc-item=\"${CSS.escape(activeId)}\"]`)\n ?.scrollIntoView({ block: 'nearest', behavior: reduce ? 'auto' : 'smooth' });\n }, [activeId, open]);\n\n // 键盘落在短横线上时,焦点交给已经展开的标题按钮。\n useEffect(() => {\n if (!open || !navRef.current) return;\n const rail = navRef.current.querySelector('[data-toc-rail]');\n if (!rail?.contains(document.activeElement)) return;\n const index = Math.max(\n 0,\n items.findIndex((item) => item.id === activeId),\n );\n itemRefs.current[index]?.focus();\n }, [open, activeId, items]);\n\n const jump = (item: TocItem) => {\n const scroller = findScrollParent(editorDom);\n pinnedId.current = item.id;\n pinScroll.current = null;\n setActiveId(item.id);\n scrollToTocHeading(item.id, scroller);\n if (pinTimer.current !== null) window.clearTimeout(pinTimer.current);\n pinTimer.current = window.setTimeout(() => {\n pinTimer.current = null;\n if (pinnedId.current !== item.id) return;\n pinScroll.current = isViewportScroller(scroller)\n ? window.scrollY\n : scroller.scrollTop;\n }, 480);\n };\n\n const move = (delta: number) => {\n const next = Math.min(items.length - 1, Math.max(0, roving + delta));\n setRoving(next);\n setOpen(true);\n itemRefs.current[next]?.focus();\n };\n\n return (\n <div className={styles.anchor}>\n <nav\n ref={navRef}\n className={styles.nav}\n aria-label={t.title}\n data-editor-toc=\"\"\n onMouseEnter={show}\n onMouseLeave={hideSoon}\n onFocus={show}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget)) hideSoon();\n }}\n onKeyDown={(event) => {\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n move(1);\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n move(-1);\n } else if (event.key === 'Escape') {\n setOpen(false);\n }\n }}\n >\n <ul className={styles.rail} data-toc-rail=\"\" aria-hidden={open} inert={open}>\n {items.map((item, index) => {\n const active = item.id === activeId;\n return (\n <li key={item.id}>\n <button\n type=\"button\"\n tabIndex={!open && index === roving ? 0 : -1}\n className={styles.tick}\n style={{ '--bar-width': `${barWidth(item.level)}px` } as CSSProperties}\n aria-current={active ? 'true' : undefined}\n aria-label={item.text}\n onClick={() => jump(item)}\n >\n <span className={active ? styles.barActive : styles.bar} />\n </button>\n </li>\n );\n })}\n </ul>\n <div className={open ? styles.cardOpen : styles.card} inert={!open}>\n <div className={styles.cardInner}>\n <ul className={styles.list}>\n {items.map((item, index) => {\n const active = item.id === activeId;\n return (\n <li key={item.id}>\n <button\n type=\"button\"\n ref={(node) => {\n itemRefs.current[index] = node;\n }}\n data-toc-item={item.id}\n tabIndex={open && index === roving ? 0 : -1}\n className={active ? `${styles.item} ${styles.itemActive}` : styles.item}\n style={\n {\n '--toc-indent': `${(item.level - 1) * 12 + 10}px`,\n } as CSSProperties\n }\n aria-current={active ? 'true' : undefined}\n aria-label={item.text}\n onClick={() => jump(item)}\n >\n <span className={styles.itemText}>{item.text}</span>\n </button>\n </li>\n );\n })}\n </ul>\n </div>\n </div>\n </nav>\n </div>\n );\n}\n","import { useEffect, useState } from 'react';\n\n/**\n * 是否窄屏(默认 <768px)。取代原项目的 useDevice,内联为纯 matchMedia,\n * 无第三方依赖。SSR 首帧返回 false,挂载后按实际视口更新。\n */\nexport function useIsMobile(breakpoint = 768): boolean {\n const [isMobile, setIsMobile] = useState(false);\n\n useEffect(() => {\n const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);\n const update = () => setIsMobile(mq.matches);\n update();\n mq.addEventListener('change', update);\n return () => mq.removeEventListener('change', update);\n }, [breakpoint]);\n\n return isMobile;\n}\n","import type { TocItem } from './extractToc';\n\nconst HEADING_TAG = /^H([1-6])$/;\n\nexport function sameTocItems(a: TocItem[], b: TocItem[]): boolean {\n if (a.length !== b.length) return false;\n return a.every(\n (item, index) =>\n item.id === b[index]?.id &&\n item.level === b[index]?.level &&\n item.text === b[index]?.text,\n );\n}\n\n/** 从已渲染的标题上收集目录。只认带 data-toc-id 的 h1–h6。 */\nexport function readTocItems(root: ParentNode): TocItem[] {\n const nodes = root.querySelectorAll<HTMLElement>('[data-toc-id]');\n const items: TocItem[] = [];\n nodes.forEach((el) => {\n const id = el.getAttribute('data-toc-id');\n const match = HEADING_TAG.exec(el.tagName);\n if (!id || !match) return;\n const text = (el.textContent ?? '').replace(/\\s+/g, ' ').trim();\n if (!text) return;\n items.push({ id, level: Number(match[1]), text });\n });\n return items;\n}\n","/**\n * 从事件目标向上找到 `.citation-ref`(且必须在 root 内)。\n * SSR 阅读页事件委托与单测共用。\n */\nexport function findCitationRefElement(\n target: EventTarget | null,\n root: ParentNode,\n): HTMLElement | null {\n let node: Node | null = null;\n if (target instanceof Element) node = target;\n else if (target instanceof Text) node = target.parentElement;\n else if (target instanceof Node) node = target.parentElement;\n if (!(node instanceof Element)) return null;\n const el = node.closest('.citation-ref');\n if (!(el instanceof HTMLElement)) return null;\n if (!root.contains(el)) return null;\n return el;\n}\n\n/** 从圆标 DOM 读取 attrs(与 CitationRef renderHTML 的 data-* 对齐)。 */\nexport function readCitationAttrs(el: HTMLElement): {\n index: string;\n url: string | null;\n title: string | null;\n} {\n return {\n index: el.getAttribute('data-index') || el.textContent?.trim() || '',\n url: el.getAttribute('data-url'),\n title: el.getAttribute('data-title'),\n };\n}\n","'use client';\n\nimport { useEffect, useRef, type RefObject } from 'react';\nimport {\n findCitationRefElement,\n readCitationAttrs,\n} from '../citationDom';\nimport type {\n OnCitationEnter,\n OnCitationLeave,\n} from '../citationTypes';\n\nexport interface CitationInteractiveProps {\n /**\n * 包含 `ReportContent` HTML 的根节点(其内应有 `.citation-ref`)。\n * 用同一 ref 包住 ReportContent 即可。\n */\n containerRef: RefObject<HTMLElement | null>;\n /** 点击圆标。宿主据此 setState 打开自己的 Popover。 */\n onCitationEnter: OnCitationEnter;\n /**\n * 点正文非圆标处 / 再点同一圆标 / Escape。\n * 库立即回调;浮层开关由宿主管。\n */\n onCitationLeave: OnCitationLeave;\n}\n\n/**\n * SSR 阅读页脚注增强:只做 **click** 事件委托,不持有 open 状态。\n *\n * ```tsx\n * <CitationInteractive\n * containerRef={ref}\n * onCitationEnter={setActive}\n * onCitationLeave={() => setActive(null)}\n * />\n * ```\n */\nexport function CitationInteractive({\n containerRef,\n onCitationEnter,\n onCitationLeave,\n}: CitationInteractiveProps) {\n const enterRef = useRef(onCitationEnter);\n const leaveRef = useRef(onCitationLeave);\n enterRef.current = onCitationEnter;\n leaveRef.current = onCitationLeave;\n\n useEffect(() => {\n const root = containerRef.current;\n if (!root) return;\n\n let currentEl: HTMLElement | null = null;\n\n const emitEnter = (el: HTMLElement) => {\n currentEl = el;\n const attrs = readCitationAttrs(el);\n enterRef.current({ index: attrs.index, attrs, anchorEl: el });\n };\n\n const emitLeave = () => {\n if (!currentEl) return;\n currentEl = null;\n leaveRef.current();\n };\n\n const ACTIVE_ATTR = 'data-tmr-citation-active';\n\n const onClick = (e: MouseEvent) => {\n const el = findCitationRefElement(e.target, root);\n if (el) {\n // 捕获阶段就取消默认,避免圆标内 <a> 跳转\n e.preventDefault();\n e.stopPropagation();\n // 仅当该圆标仍处于打开态时再点才关闭(宿主可能已外部关闭,attr 已清)\n if (el === currentEl && el.hasAttribute(ACTIVE_ATTR)) {\n emitLeave();\n return;\n }\n emitEnter(el);\n return;\n }\n emitLeave();\n };\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') emitLeave();\n };\n\n root.addEventListener('click', onClick, true);\n document.addEventListener('keydown', onKeyDown);\n\n return () => {\n root.removeEventListener('click', onClick, true);\n document.removeEventListener('keydown', onKeyDown);\n };\n }, [containerRef]);\n\n return null;\n}\n","'use client';\n\nimport { useLayoutEffect, useRef, useState, type ReactNode } from 'react';\nimport type { LocaleCode } from '../i18n';\nimport { useIsMobile } from '../hooks/useIsMobile';\nimport styles from '../styles/content.module.css';\nimport { readTocItems, sameTocItems } from '../toc/readTocItems';\nimport type { TocItem } from '../toc/extractToc';\nimport { EditorToc } from './EditorToc';\n\nexport function ContentOutline({\n toc = false,\n locale = 'en',\n watch,\n children,\n}: {\n /** 内置左缘目录。默认关。无标题或宽度小于 768px 时也不显示。 */\n toc?: boolean;\n locale?: LocaleCode;\n /** 正文变化时重读标题,一般传 html 字符串。 */\n watch?: string;\n children: ReactNode;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n const [items, setItems] = useState<TocItem[]>([]);\n const mobile = useIsMobile(768);\n\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el || !toc) {\n setItems((prev) => (prev.length === 0 ? prev : []));\n return;\n }\n const read = () => {\n const next = readTocItems(el);\n setItems((prev) => (sameTocItems(prev, next) ? prev : next));\n };\n read();\n const observer = new MutationObserver(read);\n observer.observe(el, {\n childList: true,\n subtree: true,\n characterData: true,\n });\n return () => observer.disconnect();\n }, [toc, watch]);\n\n const root = ref.current;\n const show = toc && !mobile && items.length > 0 && root !== null;\n\n return (\n <div className={styles.editorHost}>\n {show && root ? (\n <EditorToc items={items} editorDom={root} locale={locale} />\n ) : null}\n <div ref={ref} className={show ? styles.withToc : undefined}>\n {children}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport type { LocaleCode } from '../i18n';\nimport {\n ReportContent,\n type ReportContentProps,\n} from '../ReportContent';\nimport { ContentOutline } from './ContentOutline';\n\nexport interface ReaderReportContentProps extends ReportContentProps {\n /**\n * 内置左缘目录(默认关闭)。传入后,有 `data-toc-id` 的标题时显示短横线,\n * 悬停展开,点击滚动。宽度小于 768px 时不显示。\n */\n toc?: boolean;\n /** 目录按钮的无障碍文案。默认英文。 */\n locale?: LocaleCode;\n}\n\n/**\n * `./reader` 的 ReportContent:静态 HTML 加上和编辑器同一套左缘目录。\n * `./server` 导出的同名组件仍是纯 HTML,没有这块界面。\n */\nexport function ReaderReportContent({\n html,\n className,\n toc = false,\n locale = 'en',\n ...rest\n}: ReaderReportContentProps) {\n return (\n <ContentOutline toc={toc} locale={locale} watch={html}>\n <ReportContent html={html} className={className} {...rest} />\n </ContentOutline>\n );\n}\n","'use client';\n\nimport { useRef, type ComponentProps } from 'react';\nimport type { OnCitationEnter, OnCitationLeave } from '../citationTypes';\nimport type { LocaleCode } from '../i18n';\nimport { ReportContent } from '../ReportContent';\nimport { CitationInteractive } from './CitationInteractive';\nimport { ReaderReportContent } from './ReaderReportContent';\n\nexport interface ReportContentInteractiveProps\n extends Omit<ComponentProps<typeof ReportContent>, 'ref'> {\n /** 点击圆标:宿主 setState 打开自己的 Popover。 */\n onCitationEnter: OnCitationEnter;\n /** 点外部 / 再点圆标 / Escape:宿主关闭。 */\n onCitationLeave: OnCitationLeave;\n /** 内置左缘目录,默认关闭。 */\n toc?: boolean;\n /** 目录按钮的无障碍文案。默认英文。 */\n locale?: LocaleCode;\n}\n\n/**\n * SSR HTML 阅读 + 脚注 click 委托的便捷封装。\n * 内部:`ReportContent` + `CitationInteractive`(只报事件,仅 click)。\n */\nexport function ReportContentInteractive({\n onCitationEnter,\n onCitationLeave,\n className,\n html,\n toc = false,\n locale = 'en',\n ...rest\n}: ReportContentInteractiveProps) {\n const ref = useRef<HTMLDivElement>(null);\n\n return (\n <div ref={ref} className={className}>\n <ReaderReportContent html={html} toc={toc} locale={locale} {...rest} />\n <CitationInteractive\n containerRef={ref}\n onCitationEnter={onCitationEnter}\n onCitationLeave={onCitationLeave}\n />\n </div>\n );\n}\n","'use client';\n\nimport type { Chart as ChartJs } from 'chart.js';\nimport { useEffect, useRef, type RefObject } from 'react';\nimport { parseChartFenceBody } from '../chart/parse';\nimport { destroyChart, renderOrUpdateChart } from '../chart/renderChart';\nimport type { ChartTheme } from '../chart/types';\nimport '../styles/chart.css';\n\nexport interface ChartMountProps {\n containerRef: RefObject<HTMLElement | null>;\n chartTheme?: ChartTheme | null;\n /** Re-scan when this changes (e.g. html string). */\n html?: string;\n}\n\nfunction hydrateOne(\n el: HTMLElement,\n theme: ChartTheme | null | undefined,\n registry: Map<HTMLElement, ChartJs>,\n) {\n const raw = el.getAttribute('data-chart');\n const payload = parseChartFenceBody(raw ?? '');\n if (!payload?.config.length) return;\n\n let host = el.querySelector('.tmr-chart-canvas-host') as HTMLElement | null;\n if (!host) {\n host = document.createElement('div');\n host.className = 'tmr-chart-canvas-host';\n el.appendChild(host);\n }\n host.classList.remove('tmr-chart-skeleton');\n\n let canvas = host.querySelector('canvas');\n if (!canvas) {\n canvas = document.createElement('canvas');\n host.innerHTML = '';\n host.appendChild(canvas);\n }\n\n const config = payload.config[0];\n const height = config.height ?? 320;\n host.style.height = `${height}px`;\n\n if (payload.config.length > 1 && !el.querySelector('.tmr-chart-tabs')) {\n const tabs = document.createElement('div');\n tabs.className = 'tmr-chart-tabs';\n tabs.setAttribute('role', 'tablist');\n payload.config.forEach((c, i) => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'tmr-chart-tab';\n btn.setAttribute('role', 'tab');\n btn.dataset.active = i === 0 ? 'true' : 'false';\n btn.textContent = c.title?.trim() || `${c.chartType} ${i + 1}`;\n btn.addEventListener('click', () => {\n tabs.querySelectorAll('.tmr-chart-tab').forEach((b, j) => {\n (b as HTMLElement).dataset.active = j === i ? 'true' : 'false';\n });\n const existing = registry.get(el);\n destroyChart(existing);\n const next = renderOrUpdateChart({\n canvas: canvas!,\n config: payload.config[i],\n payload,\n theme,\n chart: null,\n });\n if (next) registry.set(el, next);\n const titleEl = el.querySelector('.tmr-chart-title');\n if (titleEl && payload.config[i].title) {\n titleEl.textContent = String(payload.config[i].title);\n titleEl.classList.remove('tmr-chart-title--empty');\n }\n });\n tabs.appendChild(btn);\n });\n el.insertBefore(tabs, host);\n }\n\n const existing = registry.get(el);\n const chart = renderOrUpdateChart({\n canvas,\n config,\n payload,\n theme,\n chart: existing ?? null,\n });\n if (chart) registry.set(el, chart);\n}\n\n/**\n * Hydrate SSR chart placeholders inside a container (reading page).\n */\nexport function ChartMount({\n containerRef,\n chartTheme,\n html,\n}: ChartMountProps) {\n const registryRef = useRef(new Map<HTMLElement, ChartJs>());\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n const registry = registryRef.current;\n registry.forEach((chart) => destroyChart(chart));\n registry.clear();\n\n container\n .querySelectorAll<HTMLElement>('div[data-type=\"chart\"]')\n .forEach((el) => hydrateOne(el, chartTheme, registry));\n\n return () => {\n registry.forEach((chart) => destroyChart(chart));\n registry.clear();\n };\n }, [containerRef, chartTheme, html]);\n\n return null;\n}\n\n/** Imperative helper for hosts that prefer not to use the component. */\nexport function mountChartsInContainer(\n container: HTMLElement,\n chartTheme?: ChartTheme | null,\n): () => void {\n const registry = new Map<HTMLElement, ChartJs>();\n container\n .querySelectorAll<HTMLElement>('div[data-type=\"chart\"]')\n .forEach((el) => hydrateOne(el, chartTheme, registry));\n return () => {\n registry.forEach((c) => destroyChart(c));\n registry.clear();\n };\n}\n","'use client';\n\nimport { useRef, type ComponentProps } from 'react';\nimport type { ChartTheme } from '../chart/types';\nimport type { OnCitationEnter, OnCitationLeave } from '../citationTypes';\nimport type { LocaleCode } from '../i18n';\nimport { ReportContent } from '../ReportContent';\nimport { ChartMount } from './ChartMount';\nimport { CitationInteractive } from './CitationInteractive';\nimport { ReaderReportContent } from './ReaderReportContent';\n\nexport interface ReportContentWithChartsProps\n extends Omit<ComponentProps<typeof ReportContent>, 'ref'> {\n onCitationEnter?: OnCitationEnter;\n onCitationLeave?: OnCitationLeave;\n chartTheme?: ChartTheme | null;\n /** 内置左缘目录,默认关闭。 */\n toc?: boolean;\n /** 目录按钮的无障碍文案。默认英文。 */\n locale?: LocaleCode;\n}\n\n/**\n * SSR HTML reading surface with Chart.js hydration (+ optional citation clicks).\n */\nexport function ReportContentWithCharts({\n onCitationEnter,\n onCitationLeave,\n chartTheme,\n className,\n html,\n toc = false,\n locale = 'en',\n ...rest\n}: ReportContentWithChartsProps) {\n const ref = useRef<HTMLDivElement>(null);\n\n return (\n <div ref={ref} className={className}>\n <ReaderReportContent html={html} toc={toc} locale={locale} {...rest} />\n <ChartMount\n containerRef={ref}\n chartTheme={chartTheme}\n html={html}\n />\n {onCitationEnter && onCitationLeave ? (\n <CitationInteractive\n containerRef={ref}\n onCitationEnter={onCitationEnter}\n onCitationLeave={onCitationLeave}\n />\n ) : null}\n </div>\n );\n}\n"],"names":["_a","item","id","rail","styles","existing"],"mappings":"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"}