tiptap-markdown-react 0.17.0 → 0.18.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/README.md +75 -3
- package/dist/{ReportContent-CwcppHl8.js → ReportContent-MgbebxPV.js} +8 -8
- package/dist/{ReportContent-CwcppHl8.js.map → ReportContent-MgbebxPV.js.map} +1 -1
- package/dist/components/EditorToolbar.d.ts +12 -1
- package/dist/components/EditorToolbar.dom.test.d.ts +1 -0
- package/dist/components/FindReplaceBar.d.ts +0 -7
- package/dist/components/LinkPopover.d.ts +28 -0
- package/dist/components/LinkPopover.dom.test.d.ts +1 -0
- package/dist/components/MarkdownWysiwygEditor.d.ts +12 -0
- package/dist/components/TableHandles.d.ts +19 -0
- package/dist/components/TableHandles.dom.test.d.ts +1 -0
- package/dist/components/findEntry.dom.test.d.ts +1 -0
- package/dist/{extractToc-CheLC9kh.js → extractToc-BaR6LP1f.js} +42 -4
- package/dist/extractToc-BaR6LP1f.js.map +1 -0
- package/dist/findReplace.d.ts +18 -4
- package/dist/icons/index.d.ts +6 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1320 -608
- package/dist/index.js.map +1 -1
- package/dist/labels.d.ts +41 -1
- package/dist/linkEditing.d.ts +45 -0
- package/dist/linkEditing.test.d.ts +1 -0
- package/dist/placeholder.test.d.ts +1 -0
- package/dist/reader.js +2 -2
- package/dist/{scrollToTocHeading-CBvptTaQ.js → scrollToTocHeading-BTQWajGD.js} +2 -2
- package/dist/{scrollToTocHeading-CBvptTaQ.js.map → scrollToTocHeading-BTQWajGD.js.map} +1 -1
- package/dist/server.js +4 -4
- package/dist/style-inline.css +398 -174
- package/dist/style.css +398 -174
- package/dist/supSubMarkdown.test.d.ts +1 -0
- package/dist/supSubServer.test.d.ts +1 -0
- package/dist/tableSelection.d.ts +25 -5
- package/package.json +1 -1
- package/dist/extractToc-CheLC9kh.js.map +0 -1
package/dist/labels.d.ts
CHANGED
|
@@ -25,7 +25,18 @@ export interface ToolbarLabels {
|
|
|
25
25
|
superscript: string;
|
|
26
26
|
subscript: string;
|
|
27
27
|
link: string;
|
|
28
|
+
/**
|
|
29
|
+
* 链接浮层输入框的占位与无障碍名(原 `window.prompt` 的提示语,现在落到输入框上)。
|
|
30
|
+
*/
|
|
28
31
|
linkPrompt: string;
|
|
32
|
+
/** 链接浮层「应用」按钮的 title / aria-label。 */
|
|
33
|
+
linkApply: string;
|
|
34
|
+
/** 链接浮层「在新窗口打开」按钮的 title / aria-label。 */
|
|
35
|
+
linkOpen: string;
|
|
36
|
+
/** 链接浮层「移除链接」按钮的 title / aria-label。 */
|
|
37
|
+
linkRemove: string;
|
|
38
|
+
/** 链接浮层:地址被编辑器拒绝时的提示(落在输入框 title 上)。 */
|
|
39
|
+
linkInvalid: string;
|
|
29
40
|
image: string;
|
|
30
41
|
imageUploadFailed: string;
|
|
31
42
|
/** Markdown 文件导入失败(与图片上传共用 onError 回调时,便于宿主区分文案)。 */
|
|
@@ -49,11 +60,29 @@ export interface ToolbarLabels {
|
|
|
49
60
|
orderedList: string;
|
|
50
61
|
taskList: string;
|
|
51
62
|
more: string;
|
|
63
|
+
/**
|
|
64
|
+
* 工具栏的搜索入口(放大镜按钮,落在 More 之后):title 与 aria-label。
|
|
65
|
+
* 只在宿主传了 `onSearch` 时才渲染——它只是入口,条子本身归编辑器
|
|
66
|
+
* (`<MarkdownWysiwygEditor>`),点击后由宿主调 `handle.openFind()`。
|
|
67
|
+
*/
|
|
68
|
+
search: string;
|
|
52
69
|
codeBlock: string;
|
|
53
70
|
hr: string;
|
|
54
71
|
/** 导入下拉里的 Markdown 项。 */
|
|
55
72
|
importMarkdown: string;
|
|
56
73
|
tableInsert: string;
|
|
74
|
+
/** 行手柄的 title / aria-label(鼠标悬停单元格时出现在行的左缘)。 */
|
|
75
|
+
tableRowMenu: string;
|
|
76
|
+
/** 列手柄的 title / aria-label(悬停时出现在表格上方、对齐该列)。 */
|
|
77
|
+
tableColumnMenu: string;
|
|
78
|
+
/** 表格菜单:清空选中行 / 列 / 单元格矩形里的内容(保留单元格与表头)。 */
|
|
79
|
+
tableClearContent: string;
|
|
80
|
+
/** 表格菜单:把选中单元格的样式属性复位(列宽、对齐等;不动合并结构)。 */
|
|
81
|
+
tableResetCellStyles: string;
|
|
82
|
+
/** 表格底边 `+` 手柄(末尾追加一行)的 title / aria-label。 */
|
|
83
|
+
tableAppendRow: string;
|
|
84
|
+
/** 表格右边 `+` 手柄(末尾追加一列)的 title / aria-label。 */
|
|
85
|
+
tableAppendColumn: string;
|
|
57
86
|
/** 网格选择器底部尺寸文案,如 "3 × 4"。参数顺序:列、行。 */
|
|
58
87
|
tableSizeSelected: (cols: number, rows: number) => string;
|
|
59
88
|
tableAddColumnBefore: string;
|
|
@@ -152,6 +181,17 @@ export interface ShortcutLabels {
|
|
|
152
181
|
findReplace: string;
|
|
153
182
|
}
|
|
154
183
|
export declare const defaultShortcutLabels: ShortcutLabels;
|
|
184
|
+
/** 链接编辑浮层(`<LinkPopover>`)文案。 */
|
|
185
|
+
export interface LinkPopoverLabels {
|
|
186
|
+
/** 输入框占位与无障碍名,也是浮层的 aria-label。 */
|
|
187
|
+
field: string;
|
|
188
|
+
apply: string;
|
|
189
|
+
open: string;
|
|
190
|
+
remove: string;
|
|
191
|
+
/** 地址被编辑器拒绝时的提示(落在输入框 title 上)。 */
|
|
192
|
+
invalid: string;
|
|
193
|
+
}
|
|
194
|
+
export declare const defaultLinkPopoverLabels: LinkPopoverLabels;
|
|
155
195
|
export interface ColorPaletteLabels {
|
|
156
196
|
none: string;
|
|
157
197
|
theme: string;
|
|
@@ -197,7 +237,7 @@ export interface FindLabels {
|
|
|
197
237
|
caseSensitive: string;
|
|
198
238
|
wholeWord: string;
|
|
199
239
|
useRegex: string;
|
|
200
|
-
/** 计数文案。无结果时 current 传 0。 */
|
|
240
|
+
/** 计数文案。无结果时 current 传 0;有结果但还没定位到某一条(currentIndex 为 null)时也是 0。 */
|
|
201
241
|
counter: (current: number, total: number) => string;
|
|
202
242
|
/** 正则模式下模式非法(RE2 不支持 lookaround / backreference 等,见官方扩展)。 */
|
|
203
243
|
invalidRegex: string;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Editor } from '@tiptap/react';
|
|
2
|
+
/** 链接可编辑吗:只读态、或当前选区不允许套 link mark(例如整块选中)时为 false。 */
|
|
3
|
+
export declare function canSetLink(editor: Editor | null | undefined): boolean;
|
|
4
|
+
/** 光标 / 选区是否落在链接里。 */
|
|
5
|
+
export declare function isLinkActive(editor: Editor | null | undefined): boolean;
|
|
6
|
+
/** 读当前链接的 href(不在链接里时是空串)。 */
|
|
7
|
+
export declare function readLinkHref(editor: Editor | null | undefined): string;
|
|
8
|
+
/**
|
|
9
|
+
* 把用户输入整理成要存进 href 的值。
|
|
10
|
+
*
|
|
11
|
+
* 原样保留:空、站内相对地址(`/docs`、`#sec`、`?q=1`)、已带协议的(`https:`、`mailto:`)。
|
|
12
|
+
* 补协议:裸域名(`example.com`、`example.com/a`)与主机:端口(`localhost:3000`)——补的是
|
|
13
|
+
* 扩展配置的 `defaultProtocol`,与 Tiptap 自动链接同一套,避免手打和粘贴落到不同地址。
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizeLinkHref(editor: Editor, raw: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* 应用链接:把地址套到**整条**链接(或选区)上;选区为空且原本不在链接里时,把地址当文本插进去。
|
|
18
|
+
* 返回扩展是否接受了这个地址——`setLink` 会走 Tiptap 的 `isAllowedUri`。
|
|
19
|
+
*
|
|
20
|
+
* 两处与官方那版不同,都是单测逼出来的:
|
|
21
|
+
* 1. 先 `can().setLink()` 干跑一遍。官方把 `insertContent` 挂在失败的 `setLink` 后面直接
|
|
22
|
+
* `run()`,结果是地址被拒时正文仍被改(链接文字被换成那个地址)。
|
|
23
|
+
* 2. 「当文本插入」的判据是「选区为空**且光标不在已有链接里**」。官方只看选区是否为空,
|
|
24
|
+
* 于是「光标在链接里、改一个地址」会把整条链接的文字替换成地址——而这正是这个浮层的主用途。
|
|
25
|
+
*/
|
|
26
|
+
export declare function applyLink(editor: Editor | null | undefined, raw: string): boolean;
|
|
27
|
+
/** 移除链接:范围同样扩到整条,并挡住自动链接立刻加回来。 */
|
|
28
|
+
export declare function removeLink(editor: Editor | null | undefined): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* 把待打开的地址解析成绝对地址;解析不了、或协议不在白名单里时返回 `'#'` 表示「别打开」。
|
|
31
|
+
*
|
|
32
|
+
* 与官方 `sanitizeUrl(inputUrl, baseUrl)` 同语义:先按 base 解析成绝对地址(相对地址因此也
|
|
33
|
+
* 能用),再查协议白名单。调用方拿到 `'#'` 就不开新窗口。
|
|
34
|
+
*/
|
|
35
|
+
export declare function sanitizeLinkUrl(input: string, baseUrl: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* 打开地址(新窗口 + `noopener,noreferrer`)。空输入或非法地址都不开窗——调用方在此之前
|
|
38
|
+
* 已经用 `sanitizeLinkUrl` 判过一次,这里再判一次是为了让这个入口单独用也安全。
|
|
39
|
+
*/
|
|
40
|
+
export declare function openLinkUrl(input: string, baseUrl: string): boolean;
|
|
41
|
+
/** 输入框的回车是否该当作「应用」(输入法组合中的回车是提交候选词,放行)。 */
|
|
42
|
+
export declare function isApplyKey(event: {
|
|
43
|
+
key: string;
|
|
44
|
+
nativeEvent: Pick<KeyboardEvent, 'isComposing' | 'keyCode'>;
|
|
45
|
+
}): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/reader.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { C, a, R, b, f, m, r, s } from "./scrollToTocHeading-
|
|
3
|
-
import { R as R2, a as a2, e, b as b2 } from "./ReportContent-
|
|
2
|
+
import { C, a, R, b, f, m, r, s } from "./scrollToTocHeading-BTQWajGD.js";
|
|
3
|
+
import { R as R2, a as a2, e, b as b2 } from "./ReportContent-MgbebxPV.js";
|
|
4
4
|
export {
|
|
5
5
|
C as ChartMount,
|
|
6
6
|
a as CitationInteractive,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
3
|
import { useRef, useEffect } from "react";
|
|
4
|
-
import { R as ReportContent, p as parseChartFenceBody } from "./ReportContent-
|
|
4
|
+
import { R as ReportContent, p as parseChartFenceBody } from "./ReportContent-MgbebxPV.js";
|
|
5
5
|
import { Chart, CategoryScale, LinearScale, PointElement, LineElement, BarElement, ArcElement, LineController, BarController, PieController, DoughnutController, Filler, Legend, Tooltip } from "chart.js";
|
|
6
6
|
function toNumber(value) {
|
|
7
7
|
if (typeof value === "number" && !Number.isNaN(value)) return value;
|
|
@@ -493,4 +493,4 @@ export {
|
|
|
493
493
|
readCitationAttrs as r,
|
|
494
494
|
scrollToTocHeading as s
|
|
495
495
|
};
|
|
496
|
-
//# sourceMappingURL=scrollToTocHeading-
|
|
496
|
+
//# sourceMappingURL=scrollToTocHeading-BTQWajGD.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scrollToTocHeading-CBvptTaQ.js","sources":["../src/chart/mapData.ts","../src/chart/theme.ts","../src/chart/renderChart.ts","../src/citationDom.ts","../src/components/CitationInteractive.tsx","../src/components/ReportContentInteractive.tsx","../src/components/ChartMount.tsx","../src/components/ReportContentWithCharts.tsx","../src/toc/scrollToTocHeading.ts"],"sourcesContent":["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 * 从事件目标向上找到 `.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 { useRef, type ComponentProps } from 'react';\nimport type { OnCitationEnter, OnCitationLeave } from '../citationTypes';\nimport { ReportContent } from '../ReportContent';\nimport { CitationInteractive } from './CitationInteractive';\n\nexport interface ReportContentInteractiveProps\n extends Omit<ComponentProps<typeof ReportContent>, 'ref'> {\n /** 点击圆标:宿主 setState 打开自己的 Popover。 */\n onCitationEnter: OnCitationEnter;\n /** 点外部 / 再点圆标 / Escape:宿主关闭。 */\n onCitationLeave: OnCitationLeave;\n}\n\n/**\n * SSR HTML 阅读 + 脚注 click 委托的便捷封装。\n * 内部:`ReportContent` + `CitationInteractive`(只报事件,仅 click)。\n */\nexport function ReportContentInteractive({\n onCitationEnter,\n onCitationLeave,\n className,\n html,\n ...rest\n}: ReportContentInteractiveProps) {\n const ref = useRef<HTMLDivElement>(null);\n\n return (\n <div ref={ref} className={className}>\n <ReportContent html={html} {...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 { ReportContent } from '../ReportContent';\nimport { ChartMount } from './ChartMount';\nimport { CitationInteractive } from './CitationInteractive';\n\nexport interface ReportContentWithChartsProps\n extends Omit<ComponentProps<typeof ReportContent>, 'ref'> {\n onCitationEnter?: OnCitationEnter;\n onCitationLeave?: OnCitationLeave;\n chartTheme?: ChartTheme | null;\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 ...rest\n}: ReportContentWithChartsProps) {\n const ref = useRef<HTMLDivElement>(null);\n\n return (\n <div ref={ref} className={className}>\n <ReportContent html={html} {...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","/**\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"],"names":["existing"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"scrollToTocHeading-BTQWajGD.js","sources":["../src/chart/mapData.ts","../src/chart/theme.ts","../src/chart/renderChart.ts","../src/citationDom.ts","../src/components/CitationInteractive.tsx","../src/components/ReportContentInteractive.tsx","../src/components/ChartMount.tsx","../src/components/ReportContentWithCharts.tsx","../src/toc/scrollToTocHeading.ts"],"sourcesContent":["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 * 从事件目标向上找到 `.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 { useRef, type ComponentProps } from 'react';\nimport type { OnCitationEnter, OnCitationLeave } from '../citationTypes';\nimport { ReportContent } from '../ReportContent';\nimport { CitationInteractive } from './CitationInteractive';\n\nexport interface ReportContentInteractiveProps\n extends Omit<ComponentProps<typeof ReportContent>, 'ref'> {\n /** 点击圆标:宿主 setState 打开自己的 Popover。 */\n onCitationEnter: OnCitationEnter;\n /** 点外部 / 再点圆标 / Escape:宿主关闭。 */\n onCitationLeave: OnCitationLeave;\n}\n\n/**\n * SSR HTML 阅读 + 脚注 click 委托的便捷封装。\n * 内部:`ReportContent` + `CitationInteractive`(只报事件,仅 click)。\n */\nexport function ReportContentInteractive({\n onCitationEnter,\n onCitationLeave,\n className,\n html,\n ...rest\n}: ReportContentInteractiveProps) {\n const ref = useRef<HTMLDivElement>(null);\n\n return (\n <div ref={ref} className={className}>\n <ReportContent html={html} {...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 { ReportContent } from '../ReportContent';\nimport { ChartMount } from './ChartMount';\nimport { CitationInteractive } from './CitationInteractive';\n\nexport interface ReportContentWithChartsProps\n extends Omit<ComponentProps<typeof ReportContent>, 'ref'> {\n onCitationEnter?: OnCitationEnter;\n onCitationLeave?: OnCitationLeave;\n chartTheme?: ChartTheme | null;\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 ...rest\n}: ReportContentWithChartsProps) {\n const ref = useRef<HTMLDivElement>(null);\n\n return (\n <div ref={ref} className={className}>\n <ReportContent html={html} {...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","/**\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"],"names":["existing"],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { s as stabilizeMarkdown, p as prepareChartMarkdown, b as baseExtensions, a as pureCodeBlock, c as pureImage, d as pureChart, C as CitationRef, m as makeTocGetId, r as renderMathElementHtml, e as extractToc } from "./extractToc-
|
|
2
|
-
import { f, g, l, h, i, j } from "./extractToc-
|
|
3
|
-
import { a as applyCitationSources } from "./ReportContent-
|
|
4
|
-
import { R, e, s } from "./ReportContent-
|
|
1
|
+
import { s as stabilizeMarkdown, p as prepareChartMarkdown, b as baseExtensions, a as pureCodeBlock, c as pureImage, d as pureChart, C as CitationRef, m as makeTocGetId, r as renderMathElementHtml, e as extractToc } from "./extractToc-BaR6LP1f.js";
|
|
2
|
+
import { f, g, l, h, i, j } from "./extractToc-BaR6LP1f.js";
|
|
3
|
+
import { a as applyCitationSources } from "./ReportContent-MgbebxPV.js";
|
|
4
|
+
import { R, e, s } from "./ReportContent-MgbebxPV.js";
|
|
5
5
|
import { TableOfContents, generateTocIds } from "@tiptap/extension-table-of-contents";
|
|
6
6
|
import { MarkdownManager } from "@tiptap/markdown";
|
|
7
7
|
import { renderToHTMLString } from "@tiptap/static-renderer";
|