tiptap-markdown-react 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CitationRef.d.ts +26 -0
- package/dist/CitationRef.test.d.ts +1 -0
- package/dist/citationDom.d.ts +11 -0
- package/dist/citationDom.test.d.ts +1 -0
- package/dist/citationTypes.d.ts +31 -0
- package/dist/citationUtils.d.ts +23 -0
- package/dist/citationUtils.test.d.ts +1 -0
- package/dist/components/CitationInteractive.d.ts +35 -0
- package/dist/components/CitationRefView.d.ts +6 -0
- package/dist/components/MarkdownPreview.d.ts +13 -1
- package/dist/components/MarkdownWysiwygEditor.d.ts +12 -0
- package/dist/components/ReportContentInteractive.d.ts +13 -0
- package/dist/createCitationRef.d.ts +12 -0
- package/dist/extensions.d.ts +8 -8
- package/dist/extractToc-DW6HOiGt.js +253 -0
- package/dist/extractToc-DW6HOiGt.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +276 -96
- package/dist/index.js.map +1 -1
- package/dist/insertMarkdown.d.ts +6 -2
- package/dist/renderReportHtml.d.ts +11 -1
- package/dist/server.d.ts +3 -1
- package/dist/server.js +23 -7
- package/dist/server.js.map +1 -1
- package/dist/style.css +87 -32
- package/package.json +6 -2
- package/dist/extractToc-C7e1DuVc.js +0 -97
- package/dist/extractToc-C7e1DuVc.js.map +0 -1
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Node } from '@tiptap/core';
|
|
2
|
+
export interface CitationRefOptions {
|
|
3
|
+
HTMLAttributes: Record<string, unknown>;
|
|
4
|
+
}
|
|
5
|
+
declare module '@tiptap/core' {
|
|
6
|
+
interface Commands<ReturnType> {
|
|
7
|
+
citationRef: {
|
|
8
|
+
insertCitationRef: (attrs: {
|
|
9
|
+
index: string;
|
|
10
|
+
url?: string | null;
|
|
11
|
+
title?: string | null;
|
|
12
|
+
}) => ReturnType;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 脚注/引文引用——inline atom 节点。
|
|
18
|
+
*
|
|
19
|
+
* - 输入:`[^n]`(markdownTokenizer)或 `<span class="citation-ref">`(parseHTML)
|
|
20
|
+
* - 输出 HTML:居中圆形 pill(CSS `.citation-ref`),**不是**上下标
|
|
21
|
+
* - 输出 markdown:`[^n]`
|
|
22
|
+
*
|
|
23
|
+
* Popover /「原文片段」由消费方通过 {@link createCitationRef} 的 `renderCitation`
|
|
24
|
+
* 插槽完成;本节点只负责标记与默认圆标样式。
|
|
25
|
+
*/
|
|
26
|
+
export declare const CitationRef: Node<CitationRefOptions, any>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 从事件目标向上找到 `.citation-ref`(且必须在 root 内)。
|
|
3
|
+
* SSR 阅读页事件委托与单测共用。
|
|
4
|
+
*/
|
|
5
|
+
export declare function findCitationRefElement(target: EventTarget | null, root: ParentNode): HTMLElement | null;
|
|
6
|
+
/** 从圆标 DOM 读取 attrs(与 CitationRef renderHTML 的 data-* 对齐)。 */
|
|
7
|
+
export declare function readCitationAttrs(el: HTMLElement): {
|
|
8
|
+
index: string;
|
|
9
|
+
url: string | null;
|
|
10
|
+
title: string | null;
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
/** 脚注圆标 NodeView 插槽上下文——数据源查找 / Popover 由消费方完成。 */
|
|
3
|
+
export interface RenderCitationContext {
|
|
4
|
+
/** 与 markdown `[^n]` 中的 n 对齐。 */
|
|
5
|
+
index: string;
|
|
6
|
+
attrs: {
|
|
7
|
+
index: string;
|
|
8
|
+
url?: string | null;
|
|
9
|
+
title?: string | null;
|
|
10
|
+
};
|
|
11
|
+
/** 库默认圆标 DOM;消费方通常用 Popover 包住它。 */
|
|
12
|
+
defaultDom: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export type RenderCitation = (ctx: RenderCitationContext) => ReactNode;
|
|
15
|
+
/**
|
|
16
|
+
* SSR 阅读页增强插槽:在已有 `.citation-ref` DOM 上挂宿主浮层。
|
|
17
|
+
* 与 {@link RenderCitation} 同构(按 index 查数据),输入是锚点元素而非 defaultDom。
|
|
18
|
+
*/
|
|
19
|
+
export interface RenderCitationInteractiveContext {
|
|
20
|
+
index: string;
|
|
21
|
+
attrs: {
|
|
22
|
+
index: string;
|
|
23
|
+
url?: string | null;
|
|
24
|
+
title?: string | null;
|
|
25
|
+
};
|
|
26
|
+
/** 被激活的圆标 DOM,供 Popover 锚定定位。 */
|
|
27
|
+
anchorEl: HTMLElement;
|
|
28
|
+
/** 关闭浮层。 */
|
|
29
|
+
close: () => void;
|
|
30
|
+
}
|
|
31
|
+
export type RenderCitationInteractive = (ctx: RenderCitationInteractiveContext) => ReactNode;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { JSONContent } from '@tiptap/core';
|
|
2
|
+
export interface SourceRef {
|
|
3
|
+
/** 与 markdown `[^n]` 中的 n 对齐(字符串,如 `"1"`)。 */
|
|
4
|
+
index: string;
|
|
5
|
+
url?: string;
|
|
6
|
+
title?: string;
|
|
7
|
+
/** 原文片段等;库本身不渲染 Popover,留给消费方。 */
|
|
8
|
+
excerpt?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 将 markdown 中能匹配到 `sources` 的 `[^n]` 换成带 data-* 的
|
|
12
|
+
* `<span class="citation-ref">`(**不是** `<sup>`,避免被 Superscript 吃掉、
|
|
13
|
+
* 也避免视觉上标)。未匹配的 `[^n]` 原样保留,留给 CitationRef tokenizer。
|
|
14
|
+
*
|
|
15
|
+
* 浏览器端 @tiptap/markdown 可解析内联 HTML;server 端无 DOMParser 时请改用
|
|
16
|
+
* {@link applyCitationSources}(先 parse 再补 attrs)。
|
|
17
|
+
*/
|
|
18
|
+
export declare function enrichMarkdownCitations(markdown: string, sources: SourceRef[]): string;
|
|
19
|
+
/**
|
|
20
|
+
* 在已 parse 的 Tiptap JSON 上,按 `sources` 给 `citationRef` 节点补 url/title。
|
|
21
|
+
* SSR / 无 DOMParser 环境的首选路径。
|
|
22
|
+
*/
|
|
23
|
+
export declare function applyCitationSources(doc: JSONContent, sources: SourceRef[]): JSONContent;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
import { RenderCitationInteractive } from '../citationTypes';
|
|
3
|
+
export interface CitationInteractiveProps {
|
|
4
|
+
/**
|
|
5
|
+
* 包含 `ReportContent` HTML 的根节点(其内应有 `.citation-ref`)。
|
|
6
|
+
* 用同一 ref 包住 ReportContent 即可。
|
|
7
|
+
*/
|
|
8
|
+
containerRef: RefObject<HTMLElement | null>;
|
|
9
|
+
/**
|
|
10
|
+
* 激活圆标时调用。宿主用 `anchorEl` + `index` 渲染 Popover;
|
|
11
|
+
* 数据源完全由宿主持有。
|
|
12
|
+
*/
|
|
13
|
+
renderCitation: RenderCitationInteractive;
|
|
14
|
+
/** 默认 click;hover 适合桌面预览。 */
|
|
15
|
+
trigger?: 'click' | 'hover';
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* SSR 阅读页脚注增强:在静态 HTML 圆标上事件委托,把 `index` + `anchorEl`
|
|
19
|
+
* 交给宿主 `renderCitation`(与编辑器 NodeView 插槽同构,挂载方式不同)。
|
|
20
|
+
*
|
|
21
|
+
* 用法:
|
|
22
|
+
* ```tsx
|
|
23
|
+
* const ref = useRef<HTMLDivElement>(null);
|
|
24
|
+
* <div ref={ref}>
|
|
25
|
+
* <ReportContent html={html} />
|
|
26
|
+
* <CitationInteractive
|
|
27
|
+
* containerRef={ref}
|
|
28
|
+
* renderCitation={({ index, anchorEl, close }) => (
|
|
29
|
+
* <Popover anchorEl={anchorEl} onClose={close}>…</Popover>
|
|
30
|
+
* )}
|
|
31
|
+
* />
|
|
32
|
+
* </div>
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function CitationInteractive({ containerRef, renderCitation, trigger, }: CitationInteractiveProps): import("react").JSX.Element | null;
|
|
@@ -1,6 +1,18 @@
|
|
|
1
|
+
import { SourceRef } from '../citationUtils';
|
|
2
|
+
import { RenderCitation } from '../citationTypes';
|
|
1
3
|
export interface MarkdownPreviewProps {
|
|
2
4
|
/** 要预览的 markdown 字符串。 */
|
|
3
5
|
markdown: string;
|
|
6
|
+
/**
|
|
7
|
+
* 脚注来源列表:按 `index` 与正文 `[^n]` 对齐,写入节点的 url/title。
|
|
8
|
+
* 业务数据与 Popover 仍由消费方通过 {@link renderCitation} 完成。
|
|
9
|
+
*/
|
|
10
|
+
sources?: SourceRef[];
|
|
11
|
+
/**
|
|
12
|
+
* 脚注圆标 NodeView 插槽。用 Popover 等包住 `defaultDom`;
|
|
13
|
+
* 用 `index` / `attrs` 查消费方自己的数据源。
|
|
14
|
+
*/
|
|
15
|
+
renderCitation?: RenderCitation;
|
|
4
16
|
className?: string;
|
|
5
17
|
}
|
|
6
18
|
/**
|
|
@@ -11,4 +23,4 @@ export interface MarkdownPreviewProps {
|
|
|
11
23
|
* 这是「客户端只读预览」;若需 SEO / 无 JS 静态渲染,请改用 server 入口的
|
|
12
24
|
* renderReportHtml + ReportContent。
|
|
13
25
|
*/
|
|
14
|
-
export declare function MarkdownPreview({ markdown, className }: MarkdownPreviewProps): import("react").JSX.Element;
|
|
26
|
+
export declare function MarkdownPreview({ markdown, sources, renderCitation, className, }: MarkdownPreviewProps): import("react").JSX.Element;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { AnyExtension, Editor } from '@tiptap/react';
|
|
2
|
+
import { SourceRef } from '../citationUtils';
|
|
3
|
+
import { RenderCitation } from '../citationTypes';
|
|
2
4
|
import { CodeBlockLabels } from '../labels';
|
|
3
5
|
import { TocItem } from '../toc/extractToc';
|
|
4
6
|
export interface MarkdownWysiwygEditorHandle {
|
|
@@ -14,6 +16,16 @@ export interface MarkdownWysiwygEditorHandle {
|
|
|
14
16
|
export interface MarkdownWysiwygEditorProps {
|
|
15
17
|
/** 初始 markdown 内容。 */
|
|
16
18
|
initialMarkdown?: string;
|
|
19
|
+
/**
|
|
20
|
+
* 初始脚注来源:按 index 对齐 `[^n]`,写入 citationRef 的 url/title。
|
|
21
|
+
* 仅影响初始 content;后续插入请用 `insertMarkdown(editor, md, sources)`。
|
|
22
|
+
*/
|
|
23
|
+
sources?: SourceRef[];
|
|
24
|
+
/**
|
|
25
|
+
* 脚注圆标 NodeView 插槽。消费方用 Popover 包住 `defaultDom`,
|
|
26
|
+
* 用 `index` 查自己的数据源。仅初始化时生效。
|
|
27
|
+
*/
|
|
28
|
+
renderCitation?: RenderCitation;
|
|
17
29
|
placeholder?: string;
|
|
18
30
|
/** editor 实例就绪 / 销毁时回调,供外部工具栏使用。 */
|
|
19
31
|
onEditorReady?: (editor: Editor | null) => void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ComponentProps } from 'react';
|
|
2
|
+
import { RenderCitationInteractive } from '../citationTypes';
|
|
3
|
+
import { ReportContent } from '../ReportContent';
|
|
4
|
+
export interface ReportContentInteractiveProps extends Omit<ComponentProps<typeof ReportContent>, 'ref'> {
|
|
5
|
+
/** 与编辑器 `renderCitation` 同构:按 index 查数据、渲染 Popover。 */
|
|
6
|
+
renderCitation: RenderCitationInteractive;
|
|
7
|
+
trigger?: 'click' | 'hover';
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* SSR HTML 阅读 + 脚注交互的便捷封装。
|
|
11
|
+
* 内部:`ReportContent`(静态 HTML)+ `CitationInteractive`(事件委托)。
|
|
12
|
+
*/
|
|
13
|
+
export declare function ReportContentInteractive({ renderCitation, trigger, className, html, ...rest }: ReportContentInteractiveProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CitationRefOptions } from './CitationRef';
|
|
2
|
+
import { RenderCitation } from './citationTypes';
|
|
3
|
+
export type CitationRefViewOptions = CitationRefOptions & {
|
|
4
|
+
renderCitation?: RenderCitation;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* 客户端增强版 CitationRef:挂 React NodeView,支持 `renderCitation` 插槽。
|
|
8
|
+
* server / SSR 请继续用纯 {@link CitationRef}(无 React)。
|
|
9
|
+
*/
|
|
10
|
+
export declare function createCitationRef(options?: {
|
|
11
|
+
renderCitation?: RenderCitation;
|
|
12
|
+
}): import('@tiptap/core').Node<CitationRefViewOptions, any>;
|
package/dist/extensions.d.ts
CHANGED
|
@@ -9,11 +9,11 @@ import { AnyExtension } from '@tiptap/react';
|
|
|
9
9
|
* 分层动机:交互增强依赖 @tiptap/react / 浏览器,会污染 server bundle(RSC)。
|
|
10
10
|
* base 保持纯 schema,server import 它只引入节点定义,无 React 代码。
|
|
11
11
|
*
|
|
12
|
-
* 关键边界:CodeBlock
|
|
13
|
-
*
|
|
14
|
-
* 改为:base
|
|
15
|
-
* -
|
|
16
|
-
* - server /
|
|
12
|
+
* 关键边界:CodeBlock / Image / CitationRef「会被客户端增强」,**不放进 base**——
|
|
13
|
+
* 否则编辑器追加增强版会与 base 的纯版同名冲突(Tiptap 报 "Duplicate extension names")。
|
|
14
|
+
* 改为:base 不含这三类,由调用方按需注入:
|
|
15
|
+
* - 编辑器 / 预览注入「增强版」(React NodeView)
|
|
16
|
+
* - server 注入「纯版」(pureCodeBlock / pureImage / CitationRef)
|
|
17
17
|
*/
|
|
18
18
|
export declare const lowlight: {
|
|
19
19
|
highlight: (language: string, value: string, options?: Readonly<import('lowlight').Options> | null | undefined) => import('hast').Root;
|
|
@@ -38,8 +38,8 @@ export declare const pureCodeBlock: import('@tiptap/core').Node<import('@tiptap/
|
|
|
38
38
|
*/
|
|
39
39
|
export declare const pureImage: import('@tiptap/core').Node<import('@tiptap/extension-image').ImageOptions, any>;
|
|
40
40
|
/**
|
|
41
|
-
* 三处共用的纯 schema 扩展——**不含 CodeBlock / Image**(见上方边界说明)。
|
|
42
|
-
* 编辑器:`[...baseExtensions, 增强CodeBlock, 增强Image, Markdown]`
|
|
43
|
-
* server/预览:`[...baseExtensions, pureCodeBlock, pureImage,
|
|
41
|
+
* 三处共用的纯 schema 扩展——**不含 CodeBlock / Image / CitationRef**(见上方边界说明)。
|
|
42
|
+
* 编辑器:`[...baseExtensions, 增强CodeBlock, 增强Image, createCitationRef(), Markdown]`
|
|
43
|
+
* server/预览:`[...baseExtensions, pureCodeBlock, pureImage, CitationRef, …]`
|
|
44
44
|
*/
|
|
45
45
|
export declare const baseExtensions: AnyExtension[];
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { Node, mergeAttributes } from "@tiptap/core";
|
|
2
|
+
import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
|
|
3
|
+
import Highlight from "@tiptap/extension-highlight";
|
|
4
|
+
import Image from "@tiptap/extension-image";
|
|
5
|
+
import Subscript from "@tiptap/extension-subscript";
|
|
6
|
+
import Superscript from "@tiptap/extension-superscript";
|
|
7
|
+
import { TableKit } from "@tiptap/extension-table";
|
|
8
|
+
import TaskItem from "@tiptap/extension-task-item";
|
|
9
|
+
import TaskList from "@tiptap/extension-task-list";
|
|
10
|
+
import { TextStyle, Color, FontSize } from "@tiptap/extension-text-style";
|
|
11
|
+
import StarterKit from "@tiptap/starter-kit";
|
|
12
|
+
import { createLowlight, common } from "lowlight";
|
|
13
|
+
import { jsx } from "react/jsx-runtime";
|
|
14
|
+
function escapeAttr(value) {
|
|
15
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
16
|
+
}
|
|
17
|
+
function enrichMarkdownCitations(markdown, sources) {
|
|
18
|
+
if (!sources.length) return markdown;
|
|
19
|
+
return markdown.replace(/\[\^(\d+)\]/g, (match, num) => {
|
|
20
|
+
const source = sources.find((s) => s.index === num);
|
|
21
|
+
if (!source) return match;
|
|
22
|
+
const attrs = [`class="citation-ref"`, `data-index="${num}"`];
|
|
23
|
+
if (source.url) attrs.push(`data-url="${escapeAttr(source.url)}"`);
|
|
24
|
+
if (source.title) attrs.push(`data-title="${escapeAttr(source.title)}"`);
|
|
25
|
+
if (source.url) {
|
|
26
|
+
return `<span ${attrs.join(" ")}><a href="${escapeAttr(source.url)}" title="${escapeAttr(source.title || "")}" target="_blank" rel="noopener">${num}</a></span>`;
|
|
27
|
+
}
|
|
28
|
+
return `<span ${attrs.join(" ")}>${num}</span>`;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function patchCitationNode(node, byIndex) {
|
|
32
|
+
var _a, _b, _c, _d;
|
|
33
|
+
if (node.type === "citationRef") {
|
|
34
|
+
const index = String(((_a = node.attrs) == null ? void 0 : _a.index) ?? "");
|
|
35
|
+
const source = byIndex.get(index);
|
|
36
|
+
if (!source) return node;
|
|
37
|
+
return {
|
|
38
|
+
...node,
|
|
39
|
+
attrs: {
|
|
40
|
+
...node.attrs,
|
|
41
|
+
index,
|
|
42
|
+
url: source.url ?? ((_b = node.attrs) == null ? void 0 : _b.url) ?? null,
|
|
43
|
+
title: source.title ?? ((_c = node.attrs) == null ? void 0 : _c.title) ?? null
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (!((_d = node.content) == null ? void 0 : _d.length)) return node;
|
|
48
|
+
return {
|
|
49
|
+
...node,
|
|
50
|
+
content: node.content.map((child) => patchCitationNode(child, byIndex))
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function applyCitationSources(doc, sources) {
|
|
54
|
+
if (!sources.length) return doc;
|
|
55
|
+
const byIndex = new Map(sources.map((s) => [s.index, s]));
|
|
56
|
+
return patchCitationNode(doc, byIndex);
|
|
57
|
+
}
|
|
58
|
+
const CitationRef = Node.create({
|
|
59
|
+
name: "citationRef",
|
|
60
|
+
group: "inline",
|
|
61
|
+
inline: true,
|
|
62
|
+
atom: true,
|
|
63
|
+
selectable: true,
|
|
64
|
+
// 高于普通链接,确保 `[^1]` 不被拆成残缺 link
|
|
65
|
+
priority: 1e3,
|
|
66
|
+
addOptions() {
|
|
67
|
+
return { HTMLAttributes: {} };
|
|
68
|
+
},
|
|
69
|
+
addAttributes() {
|
|
70
|
+
return {
|
|
71
|
+
index: {
|
|
72
|
+
default: null,
|
|
73
|
+
parseHTML: (element) => element.getAttribute("data-index"),
|
|
74
|
+
renderHTML: (attributes) => {
|
|
75
|
+
if (!attributes.index) return {};
|
|
76
|
+
return { "data-index": attributes.index };
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
url: {
|
|
80
|
+
default: null,
|
|
81
|
+
parseHTML: (element) => element.getAttribute("data-url"),
|
|
82
|
+
renderHTML: (attributes) => {
|
|
83
|
+
if (!attributes.url) return {};
|
|
84
|
+
return { "data-url": attributes.url };
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
title: {
|
|
88
|
+
default: null,
|
|
89
|
+
parseHTML: (element) => element.getAttribute("data-title"),
|
|
90
|
+
renderHTML: (attributes) => {
|
|
91
|
+
if (!attributes.title) return {};
|
|
92
|
+
return { "data-title": attributes.title };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
},
|
|
97
|
+
parseHTML() {
|
|
98
|
+
return [{ tag: "span.citation-ref" }];
|
|
99
|
+
},
|
|
100
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
101
|
+
const index = String(node.attrs.index ?? "");
|
|
102
|
+
const url = node.attrs.url;
|
|
103
|
+
const title = node.attrs.title || "";
|
|
104
|
+
const attrs = mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
|
|
105
|
+
class: "citation-ref"
|
|
106
|
+
});
|
|
107
|
+
if (url) {
|
|
108
|
+
return [
|
|
109
|
+
"span",
|
|
110
|
+
attrs,
|
|
111
|
+
[
|
|
112
|
+
"a",
|
|
113
|
+
{
|
|
114
|
+
href: url,
|
|
115
|
+
title,
|
|
116
|
+
target: "_blank",
|
|
117
|
+
rel: "noopener noreferrer"
|
|
118
|
+
},
|
|
119
|
+
index
|
|
120
|
+
]
|
|
121
|
+
];
|
|
122
|
+
}
|
|
123
|
+
return ["span", attrs, index];
|
|
124
|
+
},
|
|
125
|
+
renderMarkdown(node) {
|
|
126
|
+
var _a;
|
|
127
|
+
return `[^${((_a = node == null ? void 0 : node.attrs) == null ? void 0 : _a.index) ?? ""}]`;
|
|
128
|
+
},
|
|
129
|
+
parseMarkdown: (token, helpers) => {
|
|
130
|
+
return helpers.createNode("citationRef", {
|
|
131
|
+
index: String(token.index ?? ""),
|
|
132
|
+
url: token.url ?? null,
|
|
133
|
+
title: token.title ?? null
|
|
134
|
+
});
|
|
135
|
+
},
|
|
136
|
+
markdownTokenizer: {
|
|
137
|
+
name: "citationRef",
|
|
138
|
+
level: "inline",
|
|
139
|
+
start(src) {
|
|
140
|
+
const match = /\[\^\d+\]/.exec(src);
|
|
141
|
+
return (match == null ? void 0 : match.index) ?? -1;
|
|
142
|
+
},
|
|
143
|
+
tokenize(src) {
|
|
144
|
+
const match = /^\[\^(\d+)\]/.exec(src);
|
|
145
|
+
if (!match) return void 0;
|
|
146
|
+
return {
|
|
147
|
+
type: "citationRef",
|
|
148
|
+
raw: match[0],
|
|
149
|
+
index: match[1]
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
addCommands() {
|
|
154
|
+
return {
|
|
155
|
+
insertCitationRef: (attrs) => ({ commands }) => commands.insertContent({
|
|
156
|
+
type: this.name,
|
|
157
|
+
attrs: {
|
|
158
|
+
index: attrs.index,
|
|
159
|
+
url: attrs.url ?? null,
|
|
160
|
+
title: attrs.title ?? null
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
const lowlight = createLowlight(common);
|
|
167
|
+
const pureCodeBlock = CodeBlockLowlight.configure({ lowlight });
|
|
168
|
+
const pureImage = Image.configure({ inline: false });
|
|
169
|
+
const baseExtensions = [
|
|
170
|
+
// 禁用 StarterKit 内置 codeBlock,统一改用带 lowlight 的代码块(由调用方注入)
|
|
171
|
+
StarterKit.configure({ codeBlock: false }),
|
|
172
|
+
TextStyle,
|
|
173
|
+
Color.configure({ types: [TextStyle.name] }),
|
|
174
|
+
// 正文字号:官方 FontSize(v3 起并入 text-style 包),以内联样式挂在 TextStyle
|
|
175
|
+
// 的 <span> 上(如 style="font-size: 16px"),与 Color 同基座,三端共用。
|
|
176
|
+
FontSize.configure({ types: [TextStyle.name] }),
|
|
177
|
+
Highlight.configure({ multicolor: true }),
|
|
178
|
+
Superscript,
|
|
179
|
+
Subscript,
|
|
180
|
+
TableKit.configure({ table: { resizable: true } }),
|
|
181
|
+
TaskList,
|
|
182
|
+
TaskItem.configure({ nested: true })
|
|
183
|
+
];
|
|
184
|
+
const editorScroll = "_editorScroll_siipj_4";
|
|
185
|
+
const editorContent = "_editorContent_siipj_8";
|
|
186
|
+
const styles = {
|
|
187
|
+
editorScroll,
|
|
188
|
+
editorContent
|
|
189
|
+
};
|
|
190
|
+
function baseSlug(text) {
|
|
191
|
+
return text.toLowerCase().trim().replace(/\s+/g, "-").replace(/[^\w一-龥-]/g, "").replace(/^-+|-+$/g, "") || "section";
|
|
192
|
+
}
|
|
193
|
+
function makeTocGetId() {
|
|
194
|
+
const seen = /* @__PURE__ */ new Map();
|
|
195
|
+
return (content) => {
|
|
196
|
+
const base = baseSlug(content);
|
|
197
|
+
const n = (seen.get(base) ?? 0) + 1;
|
|
198
|
+
seen.set(base, n);
|
|
199
|
+
return n === 1 ? base : `${base}-${n}`;
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function ReportContent({ html, className, ...rest }) {
|
|
203
|
+
return /* @__PURE__ */ jsx(
|
|
204
|
+
"div",
|
|
205
|
+
{
|
|
206
|
+
...rest,
|
|
207
|
+
className: className ? `${styles.editorContent} ${className}` : styles.editorContent,
|
|
208
|
+
dangerouslySetInnerHTML: { __html: html }
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
const MAX_LEVEL = 6;
|
|
213
|
+
function headingText(node) {
|
|
214
|
+
if (!node.content) return "";
|
|
215
|
+
return node.content.map((c) => c.type === "text" ? c.text ?? "" : "").join("").trim();
|
|
216
|
+
}
|
|
217
|
+
function extractToc(doc, lockedTitles = []) {
|
|
218
|
+
const locked = new Set(lockedTitles.map((t) => t.trim()));
|
|
219
|
+
const items = [];
|
|
220
|
+
const walk = (node) => {
|
|
221
|
+
var _a, _b, _c, _d;
|
|
222
|
+
const level = (_a = node.attrs) == null ? void 0 : _a.level;
|
|
223
|
+
if (node.type === "heading" && typeof level === "number" && level <= MAX_LEVEL) {
|
|
224
|
+
const text = headingText(node);
|
|
225
|
+
const id = ((_b = node.attrs) == null ? void 0 : _b["data-toc-id"]) ?? ((_c = node.attrs) == null ? void 0 : _c.id);
|
|
226
|
+
if (text && id) {
|
|
227
|
+
items.push({
|
|
228
|
+
id,
|
|
229
|
+
level,
|
|
230
|
+
text,
|
|
231
|
+
locked: locked.has(text) || void 0
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
(_d = node.content) == null ? void 0 : _d.forEach(walk);
|
|
236
|
+
};
|
|
237
|
+
walk(doc);
|
|
238
|
+
return items;
|
|
239
|
+
}
|
|
240
|
+
export {
|
|
241
|
+
CitationRef as C,
|
|
242
|
+
ReportContent as R,
|
|
243
|
+
pureImage as a,
|
|
244
|
+
baseExtensions as b,
|
|
245
|
+
applyCitationSources as c,
|
|
246
|
+
extractToc as d,
|
|
247
|
+
enrichMarkdownCitations as e,
|
|
248
|
+
lowlight as l,
|
|
249
|
+
makeTocGetId as m,
|
|
250
|
+
pureCodeBlock as p,
|
|
251
|
+
styles as s
|
|
252
|
+
};
|
|
253
|
+
//# sourceMappingURL=extractToc-DW6HOiGt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractToc-DW6HOiGt.js","sources":["../src/citationUtils.ts","../src/CitationRef.ts","../src/extensions.ts","../src/toc/tocSlug.ts","../src/ReportContent.tsx","../src/toc/extractToc.ts"],"sourcesContent":["import type { JSONContent } from '@tiptap/core';\n\nexport interface SourceRef {\n /** 与 markdown `[^n]` 中的 n 对齐(字符串,如 `\"1\"`)。 */\n index: string;\n url?: string;\n title?: string;\n /** 原文片段等;库本身不渲染 Popover,留给消费方。 */\n excerpt?: string;\n}\n\nfunction escapeAttr(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/\"/g, '"')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n\n/**\n * 将 markdown 中能匹配到 `sources` 的 `[^n]` 换成带 data-* 的\n * `<span class=\"citation-ref\">`(**不是** `<sup>`,避免被 Superscript 吃掉、\n * 也避免视觉上标)。未匹配的 `[^n]` 原样保留,留给 CitationRef tokenizer。\n *\n * 浏览器端 @tiptap/markdown 可解析内联 HTML;server 端无 DOMParser 时请改用\n * {@link applyCitationSources}(先 parse 再补 attrs)。\n */\nexport function enrichMarkdownCitations(\n markdown: string,\n sources: SourceRef[],\n): string {\n if (!sources.length) return markdown;\n\n return markdown.replace(/\\[\\^(\\d+)\\]/g, (match, num: string) => {\n const source = sources.find((s) => s.index === num);\n if (!source) return match;\n\n const attrs = [`class=\"citation-ref\"`, `data-index=\"${num}\"`];\n if (source.url) attrs.push(`data-url=\"${escapeAttr(source.url)}\"`);\n if (source.title) attrs.push(`data-title=\"${escapeAttr(source.title)}\"`);\n\n if (source.url) {\n return `<span ${attrs.join(' ')}><a href=\"${escapeAttr(source.url)}\" title=\"${escapeAttr(source.title || '')}\" target=\"_blank\" rel=\"noopener\">${num}</a></span>`;\n }\n return `<span ${attrs.join(' ')}>${num}</span>`;\n });\n}\n\nfunction patchCitationNode(\n node: JSONContent,\n byIndex: Map<string, SourceRef>,\n): JSONContent {\n if (node.type === 'citationRef') {\n const index = String(node.attrs?.index ?? '');\n const source = byIndex.get(index);\n if (!source) return node;\n return {\n ...node,\n attrs: {\n ...node.attrs,\n index,\n url: source.url ?? node.attrs?.url ?? null,\n title: source.title ?? node.attrs?.title ?? null,\n },\n };\n }\n\n if (!node.content?.length) return node;\n return {\n ...node,\n content: node.content.map((child) => patchCitationNode(child, byIndex)),\n };\n}\n\n/**\n * 在已 parse 的 Tiptap JSON 上,按 `sources` 给 `citationRef` 节点补 url/title。\n * SSR / 无 DOMParser 环境的首选路径。\n */\nexport function applyCitationSources(\n doc: JSONContent,\n sources: SourceRef[],\n): JSONContent {\n if (!sources.length) return doc;\n const byIndex = new Map(sources.map((s) => [s.index, s]));\n return patchCitationNode(doc, byIndex);\n}\n","import { mergeAttributes, Node } from '@tiptap/core';\n\nexport interface CitationRefOptions {\n HTMLAttributes: Record<string, unknown>;\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n citationRef: {\n insertCitationRef: (attrs: {\n index: string;\n url?: string | null;\n title?: string | null;\n }) => ReturnType;\n };\n }\n}\n\n/**\n * 脚注/引文引用——inline atom 节点。\n *\n * - 输入:`[^n]`(markdownTokenizer)或 `<span class=\"citation-ref\">`(parseHTML)\n * - 输出 HTML:居中圆形 pill(CSS `.citation-ref`),**不是**上下标\n * - 输出 markdown:`[^n]`\n *\n * Popover /「原文片段」由消费方通过 {@link createCitationRef} 的 `renderCitation`\n * 插槽完成;本节点只负责标记与默认圆标样式。\n */\nexport const CitationRef = Node.create<CitationRefOptions>({\n name: 'citationRef',\n\n group: 'inline',\n\n inline: true,\n\n atom: true,\n\n selectable: true,\n\n // 高于普通链接,确保 `[^1]` 不被拆成残缺 link\n priority: 1000,\n\n addOptions() {\n return { HTMLAttributes: {} };\n },\n\n addAttributes() {\n return {\n index: {\n default: null,\n parseHTML: (element) => element.getAttribute('data-index'),\n renderHTML: (attributes) => {\n if (!attributes.index) return {};\n return { 'data-index': attributes.index };\n },\n },\n url: {\n default: null,\n parseHTML: (element) => element.getAttribute('data-url'),\n renderHTML: (attributes) => {\n if (!attributes.url) return {};\n return { 'data-url': attributes.url };\n },\n },\n title: {\n default: null,\n parseHTML: (element) => element.getAttribute('data-title'),\n renderHTML: (attributes) => {\n if (!attributes.title) return {};\n return { 'data-title': attributes.title };\n },\n },\n };\n },\n\n parseHTML() {\n return [{ tag: 'span.citation-ref' }];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const index = String(node.attrs.index ?? '');\n const url = node.attrs.url as string | null;\n const title = (node.attrs.title as string | null) || '';\n const attrs = mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n class: 'citation-ref',\n });\n\n if (url) {\n return [\n 'span',\n attrs,\n [\n 'a',\n {\n href: url,\n title,\n target: '_blank',\n rel: 'noopener noreferrer',\n },\n index,\n ],\n ];\n }\n\n return ['span', attrs, index];\n },\n\n renderMarkdown(node) {\n return `[^${node?.attrs?.index ?? ''}]`;\n },\n\n parseMarkdown: (token, helpers) => {\n return helpers.createNode('citationRef', {\n index: String(token.index ?? ''),\n url: token.url ?? null,\n title: token.title ?? null,\n });\n },\n\n markdownTokenizer: {\n name: 'citationRef',\n level: 'inline' as const,\n start(src: string) {\n const match = /\\[\\^\\d+\\]/.exec(src);\n return match?.index ?? -1;\n },\n tokenize(src) {\n const match = /^\\[\\^(\\d+)\\]/.exec(src);\n if (!match) return undefined;\n return {\n type: 'citationRef',\n raw: match[0],\n index: match[1],\n };\n },\n },\n\n addCommands() {\n return {\n insertCitationRef:\n (attrs) =>\n ({ commands }) =>\n commands.insertContent({\n type: this.name,\n attrs: {\n index: attrs.index,\n url: attrs.url ?? null,\n title: attrs.title ?? null,\n },\n }),\n };\n },\n});\n","import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight';\nimport Highlight from '@tiptap/extension-highlight';\nimport Image from '@tiptap/extension-image';\nimport Subscript from '@tiptap/extension-subscript';\nimport Superscript from '@tiptap/extension-superscript';\nimport { TableKit } from '@tiptap/extension-table';\nimport TaskItem from '@tiptap/extension-task-item';\nimport TaskList from '@tiptap/extension-task-list';\nimport { Color, FontSize, TextStyle } from '@tiptap/extension-text-style';\n// AnyExtension 从 @tiptap/react 取(它 re-export 自 core),避免新增 @tiptap/core 直接依赖\nimport type { AnyExtension } from '@tiptap/react';\nimport StarterKit from '@tiptap/starter-kit';\nimport { common, createLowlight } from 'lowlight';\n\n/**\n * 编辑器的「内容 schema 级」扩展集——纯节点/标记定义,不含任何 React NodeView\n * 或键盘交互绑定。三处共用:\n * 1. 编辑器(MarkdownWysiwygEditor):base + 交互增强版 CodeBlock/Image\n * 2. 只读预览(MarkdownPreview)\n * 3. server 端 markdown→HTML 渲染(renderReportHtml)\n *\n * 分层动机:交互增强依赖 @tiptap/react / 浏览器,会污染 server bundle(RSC)。\n * base 保持纯 schema,server import 它只引入节点定义,无 React 代码。\n *\n * 关键边界:CodeBlock / Image / CitationRef「会被客户端增强」,**不放进 base**——\n * 否则编辑器追加增强版会与 base 的纯版同名冲突(Tiptap 报 \"Duplicate extension names\")。\n * 改为:base 不含这三类,由调用方按需注入:\n * - 编辑器 / 预览注入「增强版」(React NodeView)\n * - server 注入「纯版」(pureCodeBlock / pureImage / CitationRef)\n */\n\n// lowlight 实例:代码块语法高亮。导出供编辑器增强版与 server 纯版共用同一实例。\nexport const lowlight = createLowlight(common);\n\n/** 纯版代码块(无 React 视图):server / 预览用,产出带高亮 class 的静态结构。 */\nexport const pureCodeBlock = CodeBlockLowlight.configure({ lowlight });\n\n/**\n * 纯版块级图片(无删除快捷键):server / 预览用。\n * inline:false(官方默认)——研报里图片均为大图独占一行,块级图片可直接作为 doc\n * 顶层子节点,避免「inline image 裸挂 doc 顶层」被 generateTocIds 严格校验判非法。\n */\nexport const pureImage = Image.configure({ inline: false });\n\n/**\n * 三处共用的纯 schema 扩展——**不含 CodeBlock / Image / CitationRef**(见上方边界说明)。\n * 编辑器:`[...baseExtensions, 增强CodeBlock, 增强Image, createCitationRef(), Markdown]`\n * server/预览:`[...baseExtensions, pureCodeBlock, pureImage, CitationRef, …]`\n */\nexport const baseExtensions: AnyExtension[] = [\n // 禁用 StarterKit 内置 codeBlock,统一改用带 lowlight 的代码块(由调用方注入)\n StarterKit.configure({ codeBlock: false }),\n TextStyle,\n Color.configure({ types: [TextStyle.name] }),\n // 正文字号:官方 FontSize(v3 起并入 text-style 包),以内联样式挂在 TextStyle\n // 的 <span> 上(如 style=\"font-size: 16px\"),与 Color 同基座,三端共用。\n FontSize.configure({ types: [TextStyle.name] }),\n Highlight.configure({ multicolor: true }),\n Superscript,\n Subscript,\n TableKit.configure({ table: { resizable: true } }),\n TaskList,\n TaskItem.configure({ nested: true }),\n];\n","/**\n * 目录锚点 id 生成——阅读页(SSR)与编辑页(editor)共用的**单一真源**,\n * 保证「创作预览的锚点 = 发布后阅读页的锚点」。\n *\n * 用 slug 而非官方默认 UUID:slug 跨 SSR / ISR revalidate 稳定(UUID 每次都变、\n * 分享的 #hash 会失效),且 `#introduction` 比 `#d4590f81-…` 可读、对 SEO 友好。\n *\n * slug 会重名(两个「细节」都 slug 成 `xi-jie`),故用闭包计数器去重:\n * 同名追加 -2 / -3(已实测:details / details-2 / details-3,HTML id 全唯一)。\n */\n\n/** 单个标题文本 → 基础 slug(保留中文,去标点,空白转连字符)。 */\nfunction baseSlug(text: string): string {\n return (\n text\n .toLowerCase()\n .trim()\n .replace(/\\s+/g, '-')\n // 保留字母/数字/下划线/中文/连字符,其余剔除\n .replace(/[^\\w一-龥-]/g, '')\n .replace(/^-+|-+$/g, '') || 'section'\n );\n}\n\n/**\n * 造一个带去重的 `getId`。每次生成新实例(闭包各自计数),传给\n * `TableOfContents.configure({ getId })` 或 `generateTocIds` 的扩展配置。\n */\nexport function makeTocGetId(): (content: string) => string {\n const seen = new Map<string, number>();\n return (content: string) => {\n const base = baseSlug(content);\n const n = (seen.get(base) ?? 0) + 1;\n seen.set(base, n);\n return n === 1 ? base : `${base}-${n}`;\n };\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","/**\n * 最小 Tiptap JSON 节点结构(只取本模块用到的字段)。\n * 不从 `@tiptap/core` 引 `JSONContent`——core 是嵌套依赖、非直接依赖,\n * 直接 import 类型解析不到(与仓库既有做法一致,见 extensions.ts)。\n */\ninterface TocDocNode {\n type?: string;\n text?: string;\n attrs?: Record<string, unknown> | null;\n content?: TocDocNode[];\n}\n\n/** 目录项。 */\nexport interface TocItem {\n /** 锚点 id(= heading 的 data-toc-id / id,由 generateTocIds 注入)。 */\n id: string;\n /** 标题层级(1-6)。 */\n level: number;\n /** 标题纯文本。 */\n text: string;\n /** 付费墙锁住的章节(置灰不可点)。 */\n locked?: boolean;\n}\n\n/** 目录纳入的最大层级(h1-h6,全层级入目录)。 */\nconst MAX_LEVEL = 6;\n\n/** 取 heading 节点的纯文本(拼接其 text 子节点)。 */\nfunction headingText(node: TocDocNode): string {\n if (!node.content) return '';\n return node.content\n .map((c) => (c.type === 'text' ? c.text ?? '' : ''))\n .join('')\n .trim();\n}\n\n/**\n * 从已注入锚点 id 的 Tiptap JSON doc 提取 h1-h6 目录。\n *\n * 必须在 `generateTocIds` 之后调用(heading 的 attrs 里才有 `data-toc-id`)。\n * `lockedTitles`:被截断(锁住)章节标题,命中则标 `locked`——\n * 目录列全部章节,锁住项置灰不可点(付费墙钩子)。用 Set 便于去重命中。\n */\nexport function extractToc(\n doc: TocDocNode,\n lockedTitles: string[] = [],\n): TocItem[] {\n const locked = new Set(lockedTitles.map((t) => t.trim()));\n const items: TocItem[] = [];\n\n const walk = (node: TocDocNode) => {\n const level = node.attrs?.level;\n if (\n node.type === 'heading' &&\n typeof level === 'number' &&\n level <= MAX_LEVEL\n ) {\n const text = headingText(node);\n const id = (node.attrs?.['data-toc-id'] ?? node.attrs?.id) as\n | string\n | undefined;\n // 有文本 + 有锚点 id 才入目录(空标题 / 未注入 id 的跳过)。\n if (text && id) {\n items.push({\n id,\n level,\n text,\n locked: locked.has(text) || undefined,\n });\n }\n }\n node.content?.forEach(walk);\n };\n\n walk(doc);\n return items;\n}\n"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,14 @@ export { ColorPalette, type ColorPaletteProps } from './components/ColorPalette'
|
|
|
5
5
|
export { TocPanel, type TocPanelProps } from './components/TocPanel';
|
|
6
6
|
export { CodeBlockView } from './components/CodeBlockView';
|
|
7
7
|
export { ReportContent, type ReportContentProps } from './ReportContent';
|
|
8
|
+
export { CitationInteractive, type CitationInteractiveProps, } from './components/CitationInteractive';
|
|
9
|
+
export { ReportContentInteractive, type ReportContentInteractiveProps, } from './components/ReportContentInteractive';
|
|
8
10
|
export { baseExtensions, lowlight, pureCodeBlock, pureImage, } from './extensions';
|
|
11
|
+
export { CitationRef } from './CitationRef';
|
|
12
|
+
export { createCitationRef } from './createCitationRef';
|
|
13
|
+
export type { RenderCitation, RenderCitationContext, RenderCitationInteractive, RenderCitationInteractiveContext, } from './citationTypes';
|
|
14
|
+
export { findCitationRefElement, readCitationAttrs, } from './citationDom';
|
|
15
|
+
export { applyCitationSources, enrichMarkdownCitations, type SourceRef, } from './citationUtils';
|
|
9
16
|
export { MarkdownPaste, looksLikeMarkdown } from './markdownPaste';
|
|
10
17
|
export { MarkdownFileDrop } from './markdownFileDrop';
|
|
11
18
|
export { extractToc, type TocItem } from './toc/extractToc';
|