@limetech/lime-elements 37.46.1 → 37.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js +84 -6
- package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js.map +1 -1
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image-remover-plugin.js +78 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image-remover-plugin.js.map +1 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link-plugin.js +5 -4
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link-plugin.js.map +1 -1
- package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js +2 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js.map +1 -1
- package/dist/esm/limel-prosemirror-adapter.entry.js +84 -6
- package/dist/esm/limel-prosemirror-adapter.entry.js.map +1 -1
- package/dist/lime-elements/lime-elements.esm.js +1 -1
- package/dist/lime-elements/{p-8d71c9e5.entry.js → p-8db40f25.entry.js} +2 -2
- package/dist/lime-elements/p-8db40f25.entry.js.map +1 -0
- package/dist/types/components/text-editor/prosemirror-adapter/plugins/image-remover-plugin.d.ts +4 -0
- package/package.json +1 -1
- package/dist/lime-elements/p-8d71c9e5.entry.js.map +0 -1
package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image-remover-plugin.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Plugin, PluginKey } from 'prosemirror-state';
|
|
2
|
+
import { Slice, Fragment, Node } from 'prosemirror-model';
|
|
3
|
+
export const pluginKey = new PluginKey('imageRemoverPlugin');
|
|
4
|
+
export const createImageRemoverPlugin = () => {
|
|
5
|
+
return new Plugin({
|
|
6
|
+
key: pluginKey,
|
|
7
|
+
props: {
|
|
8
|
+
handlePaste: (view, event, slice) => {
|
|
9
|
+
return processPasteEvent(view, event, slice);
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Check if a given ProseMirror node or fragment contains any image nodes.
|
|
16
|
+
* @param node - The ProseMirror node or fragment to check.
|
|
17
|
+
* @returns A boolean indicating whether the node contains any image nodes.
|
|
18
|
+
*/
|
|
19
|
+
const isImageNode = (node) => {
|
|
20
|
+
if (node instanceof Node) {
|
|
21
|
+
if (node.type.name === 'image') {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
let found = false;
|
|
25
|
+
node.content.forEach((child) => {
|
|
26
|
+
if (isImageNode(child)) {
|
|
27
|
+
found = true;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
return found;
|
|
31
|
+
}
|
|
32
|
+
else if (node instanceof Fragment) {
|
|
33
|
+
let found = false;
|
|
34
|
+
node.forEach((child) => {
|
|
35
|
+
if (isImageNode(child)) {
|
|
36
|
+
found = true;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
return found;
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Filter out image nodes from a ProseMirror fragment.
|
|
45
|
+
* @param fragment - The ProseMirror fragment to filter.
|
|
46
|
+
* @returns A new fragment with image nodes removed.
|
|
47
|
+
*/
|
|
48
|
+
const filterImageNodes = (fragment) => {
|
|
49
|
+
const filteredChildren = [];
|
|
50
|
+
fragment.forEach((child) => {
|
|
51
|
+
if (!isImageNode(child)) {
|
|
52
|
+
if (child.content.size > 0) {
|
|
53
|
+
const filteredContent = filterImageNodes(child.content);
|
|
54
|
+
const newNode = child.copy(filteredContent);
|
|
55
|
+
filteredChildren.push(newNode);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
filteredChildren.push(child);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return Fragment.fromArray(filteredChildren);
|
|
63
|
+
};
|
|
64
|
+
const processPasteEvent = (view, event, slice) => {
|
|
65
|
+
const clipboardData = event.clipboardData;
|
|
66
|
+
if (!clipboardData) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
const filteredSlice = new Slice(filterImageNodes(slice.content), slice.openStart, slice.openEnd);
|
|
70
|
+
if (filteredSlice.content.childCount < slice.content.childCount) {
|
|
71
|
+
const { state, dispatch } = view;
|
|
72
|
+
const tr = state.tr.replaceSelection(filteredSlice);
|
|
73
|
+
dispatch(tr);
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=image-remover-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-remover-plugin.js","sourceRoot":"","sources":["../../../../../src/components/text-editor/prosemirror-adapter/plugins/image-remover-plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { Plugin, PluginKey } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { Slice, Fragment, Node } from 'prosemirror-model';\n\nexport const pluginKey = new PluginKey('imageRemoverPlugin');\n\nexport const createImageRemoverPlugin = () => {\n return new Plugin({\n key: pluginKey,\n props: {\n handlePaste: (view, event, slice) => {\n return processPasteEvent(view, event, slice);\n },\n },\n });\n};\n\n/**\n * Check if a given ProseMirror node or fragment contains any image nodes.\n * @param node - The ProseMirror node or fragment to check.\n * @returns A boolean indicating whether the node contains any image nodes.\n */\nconst isImageNode = (node: Node | Fragment): boolean => {\n if (node instanceof Node) {\n if (node.type.name === 'image') {\n return true;\n }\n\n let found = false;\n node.content.forEach((child) => {\n if (isImageNode(child)) {\n found = true;\n }\n });\n\n return found;\n } else if (node instanceof Fragment) {\n let found = false;\n node.forEach((child) => {\n if (isImageNode(child)) {\n found = true;\n }\n });\n\n return found;\n }\n\n return false;\n};\n\n/**\n * Filter out image nodes from a ProseMirror fragment.\n * @param fragment - The ProseMirror fragment to filter.\n * @returns A new fragment with image nodes removed.\n */\nconst filterImageNodes = (fragment: Fragment): Fragment => {\n const filteredChildren: Node[] = [];\n\n fragment.forEach((child) => {\n if (!isImageNode(child)) {\n if (child.content.size > 0) {\n const filteredContent = filterImageNodes(child.content);\n const newNode = child.copy(filteredContent);\n filteredChildren.push(newNode);\n } else {\n filteredChildren.push(child);\n }\n }\n });\n\n return Fragment.fromArray(filteredChildren);\n};\n\nconst processPasteEvent = (\n view: EditorView,\n event: ClipboardEvent,\n slice: Slice,\n): boolean => {\n const clipboardData = event.clipboardData;\n if (!clipboardData) {\n return false;\n }\n\n const filteredSlice = new Slice(\n filterImageNodes(slice.content),\n slice.openStart,\n slice.openEnd,\n );\n\n if (filteredSlice.content.childCount < slice.content.childCount) {\n const { state, dispatch } = view;\n const tr = state.tr.replaceSelection(filteredSlice);\n dispatch(tr);\n\n return true;\n }\n\n return false;\n};\n"]}
|
|
@@ -125,11 +125,12 @@ const processPasteEvent = (view, event) => {
|
|
|
125
125
|
return false;
|
|
126
126
|
}
|
|
127
127
|
const text = clipboardData.getData('text/plain');
|
|
128
|
-
if
|
|
129
|
-
|
|
128
|
+
// Process as a link if the text is a valid URL
|
|
129
|
+
if (isValidUrl(text)) {
|
|
130
|
+
pasteAsLink(view, text);
|
|
131
|
+
return true;
|
|
130
132
|
}
|
|
131
|
-
|
|
132
|
-
return true;
|
|
133
|
+
return false;
|
|
133
134
|
};
|
|
134
135
|
const pasteAsLink = (view, href) => {
|
|
135
136
|
const { state, dispatch } = view;
|
package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link-plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-plugin.js","sourceRoot":"","sources":["../../../../../src/components/text-editor/prosemirror-adapter/plugins/link-plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { Plugin, PluginKey, TextSelection } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { schema } from 'prosemirror-schema-basic';\nimport { Mark } from 'prosemirror-model';\nimport { isExternalLink, isValidUrl } from '../menu/menu-commands';\nimport { EditorMenuTypes } from '../menu/types';\n\nexport const linkPluginKey = new PluginKey('linkPlugin');\n\nexport type UpdateLinkCallback = (text: string, href: string) => void;\n\nexport interface EditorLinkMenuEventDetail {\n href: string;\n text: string;\n}\n\nconst updateLink = (\n view: EditorView,\n updateLinkCallback?: UpdateLinkCallback,\n) => {\n const { from, to } = view.state.selection;\n\n let text = '';\n let href = '';\n view.state.doc.nodesBetween(from, to, (node) => {\n if (node.type.name === 'text') {\n text = node.text;\n node.marks.forEach((mark: Mark) => {\n if (mark.type.name === 'link') {\n href = mark.attrs.href;\n }\n });\n }\n });\n\n if (updateLinkCallback) {\n updateLinkCallback(text, href);\n }\n};\n\n/**\n * Finds the start position of the link node ensuring the href matches the original link's href.\n * @param doc - The ProseMirror document.\n * @param pos - The position to start searching from.\n * @param href - The href attribute of the original link mark.\n * @returns The start position of the link node.\n */\nconst findStart = (doc, pos, href) => {\n while (pos > 0) {\n const node = doc.nodeAt(pos - 1);\n if (\n !node?.isText ||\n !node.marks.some(\n (mark: Mark) =>\n mark.type.name === EditorMenuTypes.Link &&\n mark.attrs.href === href,\n )\n ) {\n break;\n }\n\n pos--;\n }\n\n return pos;\n};\n\n/**\n * Finds the end position of the link node ensuring the href matches the original link's href.\n * @param doc - The ProseMirror document.\n * @param pos - The position to start searching from.\n * @param href - The href attribute of the original link mark.\n * @returns The end position of the link node.\n */\nconst findEnd = (doc, pos, href) => {\n while (pos < doc.content.size) {\n const node = doc.nodeAt(pos);\n if (\n !node?.isText ||\n !node.marks.some(\n (mark) =>\n mark.type.name === EditorMenuTypes.Link &&\n mark.attrs.href === href,\n )\n ) {\n break;\n }\n\n pos++;\n }\n\n return pos;\n};\n\n/**\n * Gets the link data at the specified position.\n * @param view - The ProseMirror editor view.\n * @param event - The mouse event.\n * @returns An object containing the link data or null if no link is found.\n */\nconst getLinkDataAtPosition = (view: EditorView, event: MouseEvent) => {\n const pos = view.posAtCoords({ left: event.clientX, top: event.clientY });\n const node = view.state.doc.nodeAt(pos.pos);\n if (!node) {\n return null;\n }\n\n const linkMark = node.marks.find(\n (mark) => mark.type.name === EditorMenuTypes.Link,\n );\n if (!linkMark) {\n return null;\n }\n\n const href = linkMark.attrs.href;\n const from = findStart(view.state.doc, pos.pos, href);\n const to = findEnd(view.state.doc, pos.pos, href);\n const text = view.state.doc.textBetween(from, to, ' ');\n\n return { href: href, text: text, from: from, to: to };\n};\n\nconst processModClickEvent = (view: EditorView, event: MouseEvent): boolean => {\n const { href } = getLinkDataAtPosition(view, event);\n if (href) {\n window.open(href, '_blank');\n\n return true;\n }\n\n return false;\n};\n\nconst openLinkMenu = (view: EditorView, href: string, text: string) => {\n const event = new CustomEvent<EditorLinkMenuEventDetail>(\n 'open-editor-link-menu',\n {\n detail: { href: href, text: text },\n bubbles: true,\n composed: true,\n },\n );\n view.dom.dispatchEvent(event);\n};\n\nlet lastClickTime = 0;\nconst DOUBLE_CLICK_DELAY = 200;\nlet clickTimeout;\n\nconst processDoubleClickEvent = (\n view: EditorView,\n event: MouseEvent,\n): boolean => {\n const now = Date.now();\n\n if (now - lastClickTime < DOUBLE_CLICK_DELAY) {\n clearTimeout(clickTimeout);\n lastClickTime = now; // Reset lastClickTime to prevent single-click action\n\n return false;\n }\n\n lastClickTime = now;\n\n clickTimeout = setTimeout(() => {\n const linkData = getLinkDataAtPosition(view, event);\n if (linkData) {\n const { href, text, from, to } = linkData;\n const transaction = view.state.tr.setSelection(\n TextSelection.create(view.state.doc, from, to),\n );\n view.dispatch(transaction);\n openLinkMenu(view, href, text);\n }\n }, DOUBLE_CLICK_DELAY);\n\n return true;\n};\n\nconst processPasteEvent = (\n view: EditorView,\n event: ClipboardEvent,\n): boolean => {\n const clipboardData = event.clipboardData;\n if (!clipboardData) {\n return false;\n }\n\n const text = clipboardData.getData('text/plain');\n\n if (!isValidUrl(text)) {\n return false;\n }\n\n pasteAsLink(view, text);\n\n return true;\n};\n\nconst pasteAsLink = (view: EditorView, href: string) => {\n const { state, dispatch } = view;\n const { from, to } = state.selection;\n const linkMark = schema.marks.link.create({\n href: href,\n title: href,\n target: isExternalLink(href) ? '_blank' : null,\n });\n const selectedText = state.doc.textBetween(from, to, ' ') || href;\n const transaction = state.tr\n .insertText(selectedText, from, to)\n .addMark(from, from + selectedText.length, linkMark);\n\n dispatch(transaction);\n};\n\nexport const createLinkPlugin = (updateLinkCallback?: UpdateLinkCallback) => {\n return new Plugin({\n key: linkPluginKey,\n props: {\n handlePaste: (view, event) => {\n return processPasteEvent(view, event);\n },\n handleDOMEvents: {\n mousedown: (view, event) => {\n if (\n (event.metaKey || event.ctrlKey) &&\n event.button === 0\n ) {\n return processModClickEvent(view, event);\n }\n\n return processDoubleClickEvent(view, event);\n },\n },\n },\n view: () => ({\n update: (view) => {\n updateLink(view, updateLinkCallback);\n },\n }),\n });\n};\n"]}
|
|
1
|
+
{"version":3,"file":"link-plugin.js","sourceRoot":"","sources":["../../../../../src/components/text-editor/prosemirror-adapter/plugins/link-plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { Plugin, PluginKey, TextSelection } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { schema } from 'prosemirror-schema-basic';\nimport { Mark } from 'prosemirror-model';\nimport { isExternalLink, isValidUrl } from '../menu/menu-commands';\nimport { EditorMenuTypes } from '../menu/types';\n\nexport const linkPluginKey = new PluginKey('linkPlugin');\n\nexport type UpdateLinkCallback = (text: string, href: string) => void;\n\nexport interface EditorLinkMenuEventDetail {\n href: string;\n text: string;\n}\n\nconst updateLink = (\n view: EditorView,\n updateLinkCallback?: UpdateLinkCallback,\n) => {\n const { from, to } = view.state.selection;\n\n let text = '';\n let href = '';\n view.state.doc.nodesBetween(from, to, (node) => {\n if (node.type.name === 'text') {\n text = node.text;\n node.marks.forEach((mark: Mark) => {\n if (mark.type.name === 'link') {\n href = mark.attrs.href;\n }\n });\n }\n });\n\n if (updateLinkCallback) {\n updateLinkCallback(text, href);\n }\n};\n\n/**\n * Finds the start position of the link node ensuring the href matches the original link's href.\n * @param doc - The ProseMirror document.\n * @param pos - The position to start searching from.\n * @param href - The href attribute of the original link mark.\n * @returns The start position of the link node.\n */\nconst findStart = (doc, pos, href) => {\n while (pos > 0) {\n const node = doc.nodeAt(pos - 1);\n if (\n !node?.isText ||\n !node.marks.some(\n (mark: Mark) =>\n mark.type.name === EditorMenuTypes.Link &&\n mark.attrs.href === href,\n )\n ) {\n break;\n }\n\n pos--;\n }\n\n return pos;\n};\n\n/**\n * Finds the end position of the link node ensuring the href matches the original link's href.\n * @param doc - The ProseMirror document.\n * @param pos - The position to start searching from.\n * @param href - The href attribute of the original link mark.\n * @returns The end position of the link node.\n */\nconst findEnd = (doc, pos, href) => {\n while (pos < doc.content.size) {\n const node = doc.nodeAt(pos);\n if (\n !node?.isText ||\n !node.marks.some(\n (mark) =>\n mark.type.name === EditorMenuTypes.Link &&\n mark.attrs.href === href,\n )\n ) {\n break;\n }\n\n pos++;\n }\n\n return pos;\n};\n\n/**\n * Gets the link data at the specified position.\n * @param view - The ProseMirror editor view.\n * @param event - The mouse event.\n * @returns An object containing the link data or null if no link is found.\n */\nconst getLinkDataAtPosition = (view: EditorView, event: MouseEvent) => {\n const pos = view.posAtCoords({ left: event.clientX, top: event.clientY });\n const node = view.state.doc.nodeAt(pos.pos);\n if (!node) {\n return null;\n }\n\n const linkMark = node.marks.find(\n (mark) => mark.type.name === EditorMenuTypes.Link,\n );\n if (!linkMark) {\n return null;\n }\n\n const href = linkMark.attrs.href;\n const from = findStart(view.state.doc, pos.pos, href);\n const to = findEnd(view.state.doc, pos.pos, href);\n const text = view.state.doc.textBetween(from, to, ' ');\n\n return { href: href, text: text, from: from, to: to };\n};\n\nconst processModClickEvent = (view: EditorView, event: MouseEvent): boolean => {\n const { href } = getLinkDataAtPosition(view, event);\n if (href) {\n window.open(href, '_blank');\n\n return true;\n }\n\n return false;\n};\n\nconst openLinkMenu = (view: EditorView, href: string, text: string) => {\n const event = new CustomEvent<EditorLinkMenuEventDetail>(\n 'open-editor-link-menu',\n {\n detail: { href: href, text: text },\n bubbles: true,\n composed: true,\n },\n );\n view.dom.dispatchEvent(event);\n};\n\nlet lastClickTime = 0;\nconst DOUBLE_CLICK_DELAY = 200;\nlet clickTimeout;\n\nconst processDoubleClickEvent = (\n view: EditorView,\n event: MouseEvent,\n): boolean => {\n const now = Date.now();\n\n if (now - lastClickTime < DOUBLE_CLICK_DELAY) {\n clearTimeout(clickTimeout);\n lastClickTime = now; // Reset lastClickTime to prevent single-click action\n\n return false;\n }\n\n lastClickTime = now;\n\n clickTimeout = setTimeout(() => {\n const linkData = getLinkDataAtPosition(view, event);\n if (linkData) {\n const { href, text, from, to } = linkData;\n const transaction = view.state.tr.setSelection(\n TextSelection.create(view.state.doc, from, to),\n );\n view.dispatch(transaction);\n openLinkMenu(view, href, text);\n }\n }, DOUBLE_CLICK_DELAY);\n\n return true;\n};\n\nconst processPasteEvent = (\n view: EditorView,\n event: ClipboardEvent,\n): boolean => {\n const clipboardData = event.clipboardData;\n if (!clipboardData) {\n return false;\n }\n\n const text = clipboardData.getData('text/plain');\n\n // Process as a link if the text is a valid URL\n if (isValidUrl(text)) {\n pasteAsLink(view, text);\n\n return true;\n }\n\n return false;\n};\n\nconst pasteAsLink = (view: EditorView, href: string) => {\n const { state, dispatch } = view;\n const { from, to } = state.selection;\n const linkMark = schema.marks.link.create({\n href: href,\n title: href,\n target: isExternalLink(href) ? '_blank' : null,\n });\n const selectedText = state.doc.textBetween(from, to, ' ') || href;\n const transaction = state.tr\n .insertText(selectedText, from, to)\n .addMark(from, from + selectedText.length, linkMark);\n\n dispatch(transaction);\n};\n\nexport const createLinkPlugin = (updateLinkCallback?: UpdateLinkCallback) => {\n return new Plugin({\n key: linkPluginKey,\n props: {\n handlePaste: (view, event) => {\n return processPasteEvent(view, event);\n },\n handleDOMEvents: {\n mousedown: (view, event) => {\n if (\n (event.metaKey || event.ctrlKey) &&\n event.button === 0\n ) {\n return processModClickEvent(view, event);\n }\n\n return processDoubleClickEvent(view, event);\n },\n },\n },\n view: () => ({\n update: (view) => {\n updateLink(view, updateLinkCallback);\n },\n }),\n });\n};\n"]}
|
|
@@ -17,6 +17,7 @@ import { isItem } from 'src/components/action-bar/isItem';
|
|
|
17
17
|
import { cloneDeep } from 'lodash-es';
|
|
18
18
|
import { strikethrough } from './menu/menu-schema-extender';
|
|
19
19
|
import { createLinkPlugin, } from './plugins/link-plugin';
|
|
20
|
+
import { createImageRemoverPlugin } from './plugins/image-remover-plugin';
|
|
20
21
|
/**
|
|
21
22
|
* The ProseMirror adapter offers a rich text editing experience with markdown support.
|
|
22
23
|
* [Read more...](https://prosemirror.net/)
|
|
@@ -215,6 +216,7 @@ export class ProsemirrorAdapter {
|
|
|
215
216
|
keymap(this.menuCommandFactory.buildKeymap()),
|
|
216
217
|
this.createMenuStateTrackingPlugin(this.actionBarItems),
|
|
217
218
|
createLinkPlugin(this.handleNewLinkSelection),
|
|
219
|
+
createImageRemoverPlugin(),
|
|
218
220
|
],
|
|
219
221
|
});
|
|
220
222
|
}
|
package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prosemirror-adapter.js","sourceRoot":"","sources":["../../../../src/components/text-editor/prosemirror-adapter/prosemirror-adapter.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Element,\n Event,\n EventEmitter,\n Prop,\n State,\n Watch,\n h,\n} from '@stencil/core';\nimport { EditorState, Plugin, PluginKey, Transaction } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { Schema, DOMParser } from 'prosemirror-model';\nimport { schema } from 'prosemirror-schema-basic';\nimport { addListNodes } from 'prosemirror-schema-list';\nimport { exampleSetup } from 'prosemirror-example-setup';\nimport { keymap } from 'prosemirror-keymap';\nimport { ActionBarItem } from 'src/components/action-bar/action-bar.types';\nimport { ListSeparator } from 'src/components/list/list-item.types';\nimport { CommandWithActive, MenuCommandFactory } from './menu/menu-commands';\nimport { menuTranslationIDs, getTextEditorMenuItems } from './menu/menu-items';\nimport { ContentTypeConverter } from '../utils/content-type-converter';\nimport { markdownConverter } from '../utils/markdown-converter';\nimport { HTMLConverter } from '../utils/html-converter';\nimport { EditorMenuTypes, EditorTextLink } from './menu/types';\nimport translate from 'src/global/translations';\nimport { createRandomString } from 'src/util/random-string';\nimport { isItem } from 'src/components/action-bar/isItem';\nimport { cloneDeep } from 'lodash-es';\nimport { Languages } from '../../date-picker/date.types';\nimport { strikethrough } from './menu/menu-schema-extender';\nimport {\n EditorLinkMenuEventDetail,\n createLinkPlugin,\n} from './plugins/link-plugin';\n\n/**\n * The ProseMirror adapter offers a rich text editing experience with markdown support.\n * [Read more...](https://prosemirror.net/)\n *\n * @exampleComponent limel-example-prosemirror-adapter-basic\n * @exampleComponent limel-example-prosemirror-adapter-with-custom-menu\n * @beta\n * @private\n */\n@Component({\n tag: 'limel-prosemirror-adapter',\n shadow: true,\n styleUrl: 'prosemirror-adapter.scss',\n})\nexport class ProsemirrorAdapter {\n /**\n * The type of content that the editor should handle and emit, defaults to `markdown`\n *\n * Assumed to be set only once, so not reactive to changes\n */\n @Prop()\n public contentType: 'markdown' | 'html' = 'markdown';\n\n /**\n * The value of the editor, expected to be markdown\n */\n @Prop()\n public value: string;\n\n /**\n * Defines the language for translations.\n */\n @Prop({ reflect: true })\n public language: Languages;\n\n @Element()\n private host: HTMLLimelTextEditorElement;\n\n private portalId: string;\n\n @State()\n private view: EditorView;\n\n @State()\n private actionBarItems: Array<\n ActionBarItem<EditorMenuTypes> | ListSeparator\n > = [];\n\n @State()\n private link: EditorTextLink = { href: '' };\n\n /**\n * Open state of the dialog\n */\n @State()\n public isLinkMenuOpen: boolean = false;\n\n private menuCommandFactory: MenuCommandFactory;\n private schema: Schema;\n private contentConverter: ContentTypeConverter;\n private suppressChangeEvent = false;\n\n /**\n * Dispatched when a change is made to the editor\n */\n @Event()\n private change: EventEmitter<string>;\n\n constructor() {\n this.portalId = createRandomString();\n }\n\n private actionBarPluginKey = new PluginKey('actionBarPlugin');\n\n @Watch('value')\n protected watchValue(newValue: string) {\n if (\n !this.view ||\n newValue === this.contentConverter.serialize(this.view, this.schema)\n ) {\n return;\n }\n\n this.updateView(newValue);\n }\n\n public componentWillLoad() {\n this.getActionBarItems();\n this.setupContentConverter();\n }\n\n public componentDidLoad() {\n // Stencil complains loudly about triggering rerenders in\n // componentDidLoad, but we have to, so we're using setTimeout to\n // suppress the warning. /Ads\n setTimeout(() => {\n this.initializeTextEditor();\n }, 0);\n\n this.host.addEventListener(\n 'open-editor-link-menu',\n this.handleOpenLinkMenu,\n );\n }\n\n public disconnectedCallback() {\n this.host.removeEventListener(\n 'open-editor-link-menu',\n this.handleOpenLinkMenu,\n );\n this.view.destroy();\n }\n\n public render() {\n return [\n <div id=\"editor\" />,\n <limel-action-bar\n slot=\"trigger\"\n accessibleLabel=\"Toolbar\"\n actions={this.actionBarItems}\n onItemSelected={this.handleActionBarItem}\n />,\n <limel-portal\n containerId={this.portalId}\n visible={this.isLinkMenuOpen}\n openDirection=\"top\"\n inheritParentWidth={true}\n containerStyle={{ 'z-index': 1 }}\n >\n <limel-menu-surface\n open={this.isLinkMenuOpen}\n onDismiss={this.handleCancelLinkMenu}\n style={{\n '--mdc-menu-min-width': '100%',\n 'max-height': 'inherit',\n }}\n >\n <limel-text-editor-link-menu\n link={this.link}\n isOpen={this.isLinkMenuOpen}\n onLinkChange={this.handleLinkChange}\n onCancel={this.handleCancelLinkMenu}\n onSave={this.handleSaveLinkMenu}\n />\n </limel-menu-surface>\n </limel-portal>,\n ];\n }\n\n private setupContentConverter() {\n if (this.contentType === 'markdown') {\n this.contentConverter = new markdownConverter();\n } else if (this.contentType === 'html') {\n this.contentConverter = new HTMLConverter();\n } else {\n throw new Error(\n `Unsupported content type: ${this.contentType}. Only 'markdown' and 'html' are supported.`,\n );\n }\n }\n\n private getActionBarItems = () => {\n this.actionBarItems = getTextEditorMenuItems().map(\n this.getTranslatedItem,\n );\n };\n\n private getTranslatedItem = (item) => {\n const newItem = cloneDeep(item);\n\n if (isItem(item)) {\n const translationId = menuTranslationIDs[item.value];\n\n if (translationId) {\n newItem.text = translate.get(translationId, this.language);\n }\n }\n\n return newItem;\n };\n\n private async initializeTextEditor() {\n this.schema = this.initializeSchema();\n const initialDoc = await this.parseInitialContent();\n this.menuCommandFactory = new MenuCommandFactory(this.schema);\n this.view = new EditorView(\n this.host.shadowRoot.querySelector('#editor'),\n {\n state: this.createEditorState(initialDoc),\n dispatchTransaction: this.handleTransaction,\n },\n );\n\n if (this.value) {\n this.updateView(this.value);\n }\n }\n\n private initializeSchema() {\n return new Schema({\n nodes: addListNodes(schema.spec.nodes, 'paragraph block*', 'block'),\n marks: schema.spec.marks.append({\n strikethrough: strikethrough,\n }),\n });\n }\n\n private async parseInitialContent() {\n const initialContentElement = document.createElement('div');\n\n if (this.value) {\n initialContentElement.innerHTML =\n await this.contentConverter.parseAsHTML(\n this.value,\n this.schema,\n );\n } else {\n initialContentElement.innerHTML = '<p></p>';\n }\n\n return DOMParser.fromSchema(this.schema).parse(initialContentElement);\n }\n\n private createEditorState(initialDoc) {\n return EditorState.create({\n doc: initialDoc,\n plugins: [\n ...exampleSetup({ schema: this.schema, menuBar: false }),\n keymap(this.menuCommandFactory.buildKeymap()),\n this.createMenuStateTrackingPlugin(this.actionBarItems),\n createLinkPlugin(this.handleNewLinkSelection),\n ],\n });\n }\n\n private async updateView(content: string) {\n this.suppressChangeEvent = true;\n const html = await this.contentConverter.parseAsHTML(\n content,\n this.schema,\n );\n const prosemirrorDOMparser = DOMParser.fromSchema(\n this.view.state.schema,\n );\n const domParser = new window.DOMParser();\n const doc = domParser.parseFromString(html, 'text/html');\n const prosemirrorDoc = prosemirrorDOMparser.parse(doc.body);\n const tr = this.view.state.tr;\n tr.replaceWith(0, tr.doc.content.size, prosemirrorDoc.content);\n this.view.dispatch(tr);\n this.suppressChangeEvent = false;\n }\n\n private handleTransaction = (transaction: Transaction) => {\n const newState = this.view.state.apply(transaction);\n this.view.updateState(newState);\n\n if (this.suppressChangeEvent) {\n return;\n }\n\n if (transaction.getMeta('pointer')) {\n return;\n }\n\n this.change.emit(\n this.contentConverter.serialize(this.view, this.schema),\n );\n };\n\n private handleActionBarItem = (\n event: CustomEvent<ActionBarItem<EditorMenuTypes>>,\n ) => {\n event.preventDefault();\n event.stopImmediatePropagation();\n const { value } = event.detail;\n\n if (value === EditorMenuTypes.Link) {\n this.isLinkMenuOpen = true;\n\n return;\n }\n\n try {\n const command = this.menuCommandFactory.getCommand(value);\n this.dispatchMenuCommand(command);\n } catch (error) {\n throw new Error(`Error executing command: ${error}`);\n }\n };\n\n private handleCancelLinkMenu = () => {\n this.isLinkMenuOpen = false;\n };\n\n private handleSaveLinkMenu = () => {\n this.isLinkMenuOpen = false;\n\n try {\n const command = this.menuCommandFactory.getCommand(\n 'link',\n this.link,\n );\n this.dispatchMenuCommand(command);\n } catch (error) {\n throw new Error(`Error executing command: ${error}`);\n }\n\n this.link = { href: '' };\n };\n\n private handleLinkChange = (event: CustomEvent<EditorTextLink>) => {\n this.link = event.detail;\n };\n\n private dispatchMenuCommand(command) {\n const { state } = this.view;\n const selection = state.selection;\n let transaction = state.tr;\n if (!selection.empty) {\n transaction.setSelection(selection);\n }\n\n command(state, (tr) => {\n transaction = tr;\n });\n this.view.dispatch(transaction);\n this.setFocus();\n }\n\n public setFocus() {\n this.view?.focus();\n }\n\n private updateActionBarItems = (\n actionBarItems: Array<ActionBarItem<EditorMenuTypes> | ListSeparator>,\n view: EditorView,\n ) => {\n const updatedItems = cloneDeep(actionBarItems);\n updatedItems.forEach((item) => {\n if (isItem(item)) {\n const command: CommandWithActive =\n this.menuCommandFactory.getCommand(item.value);\n if (command && command.active) {\n item.selected = command.active(view.state);\n } else {\n item.selected = false;\n }\n }\n });\n this.actionBarItems = updatedItems;\n };\n\n private createMenuStateTrackingPlugin = (\n actionBarItems: Array<ActionBarItem<EditorMenuTypes> | ListSeparator>,\n ) => {\n return new Plugin({\n key: this.actionBarPluginKey,\n view: () => ({\n update: (view) => {\n this.updateActionBarItems(actionBarItems, view);\n },\n }),\n });\n };\n\n private handleNewLinkSelection = (text: string, href: string) => {\n this.link.text = text;\n this.link.href = href;\n };\n\n private handleOpenLinkMenu = (\n event: CustomEvent<EditorLinkMenuEventDetail>,\n ) => {\n event.stopImmediatePropagation();\n const { href, text } = event.detail;\n this.link = { href: href, text: text };\n this.isLinkMenuOpen = true;\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"prosemirror-adapter.js","sourceRoot":"","sources":["../../../../src/components/text-editor/prosemirror-adapter/prosemirror-adapter.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Element,\n Event,\n EventEmitter,\n Prop,\n State,\n Watch,\n h,\n} from '@stencil/core';\nimport { EditorState, Plugin, PluginKey, Transaction } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { Schema, DOMParser } from 'prosemirror-model';\nimport { schema } from 'prosemirror-schema-basic';\nimport { addListNodes } from 'prosemirror-schema-list';\nimport { exampleSetup } from 'prosemirror-example-setup';\nimport { keymap } from 'prosemirror-keymap';\nimport { ActionBarItem } from 'src/components/action-bar/action-bar.types';\nimport { ListSeparator } from 'src/components/list/list-item.types';\nimport { CommandWithActive, MenuCommandFactory } from './menu/menu-commands';\nimport { menuTranslationIDs, getTextEditorMenuItems } from './menu/menu-items';\nimport { ContentTypeConverter } from '../utils/content-type-converter';\nimport { markdownConverter } from '../utils/markdown-converter';\nimport { HTMLConverter } from '../utils/html-converter';\nimport { EditorMenuTypes, EditorTextLink } from './menu/types';\nimport translate from 'src/global/translations';\nimport { createRandomString } from 'src/util/random-string';\nimport { isItem } from 'src/components/action-bar/isItem';\nimport { cloneDeep } from 'lodash-es';\nimport { Languages } from '../../date-picker/date.types';\nimport { strikethrough } from './menu/menu-schema-extender';\nimport {\n EditorLinkMenuEventDetail,\n createLinkPlugin,\n} from './plugins/link-plugin';\nimport { createImageRemoverPlugin } from './plugins/image-remover-plugin';\n\n/**\n * The ProseMirror adapter offers a rich text editing experience with markdown support.\n * [Read more...](https://prosemirror.net/)\n *\n * @exampleComponent limel-example-prosemirror-adapter-basic\n * @exampleComponent limel-example-prosemirror-adapter-with-custom-menu\n * @beta\n * @private\n */\n@Component({\n tag: 'limel-prosemirror-adapter',\n shadow: true,\n styleUrl: 'prosemirror-adapter.scss',\n})\nexport class ProsemirrorAdapter {\n /**\n * The type of content that the editor should handle and emit, defaults to `markdown`\n *\n * Assumed to be set only once, so not reactive to changes\n */\n @Prop()\n public contentType: 'markdown' | 'html' = 'markdown';\n\n /**\n * The value of the editor, expected to be markdown\n */\n @Prop()\n public value: string;\n\n /**\n * Defines the language for translations.\n */\n @Prop({ reflect: true })\n public language: Languages;\n\n @Element()\n private host: HTMLLimelTextEditorElement;\n\n private portalId: string;\n\n @State()\n private view: EditorView;\n\n @State()\n private actionBarItems: Array<\n ActionBarItem<EditorMenuTypes> | ListSeparator\n > = [];\n\n @State()\n private link: EditorTextLink = { href: '' };\n\n /**\n * Open state of the dialog\n */\n @State()\n public isLinkMenuOpen: boolean = false;\n\n private menuCommandFactory: MenuCommandFactory;\n private schema: Schema;\n private contentConverter: ContentTypeConverter;\n private suppressChangeEvent = false;\n\n /**\n * Dispatched when a change is made to the editor\n */\n @Event()\n private change: EventEmitter<string>;\n\n constructor() {\n this.portalId = createRandomString();\n }\n\n private actionBarPluginKey = new PluginKey('actionBarPlugin');\n\n @Watch('value')\n protected watchValue(newValue: string) {\n if (\n !this.view ||\n newValue === this.contentConverter.serialize(this.view, this.schema)\n ) {\n return;\n }\n\n this.updateView(newValue);\n }\n\n public componentWillLoad() {\n this.getActionBarItems();\n this.setupContentConverter();\n }\n\n public componentDidLoad() {\n // Stencil complains loudly about triggering rerenders in\n // componentDidLoad, but we have to, so we're using setTimeout to\n // suppress the warning. /Ads\n setTimeout(() => {\n this.initializeTextEditor();\n }, 0);\n\n this.host.addEventListener(\n 'open-editor-link-menu',\n this.handleOpenLinkMenu,\n );\n }\n\n public disconnectedCallback() {\n this.host.removeEventListener(\n 'open-editor-link-menu',\n this.handleOpenLinkMenu,\n );\n this.view.destroy();\n }\n\n public render() {\n return [\n <div id=\"editor\" />,\n <limel-action-bar\n slot=\"trigger\"\n accessibleLabel=\"Toolbar\"\n actions={this.actionBarItems}\n onItemSelected={this.handleActionBarItem}\n />,\n <limel-portal\n containerId={this.portalId}\n visible={this.isLinkMenuOpen}\n openDirection=\"top\"\n inheritParentWidth={true}\n containerStyle={{ 'z-index': 1 }}\n >\n <limel-menu-surface\n open={this.isLinkMenuOpen}\n onDismiss={this.handleCancelLinkMenu}\n style={{\n '--mdc-menu-min-width': '100%',\n 'max-height': 'inherit',\n }}\n >\n <limel-text-editor-link-menu\n link={this.link}\n isOpen={this.isLinkMenuOpen}\n onLinkChange={this.handleLinkChange}\n onCancel={this.handleCancelLinkMenu}\n onSave={this.handleSaveLinkMenu}\n />\n </limel-menu-surface>\n </limel-portal>,\n ];\n }\n\n private setupContentConverter() {\n if (this.contentType === 'markdown') {\n this.contentConverter = new markdownConverter();\n } else if (this.contentType === 'html') {\n this.contentConverter = new HTMLConverter();\n } else {\n throw new Error(\n `Unsupported content type: ${this.contentType}. Only 'markdown' and 'html' are supported.`,\n );\n }\n }\n\n private getActionBarItems = () => {\n this.actionBarItems = getTextEditorMenuItems().map(\n this.getTranslatedItem,\n );\n };\n\n private getTranslatedItem = (item) => {\n const newItem = cloneDeep(item);\n\n if (isItem(item)) {\n const translationId = menuTranslationIDs[item.value];\n\n if (translationId) {\n newItem.text = translate.get(translationId, this.language);\n }\n }\n\n return newItem;\n };\n\n private async initializeTextEditor() {\n this.schema = this.initializeSchema();\n const initialDoc = await this.parseInitialContent();\n this.menuCommandFactory = new MenuCommandFactory(this.schema);\n this.view = new EditorView(\n this.host.shadowRoot.querySelector('#editor'),\n {\n state: this.createEditorState(initialDoc),\n dispatchTransaction: this.handleTransaction,\n },\n );\n\n if (this.value) {\n this.updateView(this.value);\n }\n }\n\n private initializeSchema() {\n return new Schema({\n nodes: addListNodes(schema.spec.nodes, 'paragraph block*', 'block'),\n marks: schema.spec.marks.append({\n strikethrough: strikethrough,\n }),\n });\n }\n\n private async parseInitialContent() {\n const initialContentElement = document.createElement('div');\n\n if (this.value) {\n initialContentElement.innerHTML =\n await this.contentConverter.parseAsHTML(\n this.value,\n this.schema,\n );\n } else {\n initialContentElement.innerHTML = '<p></p>';\n }\n\n return DOMParser.fromSchema(this.schema).parse(initialContentElement);\n }\n\n private createEditorState(initialDoc) {\n return EditorState.create({\n doc: initialDoc,\n plugins: [\n ...exampleSetup({ schema: this.schema, menuBar: false }),\n keymap(this.menuCommandFactory.buildKeymap()),\n this.createMenuStateTrackingPlugin(this.actionBarItems),\n createLinkPlugin(this.handleNewLinkSelection),\n createImageRemoverPlugin(),\n ],\n });\n }\n\n private async updateView(content: string) {\n this.suppressChangeEvent = true;\n const html = await this.contentConverter.parseAsHTML(\n content,\n this.schema,\n );\n const prosemirrorDOMparser = DOMParser.fromSchema(\n this.view.state.schema,\n );\n const domParser = new window.DOMParser();\n const doc = domParser.parseFromString(html, 'text/html');\n const prosemirrorDoc = prosemirrorDOMparser.parse(doc.body);\n const tr = this.view.state.tr;\n tr.replaceWith(0, tr.doc.content.size, prosemirrorDoc.content);\n this.view.dispatch(tr);\n this.suppressChangeEvent = false;\n }\n\n private handleTransaction = (transaction: Transaction) => {\n const newState = this.view.state.apply(transaction);\n this.view.updateState(newState);\n\n if (this.suppressChangeEvent) {\n return;\n }\n\n if (transaction.getMeta('pointer')) {\n return;\n }\n\n this.change.emit(\n this.contentConverter.serialize(this.view, this.schema),\n );\n };\n\n private handleActionBarItem = (\n event: CustomEvent<ActionBarItem<EditorMenuTypes>>,\n ) => {\n event.preventDefault();\n event.stopImmediatePropagation();\n const { value } = event.detail;\n\n if (value === EditorMenuTypes.Link) {\n this.isLinkMenuOpen = true;\n\n return;\n }\n\n try {\n const command = this.menuCommandFactory.getCommand(value);\n this.dispatchMenuCommand(command);\n } catch (error) {\n throw new Error(`Error executing command: ${error}`);\n }\n };\n\n private handleCancelLinkMenu = () => {\n this.isLinkMenuOpen = false;\n };\n\n private handleSaveLinkMenu = () => {\n this.isLinkMenuOpen = false;\n\n try {\n const command = this.menuCommandFactory.getCommand(\n 'link',\n this.link,\n );\n this.dispatchMenuCommand(command);\n } catch (error) {\n throw new Error(`Error executing command: ${error}`);\n }\n\n this.link = { href: '' };\n };\n\n private handleLinkChange = (event: CustomEvent<EditorTextLink>) => {\n this.link = event.detail;\n };\n\n private dispatchMenuCommand(command) {\n const { state } = this.view;\n const selection = state.selection;\n let transaction = state.tr;\n if (!selection.empty) {\n transaction.setSelection(selection);\n }\n\n command(state, (tr) => {\n transaction = tr;\n });\n this.view.dispatch(transaction);\n this.setFocus();\n }\n\n public setFocus() {\n this.view?.focus();\n }\n\n private updateActionBarItems = (\n actionBarItems: Array<ActionBarItem<EditorMenuTypes> | ListSeparator>,\n view: EditorView,\n ) => {\n const updatedItems = cloneDeep(actionBarItems);\n updatedItems.forEach((item) => {\n if (isItem(item)) {\n const command: CommandWithActive =\n this.menuCommandFactory.getCommand(item.value);\n if (command && command.active) {\n item.selected = command.active(view.state);\n } else {\n item.selected = false;\n }\n }\n });\n this.actionBarItems = updatedItems;\n };\n\n private createMenuStateTrackingPlugin = (\n actionBarItems: Array<ActionBarItem<EditorMenuTypes> | ListSeparator>,\n ) => {\n return new Plugin({\n key: this.actionBarPluginKey,\n view: () => ({\n update: (view) => {\n this.updateActionBarItems(actionBarItems, view);\n },\n }),\n });\n };\n\n private handleNewLinkSelection = (text: string, href: string) => {\n this.link.text = text;\n this.link.href = href;\n };\n\n private handleOpenLinkMenu = (\n event: CustomEvent<EditorLinkMenuEventDetail>,\n ) => {\n event.stopImmediatePropagation();\n const { href, text } = event.detail;\n this.link = { href: href, text: text };\n this.isLinkMenuOpen = true;\n };\n}\n"]}
|
|
@@ -25735,17 +25735,18 @@ const processDoubleClickEvent = (view, event) => {
|
|
|
25735
25735
|
}, DOUBLE_CLICK_DELAY);
|
|
25736
25736
|
return true;
|
|
25737
25737
|
};
|
|
25738
|
-
const processPasteEvent = (view, event) => {
|
|
25738
|
+
const processPasteEvent$1 = (view, event) => {
|
|
25739
25739
|
const clipboardData = event.clipboardData;
|
|
25740
25740
|
if (!clipboardData) {
|
|
25741
25741
|
return false;
|
|
25742
25742
|
}
|
|
25743
25743
|
const text = clipboardData.getData('text/plain');
|
|
25744
|
-
if
|
|
25745
|
-
|
|
25744
|
+
// Process as a link if the text is a valid URL
|
|
25745
|
+
if (isValidUrl(text)) {
|
|
25746
|
+
pasteAsLink(view, text);
|
|
25747
|
+
return true;
|
|
25746
25748
|
}
|
|
25747
|
-
|
|
25748
|
-
return true;
|
|
25749
|
+
return false;
|
|
25749
25750
|
};
|
|
25750
25751
|
const pasteAsLink = (view, href) => {
|
|
25751
25752
|
const { state, dispatch } = view;
|
|
@@ -25766,7 +25767,7 @@ const createLinkPlugin = (updateLinkCallback) => {
|
|
|
25766
25767
|
key: linkPluginKey,
|
|
25767
25768
|
props: {
|
|
25768
25769
|
handlePaste: (view, event) => {
|
|
25769
|
-
return processPasteEvent(view, event);
|
|
25770
|
+
return processPasteEvent$1(view, event);
|
|
25770
25771
|
},
|
|
25771
25772
|
handleDOMEvents: {
|
|
25772
25773
|
mousedown: (view, event) => {
|
|
@@ -25786,6 +25787,82 @@ const createLinkPlugin = (updateLinkCallback) => {
|
|
|
25786
25787
|
});
|
|
25787
25788
|
};
|
|
25788
25789
|
|
|
25790
|
+
const pluginKey = new PluginKey('imageRemoverPlugin');
|
|
25791
|
+
const createImageRemoverPlugin = () => {
|
|
25792
|
+
return new Plugin({
|
|
25793
|
+
key: pluginKey,
|
|
25794
|
+
props: {
|
|
25795
|
+
handlePaste: (view, event, slice) => {
|
|
25796
|
+
return processPasteEvent(view, event, slice);
|
|
25797
|
+
},
|
|
25798
|
+
},
|
|
25799
|
+
});
|
|
25800
|
+
};
|
|
25801
|
+
/**
|
|
25802
|
+
* Check if a given ProseMirror node or fragment contains any image nodes.
|
|
25803
|
+
* @param node - The ProseMirror node or fragment to check.
|
|
25804
|
+
* @returns A boolean indicating whether the node contains any image nodes.
|
|
25805
|
+
*/
|
|
25806
|
+
const isImageNode = (node) => {
|
|
25807
|
+
if (node instanceof Node$1) {
|
|
25808
|
+
if (node.type.name === 'image') {
|
|
25809
|
+
return true;
|
|
25810
|
+
}
|
|
25811
|
+
let found = false;
|
|
25812
|
+
node.content.forEach((child) => {
|
|
25813
|
+
if (isImageNode(child)) {
|
|
25814
|
+
found = true;
|
|
25815
|
+
}
|
|
25816
|
+
});
|
|
25817
|
+
return found;
|
|
25818
|
+
}
|
|
25819
|
+
else if (node instanceof Fragment) {
|
|
25820
|
+
let found = false;
|
|
25821
|
+
node.forEach((child) => {
|
|
25822
|
+
if (isImageNode(child)) {
|
|
25823
|
+
found = true;
|
|
25824
|
+
}
|
|
25825
|
+
});
|
|
25826
|
+
return found;
|
|
25827
|
+
}
|
|
25828
|
+
return false;
|
|
25829
|
+
};
|
|
25830
|
+
/**
|
|
25831
|
+
* Filter out image nodes from a ProseMirror fragment.
|
|
25832
|
+
* @param fragment - The ProseMirror fragment to filter.
|
|
25833
|
+
* @returns A new fragment with image nodes removed.
|
|
25834
|
+
*/
|
|
25835
|
+
const filterImageNodes = (fragment) => {
|
|
25836
|
+
const filteredChildren = [];
|
|
25837
|
+
fragment.forEach((child) => {
|
|
25838
|
+
if (!isImageNode(child)) {
|
|
25839
|
+
if (child.content.size > 0) {
|
|
25840
|
+
const filteredContent = filterImageNodes(child.content);
|
|
25841
|
+
const newNode = child.copy(filteredContent);
|
|
25842
|
+
filteredChildren.push(newNode);
|
|
25843
|
+
}
|
|
25844
|
+
else {
|
|
25845
|
+
filteredChildren.push(child);
|
|
25846
|
+
}
|
|
25847
|
+
}
|
|
25848
|
+
});
|
|
25849
|
+
return Fragment.fromArray(filteredChildren);
|
|
25850
|
+
};
|
|
25851
|
+
const processPasteEvent = (view, event, slice) => {
|
|
25852
|
+
const clipboardData = event.clipboardData;
|
|
25853
|
+
if (!clipboardData) {
|
|
25854
|
+
return false;
|
|
25855
|
+
}
|
|
25856
|
+
const filteredSlice = new Slice(filterImageNodes(slice.content), slice.openStart, slice.openEnd);
|
|
25857
|
+
if (filteredSlice.content.childCount < slice.content.childCount) {
|
|
25858
|
+
const { state, dispatch } = view;
|
|
25859
|
+
const tr = state.tr.replaceSelection(filteredSlice);
|
|
25860
|
+
dispatch(tr);
|
|
25861
|
+
return true;
|
|
25862
|
+
}
|
|
25863
|
+
return false;
|
|
25864
|
+
};
|
|
25865
|
+
|
|
25789
25866
|
const prosemirrorAdapterCss = "@charset \"UTF-8\";:host{--mdc-theme-primary:var(\n --lime-primary-color,\n rgb(var(--color-teal-default))\n );--mdc-theme-secondary:var(\n --lime-secondary-color,\n rgb(var(--contrast-1100))\n );--mdc-theme-on-primary:var(\n --lime-on-primary-color,\n rgb(var(--contrast-100))\n );--mdc-theme-on-secondary:var(\n --lime-on-secondary-color,\n rgb(var(--contrast-100))\n );--mdc-theme-text-disabled-on-background:var(\n --lime-text-disabled-on-background-color,\n rgba(var(--contrast-1700), 0.38)\n );--mdc-theme-text-primary-on-background:var(\n --lime-text-primary-on-background-color,\n rgba(var(--contrast-1700), 0.87)\n );--mdc-theme-text-secondary-on-background:var(\n --lime-text-secondary-on-background-color,\n rgba(var(--contrast-1700), 0.54)\n );--mdc-theme-error:var(\n --lime-error-background-color,\n rgb(var(--color-red-dark))\n );--lime-error-text-color:rgb(var(--color-red-darker));--mdc-theme-surface:var(\n --lime-surface-background-color,\n rgb(var(--contrast-100))\n );--mdc-theme-on-surface:var(\n --lime-on-surface-color,\n rgb(var(--contrast-1500))\n )}:host(limel-prosemirror-adapter){display:flex;flex-direction:column}:host(limel-prosemirror-adapter) limel-action-bar{order:1}:host(limel-prosemirror-adapter) div#editor{order:2;height:100%}:host(limel-prosemirror-adapter) div[contenteditable=true]{height:100%}*{box-sizing:border-box}.ProseMirror-menubar-wrapper{display:grid;grid-template-rows:auto 1fr}.ProseMirror-textblock-dropdown{min-width:3em}.ProseMirror-tooltip .ProseMirror-menu{width:-webkit-fit-content;width:fit-content;white-space:pre}limel-action-bar{--action-bar-border-radius:0.25rem;position:sticky;z-index:1;top:1px;background-color:rgba(var(--contrast-200), 0.5);backdrop-filter:blur(0.5rem);-webkit-backdrop-filter:blur(0.5rem);opacity:0.6;transition:opacity 0.5s ease;margin:0 1px;width:calc(100% - 2px)}:host(limel-prosemirror-adapter:focus-within) limel-action-bar,:host(limel-prosemirror-adapter:hover) limel-action-bar{opacity:1}.ProseMirror{position:relative;word-wrap:break-word;white-space:pre-wrap;white-space:break-spaces;-webkit-font-variant-ligatures:none;font-variant-ligatures:none;font-feature-settings:\"liga\" 0;padding:var(--limel-text-editor-padding)}.ProseMirror [draggable][contenteditable=false]{user-select:text}.ProseMirror:focus-visible{outline:none}.ProseMirror-hideselection{caret-color:transparent}.ProseMirror-hideselection *::selection{background:transparent}.ProseMirror-hideselection *::-moz-selection{background:transparent}.ProseMirror-selectednode{outline:0.125rem solid rgb(var(--color-sky-light))}li.ProseMirror-selectednode{outline:none}li.ProseMirror-selectednode:after{content:\"\";position:absolute;left:-2rem;right:-0.125rem;top:-0.125rem;bottom:-0.125rem;border:0.125rem solid rgb(var(--color-sky-light));pointer-events:none}img.ProseMirror-separator{display:inline !important;border:none !important;margin:0 !important}limel-portal{width:25rem}blockquote{position:relative;font-weight:100;font-size:0.875rem;max-width:100%;line-height:1.4;margin:0;padding:0.5rem 1.25rem;border-radius:0.05rem 0.75rem;background-color:rgb(var(--contrast-300))}blockquote:before,blockquote:after{position:absolute;font-size:2.75rem;opacity:0.4}blockquote:before{content:\"“\";left:0;top:-0.75rem}blockquote:after{content:\"”\";right:0;bottom:-2rem}:host(limel-markdown.truncate-paragraphs) p{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}p,li{font-size:0.875rem;word-break:break-word;hyphens:auto;-webkit-hyphens:auto}a{word-break:break-all}p{margin-top:0;margin-bottom:0.5rem}p:only-child{margin-bottom:0}a{transition:color 0.2s ease;color:var(--markdown-hyperlink-color, rgb(var(--color-blue-dark)));text-decoration:none}a:hover{color:var(--markdown-hyperlink-color--hovered, rgb(var(--color-blue-default)))}hr{margin:1.75rem 0 2rem 0;border-width:0;border-top:1px solid rgb(var(--contrast-500))}dl{display:grid;grid-template-columns:1fr 2fr;grid-template-rows:1fr;margin-bottom:2rem;border:1px solid rgb(var(--contrast-400));border-radius:0.375rem;background-color:rgb(var(--contrast-200))}dl dt,dl dd{padding:0.375rem 0.5rem;font-size:0.875rem;margin:0}dl dt:nth-of-type(even),dl dd:nth-of-type(even){background-color:rgb(var(--contrast-300))}dl dt:first-child{border-top-left-radius:0.375rem}dl dt:last-child{border-bottom-left-radius:0.375rem}dl dd:first-child{border-top-right-radius:0.375rem}dl dd:last-child{border-bottom-right-radius:0.375rem}h1{font-size:1.5rem}h2{font-size:1.25rem}h3{font-size:1.125rem}h4{font-size:1rem}h5{font-size:0.875rem}h6{font-size:0.75rem}h1,h2{margin-top:0.5rem;margin-bottom:0.5rem;letter-spacing:-0.03125rem;font-weight:500}h3,h4{margin-top:0.75rem;margin-bottom:0.25rem;font-weight:600}h5,h6{margin-top:0.5rem;margin-bottom:0.125rem;font-weight:600}h1,h2,h3,h4,h5,h6{word-break:break-word;hyphens:auto;-webkit-hyphens:auto}:not([contenteditable=true]) h1,:not([contenteditable=true]) h2,:not([contenteditable=true]) h3,:not([contenteditable=true]) h4,:not([contenteditable=true]) h5,:not([contenteditable=true]) h6{text-wrap:balance}[contenteditable=true] h1,[contenteditable=true] h2,[contenteditable=true] h3,[contenteditable=true] h4,[contenteditable=true] h5,[contenteditable=true] h6{text-wrap:initial}ul{list-style:none}ul li{position:relative;margin-left:0.75rem}ul li:before{content:\"\";position:absolute;left:-0.5rem;top:0.5rem;width:0.25rem;height:0.25rem;border-radius:50%;background-color:rgb(var(--contrast-700));display:block}ol{margin-top:0.25rem;padding-left:1rem}ul{margin-top:0.25rem;padding-left:0}ul ul,ul ol,ol ol,ol ul{margin-left:0}li{margin-bottom:0.25rem}code{font-family:ui-monospace, \"Cascadia Code\", \"Source Code Pro\", Menlo, Consolas, \"DejaVu Sans Mono\", monospace;font-size:0.8125rem;letter-spacing:-0.0125rem;color:rgb(var(--contrast-1300));-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;display:inline-block;border-radius:0.25rem;padding:0.03125rem 0.25rem;background-color:rgb(var(--contrast-600))}pre>code{display:block;margin:0.5rem 0;padding:0.5rem 0.75rem;overflow:auto;white-space:pre-wrap}:host(limel-markdown:not(.no-table-styles)) table{table-layout:auto;min-width:100%;border-collapse:collapse;border-spacing:0;background:transparent;margin:0.75rem 0;border:1px solid rgb(var(--contrast-400))}:host(limel-markdown:not(.no-table-styles)) th,:host(limel-markdown:not(.no-table-styles)) td{text-align:left;vertical-align:top;transition:background-color 0.2s ease;font-size:0.875rem}:host(limel-markdown:not(.no-table-styles)) td{padding:0.5rem 0.375rem 0.75rem 0.375rem}:host(limel-markdown:not(.no-table-styles)) tr th{background-color:rgb(var(--contrast-400));padding:0.25rem 0.375rem;font-weight:normal}:host(limel-markdown:not(.no-table-styles)) tr th:only-child{text-align:center}:host(limel-markdown:not(.no-table-styles)) tbody tr:nth-child(odd) td{background-color:rgb(var(--contrast-200))}:host(limel-markdown:not(.no-table-styles)) tbody tr:hover td{background-color:rgb(var(--contrast-300))}";
|
|
25790
25867
|
|
|
25791
25868
|
const ProsemirrorAdapter = class {
|
|
@@ -25979,6 +26056,7 @@ const ProsemirrorAdapter = class {
|
|
|
25979
26056
|
keymap(this.menuCommandFactory.buildKeymap()),
|
|
25980
26057
|
this.createMenuStateTrackingPlugin(this.actionBarItems),
|
|
25981
26058
|
createLinkPlugin(this.handleNewLinkSelection),
|
|
26059
|
+
createImageRemoverPlugin(),
|
|
25982
26060
|
],
|
|
25983
26061
|
});
|
|
25984
26062
|
}
|