image_to_media_swapper-2.x-dev/js/build/mediaSwapper.js

js/build/mediaSwapper.js
!function(root, factory) {
  "object" == typeof exports && "object" == typeof module ? module.exports = factory() : "function" == typeof define && define.amd ? define([], factory) : "object" == typeof exports ? exports.CKEditor5 = factory() : (root.CKEditor5 = root.CKEditor5 || {}, 
  root.CKEditor5.mediaSwapper = factory());
}(self, () => (() => {
  var __webpack_modules__ = {
    "ckeditor5/src/core.js": (module, __unused_webpack_exports, __webpack_require__) => {
      module.exports = __webpack_require__("dll-reference CKEditor5.dll")("./src/core.js");
    },
    "ckeditor5/src/ui.js": (module, __unused_webpack_exports, __webpack_require__) => {
      module.exports = __webpack_require__("dll-reference CKEditor5.dll")("./src/ui.js");
    },
    "dll-reference CKEditor5.dll": module => {
      "use strict";
      module.exports = CKEditor5.dll;
    }
  };
  var __webpack_module_cache__ = {};
  function __webpack_require__(moduleId) {
    var cachedModule = __webpack_module_cache__[moduleId];
    if (void 0 !== cachedModule) return cachedModule.exports;
    var module = __webpack_module_cache__[moduleId] = {
      exports: {}
    };
    __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
    return module.exports;
  }
  __webpack_require__.d = (exports, definition) => {
    for (var key in definition) __webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key) && Object.defineProperty(exports, key, {
      enumerable: !0,
      get: definition[key]
    });
  };
  __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
  __webpack_require__.r = exports => {
    "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(exports, Symbol.toStringTag, {
      value: "Module"
    });
    Object.defineProperty(exports, "__esModule", {
      value: !0
    });
  };
  var __webpack_exports__ = {};
  (() => {
    "use strict";
    __webpack_require__.r(__webpack_exports__);
    __webpack_require__.d(__webpack_exports__, {
      LogSelectedElement: () => LogSelectedElement,
      MediaSwapper: () => MediaSwapper
    });
    var delegated_corefrom_dll_reference_CKEditor5 = __webpack_require__("ckeditor5/src/core.js");
    var delegated_uifrom_dll_reference_CKEditor5 = __webpack_require__("ckeditor5/src/ui.js");
    class MediaSwapper extends delegated_corefrom_dll_reference_CKEditor5.Plugin {
      static get requires() {
        return [ "Link" ];
      }
      init() {
        const editor = this.editor;
        this.isLinkitAvailable = this.detectLinkitAvailability();
        this.securityTokens = null;
        editor.ui.componentFactory.add("mediaSwapper", locale => {
          const button = new delegated_uifrom_dll_reference_CKEditor5.ButtonView(locale);
          button.set({
            label: "Convert to Media",
            icon: '<?xml version="1.0" standalone="no"?>\n<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 1024 1024">\n  <path d="M847.9 592H152c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h605.2L612.9 851c-4.1 5.2-.4 13 6.3 13h72.5c4.9 0 9.5-2.2 12.6-6.1l168.8-214.1c16.5-21 1.6-51.8-25.2-51.8zM872 356H266.8l144.3-183c4.1-5.2.4-13-6.3-13h-72.5c-4.9 0-9.5 2.2-12.6 6.1L150.9 380.2c-16.5 21-1.6 51.8 25.1 51.8h696c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8z"/>\n</svg>\n',
            tooltip: !0,
            isEnabled: !1
          });
          const updateButtonState = () => {
            const imageBlock = this.getSelectedImageBlock();
            const linkCommand = editor.commands.get("link");
            const canProcessFileLink = linkCommand && linkCommand.value && this.isFileLink(linkCommand.value) && this.isLinkitAvailable;
            button.isEnabled = !(!imageBlock && !canProcessFileLink);
          };
          editor.model.document.selection.on("change", updateButtonState);
          editor.model.document.on("change:data", updateButtonState);
          const linkCommand = editor.commands.get("link");
          linkCommand && linkCommand.on("change:value", updateButtonState);
          updateButtonState();
          button.on("execute", async () => {
            await this.handleConversion();
          });
          return button;
        });
      }
      async getSecurityTokens() {
        if (this.securityTokens && Date.now() - this.securityTokens.timestamp < 3e5) return this.securityTokens;
        try {
          const response = await fetch("/media-api/security-tokens", {
            method: "GET",
            headers: {
              Accept: "application/json"
            }
          });
          if (!response.ok) return new Error(`HTTP ${response.status}: ${response.statusText}`);
          this.securityTokens = await response.json();
          return this.securityTokens;
        } catch (error) {
          await this.showConfirmationDialog("Failed to get security tokens. Please refresh the page and try again.", !0);
          throw error;
        }
      }
      async makeSecureApiRequest(endpoint, body) {
        const tokens = await this.getSecurityTokens();
        const secureBody = {
          ...body,
          csrf_token: tokens.csrf_token,
          user_uuid: tokens.user_uuid
        };
        const response = await fetch(endpoint, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            Accept: "application/json",
            "X-CSRF-Token": tokens.csrf_token,
            Origin: window.location.origin
          },
          body: JSON.stringify(secureBody)
        });
        if (!response.ok) {
          const errorData = await response.json().catch(() => ({}));
          throw new Error(errorData.error || `HTTP ${response.status}: ${response.statusText}`);
        }
        return response.json();
      }
      async handleConversion() {
        const linkCommand = this.editor.commands.get("link");
        linkCommand && linkCommand.value && this.isFileLink(linkCommand.value) && this.isLinkitAvailable ? await this.handleFileConversion() : await this.handleImageConversion();
      }
      async handleImageConversion() {
        const imageBlock = this.getSelectedImageBlock();
        if (!imageBlock) {
          await this.showConfirmationDialog("No image block selected.", !0);
          return;
        }
        const fileUuid = imageBlock.getAttribute("dataEntityUuid");
        const filePath = imageBlock.getAttribute("src");
        imageBlock.getAttribute("dataAlign");
        if (!fileUuid && !filePath) {
          await this.showConfirmationDialog("No file UUID or file path found in the selected image.", !0);
          return;
        }
        if (!await this.showConfirmationDialog("Convert this file-based image to a media entity?")) return;
        let endPoint;
        let body;
        if (filePath) {
          if (this.isAbsoluteUrl(filePath)) {
            const currentDomain = window.location.origin;
            if (filePath.startsWith(currentDomain)) {
              endPoint = "/media-api/swap-file-to-media/local-path";
              body = {
                filepath: filePath
              };
            } else {
              endPoint = "/media-api/swap-file-to-media/remote-uri";
              body = {
                remote_file: filePath
              };
            }
          } else {
            endPoint = "/media-api/swap-file-to-media/local-path";
            body = {
              filepath: filePath
            };
          }
        }
        if (fileUuid) {
          endPoint = "/media-api/swap-file-to-media/file-uuid";
          body = {
            uuid: fileUuid
          };
        }
        if (!endPoint || !body) return;
        let data;
        try {
          data = await this.makeSecureApiRequest(endPoint, body);
          if (data.error || !data.uuid[0]) {
            await this.showConfirmationDialog(data.error || "Unknown error occurred", !0);
            return;
          }
        } catch (error) {
          return;
        }
        try {
          const insertPosition = this.editor.model.document.selection.getFirstPosition();
          const imageBlock = this.getSelectedImageBlock();
          const imageStyle = imageBlock.getAttribute("imageStyle");
          imageBlock && this.editor.model.change(writer => {
            writer.remove(imageBlock);
          });
          this.editor.model.change(writer => {
            const mediaAttributes = {
              drupalMediaEntityUuid: data.uuid[0].value,
              drupalMediaEntityType: "media",
              drupalElementStyleViewMode: "default"
            };
            imageStyle && (mediaAttributes.imageStyle = imageStyle);
            const drupalMedia = writer.createElement("drupalMedia", mediaAttributes);
            writer.insert(drupalMedia, insertPosition);
            writer.setSelection(drupalMedia, "on");
          });
        } catch (error) {
          await this.showConfirmationDialog("Error updating editor content.", !0);
        }
      }
      async handleFileConversion() {
        const currentUrl = this.editor.commands.get("link").value;
        if (!currentUrl || !this.isFileLink(currentUrl)) {
          await this.showConfirmationDialog("No file link found at current selection.", !0);
          return;
        }
        const linkElement = {
          getAttribute: attr => "linkHref" === attr ? currentUrl : this.editor.model.document.selection.getAttribute(attr) || null,
          getHref: () => currentUrl,
          _isCommandBased: !0
        };
        await this.handleFileLink(linkElement);
      }
      showConfirmationDialog(message, isInformational = !1) {
        return new Promise(resolve => {
          const container = document.createElement("div");
          container.classList.add("custom-confirm-container");
          container.innerHTML = isInformational ? `\n        <div class="custom-confirm-box">\n          <p>${message}</p>\n          <button class="confirm-yes">Ok</button>\n        </div>\n      ` : `\n        <div class="custom-confirm-box">\n          <p>${message}</p>\n          <button class="confirm-yes">Yes</button>\n          <button class="confirm-no">Cancel</button>\n        </div>\n      `;
          document.body.appendChild(container);
          container.querySelector(".confirm-yes").addEventListener("click", () => {
            container.remove();
            resolve(!0);
          });
          const cancelButton = container.querySelector(".confirm-no");
          cancelButton && cancelButton.addEventListener("click", () => {
            container.remove();
            resolve(!1);
          });
        });
      }
      getSelectedImageBlock() {
        const selection = this.editor.model.document.selection;
        const selectedElement = selection.getSelectedElement();
        if (selectedElement && ("imageBlock" === selectedElement.name || "imageInline" === selectedElement.name) && ("file" === selectedElement.getAttribute("dataEntityType") || selectedElement.getAttribute("src"))) return selectedElement;
        const position = selection.getFirstPosition();
        if (!position) return null;
        let parent = position.parent;
        for (;parent; ) {
          if (("imageBlock" === parent.name || "imageInline" === parent.name) && "file" === parent.getAttribute("dataEntityType")) return parent;
          parent = parent.parent;
        }
        return selectedElement && "drupalEntity" === selectedElement.name && "file" === selectedElement.getAttribute("entityType") ? selectedElement : null;
      }
      detectLinkitAvailability() {
        const editor = this.editor;
        if (editor.plugins.has("Linkit")) return !0;
        if (editor.model.schema.checkAttribute("$text", "linkDataEntityType")) return !0;
        return !!editor.config.get("linkit");
      }
      isFileLink(url) {
        if (!url || "string" != typeof url) return !1;
        const supportedExtensions = this.getSupportedExtensions();
        const urlLower = url.toLowerCase();
        return supportedExtensions.some(ext => urlLower.includes(`.${ext}`) || urlLower.includes(`type=${ext}`) || urlLower.includes(`format=${ext}`));
      }
      getSupportedExtensions() {
        return "undefined" != typeof drupalSettings && drupalSettings.imageToMediaSwapper && drupalSettings.imageToMediaSwapper.supportedExtensions ? drupalSettings.imageToMediaSwapper.supportedExtensions : [ "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "zip", "rar", "mp3", "mp4", "jpg", "jpeg", "png", "gif" ];
      }
      async handleFileLink(linkElement) {
        const href = linkElement.getAttribute("linkHref") || linkElement.getHref();
        const dataMediaUuid = linkElement.getAttribute("data-media-uuid");
        if (!href) {
          await this.showConfirmationDialog("No href found in the selected file link.", !0);
          return;
        }
        if (!await this.showConfirmationDialog("Convert this file link to a media entity?")) return;
        let endPoint;
        let body;
        if (dataMediaUuid) {
          endPoint = "/media-api/swap-file-to-media/file-uuid";
          body = {
            uuid: dataMediaUuid
          };
        } else {
          if (this.isAbsoluteUrl(href)) {
            const currentDomain = window.location.origin;
            if (href.startsWith(currentDomain)) {
              endPoint = "/media-api/swap-file-to-media/local-path";
              body = {
                filepath: href
              };
            } else {
              endPoint = "/media-api/swap-file-to-media/remote-uri";
              body = {
                remote_file: href
              };
            }
          } else {
            endPoint = "/media-api/swap-file-to-media/local-path";
            body = {
              filepath: href
            };
          }
        }
        if (!endPoint || !body) {
          await this.showConfirmationDialog("Unable to determine appropriate endpoint for file conversion.", !0);
          return;
        }
        let data;
        try {
          data = await this.makeSecureApiRequest(endPoint, body);
          if (data.error || !data.uuid || !data.uuid[0]) {
            await this.showConfirmationDialog(data.error || "Unknown error occurred during file conversion", !0);
            return;
          }
        } catch (error) {
          await this.showConfirmationDialog("Error occurred during file conversion: " + error.message, !0);
          return;
        }
        try {
          await this.updateLinkAttributes(linkElement, {
            linkHref: `/media/${data.mid[0].value}`,
            linkDataEntityType: "media",
            linkDataEntityUuid: data.uuid[0].value,
            linkDataEntitySubstitution: "media"
          });
          await this.showConfirmationDialog("File link updated successfully with Linkit attributes.", !0);
        } catch (error) {
          await this.showConfirmationDialog("Error updating file link. The media entity was created but the link was not updated.", !0);
        }
      }
      async updateLinkAttributes(linkElement, newAttributes) {
        return new Promise((resolve, reject) => {
          try {
            const linkCommand = this.editor.commands.get("link");
            if (linkCommand) {
              const href = newAttributes.linkHref;
              const decorators = {
                linkDataEntityType: newAttributes.linkDataEntityType,
                linkDataEntityUuid: newAttributes.linkDataEntityUuid,
                linkDataEntitySubstitution: newAttributes.linkDataEntitySubstitution
              };
              linkCommand.execute(href, decorators);
              resolve();
            } else reject(new Error("Link command not available"));
          } catch (error) {
            reject(error);
          }
        });
      }
      isAbsoluteUrl(url) {
        if (!url || "string" != typeof url) return !1;
        if (url.startsWith("http://") || url.startsWith("https://")) try {
          new URL(url);
          return !0;
        } catch (error) {
          return !1;
        }
        return !1;
      }
    }
    class LogSelectedElement extends delegated_corefrom_dll_reference_CKEditor5.Plugin {
      init() {
        const editor = this.editor;
        editor.ui.componentFactory.add("logSelected", locale => {
          const button = new delegated_uifrom_dll_reference_CKEditor5.ButtonView(locale);
          button.set({
            label: "Log Selected",
            tooltip: !0,
            withText: !0
          });
          button.on("execute", () => {
            const selection = editor.model.document.selection;
            const selectedElement = selection.getSelectedElement();
            const position = selection.getFirstPosition();
            console.log("--- LOGGING SELECTION ---");
            console.log("Selected element:", selectedElement);
            if (selectedElement) {
              console.log("Selected element name:", selectedElement.name);
              console.log("Selected element attributes:", Array.from(selectedElement.getAttributes()));
              if ("imageInline" === selectedElement.name || "imageBlock" === selectedElement.name) {
                console.log("IMAGE ELEMENT DETECTED!");
                console.log("Image src:", selectedElement.getAttribute("src"));
                console.log("Image alt:", selectedElement.getAttribute("alt"));
                const dataEntityType = selectedElement.getAttribute("dataEntityType");
                const dataEntityUuid = selectedElement.getAttribute("dataEntityUuid");
                if (dataEntityType || dataEntityUuid) {
                  console.log("DRUPAL ENTITY DATA DETECTED:");
                  console.log("  data-entity-type:", dataEntityType);
                  console.log("  data-entity-uuid:", dataEntityUuid);
                }
              }
              if (selectedElement.hasAttribute("linkHref")) {
                console.log("LINK ELEMENT DETECTED!");
                console.log("Link href:", selectedElement.getAttribute("linkHref"));
                console.log("Link target:", selectedElement.getAttribute("linkTarget"));
                console.log("Link download:", selectedElement.getAttribute("linkDownload"));
                const href = selectedElement.getAttribute("linkHref");
                if (href) {
                  const isFileLink = this.detectPossibleFileLink(href);
                  console.log("Appears to be a file link:", isFileLink);
                  isFileLink && console.log("Possible file extension:", this.extractFileExtension(href));
                }
              }
              if ("drupalMedia" === selectedElement.name) {
                console.log("DRUPAL MEDIA ELEMENT DETECTED!");
                console.log("Media data-entity-type:", selectedElement.getAttribute("dataEntityType"));
                console.log("Media data-entity-uuid:", selectedElement.getAttribute("dataEntityUuid"));
                console.log("Media data-view-mode:", selectedElement.getAttribute("dataViewMode"));
              }
            }
            console.log("First position parent:", position.parent.name);
            console.log("First position parent attrs:", Array.from(position.parent.getAttributes()));
            console.log("First position:", selection.getFirstPosition().parent.name);
            console.log("Last position:", selection.getLastPosition().parent.name);
            console.log("Current editor model content:");
            console.log(editor.getData());
            const ranges = Array.from(selection.getRanges());
            console.log("Selection ranges:", ranges);
            if (selectedElement) {
              const schema = editor.model.schema;
              console.log("Schema information:");
              console.log("  isBlock:", schema.isBlock(selectedElement));
              console.log("  isInline:", schema.isInline(selectedElement));
              console.log("  isObject:", schema.isObject(selectedElement));
              console.log("  allowedAttributes:", schema.getAttributesAllowedOnElement(selectedElement.name));
            }
            console.log("--------------------------");
          });
          return button;
        });
      }
      detectPossibleFileLink(url) {
        const fileExtensions = [ "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "zip", "rar", "jpg", "jpeg", "png", "gif", "svg" ];
        const urlLower = url.toLowerCase();
        for (const ext of fileExtensions) if (urlLower.endsWith(`.${ext}`) || urlLower.includes(`.${ext}?`)) return !0;
        return !!(urlLower.includes("download=") || urlLower.includes("/download/") || urlLower.includes("/files/"));
      }
      extractFileExtension(url) {
        const matches = url.split("?")[0].match(/\.([a-zA-Z0-9]+)$/);
        return matches ? matches[1].toLowerCase() : null;
      }
    }
  })();
  return __webpack_exports__;
})());

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc