@4399ywkf/editor 0.6.0 → 0.8.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 +161 -2
- package/dist/{DocView-XQMJUUVK.js → DocView-WEKRSKRU.js} +6 -4
- package/dist/DocView-WEKRSKRU.js.map +1 -0
- package/dist/SheetView-SDBRSTVS.js +3 -0
- package/dist/{SheetView-DSADIZNS.js.map → SheetView-SDBRSTVS.js.map} +1 -1
- package/dist/chunk-5HMKRNIH.js +27 -0
- package/dist/chunk-5HMKRNIH.js.map +1 -0
- package/dist/chunk-DGUNVCOM.js +711 -0
- package/dist/chunk-DGUNVCOM.js.map +1 -0
- package/dist/chunk-HPSPOM2O.js +128 -0
- package/dist/chunk-HPSPOM2O.js.map +1 -0
- package/dist/chunk-KRP5V7VF.js +130 -0
- package/dist/chunk-KRP5V7VF.js.map +1 -0
- package/dist/chunk-SBTKDJAL.js +107 -0
- package/dist/chunk-SBTKDJAL.js.map +1 -0
- package/dist/{chunk-IUDLMN53.js → chunk-SGLNT6Z2.js} +2416 -176
- package/dist/chunk-SGLNT6Z2.js.map +1 -0
- package/dist/{chunk-L6ZR5HHW.js → chunk-SYCK6Y5F.js} +15 -10
- package/dist/chunk-SYCK6Y5F.js.map +1 -0
- package/dist/chunk-WF7PIIFR.js +21 -0
- package/dist/chunk-WF7PIIFR.js.map +1 -0
- package/dist/chunk-ZY5KLA7T.js +258 -0
- package/dist/chunk-ZY5KLA7T.js.map +1 -0
- package/dist/code-types-Dqmit3xx.d.ts +65 -0
- package/dist/{types-C37MAt8o.d.ts → csv-parse-D0zTBvDB.d.ts} +39 -1
- package/dist/csv.d.ts +6 -3
- package/dist/csv.js +6 -125
- package/dist/csv.js.map +1 -1
- package/dist/doc-runtime.d.ts +1 -1
- package/dist/doc-runtime.js +7 -1
- package/dist/doc-runtime.js.map +1 -1
- package/dist/doc.d.ts +113 -6
- package/dist/doc.js +2 -1
- package/dist/doc.js.map +1 -1
- package/dist/docx.d.ts +15 -0
- package/dist/docx.js +116 -8
- package/dist/docx.js.map +1 -1
- package/dist/import-GVZDLWA2.js +6 -0
- package/dist/import-GVZDLWA2.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/pdf.d.ts +3 -1
- package/dist/pptx.d.ts +3 -1
- package/dist/{registry-BBL8yeIT.d.ts → registry-CYKivRDh.d.ts} +13 -1
- package/dist/sheet-runtime.d.ts +212 -0
- package/dist/sheet-runtime.js +416 -0
- package/dist/sheet-runtime.js.map +1 -0
- package/dist/sheet.d.ts +9 -5
- package/dist/sheet.js +1 -1
- package/dist/style.css +421 -111
- package/dist/xlsx.d.ts +118 -7
- package/dist/xlsx.js +7 -78
- package/dist/xlsx.js.map +1 -1
- package/package.json +11 -5
- package/dist/DocView-XQMJUUVK.js.map +0 -1
- package/dist/SheetView-DSADIZNS.js +0 -3
- package/dist/chunk-32WQX3NR.js +0 -37
- package/dist/chunk-32WQX3NR.js.map +0 -1
- package/dist/chunk-IUDLMN53.js.map +0 -1
- package/dist/chunk-L6ZR5HHW.js.map +0 -1
package/dist/doc.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, RefObject, useEffect, HTMLAttributes } from 'react';
|
|
3
3
|
import { JSONContent, Editor, NodeWithPos, Extension as Extension$1, Node as Node$1 } from '@tiptap/react';
|
|
4
|
-
import
|
|
4
|
+
import * as _tiptap_core from '@tiptap/core';
|
|
5
|
+
import { Extensions, JSONContent as JSONContent$1, Extension } from '@tiptap/core';
|
|
5
6
|
import { Doc } from 'yjs';
|
|
7
|
+
import { C as ContentFormat, a as CodeBlockOptions, b as CodeHighlighter } from './code-types-Dqmit3xx.js';
|
|
8
|
+
export { c as CodeBlockAttrs, d as CodeGroupAttrs, H as HighlightResult, e as HighlightToken, S as ShikiTheme } from './code-types-Dqmit3xx.js';
|
|
9
|
+
import { CodeBlockOptions as CodeBlockOptions$1 } from '@tiptap/extension-code-block';
|
|
6
10
|
import { UseFloatingOptions, UseDismissProps, AutoUpdateOptions } from '@floating-ui/react';
|
|
7
11
|
import { Selection, Transaction } from '@tiptap/pm/state';
|
|
8
12
|
import { Node } from '@tiptap/pm/model';
|
|
@@ -10,6 +14,7 @@ import { B as ButtonProps } from './button-CWX5Uuj-.js';
|
|
|
10
14
|
export { a as Button } from './button-CWX5Uuj-.js';
|
|
11
15
|
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
12
16
|
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
17
|
+
import 'shiki';
|
|
13
18
|
|
|
14
19
|
/**
|
|
15
20
|
* 包消费者通过 `<EditorConfigProvider>` 注入业务侧能力。
|
|
@@ -134,6 +139,18 @@ interface NotionEditorProps {
|
|
|
134
139
|
* 协同模式下 yjs Doc 接管内容,传入会被忽略以免跟 sync 冲突。
|
|
135
140
|
*/
|
|
136
141
|
content?: string | JSONContent;
|
|
142
|
+
/**
|
|
143
|
+
* `content` 的格式。不传时沿用旧规则:对象按 JSON、字符串按 HTML。
|
|
144
|
+
* `"markdown"` 时字符串经 Markdown 解析(支持 `::: code-group` 代码分组);
|
|
145
|
+
* `"json"` 只接受对象,不会去解析 JSON 文本。格式与内容类型不匹配时
|
|
146
|
+
* console.error 一条 `[editor]` 信息并保留当前文档不动。
|
|
147
|
+
*/
|
|
148
|
+
contentFormat?: ContentFormat;
|
|
149
|
+
/**
|
|
150
|
+
* 代码块高亮配置(Shiki 主题 / 语言别名 / 额外语言注册)。默认 github-light /
|
|
151
|
+
* github-dark 随 `.dark` 切换,语言按需加载,无需配置即可用。
|
|
152
|
+
*/
|
|
153
|
+
codeBlock?: CodeBlockOptions;
|
|
137
154
|
/**
|
|
138
155
|
* 只读模式:用于展示文章内容。设为 true 时编辑器不可编辑(editable:false),
|
|
139
156
|
* 且隐藏所有编辑态 UI(头部工具栏、浮动工具栏、拖拽手柄、slash/mention/emoji
|
|
@@ -172,6 +189,10 @@ interface EditorProviderProps {
|
|
|
172
189
|
placeholder?: string;
|
|
173
190
|
/** 本地编辑模式下的初始/同步内容,详见 NotionEditorProps.content */
|
|
174
191
|
content?: string | JSONContent;
|
|
192
|
+
/** 内容格式,详见 NotionEditorProps.contentFormat */
|
|
193
|
+
contentFormat?: ContentFormat;
|
|
194
|
+
/** 代码块高亮配置,详见 NotionEditorProps.codeBlock */
|
|
195
|
+
codeBlock?: CodeBlockOptions;
|
|
175
196
|
/** 只读模式,详见 NotionEditorProps.readOnly */
|
|
176
197
|
readOnly?: boolean;
|
|
177
198
|
/** 隐藏包内置顶部工具条,详见 NotionEditorProps.hideHeader */
|
|
@@ -211,13 +232,17 @@ declare function EditorProvider(props: EditorProviderProps): react.JSX.Element;
|
|
|
211
232
|
/**
|
|
212
233
|
* Full editor with all necessary providers, ready to use with just a room ID
|
|
213
234
|
*/
|
|
214
|
-
declare function NotionEditor({ room, placeholder, content, readOnly, hideHeader, onEditorReady, extensions, }: NotionEditorProps): react.JSX.Element;
|
|
235
|
+
declare function NotionEditor({ room, placeholder, content, contentFormat, codeBlock, readOnly, hideHeader, onEditorReady, extensions, }: NotionEditorProps): react.JSX.Element;
|
|
215
236
|
/**
|
|
216
237
|
* Internal component that handles the editor loading state
|
|
217
238
|
*/
|
|
218
|
-
declare function NotionEditorContent({ placeholder, content, readOnly, hideHeader, onEditorReady, extensions, }: {
|
|
239
|
+
declare function NotionEditorContent({ placeholder, content, contentFormat, codeBlock, readOnly, hideHeader, onEditorReady, extensions, }: {
|
|
219
240
|
placeholder?: string;
|
|
220
241
|
content?: string | JSONContent;
|
|
242
|
+
/** 内容格式,详见 NotionEditorProps.contentFormat */
|
|
243
|
+
contentFormat?: ContentFormat;
|
|
244
|
+
/** 代码块高亮配置,详见 NotionEditorProps.codeBlock */
|
|
245
|
+
codeBlock?: CodeBlockOptions;
|
|
221
246
|
readOnly?: boolean;
|
|
222
247
|
hideHeader?: boolean;
|
|
223
248
|
onEditorReady?: (editor: Editor) => void;
|
|
@@ -231,8 +256,12 @@ declare function NotionEditorContent({ placeholder, content, readOnly, hideHeade
|
|
|
231
256
|
extensions?: Extensions;
|
|
232
257
|
}): react.JSX.Element;
|
|
233
258
|
interface ArticleViewerProps {
|
|
234
|
-
/** 文章内容(HTML 字符串或 tiptap JSONContent),通常由 HTTP 接口拉取后传入 */
|
|
259
|
+
/** 文章内容(HTML 字符串、Markdown 字符串或 tiptap JSONContent),通常由 HTTP 接口拉取后传入 */
|
|
235
260
|
content?: string | JSONContent;
|
|
261
|
+
/** 内容格式,详见 NotionEditorProps.contentFormat */
|
|
262
|
+
contentFormat?: ContentFormat;
|
|
263
|
+
/** 代码块高亮配置,详见 NotionEditorProps.codeBlock */
|
|
264
|
+
codeBlock?: CodeBlockOptions;
|
|
236
265
|
/** 空内容时的占位文案,默认空(viewer 一般不显示占位) */
|
|
237
266
|
placeholder?: string;
|
|
238
267
|
}
|
|
@@ -246,7 +275,85 @@ interface ArticleViewerProps {
|
|
|
246
275
|
*
|
|
247
276
|
* 用法:<ArticleViewer content={articleContent} />
|
|
248
277
|
*/
|
|
249
|
-
declare function ArticleViewer({ content, placeholder }: ArticleViewerProps): react.JSX.Element;
|
|
278
|
+
declare function ArticleViewer({ content, contentFormat, codeBlock, placeholder }: ArticleViewerProps): react.JSX.Element;
|
|
279
|
+
|
|
280
|
+
/** 只用到 Editor 的这几个面,避免把 @tiptap/core 的 Editor 类型绑死在签名里 */
|
|
281
|
+
interface EditorLike {
|
|
282
|
+
getJSON(): JSONContent$1;
|
|
283
|
+
extensionManager: {
|
|
284
|
+
extensions: Extensions;
|
|
285
|
+
};
|
|
286
|
+
storage: object;
|
|
287
|
+
}
|
|
288
|
+
type ParsedContent = {
|
|
289
|
+
ok: true;
|
|
290
|
+
json: JSONContent$1 | null;
|
|
291
|
+
} | {
|
|
292
|
+
ok: false;
|
|
293
|
+
error: string;
|
|
294
|
+
};
|
|
295
|
+
/**
|
|
296
|
+
* 把任意输入规范成 Tiptap JSON。`json: null` 表示"没有内容"(undefined / null / 空串),
|
|
297
|
+
* 调用方按"不设置内容"处理。
|
|
298
|
+
*/
|
|
299
|
+
declare function parseEditorContent(content: unknown, format: ContentFormat | undefined, extensions: Extensions): ParsedContent;
|
|
300
|
+
declare function serializeEditorMarkdown(json: JSONContent$1, extensions: Extensions): string;
|
|
301
|
+
/**
|
|
302
|
+
* `editor.getMarkdown()` 的类型安全封装。那个方法来自 @tiptap/markdown 的模块扩充,
|
|
303
|
+
* 本包的 d.ts 不会把扩充带给消费方;用这个函数就不需要额外引 @tiptap/markdown 的类型。
|
|
304
|
+
* 优先用编辑器自己的 MarkdownManager(同一套 marked 实例),没有时按扩展集临时建一个。
|
|
305
|
+
*/
|
|
306
|
+
declare function getEditorMarkdown(editor: EditorLike): string;
|
|
307
|
+
interface RenderHighlightedHTMLOptions extends CodeBlockOptions {
|
|
308
|
+
/** 传 Editor 时可省略;传 JSON 时必填 */
|
|
309
|
+
extensions?: Extensions;
|
|
310
|
+
/** 复用已有服务(传 Editor 时默认取编辑器里的那份) */
|
|
311
|
+
highlighter?: CodeHighlighter;
|
|
312
|
+
/** 主题:`"light"` / `"dark"` 走 shikiTheme 配置,其它字符串当 Shiki 主题名 */
|
|
313
|
+
theme?: "light" | "dark" | (string & {});
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* 导出调用时刻的文档快照为静态高亮 HTML:先取 JSON(之后的编辑不会混进来),
|
|
317
|
+
* 每个代码块经 Shiki 输出 token span,再按文档顺序替换语义 HTML 里的 `<pre>…</pre>`。
|
|
318
|
+
* 分组保留 `<div data-code-group>` 与每个 `<pre>` 的 data-language / data-label,
|
|
319
|
+
* 所有标签的代码都在、都可见 —— 不嵌脚本,不含 Decoration span 或按钮。
|
|
320
|
+
*/
|
|
321
|
+
declare function renderHighlightedHTML(source: EditorLike | JSONContent$1, options?: RenderHighlightedHTMLOptions): Promise<string>;
|
|
322
|
+
|
|
323
|
+
type CodeBlockSchemaOptions = CodeBlockOptions$1 & CodeBlockOptions;
|
|
324
|
+
|
|
325
|
+
declare const CodeBlockExtension: _tiptap_core.Node<CodeBlockSchemaOptions, any>;
|
|
326
|
+
|
|
327
|
+
declare const CodeGroupExtension: _tiptap_core.Node<any, any>;
|
|
328
|
+
|
|
329
|
+
declare const CalloutExtension: _tiptap_core.Node<any, any>;
|
|
330
|
+
|
|
331
|
+
declare const DetailsExtension: _tiptap_core.Node<any, any>;
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* 折叠块 / 提示框 / API 参数节点的公共类型。只有类型与常量,没有运行时依赖。
|
|
335
|
+
*/
|
|
336
|
+
declare const CALLOUT_TYPES: readonly ["info", "tip", "warning", "danger"];
|
|
337
|
+
type CalloutType = (typeof CALLOUT_TYPES)[number];
|
|
338
|
+
interface CalloutAttrs {
|
|
339
|
+
id?: string | null;
|
|
340
|
+
type: CalloutType;
|
|
341
|
+
title: string | null;
|
|
342
|
+
}
|
|
343
|
+
interface DetailsAttrs {
|
|
344
|
+
id?: string | null;
|
|
345
|
+
title: string | null;
|
|
346
|
+
}
|
|
347
|
+
interface ApiParamAttrs {
|
|
348
|
+
id?: string | null;
|
|
349
|
+
name: string;
|
|
350
|
+
type: string | null;
|
|
351
|
+
required: boolean;
|
|
352
|
+
default: string | null;
|
|
353
|
+
summary: string | null;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
declare const ApiParamExtension: _tiptap_core.Node<any, any>;
|
|
250
357
|
|
|
251
358
|
type CollabContextValue = {
|
|
252
359
|
provider: CollabProviderLike | null;
|
|
@@ -1096,4 +1203,4 @@ declare const MediaUploadButton: react.ForwardRefExoticComponent<MediaUploadButt
|
|
|
1096
1203
|
*/
|
|
1097
1204
|
declare function pickFile(accept: string, multiple?: boolean): Promise<File[]>;
|
|
1098
1205
|
|
|
1099
|
-
export { ArticleViewer, type ArticleViewerProps, Audio, ButtonProps, CollabContext, type CollabContextValue, CollabProvider, type CollabProviderLike, Column, type ColumnLayout, Columns, DEFAULT_MAX_FILE_SIZES, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type EditorCollabConfig, type EditorConfig, EditorConfigProvider, type EditorConfigProviderProps, EditorContentArea, type EditorProviderProps, type EditorUploadConfig, type EditorUserConfig, FileAttachment, type FileAttachmentAttrs, FloatingElement, HIDE_FLOATING_META, LoadingSpinner, MAC_SYMBOLS, MAX_FILE_SIZE, type MediaKind, type MediaKindForButton, MediaUploadButton, type MediaUploadButtonProps, MediaUploadPlaceholder, NotionEditor, NotionEditorContent, EditorProvider as NotionEditorInner, type NotionEditorProps, type OverflowPosition, PasteDropMedia, type PasteDropMediaOptions, type PasteDropMediaUploadFn, type PasteDropRehostProgressEvent, Popover, PopoverContent, PopoverTrigger, type RehostProgressEvent, SR_ONLY, Separator, Spacer, Toolbar, ToolbarGroup, ToolbarSeparator, UiState, UiState as UiStateType, type User, UserContext, type UserContextValue, UserProvider, Video, clamp, cn, defaultUiState, detectMediaKind, findNodeAtPosition, findNodePosition, findSelectionPosition, focusNextNode, formatShortcutKey, getAvatar, getElementOverflowPosition, getNodeDisplayName, getSelectedBlockNodes, getSelectedNodesOfType, getSelectionBoundingRect, getUrlParam, handleImageUpload, hasContentAbove, isAllowedUri, isExtensionAvailable, isMac, isMarkInSchema, isNodeInSchema, isNodeTypeSelected, isSelectionValid, isTextSelectionValid, isValidPosition, markHideFloatingOnNext, parseShortcutKeys, pickFile, removeEmptyParagraphs, resolveMaxSize, runMediaUpload, sanitizeUrl, selectCurrentBlockContent, selectNodeAndHideFloating, selectionWithinConvertibleTypes, updateNodesAttr, useCollab, useCollaboration, useComposedRef, useCursorVisibility, useEditorConfig, useElementRect, useFloatingElement, useFloatingToolbarVisibility, useIsBreakpoint, useIsomorphicLayoutEffect, useMenuNavigation, useOnClickOutside, useScrolling, useThrottledCallback, useTiptapEditor, useUiEditorState, useUiEditorState as useUiEditorStateDefault, useUnmount, useUser, useWindowSize };
|
|
1206
|
+
export { type ApiParamAttrs, ApiParamExtension, ArticleViewer, type ArticleViewerProps, Audio, ButtonProps, type CalloutAttrs, CalloutExtension, type CalloutType, CodeBlockExtension, CodeBlockOptions, CodeGroupExtension, CollabContext, type CollabContextValue, CollabProvider, type CollabProviderLike, Column, type ColumnLayout, Columns, ContentFormat, DEFAULT_MAX_FILE_SIZES, type DetailsAttrs, DetailsExtension, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type EditorCollabConfig, type EditorConfig, EditorConfigProvider, type EditorConfigProviderProps, EditorContentArea, type EditorProviderProps, type EditorUploadConfig, type EditorUserConfig, FileAttachment, type FileAttachmentAttrs, FloatingElement, HIDE_FLOATING_META, LoadingSpinner, MAC_SYMBOLS, MAX_FILE_SIZE, type MediaKind, type MediaKindForButton, MediaUploadButton, type MediaUploadButtonProps, MediaUploadPlaceholder, NotionEditor, NotionEditorContent, EditorProvider as NotionEditorInner, type NotionEditorProps, type OverflowPosition, type ParsedContent, PasteDropMedia, type PasteDropMediaOptions, type PasteDropMediaUploadFn, type PasteDropRehostProgressEvent, Popover, PopoverContent, PopoverTrigger, type RehostProgressEvent, type RenderHighlightedHTMLOptions, SR_ONLY, Separator, Spacer, Toolbar, ToolbarGroup, ToolbarSeparator, UiState, UiState as UiStateType, type User, UserContext, type UserContextValue, UserProvider, Video, clamp, cn, defaultUiState, detectMediaKind, findNodeAtPosition, findNodePosition, findSelectionPosition, focusNextNode, formatShortcutKey, getAvatar, getEditorMarkdown, getElementOverflowPosition, getNodeDisplayName, getSelectedBlockNodes, getSelectedNodesOfType, getSelectionBoundingRect, getUrlParam, handleImageUpload, hasContentAbove, isAllowedUri, isExtensionAvailable, isMac, isMarkInSchema, isNodeInSchema, isNodeTypeSelected, isSelectionValid, isTextSelectionValid, isValidPosition, markHideFloatingOnNext, parseEditorContent, parseShortcutKeys, pickFile, removeEmptyParagraphs, renderHighlightedHTML, resolveMaxSize, runMediaUpload, sanitizeUrl, selectCurrentBlockContent, selectNodeAndHideFloating, selectionWithinConvertibleTypes, serializeEditorMarkdown, updateNodesAttr, useCollab, useCollaboration, useComposedRef, useCursorVisibility, useEditorConfig, useElementRect, useFloatingElement, useFloatingToolbarVisibility, useIsBreakpoint, useIsomorphicLayoutEffect, useMenuNavigation, useOnClickOutside, useScrolling, useThrottledCallback, useTiptapEditor, useUiEditorState, useUiEditorState as useUiEditorStateDefault, useUnmount, useUser, useWindowSize };
|
package/dist/doc.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export { ArticleViewer, Audio, CollabContext, CollabProvider, Column, Columns, DEFAULT_MAX_FILE_SIZES, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EditorConfigProvider, EditorContentArea, FileAttachment, FloatingElement, HIDE_FLOATING_META, LoadingSpinner, MediaUploadButton, MediaUploadPlaceholder, NotionEditor, NotionEditorContent, EditorProvider as NotionEditorInner, PasteDropMedia, Separator, Spacer, Toolbar, ToolbarGroup, ToolbarSeparator, UiState, UserContext, UserProvider, Video, defaultUiState, detectMediaKind, findSelectionPosition, hasContentAbove, markHideFloatingOnNext, pickFile, resolveMaxSize, runMediaUpload, selectNodeAndHideFloating, useCollab, useCollaboration, useComposedRef, useCursorVisibility, useEditorConfig, useElementRect, useFloatingElement, useFloatingToolbarVisibility, useIsBreakpoint, useIsomorphicLayoutEffect, useMenuNavigation, useOnClickOutside, useThrottledCallback, useUiEditorState, use_ui_editor_state_default as useUiEditorStateDefault, useUnmount, useUser, useWindowSize } from './chunk-
|
|
1
|
+
export { ApiParamExtension, ArticleViewer, Audio, CalloutExtension, CodeBlockExtension, CodeGroupExtension, CollabContext, CollabProvider, Column, Columns, DEFAULT_MAX_FILE_SIZES, DetailsExtension, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EditorConfigProvider, EditorContentArea, FileAttachment, FloatingElement, HIDE_FLOATING_META, LoadingSpinner, MediaUploadButton, MediaUploadPlaceholder, NotionEditor, NotionEditorContent, EditorProvider as NotionEditorInner, PasteDropMedia, Separator, Spacer, Toolbar, ToolbarGroup, ToolbarSeparator, UiState, UserContext, UserProvider, Video, defaultUiState, detectMediaKind, findSelectionPosition, getEditorMarkdown, hasContentAbove, markHideFloatingOnNext, parseEditorContent, pickFile, renderHighlightedHTML, resolveMaxSize, runMediaUpload, selectNodeAndHideFloating, serializeEditorMarkdown, useCollab, useCollaboration, useComposedRef, useCursorVisibility, useEditorConfig, useElementRect, useFloatingElement, useFloatingToolbarVisibility, useIsBreakpoint, useIsomorphicLayoutEffect, useMenuNavigation, useOnClickOutside, useThrottledCallback, useUiEditorState, use_ui_editor_state_default as useUiEditorStateDefault, useUnmount, useUser, useWindowSize } from './chunk-SGLNT6Z2.js';
|
|
2
2
|
export { Button, MAC_SYMBOLS, MAX_FILE_SIZE, Popover, PopoverContent, PopoverTrigger, SR_ONLY, clamp, cn, findNodeAtPosition, findNodePosition, focusNextNode, formatShortcutKey, getAvatar, getElementOverflowPosition, getNodeDisplayName, getSelectedBlockNodes, getSelectedNodesOfType, getSelectionBoundingRect, getUrlParam, handleImageUpload, isAllowedUri, isExtensionAvailable, isMac, isMarkInSchema, isNodeInSchema, isNodeTypeSelected, isSelectionValid, isTextSelectionValid, isValidPosition, parseShortcutKeys, removeEmptyParagraphs, sanitizeUrl, selectCurrentBlockContent, selectionWithinConvertibleTypes, updateNodesAttr, useTiptapEditor } from './chunk-QMYT5WXO.js';
|
|
3
|
+
import './chunk-ZY5KLA7T.js';
|
|
3
4
|
import { useState, useEffect } from 'react';
|
|
4
5
|
|
|
5
6
|
function useScrolling(target, options = {}) {
|
package/dist/doc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/use-scrolling.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/hooks/use-scrolling.ts"],"names":[],"mappings":";;;;;AAWO,SAAS,YAAA,CACd,MAAA,EACA,OAAA,GAA+B,EAAC,EACvB;AACT,EAAA,MAAM,EAAE,QAAA,GAAW,GAAA,EAAK,kBAAA,GAAqB,MAAK,GAAI,OAAA;AACtD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,KAAK,CAAA;AAEpD,EAAA,SAAA,CAAU,MAAM;AAEd,IAAA,MAAM,OAAA,GACJ,UAAU,OAAO,MAAA,KAAW,eAAe,MAAA,YAAkB,MAAA,GACzD,MAAA,GACE,MAAA,EAAmC,OAAA,IAAW,MAAA;AAGtD,IAAA,MAAM,cACJ,kBAAA,IACA,OAAA,KAAY,UACZ,OAAO,QAAA,KAAa,cAChB,QAAA,GACA,OAAA;AAEN,IAAA,MAAM,EAAA,GAAK,CACT,EAAA,EACA,KAAA,EACA,YACG,EAAA,CAAG,gBAAA,CAAiB,KAAA,EAAO,OAAA,EAAS,IAAI,CAAA;AAE7C,IAAA,MAAM,GAAA,GAAM,CACV,EAAA,EACA,KAAA,EACA,YACG,EAAA,CAAG,mBAAA,CAAoB,OAAO,OAAO,CAAA;AAE1C,IAAA,IAAI,OAAA;AACJ,IAAA,MAAM,iBAAA,GAAoB,OAAA,KAAY,MAAA,IAAU,aAAA,IAAiB,MAAA;AAEjE,IAAA,MAAM,eAA8B,MAAM;AACxC,MAAA,IAAI,CAAC,WAAA,EAAa,cAAA,CAAe,IAAI,CAAA;AAErC,MAAA,IAAI,CAAC,iBAAA,EAAmB;AACtB,QAAA,YAAA,CAAa,OAAO,CAAA;AACpB,QAAA,OAAA,GAAU,UAAA,CAAW,MAAM,cAAA,CAAe,KAAK,GAAG,QAAQ,CAAA;AAAA,MAC5D;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,eAAA,GAAiC,MAAM,cAAA,CAAe,KAAK,CAAA;AAEjE,IAAA,EAAA,CAAG,WAAA,EAAa,UAAU,YAAY,CAAA;AACtC,IAAA,IAAI,iBAAA,EAAmB;AACrB,MAAA,EAAA,CAAG,WAAA,EAAa,aAAa,eAAe,CAAA;AAAA,IAC9C;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,GAAA,CAAI,WAAA,EAAa,UAAU,YAAY,CAAA;AACvC,MAAA,IAAI,iBAAA,EAAmB;AACrB,QAAA,GAAA,CAAI,WAAA,EAAa,aAAa,eAAe,CAAA;AAAA,MAC/C;AACA,MAAA,YAAA,CAAa,OAAO,CAAA;AAAA,IACtB,CAAA;AAAA,EACF,GAAG,CAAC,MAAA,EAAQ,QAAA,EAAU,kBAAA,EAAoB,WAAW,CAAC,CAAA;AAEtD,EAAA,OAAO,WAAA;AACT","file":"doc.js","sourcesContent":["import type { RefObject } from \"react\"\nimport { useEffect, useState } from \"react\"\n\ntype ScrollTarget = RefObject<HTMLElement> | Window | null | undefined\ntype EventTargetWithScroll = Window | HTMLElement | Document\n\ninterface UseScrollingOptions {\n debounce?: number\n fallbackToDocument?: boolean\n}\n\nexport function useScrolling(\n target?: ScrollTarget,\n options: UseScrollingOptions = {}\n): boolean {\n const { debounce = 150, fallbackToDocument = true } = options\n const [isScrolling, setIsScrolling] = useState(false)\n\n useEffect(() => {\n // Resolve element or window\n const element: EventTargetWithScroll =\n target && typeof Window !== \"undefined\" && target instanceof Window\n ? target\n : ((target as RefObject<HTMLElement>)?.current ?? window)\n\n // Mobile: fallback to document when using window\n const eventTarget: EventTargetWithScroll =\n fallbackToDocument &&\n element === window &&\n typeof document !== \"undefined\"\n ? document\n : element\n\n const on = (\n el: EventTargetWithScroll,\n event: string,\n handler: EventListener\n ) => el.addEventListener(event, handler, true)\n\n const off = (\n el: EventTargetWithScroll,\n event: string,\n handler: EventListener\n ) => el.removeEventListener(event, handler)\n\n let timeout: ReturnType<typeof setTimeout>\n const supportsScrollEnd = element === window && \"onscrollend\" in window\n\n const handleScroll: EventListener = () => {\n if (!isScrolling) setIsScrolling(true)\n\n if (!supportsScrollEnd) {\n clearTimeout(timeout)\n timeout = setTimeout(() => setIsScrolling(false), debounce)\n }\n }\n\n const handleScrollEnd: EventListener = () => setIsScrolling(false)\n\n on(eventTarget, \"scroll\", handleScroll)\n if (supportsScrollEnd) {\n on(eventTarget, \"scrollend\", handleScrollEnd)\n }\n\n return () => {\n off(eventTarget, \"scroll\", handleScroll)\n if (supportsScrollEnd) {\n off(eventTarget, \"scrollend\", handleScrollEnd)\n }\n clearTimeout(timeout)\n }\n }, [target, debounce, fallbackToDocument, isScrolling])\n\n return isScrolling\n}\n"]}
|
package/dist/docx.d.ts
CHANGED
|
@@ -104,6 +104,14 @@ interface ParseDocxResult {
|
|
|
104
104
|
header: Record<string, unknown> | null;
|
|
105
105
|
/** 默认页脚的结构化内容,同上 */
|
|
106
106
|
footer: Record<string, unknown> | null;
|
|
107
|
+
/**
|
|
108
|
+
* 脚注。**键是正文上标标记 `[n]` 里的编号**(按引用出现顺序 1 起编),
|
|
109
|
+
* 宿主拿 `footnotes["1"]` 就是正文里 `[1]` 指的那条 —— 不用自己解 w:id。
|
|
110
|
+
* 编辑器没有脚注节点,所以注文不进文档树、导出 docx 时也不会写回。
|
|
111
|
+
*/
|
|
112
|
+
footnotes: Record<string, Record<string, unknown>>;
|
|
113
|
+
/** 尾注,键的语义同 `footnotes`(编号序列与脚注各自独立) */
|
|
114
|
+
endnotes: Record<string, Record<string, unknown>>;
|
|
107
115
|
/** 节属性原件,交给导出侧原样写回 */
|
|
108
116
|
section: DocxSection;
|
|
109
117
|
}
|
|
@@ -276,7 +284,14 @@ interface ImportDocxContext {
|
|
|
276
284
|
* 但它只活在内存里:刷新页面 / 换设备就没了,要跨会话往返得自己存。
|
|
277
285
|
*/
|
|
278
286
|
section: DocxSection;
|
|
287
|
+
/**
|
|
288
|
+
* 脚注。**键是正文上标标记 `[n]` 里的编号**(按引用出现顺序 1 起编)——
|
|
289
|
+
* 宿主拿 `footnotes["1"]` 就是正文 `[1]` 指的那条,不用自己解 w:id。
|
|
290
|
+
* 编辑器没有脚注节点:注文不进文档树,导出 docx 时也不会写回
|
|
291
|
+
* (导入时 warnings 里会明说)。
|
|
292
|
+
*/
|
|
279
293
|
footnotes: Record<string, JSONContent>;
|
|
294
|
+
/** 尾注,键的语义同 `footnotes`(编号序列与脚注各自独立) */
|
|
280
295
|
endnotes: Record<string, JSONContent>;
|
|
281
296
|
}
|
|
282
297
|
interface ImportDocxCommandArgs {
|
package/dist/docx.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import { getCodeBlockTitle } from './chunk-ZY5KLA7T.js';
|
|
1
2
|
import { Node, mergeAttributes, Extension } from '@tiptap/core';
|
|
2
3
|
import { unzipSync, zipSync } from 'fflate';
|
|
3
4
|
|
|
4
|
-
// src/docx/index.ts
|
|
5
|
-
|
|
6
5
|
// src/docx/measure.ts
|
|
7
6
|
function measureContentWidth(dom) {
|
|
8
7
|
const el = dom;
|
|
@@ -142,9 +141,23 @@ function parseDocx(entries, opts) {
|
|
|
142
141
|
paraSpacing: 0,
|
|
143
142
|
paraIndent: 0,
|
|
144
143
|
lists: 0,
|
|
145
|
-
listItems: 0
|
|
144
|
+
listItems: 0,
|
|
145
|
+
footnotes: 0,
|
|
146
|
+
endnotes: 0
|
|
146
147
|
};
|
|
147
148
|
const warnings = [];
|
|
149
|
+
const noteNumbers = {
|
|
150
|
+
footnote: /* @__PURE__ */ new Map(),
|
|
151
|
+
endnote: /* @__PURE__ */ new Map()
|
|
152
|
+
};
|
|
153
|
+
function noteNumber(kind, id) {
|
|
154
|
+
const seq = noteNumbers[kind];
|
|
155
|
+
const hit = seq.get(id);
|
|
156
|
+
if (hit !== void 0) return hit;
|
|
157
|
+
const n = seq.size + 1;
|
|
158
|
+
seq.set(id, n);
|
|
159
|
+
return n;
|
|
160
|
+
}
|
|
148
161
|
const text = (p) => {
|
|
149
162
|
const b = entries.read(p);
|
|
150
163
|
return b ? decoder.decode(b) : null;
|
|
@@ -379,6 +392,17 @@ function parseDocx(entries, opts) {
|
|
|
379
392
|
if (!n) continue;
|
|
380
393
|
if (n.type === "image") out.blocks.push(n);
|
|
381
394
|
else out.inline.push(n);
|
|
395
|
+
} else if (t === "w:footnoteReference" || t === "w:endnoteReference") {
|
|
396
|
+
const id = c.getAttribute("w:id");
|
|
397
|
+
if (!id) continue;
|
|
398
|
+
const kind = t === "w:footnoteReference" ? "footnote" : "endnote";
|
|
399
|
+
const n = noteNumber(kind, id);
|
|
400
|
+
const hasSuper = marks.some((m) => m.type === "superscript");
|
|
401
|
+
out.inline.push({
|
|
402
|
+
type: "text",
|
|
403
|
+
text: `[${n}]`,
|
|
404
|
+
marks: hasSuper ? marks : [...marks, { type: "superscript" }]
|
|
405
|
+
});
|
|
382
406
|
} else if (t === "w:pict") {
|
|
383
407
|
warnings.push("遇到 VML 图形(w:pict),未处理");
|
|
384
408
|
}
|
|
@@ -706,6 +730,17 @@ function parseDocx(entries, opts) {
|
|
|
706
730
|
if (!body) throw new Error("docx 缺少 w:body");
|
|
707
731
|
const content = blocksOf(body);
|
|
708
732
|
const doc = remapTypes({ type: "doc", content }, opts.prosemirrorNodes, opts.prosemirrorMarks);
|
|
733
|
+
const footnotes = notesOf("word/footnotes.xml", "w:footnote", "footnote");
|
|
734
|
+
const endnotes = notesOf("word/endnotes.xml", "w:endnote", "endnote");
|
|
735
|
+
if (recovered.footnotes || recovered.endnotes) {
|
|
736
|
+
const parts = [
|
|
737
|
+
...recovered.footnotes ? [`${recovered.footnotes} 条脚注`] : [],
|
|
738
|
+
...recovered.endnotes ? [`${recovered.endnotes} 条尾注`] : []
|
|
739
|
+
];
|
|
740
|
+
warnings.push(
|
|
741
|
+
`文档有 ${parts.join("和")}:正文引用以上标 [n] 文本保留,注文在导入结果的 footnotes / endnotes 里(键即编号 n)。编辑器没有脚注节点,导出 docx 时不会写回`
|
|
742
|
+
);
|
|
743
|
+
}
|
|
709
744
|
const section = readSection();
|
|
710
745
|
const defaultHeader = section.refs.find((r) => r.kind === "header" && r.type === "default");
|
|
711
746
|
const defaultFooter = section.refs.find((r) => r.kind === "footer" && r.type === "default");
|
|
@@ -716,8 +751,30 @@ function parseDocx(entries, opts) {
|
|
|
716
751
|
...opts.cssStyles ? { css: extractCss(stylesDoc) } : {},
|
|
717
752
|
header: defaultHeader ? partContent(defaultHeader.path, "w:hdr") : null,
|
|
718
753
|
footer: defaultFooter ? partContent(defaultFooter.path, "w:ftr") : null,
|
|
754
|
+
footnotes,
|
|
755
|
+
endnotes,
|
|
719
756
|
section
|
|
720
757
|
};
|
|
758
|
+
function notesOf(path, tag, kind) {
|
|
759
|
+
const d = xml(path);
|
|
760
|
+
if (!d) return {};
|
|
761
|
+
const out = {};
|
|
762
|
+
for (const el of Array.from(d.getElementsByTagName(tag))) {
|
|
763
|
+
const type = el.getAttribute("w:type");
|
|
764
|
+
if (type && type !== "normal") continue;
|
|
765
|
+
const id = el.getAttribute("w:id");
|
|
766
|
+
if (id === null) continue;
|
|
767
|
+
const blocks = blocksOf(el);
|
|
768
|
+
if (!blocks.length) continue;
|
|
769
|
+
out[String(noteNumber(kind, id))] = remapTypes(
|
|
770
|
+
{ type: "doc", content: blocks },
|
|
771
|
+
opts.prosemirrorNodes,
|
|
772
|
+
opts.prosemirrorMarks
|
|
773
|
+
);
|
|
774
|
+
recovered[`${kind}s`] += 1;
|
|
775
|
+
}
|
|
776
|
+
return out;
|
|
777
|
+
}
|
|
721
778
|
function partContent(path, root) {
|
|
722
779
|
const d = xml(path);
|
|
723
780
|
const el = d?.getElementsByTagName(root)[0];
|
|
@@ -1162,7 +1219,26 @@ function serializeDocx(doc, opts = {}) {
|
|
|
1162
1219
|
});
|
|
1163
1220
|
return `${xml}</w:tbl>`;
|
|
1164
1221
|
}
|
|
1165
|
-
function
|
|
1222
|
+
function codeBlock(n) {
|
|
1223
|
+
return `<w:p><w:pPr><w:pStyle w:val="Code"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="Consolas" w:hAnsi="Consolas"/></w:rPr><w:t xml:space="preserve">${esc(collectText(n))}</w:t></w:r></w:p>`;
|
|
1224
|
+
}
|
|
1225
|
+
function indentPr(indent) {
|
|
1226
|
+
return indent ? `<w:pPr><w:ind w:left="${indent}"/></w:pPr>` : "";
|
|
1227
|
+
}
|
|
1228
|
+
function boldParagraph(text, indent) {
|
|
1229
|
+
return `<w:p>${indentPr(indent)}<w:r><w:rPr><w:b/></w:rPr><w:t xml:space="preserve">${esc(text)}</w:t></w:r></w:p>`;
|
|
1230
|
+
}
|
|
1231
|
+
function apiParamHeader(n, indent) {
|
|
1232
|
+
const a = n.attrs ?? {};
|
|
1233
|
+
const runs = [];
|
|
1234
|
+
if (a.name) runs.push(`<w:r><w:rPr><w:b/></w:rPr><w:t xml:space="preserve">${esc(a.name)}</w:t></w:r>`);
|
|
1235
|
+
if (a.type) runs.push(`<w:r><w:rPr><w:rFonts w:ascii="Consolas" w:hAnsi="Consolas"/></w:rPr><w:t xml:space="preserve"> ${esc(a.type)}</w:t></w:r>`);
|
|
1236
|
+
if (a.required) runs.push(`<w:r><w:t xml:space="preserve"> 必选</w:t></w:r>`);
|
|
1237
|
+
if (a.default != null) runs.push(`<w:r><w:t xml:space="preserve"> 默认值 ${esc(a.default)}</w:t></w:r>`);
|
|
1238
|
+
if (a.summary) runs.push(`<w:r><w:t xml:space="preserve"> | ${esc(a.summary)}</w:t></w:r>`);
|
|
1239
|
+
return `<w:p>${indentPr(indent)}${runs.join("")}</w:p>`;
|
|
1240
|
+
}
|
|
1241
|
+
function blocks(nodes, indent = 0) {
|
|
1166
1242
|
const out = [];
|
|
1167
1243
|
for (const n of nodes) {
|
|
1168
1244
|
switch (n.type) {
|
|
@@ -1170,7 +1246,7 @@ function serializeDocx(doc, opts = {}) {
|
|
|
1170
1246
|
out.push(heading(n));
|
|
1171
1247
|
break;
|
|
1172
1248
|
case "paragraph":
|
|
1173
|
-
out.push(paragraph(n));
|
|
1249
|
+
out.push(paragraph(n, [], indent || void 0));
|
|
1174
1250
|
break;
|
|
1175
1251
|
case "bulletList":
|
|
1176
1252
|
case "orderedList":
|
|
@@ -1183,7 +1259,32 @@ function serializeDocx(doc, opts = {}) {
|
|
|
1183
1259
|
for (const c of n.content ?? []) out.push(paragraph(c, [], 720));
|
|
1184
1260
|
break;
|
|
1185
1261
|
case "codeBlock":
|
|
1186
|
-
out.push(
|
|
1262
|
+
out.push(codeBlock(n));
|
|
1263
|
+
break;
|
|
1264
|
+
case "codeGroup":
|
|
1265
|
+
for (const child of n.content ?? []) {
|
|
1266
|
+
if (child.type !== "codeBlock") {
|
|
1267
|
+
warnings.push(`codeGroup 里出现非代码块节点 "${child.type}",已跳过`);
|
|
1268
|
+
continue;
|
|
1269
|
+
}
|
|
1270
|
+
out.push(`<w:p><w:r><w:rPr><w:b/></w:rPr><w:t xml:space="preserve">${esc(codeLabel(child))}</w:t></w:r></w:p>`);
|
|
1271
|
+
out.push(codeBlock(child));
|
|
1272
|
+
}
|
|
1273
|
+
break;
|
|
1274
|
+
case "details":
|
|
1275
|
+
out.push(boldParagraph(String(n.attrs?.title ?? "") || "详情", indent));
|
|
1276
|
+
out.push(blocks(n.content ?? [], indent));
|
|
1277
|
+
break;
|
|
1278
|
+
case "callout": {
|
|
1279
|
+
const type = String(n.attrs?.type ?? "info");
|
|
1280
|
+
const title = String(n.attrs?.title ?? "") || calloutDefaultTitle(type);
|
|
1281
|
+
out.push(boldParagraph(title, indent));
|
|
1282
|
+
out.push(blocks(n.content ?? [], indent + 720));
|
|
1283
|
+
break;
|
|
1284
|
+
}
|
|
1285
|
+
case "apiParam":
|
|
1286
|
+
out.push(apiParamHeader(n, indent));
|
|
1287
|
+
out.push(blocks(n.content ?? [], indent + 720));
|
|
1187
1288
|
break;
|
|
1188
1289
|
case "horizontalRule":
|
|
1189
1290
|
out.push('<w:p><w:pPr><w:pBdr><w:bottom w:val="single" w:sz="6" w:color="auto"/></w:pBdr></w:pPr></w:p>');
|
|
@@ -1280,6 +1381,13 @@ function cssFontStack(v) {
|
|
|
1280
1381
|
if (!parts.length) return null;
|
|
1281
1382
|
return { ascii: parts[0], eastAsia: parts[parts.length - 1] };
|
|
1282
1383
|
}
|
|
1384
|
+
function calloutDefaultTitle(type) {
|
|
1385
|
+
return { info: "信息", tip: "提示", warning: "注意", danger: "危险" }[type] ?? "信息";
|
|
1386
|
+
}
|
|
1387
|
+
function codeLabel(n) {
|
|
1388
|
+
const attrs = n.attrs ?? {};
|
|
1389
|
+
return getCodeBlockTitle({ language: attrs.language ?? null, label: attrs.label ?? null });
|
|
1390
|
+
}
|
|
1283
1391
|
function collectText(n) {
|
|
1284
1392
|
if (n?.type === "text") return n.text ?? "";
|
|
1285
1393
|
return (n?.content ?? []).map(collectText).join("");
|
|
@@ -1542,8 +1650,8 @@ var ImportDocx = Extension.create({
|
|
|
1542
1650
|
header: result.header,
|
|
1543
1651
|
footer: result.footer,
|
|
1544
1652
|
section: result.section,
|
|
1545
|
-
footnotes:
|
|
1546
|
-
endnotes:
|
|
1653
|
+
footnotes: result.footnotes,
|
|
1654
|
+
endnotes: result.endnotes
|
|
1547
1655
|
});
|
|
1548
1656
|
} catch (e) {
|
|
1549
1657
|
const err = e instanceof Error ? e : new Error(String(e));
|