dishui 0.0.105 → 0.0.108
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/.release-verified.json +2 -2
- package/dist/components/ChoicePicker/index.js +8 -6
- package/dist/components/ChoicePicker/index.js.map +1 -1
- package/dist/components/Column/index.d.ts +3 -2
- package/dist/components/Column/index.js +5 -17
- package/dist/components/Column/index.js.map +1 -1
- package/dist/components/ConfirmDialog/index.d.ts +20 -0
- package/dist/components/ConfirmDialog/index.js +84 -0
- package/dist/components/ConfirmDialog/index.js.map +1 -0
- package/dist/components/DateTimeInput/index.js +28 -26
- package/dist/components/DateTimeInput/index.js.map +1 -1
- package/dist/components/Input/index.js +1 -1
- package/dist/components/Input/index.js.map +1 -1
- package/dist/components/MultipleChoice/index.js +2 -1
- package/dist/components/MultipleChoice/index.js.map +1 -1
- package/dist/components/Row/index.d.ts +3 -2
- package/dist/components/Row/index.js +5 -17
- package/dist/components/Row/index.js.map +1 -1
- package/dist/components/Tab/index.js +80 -0
- package/dist/components/Tab/index.js.map +1 -0
- package/dist/components/Tabs/index.js +28 -33
- package/dist/components/Tabs/index.js.map +1 -1
- package/dist/components/Tabs/tabNavigation.d.ts +2 -0
- package/dist/components/Tabs/tabNavigation.js +14 -0
- package/dist/components/Tabs/tabNavigation.js.map +1 -0
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.d.ts +1 -1
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js +25 -26
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
- package/dist/components/pro/FileExplorer/Breadcrumb.js +8 -11
- package/dist/components/pro/FileExplorer/Breadcrumb.js.map +1 -1
- package/dist/components/pro/Flow/Flow.js +184 -182
- package/dist/components/pro/Flow/Flow.js.map +1 -1
- package/dist/components/pro/Flow/archify/convert.js +26 -26
- package/dist/components/pro/Flow/archify/convert.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useLayoutActions.js +13 -11
- package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
- package/dist/components/pro/RichTextEditor/AIRewrite.d.ts +1 -0
- package/dist/components/pro/RichTextEditor/AIRewrite.js +109 -88
- package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BubbleToolbar.js +73 -83
- package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/RichTextEditor.js +133 -132
- package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.d.ts +2 -0
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js +73 -49
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.d.ts +1 -0
- package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js +12 -14
- package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js +113 -113
- package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
- package/dist/components/pro/RichTextEditor/types.d.ts +2 -0
- package/dist/components/pro/RichTextEditor/types.js.map +1 -1
- package/dist/css.d.ts +1 -0
- package/dist/dishui.css +1 -1
- package/dist/index-nostyled.d.ts +2 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +113 -111
- package/dist/layouts/Sidebar.js +201 -107
- package/dist/layouts/Sidebar.js.map +1 -1
- package/dist/utils/flexLayout.d.ts +5 -0
- package/dist/utils/flexLayout.js +19 -0
- package/dist/utils/flexLayout.js.map +1 -0
- package/package.json +63 -57
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColorPicker.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/ColorPicker.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useId } from 'react';\nimport { useAnchoredDropdown } from './useAnchoredDropdown';\n\ninterface ColorPickerProps {\n value: string;\n onChange: (color: string) => void;\n title?: string;\n icon?: React.ReactNode;\n kind?: 'text' | 'highlight';\n /** Button class; defaults to the classic toolbar button. Bubble toolbar passes its own. */\n buttonClassName?: string;\n}\n\nconst COLORS = [\n '#000000', '#434343', '#666666', '#999999', '#cccccc', '#eeeeee', '#ffffff',\n '#ff0000', '#ff4500', '#ff8c00', '#ffd700', '#32cd32', '#00bfff', '#8a2be2',\n '#ff69b4', '#dc143c', '#ff6347', '#ffa500', '#9acd32', '#20b2aa', '#4169e1',\n '#9370db', '#db7093', '#b22222', '#d2691e', '#daa520', '#228b22', '#008b8b',\n '#191970', '#4b0082',\n];\n\nexport const ColorPicker: React.FC<ColorPickerProps> = ({ value, onChange, title, icon, kind = 'text', buttonClassName = 'rte-toolbar__btn' }) => {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const paletteRef = useRef<HTMLDivElement>(null);\n const paletteId = useId();\n const dropdownStyle = useAnchoredDropdown(isOpen, triggerRef, paletteRef);\n const label = title || (kind === 'text' ? 'Text color' : 'Highlight color');\n const description = `${label}: ${value || (kind === 'text' ? 'Default' : 'None')}`;\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, []);\n\n return (\n <div ref={ref} className=\"rte-toolbar__color-picker\"\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget)) setIsOpen(false);\n }}\n onKeyDown={(event) => {\n if (event.key === 'Escape' && isOpen) {\n event.preventDefault();\n event.stopPropagation();\n setIsOpen(false);\n triggerRef.current?.focus();\n }\n }}>\n <button\n type=\"button\"\n ref={triggerRef}\n className={`${buttonClassName} rte-toolbar__color-trigger`}\n
|
|
1
|
+
{"version":3,"file":"ColorPicker.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/ColorPicker.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useId } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useAnchoredDropdown } from './useAnchoredDropdown';\n\ninterface ColorPickerProps {\n value: string;\n onChange: (color: string) => void;\n title?: string;\n icon?: React.ReactNode;\n kind?: 'text' | 'highlight';\n /** Button class; defaults to the classic toolbar button. Bubble toolbar passes its own. */\n buttonClassName?: string;\n /** Portals the palette outside scroll-clipped bubble toolbars. */\n portalOwner?: string;\n}\n\nconst COLORS = [\n '#000000', '#434343', '#666666', '#999999', '#cccccc', '#eeeeee', '#ffffff',\n '#ff0000', '#ff4500', '#ff8c00', '#ffd700', '#32cd32', '#00bfff', '#8a2be2',\n '#ff69b4', '#dc143c', '#ff6347', '#ffa500', '#9acd32', '#20b2aa', '#4169e1',\n '#9370db', '#db7093', '#b22222', '#d2691e', '#daa520', '#228b22', '#008b8b',\n '#191970', '#4b0082',\n];\n\nexport const ColorPicker: React.FC<ColorPickerProps> = ({ value, onChange, title, icon, kind = 'text', buttonClassName = 'rte-toolbar__btn', portalOwner }) => {\n const [isOpen, setIsOpen] = useState(false);\n const [paletteTheme, setPaletteTheme] = useState<React.CSSProperties>({});\n const ref = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const paletteRef = useRef<HTMLDivElement>(null);\n const paletteId = useId();\n const dropdownStyle = useAnchoredDropdown(isOpen, triggerRef, paletteRef);\n const label = title || (kind === 'text' ? 'Text color' : 'Highlight color');\n const description = `${label}: ${value || (kind === 'text' ? 'Default' : 'None')}`;\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node) && !paletteRef.current?.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [ref, paletteRef]);\n\n const palette = isOpen && (\n <div ref={paletteRef} id={paletteId} data-rte-palette-owner={portalOwner}\n className=\"rte-toolbar__color-dropdown\" role=\"group\" aria-label={label}\n style={{ ...dropdownStyle, ...paletteTheme }}>\n {COLORS.map((color) => (\n <button key={color} type=\"button\"\n className={`rte-toolbar__color-swatch ${color === value ? 'rte-toolbar__color-swatch--active' : ''}`}\n style={{ backgroundColor: color }}\n onMouseDown={portalOwner ? event => event.preventDefault() : undefined}\n onClick={() => { onChange(color); setIsOpen(false); }}\n title={`${label}: ${color}`} aria-label={`${label}: ${color}`}\n aria-pressed={color.toLowerCase() === value.toLowerCase()} />\n ))}\n <button type=\"button\" className=\"rte-toolbar__color-clear\"\n onMouseDown={portalOwner ? event => event.preventDefault() : undefined}\n onClick={() => { onChange(''); setIsOpen(false); }}\n title={`Clear ${label}`} aria-label={`Clear ${label}`} aria-pressed={!value}>Clear</button>\n </div>\n );\n\n return (\n <div ref={ref} className=\"rte-toolbar__color-picker\"\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget) && !paletteRef.current?.contains(event.relatedTarget)) setIsOpen(false);\n }}\n onKeyDown={(event) => {\n if (event.key === 'Escape' && isOpen) {\n event.preventDefault();\n event.stopPropagation();\n setIsOpen(false);\n triggerRef.current?.focus();\n }\n }}>\n <button\n type=\"button\"\n ref={triggerRef}\n className={`${buttonClassName} rte-toolbar__color-trigger`}\n onMouseDown={portalOwner ? event => event.preventDefault() : undefined}\n onClick={event => {\n if (portalOwner && !isOpen) {\n const computed = getComputedStyle(event.currentTarget);\n const variables: Record<string, string> = {};\n for (const name of ['--rte-bg', '--rte-text', '--rte-border', '--rte-placeholder', '--rte-active-color', '--rte-toolbar-btn-hover']) {\n variables[name] = computed.getPropertyValue(name);\n }\n setPaletteTheme(variables);\n }\n setIsOpen(!isOpen);\n }}\n title={description}\n aria-label={description}\n aria-expanded={isOpen}\n aria-controls={isOpen ? paletteId : undefined}\n >\n <span className={`rte-toolbar__color-icon rte-toolbar__color-icon--${kind}`} aria-hidden=\"true\">\n {icon || (kind === 'text' ? <span className=\"rte-toolbar__color-letter\">A</span> : (\n <svg width=\"18\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"m14 3 7 7-9 9-7-7zM5 12l-2 7 2 2 7-2M14 7l3 3M3 21h6\" />\n </svg>\n ))}\n <span\n className={`rte-toolbar__color-indicator${value ? '' : ' rte-toolbar__color-indicator--empty'}`}\n style={{ backgroundColor: value || undefined }}\n />\n </span>\n </button>\n {portalOwner && typeof document !== 'undefined' ? createPortal(palette, document.body) : palette}\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import e from "../../../Select/index.js";
|
|
1
2
|
import "react";
|
|
2
|
-
import { jsx as
|
|
3
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
3
4
|
//#region src/components/pro/RichTextEditor/Toolbar/SelectDropdown.tsx
|
|
4
|
-
var
|
|
5
|
+
var n = [
|
|
5
6
|
{
|
|
6
7
|
label: "Default",
|
|
7
8
|
value: ""
|
|
@@ -42,7 +43,7 @@ var t = [
|
|
|
42
43
|
label: "Comic Sans MS",
|
|
43
44
|
value: "Comic Sans MS, cursive"
|
|
44
45
|
}
|
|
45
|
-
],
|
|
46
|
+
], r = [
|
|
46
47
|
{
|
|
47
48
|
label: "Default",
|
|
48
49
|
value: ""
|
|
@@ -99,18 +100,15 @@ var t = [
|
|
|
99
100
|
label: "72px",
|
|
100
101
|
value: "72px"
|
|
101
102
|
}
|
|
102
|
-
],
|
|
103
|
-
className:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
value: t.value,
|
|
110
|
-
children: t.label
|
|
111
|
-
}, t.value))
|
|
103
|
+
], i = ({ value: n, options: r, onChange: i, title: a, width: o = 110, className: s = "rte-toolbar__select" }) => /* @__PURE__ */ t(e, {
|
|
104
|
+
className: s,
|
|
105
|
+
style: { width: o },
|
|
106
|
+
options: r,
|
|
107
|
+
value: n,
|
|
108
|
+
onChange: (e) => i(String(e)),
|
|
109
|
+
"aria-label": a ?? "Formatting option"
|
|
112
110
|
});
|
|
113
111
|
//#endregion
|
|
114
|
-
export {
|
|
112
|
+
export { n as FONT_FAMILIES, r as FONT_SIZES, i as SelectDropdown };
|
|
115
113
|
|
|
116
114
|
//# sourceMappingURL=SelectDropdown.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectDropdown.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/SelectDropdown.tsx"],"sourcesContent":["import React from 'react';\n\nexport const FONT_FAMILIES = [\n { label: 'Default', value: '' },\n { label: 'Arial', value: 'Arial, sans-serif' },\n { label: 'Helvetica', value: 'Helvetica, sans-serif' },\n { label: 'Georgia', value: 'Georgia, serif' },\n { label: 'Times New Roman', value: 'Times New Roman, serif' },\n { label: 'Courier New', value: 'Courier New, monospace' },\n { label: 'Verdana', value: 'Verdana, sans-serif' },\n { label: 'Trebuchet MS', value: 'Trebuchet MS, sans-serif' },\n { label: 'Impact', value: 'Impact, sans-serif' },\n { label: 'Comic Sans MS', value: 'Comic Sans MS, cursive' },\n];\n\nexport const FONT_SIZES = [\n { label: 'Default', value: '' },\n { label: '10px', value: '10px' },\n { label: '12px', value: '12px' },\n { label: '14px', value: '14px' },\n { label: '16px', value: '16px' },\n { label: '18px', value: '18px' },\n { label: '20px', value: '20px' },\n { label: '24px', value: '24px' },\n { label: '28px', value: '28px' },\n { label: '32px', value: '32px' },\n { label: '36px', value: '36px' },\n { label: '48px', value: '48px' },\n { label: '64px', value: '64px' },\n { label: '72px', value: '72px' },\n];\n\ninterface SelectDropdownProps {\n value: string;\n options: { label: string; value: string }[];\n onChange: (value: string) => void;\n title?: string;\n width?: number;\n}\n\nexport const SelectDropdown: React.FC<SelectDropdownProps> = ({ value, options, onChange, title, width = 110 }) => (\n <
|
|
1
|
+
{"version":3,"file":"SelectDropdown.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/SelectDropdown.tsx"],"sourcesContent":["import React from 'react';\nimport Select from '../../../Select';\n\nexport const FONT_FAMILIES = [\n { label: 'Default', value: '' },\n { label: 'Arial', value: 'Arial, sans-serif' },\n { label: 'Helvetica', value: 'Helvetica, sans-serif' },\n { label: 'Georgia', value: 'Georgia, serif' },\n { label: 'Times New Roman', value: 'Times New Roman, serif' },\n { label: 'Courier New', value: 'Courier New, monospace' },\n { label: 'Verdana', value: 'Verdana, sans-serif' },\n { label: 'Trebuchet MS', value: 'Trebuchet MS, sans-serif' },\n { label: 'Impact', value: 'Impact, sans-serif' },\n { label: 'Comic Sans MS', value: 'Comic Sans MS, cursive' },\n];\n\nexport const FONT_SIZES = [\n { label: 'Default', value: '' },\n { label: '10px', value: '10px' },\n { label: '12px', value: '12px' },\n { label: '14px', value: '14px' },\n { label: '16px', value: '16px' },\n { label: '18px', value: '18px' },\n { label: '20px', value: '20px' },\n { label: '24px', value: '24px' },\n { label: '28px', value: '28px' },\n { label: '32px', value: '32px' },\n { label: '36px', value: '36px' },\n { label: '48px', value: '48px' },\n { label: '64px', value: '64px' },\n { label: '72px', value: '72px' },\n];\n\ninterface SelectDropdownProps {\n value: string;\n options: { label: string; value: string }[];\n onChange: (value: string) => void;\n title?: string;\n width?: number;\n className?: string;\n}\n\nexport const SelectDropdown: React.FC<SelectDropdownProps> = ({ value, options, onChange, title, width = 110, className = 'rte-toolbar__select' }) => (\n <Select\n className={className}\n style={{ width }}\n options={options}\n value={value}\n onChange={(next) => onChange(String(next))}\n aria-label={title ?? 'Formatting option'}\n />\n);\n"],"mappings":";;;;AAGA,IAAa,IAAgB;CAC3B;EAAE,OAAO;EAAW,OAAO;CAAG;CAC9B;EAAE,OAAO;EAAS,OAAO;CAAoB;CAC7C;EAAE,OAAO;EAAa,OAAO;CAAwB;CACrD;EAAE,OAAO;EAAW,OAAO;CAAiB;CAC5C;EAAE,OAAO;EAAmB,OAAO;CAAyB;CAC5D;EAAE,OAAO;EAAe,OAAO;CAAyB;CACxD;EAAE,OAAO;EAAW,OAAO;CAAsB;CACjD;EAAE,OAAO;EAAgB,OAAO;CAA2B;CAC3D;EAAE,OAAO;EAAU,OAAO;CAAqB;CAC/C;EAAE,OAAO;EAAiB,OAAO;CAAyB;AAC5D,GAEa,IAAa;CACxB;EAAE,OAAO;EAAW,OAAO;CAAG;CAC9B;EAAE,OAAO;EAAQ,OAAO;CAAO;CAC/B;EAAE,OAAO;EAAQ,OAAO;CAAO;CAC/B;EAAE,OAAO;EAAQ,OAAO;CAAO;CAC/B;EAAE,OAAO;EAAQ,OAAO;CAAO;CAC/B;EAAE,OAAO;EAAQ,OAAO;CAAO;CAC/B;EAAE,OAAO;EAAQ,OAAO;CAAO;CAC/B;EAAE,OAAO;EAAQ,OAAO;CAAO;CAC/B;EAAE,OAAO;EAAQ,OAAO;CAAO;CAC/B;EAAE,OAAO;EAAQ,OAAO;CAAO;CAC/B;EAAE,OAAO;EAAQ,OAAO;CAAO;CAC/B;EAAE,OAAO;EAAQ,OAAO;CAAO;CAC/B;EAAE,OAAO;EAAQ,OAAO;CAAO;CAC/B;EAAE,OAAO;EAAQ,OAAO;CAAO;AACjC,GAWa,KAAiD,EAAE,UAAO,YAAS,aAAU,UAAO,WAAQ,KAAK,eAAY,4BACxH,kBAAC,GAAD;CACa;CACX,OAAO,EAAE,SAAM;CACN;CACF;CACP,WAAW,MAAS,EAAS,OAAO,CAAI,CAAC;CACzC,cAAY,KAAS;AACtB,CAAA"}
|
|
@@ -1,30 +1,31 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import l from "react-
|
|
7
|
-
import u from "
|
|
8
|
-
import d from "
|
|
9
|
-
import f from "
|
|
1
|
+
import e from "../../../Select/index.js";
|
|
2
|
+
import { MermaidRenderer as t, useNodeEditable as n } from "./MarkdownBlock.js";
|
|
3
|
+
import { useEffect as r, useState as i } from "react";
|
|
4
|
+
import { Fragment as a, jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
5
|
+
import { Prism as c } from "react-syntax-highlighter";
|
|
6
|
+
import { oneLight as l } from "react-syntax-highlighter/dist/esm/styles/prism";
|
|
7
|
+
import u from "react-markdown";
|
|
8
|
+
import d from "remark-gfm";
|
|
9
|
+
import f from "rehype-katex";
|
|
10
|
+
import p from "remark-math";
|
|
10
11
|
import "katex/dist/katex.min.css";
|
|
11
|
-
import { Node as
|
|
12
|
-
import { Plugin as
|
|
12
|
+
import { Node as m, NodeViewContent as h, NodeViewWrapper as g, ReactNodeViewRenderer as _, mergeAttributes as v, textblockTypeInputRule as y } from "@tiptap/react";
|
|
13
|
+
import { Plugin as b, PluginKey as x } from "@tiptap/pm/state";
|
|
13
14
|
//#region src/components/pro/RichTextEditor/extensions/CodeBlockView.tsx
|
|
14
|
-
var
|
|
15
|
+
var S = ({ code: e }) => {
|
|
15
16
|
let t = e.includes("$$") ? e : `$$\n${e}\n$$`;
|
|
16
|
-
return /* @__PURE__ */
|
|
17
|
-
remarkPlugins: [
|
|
18
|
-
rehypePlugins: [
|
|
17
|
+
return /* @__PURE__ */ o(u, {
|
|
18
|
+
remarkPlugins: [p],
|
|
19
|
+
rehypePlugins: [f],
|
|
19
20
|
children: t
|
|
20
21
|
});
|
|
21
|
-
},
|
|
22
|
-
remarkPlugins: [
|
|
23
|
-
rehypePlugins: [
|
|
24
|
-
components: { code({ className:
|
|
25
|
-
let i = /language-(\w+)/.exec(
|
|
26
|
-
return i === "mermaid" ? /* @__PURE__ */
|
|
27
|
-
style:
|
|
22
|
+
}, C = ({ code: e }) => /* @__PURE__ */ o(u, {
|
|
23
|
+
remarkPlugins: [d, p],
|
|
24
|
+
rehypePlugins: [f],
|
|
25
|
+
components: { code({ className: e, children: n, ...r }) {
|
|
26
|
+
let i = /language-(\w+)/.exec(e || "")?.[1], a = String(n).replace(/\n$/, "");
|
|
27
|
+
return i === "mermaid" ? /* @__PURE__ */ o(t, { code: a }) : i ? /* @__PURE__ */ o(c, {
|
|
28
|
+
style: l,
|
|
28
29
|
language: i,
|
|
29
30
|
PreTag: "div",
|
|
30
31
|
customStyle: {
|
|
@@ -33,34 +34,47 @@ var x = ({ code: e }) => {
|
|
|
33
34
|
padding: "1em",
|
|
34
35
|
margin: "0.5em 0"
|
|
35
36
|
},
|
|
36
|
-
children:
|
|
37
|
-
}) : /* @__PURE__ */
|
|
38
|
-
className:
|
|
37
|
+
children: a
|
|
38
|
+
}) : /* @__PURE__ */ o("code", {
|
|
39
|
+
className: e,
|
|
39
40
|
...r,
|
|
40
41
|
children: n
|
|
41
42
|
});
|
|
42
43
|
} },
|
|
43
|
-
children:
|
|
44
|
-
}),
|
|
44
|
+
children: e
|
|
45
|
+
}), w = [
|
|
45
46
|
"markdown",
|
|
46
47
|
"mermaid",
|
|
47
48
|
"math"
|
|
48
|
-
],
|
|
49
|
-
|
|
49
|
+
], T = [
|
|
50
|
+
{
|
|
51
|
+
label: "Plain text",
|
|
52
|
+
value: ""
|
|
53
|
+
},
|
|
54
|
+
...(/* @__PURE__ */ ".javascript.typescript.python.rust.go.java.c.cpp.csharp.ruby.php.swift.kotlin.sql.bash.shell.html.css.json.yaml.toml.xml.docker.graphql.latex.tex".split(".")).filter(Boolean).map((e) => ({
|
|
55
|
+
label: `Syntax · ${e}`,
|
|
56
|
+
value: e
|
|
57
|
+
})),
|
|
58
|
+
...w.map((e) => ({
|
|
59
|
+
label: `Render · ${e}`,
|
|
60
|
+
value: e
|
|
61
|
+
}))
|
|
62
|
+
];
|
|
63
|
+
function E(e) {
|
|
50
64
|
let t = e.startsWith("r-") ? e.slice(2) : e;
|
|
51
|
-
return
|
|
65
|
+
return w.includes(t) ? t : "";
|
|
52
66
|
}
|
|
53
|
-
function
|
|
67
|
+
function D(e) {
|
|
54
68
|
return e === "math" || e === "latex" || e === "tex" ? "latex" : e;
|
|
55
69
|
}
|
|
56
|
-
var
|
|
57
|
-
let
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}, [
|
|
61
|
-
|
|
62
|
-
}, [
|
|
63
|
-
let O =
|
|
70
|
+
var O = ({ node: u, editor: d, updateAttributes: f }) => {
|
|
71
|
+
let p = n(d), m = u.attrs.language || "", _ = u.textContent, v = !!m, y = E(m), b = !!y, [x, w] = i(!0);
|
|
72
|
+
r(() => {
|
|
73
|
+
v || w(!0);
|
|
74
|
+
}, [m, v]), r(() => {
|
|
75
|
+
p || w(!1);
|
|
76
|
+
}, [p]);
|
|
77
|
+
let O = x && p, k = /* @__PURE__ */ s("svg", {
|
|
64
78
|
width: "12",
|
|
65
79
|
height: "12",
|
|
66
80
|
viewBox: "0 0 24 24",
|
|
@@ -69,8 +83,8 @@ var D = ({ node: l, editor: u, updateAttributes: d }) => {
|
|
|
69
83
|
strokeWidth: "2",
|
|
70
84
|
strokeLinecap: "round",
|
|
71
85
|
strokeLinejoin: "round",
|
|
72
|
-
children: [/* @__PURE__ */
|
|
73
|
-
}), A = /* @__PURE__ */
|
|
86
|
+
children: [/* @__PURE__ */ o("path", { d: "M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7" }), /* @__PURE__ */ o("path", { d: "M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z" })]
|
|
87
|
+
}), A = /* @__PURE__ */ s("svg", {
|
|
74
88
|
width: "12",
|
|
75
89
|
height: "12",
|
|
76
90
|
viewBox: "0 0 24 24",
|
|
@@ -79,116 +93,102 @@ var D = ({ node: l, editor: u, updateAttributes: d }) => {
|
|
|
79
93
|
strokeWidth: "2",
|
|
80
94
|
strokeLinecap: "round",
|
|
81
95
|
strokeLinejoin: "round",
|
|
82
|
-
children: [/* @__PURE__ */
|
|
96
|
+
children: [/* @__PURE__ */ o("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }), /* @__PURE__ */ o("circle", {
|
|
83
97
|
cx: "12",
|
|
84
98
|
cy: "12",
|
|
85
99
|
r: "3"
|
|
86
100
|
})]
|
|
87
|
-
}), j = () =>
|
|
101
|
+
}), j = () => y === "mermaid" ? _.trim() ? /* @__PURE__ */ o(t, { code: _ }) : /* @__PURE__ */ o("p", {
|
|
88
102
|
className: "rte-codeblock__placeholder",
|
|
89
103
|
children: "Enter mermaid diagram code..."
|
|
90
|
-
}) :
|
|
104
|
+
}) : y === "math" ? _.trim() ? /* @__PURE__ */ o(S, { code: _ }) : /* @__PURE__ */ o("p", {
|
|
91
105
|
className: "rte-codeblock__placeholder",
|
|
92
106
|
children: "Enter KaTeX math formula..."
|
|
93
|
-
}) :
|
|
107
|
+
}) : y === "markdown" ? _.trim() ? /* @__PURE__ */ o(C, { code: _ }) : /* @__PURE__ */ o("p", {
|
|
94
108
|
className: "rte-codeblock__placeholder",
|
|
95
109
|
children: "Enter Markdown content..."
|
|
96
|
-
}) : null, M =
|
|
97
|
-
return /* @__PURE__ */
|
|
98
|
-
className: `rte-codeblock-wrapper ${!
|
|
99
|
-
children: O ? /* @__PURE__ */
|
|
110
|
+
}) : null, M = y ? y + " (render)" : m || "plain text";
|
|
111
|
+
return /* @__PURE__ */ o(g, {
|
|
112
|
+
className: `rte-codeblock-wrapper ${!x && v ? "rte-codeblock-wrapper--preview" : ""}`,
|
|
113
|
+
children: O ? /* @__PURE__ */ s(a, { children: [/* @__PURE__ */ s("div", {
|
|
100
114
|
className: "rte-codeblock__header",
|
|
101
|
-
children: [/* @__PURE__ */ o("
|
|
102
|
-
className: "rte-codeblock__lang-select",
|
|
103
|
-
value: v || p,
|
|
104
|
-
disabled: !f,
|
|
105
|
-
onChange: (e) => {
|
|
106
|
-
!u.isDestroyed && u.isEditable && (d({ language: e.target.value }), e.target.value || D(!0));
|
|
107
|
-
},
|
|
115
|
+
children: [/* @__PURE__ */ o("div", {
|
|
108
116
|
contentEditable: !1,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
label: "Live Render",
|
|
123
|
-
children: C.map((e) => /* @__PURE__ */ a("option", {
|
|
124
|
-
value: e,
|
|
125
|
-
children: e
|
|
126
|
-
}, e))
|
|
127
|
-
})
|
|
128
|
-
]
|
|
129
|
-
}), _ && /* @__PURE__ */ o("button", {
|
|
117
|
+
className: "rte-codeblock__lang-control",
|
|
118
|
+
children: /* @__PURE__ */ o(e, {
|
|
119
|
+
className: "rte-codeblock__lang-select",
|
|
120
|
+
"aria-label": "Code language",
|
|
121
|
+
value: y || m,
|
|
122
|
+
options: T,
|
|
123
|
+
onChange: (e) => {
|
|
124
|
+
if (d.isDestroyed || !d.isEditable) return;
|
|
125
|
+
let t = String(e);
|
|
126
|
+
f({ language: t }), t || w(!0);
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
}), v && /* @__PURE__ */ s("button", {
|
|
130
130
|
type: "button",
|
|
131
131
|
className: "rte-codeblock__preview-btn",
|
|
132
|
-
onClick: () =>
|
|
132
|
+
onClick: () => w(!1),
|
|
133
133
|
contentEditable: !1,
|
|
134
134
|
children: [A, " Preview"]
|
|
135
135
|
})]
|
|
136
|
-
}), /* @__PURE__ */
|
|
136
|
+
}), /* @__PURE__ */ o("pre", {
|
|
137
137
|
className: "rte-codeblock__editable-pre",
|
|
138
|
-
children: /* @__PURE__ */
|
|
139
|
-
})] }) :
|
|
138
|
+
children: /* @__PURE__ */ o(h, { as: "code" })
|
|
139
|
+
})] }) : b ? /* @__PURE__ */ s("div", {
|
|
140
140
|
className: "rte-codeblock__render-preview",
|
|
141
141
|
contentEditable: !1,
|
|
142
142
|
onDoubleClick: () => {
|
|
143
|
-
|
|
143
|
+
p && w(!0);
|
|
144
144
|
},
|
|
145
145
|
children: [
|
|
146
|
-
/* @__PURE__ */
|
|
146
|
+
/* @__PURE__ */ s("div", {
|
|
147
147
|
className: "rte-codeblock__preview-toolbar",
|
|
148
148
|
contentEditable: !1,
|
|
149
|
-
children: [/* @__PURE__ */
|
|
149
|
+
children: [/* @__PURE__ */ o("span", {
|
|
150
150
|
className: "rte-codeblock__preview-label",
|
|
151
151
|
children: M
|
|
152
|
-
}),
|
|
152
|
+
}), p && /* @__PURE__ */ s("button", {
|
|
153
153
|
type: "button",
|
|
154
154
|
className: "rte-codeblock__preview-edit-btn",
|
|
155
|
-
onClick: () =>
|
|
155
|
+
onClick: () => w(!0),
|
|
156
156
|
children: [k, " Edit"]
|
|
157
157
|
})]
|
|
158
158
|
}),
|
|
159
|
-
/* @__PURE__ */
|
|
159
|
+
/* @__PURE__ */ o("div", {
|
|
160
160
|
className: "rte-codeblock__render-body",
|
|
161
161
|
children: j()
|
|
162
162
|
}),
|
|
163
|
-
/* @__PURE__ */
|
|
163
|
+
/* @__PURE__ */ o("div", {
|
|
164
164
|
style: { display: "none" },
|
|
165
165
|
"aria-hidden": "true",
|
|
166
|
-
children: /* @__PURE__ */
|
|
166
|
+
children: /* @__PURE__ */ o(h, { as: "code" })
|
|
167
167
|
})
|
|
168
168
|
]
|
|
169
|
-
}) : /* @__PURE__ */
|
|
169
|
+
}) : /* @__PURE__ */ s("div", {
|
|
170
170
|
className: "rte-codeblock__syntax-preview",
|
|
171
171
|
contentEditable: !1,
|
|
172
172
|
onDoubleClick: () => {
|
|
173
|
-
|
|
173
|
+
p && w(!0);
|
|
174
174
|
},
|
|
175
175
|
children: [
|
|
176
|
-
/* @__PURE__ */
|
|
176
|
+
/* @__PURE__ */ s("div", {
|
|
177
177
|
className: "rte-codeblock__preview-toolbar",
|
|
178
178
|
contentEditable: !1,
|
|
179
|
-
children: [/* @__PURE__ */
|
|
179
|
+
children: [/* @__PURE__ */ o("span", {
|
|
180
180
|
className: "rte-codeblock__preview-label",
|
|
181
181
|
children: M
|
|
182
|
-
}),
|
|
182
|
+
}), p && /* @__PURE__ */ s("button", {
|
|
183
183
|
type: "button",
|
|
184
184
|
className: "rte-codeblock__preview-edit-btn",
|
|
185
|
-
onClick: () =>
|
|
185
|
+
onClick: () => w(!0),
|
|
186
186
|
children: [k, " Edit"]
|
|
187
187
|
})]
|
|
188
188
|
}),
|
|
189
|
-
/* @__PURE__ */
|
|
190
|
-
style:
|
|
191
|
-
language:
|
|
189
|
+
/* @__PURE__ */ o(c, {
|
|
190
|
+
style: l,
|
|
191
|
+
language: D(m),
|
|
192
192
|
PreTag: "div",
|
|
193
193
|
customStyle: {
|
|
194
194
|
borderRadius: "0 0 0.5rem 0.5rem",
|
|
@@ -196,17 +196,17 @@ var D = ({ node: l, editor: u, updateAttributes: d }) => {
|
|
|
196
196
|
padding: "1em",
|
|
197
197
|
margin: "0"
|
|
198
198
|
},
|
|
199
|
-
children:
|
|
199
|
+
children: _ || " "
|
|
200
200
|
}),
|
|
201
|
-
/* @__PURE__ */
|
|
201
|
+
/* @__PURE__ */ o("div", {
|
|
202
202
|
style: { display: "none" },
|
|
203
203
|
"aria-hidden": "true",
|
|
204
|
-
children: /* @__PURE__ */
|
|
204
|
+
children: /* @__PURE__ */ o(h, { as: "code" })
|
|
205
205
|
})
|
|
206
206
|
]
|
|
207
207
|
})
|
|
208
208
|
});
|
|
209
|
-
},
|
|
209
|
+
}, k = /^```([a-z-]*)[\s\n]$/, A = /^~~~([a-z-]*)[\s\n]$/, j = /^(?:```|~~~)table(?:(\d+)[x×X*](\d+))?\s?$/, M = m.create({
|
|
210
210
|
name: "codeBlock",
|
|
211
211
|
group: "block",
|
|
212
212
|
content: "text*",
|
|
@@ -232,7 +232,7 @@ var D = ({ node: l, editor: u, updateAttributes: d }) => {
|
|
|
232
232
|
renderHTML({ node: e, HTMLAttributes: t }) {
|
|
233
233
|
return [
|
|
234
234
|
"pre",
|
|
235
|
-
|
|
235
|
+
v(t, { "data-language": e.attrs.language }),
|
|
236
236
|
[
|
|
237
237
|
"code",
|
|
238
238
|
{ class: e.attrs.language ? `language-${e.attrs.language}` : void 0 },
|
|
@@ -241,31 +241,31 @@ var D = ({ node: l, editor: u, updateAttributes: d }) => {
|
|
|
241
241
|
];
|
|
242
242
|
},
|
|
243
243
|
addInputRules() {
|
|
244
|
-
return [
|
|
245
|
-
find:
|
|
244
|
+
return [y({
|
|
245
|
+
find: k,
|
|
246
246
|
type: this.type,
|
|
247
247
|
getAttributes: (e) => !e[1]?.startsWith("table") && { language: e[1] || null }
|
|
248
|
-
}),
|
|
249
|
-
find:
|
|
248
|
+
}), y({
|
|
249
|
+
find: A,
|
|
250
250
|
type: this.type,
|
|
251
251
|
getAttributes: (e) => !e[1]?.startsWith("table") && { language: e[1] || null }
|
|
252
252
|
})];
|
|
253
253
|
},
|
|
254
254
|
addProseMirrorPlugins() {
|
|
255
255
|
let e = this.editor;
|
|
256
|
-
return [new
|
|
257
|
-
key: new
|
|
256
|
+
return [new b({
|
|
257
|
+
key: new x("tableShortcut"),
|
|
258
258
|
props: {
|
|
259
259
|
handleTextInput(n, r, i, a) {
|
|
260
260
|
if (!e.isEditable || a !== " ") return !1;
|
|
261
|
-
let { state: o } = n, s = o.doc.resolve(r).start(), c = o.doc.textBetween(s, r, "\0") + " ", l =
|
|
261
|
+
let { state: o } = n, s = o.doc.resolve(r).start(), c = o.doc.textBetween(s, r, "\0") + " ", l = j.exec(c);
|
|
262
262
|
return l ? (t(n, s, i, Math.min(Math.max(parseInt(l[1], 10) || 3, 1), 20), Math.min(Math.max(parseInt(l[2], 10) || 3, 1), 20)), !0) : !1;
|
|
263
263
|
},
|
|
264
264
|
handleKeyDown(n, r) {
|
|
265
265
|
if (!e.isEditable || r.key !== "Enter") return !1;
|
|
266
266
|
let { state: i } = n, { $from: a } = i.selection;
|
|
267
267
|
if (!a.parent.isTextblock) return !1;
|
|
268
|
-
let o = a.start(), s = i.doc.textBetween(o, a.pos, "\0"), c =
|
|
268
|
+
let o = a.start(), s = i.doc.textBetween(o, a.pos, "\0"), c = j.exec(s);
|
|
269
269
|
if (!c) return !1;
|
|
270
270
|
r.preventDefault();
|
|
271
271
|
let l = Math.min(Math.max(parseInt(c[1], 10) || 3, 1), 20), u = Math.min(Math.max(parseInt(c[2], 10) || 3, 1), 20);
|
|
@@ -298,10 +298,10 @@ var D = ({ node: l, editor: u, updateAttributes: d }) => {
|
|
|
298
298
|
};
|
|
299
299
|
},
|
|
300
300
|
addNodeView() {
|
|
301
|
-
return
|
|
301
|
+
return _(O);
|
|
302
302
|
}
|
|
303
303
|
});
|
|
304
304
|
//#endregion
|
|
305
|
-
export {
|
|
305
|
+
export { M as CodeBlockExtension, M as default };
|
|
306
306
|
|
|
307
307
|
//# sourceMappingURL=CodeBlockView.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeBlockView.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/extensions/CodeBlockView.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport { Node, mergeAttributes, textblockTypeInputRule } from '@tiptap/react';\nimport { Plugin, PluginKey } from '@tiptap/pm/state';\nimport { NodeViewWrapper, NodeViewContent, ReactNodeViewRenderer } from '@tiptap/react';\nimport type { NodeViewProps } from '@tiptap/react';\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport { oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport remarkMath from 'remark-math';\nimport rehypeKatex from 'rehype-katex';\nimport { MermaidRenderer, useNodeEditable } from './MarkdownBlock';\nimport 'katex/dist/katex.min.css';\n\n\nconst KatexRenderer: React.FC<{ code: string }> = ({ code }) => {\n const wrapped = code.includes('$$') ? code : `$$\\n${code}\\n$$`;\n return (\n <ReactMarkdown\n remarkPlugins={[remarkMath]}\n rehypePlugins={[rehypeKatex]}\n >\n {wrapped}\n </ReactMarkdown>\n );\n};\n\nconst MarkdownRenderer: React.FC<{ code: string }> = ({ code }) => {\n return (\n <ReactMarkdown\n remarkPlugins={[remarkGfm, remarkMath]}\n rehypePlugins={[rehypeKatex]}\n components={{\n code({ className, children, ...props }) {\n const match = /language-(\\w+)/.exec(className || '');\n const lang = match?.[1];\n const text = String(children).replace(/\\n$/, '');\n\n if (lang === 'mermaid') return <MermaidRenderer code={text} />;\n\n if (lang) {\n return (\n <SyntaxHighlighter\n style={oneLight as Record<string, React.CSSProperties>}\n language={lang}\n PreTag=\"div\"\n customStyle={{ borderRadius: '0.5rem', fontSize: '0.875em', padding: '1em', margin: '0.5em 0' }}\n >\n {text}\n </SyntaxHighlighter>\n );\n }\n return <code className={className} {...props}>{children}</code>;\n },\n }}\n >\n {code}\n </ReactMarkdown>\n );\n};\n\nconst RENDER_LANGUAGES = ['markdown', 'mermaid', 'math'];\n\nconst HIGHLIGHT_LANGUAGES = [\n '', 'javascript', 'typescript', 'python', 'rust', 'go', 'java', 'c', 'cpp',\n 'csharp', 'ruby', 'php', 'swift', 'kotlin', 'sql', 'bash', 'shell',\n 'html', 'css', 'json', 'yaml', 'toml', 'xml',\n 'docker', 'graphql', 'latex', 'tex',\n];\n\nfunction renderLang(lang: string): string {\n // Legacy documents keep their r- attributes; the selector uses canonical names.\n const canonical = lang.startsWith('r-') ? lang.slice(2) : lang;\n return RENDER_LANGUAGES.includes(canonical) ? canonical : '';\n}\n\nfunction highlightLang(lang: string): string {\n if (lang === 'math' || lang === 'latex' || lang === 'tex') return 'latex';\n return lang;\n}\n\nconst CodeBlockNodeView: React.FC<NodeViewProps> = ({\n node,\n editor,\n updateAttributes,\n}) => {\n const editable = useNodeEditable(editor);\n const language = node.attrs.language || '';\n const textContent = node.textContent;\n const hasLanguage = !!language;\n const renderLanguage = renderLang(language);\n const isRenderable = !!renderLanguage;\n\n const [isEditing, setIsEditing] = useState(true);\n\n useEffect(() => {\n if (!hasLanguage) setIsEditing(true);\n }, [language, hasLanguage]);\n\n // Read-only viewers always get the rendered/preview state, never the editor chrome.\n useEffect(() => {\n if (!editable) setIsEditing(false);\n }, [editable]);\n\n const showEditing = isEditing && editable;\n\n const editIcon = (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\" />\n <path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\" />\n </svg>\n );\n const previewIcon = (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n );\n\n const renderPreview = () => {\n if (renderLanguage === 'mermaid') {\n return textContent.trim()\n ? <MermaidRenderer code={textContent} />\n : <p className=\"rte-codeblock__placeholder\">Enter mermaid diagram code...</p>;\n }\n if (renderLanguage === 'math') {\n return textContent.trim()\n ? <KatexRenderer code={textContent} />\n : <p className=\"rte-codeblock__placeholder\">Enter KaTeX math formula...</p>;\n }\n if (renderLanguage === 'markdown') {\n return textContent.trim()\n ? <MarkdownRenderer code={textContent} />\n : <p className=\"rte-codeblock__placeholder\">Enter Markdown content...</p>;\n }\n return null;\n };\n\n const displayLabel = renderLanguage ? renderLanguage + ' (render)' : language || 'plain text';\n\n return (\n <NodeViewWrapper className={`rte-codeblock-wrapper ${!isEditing && hasLanguage ? 'rte-codeblock-wrapper--preview' : ''}`}>\n {showEditing ? (\n <>\n <div className=\"rte-codeblock__header\">\n <select\n className=\"rte-codeblock__lang-select\"\n value={renderLanguage || language}\n disabled={!editable}\n onChange={(e) => {\n if (editor.isDestroyed || !editor.isEditable) return;\n updateAttributes({ language: e.target.value });\n if (!e.target.value) setIsEditing(true);\n }}\n contentEditable={false}\n >\n <option value=\"\">Plain text</option>\n <optgroup label=\"Syntax Highlight\">\n {HIGHLIGHT_LANGUAGES.filter(Boolean).map((lang) => (\n <option key={lang} value={lang}>{lang}</option>\n ))}\n </optgroup>\n <optgroup label=\"Live Render\">\n {RENDER_LANGUAGES.map((lang) => (\n <option key={lang} value={lang}>{lang}</option>\n ))}\n </optgroup>\n </select>\n {hasLanguage && (\n <button\n type=\"button\"\n className=\"rte-codeblock__preview-btn\"\n onClick={() => setIsEditing(false)}\n contentEditable={false}\n >\n {previewIcon} Preview\n </button>\n )}\n </div>\n <pre className=\"rte-codeblock__editable-pre\">\n <NodeViewContent as={'code' as any} />\n </pre>\n </>\n ) : isRenderable ? (\n <div\n className=\"rte-codeblock__render-preview\"\n contentEditable={false}\n onDoubleClick={() => { if (editable) setIsEditing(true); }}\n >\n <div className=\"rte-codeblock__preview-toolbar\" contentEditable={false}>\n <span className=\"rte-codeblock__preview-label\">{displayLabel}</span>\n {editable && (\n <button\n type=\"button\"\n className=\"rte-codeblock__preview-edit-btn\"\n onClick={() => setIsEditing(true)}\n >\n {editIcon} Edit\n </button>\n )}\n </div>\n <div className=\"rte-codeblock__render-body\">\n {renderPreview()}\n </div>\n {/* 预览分支也必须挂载 contentDOM(隐藏):不渲染 NodeViewContent 时\n tiptap 会把代码文本以 data-node-view-content-react 形式再渲染\n 一份裸露副本,只读 / 预览下出现重复的原始代码。 */}\n <div style={{ display: 'none' }} aria-hidden=\"true\">\n <NodeViewContent as={'code' as any} />\n </div>\n </div>\n ) : (\n <div\n className=\"rte-codeblock__syntax-preview\"\n contentEditable={false}\n onDoubleClick={() => { if (editable) setIsEditing(true); }}\n >\n <div className=\"rte-codeblock__preview-toolbar\" contentEditable={false}>\n <span className=\"rte-codeblock__preview-label\">{displayLabel}</span>\n {editable && (\n <button\n type=\"button\"\n className=\"rte-codeblock__preview-edit-btn\"\n onClick={() => setIsEditing(true)}\n >\n {editIcon} Edit\n </button>\n )}\n </div>\n <SyntaxHighlighter\n style={oneLight as Record<string, React.CSSProperties>}\n language={highlightLang(language)}\n PreTag=\"div\"\n customStyle={{\n borderRadius: '0 0 0.5rem 0.5rem',\n fontSize: '0.875em',\n padding: '1em',\n margin: '0',\n }}\n >\n {textContent || ' '}\n </SyntaxHighlighter>\n <div style={{ display: 'none' }} aria-hidden=\"true\">\n <NodeViewContent as={'code' as any} />\n </div>\n </div>\n )}\n </NodeViewWrapper>\n );\n};\n\nconst backtickInputRegex = /^```([a-z-]*)[\\s\\n]$/;\nconst tildeInputRegex = /^~~~([a-z-]*)[\\s\\n]$/;\nconst tableShortcutRegex = /^(?:```|~~~)table(?:(\\d+)[x×X*](\\d+))?\\s?$/;\n\nexport const CodeBlockExtension = Node.create({\n name: 'codeBlock',\n group: 'block',\n content: 'text*',\n marks: '',\n code: true,\n defining: true,\n\n addAttributes() {\n return {\n language: {\n default: null,\n parseHTML: (element) => {\n const classAttr = element.querySelector('code')?.className ||\n element.className || '';\n const match = /language-([\\w-]+)/.exec(classAttr);\n return match?.[1] || element.getAttribute('data-language') || null;\n },\n renderHTML: (attributes) => {\n if (!attributes.language) return {};\n return { 'data-language': attributes.language };\n },\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'pre',\n preserveWhitespace: 'full',\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n return [\n 'pre',\n mergeAttributes(HTMLAttributes, { 'data-language': node.attrs.language }),\n ['code', { class: node.attrs.language ? `language-${node.attrs.language}` : undefined }, 0],\n ];\n },\n\n addInputRules() {\n return [\n textblockTypeInputRule({\n find: backtickInputRegex,\n type: this.type,\n getAttributes: (match) => {\n if (match[1]?.startsWith('table')) return false;\n return { language: match[1] || null };\n },\n }),\n textblockTypeInputRule({\n find: tildeInputRegex,\n type: this.type,\n getAttributes: (match) => {\n if (match[1]?.startsWith('table')) return false;\n return { language: match[1] || null };\n },\n }),\n ];\n },\n\n addProseMirrorPlugins() {\n const editorRef = this.editor;\n return [\n new Plugin({\n key: new PluginKey('tableShortcut'),\n props: {\n handleTextInput(view, from, to, text) {\n if (!editorRef.isEditable || text !== ' ') return false;\n const { state } = view;\n const $from = state.doc.resolve(from);\n const blockStart = $from.start();\n const textBefore = state.doc.textBetween(blockStart, from, '\\0');\n const full = textBefore + ' ';\n const m = tableShortcutRegex.exec(full);\n if (!m) return false;\n\n const rows = Math.min(Math.max(parseInt(m[1], 10) || 3, 1), 20);\n const cols = Math.min(Math.max(parseInt(m[2], 10) || 3, 1), 20);\n dispatchTable(view, blockStart, to, rows, cols);\n return true;\n },\n handleKeyDown(view, event) {\n if (!editorRef.isEditable || event.key !== 'Enter') return false;\n const { state } = view;\n const { $from } = state.selection;\n if (!$from.parent.isTextblock) return false;\n const blockStart = $from.start();\n const textBefore = state.doc.textBetween(blockStart, $from.pos, '\\0');\n const m = tableShortcutRegex.exec(textBefore);\n if (!m) return false;\n\n event.preventDefault();\n const rows = Math.min(Math.max(parseInt(m[1], 10) || 3, 1), 20);\n const cols = Math.min(Math.max(parseInt(m[2], 10) || 3, 1), 20);\n dispatchTable(view, blockStart, $from.pos, rows, cols);\n return true;\n },\n },\n }),\n ];\n\n function dispatchTable(view: typeof editorRef.view, from: number, to: number, rows: number, cols: number) {\n const { state } = view;\n const $from = state.doc.resolve(from);\n const blockNode = $from.parent;\n const blockPos = $from.before();\n\n const tableType = state.schema.nodes.table;\n const rowType = state.schema.nodes.tableRow;\n const headerType = state.schema.nodes.tableHeader;\n const cellType = state.schema.nodes.tableCell;\n if (!tableType || !rowType || !cellType) return;\n\n const emptyParagraph = state.schema.nodes.paragraph.create();\n const buildRow = (isHeader: boolean) => {\n const type = isHeader && headerType ? headerType : cellType;\n const cells = Array.from({ length: cols }, () => type.create(null, emptyParagraph));\n return rowType.create(null, cells);\n };\n\n const tableRows = [\n buildRow(true),\n ...Array.from({ length: rows - 1 }, () => buildRow(false)),\n ];\n const table = tableType.create(null, tableRows);\n const tr = state.tr.replaceWith(blockPos, blockPos + blockNode.nodeSize, table);\n view.dispatch(tr);\n }\n },\n\n addKeyboardShortcuts() {\n return {\n 'Mod-Alt-c': () => this.editor.isEditable && this.editor.commands.toggleNode('codeBlock', 'paragraph'),\n Tab: ({ editor }) => {\n if (!editor.isEditable) return false;\n if (editor.isActive('codeBlock')) {\n editor.commands.insertContent('\\t');\n return true;\n }\n return false;\n },\n Enter: ({ editor }) => {\n if (!editor.isEditable) return false;\n if (!editor.isActive('codeBlock')) return false;\n editor.commands.newlineInCode();\n return true;\n },\n ArrowDown: ({ editor }) => {\n if (!editor.isEditable) return false;\n if (!editor.isActive('codeBlock')) return false;\n const { $from } = editor.state.selection;\n const isAtEnd = $from.parentOffset === $from.parent.content.size;\n if (!isAtEnd) return false;\n const after = $from.after();\n if (after === undefined) return false;\n const nodeAfter = editor.state.doc.nodeAt(after);\n if (nodeAfter) return false;\n editor.commands.exitCode();\n return true;\n },\n };\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(CodeBlockNodeView);\n },\n});\n\nexport default CodeBlockExtension;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CodeBlockView.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/extensions/CodeBlockView.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport { Node, mergeAttributes, textblockTypeInputRule } from '@tiptap/react';\nimport { Plugin, PluginKey } from '@tiptap/pm/state';\nimport { NodeViewWrapper, NodeViewContent, ReactNodeViewRenderer } from '@tiptap/react';\nimport type { NodeViewProps } from '@tiptap/react';\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport { oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport remarkMath from 'remark-math';\nimport rehypeKatex from 'rehype-katex';\nimport { MermaidRenderer, useNodeEditable } from './MarkdownBlock';\nimport Select from '../../../Select';\nimport 'katex/dist/katex.min.css';\n\n\nconst KatexRenderer: React.FC<{ code: string }> = ({ code }) => {\n const wrapped = code.includes('$$') ? code : `$$\\n${code}\\n$$`;\n return (\n <ReactMarkdown\n remarkPlugins={[remarkMath]}\n rehypePlugins={[rehypeKatex]}\n >\n {wrapped}\n </ReactMarkdown>\n );\n};\n\nconst MarkdownRenderer: React.FC<{ code: string }> = ({ code }) => {\n return (\n <ReactMarkdown\n remarkPlugins={[remarkGfm, remarkMath]}\n rehypePlugins={[rehypeKatex]}\n components={{\n code({ className, children, ...props }) {\n const match = /language-(\\w+)/.exec(className || '');\n const lang = match?.[1];\n const text = String(children).replace(/\\n$/, '');\n\n if (lang === 'mermaid') return <MermaidRenderer code={text} />;\n\n if (lang) {\n return (\n <SyntaxHighlighter\n style={oneLight as Record<string, React.CSSProperties>}\n language={lang}\n PreTag=\"div\"\n customStyle={{ borderRadius: '0.5rem', fontSize: '0.875em', padding: '1em', margin: '0.5em 0' }}\n >\n {text}\n </SyntaxHighlighter>\n );\n }\n return <code className={className} {...props}>{children}</code>;\n },\n }}\n >\n {code}\n </ReactMarkdown>\n );\n};\n\nconst RENDER_LANGUAGES = ['markdown', 'mermaid', 'math'];\n\nconst HIGHLIGHT_LANGUAGES = [\n '', 'javascript', 'typescript', 'python', 'rust', 'go', 'java', 'c', 'cpp',\n 'csharp', 'ruby', 'php', 'swift', 'kotlin', 'sql', 'bash', 'shell',\n 'html', 'css', 'json', 'yaml', 'toml', 'xml',\n 'docker', 'graphql', 'latex', 'tex',\n];\n\nconst LANGUAGE_OPTIONS = [\n { label: 'Plain text', value: '' },\n ...HIGHLIGHT_LANGUAGES.filter(Boolean).map(lang => ({ label: `Syntax · ${lang}`, value: lang })),\n ...RENDER_LANGUAGES.map(lang => ({ label: `Render · ${lang}`, value: lang })),\n];\n\nfunction renderLang(lang: string): string {\n // Legacy documents keep their r- attributes; the selector uses canonical names.\n const canonical = lang.startsWith('r-') ? lang.slice(2) : lang;\n return RENDER_LANGUAGES.includes(canonical) ? canonical : '';\n}\n\nfunction highlightLang(lang: string): string {\n if (lang === 'math' || lang === 'latex' || lang === 'tex') return 'latex';\n return lang;\n}\n\nconst CodeBlockNodeView: React.FC<NodeViewProps> = ({\n node,\n editor,\n updateAttributes,\n}) => {\n const editable = useNodeEditable(editor);\n const language = node.attrs.language || '';\n const textContent = node.textContent;\n const hasLanguage = !!language;\n const renderLanguage = renderLang(language);\n const isRenderable = !!renderLanguage;\n\n const [isEditing, setIsEditing] = useState(true);\n\n useEffect(() => {\n if (!hasLanguage) setIsEditing(true);\n }, [language, hasLanguage]);\n\n // Read-only viewers always get the rendered/preview state, never the editor chrome.\n useEffect(() => {\n if (!editable) setIsEditing(false);\n }, [editable]);\n\n const showEditing = isEditing && editable;\n\n const editIcon = (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\" />\n <path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\" />\n </svg>\n );\n const previewIcon = (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n );\n\n const renderPreview = () => {\n if (renderLanguage === 'mermaid') {\n return textContent.trim()\n ? <MermaidRenderer code={textContent} />\n : <p className=\"rte-codeblock__placeholder\">Enter mermaid diagram code...</p>;\n }\n if (renderLanguage === 'math') {\n return textContent.trim()\n ? <KatexRenderer code={textContent} />\n : <p className=\"rte-codeblock__placeholder\">Enter KaTeX math formula...</p>;\n }\n if (renderLanguage === 'markdown') {\n return textContent.trim()\n ? <MarkdownRenderer code={textContent} />\n : <p className=\"rte-codeblock__placeholder\">Enter Markdown content...</p>;\n }\n return null;\n };\n\n const displayLabel = renderLanguage ? renderLanguage + ' (render)' : language || 'plain text';\n\n return (\n <NodeViewWrapper className={`rte-codeblock-wrapper ${!isEditing && hasLanguage ? 'rte-codeblock-wrapper--preview' : ''}`}>\n {showEditing ? (\n <>\n <div className=\"rte-codeblock__header\">\n <div contentEditable={false} className=\"rte-codeblock__lang-control\">\n <Select\n className=\"rte-codeblock__lang-select\"\n aria-label=\"Code language\"\n value={renderLanguage || language}\n options={LANGUAGE_OPTIONS}\n onChange={(next) => {\n if (editor.isDestroyed || !editor.isEditable) return;\n const selected = String(next);\n updateAttributes({ language: selected });\n if (!selected) setIsEditing(true);\n }}\n />\n </div>\n {hasLanguage && (\n <button\n type=\"button\"\n className=\"rte-codeblock__preview-btn\"\n onClick={() => setIsEditing(false)}\n contentEditable={false}\n >\n {previewIcon} Preview\n </button>\n )}\n </div>\n <pre className=\"rte-codeblock__editable-pre\">\n <NodeViewContent as={'code' as any} />\n </pre>\n </>\n ) : isRenderable ? (\n <div\n className=\"rte-codeblock__render-preview\"\n contentEditable={false}\n onDoubleClick={() => { if (editable) setIsEditing(true); }}\n >\n <div className=\"rte-codeblock__preview-toolbar\" contentEditable={false}>\n <span className=\"rte-codeblock__preview-label\">{displayLabel}</span>\n {editable && (\n <button\n type=\"button\"\n className=\"rte-codeblock__preview-edit-btn\"\n onClick={() => setIsEditing(true)}\n >\n {editIcon} Edit\n </button>\n )}\n </div>\n <div className=\"rte-codeblock__render-body\">\n {renderPreview()}\n </div>\n {/* 预览分支也必须挂载 contentDOM(隐藏):不渲染 NodeViewContent 时\n tiptap 会把代码文本以 data-node-view-content-react 形式再渲染\n 一份裸露副本,只读 / 预览下出现重复的原始代码。 */}\n <div style={{ display: 'none' }} aria-hidden=\"true\">\n <NodeViewContent as={'code' as any} />\n </div>\n </div>\n ) : (\n <div\n className=\"rte-codeblock__syntax-preview\"\n contentEditable={false}\n onDoubleClick={() => { if (editable) setIsEditing(true); }}\n >\n <div className=\"rte-codeblock__preview-toolbar\" contentEditable={false}>\n <span className=\"rte-codeblock__preview-label\">{displayLabel}</span>\n {editable && (\n <button\n type=\"button\"\n className=\"rte-codeblock__preview-edit-btn\"\n onClick={() => setIsEditing(true)}\n >\n {editIcon} Edit\n </button>\n )}\n </div>\n <SyntaxHighlighter\n style={oneLight as Record<string, React.CSSProperties>}\n language={highlightLang(language)}\n PreTag=\"div\"\n customStyle={{\n borderRadius: '0 0 0.5rem 0.5rem',\n fontSize: '0.875em',\n padding: '1em',\n margin: '0',\n }}\n >\n {textContent || ' '}\n </SyntaxHighlighter>\n <div style={{ display: 'none' }} aria-hidden=\"true\">\n <NodeViewContent as={'code' as any} />\n </div>\n </div>\n )}\n </NodeViewWrapper>\n );\n};\n\nconst backtickInputRegex = /^```([a-z-]*)[\\s\\n]$/;\nconst tildeInputRegex = /^~~~([a-z-]*)[\\s\\n]$/;\nconst tableShortcutRegex = /^(?:```|~~~)table(?:(\\d+)[x×X*](\\d+))?\\s?$/;\n\nexport const CodeBlockExtension = Node.create({\n name: 'codeBlock',\n group: 'block',\n content: 'text*',\n marks: '',\n code: true,\n defining: true,\n\n addAttributes() {\n return {\n language: {\n default: null,\n parseHTML: (element) => {\n const classAttr = element.querySelector('code')?.className ||\n element.className || '';\n const match = /language-([\\w-]+)/.exec(classAttr);\n return match?.[1] || element.getAttribute('data-language') || null;\n },\n renderHTML: (attributes) => {\n if (!attributes.language) return {};\n return { 'data-language': attributes.language };\n },\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'pre',\n preserveWhitespace: 'full',\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n return [\n 'pre',\n mergeAttributes(HTMLAttributes, { 'data-language': node.attrs.language }),\n ['code', { class: node.attrs.language ? `language-${node.attrs.language}` : undefined }, 0],\n ];\n },\n\n addInputRules() {\n return [\n textblockTypeInputRule({\n find: backtickInputRegex,\n type: this.type,\n getAttributes: (match) => {\n if (match[1]?.startsWith('table')) return false;\n return { language: match[1] || null };\n },\n }),\n textblockTypeInputRule({\n find: tildeInputRegex,\n type: this.type,\n getAttributes: (match) => {\n if (match[1]?.startsWith('table')) return false;\n return { language: match[1] || null };\n },\n }),\n ];\n },\n\n addProseMirrorPlugins() {\n const editorRef = this.editor;\n return [\n new Plugin({\n key: new PluginKey('tableShortcut'),\n props: {\n handleTextInput(view, from, to, text) {\n if (!editorRef.isEditable || text !== ' ') return false;\n const { state } = view;\n const $from = state.doc.resolve(from);\n const blockStart = $from.start();\n const textBefore = state.doc.textBetween(blockStart, from, '\\0');\n const full = textBefore + ' ';\n const m = tableShortcutRegex.exec(full);\n if (!m) return false;\n\n const rows = Math.min(Math.max(parseInt(m[1], 10) || 3, 1), 20);\n const cols = Math.min(Math.max(parseInt(m[2], 10) || 3, 1), 20);\n dispatchTable(view, blockStart, to, rows, cols);\n return true;\n },\n handleKeyDown(view, event) {\n if (!editorRef.isEditable || event.key !== 'Enter') return false;\n const { state } = view;\n const { $from } = state.selection;\n if (!$from.parent.isTextblock) return false;\n const blockStart = $from.start();\n const textBefore = state.doc.textBetween(blockStart, $from.pos, '\\0');\n const m = tableShortcutRegex.exec(textBefore);\n if (!m) return false;\n\n event.preventDefault();\n const rows = Math.min(Math.max(parseInt(m[1], 10) || 3, 1), 20);\n const cols = Math.min(Math.max(parseInt(m[2], 10) || 3, 1), 20);\n dispatchTable(view, blockStart, $from.pos, rows, cols);\n return true;\n },\n },\n }),\n ];\n\n function dispatchTable(view: typeof editorRef.view, from: number, to: number, rows: number, cols: number) {\n const { state } = view;\n const $from = state.doc.resolve(from);\n const blockNode = $from.parent;\n const blockPos = $from.before();\n\n const tableType = state.schema.nodes.table;\n const rowType = state.schema.nodes.tableRow;\n const headerType = state.schema.nodes.tableHeader;\n const cellType = state.schema.nodes.tableCell;\n if (!tableType || !rowType || !cellType) return;\n\n const emptyParagraph = state.schema.nodes.paragraph.create();\n const buildRow = (isHeader: boolean) => {\n const type = isHeader && headerType ? headerType : cellType;\n const cells = Array.from({ length: cols }, () => type.create(null, emptyParagraph));\n return rowType.create(null, cells);\n };\n\n const tableRows = [\n buildRow(true),\n ...Array.from({ length: rows - 1 }, () => buildRow(false)),\n ];\n const table = tableType.create(null, tableRows);\n const tr = state.tr.replaceWith(blockPos, blockPos + blockNode.nodeSize, table);\n view.dispatch(tr);\n }\n },\n\n addKeyboardShortcuts() {\n return {\n 'Mod-Alt-c': () => this.editor.isEditable && this.editor.commands.toggleNode('codeBlock', 'paragraph'),\n Tab: ({ editor }) => {\n if (!editor.isEditable) return false;\n if (editor.isActive('codeBlock')) {\n editor.commands.insertContent('\\t');\n return true;\n }\n return false;\n },\n Enter: ({ editor }) => {\n if (!editor.isEditable) return false;\n if (!editor.isActive('codeBlock')) return false;\n editor.commands.newlineInCode();\n return true;\n },\n ArrowDown: ({ editor }) => {\n if (!editor.isEditable) return false;\n if (!editor.isActive('codeBlock')) return false;\n const { $from } = editor.state.selection;\n const isAtEnd = $from.parentOffset === $from.parent.content.size;\n if (!isAtEnd) return false;\n const after = $from.after();\n if (after === undefined) return false;\n const nodeAfter = editor.state.doc.nodeAt(after);\n if (nodeAfter) return false;\n editor.commands.exitCode();\n return true;\n },\n };\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(CodeBlockNodeView);\n },\n});\n\nexport default CodeBlockExtension;\n"],"mappings":"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"}
|
|
@@ -102,6 +102,8 @@ export interface RichTextEditorProps {
|
|
|
102
102
|
onRequestAIConfig?: () => void;
|
|
103
103
|
/** Toggle toolbar sections (all enabled by default) */
|
|
104
104
|
toolbarConfig?: ToolbarSection;
|
|
105
|
+
/** Keep an open AI panel's selected text and replacement target in sync with new editor selections. */
|
|
106
|
+
aiSelectionFollowsEditor?: boolean;
|
|
105
107
|
/** Minimum editor height */
|
|
106
108
|
minHeight?: string | number;
|
|
107
109
|
/** Maximum editor height */
|