@harbour-enterprises/superdoc 0.12.37-next.1 → 0.12.37-next.2

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.
Files changed (32) hide show
  1. package/dist/chunks/{super-editor.es-DmBtUqwe.cjs → super-editor.es-3IGIxgjF.cjs} +376 -148
  2. package/dist/chunks/{super-editor.es-DYzhjqc5.es.js → super-editor.es-WrgX5vxB.es.js} +376 -148
  3. package/dist/style.css +76 -0
  4. package/dist/super-editor/ai-writer.es.js +2 -2
  5. package/dist/super-editor/chunks/{converter-ffnCghzo.js → converter-RpLHCUPf.js} +2 -2
  6. package/dist/super-editor/chunks/{docx-zipper-BvIz98Bh.js → docx-zipper-V5sLSr7T.js} +1 -1
  7. package/dist/super-editor/chunks/{editor-BCC23g3q.js → editor-CAT1dxaK.js} +379 -16
  8. package/dist/super-editor/chunks/{toolbar-BZxPbO0T.js → toolbar-Cts0XR5V.js} +2 -2
  9. package/dist/super-editor/converter.es.js +1 -1
  10. package/dist/super-editor/docx-zipper.es.js +2 -2
  11. package/dist/super-editor/editor.es.js +3 -3
  12. package/dist/super-editor/extensions/image/imageHelpers/imagePositionPlugin.d.ts.map +1 -1
  13. package/dist/super-editor/extensions/image/imageHelpers/index.d.ts +1 -0
  14. package/dist/super-editor/extensions/image/imageHelpers/processUploadedImage.d.ts.map +1 -1
  15. package/dist/super-editor/extensions/image/index.d.ts +1 -0
  16. package/dist/super-editor/extensions/index.d.ts +2 -1
  17. package/dist/super-editor/extensions/index.d.ts.map +1 -1
  18. package/dist/super-editor/extensions/noderesizer/index.d.ts +2 -0
  19. package/dist/super-editor/extensions/noderesizer/index.d.ts.map +1 -0
  20. package/dist/super-editor/extensions/noderesizer/noderesizer.d.ts +7 -0
  21. package/dist/super-editor/extensions/noderesizer/noderesizer.d.ts.map +1 -0
  22. package/dist/super-editor/file-zipper.es.js +1 -1
  23. package/dist/super-editor/style.css +76 -0
  24. package/dist/super-editor/super-editor.es.js +7 -141
  25. package/dist/super-editor/toolbar.es.js +2 -2
  26. package/dist/super-editor.cjs +1 -1
  27. package/dist/super-editor.es.js +1 -1
  28. package/dist/superdoc.cjs +2 -2
  29. package/dist/superdoc.es.js +3 -3
  30. package/dist/superdoc.umd.js +376 -148
  31. package/dist/superdoc.umd.js.map +1 -1
  32. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
- const Y = require("yjs");
3
2
  const vue = require("./vue-HIY1g7dm.cjs");
3
+ const Y = require("yjs");
4
4
  function _interopNamespaceDefault(e) {
5
5
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
6
6
  if (e) {
@@ -23410,7 +23410,7 @@ const _SuperConverter = class _SuperConverter2 {
23410
23410
  return;
23411
23411
  }
23412
23412
  }
23413
- static updateDocumentVersion(docx = this.convertedXml, version2 = "0.12.37-next.1") {
23413
+ static updateDocumentVersion(docx = this.convertedXml, version2 = "0.12.37-next.2") {
23414
23414
  const customLocation = "docProps/custom.xml";
23415
23415
  if (!docx[customLocation]) {
23416
23416
  docx[customLocation] = generateCustomXml();
@@ -23877,7 +23877,7 @@ function storeSuperdocVersion(docx) {
23877
23877
  function generateCustomXml() {
23878
23878
  return DEFAULT_CUSTOM_XML;
23879
23879
  }
23880
- function generateSuperdocVersion(pid = 2, version2 = "0.12.37-next.1") {
23880
+ function generateSuperdocVersion(pid = 2, version2 = "0.12.37-next.2") {
23881
23881
  return {
23882
23882
  type: "element",
23883
23883
  name: "property",
@@ -41254,7 +41254,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
41254
41254
  * @returns {Object | void} Migration results
41255
41255
  */
41256
41256
  processCollaborationMigrations() {
41257
- console.debug("[checkVersionMigrations] Current editor version", "0.12.37-next.1");
41257
+ console.debug("[checkVersionMigrations] Current editor version", "0.12.37-next.2");
41258
41258
  if (!this.options.ydoc) return;
41259
41259
  const metaMap = this.options.ydoc.getMap("meta");
41260
41260
  let docVersion = metaMap.get("version");
@@ -48637,10 +48637,7 @@ const ImagePositionPlugin = ({ editor }) => {
48637
48637
  if (shouldUpdate) {
48638
48638
  shouldUpdate = false;
48639
48639
  const decorations = getImagePositionDecorations(lastState, view3);
48640
- const updateTransaction = view3.state.tr.setMeta(
48641
- ImagePositionPluginKey,
48642
- { decorations }
48643
- );
48640
+ const updateTransaction = view3.state.tr.setMeta(ImagePositionPluginKey, { decorations });
48644
48641
  view3.dispatch(updateTransaction);
48645
48642
  }
48646
48643
  if (pagination?.isReadyToInit) {
@@ -48772,16 +48769,16 @@ const Image = Node$1.create({
48772
48769
  default: {},
48773
48770
  renderDOM: ({ size: size2 }) => {
48774
48771
  let style2 = "";
48775
- let { width, height } = size2 ?? {};
48772
+ const { width, height } = size2 ?? {};
48776
48773
  if (width) style2 += `width: ${width}px;`;
48777
- if (height) style2 += `height: auto;`;
48774
+ if (height) style2 += "height: auto;";
48778
48775
  return { style: style2 };
48779
48776
  }
48780
48777
  },
48781
48778
  padding: {
48782
48779
  default: {},
48783
48780
  renderDOM: ({ padding, marginOffset }) => {
48784
- let { left: left2 = 0, top: top2 = 0, bottom: bottom2 = 0, right: right2 = 0 } = padding ?? {};
48781
+ const { left: left2 = 0, top: top2 = 0, bottom: bottom2 = 0, right: right2 = 0 } = padding ?? {};
48785
48782
  let style2 = "";
48786
48783
  if (left2 && !marginOffset?.left) style2 += `margin-left: ${left2}px;`;
48787
48784
  if (top2 && !marginOffset?.top) style2 += `margin-top: ${top2}px;`;
@@ -48793,7 +48790,7 @@ const Image = Node$1.create({
48793
48790
  marginOffset: {
48794
48791
  default: {},
48795
48792
  renderDOM: ({ marginOffset }) => {
48796
- let { left: left2 = 0, top: top2 = 0 } = marginOffset ?? {};
48793
+ const { left: left2 = 0, top: top2 = 0 } = marginOffset ?? {};
48797
48794
  let style2 = "";
48798
48795
  if (left2) style2 += `margin-left: ${left2}px;`;
48799
48796
  if (top2) style2 += `margin-top: ${top2}px;`;
@@ -48834,6 +48831,136 @@ const Image = Node$1.create({
48834
48831
  return [ImagePlaceholderPlugin(), ImagePositionPlugin({ editor: this.editor })];
48835
48832
  }
48836
48833
  });
48834
+ const ACCEPT_IMAGE_TYPES = [".jpg", ".jpeg", ".png", "image/jpeg", "image/png"];
48835
+ const getFileOpener = () => {
48836
+ let fileInput = document.createElement("input");
48837
+ fileInput.type = "file";
48838
+ let acceptTypes = ACCEPT_IMAGE_TYPES;
48839
+ fileInput.accept = acceptTypes.join(",");
48840
+ const openFile = () => {
48841
+ return new Promise((resolve, reject) => {
48842
+ fileInput.onchange = async () => {
48843
+ const files = fileInput.files;
48844
+ if (!files) return resolve(null);
48845
+ const file = files.item(0);
48846
+ if (!file) return resolve(null);
48847
+ return resolve({ file });
48848
+ };
48849
+ fileInput.oncancel = () => resolve(null);
48850
+ fileInput.onerror = reject;
48851
+ fileInput.click();
48852
+ });
48853
+ };
48854
+ return openFile;
48855
+ };
48856
+ const handleImageUpload = (file) => {
48857
+ return new Promise((resolve, reject) => {
48858
+ let reader = new FileReader();
48859
+ reader.onload = (event) => resolve(event.target.result);
48860
+ reader.onerror = reject;
48861
+ setTimeout(() => reader.readAsDataURL(file), 250);
48862
+ });
48863
+ };
48864
+ const processUploadedImage = (fileData, editor) => {
48865
+ return new Promise((resolve, reject) => {
48866
+ const img = new window.Image();
48867
+ img.onload = () => {
48868
+ const canvas = document.createElement("canvas");
48869
+ const { width, height } = getAllowedImageDimensions(img.width, img.height, editor);
48870
+ canvas.width = width;
48871
+ canvas.height = height;
48872
+ const ctx2 = canvas.getContext("2d");
48873
+ ctx2.drawImage(img, 0, 0, width, height);
48874
+ if (typeof fileData === "string") {
48875
+ const resizedBase64 = canvas.toDataURL();
48876
+ resolve(resizedBase64);
48877
+ } else {
48878
+ canvas.toBlob((blob) => {
48879
+ const updatedFile = new File([blob], fileData.name, {
48880
+ type: fileData.type,
48881
+ lastModified: Date.now()
48882
+ });
48883
+ resolve({ file: updatedFile, width, height });
48884
+ });
48885
+ }
48886
+ };
48887
+ img.onerror = (error) => reject(error);
48888
+ img.src = typeof fileData === "string" ? fileData : URL.createObjectURL(fileData);
48889
+ });
48890
+ };
48891
+ const getAllowedImageDimensions = (width, height, editor) => {
48892
+ const { width: maxWidth, height: maxHeight } = editor.getMaxContentSize();
48893
+ if (!maxWidth || !maxHeight) return { width, height };
48894
+ let adjustedWidth = width;
48895
+ let adjustedHeight = height;
48896
+ const aspectRatio = width / height;
48897
+ if (height > maxHeight) {
48898
+ adjustedHeight = maxHeight;
48899
+ adjustedWidth = Math.round(maxHeight * aspectRatio);
48900
+ }
48901
+ if (adjustedWidth > maxWidth) {
48902
+ adjustedWidth = maxWidth;
48903
+ adjustedHeight = Math.round(maxWidth / aspectRatio);
48904
+ }
48905
+ return { width: adjustedWidth, height: adjustedHeight };
48906
+ };
48907
+ const startImageUpload = async ({ editor, view, file }) => {
48908
+ let imageUploadHandler = typeof editor.options.handleImageUpload === "function" ? editor.options.handleImageUpload : handleImageUpload;
48909
+ let fileSizeMb = (file.size / (1024 * 1024)).toFixed(4);
48910
+ if (fileSizeMb > 5) {
48911
+ window.alert("Image size must be less than 5MB");
48912
+ return;
48913
+ }
48914
+ let width;
48915
+ let height;
48916
+ try {
48917
+ const processedImageResult = await processUploadedImage(file, editor);
48918
+ width = processedImageResult.width;
48919
+ height = processedImageResult.height;
48920
+ file = processedImageResult.file;
48921
+ } catch (err) {
48922
+ console.warn("Error processing image:", err);
48923
+ return;
48924
+ }
48925
+ let id = {};
48926
+ let { tr, schema } = view.state;
48927
+ if (!tr.selection.empty) {
48928
+ tr.deleteSelection();
48929
+ }
48930
+ let imageMeta = {
48931
+ type: "add",
48932
+ pos: tr.selection.from,
48933
+ id
48934
+ };
48935
+ tr.setMeta(ImagePlaceholderPluginKey, imageMeta);
48936
+ view.dispatch(tr);
48937
+ imageUploadHandler(file).then(
48938
+ (url) => {
48939
+ let fileName = file.name.replace(" ", "_");
48940
+ let placeholderPos = findPlaceholder(view.state, id);
48941
+ if (placeholderPos == null) {
48942
+ return;
48943
+ }
48944
+ let removeMeta = { type: "remove", id };
48945
+ let mediaPath = `word/media/${fileName}`;
48946
+ let imageNode = schema.nodes.image.create({
48947
+ src: mediaPath,
48948
+ size: { width, height }
48949
+ });
48950
+ editor.storage.image.media = Object.assign(editor.storage.image.media, { [mediaPath]: url });
48951
+ if (editor.options.ydoc) {
48952
+ editor.commands.addImageToCollaboration({ mediaPath, fileData: url });
48953
+ }
48954
+ view.dispatch(
48955
+ view.state.tr.replaceWith(placeholderPos, placeholderPos, imageNode).setMeta(ImagePlaceholderPluginKey, removeMeta)
48956
+ );
48957
+ },
48958
+ () => {
48959
+ let removeMeta = { type: "remove", id };
48960
+ view.dispatch(tr.setMeta(ImagePlaceholderPluginKey, removeMeta));
48961
+ }
48962
+ );
48963
+ };
48837
48964
  const BookmarkStart = Node$1.create({
48838
48965
  name: "bookmarkStart",
48839
48966
  group: "inline",
@@ -55002,6 +55129,239 @@ const Search = Extension.create({
55002
55129
  };
55003
55130
  }
55004
55131
  });
55132
+ const NodeResizerKey = new PluginKey("node-resizer");
55133
+ const nodeResizer = (nodeNames = ["image"]) => {
55134
+ let resizeState = {
55135
+ dragging: false,
55136
+ startX: 0,
55137
+ startY: 0,
55138
+ startWidth: 0,
55139
+ handle: null,
55140
+ pos: null,
55141
+ resizableElement: null,
55142
+ aspectRatio: 1
55143
+ };
55144
+ let resizeContainer = null;
55145
+ let editorView = null;
55146
+ let globalClickHandler = null;
55147
+ let globalMousedownHandler = null;
55148
+ return new Plugin({
55149
+ key: NodeResizerKey,
55150
+ state: {
55151
+ init() {
55152
+ return DecorationSet.empty;
55153
+ },
55154
+ apply(tr, oldState, _, newState) {
55155
+ if (tr.getMeta(NodeResizerKey)) {
55156
+ return oldState;
55157
+ }
55158
+ const decorations = [];
55159
+ const { selection } = newState;
55160
+ if (nodeNames.includes(selection.node?.type.name)) {
55161
+ decorations.push(
55162
+ Decoration.node(selection.from, selection.to, {
55163
+ nodeName: "span",
55164
+ class: "sd-editor-resizable-wrapper",
55165
+ "data-pos": selection.from
55166
+ })
55167
+ );
55168
+ }
55169
+ return DecorationSet.create(newState.doc, decorations);
55170
+ }
55171
+ },
55172
+ props: {
55173
+ decorations(state2) {
55174
+ return this.getState(state2);
55175
+ }
55176
+ },
55177
+ view(view) {
55178
+ editorView = view;
55179
+ globalClickHandler = (event) => {
55180
+ if (!event.target.closest(".sd-editor-resizable-wrapper") && !event.target.closest(".sd-editor-resize-container")) {
55181
+ hideResizeHandles();
55182
+ }
55183
+ };
55184
+ document.addEventListener("click", globalClickHandler);
55185
+ globalMousedownHandler = (event) => {
55186
+ if (event.target.closest(".sd-editor-resize-handle")) {
55187
+ event.preventDefault();
55188
+ event.stopPropagation();
55189
+ startResize(editorView, event, event.target);
55190
+ return true;
55191
+ }
55192
+ };
55193
+ document.addEventListener("mousedown", globalMousedownHandler);
55194
+ return {
55195
+ update(view2, prevState) {
55196
+ const { selection } = view2.state;
55197
+ const prevSelection = prevState.selection;
55198
+ if (selection.from !== prevSelection.from || selection.to !== prevSelection.to) {
55199
+ setTimeout(() => {
55200
+ const selectedResizableWrapper = document.querySelector(".sd-editor-resizable-wrapper");
55201
+ if (selectedResizableWrapper) {
55202
+ showResizeHandles(view2, selectedResizableWrapper);
55203
+ } else {
55204
+ hideResizeHandles();
55205
+ }
55206
+ }, 10);
55207
+ }
55208
+ },
55209
+ destroy() {
55210
+ hideResizeHandles();
55211
+ cleanupEventListeners();
55212
+ if (globalClickHandler) {
55213
+ document.removeEventListener("click", globalClickHandler);
55214
+ globalClickHandler = null;
55215
+ }
55216
+ if (globalMousedownHandler) {
55217
+ document.removeEventListener("mousedown", globalMousedownHandler);
55218
+ globalMousedownHandler = null;
55219
+ }
55220
+ editorView = null;
55221
+ }
55222
+ };
55223
+ }
55224
+ });
55225
+ function showResizeHandles(view, wrapper) {
55226
+ hideResizeHandles();
55227
+ const pos = Number.parseInt(wrapper.getAttribute("data-pos"), 10);
55228
+ const node2 = view.state.doc.nodeAt(pos);
55229
+ if (!nodeNames.includes(node2?.type.name)) return;
55230
+ resizeContainer = document.createElement("div");
55231
+ resizeContainer.className = "sd-editor-resize-container";
55232
+ resizeContainer.style.position = "absolute";
55233
+ resizeContainer.style.pointerEvents = "none";
55234
+ resizeContainer.style.zIndex = "1000";
55235
+ const handles = ["nw", "ne", "sw", "se"];
55236
+ for (const handle of handles) {
55237
+ const handleEl = document.createElement("div");
55238
+ handleEl.className = `sd-editor-resize-handle sd-editor-resize-handle-${handle}`;
55239
+ handleEl.setAttribute("data-handle", handle);
55240
+ handleEl.setAttribute("data-pos", pos);
55241
+ handleEl.style.pointerEvents = "auto";
55242
+ resizeContainer.appendChild(handleEl);
55243
+ }
55244
+ document.body.appendChild(resizeContainer);
55245
+ updateHandlePositions(wrapper.firstElementChild);
55246
+ }
55247
+ function hideResizeHandles() {
55248
+ if (resizeContainer?.parentNode) {
55249
+ resizeContainer.parentNode.removeChild(resizeContainer);
55250
+ resizeContainer = null;
55251
+ }
55252
+ }
55253
+ function updateHandlePositions(resizableElement) {
55254
+ if (!resizeContainer || !resizableElement) return;
55255
+ const rect = resizableElement.getBoundingClientRect();
55256
+ const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
55257
+ const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
55258
+ resizeContainer.style.left = `${rect.left + scrollLeft}px`;
55259
+ resizeContainer.style.top = `${rect.top + scrollTop}px`;
55260
+ resizeContainer.style.width = `${rect.width}px`;
55261
+ resizeContainer.style.height = `${rect.height}px`;
55262
+ }
55263
+ function startResize(view, event, handleElement) {
55264
+ if (!view.hasFocus()) return;
55265
+ const handle = handleElement.getAttribute("data-handle");
55266
+ const pos = Number.parseInt(handleElement.getAttribute("data-pos"), 10);
55267
+ if (view.state.selection.from !== pos || !nodeNames.includes(view.state.selection.node?.type.name)) return;
55268
+ const resizableElement = view.nodeDOM(pos);
55269
+ if (!resizableElement) return;
55270
+ const rect = resizableElement.getBoundingClientRect();
55271
+ resizeState = {
55272
+ dragging: true,
55273
+ startX: event.clientX,
55274
+ startY: event.clientY,
55275
+ startWidth: rect.width,
55276
+ startHeight: rect.height,
55277
+ handle,
55278
+ pos,
55279
+ resizableElement,
55280
+ aspectRatio: rect.width / rect.height
55281
+ };
55282
+ document.addEventListener("mousemove", handleMouseMove2);
55283
+ document.addEventListener("mouseup", handleMouseUp);
55284
+ document.body.style.cursor = getResizeCursor(handle);
55285
+ document.body.style.userSelect = "none";
55286
+ }
55287
+ function handleMouseMove2(event) {
55288
+ if (!resizeState.dragging) return;
55289
+ event.preventDefault();
55290
+ event.stopPropagation();
55291
+ let deltaX = event.clientX - resizeState.startX;
55292
+ event.clientY - resizeState.startY;
55293
+ if (resizeState.handle.includes("w")) deltaX = -deltaX;
55294
+ if (resizeState.handle.includes("n")) ;
55295
+ const newWidth = Math.max(20, resizeState.startWidth + deltaX);
55296
+ if (resizeState.resizableElement) {
55297
+ resizeState.resizableElement.style.width = `${newWidth}px`;
55298
+ resizeState.resizableElement.style.height = "auto";
55299
+ updateHandlePositions(resizeState.resizableElement);
55300
+ }
55301
+ }
55302
+ function handleMouseUp(event) {
55303
+ if (!resizeState.dragging) return;
55304
+ cleanupEventListeners();
55305
+ let deltaX = event.clientX - resizeState.startX;
55306
+ event.clientY - resizeState.startY;
55307
+ if (resizeState.handle.includes("w")) deltaX = -deltaX;
55308
+ if (resizeState.handle.includes("n")) ;
55309
+ const newWidth = Math.max(20, resizeState.startWidth + deltaX);
55310
+ const newHeight = newWidth / resizeState.aspectRatio;
55311
+ if (editorView && resizeState.pos < editorView.state.doc.content.size) {
55312
+ const tr = editorView.state.tr;
55313
+ const node2 = tr.doc.nodeAt(resizeState.pos);
55314
+ if (nodeNames.includes(node2?.type.name)) {
55315
+ const attrs = {
55316
+ ...node2.attrs,
55317
+ size: {
55318
+ ...node2.attrs.size,
55319
+ width: Math.round(newWidth),
55320
+ height: Math.round(newHeight)
55321
+ }
55322
+ };
55323
+ tr.setNodeMarkup(resizeState.pos, null, attrs);
55324
+ tr.setMeta(NodeResizerKey, { action: "resize" });
55325
+ editorView.dispatch(tr);
55326
+ }
55327
+ }
55328
+ resizeState = {
55329
+ dragging: false,
55330
+ startX: 0,
55331
+ startY: 0,
55332
+ startWidth: 0,
55333
+ startHeight: 0,
55334
+ handle: null,
55335
+ pos: null,
55336
+ resizableElement: null,
55337
+ aspectRatio: 1
55338
+ };
55339
+ }
55340
+ function cleanupEventListeners() {
55341
+ document.removeEventListener("mousemove", handleMouseMove2);
55342
+ document.removeEventListener("mouseup", handleMouseUp);
55343
+ document.body.style.cursor = "";
55344
+ document.body.style.userSelect = "";
55345
+ }
55346
+ function getResizeCursor(handle) {
55347
+ switch (handle) {
55348
+ case "nw":
55349
+ case "se":
55350
+ return "nwse-resize";
55351
+ case "ne":
55352
+ case "sw":
55353
+ return "nesw-resize";
55354
+ default:
55355
+ return "default";
55356
+ }
55357
+ }
55358
+ };
55359
+ const NodeResizer = Extension.create({
55360
+ name: "nodeResizer",
55361
+ addPmPlugins() {
55362
+ return [nodeResizer(["image"])];
55363
+ }
55364
+ });
55005
55365
  const getRichTextExtensions = () => {
55006
55366
  return [
55007
55367
  Bold,
@@ -55039,7 +55399,8 @@ const getRichTextExtensions = () => {
55039
55399
  TrackDelete,
55040
55400
  TrackFormat,
55041
55401
  AiPlugin,
55042
- Image
55402
+ Image,
55403
+ NodeResizer
55043
55404
  ];
55044
55405
  };
55045
55406
  const getStarterExtensions = () => {
@@ -55103,7 +55464,8 @@ const getStarterExtensions = () => {
55103
55464
  ShapeTextbox,
55104
55465
  ContentBlock,
55105
55466
  Search,
55106
- StructuredContent
55467
+ StructuredContent,
55468
+ NodeResizer
55107
55469
  ];
55108
55470
  };
55109
55471
  const sanitizeNumber = (value, defaultNumber) => {
@@ -67813,140 +68175,6 @@ const makeDefaultItems = ({
67813
68175
  overflowItems: overflowItems.filter((item) => item.type !== "separator")
67814
68176
  };
67815
68177
  };
67816
- const ACCEPT_IMAGE_TYPES = [".jpg", ".jpeg", ".png", "image/jpeg", "image/png"];
67817
- const getFileOpener = () => {
67818
- let fileInput = document.createElement("input");
67819
- fileInput.type = "file";
67820
- let acceptTypes = ACCEPT_IMAGE_TYPES;
67821
- fileInput.accept = acceptTypes.join(",");
67822
- const openFile = () => {
67823
- return new Promise((resolve, reject) => {
67824
- fileInput.onchange = async () => {
67825
- const files = fileInput.files;
67826
- if (!files) return resolve(null);
67827
- const file = files.item(0);
67828
- if (!file) return resolve(null);
67829
- return resolve({ file });
67830
- };
67831
- fileInput.oncancel = () => resolve(null);
67832
- fileInput.onerror = reject;
67833
- fileInput.click();
67834
- });
67835
- };
67836
- return openFile;
67837
- };
67838
- const handleImageUpload = (file) => {
67839
- return new Promise((resolve, reject) => {
67840
- let reader = new FileReader();
67841
- reader.onload = (event) => resolve(event.target.result);
67842
- reader.onerror = reject;
67843
- setTimeout(() => reader.readAsDataURL(file), 250);
67844
- });
67845
- };
67846
- const processUploadedImage = (fileData, editor) => {
67847
- return new Promise((resolve, reject) => {
67848
- const img = new window.Image();
67849
- img.onload = () => {
67850
- const canvas = document.createElement("canvas");
67851
- const { width, height } = getAllowedImageDimensions(
67852
- img.width,
67853
- img.height,
67854
- editor
67855
- );
67856
- canvas.width = width;
67857
- canvas.height = height;
67858
- const ctx2 = canvas.getContext("2d");
67859
- ctx2.drawImage(img, 0, 0, width, height);
67860
- if (typeof fileData === "string") {
67861
- const resizedBase64 = canvas.toDataURL();
67862
- resolve(resizedBase64);
67863
- } else {
67864
- canvas.toBlob((blob) => {
67865
- const updatedFile = new File([blob], fileData.name, {
67866
- type: fileData.type,
67867
- lastModified: Date.now()
67868
- });
67869
- resolve({ file: updatedFile, width, height });
67870
- });
67871
- }
67872
- };
67873
- img.onerror = (error) => reject(error);
67874
- img.src = typeof fileData === "string" ? fileData : URL.createObjectURL(fileData);
67875
- });
67876
- };
67877
- const getAllowedImageDimensions = (width, height, editor) => {
67878
- const { width: maxWidth, height: maxHeight } = editor.getMaxContentSize();
67879
- if (!maxWidth || !maxHeight) return { width, height };
67880
- let adjustedWidth = width;
67881
- let adjustedHeight = height;
67882
- const aspectRatio = width / height;
67883
- if (height > maxHeight) {
67884
- adjustedHeight = maxHeight;
67885
- adjustedWidth = Math.round(maxHeight * aspectRatio);
67886
- }
67887
- if (adjustedWidth > maxWidth) {
67888
- adjustedWidth = maxWidth;
67889
- adjustedHeight = Math.round(maxWidth / aspectRatio);
67890
- }
67891
- return { width: adjustedWidth, height: adjustedHeight };
67892
- };
67893
- const startImageUpload = async ({ editor, view, file }) => {
67894
- let imageUploadHandler = typeof editor.options.handleImageUpload === "function" ? editor.options.handleImageUpload : handleImageUpload;
67895
- let fileSizeMb = (file.size / (1024 * 1024)).toFixed(4);
67896
- if (fileSizeMb > 5) {
67897
- window.alert("Image size must be less than 5MB");
67898
- return;
67899
- }
67900
- let width;
67901
- let height;
67902
- try {
67903
- const processedImageResult = await processUploadedImage(file, editor);
67904
- width = processedImageResult.width;
67905
- height = processedImageResult.height;
67906
- file = processedImageResult.file;
67907
- } catch (err) {
67908
- console.warn("Error processing image:", err);
67909
- return;
67910
- }
67911
- let id = {};
67912
- let { tr, schema } = view.state;
67913
- if (!tr.selection.empty) {
67914
- tr.deleteSelection();
67915
- }
67916
- let imageMeta = {
67917
- type: "add",
67918
- pos: tr.selection.from,
67919
- id
67920
- };
67921
- tr.setMeta(ImagePlaceholderPluginKey, imageMeta);
67922
- view.dispatch(tr);
67923
- imageUploadHandler(file).then(
67924
- (url) => {
67925
- let fileName = file.name.replace(" ", "_");
67926
- let placeholderPos = findPlaceholder(view.state, id);
67927
- if (placeholderPos == null) {
67928
- return;
67929
- }
67930
- let removeMeta = { type: "remove", id };
67931
- let mediaPath = `word/media/${fileName}`;
67932
- let imageNode = schema.nodes.image.create({
67933
- src: mediaPath,
67934
- size: { width, height }
67935
- });
67936
- editor.storage.image.media = Object.assign(editor.storage.image.media, { [mediaPath]: url });
67937
- if (editor.options.ydoc) {
67938
- editor.commands.addImageToCollaboration({ mediaPath, fileData: url });
67939
- }
67940
- view.dispatch(
67941
- view.state.tr.replaceWith(placeholderPos, placeholderPos, imageNode).setMeta(ImagePlaceholderPluginKey, removeMeta)
67942
- );
67943
- },
67944
- () => {
67945
- let removeMeta = { type: "remove", id };
67946
- view.dispatch(tr.setMeta(ImagePlaceholderPluginKey, removeMeta));
67947
- }
67948
- );
67949
- };
67950
68178
  const toolbarTexts = {
67951
68179
  bold: "Bold",
67952
68180
  fontFamily: "Font",