'use strict';

var _defineProperty = require('@babel/runtime/helpers/defineProperty');
var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
var React = require('react');
var classnames = require('classnames');
var DOMPurify = require('dompurify');
var CopyToClipboardButton = require('@bigbinary/neeto-molecules/v2/CopyToClipboardButton');
var ramda = require('ramda');
var client = require('react-dom/client');
var constants = require('./chunk-2HrSPdAV.cjs.js');
var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
var common = require('./chunk-De3nCFAF.cjs.js');
var common$1 = require('./chunk-JCA39oKB.cjs.js');
var neetoCist = require('@bigbinary/neeto-cist');
var ReactDOM = require('react-dom/server');
require('./chunk-BGy3NmZC.cjs.js');
var neetoAtoms = require('@bigbinary/neeto-atoms');
var lucideReact = require('lucide-react');
var reactUtils = require('@bigbinary/neeto-commons-frontend/v2/react-utils');
var ReactDOM$1 = require('react-dom');
var reactI18next = require('react-i18next');
var jsxRuntime = require('react/jsx-runtime');

function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }

var _defineProperty__default = /*#__PURE__*/_interopDefault(_defineProperty);
var _slicedToArray__default = /*#__PURE__*/_interopDefault(_slicedToArray);
var _objectWithoutProperties__default = /*#__PURE__*/_interopDefault(_objectWithoutProperties);
var classnames__default = /*#__PURE__*/_interopDefault(classnames);
var DOMPurify__default = /*#__PURE__*/_interopDefault(DOMPurify);
var CopyToClipboardButton__default = /*#__PURE__*/_interopDefault(CopyToClipboardButton);
var _toConsumableArray__default = /*#__PURE__*/_interopDefault(_toConsumableArray);

var EDITOR_CONTENT_CLASS_NAME = "neeto-editor-content";
var SANITIZE_OPTIONS = {
  ADD_TAGS: ["iframe"],
  ADD_ATTR: ["target", "allow", "allowfullscreen", "frameborder"]
};
var CODE_BLOCK_REGEX = /<pre(?:\s+[^>]+)?><code(?:\s+class="language-([^"]*)")?>([\S\s]*?)<\/code><\/pre>/gim;
var VARIABLE_SPAN_REGEX = /<span data-variable="" [^>]*data-label="([^"]+)">{{([^}]+)}}<\/span>/g;
var LANGUAGE_LIST = [].concat(_toConsumableArray__default.default(common.lowlight.listLanguages()), ["html"]);
var EDITOR_CONTENT_DEFAULT_CONFIGURATION = {
  enableHeaderLinks: false
};

function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike) { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
var transformCode = function transformCode(code) {
  return code.replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&amp;/g, "&");
};
var buildReactElementFromAST = function buildReactElementFromAST(element) {
  if (element.tagName) {
    var children = element.children ? element.children.map(buildReactElementFromAST) : null;
    return /*#__PURE__*/React.createElement(element.tagName, element.properties, children);
  }
  return element.value;
};
var splitCodeBlockIntoLines = function splitCodeBlockIntoLines(codeBlock) {
  codeBlock.innerHTML = codeBlock.innerHTML.replace(/([ \S]*\n|[ \S]*$)/gm, function (match) {
    return "<div class=\"highlight-line\">".concat(match, "</div>");
  });
};
var highlightLinesCode = function highlightLinesCode(code, options) {
  if (options === undefined) {
    return;
  }
  var paddingLeft = parseInt(window.getComputedStyle(code).paddingLeft);
  var paddingRight = parseInt(window.getComputedStyle(code).paddingRight);
  var lines = code.getElementsByClassName("highlight-line");
  var scroll_width = code.scrollWidth;
  // eslint-disable-next-line @bigbinary/neeto/use-array-methods
  var _iterator = _createForOfIteratorHelper(options),
    _step;
  try {
    for (_iterator.s(); !(_step = _iterator.n()).done;) {
      var option = _step.value;
      for (var j = option.start; j <= option.end; ++j) {
        if (j >= lines.length) return;
        lines[j].style.backgroundColor = option.color;
        lines[j].style.minWidth = "".concat(scroll_width - paddingLeft - paddingRight, "px");
      }
    }
  } catch (err) {
    _iterator.e(err);
  } finally {
    _iterator.f();
  }
};
var highlightLinesElement = function highlightLinesElement(code, options) {
  // eslint-disable-next-line @bigbinary/neeto/use-array-methods
  var _iterator2 = _createForOfIteratorHelper(options),
    _step2;
  try {
    for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
      var option = _step2.value;
      --option.start;
      --option.end;
    }
  } catch (err) {
    _iterator2.e(err);
  } finally {
    _iterator2.f();
  }
  highlightLinesCode(code, options);
};
var applySyntaxHighlightingAndLineNumbers = function applySyntaxHighlightingAndLineNumbers(content) {
  common.lowlight.highlightAuto("");
  var highlightedAST = {};
  return content.replace(CODE_BLOCK_REGEX, function (_, language, code) {
    var _highlightMatch$;
    var highlightRegex = /data-highlighted-lines="([^"]*)"/;
    var linenumbersRegex = /data-linenumbers/;
    var highlightMatch = content.match(highlightRegex);
    if (language && LANGUAGE_LIST.includes(language)) {
      highlightedAST = common.lowlight.highlight(language, transformCode(code));
    } else {
      highlightedAST = common$1.HighlightJS.highlightAuto(transformCode(code))._emitter.root;
      if (ramda.isEmpty(highlightedAST.children)) {
        highlightedAST = common.lowlight.highlight("javascript", transformCode(code));
      }
    }
    var highlightedNode = highlightedAST.children.map(buildReactElementFromAST);
    var dataHighlight = "data-highlighted-lines=".concat((_highlightMatch$ = highlightMatch === null || highlightMatch === void 0 ? void 0 : highlightMatch[1]) !== null && _highlightMatch$ !== void 0 ? _highlightMatch$ : "");
    var dataLinenumbers = content.match(linenumbersRegex) ? "data-linenumbers=\"true\"" : "";
    return "<pre ".concat(dataLinenumbers, " ").concat(dataHighlight, "><code>").concat(ReactDOM.renderToString(highlightedNode), "</code></pre>");
  });
};
var applyLineHighlighting = function applyLineHighlighting(editorContent) {
  var codeTags = editorContent === null || editorContent === void 0 ? void 0 : editorContent.querySelectorAll("pre code");
  codeTags.forEach(function (codeTag) {
    splitCodeBlockIntoLines(codeTag);
    var highlightedLines = codeTag.closest("pre").getAttribute("data-highlighted-lines");
    if (highlightedLines) {
      var linesToHighlight = highlightedLines.split(",").map(Number).filter(Boolean);
      var highlightLinesOptions = linesToHighlight.map(function (line) {
        return {
          start: line,
          end: line,
          color: "rgba(255, 255, 0, 0.2)"
        };
      });
      highlightLinesElement(codeTag, highlightLinesOptions);
    }
  });
};
var substituteVariables = function substituteVariables(highlightedContent, variables) {
  return highlightedContent.replace(VARIABLE_SPAN_REGEX, function (matchedSpan, _, key) {
    var keySplitted = key.split(".");
    if (keySplitted.length > 1) {
      var category = neetoCist.findBy({
        category: keySplitted[0]
      }, variables);
      var _variable = neetoCist.findBy({
        key: keySplitted[1]
      }, (category === null || category === void 0 ? void 0 : category.variables) || []);
      return _variable !== null && _variable !== void 0 && _variable.value ? _variable.value : matchedSpan;
    }
    var variable = neetoCist.findBy({
      key: keySplitted[0]
    }, variables);
    return variable !== null && variable !== void 0 && variable.value ? variable.value : matchedSpan;
  });
};
var convertPlainTextToHtml = function convertPlainTextToHtml(htmlString) {
  if (/^<[a-z].*>/i.test(htmlString.trim())) return htmlString;
  return htmlString.split("\n").reduce(function (html, str) {
    return "".concat(html, "<p>").concat(str, "</p>");
  }, "");
};

var buildLinkSVG = function buildLinkSVG() {
  var svgNS = "http://www.w3.org/2000/svg";
  var svgWrapper = document.createElement("span");
  svgWrapper.classList.add("header-link-icon-wrapper");
  var svg = document.createElementNS(svgNS, "svg");
  svg.setAttribute("aria-hidden", "true");
  svg.setAttribute("height", "20");
  svg.setAttribute("viewBox", "0 0 16 16");
  svg.setAttribute("width", "20");
  var path = document.createElementNS(svgNS, "path");
  path.setAttribute("d", "M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z");
  svg.appendChild(path);
  svgWrapper.appendChild(svg);
  return svgWrapper;
};
var convertTextToId = function convertTextToId(text) {
  return text.trim().toLowerCase().replace(/[^a-z0-9\s]/g, "").replace(/\s+/g, "-");
};
var buildHeaderLinks = function buildHeaderLinks(editorContentNode) {
  var headerTags = editorContentNode.querySelectorAll("h1, h2, h3, h4, h5, h6");
  var usedIds = new Map();
  headerTags.forEach(function (heading) {
    if (heading.getAttribute("data-link") === "false") {
      return;
    }
    var headingId = convertTextToId(heading.textContent);
    if (usedIds.has(headingId)) {
      var count = usedIds.get(headingId);
      usedIds.set(headingId, count + 1);
      headingId = "".concat(headingId, "-").concat(count);
    } else usedIds.set(headingId, 1);
    heading.setAttribute("id", headingId);
    var wrapper = document.createElement("div");
    var anchor = document.createElement("a");
    wrapper.classList.add("header-wrapper");
    anchor.setAttribute("href", "#".concat(headingId));
    anchor.classList.add("header-wrapper__link");
    anchor.appendChild(buildLinkSVG());
    wrapper.appendChild(heading.cloneNode(true));
    wrapper.appendChild(anchor);
    heading.replaceWith(wrapper);
  });
};

var handleTodoCheckboxClick = function handleTodoCheckboxClick(event, editorContentRef, onChange) {
  if (!(event.target.type === "checkbox" && event.target.closest('ul[data-type="todoList"] li[data-type="taskItem"]'))) {
    return;
  }
  var checkbox = event.target;
  var listItem = checkbox.closest("li");
  if (listItem) {
    listItem.setAttribute("data-checked", checkbox.checked.toString());
    if (checkbox.checked) {
      checkbox.setAttribute("checked", "checked");
    } else {
      checkbox.removeAttribute("checked");
    }
    onChange === null || onChange === void 0 || onChange(editorContentRef === null || editorContentRef === void 0 ? void 0 : editorContentRef.innerHTML);
  }
};
var syncTodoCheckboxStates = function syncTodoCheckboxStates(editorContentRef) {
  if (!editorContentRef) return;
  var todoItems = editorContentRef.querySelectorAll("ul[data-type=\"todoList\"] li[data-type=\"taskItem\"]");
  todoItems.forEach(function (listItem) {
    var isChecked = listItem.getAttribute("data-checked") === "true";
    var checkbox = listItem.querySelector('input[type="checkbox"]');
    if (checkbox) {
      checkbox.checked = isChecked;
      if (isChecked) {
        checkbox.setAttribute("checked", "checked");
      } else {
        checkbox.removeAttribute("checked");
      }
    }
  });
};

var ImagePreview = function ImagePreview(_ref) {
  var imagePreviewDetails = _ref.imagePreviewDetails,
    setImagePreviewDetails = _ref.setImagePreviewDetails;
  var _useState = React.useState(true),
    _useState2 = _slicedToArray__default.default(_useState, 2),
    isLoading = _useState2[0],
    setIsLoading = _useState2[1];
  var _useTranslation = reactI18next.useTranslation(),
    t = _useTranslation.t;
  var imagePreviewRef = React.useRef(null);
  reactUtils.useOnClickOutside(imagePreviewRef, function () {
    return setImagePreviewDetails(null);
  }, {
    enabled: true
  });
  React.useEffect(function () {
    if (!imagePreviewRef.current) return;
    imagePreviewRef.current.setAttribute("tabindex", "-1");
    imagePreviewRef.current.focus();
  }, []);
  var handleKeyDown = function handleKeyDown(e) {
    e.stopPropagation();
    e.key === "Escape" && setImagePreviewDetails(null);
  };
  return /*#__PURE__*/ReactDOM$1.createPortal(/*#__PURE__*/jsxRuntime.jsxs("div", {
    className: "ne-image-preview-wrapper active",
    children: [isLoading && /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Spinner, {
      className: "ne-image-preview-wrapper__spinner"
    }), !isLoading && /*#__PURE__*/jsxRuntime.jsx("div", {
      className: "close-button",
      children: /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Button, {
        icon: lucideReact.X,
        variant: "secondary",
        onClick: function onClick() {
          return setImagePreviewDetails(null);
        }
      })
    }), /*#__PURE__*/jsxRuntime.jsxs("div", {
      className: classnames__default.default("ne-image-preview", {
        "image-loaded": !isLoading
      }),
      children: [/*#__PURE__*/jsxRuntime.jsx("img", {
        alt: t("neetoEditor.editorContent.imagePreviewAltText"),
        ref: imagePreviewRef,
        src: imagePreviewDetails.src,
        onKeyDown: handleKeyDown,
        onLoad: function onLoad() {
          return setIsLoading(false);
        }
      }), imagePreviewDetails && /*#__PURE__*/jsxRuntime.jsx("p", {
        className: "ne-image-preview__caption",
        children: imagePreviewDetails.caption
      })]
    })]
  }), document.body);
};

var _excluded = ["content", "variables", "className", "size", "configuration", "onChange", "onClick"];
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), true).forEach(function (r) { _defineProperty__default.default(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
var EditorContent = function EditorContent(_ref) {
  var _ref$content = _ref.content,
    content = _ref$content === void 0 ? "" : _ref$content,
    _ref$variables = _ref.variables,
    variables = _ref$variables === void 0 ? [] : _ref$variables,
    className = _ref.className,
    _ref$size = _ref.size,
    size = _ref$size === void 0 ? constants.EDITOR_SIZES.SMALL : _ref$size,
    _ref$configuration = _ref.configuration,
    configuration = _ref$configuration === void 0 ? EDITOR_CONTENT_DEFAULT_CONFIGURATION : _ref$configuration,
    onChange = _ref.onChange,
    onClick = _ref.onClick,
    otherProps = _objectWithoutProperties__default.default(_ref, _excluded);
  var _useState = React.useState(null),
    _useState2 = _slicedToArray__default.default(_useState, 2),
    imagePreviewDetails = _useState2[0],
    setImagePreviewDetails = _useState2[1];
  var editorContentRef = React.useRef(null);
  var htmlContent = convertPlainTextToHtml(substituteVariables(applySyntaxHighlightingAndLineNumbers(common.removeEmptyTags(content)), variables));
  var sanitize = DOMPurify__default.default.sanitize;
  var handleContentClick = function handleContentClick(event) {
    handleTodoCheckboxClick(event, editorContentRef.current, onChange);
    onClick === null || onClick === void 0 || onClick(event);
  };
  var injectCopyButtonToCodeBlocks = function injectCopyButtonToCodeBlocks() {
    var _editorContentRef$cur;
    var preTags = (_editorContentRef$cur = editorContentRef.current) === null || _editorContentRef$cur === void 0 ? void 0 : _editorContentRef$cur.querySelectorAll(".".concat(EDITOR_CONTENT_CLASS_NAME, " pre"));
    preTags.forEach(function (preTag) {
      var button = document.createElement("div");
      button.className = "neeto-editor-codeblock-options";
      var root = client.createRoot(button);
      root.render(/*#__PURE__*/jsxRuntime.jsx(CopyToClipboardButton__default.default, {
        size: "sm",
        value: preTag.textContent,
        variant: "ghost"
      }));
      preTag.appendChild(button);
    });
  };
  var bindImageClickListener = function bindImageClickListener() {
    var _editorContentRef$cur2;
    var figureTags = (_editorContentRef$cur2 = editorContentRef.current) === null || _editorContentRef$cur2 === void 0 ? void 0 : _editorContentRef$cur2.querySelectorAll(".".concat(EDITOR_CONTENT_CLASS_NAME, " figure"));
    figureTags.forEach(function (figureTag) {
      var image = figureTag.querySelector("img");
      var link = figureTag.querySelector("a");
      if (ramda.isNil(image) || ramda.isNil(link)) return;
      figureTag.addEventListener("click", function (event) {
        event.preventDefault();
        var caption = figureTag.querySelector("figcaption").innerText;
        setImagePreviewDetails({
          src: image.src,
          caption: caption
        });
      });
    });
  };
  React.useEffect(function () {
    injectCopyButtonToCodeBlocks();
    bindImageClickListener();
    syncTodoCheckboxStates(editorContentRef.current);
    applyLineHighlighting(editorContentRef.current);
    configuration.enableHeaderLinks && buildHeaderLinks(editorContentRef.current);
  }, [content]);
  return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
    children: [/*#__PURE__*/jsxRuntime.jsx("div", _objectSpread({
      "data-testid": "neeto-editor-content",
      ref: editorContentRef,
      className: classnames__default.default(EDITOR_CONTENT_CLASS_NAME, _defineProperty__default.default(_defineProperty__default.default({}, className, className), "neeto-editor-size--".concat(size), true)),
      dangerouslySetInnerHTML: {
        __html: sanitize(htmlContent, SANITIZE_OPTIONS)
      },
      onClick: handleContentClick
    }, otherProps)), imagePreviewDetails && /*#__PURE__*/jsxRuntime.jsx(ImagePreview, {
      imagePreviewDetails: imagePreviewDetails,
      setImagePreviewDetails: setImagePreviewDetails
    })]
  });
};
var index = /*#__PURE__*/React.memo(EditorContent);

exports.index = index;
exports.substituteVariables = substituteVariables;
//# sourceMappingURL=chunk-CIuJ_EMY.cjs.js.map
