@gravity-ui/markdown-editor 15.34.3 → 15.34.5
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/build/cjs/extensions/additional/Mermaid/MermaidNodeView/MermaidView.js +3 -1
- package/build/cjs/extensions/additional/Mermaid/MermaidNodeView/MermaidView.js.map +1 -1
- package/build/cjs/extensions/behavior/Placeholder/index.js +54 -20
- package/build/cjs/extensions/behavior/Placeholder/index.js.map +1 -1
- package/build/cjs/version.js +1 -1
- package/build/cjs/version.js.map +1 -1
- package/build/esm/extensions/additional/Mermaid/MermaidNodeView/MermaidView.js +4 -2
- package/build/esm/extensions/additional/Mermaid/MermaidNodeView/MermaidView.js.map +1 -1
- package/build/esm/extensions/behavior/Placeholder/index.js +55 -21
- package/build/esm/extensions/behavior/Placeholder/index.js.map +1 -1
- package/build/esm/version.js +1 -1
- package/build/esm/version.js.map +1 -1
- package/package.json +1 -1
|
@@ -20,12 +20,14 @@ const b = exports.cnMermaid;
|
|
|
20
20
|
const MermaidPreview = ({ mermaidInstance, text = '', }) => {
|
|
21
21
|
const [svg, setSvg] = (0, react_1.useState)();
|
|
22
22
|
const [error, setError] = (0, react_1.useState)(null);
|
|
23
|
+
const theme = (0, uikit_1.useThemeType)();
|
|
23
24
|
(0, react_1.useEffect)(() => {
|
|
24
25
|
const p = async () => {
|
|
25
26
|
if (mermaidInstance) {
|
|
26
27
|
try {
|
|
27
28
|
// Validates syntax and throws error if text is invalid
|
|
28
29
|
await mermaidInstance.parse(text);
|
|
30
|
+
mermaidInstance.initialize({ theme: theme === 'dark' ? 'dark' : 'forest' });
|
|
29
31
|
const { svg: S } = await mermaidInstance.render(`mermaid-${Date.now()}`, text);
|
|
30
32
|
setSvg(S);
|
|
31
33
|
setError(null);
|
|
@@ -36,7 +38,7 @@ const MermaidPreview = ({ mermaidInstance, text = '', }) => {
|
|
|
36
38
|
}
|
|
37
39
|
};
|
|
38
40
|
p();
|
|
39
|
-
}, [mermaidInstance, text]);
|
|
41
|
+
}, [mermaidInstance, text, theme]);
|
|
40
42
|
if (error) {
|
|
41
43
|
return (0, jsx_runtime_1.jsx)("div", { className: b('Error'), children: error && (0, jsx_runtime_1.jsx)("div", { children: error }) });
|
|
42
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MermaidView.js","sourceRoot":"../../../../../../src","sources":["extensions/additional/Mermaid/MermaidNodeView/MermaidView.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useEffect, useMemo, useState} from 'react';\n\nimport {Ellipsis as DotsIcon} from '@gravity-ui/icons';\nimport {Button, Icon, Loader, Menu, Popup} from '@gravity-ui/uikit';\nimport type {Mermaid} from 'mermaid' with {'resolution-mode': 'import'};\nimport type {Node} from 'prosemirror-model';\nimport type {EditorView} from 'prosemirror-view';\n\nimport {SharedStateKey} from 'src/extensions/behavior/SharedState';\nimport {useSharedEditingState} from 'src/react-utils/useSharedEditingState';\n\nimport {cn} from '../../../../classname';\nimport {TextAreaFixed as TextArea} from '../../../../forms/TextInput';\nimport {i18n} from '../../../../i18n/common';\nimport {useAutoSave, useBooleanState, useElementState} from '../../../../react-utils';\nimport {removeNode} from '../../../../utils';\nimport {MermaidConsts} from '../MermaidSpecs/const';\nimport type {MermaidOptions} from '../index';\nimport type {MermaidEntitySharedState} from '../types';\n\nexport const cnMermaid = cn('Mermaid');\n\nexport const STOP_EVENT_CLASSNAME = 'prosemirror-stop-event';\n\nimport './Mermaid.scss';\n\nconst b = cnMermaid;\n\nconst MermaidPreview: React.FC<{mermaidInstance: Mermaid | null; text: string}> = ({\n mermaidInstance,\n text = '',\n}) => {\n const [svg, setSvg] = useState<string>();\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const p = async () => {\n if (mermaidInstance) {\n try {\n // Validates syntax and throws error if text is invalid\n await mermaidInstance.parse(text);\n\n const {svg: S} = await mermaidInstance.render(`mermaid-${Date.now()}`, text);\n\n setSvg(S);\n setError(null);\n } catch (e) {\n setError((e as Error).message);\n }\n }\n };\n\n p();\n }, [mermaidInstance, text]);\n\n if (error) {\n return <div className={b('Error')}>{error && <div>{error}</div>}</div>;\n }\n\n return (\n <div className={b('Preview')}>\n {svg ? <div className=\"mermaid\" dangerouslySetInnerHTML={{__html: svg}} /> : <Loader />}\n </div>\n );\n};\n\nconst DiagramEditMode: React.FC<{\n initialText: string;\n mermaidInstance: Mermaid | null;\n onSave: (v: string) => void;\n onCancel: () => void;\n options: MermaidOptions;\n}> = ({initialText, onSave, onCancel, mermaidInstance, options: {autoSave}}) => {\n const {value, handleChange, handleManualSave, isSaveDisabled, isAutoSaveEnabled} = useAutoSave({\n initialValue: initialText || '',\n onSave,\n onClose: onCancel,\n autoSave,\n });\n\n return (\n <div className={b()}>\n <MermaidPreview mermaidInstance={mermaidInstance} text={value} />\n <div className={b('Editor')}>\n <div>\n <TextArea\n controlProps={{\n className: STOP_EVENT_CLASSNAME,\n }}\n value={value}\n onUpdate={handleChange}\n autoFocus\n />\n </div>\n <div className={b('Controls')}>\n <div>\n <Button onClick={onCancel} view={'flat'}>\n <span className={STOP_EVENT_CLASSNAME}>\n {isAutoSaveEnabled ? i18n('close') : i18n('cancel')}\n </span>\n </Button>\n {!isAutoSaveEnabled && (\n <Button\n onClick={handleManualSave}\n view={'action'}\n disabled={isSaveDisabled}\n >\n <span className={STOP_EVENT_CLASSNAME}>{i18n('save')}</span>\n </Button>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport const MermaidView: React.FC<{\n view: EditorView;\n onChange: (attrs: {[MermaidConsts.NodeAttrs.content]: string}) => void;\n getMermaidInstance: () => Mermaid;\n node: Node;\n getPos: () => number | undefined;\n options: MermaidOptions;\n}> = ({onChange, node, getPos, view, getMermaidInstance, options}) => {\n const enitityId: string = node.attrs[MermaidConsts.NodeAttrs.EntityId];\n const entityKey = useMemo(\n () => SharedStateKey.define<MermaidEntitySharedState>({name: enitityId}),\n [enitityId],\n );\n\n const [editing, setEditing, unsetEditing] = useSharedEditingState(view, entityKey);\n const [menuOpen, , closeMenu, toggleMenuOpen] = useBooleanState(false);\n const [anchorElement, setAnchorElement] = useElementState();\n\n const [mermaidInstance, setMermaidInstance] = useState<Mermaid | null>(null);\n useEffect(() => {\n const waitForMermaid = () =>\n setTimeout(() => {\n const instance = getMermaidInstance();\n if (instance) {\n setMermaidInstance(instance);\n\n return;\n }\n\n waitForMermaid();\n }, 100);\n\n waitForMermaid();\n }, []);\n\n if (editing) {\n return (\n <DiagramEditMode\n initialText={node.attrs[MermaidConsts.NodeAttrs.content]}\n mermaidInstance={mermaidInstance}\n onCancel={unsetEditing}\n onSave={(v) => {\n onChange({[MermaidConsts.NodeAttrs.content]: v});\n }}\n options={options}\n />\n );\n }\n\n return (\n <div className={b()} onDoubleClick={setEditing}>\n <MermaidPreview\n mermaidInstance={mermaidInstance}\n text={node.attrs[MermaidConsts.NodeAttrs.content]}\n />\n <div>\n <Button\n onClick={toggleMenuOpen}\n ref={setAnchorElement}\n size={'s'}\n className={STOP_EVENT_CLASSNAME}\n >\n <Icon data={DotsIcon} className={STOP_EVENT_CLASSNAME} />\n </Button>\n <Popup\n open={menuOpen}\n anchorElement={anchorElement}\n onOpenChange={closeMenu}\n placement=\"bottom-end\"\n >\n <Menu>\n <Menu.Item\n onClick={() => {\n setEditing();\n closeMenu();\n }}\n >\n {i18n('edit')}\n </Menu.Item>\n <Menu.Item\n onClick={() => {\n const pos = getPos();\n if (pos === undefined) return;\n removeNode({\n node,\n pos,\n tr: view.state.tr,\n dispatch: view.dispatch,\n });\n }}\n >\n {i18n('remove')}\n </Menu.Item>\n </Menu>\n </Popup>\n </div>\n </div>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"file":"MermaidView.js","sourceRoot":"../../../../../../src","sources":["extensions/additional/Mermaid/MermaidNodeView/MermaidView.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useEffect, useMemo, useState} from 'react';\n\nimport {Ellipsis as DotsIcon} from '@gravity-ui/icons';\nimport {Button, Icon, Loader, Menu, Popup, useThemeType} from '@gravity-ui/uikit';\nimport type {Mermaid} from 'mermaid' with {'resolution-mode': 'import'};\nimport type {Node} from 'prosemirror-model';\nimport type {EditorView} from 'prosemirror-view';\n\nimport {SharedStateKey} from 'src/extensions/behavior/SharedState';\nimport {useSharedEditingState} from 'src/react-utils/useSharedEditingState';\n\nimport {cn} from '../../../../classname';\nimport {TextAreaFixed as TextArea} from '../../../../forms/TextInput';\nimport {i18n} from '../../../../i18n/common';\nimport {useAutoSave, useBooleanState, useElementState} from '../../../../react-utils';\nimport {removeNode} from '../../../../utils';\nimport {MermaidConsts} from '../MermaidSpecs/const';\nimport type {MermaidOptions} from '../index';\nimport type {MermaidEntitySharedState} from '../types';\n\nexport const cnMermaid = cn('Mermaid');\n\nexport const STOP_EVENT_CLASSNAME = 'prosemirror-stop-event';\n\nimport './Mermaid.scss';\n\nconst b = cnMermaid;\n\nconst MermaidPreview: React.FC<{mermaidInstance: Mermaid | null; text: string}> = ({\n mermaidInstance,\n text = '',\n}) => {\n const [svg, setSvg] = useState<string>();\n const [error, setError] = useState<string | null>(null);\n\n const theme = useThemeType();\n\n useEffect(() => {\n const p = async () => {\n if (mermaidInstance) {\n try {\n // Validates syntax and throws error if text is invalid\n await mermaidInstance.parse(text);\n\n mermaidInstance.initialize({theme: theme === 'dark' ? 'dark' : 'forest'});\n\n const {svg: S} = await mermaidInstance.render(`mermaid-${Date.now()}`, text);\n\n setSvg(S);\n setError(null);\n } catch (e) {\n setError((e as Error).message);\n }\n }\n };\n\n p();\n }, [mermaidInstance, text, theme]);\n\n if (error) {\n return <div className={b('Error')}>{error && <div>{error}</div>}</div>;\n }\n\n return (\n <div className={b('Preview')}>\n {svg ? <div className=\"mermaid\" dangerouslySetInnerHTML={{__html: svg}} /> : <Loader />}\n </div>\n );\n};\n\nconst DiagramEditMode: React.FC<{\n initialText: string;\n mermaidInstance: Mermaid | null;\n onSave: (v: string) => void;\n onCancel: () => void;\n options: MermaidOptions;\n}> = ({initialText, onSave, onCancel, mermaidInstance, options: {autoSave}}) => {\n const {value, handleChange, handleManualSave, isSaveDisabled, isAutoSaveEnabled} = useAutoSave({\n initialValue: initialText || '',\n onSave,\n onClose: onCancel,\n autoSave,\n });\n\n return (\n <div className={b()}>\n <MermaidPreview mermaidInstance={mermaidInstance} text={value} />\n <div className={b('Editor')}>\n <div>\n <TextArea\n controlProps={{\n className: STOP_EVENT_CLASSNAME,\n }}\n value={value}\n onUpdate={handleChange}\n autoFocus\n />\n </div>\n <div className={b('Controls')}>\n <div>\n <Button onClick={onCancel} view={'flat'}>\n <span className={STOP_EVENT_CLASSNAME}>\n {isAutoSaveEnabled ? i18n('close') : i18n('cancel')}\n </span>\n </Button>\n {!isAutoSaveEnabled && (\n <Button\n onClick={handleManualSave}\n view={'action'}\n disabled={isSaveDisabled}\n >\n <span className={STOP_EVENT_CLASSNAME}>{i18n('save')}</span>\n </Button>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport const MermaidView: React.FC<{\n view: EditorView;\n onChange: (attrs: {[MermaidConsts.NodeAttrs.content]: string}) => void;\n getMermaidInstance: () => Mermaid;\n node: Node;\n getPos: () => number | undefined;\n options: MermaidOptions;\n}> = ({onChange, node, getPos, view, getMermaidInstance, options}) => {\n const enitityId: string = node.attrs[MermaidConsts.NodeAttrs.EntityId];\n const entityKey = useMemo(\n () => SharedStateKey.define<MermaidEntitySharedState>({name: enitityId}),\n [enitityId],\n );\n\n const [editing, setEditing, unsetEditing] = useSharedEditingState(view, entityKey);\n const [menuOpen, , closeMenu, toggleMenuOpen] = useBooleanState(false);\n const [anchorElement, setAnchorElement] = useElementState();\n\n const [mermaidInstance, setMermaidInstance] = useState<Mermaid | null>(null);\n useEffect(() => {\n const waitForMermaid = () =>\n setTimeout(() => {\n const instance = getMermaidInstance();\n if (instance) {\n setMermaidInstance(instance);\n\n return;\n }\n\n waitForMermaid();\n }, 100);\n\n waitForMermaid();\n }, []);\n\n if (editing) {\n return (\n <DiagramEditMode\n initialText={node.attrs[MermaidConsts.NodeAttrs.content]}\n mermaidInstance={mermaidInstance}\n onCancel={unsetEditing}\n onSave={(v) => {\n onChange({[MermaidConsts.NodeAttrs.content]: v});\n }}\n options={options}\n />\n );\n }\n\n return (\n <div className={b()} onDoubleClick={setEditing}>\n <MermaidPreview\n mermaidInstance={mermaidInstance}\n text={node.attrs[MermaidConsts.NodeAttrs.content]}\n />\n <div>\n <Button\n onClick={toggleMenuOpen}\n ref={setAnchorElement}\n size={'s'}\n className={STOP_EVENT_CLASSNAME}\n >\n <Icon data={DotsIcon} className={STOP_EVENT_CLASSNAME} />\n </Button>\n <Popup\n open={menuOpen}\n anchorElement={anchorElement}\n onOpenChange={closeMenu}\n placement=\"bottom-end\"\n >\n <Menu>\n <Menu.Item\n onClick={() => {\n setEditing();\n closeMenu();\n }}\n >\n {i18n('edit')}\n </Menu.Item>\n <Menu.Item\n onClick={() => {\n const pos = getPos();\n if (pos === undefined) return;\n removeNode({\n node,\n pos,\n tr: view.state.tr,\n dispatch: view.dispatch,\n });\n }}\n >\n {i18n('remove')}\n </Menu.Item>\n </Menu>\n </Popup>\n </div>\n </div>\n );\n};\n"]}
|
|
@@ -7,7 +7,6 @@ const prosemirror_utils_1 = require("prosemirror-utils");
|
|
|
7
7
|
const prosemirror_view_1 = require("prosemirror-view");
|
|
8
8
|
const classname_1 = require("../../../classname.js");
|
|
9
9
|
const lodash_1 = require("../../../lodash.js");
|
|
10
|
-
const nodes_1 = require("../../../utils/nodes.js");
|
|
11
10
|
const placeholder_1 = require("../../../utils/placeholder.js");
|
|
12
11
|
const selection_1 = require("../../../utils/selection.js");
|
|
13
12
|
require("./index.css");
|
|
@@ -40,10 +39,32 @@ const createPlaceholder = (node, parent, focus) => {
|
|
|
40
39
|
};
|
|
41
40
|
exports.createPlaceholder = createPlaceholder;
|
|
42
41
|
const placeholderNeeded = (node) => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
// Combine all checks in a single descendants pass
|
|
43
|
+
let hasAlwaysVisiblePlaceholder = false;
|
|
44
|
+
let hasNonEmptyContent = false;
|
|
45
|
+
node.descendants((n) => {
|
|
46
|
+
// Check for alwaysVisible placeholder
|
|
47
|
+
if (n.type.spec.placeholder?.alwaysVisible) {
|
|
48
|
+
hasAlwaysVisiblePlaceholder = true;
|
|
49
|
+
return false; // Stop traversal early
|
|
50
|
+
}
|
|
51
|
+
// Check if node has non-empty content (same logic as isNodeEmpty)
|
|
52
|
+
if (n.isAtom) {
|
|
53
|
+
hasNonEmptyContent = true;
|
|
54
|
+
return false; // Stop traversal early
|
|
55
|
+
}
|
|
56
|
+
if (n.isText && n.textContent) {
|
|
57
|
+
hasNonEmptyContent = true;
|
|
58
|
+
return false; // Stop traversal early
|
|
59
|
+
}
|
|
60
|
+
// Non-empty paragraph or other block with content
|
|
61
|
+
if (n.content.size > 0 && n.type.name !== 'paragraph') {
|
|
62
|
+
hasNonEmptyContent = true;
|
|
63
|
+
return false; // Stop traversal early
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
});
|
|
67
|
+
return !hasNonEmptyContent && !hasAlwaysVisiblePlaceholder;
|
|
47
68
|
};
|
|
48
69
|
const addDecoration = (widgetsMap, node, pos, parent, cursorPos, globalState) => {
|
|
49
70
|
const placeholderSpec = node.type.spec.placeholder;
|
|
@@ -92,19 +113,19 @@ const Placeholder = (builder, opts) => {
|
|
|
92
113
|
}), builder.Priority.VeryHigh);
|
|
93
114
|
};
|
|
94
115
|
exports.Placeholder = Placeholder;
|
|
95
|
-
function getPlaceholderWidgetSpecs(state) {
|
|
116
|
+
function getPlaceholderWidgetSpecs(state, pluginKeys) {
|
|
96
117
|
const globalState = { hasFocus: false };
|
|
97
118
|
const widgetsMap = {};
|
|
98
119
|
const { selection } = state;
|
|
99
120
|
const cursorPos = (0, selection_1.isTextSelection)(selection) ? selection.$cursor?.pos : null;
|
|
100
|
-
|
|
121
|
+
pluginKeys.forEach((f) => {
|
|
101
122
|
// We use find because it can be used to iterate over the DecorationSet.
|
|
102
123
|
f.getState(state)?.find(undefined, undefined, (spec) => {
|
|
103
124
|
widgetsMap[spec.pos] = f;
|
|
104
125
|
return false;
|
|
105
126
|
});
|
|
106
127
|
});
|
|
107
|
-
//
|
|
128
|
+
// Draw placeholder for all nodes where placeholder is alwaysVisible
|
|
108
129
|
const decorate = (node, pos, parent) => {
|
|
109
130
|
const placeholderSpec = node.type.spec.placeholder;
|
|
110
131
|
if (placeholderSpec && placeholderSpec.alwaysVisible && placeholderNeeded(node)) {
|
|
@@ -129,23 +150,36 @@ function getPlaceholderWidgetSpecs(state) {
|
|
|
129
150
|
return { widgetSpecs, hasFocus: globalState.hasFocus };
|
|
130
151
|
}
|
|
131
152
|
function initState(state) {
|
|
132
|
-
const
|
|
153
|
+
const pluginKeys = getPlaceholderPluginKeys(state.schema);
|
|
154
|
+
const { widgetSpecs, hasFocus } = getPlaceholderWidgetSpecs(state, pluginKeys);
|
|
133
155
|
const decorationSet = prosemirror_view_1.DecorationSet.create(state.doc, widgetSpecs.map((widget) => prosemirror_view_1.Decoration.widget(widget.pos, widget.toDOM, widget.spec)));
|
|
134
|
-
return { decorationSet, hasFocus };
|
|
156
|
+
return { decorationSet, hasFocus, pluginKeys };
|
|
135
157
|
}
|
|
136
|
-
function applyState(tr, oldPluginState,
|
|
137
|
-
|
|
158
|
+
function applyState(tr, oldPluginState, oldState, newState) {
|
|
159
|
+
// Early return if document hasn't changed and selection hasn't changed
|
|
160
|
+
// This avoids unnecessary recalculation of decorations
|
|
161
|
+
if (!tr.docChanged && !tr.selectionSet) {
|
|
162
|
+
return oldPluginState;
|
|
163
|
+
}
|
|
164
|
+
// Reuse cached plugin keys if schema hasn't changed
|
|
165
|
+
const pluginKeys = oldState.schema === newState.schema
|
|
166
|
+
? oldPluginState.pluginKeys
|
|
167
|
+
: getPlaceholderPluginKeys(newState.schema);
|
|
168
|
+
const { widgetSpecs, hasFocus } = getPlaceholderWidgetSpecs(newState, pluginKeys);
|
|
138
169
|
const { decorationSet } = oldPluginState;
|
|
139
170
|
const oldMappedSet = decorationSet.map(tr.mapping, tr.doc);
|
|
140
171
|
// Find all decorations that are present in old and new set
|
|
141
|
-
const
|
|
172
|
+
const unchangedPositions = new Set();
|
|
173
|
+
const decorationsThatDidNotChange = [];
|
|
174
|
+
widgetSpecs.forEach(({ pos, spec }) => {
|
|
142
175
|
const deco = oldMappedSet.find(pos, pos);
|
|
143
|
-
if (deco.length && (0, lodash_1.isEqual)(deco[0].spec, spec))
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
176
|
+
if (deco.length && (0, lodash_1.isEqual)(deco[0].spec, spec)) {
|
|
177
|
+
unchangedPositions.add(pos);
|
|
178
|
+
decorationsThatDidNotChange.push(...deco);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
// Those are decorations that are present only in new set
|
|
182
|
+
const newAddedDecorations = widgetSpecs.filter(({ pos }) => !unchangedPositions.has(pos));
|
|
149
183
|
// That is a set with decorations that are present in old set and absent in new set
|
|
150
184
|
const notRelevantDecorations = oldMappedSet.remove(decorationsThatDidNotChange);
|
|
151
185
|
let newSet = oldMappedSet;
|
|
@@ -155,6 +189,6 @@ function applyState(tr, oldPluginState, _oldState, newState) {
|
|
|
155
189
|
// Add new decorations
|
|
156
190
|
if (newAddedDecorations.length)
|
|
157
191
|
newSet = newSet.add(tr.doc, newAddedDecorations.map((widget) => prosemirror_view_1.Decoration.widget(widget.pos, widget.toDOM, widget.spec)));
|
|
158
|
-
return { decorationSet: newSet, hasFocus };
|
|
192
|
+
return { decorationSet: newSet, hasFocus, pluginKeys };
|
|
159
193
|
}
|
|
160
194
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/behavior/Placeholder/index.ts"],"names":[],"mappings":";;;AACA,yDAAwF;AACxF,oCAAoC;AACpC,yDAA2E;AAC3E,uDAA2D;AAE3D,qDAAsC;AAEtC,+CAAwC;AACxC,mDAAiD;AACjD,+DAA0F;AAC1F,2DAAyD;AAEzD,uBAAsB;AAEtB,MAAM,wBAAwB,GAAG,CAAC,MAAc,EAAE,EAAE;IAChD,MAAM,UAAU,GAAG,EAAE,CAAC;IACtB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;YACrC,IAAI,IAAI,CAAC,WAAW,EAAE,YAAY,EAAE,CAAC;gBACjC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;YACnD,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO,UAAU,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,CAAC,GAAG,IAAA,cAAE,EAAC,aAAa,CAAC,CAAC;AAErB,MAAM,iBAAiB,GAAG,CAAC,IAAU,EAAE,MAAmB,EAAE,KAAe,EAAE,EAAE;IAClF,MAAM,OAAO,GAAG,IAAA,mCAAqB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,MAAM,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAClD,WAAW,CAAC,SAAS,GAAG,CAAC,CAAC,EAAC,KAAK,EAAC,CAAC,CAAC;IAEnC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACzD,iBAAiB,CAAC,SAAS,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IAE1C,MAAM,eAAe,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACvD,eAAe,CAAC,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,WAAW,GAAG,OAAO,CAAC;IAEtC,WAAW,CAAC,MAAM,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC;IAEvD,OAAO,WAAW,CAAC;AACvB,CAAC,CAAC;AAjBW,QAAA,iBAAiB,qBAiB5B;AAEF,MAAM,iBAAiB,GAAG,CAAC,IAAU,EAAE,EAAE;IACrC,MAAM,8BAA8B,GAAG,IAAA,gCAAY,EAAC,IAAI,EAAE,CAAC,CAAO,EAAE,EAAE,CAClE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAClD,CAAC;IAEF,OAAO,CACH,IAAA,mBAAW,EAAC,IAAI,CAAC;QACjB,8EAA8E;QAC9E,CAAC,8BAA8B,CAAC,MAAM,CACzC,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAClB,UAAsB,EACtB,IAAU,EACV,GAAW,EACX,MAAmB,EACnB,SAAoC,EACpC,WAA6B,EAC/B,EAAE;IACA,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;IACnD,MAAM,kBAAkB,GAAG,GAAG,GAAG,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;IAErD,8EAA8E;IAC9E,IAAI,CAAC,eAAe,IAAI,UAAU,CAAC,kBAAkB,CAAC;QAAE,OAAO;IAE/D,IAAI,eAAe,CAAC,YAAY,EAAE,CAAC;QAC/B,UAAU,CAAC,kBAAkB,CAAC,GAAG,eAAe,CAAC,YAAY,CAAC;QAC9D,OAAO;IACX,CAAC;IAED,MAAM,KAAK,GAAG,kBAAkB,KAAK,SAAS,CAAC;IAE/C,MAAM,cAAc,GAAG,IAAA,yBAAiB,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9D,IAAI,CAAC,cAAc;QAAE,OAAO;IAE5B,IAAI,KAAK;QAAE,WAAW,CAAC,QAAQ,GAAG,IAAI,CAAC;IAEvC,UAAU,CAAC,kBAAkB,CAAC,GAAG;QAC7B,GAAG,EAAE,kBAAkB;QACvB,KAAK,EAAE,cAAc;QACrB,IAAI,EAAE,EAAC,KAAK,EAAC;KAChB,CAAC;AACN,CAAC,CAAC;AAeF,MAAM,SAAS,GAAG,IAAI,6BAAS,CAAyB,oBAAoB,CAAC,CAAC;AAEvE,MAAM,WAAW,GAAsC,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;IAC5E,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IACzC,OAAO,CAAC,SAAS,CACb,GAAG,EAAE,CACD,IAAI,0BAAM,CAAyB;QAC/B,GAAG,EAAE,SAAS;QACd,KAAK,EAAE;YACH,UAAU,CAAC,KAAK;gBACZ,MAAM,KAAK,GAA2B,EAAE,CAAC;gBACzC,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAE,CAAC,QAAQ,EAAE,CAAC;oBACtC,qBAAqB;oBACrB,KAAK,CAAC,KAAK,GAAG,wBAAwB,CAAC;gBAC3C,CAAC;gBACD,OAAO,KAAK,CAAC;YACjB,CAAC;YACD,WAAW,CAAC,KAAK;gBACb,OAAO,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;YACpD,CAAC;SACJ;QACD,KAAK,EAAE;YACH,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC;YAC1C,KAAK,EAAE,UAAU;SACpB;KACJ,CAAC,EACN,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAC5B,CAAC;AACN,CAAC,CAAC;AA1BW,QAAA,WAAW,eA0BtB;AAEF,SAAS,yBAAyB,CAAC,KAAkB;IACjD,MAAM,WAAW,GAAqB,EAAC,QAAQ,EAAE,KAAK,EAAC,CAAC;IACxD,MAAM,UAAU,GAAe,EAAE,CAAC;IAClC,MAAM,EAAC,SAAS,EAAC,GAAG,KAAK,CAAC;IAC1B,MAAM,SAAS,GAAG,IAAA,2BAAe,EAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IAE7E,wBAAwB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QACjD,wEAAwE;QACxE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;YACnD,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACzB,OAAO,KAAK,CAAC;QACjB,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,oEAAoE;IACpE,MAAM,QAAQ,GAAG,CAAC,IAAU,EAAE,GAAW,EAAE,MAAmB,EAAE,EAAE;QAC9D,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;QAEnD,IAAI,eAAe,IAAI,eAAe,CAAC,aAAa,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9E,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;QACzE,CAAC;IACL,CAAC,CAAC;IAEF,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAEhC,MAAM,UAAU,GAAG,IAAA,8CAA0B,EAAC,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,IAAU,EAAE,EAAE;QAChF,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;IAE/D,iEAAiE;IACjE,IACI,UAAU;QACV,iBAAiB,CAAC,UAAU,CAAC,IAAI,CAAC;QAClC,eAAe;QACf,CAAC,eAAe,CAAC,aAAa,EAChC,CAAC;QACC,MAAM,EAAC,IAAI,EAAE,GAAG,EAAE,KAAK,EAAC,GAAG,UAAU,CAAC;QACtC,MAAM,MAAM,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACxE,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAChD,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,YAAY,6BAAS,CAAC,CACrC,CAAC;IAElB,OAAO,EAAC,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,QAAQ,EAAC,CAAC;AACzD,CAAC;AAED,SAAS,SAAS,CAAC,KAAkB;IACjC,MAAM,EAAC,WAAW,EAAE,QAAQ,EAAC,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;IACjE,MAAM,aAAa,GAAG,gCAAa,CAAC,MAAM,CACtC,KAAK,CAAC,GAAG,EACT,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,6BAAU,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CACxF,CAAC;IAEF,OAAO,EAAC,aAAa,EAAE,QAAQ,EAAC,CAAC;AACrC,CAAC;AAED,SAAS,UAAU,CACf,EAAe,EACf,cAAsC,EACtC,SAAsB,EACtB,QAAqB;IAErB,MAAM,EAAC,WAAW,EAAE,QAAQ,EAAC,GAAG,yBAAyB,CAAC,QAAQ,CAAC,CAAC;IACpE,MAAM,EAAC,aAAa,EAAC,GAAG,cAAc,CAAC;IACvC,MAAM,YAAY,GAAG,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;IAE3D,2DAA2D;IAC3D,MAAM,2BAA2B,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAe,EAAE,EAAC,GAAG,EAAE,IAAI,EAAC,EAAE,EAAE;QACpF,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACzC,IAAI,IAAI,CAAC,MAAM,IAAI,IAAA,gBAAO,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC;YAAE,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QAChE,OAAO,CAAC,CAAC;IACb,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,yDAAyD;IACzD,MAAM,mBAAmB,GAAG,WAAW,CAAC,MAAM,CAC1C,CAAC,EAAC,GAAG,EAAC,EAAE,EAAE,CAAC,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC,EAAC,IAAI,EAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAC9E,CAAC;IAEF,mFAAmF;IACnF,MAAM,sBAAsB,GAAG,YAAY,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC;IAChF,IAAI,MAAM,GAAG,YAAY,CAAC;IAC1B,qDAAqD;IACrD,IAAI,sBAAsB,CAAC,IAAI,EAAE,CAAC,MAAM;QAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,IAAI,EAAE,CAAC,CAAC;IAChG,sBAAsB;IACtB,IAAI,mBAAmB,CAAC,MAAM;QAC1B,MAAM,GAAG,MAAM,CAAC,GAAG,CACf,EAAE,CAAC,GAAG,EACN,mBAAmB,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAC/B,6BAAU,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAC3D,CACJ,CAAC;IAEN,OAAO,EAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAC,CAAC;AAC7C,CAAC","sourcesContent":["import type {Node, Schema} from 'prosemirror-model';\nimport {type EditorState, Plugin, PluginKey, type Transaction} from 'prosemirror-state';\n// @ts-ignore // TODO: fix cjs build\nimport {findChildren, findParentNodeClosestToPos} from 'prosemirror-utils';\nimport {Decoration, DecorationSet} from 'prosemirror-view';\n\nimport {cn} from '../../../classname';\nimport type {ExtensionAuto} from '../../../core';\nimport {isEqual} from '../../../lodash';\nimport {isNodeEmpty} from '../../../utils/nodes';\nimport {type PlaceholderOptions, getPlaceholderContent} from '../../../utils/placeholder';\nimport {isTextSelection} from '../../../utils/selection';\n\nimport './index.scss';\n\nconst getPlaceholderPluginKeys = (schema: Schema) => {\n const pluginKeys = [];\n for (const node in schema.nodes) {\n if (schema.nodes[node]) {\n const spec = schema.nodes[node].spec;\n if (spec.placeholder?.customPlugin) {\n pluginKeys.push(spec.placeholder.customPlugin);\n }\n }\n }\n\n return pluginKeys;\n};\n\nconst b = cn('placeholder');\n\nexport const createPlaceholder = (node: Node, parent: Node | null, focus?: boolean) => {\n const content = getPlaceholderContent(node, parent);\n if (!content) return null;\n\n const placeholder = document.createElement('div');\n placeholder.className = b({focus});\n\n const placeholderCursor = document.createElement('span');\n placeholderCursor.className = b('cursor');\n\n const placeholderText = document.createElement('span');\n placeholderText.className = b('text');\n placeholderText.textContent = content;\n\n placeholder.append(placeholderCursor, placeholderText);\n\n return placeholder;\n};\n\nconst placeholderNeeded = (node: Node) => {\n const childrenWithPlaceholderVisible = findChildren(node, (n: Node) =>\n Boolean(n.type.spec.placeholder?.alwaysVisible),\n );\n\n return (\n isNodeEmpty(node) &&\n // If there are child nodes with constant placeholder - give them the priority\n !childrenWithPlaceholderVisible.length\n );\n};\n\nconst addDecoration = (\n widgetsMap: WidgetsMap,\n node: Node,\n pos: number,\n parent: Node | null,\n cursorPos: number | null | undefined,\n globalState: ApplyGlobalState,\n) => {\n const placeholderSpec = node.type.spec.placeholder;\n const decorationPosition = pos + node.childCount + 1;\n\n // We do not add decoration if there is already a placeholder at this position\n if (!placeholderSpec || widgetsMap[decorationPosition]) return;\n\n if (placeholderSpec.customPlugin) {\n widgetsMap[decorationPosition] = placeholderSpec.customPlugin;\n return;\n }\n\n const focus = decorationPosition === cursorPos;\n\n const placeholderDOM = createPlaceholder(node, parent, focus);\n if (!placeholderDOM) return;\n\n if (focus) globalState.hasFocus = true;\n\n widgetsMap[decorationPosition] = {\n pos: decorationPosition,\n toDOM: placeholderDOM,\n spec: {focus},\n };\n};\n\ntype ApplyGlobalState = {hasFocus: boolean};\n\ntype DecoWidgetParameters = Parameters<typeof Decoration.widget>;\ntype WidgetSpec = {\n pos: DecoWidgetParameters[0];\n toDOM: DecoWidgetParameters[1];\n spec?: DecoWidgetParameters[2];\n};\n\ntype PlaceholderPluginState = {decorationSet: DecorationSet; hasFocus: boolean};\n\ntype WidgetsMap = Record<number, WidgetSpec | PluginKey>;\n\nconst pluginKey = new PluginKey<PlaceholderPluginState>('placeholder_plugin');\n\nexport const Placeholder: ExtensionAuto<PlaceholderOptions> = (builder, opts) => {\n builder.context.set('placeholder', opts);\n builder.addPlugin(\n () =>\n new Plugin<PlaceholderPluginState>({\n key: pluginKey,\n props: {\n attributes(state) {\n const attrs: Record<string, string> = {};\n if (pluginKey.getState(state)!.hasFocus) {\n // hide native cursor\n attrs.class = 'g-md-editor-hidecursor';\n }\n return attrs;\n },\n decorations(state) {\n return pluginKey.getState(state)?.decorationSet;\n },\n },\n state: {\n init: (_config, state) => initState(state),\n apply: applyState,\n },\n }),\n builder.Priority.VeryHigh,\n );\n};\n\nfunction getPlaceholderWidgetSpecs(state: EditorState) {\n const globalState: ApplyGlobalState = {hasFocus: false};\n const widgetsMap: WidgetsMap = {};\n const {selection} = state;\n const cursorPos = isTextSelection(selection) ? selection.$cursor?.pos : null;\n\n getPlaceholderPluginKeys(state.schema).forEach((f) => {\n // We use find because it can be used to iterate over the DecorationSet.\n f.getState(state)?.find(undefined, undefined, (spec) => {\n widgetsMap[spec.pos] = f;\n return false;\n });\n });\n\n // Fraw placeholder for all nodes where placeholder is alwaysVisible\n const decorate = (node: Node, pos: number, parent: Node | null) => {\n const placeholderSpec = node.type.spec.placeholder;\n\n if (placeholderSpec && placeholderSpec.alwaysVisible && placeholderNeeded(node)) {\n addDecoration(widgetsMap, node, pos, parent, cursorPos, globalState);\n }\n };\n\n state.doc.descendants(decorate);\n\n const parentNode = findParentNodeClosestToPos(state.selection.$from, (node: Node) => {\n return Boolean(node.type.spec.placeholder);\n });\n\n const placeholderSpec = parentNode?.node.type.spec.placeholder;\n\n // Draw placeholder if it needs to be draw in the place of cursor\n if (\n parentNode &&\n placeholderNeeded(parentNode.node) &&\n placeholderSpec &&\n !placeholderSpec.alwaysVisible\n ) {\n const {node, pos, depth} = parentNode;\n const parent = depth > 0 ? state.selection.$from.node(depth - 1) : null;\n addDecoration(widgetsMap, node, pos, parent, cursorPos, globalState);\n }\n\n const widgetSpecs = Object.values(widgetsMap).filter(\n (decoration) => !(decoration instanceof PluginKey),\n ) as WidgetSpec[];\n\n return {widgetSpecs, hasFocus: globalState.hasFocus};\n}\n\nfunction initState(state: EditorState): PlaceholderPluginState {\n const {widgetSpecs, hasFocus} = getPlaceholderWidgetSpecs(state);\n const decorationSet = DecorationSet.create(\n state.doc,\n widgetSpecs.map((widget) => Decoration.widget(widget.pos, widget.toDOM, widget.spec)),\n );\n\n return {decorationSet, hasFocus};\n}\n\nfunction applyState(\n tr: Transaction,\n oldPluginState: PlaceholderPluginState,\n _oldState: EditorState,\n newState: EditorState,\n): PlaceholderPluginState {\n const {widgetSpecs, hasFocus} = getPlaceholderWidgetSpecs(newState);\n const {decorationSet} = oldPluginState;\n const oldMappedSet = decorationSet.map(tr.mapping, tr.doc);\n\n // Find all decorations that are present in old and new set\n const decorationsThatDidNotChange = widgetSpecs.reduce((a: Decoration[], {pos, spec}) => {\n const deco = oldMappedSet.find(pos, pos);\n if (deco.length && isEqual(deco[0].spec, spec)) a.push(...deco);\n return a;\n }, []);\n\n // Those are decorations that are presenr only in new set\n const newAddedDecorations = widgetSpecs.filter(\n ({pos}) => !decorationsThatDidNotChange.map(({from}) => from).includes(pos),\n );\n\n // That is a set with decorations that are present in old set and absent in new set\n const notRelevantDecorations = oldMappedSet.remove(decorationsThatDidNotChange);\n let newSet = oldMappedSet;\n // Remove decorations that are not present in new set\n if (notRelevantDecorations.find().length) newSet = newSet.remove(notRelevantDecorations.find());\n // Add new decorations\n if (newAddedDecorations.length)\n newSet = newSet.add(\n tr.doc,\n newAddedDecorations.map((widget) =>\n Decoration.widget(widget.pos, widget.toDOM, widget.spec),\n ),\n );\n\n return {decorationSet: newSet, hasFocus};\n}\n\ndeclare module 'prosemirror-model' {\n interface NodeSpec {\n placeholder?: {\n content: string | ((node: Node, parent?: Node | null) => string | null);\n customPlugin?: PluginKey<DecorationSet>;\n alwaysVisible?: boolean;\n };\n }\n}\n\ndeclare global {\n namespace WysiwygEditor {\n interface Context {\n placeholder: PlaceholderOptions;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/behavior/Placeholder/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type {Node, Schema} from 'prosemirror-model';\nimport {type EditorState, Plugin, PluginKey, type Transaction} from 'prosemirror-state';\n// @ts-ignore // TODO: fix cjs build\nimport {findParentNodeClosestToPos} from 'prosemirror-utils';\nimport {Decoration, DecorationSet} from 'prosemirror-view';\n\nimport {cn} from 'src/classname';\nimport type {ExtensionAuto} from 'src/core';\nimport {isEqual} from 'src/lodash';\nimport {type PlaceholderOptions, getPlaceholderContent} from 'src/utils/placeholder';\nimport {isTextSelection} from 'src/utils/selection';\n\nimport './index.scss';\n\nconst getPlaceholderPluginKeys = (schema: Schema) => {\n const pluginKeys = [];\n for (const node in schema.nodes) {\n if (schema.nodes[node]) {\n const spec = schema.nodes[node].spec;\n if (spec.placeholder?.customPlugin) {\n pluginKeys.push(spec.placeholder.customPlugin);\n }\n }\n }\n\n return pluginKeys;\n};\n\nconst b = cn('placeholder');\n\nexport const createPlaceholder = (node: Node, parent: Node | null, focus?: boolean) => {\n const content = getPlaceholderContent(node, parent);\n if (!content) return null;\n\n const placeholder = document.createElement('div');\n placeholder.className = b({focus});\n\n const placeholderCursor = document.createElement('span');\n placeholderCursor.className = b('cursor');\n\n const placeholderText = document.createElement('span');\n placeholderText.className = b('text');\n placeholderText.textContent = content;\n\n placeholder.append(placeholderCursor, placeholderText);\n\n return placeholder;\n};\n\nconst placeholderNeeded = (node: Node) => {\n // Combine all checks in a single descendants pass\n let hasAlwaysVisiblePlaceholder = false;\n let hasNonEmptyContent = false;\n\n node.descendants((n: Node) => {\n // Check for alwaysVisible placeholder\n if (n.type.spec.placeholder?.alwaysVisible) {\n hasAlwaysVisiblePlaceholder = true;\n return false; // Stop traversal early\n }\n\n // Check if node has non-empty content (same logic as isNodeEmpty)\n if (n.isAtom) {\n hasNonEmptyContent = true;\n return false; // Stop traversal early\n }\n\n if (n.isText && n.textContent) {\n hasNonEmptyContent = true;\n return false; // Stop traversal early\n }\n\n // Non-empty paragraph or other block with content\n if (n.content.size > 0 && n.type.name !== 'paragraph') {\n hasNonEmptyContent = true;\n return false; // Stop traversal early\n }\n\n return true;\n });\n\n return !hasNonEmptyContent && !hasAlwaysVisiblePlaceholder;\n};\n\nconst addDecoration = (\n widgetsMap: WidgetsMap,\n node: Node,\n pos: number,\n parent: Node | null,\n cursorPos: number | null | undefined,\n globalState: ApplyGlobalState,\n) => {\n const placeholderSpec = node.type.spec.placeholder;\n const decorationPosition = pos + node.childCount + 1;\n\n // We do not add decoration if there is already a placeholder at this position\n if (!placeholderSpec || widgetsMap[decorationPosition]) return;\n\n if (placeholderSpec.customPlugin) {\n widgetsMap[decorationPosition] = placeholderSpec.customPlugin;\n return;\n }\n\n const focus = decorationPosition === cursorPos;\n\n const placeholderDOM = createPlaceholder(node, parent, focus);\n if (!placeholderDOM) return;\n\n if (focus) globalState.hasFocus = true;\n\n widgetsMap[decorationPosition] = {\n pos: decorationPosition,\n toDOM: placeholderDOM,\n spec: {focus},\n };\n};\n\ntype ApplyGlobalState = {hasFocus: boolean};\n\ntype DecoWidgetParameters = Parameters<typeof Decoration.widget>;\ntype WidgetSpec = {\n pos: DecoWidgetParameters[0];\n toDOM: DecoWidgetParameters[1];\n spec?: DecoWidgetParameters[2];\n};\n\ntype PlaceholderPluginState = {\n decorationSet: DecorationSet;\n hasFocus: boolean;\n pluginKeys: PluginKey<DecorationSet>[];\n};\n\ntype WidgetsMap = Record<number, WidgetSpec | PluginKey>;\n\nconst pluginKey = new PluginKey<PlaceholderPluginState>('placeholder_plugin');\n\nexport const Placeholder: ExtensionAuto<PlaceholderOptions> = (builder, opts) => {\n builder.context.set('placeholder', opts);\n builder.addPlugin(\n () =>\n new Plugin<PlaceholderPluginState>({\n key: pluginKey,\n props: {\n attributes(state) {\n const attrs: Record<string, string> = {};\n if (pluginKey.getState(state)!.hasFocus) {\n // hide native cursor\n attrs.class = 'g-md-editor-hidecursor';\n }\n return attrs;\n },\n decorations(state) {\n return pluginKey.getState(state)?.decorationSet;\n },\n },\n state: {\n init: (_config, state) => initState(state),\n apply: applyState,\n },\n }),\n builder.Priority.VeryHigh,\n );\n};\n\nfunction getPlaceholderWidgetSpecs(state: EditorState, pluginKeys: PluginKey<DecorationSet>[]) {\n const globalState: ApplyGlobalState = {hasFocus: false};\n const widgetsMap: WidgetsMap = {};\n const {selection} = state;\n const cursorPos = isTextSelection(selection) ? selection.$cursor?.pos : null;\n\n pluginKeys.forEach((f) => {\n // We use find because it can be used to iterate over the DecorationSet.\n f.getState(state)?.find(undefined, undefined, (spec) => {\n widgetsMap[spec.pos] = f;\n return false;\n });\n });\n\n // Draw placeholder for all nodes where placeholder is alwaysVisible\n const decorate = (node: Node, pos: number, parent: Node | null) => {\n const placeholderSpec = node.type.spec.placeholder;\n\n if (placeholderSpec && placeholderSpec.alwaysVisible && placeholderNeeded(node)) {\n addDecoration(widgetsMap, node, pos, parent, cursorPos, globalState);\n }\n };\n\n state.doc.descendants(decorate);\n\n const parentNode = findParentNodeClosestToPos(state.selection.$from, (node: Node) => {\n return Boolean(node.type.spec.placeholder);\n });\n\n const placeholderSpec = parentNode?.node.type.spec.placeholder;\n\n // Draw placeholder if it needs to be draw in the place of cursor\n if (\n parentNode &&\n placeholderNeeded(parentNode.node) &&\n placeholderSpec &&\n !placeholderSpec.alwaysVisible\n ) {\n const {node, pos, depth} = parentNode;\n const parent = depth > 0 ? state.selection.$from.node(depth - 1) : null;\n addDecoration(widgetsMap, node, pos, parent, cursorPos, globalState);\n }\n\n const widgetSpecs = Object.values(widgetsMap).filter(\n (decoration) => !(decoration instanceof PluginKey),\n ) as WidgetSpec[];\n\n return {widgetSpecs, hasFocus: globalState.hasFocus};\n}\n\nfunction initState(state: EditorState): PlaceholderPluginState {\n const pluginKeys = getPlaceholderPluginKeys(state.schema);\n const {widgetSpecs, hasFocus} = getPlaceholderWidgetSpecs(state, pluginKeys);\n const decorationSet = DecorationSet.create(\n state.doc,\n widgetSpecs.map((widget) => Decoration.widget(widget.pos, widget.toDOM, widget.spec)),\n );\n\n return {decorationSet, hasFocus, pluginKeys};\n}\n\nfunction applyState(\n tr: Transaction,\n oldPluginState: PlaceholderPluginState,\n oldState: EditorState,\n newState: EditorState,\n): PlaceholderPluginState {\n // Early return if document hasn't changed and selection hasn't changed\n // This avoids unnecessary recalculation of decorations\n if (!tr.docChanged && !tr.selectionSet) {\n return oldPluginState;\n }\n\n // Reuse cached plugin keys if schema hasn't changed\n const pluginKeys =\n oldState.schema === newState.schema\n ? oldPluginState.pluginKeys\n : getPlaceholderPluginKeys(newState.schema);\n\n const {widgetSpecs, hasFocus} = getPlaceholderWidgetSpecs(newState, pluginKeys);\n const {decorationSet} = oldPluginState;\n const oldMappedSet = decorationSet.map(tr.mapping, tr.doc);\n\n // Find all decorations that are present in old and new set\n const unchangedPositions = new Set<number>();\n const decorationsThatDidNotChange: Decoration[] = [];\n\n widgetSpecs.forEach(({pos, spec}) => {\n const deco = oldMappedSet.find(pos, pos);\n if (deco.length && isEqual(deco[0].spec, spec)) {\n unchangedPositions.add(pos);\n decorationsThatDidNotChange.push(...deco);\n }\n });\n\n // Those are decorations that are present only in new set\n const newAddedDecorations = widgetSpecs.filter(({pos}) => !unchangedPositions.has(pos));\n\n // That is a set with decorations that are present in old set and absent in new set\n const notRelevantDecorations = oldMappedSet.remove(decorationsThatDidNotChange);\n let newSet = oldMappedSet;\n // Remove decorations that are not present in new set\n if (notRelevantDecorations.find().length) newSet = newSet.remove(notRelevantDecorations.find());\n // Add new decorations\n if (newAddedDecorations.length)\n newSet = newSet.add(\n tr.doc,\n newAddedDecorations.map((widget) =>\n Decoration.widget(widget.pos, widget.toDOM, widget.spec),\n ),\n );\n\n return {decorationSet: newSet, hasFocus, pluginKeys};\n}\n\ndeclare module 'prosemirror-model' {\n interface NodeSpec {\n placeholder?: {\n content: string | ((node: Node, parent?: Node | null) => string | null);\n customPlugin?: PluginKey<DecorationSet>;\n alwaysVisible?: boolean;\n };\n }\n}\n\ndeclare global {\n namespace WysiwygEditor {\n interface Context {\n placeholder: PlaceholderOptions;\n }\n }\n}\n"]}
|
package/build/cjs/version.js
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.VERSION = void 0;
|
|
4
4
|
/** During build process, the current version will be injected here */
|
|
5
|
-
exports.VERSION = typeof '15.34.
|
|
5
|
+
exports.VERSION = typeof '15.34.5' !== 'undefined' ? '15.34.5' : 'unknown';
|
|
6
6
|
//# sourceMappingURL=version.js.map
|
package/build/cjs/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"../../src","sources":["version.ts"],"names":[],"mappings":";;;AAAA,sEAAsE;AACzD,QAAA,OAAO,GAAG,OAAO,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC","sourcesContent":["/** During build process, the current version will be injected here */\nexport const VERSION = typeof '15.34.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"../../src","sources":["version.ts"],"names":[],"mappings":";;;AAAA,sEAAsE;AACzD,QAAA,OAAO,GAAG,OAAO,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC","sourcesContent":["/** During build process, the current version will be injected here */\nexport const VERSION = typeof '15.34.5' !== 'undefined' ? '15.34.5' : 'unknown';\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useMemo, useState } from 'react';
|
|
3
3
|
import { Ellipsis as DotsIcon } from '@gravity-ui/icons';
|
|
4
|
-
import { Button, Icon, Loader, Menu, Popup } from '@gravity-ui/uikit';
|
|
4
|
+
import { Button, Icon, Loader, Menu, Popup, useThemeType } from '@gravity-ui/uikit';
|
|
5
5
|
import { SharedStateKey } from "../../../behavior/SharedState/index.js";
|
|
6
6
|
import { useSharedEditingState } from "../../../../react-utils/useSharedEditingState.js";
|
|
7
7
|
import { cn } from "../../../../classname.js";
|
|
@@ -17,12 +17,14 @@ const b = cnMermaid;
|
|
|
17
17
|
const MermaidPreview = ({ mermaidInstance, text = '', }) => {
|
|
18
18
|
const [svg, setSvg] = useState();
|
|
19
19
|
const [error, setError] = useState(null);
|
|
20
|
+
const theme = useThemeType();
|
|
20
21
|
useEffect(() => {
|
|
21
22
|
const p = async () => {
|
|
22
23
|
if (mermaidInstance) {
|
|
23
24
|
try {
|
|
24
25
|
// Validates syntax and throws error if text is invalid
|
|
25
26
|
await mermaidInstance.parse(text);
|
|
27
|
+
mermaidInstance.initialize({ theme: theme === 'dark' ? 'dark' : 'forest' });
|
|
26
28
|
const { svg: S } = await mermaidInstance.render(`mermaid-${Date.now()}`, text);
|
|
27
29
|
setSvg(S);
|
|
28
30
|
setError(null);
|
|
@@ -33,7 +35,7 @@ const MermaidPreview = ({ mermaidInstance, text = '', }) => {
|
|
|
33
35
|
}
|
|
34
36
|
};
|
|
35
37
|
p();
|
|
36
|
-
}, [mermaidInstance, text]);
|
|
38
|
+
}, [mermaidInstance, text, theme]);
|
|
37
39
|
if (error) {
|
|
38
40
|
return _jsx("div", { className: b('Error'), children: error && _jsx("div", { children: error }) });
|
|
39
41
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MermaidView.js","sourceRoot":"../../../../../../src","sources":["extensions/additional/Mermaid/MermaidNodeView/MermaidView.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useEffect, useMemo, useState} from 'react';\n\nimport {Ellipsis as DotsIcon} from '@gravity-ui/icons';\nimport {Button, Icon, Loader, Menu, Popup} from '@gravity-ui/uikit';\nimport type {Mermaid} from 'mermaid' with {'resolution-mode': 'import'};\nimport type {Node} from 'prosemirror-model';\nimport type {EditorView} from 'prosemirror-view';\n\nimport {SharedStateKey} from 'src/extensions/behavior/SharedState';\nimport {useSharedEditingState} from 'src/react-utils/useSharedEditingState';\n\nimport {cn} from '../../../../classname';\nimport {TextAreaFixed as TextArea} from '../../../../forms/TextInput';\nimport {i18n} from '../../../../i18n/common';\nimport {useAutoSave, useBooleanState, useElementState} from '../../../../react-utils';\nimport {removeNode} from '../../../../utils';\nimport {MermaidConsts} from '../MermaidSpecs/const';\nimport type {MermaidOptions} from '../index';\nimport type {MermaidEntitySharedState} from '../types';\n\nexport const cnMermaid = cn('Mermaid');\n\nexport const STOP_EVENT_CLASSNAME = 'prosemirror-stop-event';\n\nimport './Mermaid.scss';\n\nconst b = cnMermaid;\n\nconst MermaidPreview: React.FC<{mermaidInstance: Mermaid | null; text: string}> = ({\n mermaidInstance,\n text = '',\n}) => {\n const [svg, setSvg] = useState<string>();\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const p = async () => {\n if (mermaidInstance) {\n try {\n // Validates syntax and throws error if text is invalid\n await mermaidInstance.parse(text);\n\n const {svg: S} = await mermaidInstance.render(`mermaid-${Date.now()}`, text);\n\n setSvg(S);\n setError(null);\n } catch (e) {\n setError((e as Error).message);\n }\n }\n };\n\n p();\n }, [mermaidInstance, text]);\n\n if (error) {\n return <div className={b('Error')}>{error && <div>{error}</div>}</div>;\n }\n\n return (\n <div className={b('Preview')}>\n {svg ? <div className=\"mermaid\" dangerouslySetInnerHTML={{__html: svg}} /> : <Loader />}\n </div>\n );\n};\n\nconst DiagramEditMode: React.FC<{\n initialText: string;\n mermaidInstance: Mermaid | null;\n onSave: (v: string) => void;\n onCancel: () => void;\n options: MermaidOptions;\n}> = ({initialText, onSave, onCancel, mermaidInstance, options: {autoSave}}) => {\n const {value, handleChange, handleManualSave, isSaveDisabled, isAutoSaveEnabled} = useAutoSave({\n initialValue: initialText || '',\n onSave,\n onClose: onCancel,\n autoSave,\n });\n\n return (\n <div className={b()}>\n <MermaidPreview mermaidInstance={mermaidInstance} text={value} />\n <div className={b('Editor')}>\n <div>\n <TextArea\n controlProps={{\n className: STOP_EVENT_CLASSNAME,\n }}\n value={value}\n onUpdate={handleChange}\n autoFocus\n />\n </div>\n <div className={b('Controls')}>\n <div>\n <Button onClick={onCancel} view={'flat'}>\n <span className={STOP_EVENT_CLASSNAME}>\n {isAutoSaveEnabled ? i18n('close') : i18n('cancel')}\n </span>\n </Button>\n {!isAutoSaveEnabled && (\n <Button\n onClick={handleManualSave}\n view={'action'}\n disabled={isSaveDisabled}\n >\n <span className={STOP_EVENT_CLASSNAME}>{i18n('save')}</span>\n </Button>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport const MermaidView: React.FC<{\n view: EditorView;\n onChange: (attrs: {[MermaidConsts.NodeAttrs.content]: string}) => void;\n getMermaidInstance: () => Mermaid;\n node: Node;\n getPos: () => number | undefined;\n options: MermaidOptions;\n}> = ({onChange, node, getPos, view, getMermaidInstance, options}) => {\n const enitityId: string = node.attrs[MermaidConsts.NodeAttrs.EntityId];\n const entityKey = useMemo(\n () => SharedStateKey.define<MermaidEntitySharedState>({name: enitityId}),\n [enitityId],\n );\n\n const [editing, setEditing, unsetEditing] = useSharedEditingState(view, entityKey);\n const [menuOpen, , closeMenu, toggleMenuOpen] = useBooleanState(false);\n const [anchorElement, setAnchorElement] = useElementState();\n\n const [mermaidInstance, setMermaidInstance] = useState<Mermaid | null>(null);\n useEffect(() => {\n const waitForMermaid = () =>\n setTimeout(() => {\n const instance = getMermaidInstance();\n if (instance) {\n setMermaidInstance(instance);\n\n return;\n }\n\n waitForMermaid();\n }, 100);\n\n waitForMermaid();\n }, []);\n\n if (editing) {\n return (\n <DiagramEditMode\n initialText={node.attrs[MermaidConsts.NodeAttrs.content]}\n mermaidInstance={mermaidInstance}\n onCancel={unsetEditing}\n onSave={(v) => {\n onChange({[MermaidConsts.NodeAttrs.content]: v});\n }}\n options={options}\n />\n );\n }\n\n return (\n <div className={b()} onDoubleClick={setEditing}>\n <MermaidPreview\n mermaidInstance={mermaidInstance}\n text={node.attrs[MermaidConsts.NodeAttrs.content]}\n />\n <div>\n <Button\n onClick={toggleMenuOpen}\n ref={setAnchorElement}\n size={'s'}\n className={STOP_EVENT_CLASSNAME}\n >\n <Icon data={DotsIcon} className={STOP_EVENT_CLASSNAME} />\n </Button>\n <Popup\n open={menuOpen}\n anchorElement={anchorElement}\n onOpenChange={closeMenu}\n placement=\"bottom-end\"\n >\n <Menu>\n <Menu.Item\n onClick={() => {\n setEditing();\n closeMenu();\n }}\n >\n {i18n('edit')}\n </Menu.Item>\n <Menu.Item\n onClick={() => {\n const pos = getPos();\n if (pos === undefined) return;\n removeNode({\n node,\n pos,\n tr: view.state.tr,\n dispatch: view.dispatch,\n });\n }}\n >\n {i18n('remove')}\n </Menu.Item>\n </Menu>\n </Popup>\n </div>\n </div>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"file":"MermaidView.js","sourceRoot":"../../../../../../src","sources":["extensions/additional/Mermaid/MermaidNodeView/MermaidView.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useEffect, useMemo, useState} from 'react';\n\nimport {Ellipsis as DotsIcon} from '@gravity-ui/icons';\nimport {Button, Icon, Loader, Menu, Popup, useThemeType} from '@gravity-ui/uikit';\nimport type {Mermaid} from 'mermaid' with {'resolution-mode': 'import'};\nimport type {Node} from 'prosemirror-model';\nimport type {EditorView} from 'prosemirror-view';\n\nimport {SharedStateKey} from 'src/extensions/behavior/SharedState';\nimport {useSharedEditingState} from 'src/react-utils/useSharedEditingState';\n\nimport {cn} from '../../../../classname';\nimport {TextAreaFixed as TextArea} from '../../../../forms/TextInput';\nimport {i18n} from '../../../../i18n/common';\nimport {useAutoSave, useBooleanState, useElementState} from '../../../../react-utils';\nimport {removeNode} from '../../../../utils';\nimport {MermaidConsts} from '../MermaidSpecs/const';\nimport type {MermaidOptions} from '../index';\nimport type {MermaidEntitySharedState} from '../types';\n\nexport const cnMermaid = cn('Mermaid');\n\nexport const STOP_EVENT_CLASSNAME = 'prosemirror-stop-event';\n\nimport './Mermaid.scss';\n\nconst b = cnMermaid;\n\nconst MermaidPreview: React.FC<{mermaidInstance: Mermaid | null; text: string}> = ({\n mermaidInstance,\n text = '',\n}) => {\n const [svg, setSvg] = useState<string>();\n const [error, setError] = useState<string | null>(null);\n\n const theme = useThemeType();\n\n useEffect(() => {\n const p = async () => {\n if (mermaidInstance) {\n try {\n // Validates syntax and throws error if text is invalid\n await mermaidInstance.parse(text);\n\n mermaidInstance.initialize({theme: theme === 'dark' ? 'dark' : 'forest'});\n\n const {svg: S} = await mermaidInstance.render(`mermaid-${Date.now()}`, text);\n\n setSvg(S);\n setError(null);\n } catch (e) {\n setError((e as Error).message);\n }\n }\n };\n\n p();\n }, [mermaidInstance, text, theme]);\n\n if (error) {\n return <div className={b('Error')}>{error && <div>{error}</div>}</div>;\n }\n\n return (\n <div className={b('Preview')}>\n {svg ? <div className=\"mermaid\" dangerouslySetInnerHTML={{__html: svg}} /> : <Loader />}\n </div>\n );\n};\n\nconst DiagramEditMode: React.FC<{\n initialText: string;\n mermaidInstance: Mermaid | null;\n onSave: (v: string) => void;\n onCancel: () => void;\n options: MermaidOptions;\n}> = ({initialText, onSave, onCancel, mermaidInstance, options: {autoSave}}) => {\n const {value, handleChange, handleManualSave, isSaveDisabled, isAutoSaveEnabled} = useAutoSave({\n initialValue: initialText || '',\n onSave,\n onClose: onCancel,\n autoSave,\n });\n\n return (\n <div className={b()}>\n <MermaidPreview mermaidInstance={mermaidInstance} text={value} />\n <div className={b('Editor')}>\n <div>\n <TextArea\n controlProps={{\n className: STOP_EVENT_CLASSNAME,\n }}\n value={value}\n onUpdate={handleChange}\n autoFocus\n />\n </div>\n <div className={b('Controls')}>\n <div>\n <Button onClick={onCancel} view={'flat'}>\n <span className={STOP_EVENT_CLASSNAME}>\n {isAutoSaveEnabled ? i18n('close') : i18n('cancel')}\n </span>\n </Button>\n {!isAutoSaveEnabled && (\n <Button\n onClick={handleManualSave}\n view={'action'}\n disabled={isSaveDisabled}\n >\n <span className={STOP_EVENT_CLASSNAME}>{i18n('save')}</span>\n </Button>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport const MermaidView: React.FC<{\n view: EditorView;\n onChange: (attrs: {[MermaidConsts.NodeAttrs.content]: string}) => void;\n getMermaidInstance: () => Mermaid;\n node: Node;\n getPos: () => number | undefined;\n options: MermaidOptions;\n}> = ({onChange, node, getPos, view, getMermaidInstance, options}) => {\n const enitityId: string = node.attrs[MermaidConsts.NodeAttrs.EntityId];\n const entityKey = useMemo(\n () => SharedStateKey.define<MermaidEntitySharedState>({name: enitityId}),\n [enitityId],\n );\n\n const [editing, setEditing, unsetEditing] = useSharedEditingState(view, entityKey);\n const [menuOpen, , closeMenu, toggleMenuOpen] = useBooleanState(false);\n const [anchorElement, setAnchorElement] = useElementState();\n\n const [mermaidInstance, setMermaidInstance] = useState<Mermaid | null>(null);\n useEffect(() => {\n const waitForMermaid = () =>\n setTimeout(() => {\n const instance = getMermaidInstance();\n if (instance) {\n setMermaidInstance(instance);\n\n return;\n }\n\n waitForMermaid();\n }, 100);\n\n waitForMermaid();\n }, []);\n\n if (editing) {\n return (\n <DiagramEditMode\n initialText={node.attrs[MermaidConsts.NodeAttrs.content]}\n mermaidInstance={mermaidInstance}\n onCancel={unsetEditing}\n onSave={(v) => {\n onChange({[MermaidConsts.NodeAttrs.content]: v});\n }}\n options={options}\n />\n );\n }\n\n return (\n <div className={b()} onDoubleClick={setEditing}>\n <MermaidPreview\n mermaidInstance={mermaidInstance}\n text={node.attrs[MermaidConsts.NodeAttrs.content]}\n />\n <div>\n <Button\n onClick={toggleMenuOpen}\n ref={setAnchorElement}\n size={'s'}\n className={STOP_EVENT_CLASSNAME}\n >\n <Icon data={DotsIcon} className={STOP_EVENT_CLASSNAME} />\n </Button>\n <Popup\n open={menuOpen}\n anchorElement={anchorElement}\n onOpenChange={closeMenu}\n placement=\"bottom-end\"\n >\n <Menu>\n <Menu.Item\n onClick={() => {\n setEditing();\n closeMenu();\n }}\n >\n {i18n('edit')}\n </Menu.Item>\n <Menu.Item\n onClick={() => {\n const pos = getPos();\n if (pos === undefined) return;\n removeNode({\n node,\n pos,\n tr: view.state.tr,\n dispatch: view.dispatch,\n });\n }}\n >\n {i18n('remove')}\n </Menu.Item>\n </Menu>\n </Popup>\n </div>\n </div>\n );\n};\n"]}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Plugin, PluginKey } from 'prosemirror-state';
|
|
2
2
|
// @ts-ignore // TODO: fix cjs build
|
|
3
|
-
import {
|
|
3
|
+
import { findParentNodeClosestToPos } from 'prosemirror-utils';
|
|
4
4
|
import { Decoration, DecorationSet } from 'prosemirror-view';
|
|
5
5
|
import { cn } from "../../../classname.js";
|
|
6
6
|
import { isEqual } from "../../../lodash.js";
|
|
7
|
-
import { isNodeEmpty } from "../../../utils/nodes.js";
|
|
8
7
|
import { getPlaceholderContent } from "../../../utils/placeholder.js";
|
|
9
8
|
import { isTextSelection } from "../../../utils/selection.js";
|
|
10
9
|
import "./index.css";
|
|
@@ -36,10 +35,32 @@ export const createPlaceholder = (node, parent, focus) => {
|
|
|
36
35
|
return placeholder;
|
|
37
36
|
};
|
|
38
37
|
const placeholderNeeded = (node) => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
// Combine all checks in a single descendants pass
|
|
39
|
+
let hasAlwaysVisiblePlaceholder = false;
|
|
40
|
+
let hasNonEmptyContent = false;
|
|
41
|
+
node.descendants((n) => {
|
|
42
|
+
// Check for alwaysVisible placeholder
|
|
43
|
+
if (n.type.spec.placeholder?.alwaysVisible) {
|
|
44
|
+
hasAlwaysVisiblePlaceholder = true;
|
|
45
|
+
return false; // Stop traversal early
|
|
46
|
+
}
|
|
47
|
+
// Check if node has non-empty content (same logic as isNodeEmpty)
|
|
48
|
+
if (n.isAtom) {
|
|
49
|
+
hasNonEmptyContent = true;
|
|
50
|
+
return false; // Stop traversal early
|
|
51
|
+
}
|
|
52
|
+
if (n.isText && n.textContent) {
|
|
53
|
+
hasNonEmptyContent = true;
|
|
54
|
+
return false; // Stop traversal early
|
|
55
|
+
}
|
|
56
|
+
// Non-empty paragraph or other block with content
|
|
57
|
+
if (n.content.size > 0 && n.type.name !== 'paragraph') {
|
|
58
|
+
hasNonEmptyContent = true;
|
|
59
|
+
return false; // Stop traversal early
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
});
|
|
63
|
+
return !hasNonEmptyContent && !hasAlwaysVisiblePlaceholder;
|
|
43
64
|
};
|
|
44
65
|
const addDecoration = (widgetsMap, node, pos, parent, cursorPos, globalState) => {
|
|
45
66
|
const placeholderSpec = node.type.spec.placeholder;
|
|
@@ -87,19 +108,19 @@ export const Placeholder = (builder, opts) => {
|
|
|
87
108
|
},
|
|
88
109
|
}), builder.Priority.VeryHigh);
|
|
89
110
|
};
|
|
90
|
-
function getPlaceholderWidgetSpecs(state) {
|
|
111
|
+
function getPlaceholderWidgetSpecs(state, pluginKeys) {
|
|
91
112
|
const globalState = { hasFocus: false };
|
|
92
113
|
const widgetsMap = {};
|
|
93
114
|
const { selection } = state;
|
|
94
115
|
const cursorPos = isTextSelection(selection) ? selection.$cursor?.pos : null;
|
|
95
|
-
|
|
116
|
+
pluginKeys.forEach((f) => {
|
|
96
117
|
// We use find because it can be used to iterate over the DecorationSet.
|
|
97
118
|
f.getState(state)?.find(undefined, undefined, (spec) => {
|
|
98
119
|
widgetsMap[spec.pos] = f;
|
|
99
120
|
return false;
|
|
100
121
|
});
|
|
101
122
|
});
|
|
102
|
-
//
|
|
123
|
+
// Draw placeholder for all nodes where placeholder is alwaysVisible
|
|
103
124
|
const decorate = (node, pos, parent) => {
|
|
104
125
|
const placeholderSpec = node.type.spec.placeholder;
|
|
105
126
|
if (placeholderSpec && placeholderSpec.alwaysVisible && placeholderNeeded(node)) {
|
|
@@ -124,23 +145,36 @@ function getPlaceholderWidgetSpecs(state) {
|
|
|
124
145
|
return { widgetSpecs, hasFocus: globalState.hasFocus };
|
|
125
146
|
}
|
|
126
147
|
function initState(state) {
|
|
127
|
-
const
|
|
148
|
+
const pluginKeys = getPlaceholderPluginKeys(state.schema);
|
|
149
|
+
const { widgetSpecs, hasFocus } = getPlaceholderWidgetSpecs(state, pluginKeys);
|
|
128
150
|
const decorationSet = DecorationSet.create(state.doc, widgetSpecs.map((widget) => Decoration.widget(widget.pos, widget.toDOM, widget.spec)));
|
|
129
|
-
return { decorationSet, hasFocus };
|
|
151
|
+
return { decorationSet, hasFocus, pluginKeys };
|
|
130
152
|
}
|
|
131
|
-
function applyState(tr, oldPluginState,
|
|
132
|
-
|
|
153
|
+
function applyState(tr, oldPluginState, oldState, newState) {
|
|
154
|
+
// Early return if document hasn't changed and selection hasn't changed
|
|
155
|
+
// This avoids unnecessary recalculation of decorations
|
|
156
|
+
if (!tr.docChanged && !tr.selectionSet) {
|
|
157
|
+
return oldPluginState;
|
|
158
|
+
}
|
|
159
|
+
// Reuse cached plugin keys if schema hasn't changed
|
|
160
|
+
const pluginKeys = oldState.schema === newState.schema
|
|
161
|
+
? oldPluginState.pluginKeys
|
|
162
|
+
: getPlaceholderPluginKeys(newState.schema);
|
|
163
|
+
const { widgetSpecs, hasFocus } = getPlaceholderWidgetSpecs(newState, pluginKeys);
|
|
133
164
|
const { decorationSet } = oldPluginState;
|
|
134
165
|
const oldMappedSet = decorationSet.map(tr.mapping, tr.doc);
|
|
135
166
|
// Find all decorations that are present in old and new set
|
|
136
|
-
const
|
|
167
|
+
const unchangedPositions = new Set();
|
|
168
|
+
const decorationsThatDidNotChange = [];
|
|
169
|
+
widgetSpecs.forEach(({ pos, spec }) => {
|
|
137
170
|
const deco = oldMappedSet.find(pos, pos);
|
|
138
|
-
if (deco.length && isEqual(deco[0].spec, spec))
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
171
|
+
if (deco.length && isEqual(deco[0].spec, spec)) {
|
|
172
|
+
unchangedPositions.add(pos);
|
|
173
|
+
decorationsThatDidNotChange.push(...deco);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
// Those are decorations that are present only in new set
|
|
177
|
+
const newAddedDecorations = widgetSpecs.filter(({ pos }) => !unchangedPositions.has(pos));
|
|
144
178
|
// That is a set with decorations that are present in old set and absent in new set
|
|
145
179
|
const notRelevantDecorations = oldMappedSet.remove(decorationsThatDidNotChange);
|
|
146
180
|
let newSet = oldMappedSet;
|
|
@@ -150,6 +184,6 @@ function applyState(tr, oldPluginState, _oldState, newState) {
|
|
|
150
184
|
// Add new decorations
|
|
151
185
|
if (newAddedDecorations.length)
|
|
152
186
|
newSet = newSet.add(tr.doc, newAddedDecorations.map((widget) => Decoration.widget(widget.pos, widget.toDOM, widget.spec)));
|
|
153
|
-
return { decorationSet: newSet, hasFocus };
|
|
187
|
+
return { decorationSet: newSet, hasFocus, pluginKeys };
|
|
154
188
|
}
|
|
155
189
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/behavior/Placeholder/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type {Node, Schema} from 'prosemirror-model';\nimport {type EditorState, Plugin, PluginKey, type Transaction} from 'prosemirror-state';\n// @ts-ignore // TODO: fix cjs build\nimport {findChildren, findParentNodeClosestToPos} from 'prosemirror-utils';\nimport {Decoration, DecorationSet} from 'prosemirror-view';\n\nimport {cn} from '../../../classname';\nimport type {ExtensionAuto} from '../../../core';\nimport {isEqual} from '../../../lodash';\nimport {isNodeEmpty} from '../../../utils/nodes';\nimport {type PlaceholderOptions, getPlaceholderContent} from '../../../utils/placeholder';\nimport {isTextSelection} from '../../../utils/selection';\n\nimport './index.scss';\n\nconst getPlaceholderPluginKeys = (schema: Schema) => {\n const pluginKeys = [];\n for (const node in schema.nodes) {\n if (schema.nodes[node]) {\n const spec = schema.nodes[node].spec;\n if (spec.placeholder?.customPlugin) {\n pluginKeys.push(spec.placeholder.customPlugin);\n }\n }\n }\n\n return pluginKeys;\n};\n\nconst b = cn('placeholder');\n\nexport const createPlaceholder = (node: Node, parent: Node | null, focus?: boolean) => {\n const content = getPlaceholderContent(node, parent);\n if (!content) return null;\n\n const placeholder = document.createElement('div');\n placeholder.className = b({focus});\n\n const placeholderCursor = document.createElement('span');\n placeholderCursor.className = b('cursor');\n\n const placeholderText = document.createElement('span');\n placeholderText.className = b('text');\n placeholderText.textContent = content;\n\n placeholder.append(placeholderCursor, placeholderText);\n\n return placeholder;\n};\n\nconst placeholderNeeded = (node: Node) => {\n const childrenWithPlaceholderVisible = findChildren(node, (n: Node) =>\n Boolean(n.type.spec.placeholder?.alwaysVisible),\n );\n\n return (\n isNodeEmpty(node) &&\n // If there are child nodes with constant placeholder - give them the priority\n !childrenWithPlaceholderVisible.length\n );\n};\n\nconst addDecoration = (\n widgetsMap: WidgetsMap,\n node: Node,\n pos: number,\n parent: Node | null,\n cursorPos: number | null | undefined,\n globalState: ApplyGlobalState,\n) => {\n const placeholderSpec = node.type.spec.placeholder;\n const decorationPosition = pos + node.childCount + 1;\n\n // We do not add decoration if there is already a placeholder at this position\n if (!placeholderSpec || widgetsMap[decorationPosition]) return;\n\n if (placeholderSpec.customPlugin) {\n widgetsMap[decorationPosition] = placeholderSpec.customPlugin;\n return;\n }\n\n const focus = decorationPosition === cursorPos;\n\n const placeholderDOM = createPlaceholder(node, parent, focus);\n if (!placeholderDOM) return;\n\n if (focus) globalState.hasFocus = true;\n\n widgetsMap[decorationPosition] = {\n pos: decorationPosition,\n toDOM: placeholderDOM,\n spec: {focus},\n };\n};\n\ntype ApplyGlobalState = {hasFocus: boolean};\n\ntype DecoWidgetParameters = Parameters<typeof Decoration.widget>;\ntype WidgetSpec = {\n pos: DecoWidgetParameters[0];\n toDOM: DecoWidgetParameters[1];\n spec?: DecoWidgetParameters[2];\n};\n\ntype PlaceholderPluginState = {decorationSet: DecorationSet; hasFocus: boolean};\n\ntype WidgetsMap = Record<number, WidgetSpec | PluginKey>;\n\nconst pluginKey = new PluginKey<PlaceholderPluginState>('placeholder_plugin');\n\nexport const Placeholder: ExtensionAuto<PlaceholderOptions> = (builder, opts) => {\n builder.context.set('placeholder', opts);\n builder.addPlugin(\n () =>\n new Plugin<PlaceholderPluginState>({\n key: pluginKey,\n props: {\n attributes(state) {\n const attrs: Record<string, string> = {};\n if (pluginKey.getState(state)!.hasFocus) {\n // hide native cursor\n attrs.class = 'g-md-editor-hidecursor';\n }\n return attrs;\n },\n decorations(state) {\n return pluginKey.getState(state)?.decorationSet;\n },\n },\n state: {\n init: (_config, state) => initState(state),\n apply: applyState,\n },\n }),\n builder.Priority.VeryHigh,\n );\n};\n\nfunction getPlaceholderWidgetSpecs(state: EditorState) {\n const globalState: ApplyGlobalState = {hasFocus: false};\n const widgetsMap: WidgetsMap = {};\n const {selection} = state;\n const cursorPos = isTextSelection(selection) ? selection.$cursor?.pos : null;\n\n getPlaceholderPluginKeys(state.schema).forEach((f) => {\n // We use find because it can be used to iterate over the DecorationSet.\n f.getState(state)?.find(undefined, undefined, (spec) => {\n widgetsMap[spec.pos] = f;\n return false;\n });\n });\n\n // Fraw placeholder for all nodes where placeholder is alwaysVisible\n const decorate = (node: Node, pos: number, parent: Node | null) => {\n const placeholderSpec = node.type.spec.placeholder;\n\n if (placeholderSpec && placeholderSpec.alwaysVisible && placeholderNeeded(node)) {\n addDecoration(widgetsMap, node, pos, parent, cursorPos, globalState);\n }\n };\n\n state.doc.descendants(decorate);\n\n const parentNode = findParentNodeClosestToPos(state.selection.$from, (node: Node) => {\n return Boolean(node.type.spec.placeholder);\n });\n\n const placeholderSpec = parentNode?.node.type.spec.placeholder;\n\n // Draw placeholder if it needs to be draw in the place of cursor\n if (\n parentNode &&\n placeholderNeeded(parentNode.node) &&\n placeholderSpec &&\n !placeholderSpec.alwaysVisible\n ) {\n const {node, pos, depth} = parentNode;\n const parent = depth > 0 ? state.selection.$from.node(depth - 1) : null;\n addDecoration(widgetsMap, node, pos, parent, cursorPos, globalState);\n }\n\n const widgetSpecs = Object.values(widgetsMap).filter(\n (decoration) => !(decoration instanceof PluginKey),\n ) as WidgetSpec[];\n\n return {widgetSpecs, hasFocus: globalState.hasFocus};\n}\n\nfunction initState(state: EditorState): PlaceholderPluginState {\n const {widgetSpecs, hasFocus} = getPlaceholderWidgetSpecs(state);\n const decorationSet = DecorationSet.create(\n state.doc,\n widgetSpecs.map((widget) => Decoration.widget(widget.pos, widget.toDOM, widget.spec)),\n );\n\n return {decorationSet, hasFocus};\n}\n\nfunction applyState(\n tr: Transaction,\n oldPluginState: PlaceholderPluginState,\n _oldState: EditorState,\n newState: EditorState,\n): PlaceholderPluginState {\n const {widgetSpecs, hasFocus} = getPlaceholderWidgetSpecs(newState);\n const {decorationSet} = oldPluginState;\n const oldMappedSet = decorationSet.map(tr.mapping, tr.doc);\n\n // Find all decorations that are present in old and new set\n const decorationsThatDidNotChange = widgetSpecs.reduce((a: Decoration[], {pos, spec}) => {\n const deco = oldMappedSet.find(pos, pos);\n if (deco.length && isEqual(deco[0].spec, spec)) a.push(...deco);\n return a;\n }, []);\n\n // Those are decorations that are presenr only in new set\n const newAddedDecorations = widgetSpecs.filter(\n ({pos}) => !decorationsThatDidNotChange.map(({from}) => from).includes(pos),\n );\n\n // That is a set with decorations that are present in old set and absent in new set\n const notRelevantDecorations = oldMappedSet.remove(decorationsThatDidNotChange);\n let newSet = oldMappedSet;\n // Remove decorations that are not present in new set\n if (notRelevantDecorations.find().length) newSet = newSet.remove(notRelevantDecorations.find());\n // Add new decorations\n if (newAddedDecorations.length)\n newSet = newSet.add(\n tr.doc,\n newAddedDecorations.map((widget) =>\n Decoration.widget(widget.pos, widget.toDOM, widget.spec),\n ),\n );\n\n return {decorationSet: newSet, hasFocus};\n}\n\ndeclare module 'prosemirror-model' {\n interface NodeSpec {\n placeholder?: {\n content: string | ((node: Node, parent?: Node | null) => string | null);\n customPlugin?: PluginKey<DecorationSet>;\n alwaysVisible?: boolean;\n };\n }\n}\n\ndeclare global {\n namespace WysiwygEditor {\n interface Context {\n placeholder: PlaceholderOptions;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/behavior/Placeholder/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type {Node, Schema} from 'prosemirror-model';\nimport {type EditorState, Plugin, PluginKey, type Transaction} from 'prosemirror-state';\n// @ts-ignore // TODO: fix cjs build\nimport {findParentNodeClosestToPos} from 'prosemirror-utils';\nimport {Decoration, DecorationSet} from 'prosemirror-view';\n\nimport {cn} from 'src/classname';\nimport type {ExtensionAuto} from 'src/core';\nimport {isEqual} from 'src/lodash';\nimport {type PlaceholderOptions, getPlaceholderContent} from 'src/utils/placeholder';\nimport {isTextSelection} from 'src/utils/selection';\n\nimport './index.scss';\n\nconst getPlaceholderPluginKeys = (schema: Schema) => {\n const pluginKeys = [];\n for (const node in schema.nodes) {\n if (schema.nodes[node]) {\n const spec = schema.nodes[node].spec;\n if (spec.placeholder?.customPlugin) {\n pluginKeys.push(spec.placeholder.customPlugin);\n }\n }\n }\n\n return pluginKeys;\n};\n\nconst b = cn('placeholder');\n\nexport const createPlaceholder = (node: Node, parent: Node | null, focus?: boolean) => {\n const content = getPlaceholderContent(node, parent);\n if (!content) return null;\n\n const placeholder = document.createElement('div');\n placeholder.className = b({focus});\n\n const placeholderCursor = document.createElement('span');\n placeholderCursor.className = b('cursor');\n\n const placeholderText = document.createElement('span');\n placeholderText.className = b('text');\n placeholderText.textContent = content;\n\n placeholder.append(placeholderCursor, placeholderText);\n\n return placeholder;\n};\n\nconst placeholderNeeded = (node: Node) => {\n // Combine all checks in a single descendants pass\n let hasAlwaysVisiblePlaceholder = false;\n let hasNonEmptyContent = false;\n\n node.descendants((n: Node) => {\n // Check for alwaysVisible placeholder\n if (n.type.spec.placeholder?.alwaysVisible) {\n hasAlwaysVisiblePlaceholder = true;\n return false; // Stop traversal early\n }\n\n // Check if node has non-empty content (same logic as isNodeEmpty)\n if (n.isAtom) {\n hasNonEmptyContent = true;\n return false; // Stop traversal early\n }\n\n if (n.isText && n.textContent) {\n hasNonEmptyContent = true;\n return false; // Stop traversal early\n }\n\n // Non-empty paragraph or other block with content\n if (n.content.size > 0 && n.type.name !== 'paragraph') {\n hasNonEmptyContent = true;\n return false; // Stop traversal early\n }\n\n return true;\n });\n\n return !hasNonEmptyContent && !hasAlwaysVisiblePlaceholder;\n};\n\nconst addDecoration = (\n widgetsMap: WidgetsMap,\n node: Node,\n pos: number,\n parent: Node | null,\n cursorPos: number | null | undefined,\n globalState: ApplyGlobalState,\n) => {\n const placeholderSpec = node.type.spec.placeholder;\n const decorationPosition = pos + node.childCount + 1;\n\n // We do not add decoration if there is already a placeholder at this position\n if (!placeholderSpec || widgetsMap[decorationPosition]) return;\n\n if (placeholderSpec.customPlugin) {\n widgetsMap[decorationPosition] = placeholderSpec.customPlugin;\n return;\n }\n\n const focus = decorationPosition === cursorPos;\n\n const placeholderDOM = createPlaceholder(node, parent, focus);\n if (!placeholderDOM) return;\n\n if (focus) globalState.hasFocus = true;\n\n widgetsMap[decorationPosition] = {\n pos: decorationPosition,\n toDOM: placeholderDOM,\n spec: {focus},\n };\n};\n\ntype ApplyGlobalState = {hasFocus: boolean};\n\ntype DecoWidgetParameters = Parameters<typeof Decoration.widget>;\ntype WidgetSpec = {\n pos: DecoWidgetParameters[0];\n toDOM: DecoWidgetParameters[1];\n spec?: DecoWidgetParameters[2];\n};\n\ntype PlaceholderPluginState = {\n decorationSet: DecorationSet;\n hasFocus: boolean;\n pluginKeys: PluginKey<DecorationSet>[];\n};\n\ntype WidgetsMap = Record<number, WidgetSpec | PluginKey>;\n\nconst pluginKey = new PluginKey<PlaceholderPluginState>('placeholder_plugin');\n\nexport const Placeholder: ExtensionAuto<PlaceholderOptions> = (builder, opts) => {\n builder.context.set('placeholder', opts);\n builder.addPlugin(\n () =>\n new Plugin<PlaceholderPluginState>({\n key: pluginKey,\n props: {\n attributes(state) {\n const attrs: Record<string, string> = {};\n if (pluginKey.getState(state)!.hasFocus) {\n // hide native cursor\n attrs.class = 'g-md-editor-hidecursor';\n }\n return attrs;\n },\n decorations(state) {\n return pluginKey.getState(state)?.decorationSet;\n },\n },\n state: {\n init: (_config, state) => initState(state),\n apply: applyState,\n },\n }),\n builder.Priority.VeryHigh,\n );\n};\n\nfunction getPlaceholderWidgetSpecs(state: EditorState, pluginKeys: PluginKey<DecorationSet>[]) {\n const globalState: ApplyGlobalState = {hasFocus: false};\n const widgetsMap: WidgetsMap = {};\n const {selection} = state;\n const cursorPos = isTextSelection(selection) ? selection.$cursor?.pos : null;\n\n pluginKeys.forEach((f) => {\n // We use find because it can be used to iterate over the DecorationSet.\n f.getState(state)?.find(undefined, undefined, (spec) => {\n widgetsMap[spec.pos] = f;\n return false;\n });\n });\n\n // Draw placeholder for all nodes where placeholder is alwaysVisible\n const decorate = (node: Node, pos: number, parent: Node | null) => {\n const placeholderSpec = node.type.spec.placeholder;\n\n if (placeholderSpec && placeholderSpec.alwaysVisible && placeholderNeeded(node)) {\n addDecoration(widgetsMap, node, pos, parent, cursorPos, globalState);\n }\n };\n\n state.doc.descendants(decorate);\n\n const parentNode = findParentNodeClosestToPos(state.selection.$from, (node: Node) => {\n return Boolean(node.type.spec.placeholder);\n });\n\n const placeholderSpec = parentNode?.node.type.spec.placeholder;\n\n // Draw placeholder if it needs to be draw in the place of cursor\n if (\n parentNode &&\n placeholderNeeded(parentNode.node) &&\n placeholderSpec &&\n !placeholderSpec.alwaysVisible\n ) {\n const {node, pos, depth} = parentNode;\n const parent = depth > 0 ? state.selection.$from.node(depth - 1) : null;\n addDecoration(widgetsMap, node, pos, parent, cursorPos, globalState);\n }\n\n const widgetSpecs = Object.values(widgetsMap).filter(\n (decoration) => !(decoration instanceof PluginKey),\n ) as WidgetSpec[];\n\n return {widgetSpecs, hasFocus: globalState.hasFocus};\n}\n\nfunction initState(state: EditorState): PlaceholderPluginState {\n const pluginKeys = getPlaceholderPluginKeys(state.schema);\n const {widgetSpecs, hasFocus} = getPlaceholderWidgetSpecs(state, pluginKeys);\n const decorationSet = DecorationSet.create(\n state.doc,\n widgetSpecs.map((widget) => Decoration.widget(widget.pos, widget.toDOM, widget.spec)),\n );\n\n return {decorationSet, hasFocus, pluginKeys};\n}\n\nfunction applyState(\n tr: Transaction,\n oldPluginState: PlaceholderPluginState,\n oldState: EditorState,\n newState: EditorState,\n): PlaceholderPluginState {\n // Early return if document hasn't changed and selection hasn't changed\n // This avoids unnecessary recalculation of decorations\n if (!tr.docChanged && !tr.selectionSet) {\n return oldPluginState;\n }\n\n // Reuse cached plugin keys if schema hasn't changed\n const pluginKeys =\n oldState.schema === newState.schema\n ? oldPluginState.pluginKeys\n : getPlaceholderPluginKeys(newState.schema);\n\n const {widgetSpecs, hasFocus} = getPlaceholderWidgetSpecs(newState, pluginKeys);\n const {decorationSet} = oldPluginState;\n const oldMappedSet = decorationSet.map(tr.mapping, tr.doc);\n\n // Find all decorations that are present in old and new set\n const unchangedPositions = new Set<number>();\n const decorationsThatDidNotChange: Decoration[] = [];\n\n widgetSpecs.forEach(({pos, spec}) => {\n const deco = oldMappedSet.find(pos, pos);\n if (deco.length && isEqual(deco[0].spec, spec)) {\n unchangedPositions.add(pos);\n decorationsThatDidNotChange.push(...deco);\n }\n });\n\n // Those are decorations that are present only in new set\n const newAddedDecorations = widgetSpecs.filter(({pos}) => !unchangedPositions.has(pos));\n\n // That is a set with decorations that are present in old set and absent in new set\n const notRelevantDecorations = oldMappedSet.remove(decorationsThatDidNotChange);\n let newSet = oldMappedSet;\n // Remove decorations that are not present in new set\n if (notRelevantDecorations.find().length) newSet = newSet.remove(notRelevantDecorations.find());\n // Add new decorations\n if (newAddedDecorations.length)\n newSet = newSet.add(\n tr.doc,\n newAddedDecorations.map((widget) =>\n Decoration.widget(widget.pos, widget.toDOM, widget.spec),\n ),\n );\n\n return {decorationSet: newSet, hasFocus, pluginKeys};\n}\n\ndeclare module 'prosemirror-model' {\n interface NodeSpec {\n placeholder?: {\n content: string | ((node: Node, parent?: Node | null) => string | null);\n customPlugin?: PluginKey<DecorationSet>;\n alwaysVisible?: boolean;\n };\n }\n}\n\ndeclare global {\n namespace WysiwygEditor {\n interface Context {\n placeholder: PlaceholderOptions;\n }\n }\n}\n"]}
|
package/build/esm/version.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/** During build process, the current version will be injected here */
|
|
2
|
-
export const VERSION = typeof '15.34.
|
|
2
|
+
export const VERSION = typeof '15.34.5' !== 'undefined' ? '15.34.5' : 'unknown';
|
|
3
3
|
//# sourceMappingURL=version.js.map
|
package/build/esm/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"../../src","sources":["version.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC","sourcesContent":["/** During build process, the current version will be injected here */\nexport const VERSION = typeof '15.34.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"../../src","sources":["version.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC","sourcesContent":["/** During build process, the current version will be injected here */\nexport const VERSION = typeof '15.34.5' !== 'undefined' ? '15.34.5' : 'unknown';\n"]}
|