@blocklet/editor 2.6.17 → 2.6.19

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.
@@ -0,0 +1 @@
1
+ export declare function formatUrl(url: string): string;
@@ -0,0 +1,23 @@
1
+ const PHONE_NUMBER_REGEX = /^\+?[0-9\s()-]{5,}$/;
2
+ export function formatUrl(url) {
3
+ // Check if URL already has a protocol
4
+ if (url.match(/^[a-z][a-z0-9+.-]*:/i)) {
5
+ // URL already has a protocol, leave it as is
6
+ return url;
7
+ }
8
+ // Check if it's a relative path (starting with '/', '.', or '#')
9
+ if (url.match(/^[/#.]/)) {
10
+ // Relative path, leave it as is
11
+ return url;
12
+ }
13
+ // Check for email address
14
+ if (url.includes('@')) {
15
+ return `mailto:${url}`;
16
+ }
17
+ // Check for phone number
18
+ if (PHONE_NUMBER_REGEX.test(url)) {
19
+ return `tel:${url}`;
20
+ }
21
+ // For everything else, return with "./" prefix
22
+ return `./${url}`;
23
+ }
@@ -24,6 +24,7 @@ import useHasNodes from './hooks/useHasNodes';
24
24
  import AutoEmbedPlugin from './plugins/AutoEmbedPlugin';
25
25
  import AutoLinkPlugin from './plugins/AutoLinkPlugin';
26
26
  import ClickableLinkPlugin from './plugins/ClickableLinkPlugin';
27
+ import LinkUrlFixerPlugin from './plugins/LinkUrlFixerPlugin';
27
28
  import CodeHighlightPlugin from './plugins/CodeHighlightPlugin';
28
29
  import CollapsiblePlugin from './plugins/CollapsiblePlugin';
29
30
  import ComponentPickerPlugin from './plugins/ComponentPickerPlugin';
@@ -95,7 +96,7 @@ export default function Editor({ children, prepend, placeholder, onChange, autoF
95
96
  }
96
97
  }, [hasNodes('image'), hasUploader]);
97
98
  if (minimalMode) {
98
- return (_jsxs(_Fragment, { children: [prepend, _jsx(VideoPathFixerPlugin, {}), _jsx(ImagePathFixerPlugin, {}), editable && showToolbar && _jsx(ToolbarPlugin, {}), hasNodes('image') && hasUploader && _jsx(DragDropPaste, {}), autoFocus && _jsx(AutoFocusPlugin, { defaultSelection: "rootEnd" }), _jsx(ClearEditorPlugin, {}), !!editable && _jsx(ComponentPickerPlugin, {}), !!editable && _jsx(MentionsPlugin, {}), hasNodes('link') && _jsx(AutoEmbedPlugin, {}), _jsx(PasteSlackImagePlugin, {}), _jsx(StyledEditorContent, { ref: onRef, className: cx('be-content', editable && 'editable'), children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: cx('be-editable', 'notranslate') }), placeholder: _jsx(Placeholder, { className: "be-placeholder", children: placeholder }), ErrorBoundary: LexicalErrorBoundary }) }), hasNodes('code', 'code-highlight') && _jsx(CodeHighlightPlugin, {}), hasNodes('image') && hasUploader && _jsx(ImagesPlugin, {}), hasNodes('video') && _jsx(VideoPlugin, {}), hasNodes('link') && _jsx(LinkPlugin, {}), hasNodes('autolink') && !!editable && _jsx(AutoLinkPlugin, {}), hasNodes('tweet') && _jsx(TwitterPlugin, {}), hasNodes('youtube') && _jsx(YouTubePlugin, {}), hasNodes('figma') && _jsx(FigmaPlugin, {}), _jsx(PostLinkEmbedPlugin, {}), _jsx(BookmarkPlugin, {}), hasNodes('pdf') && _jsx(PdfPlugin, {}), hasNodes('file') && _jsx(FilePlugin, {}), hasNodes('horizontalrule') && _jsx(HorizontalRulePlugin, {}), hasNodes('excalidraw') && _jsx(ExcalidrawPlugin, {}), hasNodes('alert') && _jsx(AlertPlugin, {}), hasNodes('pages-kit-component') && _jsx(PagesKitComponentPlugin, {}), _jsx(TabFocusPlugin, {}), onChange && _jsx(OnChangePlugin, { onChange: onChange }), floatingAnchorElem && editable && hasNodes('link') && (_jsx(FloatingLinkEditorPlugin, { anchorElem: floatingAnchorElem })), !!characterLimitConfig?.maxLength && ENABLE_EDITOR_PLUGIN_CHAR_LIMIT && (_jsx(CharacterLimitPlugin, { maxLength: characterLimitConfig.maxLength, charLimitIndicatorStyle: characterLimitConfig.indicatorStyle, alignLeft: characterLimitConfig.alignLeft })), editorRef && _jsx(EditorRefPlugin, { editorRef: editorRef }), children] }));
99
+ return (_jsxs(_Fragment, { children: [prepend, _jsx(VideoPathFixerPlugin, {}), _jsx(ImagePathFixerPlugin, {}), editable && showToolbar && _jsx(ToolbarPlugin, {}), hasNodes('image') && hasUploader && _jsx(DragDropPaste, {}), autoFocus && _jsx(AutoFocusPlugin, { defaultSelection: "rootEnd" }), _jsx(ClearEditorPlugin, {}), !!editable && _jsx(ComponentPickerPlugin, {}), !!editable && _jsx(MentionsPlugin, {}), hasNodes('link') && _jsx(AutoEmbedPlugin, {}), _jsx(PasteSlackImagePlugin, {}), _jsx(StyledEditorContent, { ref: onRef, className: cx('be-content', editable && 'editable'), children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: cx('be-editable', 'notranslate') }), placeholder: _jsx(Placeholder, { className: "be-placeholder", children: placeholder }), ErrorBoundary: LexicalErrorBoundary }) }), hasNodes('code', 'code-highlight') && _jsx(CodeHighlightPlugin, {}), hasNodes('image') && hasUploader && _jsx(ImagesPlugin, {}), hasNodes('video') && _jsx(VideoPlugin, {}), hasNodes('link') && _jsx(LinkPlugin, {}), hasNodes('link') && _jsx(LinkUrlFixerPlugin, {}), hasNodes('autolink') && !!editable && _jsx(AutoLinkPlugin, {}), hasNodes('tweet') && _jsx(TwitterPlugin, {}), hasNodes('youtube') && _jsx(YouTubePlugin, {}), hasNodes('figma') && _jsx(FigmaPlugin, {}), _jsx(PostLinkEmbedPlugin, {}), _jsx(BookmarkPlugin, {}), hasNodes('pdf') && _jsx(PdfPlugin, {}), hasNodes('file') && _jsx(FilePlugin, {}), hasNodes('horizontalrule') && _jsx(HorizontalRulePlugin, {}), hasNodes('excalidraw') && _jsx(ExcalidrawPlugin, {}), hasNodes('alert') && _jsx(AlertPlugin, {}), hasNodes('pages-kit-component') && _jsx(PagesKitComponentPlugin, {}), _jsx(TabFocusPlugin, {}), onChange && _jsx(OnChangePlugin, { onChange: onChange }), floatingAnchorElem && editable && hasNodes('link') && (_jsx(FloatingLinkEditorPlugin, { anchorElem: floatingAnchorElem })), !!characterLimitConfig?.maxLength && ENABLE_EDITOR_PLUGIN_CHAR_LIMIT && (_jsx(CharacterLimitPlugin, { maxLength: characterLimitConfig.maxLength, charLimitIndicatorStyle: characterLimitConfig.indicatorStyle, alignLeft: characterLimitConfig.alignLeft })), editorRef && _jsx(EditorRefPlugin, { editorRef: editorRef }), children] }));
99
100
  }
100
- return (_jsxs(_Fragment, { children: [prepend, _jsx(VideoPathFixerPlugin, {}), _jsx(ImagePathFixerPlugin, {}), editable && showToolbar && _jsx(ToolbarPlugin, {}), !!characterLimitConfig?.maxLength && ENABLE_EDITOR_PLUGIN_CHAR_LIMIT && (_jsx(CharacterLimitPlugin, { maxLength: characterLimitConfig.maxLength, charLimitIndicatorStyle: characterLimitConfig.indicatorStyle, alignLeft: characterLimitConfig.alignLeft })), hasNodes('image') && hasUploader && _jsx(DragDropPaste, {}), autoFocus && _jsx(AutoFocusPlugin, { defaultSelection: "rootEnd" }), _jsx(ClearEditorPlugin, {}), !!editable && _jsx(ComponentPickerPlugin, {}), hasNodes('link') && _jsx(AutoEmbedPlugin, {}), !!editable && _jsx(MentionsPlugin, {}), hasNodes('autolink') && !!editable && _jsx(AutoLinkPlugin, {}), _jsxs(_Fragment, { children: [_jsx(PasteSlackImagePlugin, {}), _jsx(HistoryPlugin, { externalHistoryState: historyState }), _jsx(StyledEditorContent, { ref: onRef, className: cx('be-content', editable && 'editable'), children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: cx('be-editable', 'notranslate') }), placeholder: _jsx(Placeholder, { className: "be-placeholder", children: placeholder }), ErrorBoundary: LexicalErrorBoundary }) }), _jsx(MarkdownShortcutPlugin, {}), _jsx(TabIndentationPlugin, {}), hasNodes('code', 'code-highlight') && _jsx(CodeHighlightPlugin, {}), hasNodes('list', 'listitem') && _jsx(ListPlugin, {}), hasNodes('list', 'listitem') && _jsx(CheckListPlugin, {}), hasNodes('table', 'tablerow', 'tablecell') && (_jsx(TablePlugin, { hasCellMerge: true, hasCellBackgroundColor: true, hasHorizontalScroll: true })), hasNodes('table', 'tablerow', 'tablecell') && _jsx(TableCellResizer, {}), hasNodes('image') && hasUploader && _jsx(ImagesPlugin, {}), hasNodes('video') && _jsx(VideoPlugin, {}), hasNodes('link') && _jsx(LinkPlugin, {}), hasNodes('tweet') && _jsx(TwitterPlugin, {}), hasNodes('youtube') && _jsx(YouTubePlugin, {}), hasNodes('figma') && _jsx(FigmaPlugin, {}), _jsx(BilibiliPlugin, {}), _jsx(BlockletEmbedPlugin, {}), _jsx(PostLinkEmbedPlugin, {}), _jsx(BookmarkPlugin, {}), _jsx(AidePlugin, {}), hasNodes('pdf') && _jsx(PdfPlugin, {}), hasNodes('file') && _jsx(FilePlugin, {}), hasNodes('link') && _jsx(ClickableLinkPlugin, {}), hasNodes('horizontalrule') && _jsx(HorizontalRulePlugin, {}), hasNodes('excalidraw') && _jsx(ExcalidrawPlugin, {}), hasNodes('alert') && _jsx(AlertPlugin, {}), hasNodes('pages-kit-component') && _jsx(PagesKitComponentPlugin, {}), _jsx(TabFocusPlugin, {}), hasNodes('collapsible-container', 'collapsible-content', 'collapsible-title') && _jsx(CollapsiblePlugin, {}), onChange && _jsx(OnChangePlugin, { onChange: onChange }), floatingAnchorElem && editable && (_jsxs(_Fragment, { children: [_jsx(DraggableBlockPlugin, { anchorElem: floatingAnchorElem }), hasNodes('link') && _jsx(FloatingLinkEditorPlugin, { anchorElem: floatingAnchorElem }), hasNodes('table') && _jsx(TableCellActionMenuPlugin, { anchorElem: floatingAnchorElem, cellMerge: true }), _jsx(FloatingTextFormatToolbarPlugin, { anchorElem: floatingAnchorElem })] })), enableHeadingsIdPlugin && _jsx(HeadingsIdPlugin, {})] }), _jsx(EditorHolderPlugin, {}), editorRef && _jsx(EditorRefPlugin, { editorRef: editorRef }), onReady && _jsx(EditorReadyPlugin, { onReady: onReady }), config.enableSafeAreaPlugin && _jsx(SafeAreaPlugin, {}), children] }));
101
+ return (_jsxs(_Fragment, { children: [prepend, _jsx(VideoPathFixerPlugin, {}), _jsx(ImagePathFixerPlugin, {}), editable && showToolbar && _jsx(ToolbarPlugin, {}), !!characterLimitConfig?.maxLength && ENABLE_EDITOR_PLUGIN_CHAR_LIMIT && (_jsx(CharacterLimitPlugin, { maxLength: characterLimitConfig.maxLength, charLimitIndicatorStyle: characterLimitConfig.indicatorStyle, alignLeft: characterLimitConfig.alignLeft })), hasNodes('image') && hasUploader && _jsx(DragDropPaste, {}), autoFocus && _jsx(AutoFocusPlugin, { defaultSelection: "rootEnd" }), _jsx(ClearEditorPlugin, {}), !!editable && _jsx(ComponentPickerPlugin, {}), hasNodes('link') && _jsx(AutoEmbedPlugin, {}), !!editable && _jsx(MentionsPlugin, {}), hasNodes('autolink') && !!editable && _jsx(AutoLinkPlugin, {}), _jsxs(_Fragment, { children: [_jsx(PasteSlackImagePlugin, {}), _jsx(HistoryPlugin, { externalHistoryState: historyState }), _jsx(StyledEditorContent, { ref: onRef, className: cx('be-content', editable && 'editable'), children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: cx('be-editable', 'notranslate') }), placeholder: _jsx(Placeholder, { className: "be-placeholder", children: placeholder }), ErrorBoundary: LexicalErrorBoundary }) }), _jsx(MarkdownShortcutPlugin, {}), _jsx(TabIndentationPlugin, {}), hasNodes('code', 'code-highlight') && _jsx(CodeHighlightPlugin, {}), hasNodes('list', 'listitem') && _jsx(ListPlugin, {}), hasNodes('list', 'listitem') && _jsx(CheckListPlugin, {}), hasNodes('table', 'tablerow', 'tablecell') && (_jsx(TablePlugin, { hasCellMerge: true, hasCellBackgroundColor: true, hasHorizontalScroll: true })), hasNodes('table', 'tablerow', 'tablecell') && _jsx(TableCellResizer, {}), hasNodes('image') && hasUploader && _jsx(ImagesPlugin, {}), hasNodes('video') && _jsx(VideoPlugin, {}), hasNodes('link') && _jsx(LinkPlugin, {}), hasNodes('link') && _jsx(LinkUrlFixerPlugin, {}), hasNodes('tweet') && _jsx(TwitterPlugin, {}), hasNodes('youtube') && _jsx(YouTubePlugin, {}), hasNodes('figma') && _jsx(FigmaPlugin, {}), _jsx(BilibiliPlugin, {}), _jsx(BlockletEmbedPlugin, {}), _jsx(PostLinkEmbedPlugin, {}), _jsx(BookmarkPlugin, {}), _jsx(AidePlugin, {}), hasNodes('pdf') && _jsx(PdfPlugin, {}), hasNodes('file') && _jsx(FilePlugin, {}), hasNodes('link') && _jsx(ClickableLinkPlugin, {}), hasNodes('horizontalrule') && _jsx(HorizontalRulePlugin, {}), hasNodes('excalidraw') && _jsx(ExcalidrawPlugin, {}), hasNodes('alert') && _jsx(AlertPlugin, {}), hasNodes('pages-kit-component') && _jsx(PagesKitComponentPlugin, {}), _jsx(TabFocusPlugin, {}), hasNodes('collapsible-container', 'collapsible-content', 'collapsible-title') && _jsx(CollapsiblePlugin, {}), onChange && _jsx(OnChangePlugin, { onChange: onChange }), floatingAnchorElem && editable && (_jsxs(_Fragment, { children: [_jsx(DraggableBlockPlugin, { anchorElem: floatingAnchorElem }), hasNodes('link') && _jsx(FloatingLinkEditorPlugin, { anchorElem: floatingAnchorElem }), hasNodes('table') && _jsx(TableCellActionMenuPlugin, { anchorElem: floatingAnchorElem, cellMerge: true }), _jsx(FloatingTextFormatToolbarPlugin, { anchorElem: floatingAnchorElem })] })), enableHeadingsIdPlugin && _jsx(HeadingsIdPlugin, {})] }), _jsx(EditorHolderPlugin, {}), editorRef && _jsx(EditorRefPlugin, { editorRef: editorRef }), onReady && _jsx(EditorReadyPlugin, { onReady: onReady }), config.enableSafeAreaPlugin && _jsx(SafeAreaPlugin, {}), children] }));
101
102
  }
@@ -6,6 +6,7 @@ import { useEffect } from 'react';
6
6
  import { useParams, useNavigate } from 'react-router-dom';
7
7
  import { useEditorConfig } from '../../../config';
8
8
  import { getUTMUrl } from '../../../libs/utm';
9
+ import { formatUrl } from '../../../libs/utils';
9
10
  function findMatchingDOM(startNode, predicate) {
10
11
  let node = startNode;
11
12
  while (node != null) {
@@ -25,29 +26,6 @@ function isSameOrigin(url) {
25
26
  return false;
26
27
  }
27
28
  }
28
- const PHONE_NUMBER_REGEX = /^\+?[0-9\s()-]{5,}$/;
29
- function formatUrl(url) {
30
- // Check if URL already has a protocol
31
- if (url.match(/^[a-z][a-z0-9+.-]*:/i)) {
32
- // URL already has a protocol, leave it as is
33
- return url;
34
- }
35
- // Check if it's a relative path (starting with '/', '.', or '#')
36
- if (url.match(/^[/#.]/)) {
37
- // Relative path, leave it as is
38
- return url;
39
- }
40
- // Check for email address
41
- if (url.includes('@')) {
42
- return `mailto:${url}`;
43
- }
44
- // Check for phone number
45
- if (PHONE_NUMBER_REGEX.test(url)) {
46
- return `tel:${url}`;
47
- }
48
- // For everything else, return with "./" prefix
49
- return `./${url}`;
50
- }
51
29
  /**
52
30
  * 代码复制自 @lexical/react/LexicalClickableLinkPlugin, 逻辑改动:
53
31
  * - url origin 与 window.location.origin 相同时, 避免 newTab 方式跳转
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Plugin that transforms invalid link URLs to valid ones by adding "./" prefix
3
+ * This ensures links like "example" become "./example"
4
+ */
5
+ export default function LinkUrlFixerPlugin(): null;
@@ -0,0 +1,24 @@
1
+ import { $isLinkNode, LinkNode } from '@lexical/link';
2
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
3
+ import { useEffect } from 'react';
4
+ import { formatUrl } from '../../../libs/utils';
5
+ /**
6
+ * Plugin that transforms invalid link URLs to valid ones by adding "./" prefix
7
+ * This ensures links like "example" become "./example"
8
+ */
9
+ export default function LinkUrlFixerPlugin() {
10
+ const [editor] = useLexicalComposerContext();
11
+ useEffect(() => {
12
+ return editor.registerNodeTransform(LinkNode, (node) => {
13
+ if (!$isLinkNode(node)) {
14
+ return;
15
+ }
16
+ const url = node.getURL();
17
+ const formattedUrl = formatUrl(url);
18
+ if (formattedUrl !== url) {
19
+ node.setURL(formattedUrl);
20
+ }
21
+ });
22
+ }, [editor]);
23
+ return null;
24
+ }
@@ -9,6 +9,7 @@ import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
9
9
  import { TablePlugin } from '@lexical/react/LexicalTablePlugin';
10
10
  import useHasNodes from '../hooks/useHasNodes';
11
11
  import ClickableLinkPlugin from '../plugins/ClickableLinkPlugin';
12
+ import LinkUrlFixerPlugin from '../plugins/LinkUrlFixerPlugin';
12
13
  import CodeHighlightPlugin from '../plugins/CodeHighlightPlugin';
13
14
  import CollapsiblePlugin from '../plugins/CollapsiblePlugin';
14
15
  import MarkdownShortcutPlugin from '../plugins/MarkdownShortcutPlugin';
@@ -27,5 +28,5 @@ import { useFixInvalidPostLinkNodes } from '../../ext/PostLinkEmbedPlugin/fixInv
27
28
  export function EditorViewer({ children, prepend, onChange, editorRef, onReady, enableHeadingsIdPlugin, onCheckboxChange, }) {
28
29
  const hasNodes = useHasNodes();
29
30
  useFixInvalidPostLinkNodes();
30
- return (_jsxs(_Fragment, { children: [prepend, _jsx(VideoPathFixerPlugin, {}), _jsx(ImagePathFixerPlugin, {}), _jsx(StyledEditorContent, { className: "be-content", children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: cx('be-editable', 'notranslate') }), ErrorBoundary: LexicalErrorBoundary }) }), _jsx(MarkdownShortcutPlugin, {}), hasNodes('code', 'code-highlight') && _jsx(CodeHighlightPlugin, {}), hasNodes('list', 'listitem') && _jsx(ListPlugin, {}), hasNodes('list', 'listitem') && _jsx(CheckListPlugin, {}), hasNodes('link') && _jsx(LinkPlugin, {}), hasNodes('link') && _jsx(ClickableLinkPlugin, {}), _jsx(TabFocusPlugin, {}), hasNodes('table', 'tablerow', 'tablecell') && (_jsx(TablePlugin, { hasCellMerge: true, hasCellBackgroundColor: true, hasHorizontalScroll: true })), hasNodes('collapsible-container', 'collapsible-content', 'collapsible-title') && _jsx(CollapsiblePlugin, {}), onChange && _jsx(OnChangePlugin, { onChange: onChange }), enableHeadingsIdPlugin && _jsx(HeadingsIdPlugin, {}), _jsx(EditorHolderPlugin, {}), editorRef && _jsx(EditorRefPlugin, { editorRef: editorRef }), onReady && _jsx(EditorReadyPlugin, { onReady: onReady }), _jsx(CheckboxPlugin, { send: onCheckboxChange }), children] }));
31
+ return (_jsxs(_Fragment, { children: [prepend, _jsx(VideoPathFixerPlugin, {}), _jsx(ImagePathFixerPlugin, {}), _jsx(StyledEditorContent, { className: "be-content", children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: cx('be-editable', 'notranslate') }), ErrorBoundary: LexicalErrorBoundary }) }), _jsx(MarkdownShortcutPlugin, {}), hasNodes('code', 'code-highlight') && _jsx(CodeHighlightPlugin, {}), hasNodes('list', 'listitem') && _jsx(ListPlugin, {}), hasNodes('list', 'listitem') && _jsx(CheckListPlugin, {}), hasNodes('link') && _jsx(LinkPlugin, {}), hasNodes('link') && _jsx(ClickableLinkPlugin, {}), hasNodes('link') && _jsx(LinkUrlFixerPlugin, {}), _jsx(TabFocusPlugin, {}), hasNodes('table', 'tablerow', 'tablecell') && (_jsx(TablePlugin, { hasCellMerge: true, hasCellBackgroundColor: true, hasHorizontalScroll: true })), hasNodes('collapsible-container', 'collapsible-content', 'collapsible-title') && _jsx(CollapsiblePlugin, {}), onChange && _jsx(OnChangePlugin, { onChange: onChange }), enableHeadingsIdPlugin && _jsx(HeadingsIdPlugin, {}), _jsx(EditorHolderPlugin, {}), editorRef && _jsx(EditorRefPlugin, { editorRef: editorRef }), onReady && _jsx(EditorReadyPlugin, { onReady: onReady }), _jsx(CheckboxPlugin, { send: onCheckboxChange }), children] }));
31
32
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/editor",
3
- "version": "2.6.17",
3
+ "version": "2.6.19",
4
4
  "main": "lib/index.js",
5
5
  "sideEffects": false,
6
6
  "publishConfig": {
@@ -73,7 +73,7 @@
73
73
  "ufo": "^1.5.4",
74
74
  "url-join": "^4.0.1",
75
75
  "zustand": "^4.5.5",
76
- "@blocklet/pdf": "2.6.17"
76
+ "@blocklet/pdf": "2.6.19"
77
77
  },
78
78
  "devDependencies": {
79
79
  "@babel/core": "^7.25.2",