@limetech/lime-elements 38.13.0 → 38.13.2-dev.1
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 +16 -0
- package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js +59 -9
- package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js.map +1 -1
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/inserter.js +59 -9
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/inserter.js.map +1 -1
- package/dist/esm/limel-prosemirror-adapter.entry.js +59 -9
- 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-587f6b6d.entry.js → p-d5ac8f59.entry.js} +2 -2
- package/dist/lime-elements/p-d5ac8f59.entry.js.map +1 -0
- package/package.json +1 -1
- package/dist/lime-elements/p-587f6b6d.entry.js.map +0 -1
package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/inserter.js
CHANGED
|
@@ -132,9 +132,29 @@ const processPasteEvent = (view, event, slice) => {
|
|
|
132
132
|
if (!clipboardData) {
|
|
133
133
|
return false;
|
|
134
134
|
}
|
|
135
|
+
const isImageFilePasted = handlePastedImages(view, clipboardData);
|
|
136
|
+
const filteredSlice = new Slice(filterImageNodes(slice.content), slice.openStart, slice.openEnd);
|
|
137
|
+
if (filteredSlice.content.childCount < slice.content.childCount) {
|
|
138
|
+
const { state, dispatch } = view;
|
|
139
|
+
const tr = state.tr.replaceSelection(filteredSlice);
|
|
140
|
+
dispatch(tr);
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
return isImageFilePasted;
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Processes any image files found in the clipboard data and dispatches an imagePasted event.
|
|
147
|
+
*
|
|
148
|
+
* @param view - The ProseMirror editor view
|
|
149
|
+
* @param clipboardData - The clipboard data transfer object containing potential image files
|
|
150
|
+
* @returns True if at least one valid image file was found and processed, false otherwise
|
|
151
|
+
*/
|
|
152
|
+
function handlePastedImages(view, clipboardData) {
|
|
153
|
+
let isImageFilePasted = false;
|
|
135
154
|
const files = Array.from(clipboardData.files || []);
|
|
136
155
|
for (const file of files) {
|
|
137
|
-
if (file
|
|
156
|
+
if (isImageFile(file, clipboardData)) {
|
|
157
|
+
isImageFilePasted = true;
|
|
138
158
|
const reader = new FileReader();
|
|
139
159
|
reader.onloadend = () => {
|
|
140
160
|
view.dom.dispatchEvent(new CustomEvent('imagePasted', {
|
|
@@ -144,13 +164,43 @@ const processPasteEvent = (view, event, slice) => {
|
|
|
144
164
|
reader.readAsDataURL(file);
|
|
145
165
|
}
|
|
146
166
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
167
|
+
return isImageFilePasted;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Determines if a file is an image that should be processed by the image handler.
|
|
171
|
+
*
|
|
172
|
+
* This function checks both the file's MIME type and the clipboard HTML content.
|
|
173
|
+
* It filters out HTML content from Excel and HTML tables, as they are not relevant for image processing.
|
|
174
|
+
*
|
|
175
|
+
* @param file - The file object to check
|
|
176
|
+
* @param clipboardData - The full clipboard data transfer object to examine for context
|
|
177
|
+
* @returns True if the file is an image that should be processed, false otherwise
|
|
178
|
+
*/
|
|
179
|
+
function isImageFile(file, clipboardData) {
|
|
180
|
+
var _a, _b;
|
|
181
|
+
if (!isContentTypeImage(file)) {
|
|
182
|
+
return false;
|
|
153
183
|
}
|
|
154
|
-
|
|
155
|
-
|
|
184
|
+
const html = (_b = (_a = clipboardData === null || clipboardData === void 0 ? void 0 : clipboardData.getData('text/html')) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : '';
|
|
185
|
+
return !isHtmlFromExcel(html) && !isHtmlTable(html);
|
|
186
|
+
}
|
|
187
|
+
function isContentTypeImage(file) {
|
|
188
|
+
if (!(file === null || file === void 0 ? void 0 : file.type)) {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
return file.type.startsWith('image/');
|
|
192
|
+
}
|
|
193
|
+
function isHtmlFromExcel(html) {
|
|
194
|
+
if (!html) {
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
return (html.includes('name=generator content="microsoft excel"') ||
|
|
198
|
+
html.includes('xmlns:x="urn:schemas-microsoft-com:office:excel"'));
|
|
199
|
+
}
|
|
200
|
+
function isHtmlTable(html) {
|
|
201
|
+
if (!html) {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
return html.includes('<table');
|
|
205
|
+
}
|
|
156
206
|
//# sourceMappingURL=inserter.js.map
|
package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/inserter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inserter.js","sourceRoot":"","sources":["../../../../../../src/components/text-editor/prosemirror-adapter/plugins/image/inserter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAG3D,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG1D,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,qBAAqB,CAAC,CAAC;AAI9D,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACrC,mBAAwC,EAC1C,EAAE;EACA,OAAO,IAAI,MAAM,CAAC;IACd,GAAG,EAAE,SAAS;IACd,KAAK,EAAE;MACH,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAChC,OAAO,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;MACjD,CAAC;MACD,eAAe,EAAE;QACb,WAAW,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE;UACtB,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACtC,CAAC;OACJ;KACJ;GACJ,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAChC,IAAgB,EAChB,UAAkB,EAClB,QAAkB,EACL,EAAE;EACf,OAAO;IACH,QAAQ,EAAE,QAAQ;IAClB,eAAe,EAAE,uBAAuB,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC;IACpE,WAAW,EAAE,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC;IAChD,qBAAqB,EAAE,6BAA6B,CAAC,IAAI,EAAE,QAAQ,CAAC;GACvE,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,uBAAuB,GACzB,CAAC,IAAgB,EAAE,UAAkB,EAAE,QAAkB,EAAE,EAAE,CAAC,GAAG,EAAE;EAC/D,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;EACjC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;EAEzB,MAAM,cAAc,GAAG,oBAAoB,CACvC,UAAU,EACV,QAAQ,EACR,SAAS,CACZ,CAAC;EACF,MAAM,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;EAElE,MAAM,WAAW,GAAG,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAAC,eAAe,CAAC,CAAC;EAEnE,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC1B,CAAC,CAAC;AAEN,MAAM,mBAAmB,GACrB,CAAC,IAAgB,EAAE,QAAkB,EAAE,EAAE,CAAC,CAAC,GAAY,EAAE,EAAE;EACvD,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;EACjC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;EAEzB,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;EACpB,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IAChC,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,KAAK,QAAQ,CAAC,EAAE,EAAE;MACvC,MAAM,cAAc,GAAG,oBAAoB,CACvC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAC1B,QAAQ,EACR,SAAS,CACZ,CAAC;MACF,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;MAE5D,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;MAEpD,OAAO,KAAK,CAAC;KAChB;EACL,CAAC,CAAC,CAAC;EAEH,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjB,CAAC,CAAC;AAEN,MAAM,6BAA6B,GAC/B,CAAC,IAAgB,EAAE,QAAkB,EAAE,EAAE,CAAC,GAAG,EAAE;EAC3C,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;EACjC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;EAEzB,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;EACpB,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IAChC,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,KAAK,QAAQ,CAAC,EAAE,EAAE;MACvC,MAAM,cAAc,GAAG,oBAAoB,CACvC,IAAI,CAAC,KAAK,CAAC,GAAG,EACd,QAAQ,EACR,QAAQ,CACX,CAAC;MACF,MAAM,oBAAoB,GACtB,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;MAE9C,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;MAE/D,OAAO,KAAK,CAAC;KAChB;EACL,CAAC,CAAC,CAAC;EAEH,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjB,CAAC,CAAC;AAEN,SAAS,oBAAoB,CACzB,GAAW,EACX,QAAkB,EAClB,KAAuB;EAEvB,OAAO;IACH,GAAG,EAAE,GAAG;IACR,GAAG,EAAE,QAAQ,CAAC,QAAQ;IACtB,UAAU,EAAE,QAAQ,CAAC,EAAE;IACvB,KAAK,EAAE,KAAK;GACf,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,MAAM,WAAW,GAAG,CAAC,IAAqB,EAAW,EAAE;EACnD,IAAI,IAAI,YAAY,IAAI,EAAE;IACtB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE;MAC5B,OAAO,IAAI,CAAC;KACf;IAED,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;MAC3B,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE;QACpB,KAAK,GAAG,IAAI,CAAC;OAChB;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;GAChB;OAAM,IAAI,IAAI,YAAY,QAAQ,EAAE;IACjC,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;MACnB,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE;QACpB,KAAK,GAAG,IAAI,CAAC;OAChB;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;GAChB;EAED,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,gBAAgB,GAAG,CAAC,QAAkB,EAAY,EAAE;EACtD,MAAM,gBAAgB,GAAW,EAAE,CAAC;EAEpC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;IACvB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE;MACrB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE;QACxB,MAAM,eAAe,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACxD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC5C,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;OAClC;WAAM;QACH,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;OAChC;KACJ;EACL,CAAC,CAAC,CAAC;EAEH,OAAO,QAAQ,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;AAChD,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,iBAAiB,GAAG,CACtB,IAAgB,EAChB,KAAqB,EACrB,KAAY,EACL,EAAE;EACT,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;EAC1C,IAAI,CAAC,aAAa,EAAE;IAChB,OAAO,KAAK,CAAC;GAChB;EAED,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;EACpD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;IACtB,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;MAChC,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;MAChC,MAAM,CAAC,SAAS,GAAG,GAAG,EAAE;QACpB,IAAI,CAAC,GAAG,CAAC,aAAa,CAClB,IAAI,WAAW,CAAC,aAAa,EAAE;UAC3B,MAAM,EAAE,oBAAoB,CACxB,IAAI,EACJ,MAAM,CAAC,MAAgB,EACvB,cAAc,CAAC,IAAI,CAAC,CACvB;SACJ,CAAC,CACL,CAAC;MACN,CAAC,CAAC;MAEF,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;KAC9B;GACJ;EAED,MAAM,aAAa,GAAG,IAAI,KAAK,CAC3B,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,EAC/B,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,OAAO,CAChB,CAAC;EAEF,IAAI,aAAa,CAAC,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE;IAC7D,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IACjC,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACpD,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEb,OAAO,IAAI,CAAC;GACf;EAED,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AAC5B,CAAC,CAAC","sourcesContent":["import { Plugin, PluginKey } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { createFileInfo } from '../../../../../util/files';\nimport { FileInfo } from '../../../../../global/shared-types/file.types';\nimport { ImageInserter, EditorImageState } from '../../../text-editor.types';\nimport { Node, Slice, Fragment } from 'prosemirror-model';\nimport { ImageNodeAttrs } from './node';\n\nexport const pluginKey = new PluginKey('imageInserterPlugin');\n\ntype ImagePastedCallback = (data: ImageInserter) => CustomEvent<ImageInserter>;\n\nexport const createImageInserterPlugin = (\n imagePastedCallback: ImagePastedCallback,\n) => {\n return new Plugin({\n key: pluginKey,\n props: {\n handlePaste: (view, event, slice) => {\n return processPasteEvent(view, event, slice);\n },\n handleDOMEvents: {\n imagePasted: (_, event) => {\n imagePastedCallback(event.detail);\n },\n },\n },\n });\n};\n\nexport const imageInserterFactory = (\n view: EditorView,\n base64Data: string,\n fileInfo: FileInfo,\n): ImageInserter => {\n return {\n fileInfo: fileInfo,\n insertThumbnail: createThumbnailInserter(view, base64Data, fileInfo),\n insertImage: createImageInserter(view, fileInfo),\n insertFailedThumbnail: createFailedThumbnailInserter(view, fileInfo),\n };\n};\n\nconst createThumbnailInserter =\n (view: EditorView, base64Data: string, fileInfo: FileInfo) => () => {\n const { state, dispatch } = view;\n const { schema } = state;\n\n const imageNodeAttrs = createImageNodeAttrs(\n base64Data,\n fileInfo,\n 'loading',\n );\n const placeholderNode = schema.nodes.image.create(imageNodeAttrs);\n\n const transaction = state.tr.replaceSelectionWith(placeholderNode);\n\n dispatch(transaction);\n };\n\nconst createImageInserter =\n (view: EditorView, fileInfo: FileInfo) => (src?: string) => {\n const { state, dispatch } = view;\n const { schema } = state;\n\n const tr = state.tr;\n state.doc.descendants((node, pos) => {\n if (node.attrs.fileInfoId === fileInfo.id) {\n const imageNodeAttrs = createImageNodeAttrs(\n src ? src : node.attrs.src,\n fileInfo,\n 'success',\n );\n const imageNode = schema.nodes.image.create(imageNodeAttrs);\n\n tr.replaceWith(pos, pos + node.nodeSize, imageNode);\n\n return false;\n }\n });\n\n dispatch(tr);\n };\n\nconst createFailedThumbnailInserter =\n (view: EditorView, fileInfo: FileInfo) => () => {\n const { state, dispatch } = view;\n const { schema } = state;\n\n const tr = state.tr;\n state.doc.descendants((node, pos) => {\n if (node.attrs.fileInfoId === fileInfo.id) {\n const imageNodeAttrs = createImageNodeAttrs(\n node.attrs.src,\n fileInfo,\n 'failed',\n );\n const errorPlaceholderNode =\n schema.nodes.image.create(imageNodeAttrs);\n\n tr.replaceWith(pos, pos + node.nodeSize, errorPlaceholderNode);\n\n return false;\n }\n });\n\n dispatch(tr);\n };\n\nfunction createImageNodeAttrs(\n src: string,\n fileInfo: FileInfo,\n state: EditorImageState,\n): ImageNodeAttrs {\n return {\n src: src,\n alt: fileInfo.filename,\n fileInfoId: fileInfo.id,\n state: state,\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\n/**\n * Process a paste event and trigger an imagePasted event if an image file is pasted.\n * If an HTML image element is pasted, this image is filtered out from the slice content.\n *\n * @param view - The ProseMirror editor view.\n * @param event - The paste event.\n * @returns A boolean; True if an image file was pasted to prevent default paste behavior, otherwise false.\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 files = Array.from(clipboardData.files || []);\n for (const file of files) {\n if (file.type.startsWith('image/')) {\n const reader = new FileReader();\n reader.onloadend = () => {\n view.dom.dispatchEvent(\n new CustomEvent('imagePasted', {\n detail: imageInserterFactory(\n view,\n reader.result as string,\n createFileInfo(file),\n ),\n }),\n );\n };\n\n reader.readAsDataURL(file);\n }\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 files.length > 0;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"inserter.js","sourceRoot":"","sources":["../../../../../../src/components/text-editor/prosemirror-adapter/plugins/image/inserter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Plugin, PluginKey } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { createFileInfo } from '../../../../../util/files';\nimport { FileInfo } from '../../../../../global/shared-types/file.types';\nimport { ImageInserter, EditorImageState } from '../../../text-editor.types';\nimport { Node, Slice, Fragment } from 'prosemirror-model';\nimport { ImageNodeAttrs } from './node';\n\nexport const pluginKey = new PluginKey('imageInserterPlugin');\n\ntype ImagePastedCallback = (data: ImageInserter) => CustomEvent<ImageInserter>;\n\nexport const createImageInserterPlugin = (\n imagePastedCallback: ImagePastedCallback,\n) => {\n return new Plugin({\n key: pluginKey,\n props: {\n handlePaste: (view, event, slice) => {\n return processPasteEvent(view, event, slice);\n },\n handleDOMEvents: {\n imagePasted: (_, event) => {\n imagePastedCallback(event.detail);\n },\n },\n },\n });\n};\n\nexport const imageInserterFactory = (\n view: EditorView,\n base64Data: string,\n fileInfo: FileInfo,\n): ImageInserter => {\n return {\n fileInfo: fileInfo,\n insertThumbnail: createThumbnailInserter(view, base64Data, fileInfo),\n insertImage: createImageInserter(view, fileInfo),\n insertFailedThumbnail: createFailedThumbnailInserter(view, fileInfo),\n };\n};\n\nconst createThumbnailInserter =\n (view: EditorView, base64Data: string, fileInfo: FileInfo) => () => {\n const { state, dispatch } = view;\n const { schema } = state;\n\n const imageNodeAttrs = createImageNodeAttrs(\n base64Data,\n fileInfo,\n 'loading',\n );\n const placeholderNode = schema.nodes.image.create(imageNodeAttrs);\n\n const transaction = state.tr.replaceSelectionWith(placeholderNode);\n\n dispatch(transaction);\n };\n\nconst createImageInserter =\n (view: EditorView, fileInfo: FileInfo) => (src?: string) => {\n const { state, dispatch } = view;\n const { schema } = state;\n\n const tr = state.tr;\n state.doc.descendants((node, pos) => {\n if (node.attrs.fileInfoId === fileInfo.id) {\n const imageNodeAttrs = createImageNodeAttrs(\n src ? src : node.attrs.src,\n fileInfo,\n 'success',\n );\n const imageNode = schema.nodes.image.create(imageNodeAttrs);\n\n tr.replaceWith(pos, pos + node.nodeSize, imageNode);\n\n return false;\n }\n });\n\n dispatch(tr);\n };\n\nconst createFailedThumbnailInserter =\n (view: EditorView, fileInfo: FileInfo) => () => {\n const { state, dispatch } = view;\n const { schema } = state;\n\n const tr = state.tr;\n state.doc.descendants((node, pos) => {\n if (node.attrs.fileInfoId === fileInfo.id) {\n const imageNodeAttrs = createImageNodeAttrs(\n node.attrs.src,\n fileInfo,\n 'failed',\n );\n const errorPlaceholderNode =\n schema.nodes.image.create(imageNodeAttrs);\n\n tr.replaceWith(pos, pos + node.nodeSize, errorPlaceholderNode);\n\n return false;\n }\n });\n\n dispatch(tr);\n };\n\nfunction createImageNodeAttrs(\n src: string,\n fileInfo: FileInfo,\n state: EditorImageState,\n): ImageNodeAttrs {\n return {\n src: src,\n alt: fileInfo.filename,\n fileInfoId: fileInfo.id,\n state: state,\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\n/**\n * Process a paste event and trigger an imagePasted event if an image file is pasted.\n * If an HTML image element is pasted, this image is filtered out from the slice content.\n *\n * @param view - The ProseMirror editor view.\n * @param event - The paste event.\n * @returns A boolean; True if an image file was pasted to prevent default paste behavior, otherwise false.\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 isImageFilePasted = handlePastedImages(view, clipboardData);\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 isImageFilePasted;\n};\n\n/**\n * Processes any image files found in the clipboard data and dispatches an imagePasted event.\n *\n * @param view - The ProseMirror editor view\n * @param clipboardData - The clipboard data transfer object containing potential image files\n * @returns True if at least one valid image file was found and processed, false otherwise\n */\nfunction handlePastedImages(\n view: EditorView,\n clipboardData: DataTransfer,\n): boolean {\n let isImageFilePasted = false;\n const files = Array.from(clipboardData.files || []);\n\n for (const file of files) {\n if (isImageFile(file, clipboardData)) {\n isImageFilePasted = true;\n\n const reader = new FileReader();\n reader.onloadend = () => {\n view.dom.dispatchEvent(\n new CustomEvent('imagePasted', {\n detail: imageInserterFactory(\n view,\n reader.result as string,\n createFileInfo(file),\n ),\n }),\n );\n };\n\n reader.readAsDataURL(file);\n }\n }\n\n return isImageFilePasted;\n}\n\n/**\n * Determines if a file is an image that should be processed by the image handler.\n *\n * This function checks both the file's MIME type and the clipboard HTML content.\n * It filters out HTML content from Excel and HTML tables, as they are not relevant for image processing.\n *\n * @param file - The file object to check\n * @param clipboardData - The full clipboard data transfer object to examine for context\n * @returns True if the file is an image that should be processed, false otherwise\n */\nfunction isImageFile(file: File, clipboardData: DataTransfer): boolean {\n if (!isContentTypeImage(file)) {\n return false;\n }\n\n const html = clipboardData?.getData('text/html')?.toLowerCase() ?? '';\n\n return !isHtmlFromExcel(html) && !isHtmlTable(html);\n}\n\nfunction isContentTypeImage(file: File): boolean {\n if (!file?.type) {\n return false;\n }\n\n return file.type.startsWith('image/');\n}\n\nfunction isHtmlFromExcel(html: string): boolean {\n if (!html) {\n return false;\n }\n\n return (\n html.includes('name=generator content=\"microsoft excel\"') ||\n html.includes('xmlns:x=\"urn:schemas-microsoft-com:office:excel\"')\n );\n}\n\nfunction isHtmlTable(html: string): boolean {\n if (!html) {\n return false;\n }\n\n return html.includes('<table');\n}\n"]}
|
|
@@ -26454,9 +26454,29 @@ const processPasteEvent = (view, event, slice) => {
|
|
|
26454
26454
|
if (!clipboardData) {
|
|
26455
26455
|
return false;
|
|
26456
26456
|
}
|
|
26457
|
+
const isImageFilePasted = handlePastedImages(view, clipboardData);
|
|
26458
|
+
const filteredSlice = new Slice(filterImageNodes(slice.content), slice.openStart, slice.openEnd);
|
|
26459
|
+
if (filteredSlice.content.childCount < slice.content.childCount) {
|
|
26460
|
+
const { state, dispatch } = view;
|
|
26461
|
+
const tr = state.tr.replaceSelection(filteredSlice);
|
|
26462
|
+
dispatch(tr);
|
|
26463
|
+
return true;
|
|
26464
|
+
}
|
|
26465
|
+
return isImageFilePasted;
|
|
26466
|
+
};
|
|
26467
|
+
/**
|
|
26468
|
+
* Processes any image files found in the clipboard data and dispatches an imagePasted event.
|
|
26469
|
+
*
|
|
26470
|
+
* @param view - The ProseMirror editor view
|
|
26471
|
+
* @param clipboardData - The clipboard data transfer object containing potential image files
|
|
26472
|
+
* @returns True if at least one valid image file was found and processed, false otherwise
|
|
26473
|
+
*/
|
|
26474
|
+
function handlePastedImages(view, clipboardData) {
|
|
26475
|
+
let isImageFilePasted = false;
|
|
26457
26476
|
const files = Array.from(clipboardData.files || []);
|
|
26458
26477
|
for (const file of files) {
|
|
26459
|
-
if (file
|
|
26478
|
+
if (isImageFile(file, clipboardData)) {
|
|
26479
|
+
isImageFilePasted = true;
|
|
26460
26480
|
const reader = new FileReader();
|
|
26461
26481
|
reader.onloadend = () => {
|
|
26462
26482
|
view.dom.dispatchEvent(new CustomEvent('imagePasted', {
|
|
@@ -26466,15 +26486,45 @@ const processPasteEvent = (view, event, slice) => {
|
|
|
26466
26486
|
reader.readAsDataURL(file);
|
|
26467
26487
|
}
|
|
26468
26488
|
}
|
|
26469
|
-
|
|
26470
|
-
|
|
26471
|
-
|
|
26472
|
-
|
|
26473
|
-
|
|
26474
|
-
|
|
26489
|
+
return isImageFilePasted;
|
|
26490
|
+
}
|
|
26491
|
+
/**
|
|
26492
|
+
* Determines if a file is an image that should be processed by the image handler.
|
|
26493
|
+
*
|
|
26494
|
+
* This function checks both the file's MIME type and the clipboard HTML content.
|
|
26495
|
+
* It filters out HTML content from Excel and HTML tables, as they are not relevant for image processing.
|
|
26496
|
+
*
|
|
26497
|
+
* @param file - The file object to check
|
|
26498
|
+
* @param clipboardData - The full clipboard data transfer object to examine for context
|
|
26499
|
+
* @returns True if the file is an image that should be processed, false otherwise
|
|
26500
|
+
*/
|
|
26501
|
+
function isImageFile(file, clipboardData) {
|
|
26502
|
+
var _a, _b;
|
|
26503
|
+
if (!isContentTypeImage(file)) {
|
|
26504
|
+
return false;
|
|
26475
26505
|
}
|
|
26476
|
-
|
|
26477
|
-
|
|
26506
|
+
const html = (_b = (_a = clipboardData === null || clipboardData === void 0 ? void 0 : clipboardData.getData('text/html')) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : '';
|
|
26507
|
+
return !isHtmlFromExcel(html) && !isHtmlTable(html);
|
|
26508
|
+
}
|
|
26509
|
+
function isContentTypeImage(file) {
|
|
26510
|
+
if (!(file === null || file === void 0 ? void 0 : file.type)) {
|
|
26511
|
+
return false;
|
|
26512
|
+
}
|
|
26513
|
+
return file.type.startsWith('image/');
|
|
26514
|
+
}
|
|
26515
|
+
function isHtmlFromExcel(html) {
|
|
26516
|
+
if (!html) {
|
|
26517
|
+
return false;
|
|
26518
|
+
}
|
|
26519
|
+
return (html.includes('name=generator content="microsoft excel"') ||
|
|
26520
|
+
html.includes('xmlns:x="urn:schemas-microsoft-com:office:excel"'));
|
|
26521
|
+
}
|
|
26522
|
+
function isHtmlTable(html) {
|
|
26523
|
+
if (!html) {
|
|
26524
|
+
return false;
|
|
26525
|
+
}
|
|
26526
|
+
return html.includes('<table');
|
|
26527
|
+
}
|
|
26478
26528
|
|
|
26479
26529
|
const MIN_WIDTH = 10;
|
|
26480
26530
|
const createImageViewPlugin = (language) => {
|