@blocklet/editor 2.2.39 → 2.2.41

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.
@@ -1,3 +1,9 @@
1
1
  /// <reference types="react" />
2
2
  export declare function isMarkdownText(text: string): boolean;
3
+ /**
4
+ *
5
+ * 测试集 https://markdownlivepreview.com/
6
+ * @export
7
+ * @return {*} {(JSX.Element | null)}
8
+ */
3
9
  export default function PasteMarkdownPlugin(): JSX.Element | null;
@@ -6,7 +6,7 @@ import isEmpty from 'lodash/isEmpty';
6
6
  import { lexer } from 'marked';
7
7
  import { isValidUrl } from '../utils';
8
8
  import { CUSTOM_TRANSFORMERS } from './CustomTransformers';
9
- function isHtml(str) {
9
+ function isPureHtml(str) {
10
10
  const doc = new DOMParser().parseFromString(str, 'text/html');
11
11
  return Array.from(doc.body.childNodes).some((node) => node.nodeType === 1);
12
12
  }
@@ -17,7 +17,7 @@ export function isMarkdownText(text) {
17
17
  if (isEmpty(text.trim())) {
18
18
  return false;
19
19
  }
20
- if (isHtml(text)) {
20
+ if (isPureHtml(text)) {
21
21
  return false;
22
22
  }
23
23
  if (isValidUrl(text)) {
@@ -39,6 +39,7 @@ export function isMarkdownText(text) {
39
39
  }
40
40
  function getMarkdownText(e) {
41
41
  const markdownText = e.clipboardData?.types
42
+ .filter((type) => ['text/markdown', 'text/plain', 'text/html'].includes(type))
42
43
  .map((type) => {
43
44
  const data = e.clipboardData?.getData(type);
44
45
  return data;
@@ -46,6 +47,12 @@ function getMarkdownText(e) {
46
47
  .find((data) => data && isMarkdownText(data));
47
48
  return markdownText;
48
49
  }
50
+ /**
51
+ *
52
+ * 测试集 https://markdownlivepreview.com/
53
+ * @export
54
+ * @return {*} {(JSX.Element | null)}
55
+ */
49
56
  export default function PasteMarkdownPlugin() {
50
57
  const [editor] = useLexicalComposerContext();
51
58
  useEffect(() => {
@@ -72,16 +79,16 @@ export default function PasteMarkdownPlugin() {
72
79
  // 判断光标在文本中的位置
73
80
  const isCursorInMiddleOfText = textContent.length > 0 && anchorOffset > 0 && anchorOffset < textContent.length;
74
81
  const isCursorAtLineStart = anchorOffset === 0 && textContent.length > 0;
82
+ const emptyNode = $createParagraphNode();
75
83
  if (isCursorInMiddleOfText) {
76
84
  // 如果光标在文本中间,先添加一个空行后再插入内容
77
- selection.insertNodes([containerNode, $createParagraphNode()]);
85
+ selection.insertNodes([containerNode, emptyNode]);
78
86
  }
79
87
  else if (isCursorAtLineStart) {
80
88
  // 如果光标在行首(比如在"B"前面),插入内容后添加一个空行
81
- const emptyParagraph = $createParagraphNode();
82
- selection.insertNodes([containerNode, emptyParagraph]);
89
+ selection.insertNodes([containerNode, emptyNode]);
83
90
  // 将光标放在新插入的内容之后的空行上
84
- emptyParagraph.select();
91
+ emptyNode.select();
85
92
  }
86
93
  else {
87
94
  // 其他情况(光标在行尾或空行),直接插入
@@ -84,7 +84,6 @@ import { useResponsiveTable } from './hooks/useResponsiveTable';
84
84
  import { useTranslationListener } from './hooks/useTranslationListener';
85
85
  import { PagesKitComponentPlugin } from '../ext/PagesKitComponent/PagesKitComponentPlugin';
86
86
  import { EditorHolderPlugin } from '../ext/EditorHolderPlugin';
87
- import PasteMarkdownPlugin from '../ext/PasteMarkdownPlugin';
88
87
  export default function Editor({ children, prepend, placeholder, onChange, autoFocus = true, showToolbar = true, editorRef, onReady, enableHeadingsIdPlugin, }) {
89
88
  const [editor] = useLexicalComposerContext();
90
89
  const [editable, setEditable] = useState(false);
@@ -114,9 +113,9 @@ export default function Editor({ children, prepend, placeholder, onChange, autoF
114
113
  }
115
114
  }, [hasNodes('image'), hasUploader]);
116
115
  if (minimalMode) {
117
- return (_jsxs(_Fragment, { children: [prepend, isRichText && 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(PasteMarkdownPlugin, {}), _jsx(EditorContent, { 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('tweet') && _jsx(TwitterPlugin, {}), hasNodes('youtube') && _jsx(YouTubePlugin, {}), hasNodes('figma') && _jsx(FigmaPlugin, {}), _jsx(PostLinkEmbedPlugin, {}), _jsx(BookmarkPlugin, {}), editable && _jsx(CustomOnChangePlugin, { placeholder: placeholder }), editable && _jsx(TemplatePlugin, {}), !editable && _jsx(BlurTextPlugin, {}), 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 && (_jsxs(_Fragment, { children: [hasNodes('code') && _jsx(CodeActionMenuPlugin, { anchorElem: floatingAnchorElem }), hasNodes('link') && _jsx(FloatingLinkEditorPlugin, { anchorElem: floatingAnchorElem })] })), _jsx(AiImagePlugin, {}), editorRef && _jsx(EditorRefPlugin, { editorRef: editorRef }), children] }));
116
+ return (_jsxs(_Fragment, { children: [prepend, isRichText && 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(EditorContent, { 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('tweet') && _jsx(TwitterPlugin, {}), hasNodes('youtube') && _jsx(YouTubePlugin, {}), hasNodes('figma') && _jsx(FigmaPlugin, {}), _jsx(PostLinkEmbedPlugin, {}), _jsx(BookmarkPlugin, {}), editable && _jsx(CustomOnChangePlugin, { placeholder: placeholder }), editable && _jsx(TemplatePlugin, {}), !editable && _jsx(BlurTextPlugin, {}), 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 && (_jsxs(_Fragment, { children: [hasNodes('code') && _jsx(CodeActionMenuPlugin, { anchorElem: floatingAnchorElem }), hasNodes('link') && _jsx(FloatingLinkEditorPlugin, { anchorElem: floatingAnchorElem })] })), _jsx(AiImagePlugin, {}), editorRef && _jsx(EditorRefPlugin, { editorRef: editorRef }), children] }));
118
117
  }
119
- return (_jsxs(_Fragment, { children: [prepend, isRichText && editable && showToolbar && _jsx(ToolbarPlugin, {}), isMaxLength && _jsx(MaxLengthPlugin, { maxLength: 30 }), hasNodes('image') && hasUploader && _jsx(DragDropPaste, {}), autoFocus && _jsx(AutoFocusPlugin, { defaultSelection: "rootEnd" }), _jsx(ClearEditorPlugin, {}), !!editable && _jsx(ComponentPickerPlugin, {}), !!editable && _jsx(EmojiPickerPlugin, {}), hasNodes('link') && _jsx(AutoEmbedPlugin, {}), !!editable && _jsx(MentionsPlugin, {}), hasNodes('emoji') && _jsx(EmojisPlugin, {}), hasNodes('hashtag') && _jsx(HashtagPlugin, {}), _jsx(SpeechToTextPlugin, {}), hasNodes('autolink') && _jsx(AutoLinkPlugin, {}), isRichText ? (_jsxs(_Fragment, { children: [_jsx(PasteSlackImagePlugin, {}), _jsx(PasteMarkdownPlugin, {}), _jsx(HistoryPlugin, { externalHistoryState: historyState }), _jsx(EditorContent, { 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('list', 'listitem') && _jsx(ListMaxIndentLevelPlugin, { maxDepth: 7 }), hasNodes('table', 'tablerow', 'tablecell') && editable && (_jsx(TablePlugin, { hasCellMerge: true, hasCellBackgroundColor: 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, {}), editable && _jsx(CustomOnChangePlugin, { placeholder: placeholder }), editable && _jsx(TemplatePlugin, {}), !editable && _jsx(BlurTextPlugin, {}), 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('code') && _jsx(CodeActionMenuPlugin, { anchorElem: floatingAnchorElem }), hasNodes('link') && _jsx(FloatingLinkEditorPlugin, { anchorElem: floatingAnchorElem }), hasNodes('table') && _jsx(TableCellActionMenuPlugin, { anchorElem: floatingAnchorElem, cellMerge: true }), _jsx(FloatingTextFormatToolbarPlugin, { anchorElem: floatingAnchorElem })] })), enableHeadingsIdPlugin && _jsx(HeadingsIdPlugin, {})] })) : (_jsxs(_Fragment, { children: [_jsx(PlainTextPlugin, { contentEditable: _jsx(ContentEditable, {}), placeholder: _jsx(Placeholder, { children: "placeholder" }), ErrorBoundary: LexicalErrorBoundary }), _jsx(HistoryPlugin, { externalHistoryState: historyState })] })), (isCharLimit || isCharLimitUtf8) && (_jsx(CharacterLimitPlugin, { charset: isCharLimit ? 'UTF-16' : 'UTF-8', maxLength: 5 })), isAutocomplete && hasNodes('autocomplete') && _jsx(AutocompletePlugin, {}), _jsx("div", { children: showTableOfContents && _jsx(TableOfContentsPlugin, {}) }), _jsx(SelectBlockPlugin, {}), _jsx(RemoveListPlugin, {}), _jsx(MarkdownHeadTextPlugin, {}), _jsx(AiImagePlugin, {}), _jsx(EditorHolderPlugin, {}), editorRef && _jsx(EditorRefPlugin, { editorRef: editorRef }), onReady && _jsx(EditorReadyPlugin, { onReady: onReady }), children] }));
118
+ return (_jsxs(_Fragment, { children: [prepend, isRichText && editable && showToolbar && _jsx(ToolbarPlugin, {}), isMaxLength && _jsx(MaxLengthPlugin, { maxLength: 30 }), hasNodes('image') && hasUploader && _jsx(DragDropPaste, {}), autoFocus && _jsx(AutoFocusPlugin, { defaultSelection: "rootEnd" }), _jsx(ClearEditorPlugin, {}), !!editable && _jsx(ComponentPickerPlugin, {}), !!editable && _jsx(EmojiPickerPlugin, {}), hasNodes('link') && _jsx(AutoEmbedPlugin, {}), !!editable && _jsx(MentionsPlugin, {}), hasNodes('emoji') && _jsx(EmojisPlugin, {}), hasNodes('hashtag') && _jsx(HashtagPlugin, {}), _jsx(SpeechToTextPlugin, {}), hasNodes('autolink') && _jsx(AutoLinkPlugin, {}), isRichText ? (_jsxs(_Fragment, { children: [_jsx(PasteSlackImagePlugin, {}), _jsx(HistoryPlugin, { externalHistoryState: historyState }), _jsx(EditorContent, { 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('list', 'listitem') && _jsx(ListMaxIndentLevelPlugin, { maxDepth: 7 }), hasNodes('table', 'tablerow', 'tablecell') && editable && (_jsx(TablePlugin, { hasCellMerge: true, hasCellBackgroundColor: 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, {}), editable && _jsx(CustomOnChangePlugin, { placeholder: placeholder }), editable && _jsx(TemplatePlugin, {}), !editable && _jsx(BlurTextPlugin, {}), 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('code') && _jsx(CodeActionMenuPlugin, { anchorElem: floatingAnchorElem }), hasNodes('link') && _jsx(FloatingLinkEditorPlugin, { anchorElem: floatingAnchorElem }), hasNodes('table') && _jsx(TableCellActionMenuPlugin, { anchorElem: floatingAnchorElem, cellMerge: true }), _jsx(FloatingTextFormatToolbarPlugin, { anchorElem: floatingAnchorElem })] })), enableHeadingsIdPlugin && _jsx(HeadingsIdPlugin, {})] })) : (_jsxs(_Fragment, { children: [_jsx(PlainTextPlugin, { contentEditable: _jsx(ContentEditable, {}), placeholder: _jsx(Placeholder, { children: "placeholder" }), ErrorBoundary: LexicalErrorBoundary }), _jsx(HistoryPlugin, { externalHistoryState: historyState })] })), (isCharLimit || isCharLimitUtf8) && (_jsx(CharacterLimitPlugin, { charset: isCharLimit ? 'UTF-16' : 'UTF-8', maxLength: 5 })), isAutocomplete && hasNodes('autocomplete') && _jsx(AutocompletePlugin, {}), _jsx("div", { children: showTableOfContents && _jsx(TableOfContentsPlugin, {}) }), _jsx(SelectBlockPlugin, {}), _jsx(RemoveListPlugin, {}), _jsx(MarkdownHeadTextPlugin, {}), _jsx(AiImagePlugin, {}), _jsx(EditorHolderPlugin, {}), editorRef && _jsx(EditorRefPlugin, { editorRef: editorRef }), onReady && _jsx(EditorReadyPlugin, { onReady: onReady }), children] }));
120
119
  }
121
120
  const EditorContent = styled(Box) `
122
121
  position: relative;
@@ -6,4 +6,4 @@
6
6
  *
7
7
  */
8
8
  /// <reference types="react" />
9
- export default function MarkdownPlugin(): JSX.Element;
9
+ export default function MarkdownShortcutPlugin(): JSX.Element;
@@ -7,10 +7,10 @@ import { jsx as _jsx } from "react/jsx-runtime";
7
7
  *
8
8
  */
9
9
  import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
10
- import { MarkdownShortcutPlugin } from '@lexical/react/LexicalMarkdownShortcutPlugin';
10
+ import { MarkdownShortcutPlugin as OfficialMarkdownShortcutPlugin } from '@lexical/react/LexicalMarkdownShortcutPlugin';
11
11
  import { useMemo } from 'react';
12
12
  import { PLAYGROUND_TRANSFORMERS } from '../MarkdownTransformers';
13
- export default function MarkdownPlugin() {
13
+ export default function MarkdownShortcutPlugin() {
14
14
  const [editor] = useLexicalComposerContext();
15
15
  const transformers = useMemo(() => PLAYGROUND_TRANSFORMERS.filter((i) => {
16
16
  if (i.type === 'element' || i.type === 'text-match') {
@@ -18,5 +18,5 @@ export default function MarkdownPlugin() {
18
18
  }
19
19
  return true;
20
20
  }), [editor]);
21
- return _jsx(MarkdownShortcutPlugin, { transformers: transformers });
21
+ return _jsx(OfficialMarkdownShortcutPlugin, { transformers: transformers });
22
22
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/editor",
3
- "version": "2.2.39",
3
+ "version": "2.2.41",
4
4
  "main": "lib/index.js",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -27,8 +27,8 @@
27
27
  "@blocklet/code-editor": "^0.4.256",
28
28
  "@blocklet/embed": "^0.2.3",
29
29
  "@blocklet/js-sdk": "^1.16.42-beta-20250407-225010-b71aee89",
30
- "@blocklet/pages-kit": "^0.4.109",
31
- "@blocklet/pages-kit-runtime": "^0.4.109",
30
+ "@blocklet/pages-kit": "^0.4.115",
31
+ "@blocklet/pages-kit-runtime": "^0.4.115",
32
32
  "@excalidraw/excalidraw": "^0.14.2",
33
33
  "@iconify/iconify": "^3.1.1",
34
34
  "@iconify/icons-tabler": "^1.2.95",
@@ -58,18 +58,18 @@
58
58
  "lexical": "0.13.1",
59
59
  "lodash": "^4.17.21",
60
60
  "lottie-react": "^2.4.0",
61
+ "marked": "^15.0.8",
61
62
  "markerjs-live": "^1.2.1",
62
63
  "markerjs2": "^2.32.2",
63
64
  "medium-zoom": "^1.1.0",
64
65
  "path-parser": "^6.1.0",
65
- "split-pane-react": "^0.1.3",
66
66
  "react-player": "^2.16.0",
67
67
  "react-popper": "^2.3.0",
68
+ "split-pane-react": "^0.1.3",
68
69
  "ufo": "^1.5.4",
69
70
  "url-join": "^4.0.1",
70
71
  "zustand": "^4.5.5",
71
- "marked": "^15.0.8",
72
- "@blocklet/pdf": "^2.2.39"
72
+ "@blocklet/pdf": "^2.2.41"
73
73
  },
74
74
  "devDependencies": {
75
75
  "@babel/core": "^7.25.2",