diff --git a/apps/web/package.json b/apps/web/package.json
index 1e8a26128..ea1ee8dbc 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -11,6 +11,7 @@
"@mdi/react": "^1.4.0",
"@notesnook/desktop": "./desktop/",
"@rebass/forms": "^4.0.6",
+ "@streetwritersco/tinymce-plugins": "^1.0.0",
"@tinymce/tinymce-react": "^3.12.6",
"clipboard": "^2.0.6",
"cogo-toast": "^4.2.3",
diff --git a/apps/web/src/components/editor/editor.css b/apps/web/src/components/editor/editor.css
index dbcf40b50..cf8f9f6d3 100644
--- a/apps/web/src/components/editor/editor.css
+++ b/apps/web/src/components/editor/editor.css
@@ -84,77 +84,3 @@ tox-tbtn tox-tbtn--select {
.mce-content-body[data-mce-placeholder]:not(.mce-visualblocks)::before {
margin-top: 1em !important;
}
-
-.mce-content-body h2::before,
-h3::before,
-h4::before,
-h5::before,
-h6::before {
- font-size: 12px;
- font-weight: normal;
- color: var(--fontTertiary);
- letter-spacing: 1.2px;
- padding: 1px 3px 1px 3px;
- margin-left: -31px;
- margin-right: 7px;
- cursor: row-resize;
-}
-
-.mce-content-body h2::before {
- content: "H2";
-}
-
-.mce-content-body h3::before {
- content: "H3";
-}
-
-.mce-content-body h4::before {
- content: "H4";
-}
-
-.mce-content-body h5::before {
- content: "H5";
-}
-
-.mce-content-body .c::before {
- color: var(--static);
- background-color: var(--primary);
- border-radius: 5px;
-}
-
-.h {
- display: none;
-}
-
-.tox-menu.tox-collection.tox-collection--list.tox-selected-menu {
- max-height: 190px !important;
-}
-
-.mce-content-body pre {
- overflow: auto;
- max-height: 600px;
- line-height: 1.5 !important;
- padding: 15px;
- border: 1px solid var(--border);
- border-radius: 5px;
- border: 1px solid var(--border);
- border-radius: 5px;
-}
-
-.mce-content-body code[data-mce-selected="inline-boundary"] {
- background-color: rgb(27 31 35 / 5%);
-}
-
-.mce-content-body code {
- background-color: rgb(27 31 35 / 5%);
- border: 1px solid var(--border);
- border-radius: 5px;
-}
-
-code,
-pre,
-pre * {
- font-family: ui-monospace, SFMono-Regular, SF Mono, Consolas, Liberation Mono,
- Menlo, monospace !important;
- font-size: 14px !important;
-}
diff --git a/apps/web/src/components/editor/plugins/checklist/index.js b/apps/web/src/components/editor/plugins/checklist/index.js
deleted file mode 100644
index dfd8f6603..000000000
--- a/apps/web/src/components/editor/plugins/checklist/index.js
+++ /dev/null
@@ -1 +0,0 @@
-import "./plugin";
diff --git a/apps/web/src/components/editor/plugins/checklist/plugin.js b/apps/web/src/components/editor/plugins/checklist/plugin.js
deleted file mode 100644
index 27223944c..000000000
--- a/apps/web/src/components/editor/plugins/checklist/plugin.js
+++ /dev/null
@@ -1,114 +0,0 @@
-import tinymce from "tinymce/tinymce";
-
-(function () {
- tinymce.PluginManager.add("checklist", function (editor, url) {
- /**
- * Plugin behaviour for when the Toolbar or Menu item is selected
- *
- * @private
- */
- function _onAction() {
- var content = `
`;
- editor.undoManager.transact(function () {
- editor.insertContent(content);
- });
- }
-
- editor.addCommand("InsertCheckList", function (ui, value) {
- _onAction();
- });
-
- editor.ui.registry.addButton("checklist", {
- icon: "checklist",
- tooltip: "Insert check list",
- onAction: _onAction,
- });
-
- editor.on(
- "mousedown",
- function (event) {
- var node = event.target;
- var parent = node.parentElement;
- if (event.offsetX > 0 || parent.className !== "tox-checklist") {
- return;
- }
- //editor.selection.setRng(range_selection);
-
- editor.undoManager.transact(function () {
- event.preventDefault();
- if (parent.className === "tox-checklist") {
- if (
- node.nodeName === "LI" &&
- node.className === "tox-checklist--checked"
- ) {
- node.className = "";
- } else if (node.nodeName === "LI" && node.className === "") {
- node.className = "tox-checklist--checked";
- }
- }
- });
-
- //editor.fire("input",)
- //editor.selection.setRng(range_selection);
- },
- { capture: true, passive: false }
- );
-
- editor.on(
- "touchstart",
- function (event) {
- var node = event.target;
- var parent = node.parentElement;
- if (
- event.targetTouches.length > 0 ||
- event.targetTouches[0].clientX > 45 ||
- parent.className !== "tox-checklist"
- ) {
- return;
- }
- //editor.selection.setRng(range_selection);
- editor.undoManager.transact(function () {
- event.preventDefault();
- if (parent.className === "tox-checklist") {
- node.scrollIntoView(false);
- if (
- node.nodeName === "LI" &&
- node.className === "tox-checklist--checked"
- ) {
- node.className = "";
- } else if (node.nodeName === "LI" && node.className === "") {
- node.className = "tox-checklist--checked";
- }
- }
- });
-
- //editor.fire("input",)
- //editor.selection.setRng(range_selection);
- },
- { capture: true, passive: false }
- );
-
- editor.on("NodeChange", function (event) {
- var node = event.target;
- var parent = node?.parentElement;
- if (!parent) return;
- if (parent.className === "tox-checklist") {
- if (
- node.nodeName === "LI" &&
- node.className === "tox-checklist--checked"
- ) {
- node.className = "";
- }
- }
- });
-
- editor.on("NewBlock", function (event) {
- if (
- event.newBlock.nodeName === "LI" &&
- event.newBlock.className === "tox-checklist--checked"
- ) {
- event.newBlock.className = "";
- }
- });
- });
-})();
diff --git a/apps/web/src/components/editor/plugins/code/index.js b/apps/web/src/components/editor/plugins/code/index.js
deleted file mode 100644
index dfd8f6603..000000000
--- a/apps/web/src/components/editor/plugins/code/index.js
+++ /dev/null
@@ -1 +0,0 @@
-import "./plugin";
diff --git a/apps/web/src/components/editor/plugins/code/plugin.js b/apps/web/src/components/editor/plugins/code/plugin.js
deleted file mode 100644
index b44822843..000000000
--- a/apps/web/src/components/editor/plugins/code/plugin.js
+++ /dev/null
@@ -1,379 +0,0 @@
-import tinymce from "tinymce/tinymce";
-import hljs from "highlight.js/lib/common";
-import { getCharacterRange, moveCaretTo, persistSelection } from "../utils";
-
-const TAB = " ";
-const LANGUAGE_SELECT_LABEL_SELECTOR =
- ".tox-pop__dialog span.tox-tbtn__select-label";
-const state = {
- activeBlock: null,
- languages: [{ type: "choiceitem", text: "Auto detect", value: "autodetect" }],
-};
-languagesToItems();
-
-(function () {
- var global = tinymce.util.Tools.resolve("tinymce.PluginManager");
-
- var replaceContent = function (editor, content) {
- editor.undoManager.transact(function () {
- editor.execCommand("mceInsertContent", false, content("
"));
- });
- };
-
- function createPreBlock(content) {
- const pre = document.createElement("pre");
- pre.spellcheck = false;
- pre.classList.add("hljs");
- pre.innerHTML = content;
- return pre;
- }
-
- function insertPreBlock(editor, content) {
- editor.undoManager.transact(function () {
- const pre = createPreBlock(content);
- editor.dom.setAttrib(pre, "data-mce-id", "__mcenew");
- editor.focus();
- editor.insertContent(`${pre.outerHTML}
`);
-
- setTimeout(() => {
- const insertedPre = editor.dom.select('*[data-mce-id="__mcenew"]')[0];
- editor.dom.setAttrib(insertedPre, "data-mce-id", null);
- editor.selection.select(insertedPre, true);
- editor.selection.collapse(true);
- editor.nodeChanged({ selectionChange: true });
- }, 0);
- });
- }
-
- function exitPreBlock(editor, block) {
- editor.undoManager.transact(function () {
- const p = document.createElement("p");
- p.innerHTML = "
";
- editor.focus();
- editor.dom.insertAfter(p, block);
-
- setTimeout(() => {
- editor.selection.select(p, true);
- editor.selection.collapse(true);
- editor.nodeChanged({ selectionChange: true });
- }, 0);
- });
- }
-
- var addCodeBlock = function (editor, api, type) {
- if (api && api.isActive && api.isActive()) {
- let node = editor.selection.getNode();
- const innerText = node.textContent;
- if (innerText.length <= 0) {
- replaceContent(
- editor,
- (html) => `${html.replace(/\n/gm, "
")}
`
- );
- } else {
- exitPreBlock(editor, node);
- }
- } else {
- var content = editor.selection.getContent({ format: "text" }); //.replace(/^\n/gm, "");
- if (type === "shortcut") content = "
";
- insertPreBlock(editor, content);
- }
- };
-
- var addInlineCode = function (editor) {
- var content = editor.selection.getContent({ format: "text" });
- content = content.replace(/^\n/gm, "") || " ";
-
- editor.undoManager.transact(function () {
- editor.execCommand(
- "mceInsertContent",
- false,
- `${content} `
- );
- });
-
- editor.nodeChanged({ selectionChange: true });
- };
-
- var register = function (editor) {
- editor.addCommand("mceInsertCodeBlock", function (api, args) {
- addCodeBlock(editor, api, args);
- });
-
- editor.addCommand("mceCode", function (api, value) {
- addInlineCode(editor);
- });
- };
-
- var register$1 = function (editor) {
- editor.ui.registry.addToggleButton("codeblock", {
- icon: "code-sample",
- tooltip: "Codeblock",
- onAction: function (api) {
- return addCodeBlock(editor, api);
- },
- onSetup: getNodeChangeHandler(editor),
- });
- editor.ui.registry.addToggleButton("inlinecode", {
- icon: "sourcecode",
- tooltip: "Inline code",
- onAction: function (api) {
- return addInlineCode(editor);
- },
- onSetup: function (api) {
- var nodeChangeHandler = function (e) {
- if (e.element.tagName === "CODE") {
- if (!e.element.innerHTML.trim().length) {
- e.element.remove();
- }
- api.setActive(e.element.tagName === "PRE");
- }
- };
-
- editor.on("NodeChange", nodeChangeHandler);
- return function () {
- return editor.off("NodeChange", nodeChangeHandler);
- };
- },
- });
- };
-
- var getNodeChangeHandler = function (editor) {
- return function (api) {
- var nodeChangeHandler = function (e) {
- if (e.element.tagName === "CODE") {
- if (!e.element.innerHTML.trim().length) {
- e.element.remove();
- }
- }
- api.setActive(e.element.tagName === "PRE");
- };
-
- var setContentHandler = function (e) {
- if (e.content === "") {
- e.preventDefault();
- editor.creatingCodeBlock = true;
- addCodeBlock(editor, undefined, "shortcut");
- }
- };
-
- var beforeExecCommandHandler = function (e) {
- const node = editor.selection.getNode();
- if (
- node?.tagName === "PRE" &&
- e.command === "mceInsertContent" &&
- e.value?.paste
- ) {
- e.value.content = e.value.content
- .replace(//gm, "")
- .replace(/<\/p>|
/gm, "\n");
- }
- if (editor.creatingCodeBlock && e.command === "mceInsertNewLine") {
- e.preventDefault();
- editor.creatingCodeBlock = false;
- }
- };
-
- function handleKeyDown(e) {
- if (state.activeBlock) {
- if (e.code === "Tab") {
- e.preventDefault();
- const isDeindent = e.shiftKey;
- const text = state.activeBlock.textContent;
- const characterRange = getCharacterRange(state.activeBlock);
- if (!characterRange) return;
-
- if (text.substring(characterRange.start).length > 0) {
- if (characterRange.start === characterRange.end) {
- state.activeBlock.textContent = insertAt(
- text,
- TAB,
- characterRange.start
- );
- moveCaretTo(
- state.activeBlock,
- characterRange.start + TAB.length,
- characterRange.end + TAB.length
- );
- } else {
- let content = text.substring(0, characterRange.start);
- const lines = text
- .substring(characterRange.start, characterRange.end)
- .split("\n");
- for (var i = 0; i < lines.length; ++i) {
- const line = lines[i];
- lines[i] = isDeindent
- ? line.replace(TAB, "")
- : `${TAB}${line}`;
- }
- content += lines.join("\n");
- content += text.substring(characterRange.end);
- state.activeBlock.textContent = content;
-
- const endIndex = isDeindent
- ? characterRange.end - TAB.length * lines.length
- : characterRange.end + TAB.length * lines.length;
- moveCaretTo(state.activeBlock, characterRange.start, endIndex);
- }
- } else {
- editor.insertContent(TAB);
- }
- }
- }
- }
-
- function handleKeyUp(e) {
- if (
- e.code === "Enter" ||
- e.code === "Space" ||
- e.code === "Backspace" ||
- e.code === "Tab"
- )
- applyHighlighting(editor, null, true);
- }
-
- editor.on("BeforeExecCommand", beforeExecCommandHandler);
- editor.on("BeforeSetContent", setContentHandler);
- editor.on("NodeChange", nodeChangeHandler);
- editor.on("keydown", handleKeyDown);
- editor.on("keyup", handleKeyUp);
- return function () {
- editor.off("BeforeExecCommand", beforeExecCommandHandler);
- editor.off("BeforeSetContent", setContentHandler);
- editor.off("keydown", handleKeyDown);
- editor.off("keyup", handleKeyUp);
- editor.off("NodeChange", nodeChangeHandler);
- };
- };
- };
-
- function Plugin() {
- global.add("code", function (editor) {
- setupChangeLanguageButton(editor);
- setupPreToolbar(editor);
-
- register(editor);
- register$1(editor);
-
- return {};
- });
- }
-
- Plugin();
-})();
-
-function languagesToItems() {
- const languages = hljs.listLanguages();
- languages.forEach((lang) => {
- const language = hljs.getLanguage(lang);
- state.languages.push({
- type: "choiceitem",
- text: language.name,
- value: language,
- });
- });
-}
-
-function setupPreToolbar(editor) {
- editor.ui.registry.addContextToolbar("preselection", {
- predicate: function (node) {
- if (node.nodeName === "PRE") {
- state.activeBlock = node;
- const language = detectCodeblockLanguage(node);
- changeSelectedLanguage(editor, language, true);
- return true;
- } else if (
- node.parentElement.nodeName !== "PRE" &&
- node.className !== "line"
- ) {
- state.activeBlock = null;
- }
- return false;
- },
- items: "copy hljs-languages",
- position: "node",
- });
-}
-
-function setupChangeLanguageButton(editor, text) {
- editor.ui.registry.addSplitButton("hljs-languages", {
- text: text || "Auto detect",
- onAction: function () {
- const isAutoDetect = text === "Auto detect" || !text;
- if (!isAutoDetect) applyHighlighting(editor, null, true);
- else applyHighlighting(editor, null, false, true);
- },
- onItemAction: function (_buttonApi, value) {
- changeSelectedLanguage(editor, value);
- },
- select: (value) => value?.name === text,
- fetch: (callback) => {
- callback(state.languages);
- },
- });
-}
-
-function changeSelectedLanguage(editor, value, highlighted = false) {
- if (!highlighted) applyHighlighting(editor, value);
-
- const label = document.querySelector(LANGUAGE_SELECT_LABEL_SELECTOR);
- if (!label || label?.textContent === value?.name) return;
- label.textContent = value?.name || "Auto detect";
-
- setupChangeLanguageButton(editor, value?.name);
-}
-
-function detectCodeblockLanguage(node, auto = false) {
- if (node?.tagName !== "PRE") return;
-
- const languageAliases = getLanguageFromClassName(node.className).split("-");
- if (languageAliases.length > 1) {
- return hljs.getLanguage(languageAliases[1]);
- } else if (auto) {
- const result = hljs.highlightAuto(node.innerText);
- if (result.errorRaised) {
- console.error(result.errorRaised);
- return;
- }
- return hljs.getLanguage(result.language);
- }
-}
-
-function applyHighlighting(editor, language, refresh = false, auto = false) {
- const node = state.activeBlock;
- const detectedLanguage = detectCodeblockLanguage(node, auto);
-
- const isDifferentLanguage = detectedLanguage?.name !== language?.name;
- const shouldHighlight = refresh || !detectedLanguage || isDifferentLanguage;
- if (!shouldHighlight) return;
-
- if (refresh || auto) language = detectedLanguage;
- if (!language || !language.aliases?.length) return;
-
- const alias = language.aliases[0];
-
- persistSelection(node, () => {
- node.innerHTML = hljs.highlight(node.innerText, {
- language: alias,
- }).value;
- editor.save();
- });
-
- if (refresh) return;
-
- node.className = node.className.replace(
- getLanguageFromClassName(node.className),
- ` language-${alias} `
- );
-
- if (auto) changeSelectedLanguage(editor, language, true);
-}
-
-function insertAt(str, token, index) {
- return str.substring(0, index) + token + str.substring(index);
-}
-
-function getLanguageFromClassName(className) {
- const classes = className.split(" ");
- const languageKey = classes.find((c) => c.startsWith("lang"));
- return languageKey || "";
-}
diff --git a/apps/web/src/components/editor/plugins/collapsibleheaders/index.js b/apps/web/src/components/editor/plugins/collapsibleheaders/index.js
deleted file mode 100644
index dfd8f6603..000000000
--- a/apps/web/src/components/editor/plugins/collapsibleheaders/index.js
+++ /dev/null
@@ -1 +0,0 @@
-import "./plugin";
diff --git a/apps/web/src/components/editor/plugins/collapsibleheaders/plugin.js b/apps/web/src/components/editor/plugins/collapsibleheaders/plugin.js
deleted file mode 100644
index df15e7a2d..000000000
--- a/apps/web/src/components/editor/plugins/collapsibleheaders/plugin.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import tinymce from "tinymce/tinymce";
-
-const COLLAPSED_KEY = "c";
-const HIDDEN_KEY = "h";
-const collapsibleTags = { HR: 1, H2: 2, H3: 3, H4: 4, H5: 5 };
-
-function toggleElementVisibility(element, toggleState) {
- if (!toggleState) element.classList.remove(HIDDEN_KEY);
- else element.classList.add(HIDDEN_KEY);
-}
-
-function collapseElement(target) {
- let sibling = target.nextSibling;
- const isTargetCollapsed = target.classList.contains(COLLAPSED_KEY);
- let skip = false;
-
- while (
- sibling &&
- (!collapsibleTags[sibling.tagName] ||
- collapsibleTags[sibling.tagName] > collapsibleTags[target.tagName])
- ) {
- const isCollapsed = sibling.classList.contains(COLLAPSED_KEY);
- if (!isTargetCollapsed) {
- if (isCollapsed) {
- skip = true;
- toggleElementVisibility(sibling, isTargetCollapsed);
- } else if (skip && collapsibleTags[sibling.tagName]) {
- skip = false;
- }
- }
- if (!skip) {
- toggleElementVisibility(sibling, isTargetCollapsed);
- }
- if (!sibling.nextSibling) break;
- sibling = sibling.nextSibling;
- }
-}
-
-(function () {
- tinymce.PluginManager.add("collapsibleheaders", function (editor, url) {
- editor.on(
- "mousedown touchstart",
- function (e) {
- const { target } = e;
- if (
- e.offsetX < 0 &&
- collapsibleTags[target.tagName] &&
- target.parentElement.tagName === "DIV"
- ) {
- e.preventDefault();
- e.stopImmediatePropagation();
- e.stopPropagation();
- editor.undoManager.transact(() => {
- if (target.classList.contains(COLLAPSED_KEY)) {
- target.classList.remove(COLLAPSED_KEY);
- } else {
- target.classList.add(COLLAPSED_KEY);
- }
- collapseElement(target);
- // onSave();
- });
- }
- },
- { capture: true, passive: false }
- );
-
- editor.on("NewBlock", function (event) {
- const { newBlock } = event;
- const target = newBlock?.previousElementSibling;
- if (target?.classList.contains(COLLAPSED_KEY)) {
- target.classList.remove(COLLAPSED_KEY);
- collapseElement(target);
- }
- });
- });
-})();
diff --git a/apps/web/src/components/editor/plugins/paste/index.js b/apps/web/src/components/editor/plugins/paste/index.js
deleted file mode 100644
index dfd8f6603..000000000
--- a/apps/web/src/components/editor/plugins/paste/index.js
+++ /dev/null
@@ -1 +0,0 @@
-import "./plugin";
diff --git a/apps/web/src/components/editor/plugins/paste/plugin.js b/apps/web/src/components/editor/plugins/paste/plugin.js
deleted file mode 100644
index f03cf1adc..000000000
--- a/apps/web/src/components/editor/plugins/paste/plugin.js
+++ /dev/null
@@ -1,1992 +0,0 @@
-import tinymce from "tinymce/tinymce";
-
-/**
- * Copyright (c) Tiny Technologies, Inc. All rights reserved.
- * Licensed under the LGPL or a commercial license.
- * For LGPL see License.txt in the project root for license information.
- * For commercial licenses see https://www.tiny.cloud/
- *
- * Version: 5.8.1 (2021-05-20)
- */
-(function () {
- var Cell = function (initial) {
- var value = initial;
- var get = function () {
- return value;
- };
- var set = function (v) {
- value = v;
- };
- return {
- get: get,
- set: set,
- };
- };
-
- var global = tinymce.util.Tools.resolve("tinymce.PluginManager");
-
- var hasProPlugin = function (editor) {
- if (editor.hasPlugin("powerpaste", true)) {
- if (typeof window.console !== "undefined" && window.console.log) {
- window.console.log(
- "PowerPaste is incompatible with Paste plugin! Remove 'paste' from the 'plugins' option."
- );
- }
- return true;
- } else {
- return false;
- }
- };
-
- var get = function (clipboard, quirks) {
- return {
- clipboard: clipboard,
- quirks: quirks,
- };
- };
-
- var isSimpleType = function (type) {
- return function (value) {
- return typeof value === type;
- };
- };
- var isNullable = function (a) {
- return a === null || a === undefined;
- };
- var isNonNullable = function (a) {
- return !isNullable(a);
- };
- var isFunction = isSimpleType("function");
-
- var noop = function () {};
- var constant = function (value) {
- return function () {
- return value;
- };
- };
- var never = constant(false);
- var always = constant(true);
-
- var none = function () {
- return NONE;
- };
- var NONE = (function () {
- var eq = function (o) {
- return o.isNone();
- };
- var call = function (thunk) {
- return thunk();
- };
- var id = function (n) {
- return n;
- };
- var me = {
- fold: function (n, _s) {
- return n();
- },
- is: never,
- isSome: never,
- isNone: always,
- getOr: id,
- getOrThunk: call,
- getOrDie: function (msg) {
- throw new Error(msg || "error: getOrDie called on none.");
- },
- getOrNull: constant(null),
- getOrUndefined: constant(undefined),
- or: id,
- orThunk: call,
- map: none,
- each: noop,
- bind: none,
- exists: never,
- forall: always,
- filter: none,
- equals: eq,
- equals_: eq,
- toArray: function () {
- return [];
- },
- toString: constant("none()"),
- };
- return me;
- })();
- var some = function (a) {
- var constant_a = constant(a);
- var self = function () {
- return me;
- };
- var bind = function (f) {
- return f(a);
- };
- var me = {
- fold: function (n, s) {
- return s(a);
- },
- is: function (v) {
- return a === v;
- },
- isSome: always,
- isNone: never,
- getOr: constant_a,
- getOrThunk: constant_a,
- getOrDie: constant_a,
- getOrNull: constant_a,
- getOrUndefined: constant_a,
- or: self,
- orThunk: self,
- map: function (f) {
- return some(f(a));
- },
- each: function (f) {
- f(a);
- },
- bind: bind,
- exists: bind,
- forall: bind,
- filter: function (f) {
- return f(a) ? me : NONE;
- },
- toArray: function () {
- return [a];
- },
- toString: function () {
- return "some(" + a + ")";
- },
- equals: function (o) {
- return o.is(a);
- },
- equals_: function (o, elementEq) {
- return o.fold(never, function (b) {
- return elementEq(a, b);
- });
- },
- };
- return me;
- };
- var from = function (value) {
- return value === null || value === undefined ? NONE : some(value);
- };
- var Optional = {
- some: some,
- none: none,
- from: from,
- };
-
- var nativeSlice = Array.prototype.slice;
- var exists = function (xs, pred) {
- for (var i = 0, len = xs.length; i < len; i++) {
- var x = xs[i];
- if (pred(x, i)) {
- return true;
- }
- }
- return false;
- };
- var map = function (xs, f) {
- var len = xs.length;
- var r = new Array(len);
- for (var i = 0; i < len; i++) {
- var x = xs[i];
- r[i] = f(x, i);
- }
- return r;
- };
- var each = function (xs, f) {
- for (var i = 0, len = xs.length; i < len; i++) {
- var x = xs[i];
- f(x, i);
- }
- };
- var filter = function (xs, pred) {
- var r = [];
- for (var i = 0, len = xs.length; i < len; i++) {
- var x = xs[i];
- if (pred(x, i)) {
- r.push(x);
- }
- }
- return r;
- };
- var foldl = function (xs, f, acc) {
- each(xs, function (x) {
- acc = f(acc, x);
- });
- return acc;
- };
- var from$1 = isFunction(Array.from)
- ? Array.from
- : function (x) {
- return nativeSlice.call(x);
- };
-
- var value = function () {
- var subject = Cell(Optional.none());
- var clear = function () {
- return subject.set(Optional.none());
- };
- var set = function (s) {
- return subject.set(Optional.some(s));
- };
- var isSet = function () {
- return subject.get().isSome();
- };
- var on = function (f) {
- return subject.get().each(f);
- };
- return {
- clear: clear,
- set: set,
- isSet: isSet,
- on: on,
- };
- };
-
- var checkRange = function (str, substr, start) {
- return (
- substr === "" ||
- (str.length >= substr.length &&
- str.substr(start, start + substr.length) === substr)
- );
- };
- var startsWith = function (str, prefix) {
- return checkRange(str, prefix, 0);
- };
- var endsWith = function (str, suffix) {
- return checkRange(str, suffix, str.length - suffix.length);
- };
- var repeat = function (s, count) {
- return count <= 0 ? "" : new Array(count + 1).join(s);
- };
-
- var global$1 = tinymce.util.Tools.resolve("tinymce.Env");
-
- var global$2 = tinymce.util.Tools.resolve("tinymce.util.Delay");
-
- var global$3 = tinymce.util.Tools.resolve("tinymce.util.Promise");
-
- var global$4 = tinymce.util.Tools.resolve("tinymce.util.VK");
-
- var firePastePreProcess = function (editor, html, internal, isWordHtml) {
- return editor.fire("PastePreProcess", {
- content: html,
- internal: internal,
- wordContent: isWordHtml,
- });
- };
- var firePastePostProcess = function (editor, node, internal, isWordHtml) {
- return editor.fire("PastePostProcess", {
- node: node,
- internal: internal,
- wordContent: isWordHtml,
- });
- };
- var firePastePlainTextToggle = function (editor, state) {
- return editor.fire("PastePlainTextToggle", { state: state });
- };
- var firePaste = function (editor, ieFake) {
- return editor.fire("paste", { ieFake: ieFake });
- };
-
- var global$5 = tinymce.util.Tools.resolve("tinymce.util.Tools");
-
- var shouldBlockDrop = function (editor) {
- return editor.getParam("paste_block_drop", false);
- };
- var shouldPasteDataImages = function (editor) {
- return editor.getParam("paste_data_images", false);
- };
- var shouldFilterDrop = function (editor) {
- return editor.getParam("paste_filter_drop", true);
- };
- var getPreProcess = function (editor) {
- return editor.getParam("paste_preprocess");
- };
- var getPostProcess = function (editor) {
- return editor.getParam("paste_postprocess");
- };
- var getWebkitStyles = function (editor) {
- return editor.getParam("paste_webkit_styles");
- };
- var shouldRemoveWebKitStyles = function (editor) {
- return editor.getParam("paste_remove_styles_if_webkit", true);
- };
- var shouldMergeFormats = function (editor) {
- return editor.getParam("paste_merge_formats", true);
- };
- var isSmartPasteEnabled = function (editor) {
- return editor.getParam("smart_paste", true);
- };
- var isPasteAsTextEnabled = function (editor) {
- return editor.getParam("paste_as_text", false);
- };
- var getRetainStyleProps = function (editor) {
- return editor.getParam("paste_retain_style_properties");
- };
- var getWordValidElements = function (editor) {
- var defaultValidElements =
- "-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6," +
- "-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr," +
- "td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody";
- return editor.getParam("paste_word_valid_elements", defaultValidElements);
- };
- var shouldConvertWordFakeLists = function (editor) {
- return editor.getParam("paste_convert_word_fake_lists", true);
- };
- var shouldUseDefaultFilters = function (editor) {
- return editor.getParam("paste_enable_default_filters", true);
- };
- var getValidate = function (editor) {
- return editor.getParam("validate");
- };
- var getAllowHtmlDataUrls = function (editor) {
- return editor.getParam("allow_html_data_urls", false, "boolean");
- };
- var getPasteDataImages = function (editor) {
- return editor.getParam("paste_data_images", false, "boolean");
- };
- var getImagesDataImgFilter = function (editor) {
- return editor.getParam("images_dataimg_filter");
- };
- var getImagesReuseFilename = function (editor) {
- return editor.getParam("images_reuse_filename");
- };
- var getForcedRootBlock = function (editor) {
- return editor.getParam("forced_root_block");
- };
- var getForcedRootBlockAttrs = function (editor) {
- return editor.getParam("forced_root_block_attrs");
- };
- var getTabSpaces = function (editor) {
- return editor.getParam("paste_tab_spaces", 4, "number");
- };
- var getAllowedImageFileTypes = function (editor) {
- var defaultImageFileTypes = "jpeg,jpg,jpe,jfi,jif,jfif,png,gif,bmp,webp";
- return global$5.explode(
- editor.getParam("images_file_types", defaultImageFileTypes, "string")
- );
- };
-
- var internalMimeType = "x-tinymce/html";
- var internalMark = "";
- var mark = function (html) {
- return internalMark + html;
- };
- var unmark = function (html) {
- return html.replace(internalMark, "");
- };
- var isMarked = function (html) {
- return html.indexOf(internalMark) !== -1;
- };
- var internalHtmlMime = function () {
- return internalMimeType;
- };
-
- var global$6 = tinymce.util.Tools.resolve("tinymce.html.Entities");
-
- var isPlainText = function (text) {
- return !/<(?:\/?(?!(?:div|p|br|span)>)\w+|(?:(?!(?:span style="white-space:\s?pre;?">)|br\s?\/>))\w+\s[^>]+)>/i.test(
- text
- );
- };
- var toBRs = function (text) {
- return text.replace(/\r?\n/g, "
");
- };
- var openContainer = function (rootTag, rootAttrs) {
- var key;
- var attrs = [];
- var tag = "<" + rootTag;
- if (typeof rootAttrs === "object") {
- for (key in rootAttrs) {
- if (rootAttrs.hasOwnProperty(key)) {
- attrs.push(key + '="' + global$6.encodeAllRaw(rootAttrs[key]) + '"');
- }
- }
- if (attrs.length) {
- tag += " " + attrs.join(" ");
- }
- }
- return tag + ">";
- };
- var toBlockElements = function (text, rootTag, rootAttrs) {
- var blocks = text.split(/\n\n/);
- var tagOpen = openContainer(rootTag, rootAttrs);
- var tagClose = "" + rootTag + ">";
- var paragraphs = global$5.map(blocks, function (p) {
- return p.split(/\n/).join("
");
- });
- var stitch = function (p) {
- return tagOpen + p + tagClose;
- };
- return paragraphs.length === 1
- ? paragraphs[0]
- : global$5.map(paragraphs, stitch).join("");
- };
- var convert = function (text, rootTag, rootAttrs) {
- return rootTag
- ? toBlockElements(text, rootTag === true ? "p" : rootTag, rootAttrs)
- : toBRs(text);
- };
-
- var global$7 = tinymce.util.Tools.resolve("tinymce.html.DomParser");
-
- var global$8 = tinymce.util.Tools.resolve("tinymce.html.Serializer");
-
- var nbsp = "\xA0";
-
- var global$9 = tinymce.util.Tools.resolve("tinymce.html.Node");
-
- var global$a = tinymce.util.Tools.resolve("tinymce.html.Schema");
-
- var filter$1 = function (content, items) {
- global$5.each(items, function (v) {
- if (v.constructor === RegExp) {
- content = content.replace(v, "");
- } else {
- content = content.replace(v[0], v[1]);
- }
- });
- return content;
- };
- var innerText = function (html) {
- var schema = global$a();
- var domParser = global$7({}, schema);
- var text = "";
- var shortEndedElements = schema.getShortEndedElements();
- var ignoreElements = global$5.makeMap(
- "script noscript style textarea video audio iframe object",
- " "
- );
- var blockElements = schema.getBlockElements();
- var walk = function (node) {
- var name = node.name,
- currentNode = node;
- if (name === "br") {
- text += "\n";
- return;
- }
- if (name === "wbr") {
- return;
- }
- if (shortEndedElements[name]) {
- text += " ";
- }
- if (ignoreElements[name]) {
- text += " ";
- return;
- }
- if (node.type === 3) {
- text += node.value;
- }
- if (!node.shortEnded) {
- if ((node = node.firstChild)) {
- do {
- walk(node);
- } while ((node = node.next));
- }
- }
- if (blockElements[name] && currentNode.next) {
- text += "\n";
- if (name === "p") {
- text += "\n";
- }
- }
- };
- html = filter$1(html, [//g]);
- walk(domParser.parse(html));
- return text;
- };
- var trimHtml = function (html) {
- var trimSpaces = function (all, s1, s2) {
- if (!s1 && !s2) {
- return " ";
- }
- return nbsp;
- };
- html = filter$1(html, [
- /^[\s\S]*
]*>\s*|\s*<\/body[^>]*>[\s\S]*$/gi,
- /|/g,
- [
- /( ?)\u00a0<\/span>( ?)/g,
- trimSpaces,
- ],
- /
/g,
- /
$/i,
- ]);
- return html;
- };
- var createIdGenerator = function (prefix) {
- var count = 0;
- return function () {
- return prefix + count++;
- };
- };
- var getImageMimeType = function (ext) {
- var lowerExt = ext.toLowerCase();
- var mimeOverrides = {
- jpg: "jpeg",
- jpe: "jpeg",
- jfi: "jpeg",
- jif: "jpeg",
- jfif: "jpeg",
- pjpeg: "jpeg",
- pjp: "jpeg",
- svg: "svg+xml",
- };
- return global$5.hasOwn(mimeOverrides, lowerExt)
- ? "image/" + mimeOverrides[lowerExt]
- : "image/" + lowerExt;
- };
-
- var isWordContent = function (content) {
- return (
- / 1) {
- currentListNode.attr("start", "" + start);
- }
- paragraphNode.wrap(currentListNode);
- } else {
- currentListNode.append(paragraphNode);
- }
- paragraphNode.name = "li";
- if (level > lastLevel && prevListNode) {
- prevListNode.lastChild.append(currentListNode);
- }
- lastLevel = level;
- removeIgnoredNodes(paragraphNode);
- trimListStart(paragraphNode, /^\u00a0+/);
- trimListStart(paragraphNode, /^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/);
- trimListStart(paragraphNode, /^\u00a0+/);
- };
- var elements = [];
- var child = node.firstChild;
- while (typeof child !== "undefined" && child !== null) {
- elements.push(child);
- child = child.walk();
- if (child !== null) {
- while (typeof child !== "undefined" && child.parent !== node) {
- child = child.walk();
- }
- }
- }
- for (var i = 0; i < elements.length; i++) {
- node = elements[i];
- if (node.name === "p" && node.firstChild) {
- var nodeText = getText(node);
- if (isBulletList(nodeText)) {
- convertParagraphToLi(node, "ul");
- continue;
- }
- if (isNumericList(nodeText)) {
- var matches = /([0-9]+)\./.exec(nodeText);
- var start = 1;
- if (matches) {
- start = parseInt(matches[1], 10);
- }
- convertParagraphToLi(node, "ol", start);
- continue;
- }
- if (node._listLevel) {
- convertParagraphToLi(node, "ul", 1);
- continue;
- }
- currentListNode = null;
- } else {
- prevListNode = currentListNode;
- currentListNode = null;
- }
- }
- };
- var filterStyles = function (editor, validStyles, node, styleValue) {
- var outputStyles = {},
- matches;
- var styles = editor.dom.parseStyle(styleValue);
- global$5.each(styles, function (value, name) {
- switch (name) {
- case "mso-list":
- matches = /\w+ \w+([0-9]+)/i.exec(styleValue);
- if (matches) {
- node._listLevel = parseInt(matches[1], 10);
- }
- if (/Ignore/i.test(value) && node.firstChild) {
- node._listIgnore = true;
- node.firstChild._listIgnore = true;
- }
- break;
- case "horiz-align":
- name = "text-align";
- break;
- case "vert-align":
- name = "vertical-align";
- break;
- case "font-color":
- case "mso-foreground":
- name = "color";
- break;
- case "mso-background":
- case "mso-highlight":
- name = "background";
- break;
- case "font-weight":
- case "font-style":
- if (value !== "normal") {
- outputStyles[name] = value;
- }
- return;
- case "mso-element":
- if (/^(comment|comment-list)$/i.test(value)) {
- node.remove();
- return;
- }
- break;
- default:
- break;
- }
- if (name.indexOf("mso-comment") === 0) {
- node.remove();
- return;
- }
- if (name.indexOf("mso-") === 0) {
- return;
- }
- if (
- getRetainStyleProps(editor) === "all" ||
- (validStyles && validStyles[name])
- ) {
- outputStyles[name] = value;
- }
- });
- if (/(bold)/i.test(outputStyles["font-weight"])) {
- delete outputStyles["font-weight"];
- node.wrap(new global$9("b", 1));
- }
- if (/(italic)/i.test(outputStyles["font-style"])) {
- delete outputStyles["font-style"];
- node.wrap(new global$9("i", 1));
- }
- outputStyles = editor.dom.serializeStyle(outputStyles, node.name);
- if (outputStyles) {
- return outputStyles;
- }
- return null;
- };
- var filterWordContent = function (editor, content) {
- var validStyles;
- var retainStyleProperties = getRetainStyleProps(editor);
- if (retainStyleProperties) {
- validStyles = global$5.makeMap(retainStyleProperties.split(/[, ]/));
- }
- content = filter$1(content, [
- /
/gi,
- /]+id="?docs-internal-[^>]*>/gi,
- //gi,
- /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s/>]))[^>]*>/gi,
- [/<(\/?)s>/gi, "<$1strike>"],
- [/ /gi, nbsp],
- [
- /([\s\u00a0]*)<\/span>/gi,
- function (str, spaces) {
- return spaces.length > 0
- ? spaces
- .replace(/./, " ")
- .slice(Math.floor(spaces.length / 2))
- .split("")
- .join(nbsp)
- : "";
- },
- ],
- ]);
- var validElements = getWordValidElements(editor);
- var schema = global$a({
- valid_elements: validElements,
- valid_children: "-li[p]",
- });
- global$5.each(schema.elements, function (rule) {
- if (!rule.attributes.class) {
- rule.attributes.class = {};
- rule.attributesOrder.push("class");
- }
- if (!rule.attributes.style) {
- rule.attributes.style = {};
- rule.attributesOrder.push("style");
- }
- });
- var domParser = global$7({}, schema);
- domParser.addAttributeFilter("style", function (nodes) {
- var i = nodes.length,
- node;
- while (i--) {
- node = nodes[i];
- node.attr(
- "style",
- filterStyles(editor, validStyles, node, node.attr("style"))
- );
- if (node.name === "span" && node.parent && !node.attributes.length) {
- node.unwrap();
- }
- }
- });
- domParser.addAttributeFilter("class", function (nodes) {
- var i = nodes.length,
- node,
- className;
- while (i--) {
- node = nodes[i];
- className = node.attr("class");
- if (/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(className)) {
- node.remove();
- }
- node.attr("class", null);
- }
- });
- domParser.addNodeFilter("del", function (nodes) {
- var i = nodes.length;
- while (i--) {
- nodes[i].remove();
- }
- });
- domParser.addNodeFilter("a", function (nodes) {
- var i = nodes.length,
- node,
- href,
- name;
- while (i--) {
- node = nodes[i];
- href = node.attr("href");
- name = node.attr("name");
- if (href && href.indexOf("#_msocom_") !== -1) {
- node.remove();
- continue;
- }
- if (href && href.indexOf("file://") === 0) {
- href = href.split("#")[1];
- if (href) {
- href = "#" + href;
- }
- }
- if (!href && !name) {
- node.unwrap();
- } else {
- if (name && !/^_?(?:toc|edn|ftn)/i.test(name)) {
- node.unwrap();
- continue;
- }
- node.attr({
- href: href,
- name: name,
- });
- }
- }
- });
- var rootNode = domParser.parse(content);
- if (shouldConvertWordFakeLists(editor)) {
- convertFakeListsToProperLists(rootNode);
- }
- content = global$8({ validate: getValidate(editor) }, schema).serialize(
- rootNode
- );
- return content;
- };
- var preProcess = function (editor, content) {
- return shouldUseDefaultFilters(editor)
- ? filterWordContent(editor, content)
- : content;
- };
-
- var preProcess$1 = function (editor, html) {
- var parser = global$7({}, editor.schema);
- parser.addNodeFilter("meta", function (nodes) {
- global$5.each(nodes, function (node) {
- node.remove();
- });
- });
- var fragment = parser.parse(html, {
- forced_root_block: false,
- isRootContent: true,
- });
- return global$8({ validate: getValidate(editor) }, editor.schema).serialize(
- fragment
- );
- };
- var processResult = function (content, cancelled) {
- return {
- content: content,
- cancelled: cancelled,
- };
- };
- var postProcessFilter = function (editor, html, internal, isWordHtml) {
- var tempBody = editor.dom.create("div", { style: "display:none" }, html);
- var postProcessArgs = firePastePostProcess(
- editor,
- tempBody,
- internal,
- isWordHtml
- );
- return processResult(
- postProcessArgs.node.innerHTML,
- postProcessArgs.isDefaultPrevented()
- );
- };
- var filterContent = function (editor, content, internal, isWordHtml) {
- var preProcessArgs = firePastePreProcess(
- editor,
- content,
- internal,
- isWordHtml
- );
- var filteredContent = preProcess$1(editor, preProcessArgs.content);
- if (
- editor.hasEventListeners("PastePostProcess") &&
- !preProcessArgs.isDefaultPrevented()
- ) {
- return postProcessFilter(editor, filteredContent, internal, isWordHtml);
- } else {
- return processResult(
- filteredContent,
- preProcessArgs.isDefaultPrevented()
- );
- }
- };
- var process = function (editor, html, internal) {
- var isWordHtml = isWordContent(html);
- var content = isWordHtml ? preProcess(editor, html) : html;
- return filterContent(editor, content, internal, isWordHtml);
- };
-
- var pasteHtml = function (editor, html) {
- editor.insertContent(html, {
- merge: shouldMergeFormats(editor),
- paste: true,
- });
- return true;
- };
- var isAbsoluteUrl = function (url) {
- return /^https?:\/\/[\w?\-/+=.&%@~#]+$/i.test(url);
- };
- var isImageUrl = function (editor, url) {
- return (
- isAbsoluteUrl(url) &&
- exists(getAllowedImageFileTypes(editor), function (type) {
- return endsWith(url.toLowerCase(), "." + type.toLowerCase());
- })
- );
- };
- var createImage = function (editor, url, pasteHtmlFn) {
- editor.undoManager.extra(
- function () {
- pasteHtmlFn(editor, url);
- },
- function () {
- editor.insertContent('
');
- }
- );
- return true;
- };
- var createLink = function (editor, url, pasteHtmlFn) {
- editor.undoManager.extra(
- function () {
- pasteHtmlFn(editor, url);
- },
- function () {
- editor.execCommand("mceInsertLink", false, url);
- }
- );
- return true;
- };
- var linkSelection = function (editor, html, pasteHtmlFn) {
- return editor.selection.isCollapsed() === false && isAbsoluteUrl(html)
- ? createLink(editor, html, pasteHtmlFn)
- : false;
- };
- var insertImage = function (editor, html, pasteHtmlFn) {
- return isImageUrl(editor, html)
- ? createImage(editor, html, pasteHtmlFn)
- : false;
- };
- var smartInsertContent = function (editor, html) {
- global$5.each([linkSelection, insertImage, pasteHtml], function (action) {
- return action(editor, html, pasteHtml) !== true;
- });
- };
- var insertContent = function (editor, html, pasteAsText) {
- if (pasteAsText || isSmartPasteEnabled(editor) === false) {
- pasteHtml(editor, html);
- } else {
- smartInsertContent(editor, html);
- }
- };
-
- var isCollapsibleWhitespace = function (c) {
- return " \f\t\x0B".indexOf(c) !== -1;
- };
- var isNewLineChar = function (c) {
- return c === "\n" || c === "\r";
- };
- var isNewline = function (text, idx) {
- return idx < text.length && idx >= 0 ? isNewLineChar(text[idx]) : false;
- };
- var normalizeWhitespace = function (editor, text) {
- var tabSpace = repeat(" ", getTabSpaces(editor));
- var normalizedText = text.replace(/\t/g, tabSpace);
- var result = foldl(
- normalizedText,
- function (acc, c) {
- if (isCollapsibleWhitespace(c) || c === nbsp) {
- if (
- acc.pcIsSpace ||
- acc.str === "" ||
- acc.str.length === normalizedText.length - 1 ||
- isNewline(normalizedText, acc.str.length + 1)
- ) {
- return {
- pcIsSpace: false,
- str: acc.str + nbsp,
- };
- } else {
- return {
- pcIsSpace: true,
- str: acc.str + " ",
- };
- }
- } else {
- return {
- pcIsSpace: isNewLineChar(c),
- str: acc.str + c,
- };
- }
- },
- {
- pcIsSpace: false,
- str: "",
- }
- );
- return result.str;
- };
-
- var doPaste = function (editor, content, internal, pasteAsText) {
- var args = process(editor, content, internal);
- if (args.cancelled === false) {
- insertContent(editor, args.content, pasteAsText);
- }
- };
- var pasteHtml$1 = function (editor, html, internalFlag) {
- var internal = internalFlag ? internalFlag : isMarked(html);
- doPaste(editor, unmark(html), internal, false);
- };
- var pasteText = function (editor, text) {
- var encodedText = editor.dom.encode(text).replace(/\r\n/g, "\n");
- var normalizedText = normalizeWhitespace(editor, encodedText);
- var html = convert(
- normalizedText,
- getForcedRootBlock(editor),
- getForcedRootBlockAttrs(editor)
- );
- doPaste(editor, html, false, true);
- };
- var getDataTransferItems = function (dataTransfer) {
- var items = {};
- var mceInternalUrlPrefix = "data:text/mce-internal,";
- if (dataTransfer) {
- if (dataTransfer.getData) {
- var legacyText = dataTransfer.getData("Text");
- if (legacyText && legacyText.length > 0) {
- if (legacyText.indexOf(mceInternalUrlPrefix) === -1) {
- items["text/plain"] = legacyText;
- }
- }
- }
- if (dataTransfer.types) {
- for (var i = 0; i < dataTransfer.types.length; i++) {
- var contentType = dataTransfer.types[i];
- try {
- items[contentType] = dataTransfer.getData(contentType);
- } catch (ex) {
- items[contentType] = "";
- }
- }
- }
- }
- return items;
- };
- var getClipboardContent = function (editor, clipboardEvent) {
- return getDataTransferItems(
- clipboardEvent.clipboardData || editor.getDoc().dataTransfer
- );
- };
- var hasContentType = function (clipboardContent, mimeType) {
- return (
- mimeType in clipboardContent && clipboardContent[mimeType].length > 0
- );
- };
- var hasHtmlOrText = function (content) {
- return (
- hasContentType(content, "text/html") ||
- hasContentType(content, "text/plain")
- );
- };
- var parseDataUri = function (uri) {
- var matches = /data:([^;]+);base64,([a-z0-9+/=]+)/i.exec(uri);
- if (matches) {
- return {
- type: matches[1],
- data: decodeURIComponent(matches[2]),
- };
- } else {
- return {
- type: null,
- data: null,
- };
- }
- };
- var isValidDataUriImage = function (editor, imgElm) {
- var filter = getImagesDataImgFilter(editor);
- return filter ? filter(imgElm) : true;
- };
- var extractFilename = function (editor, str) {
- var m = str.match(/([\s\S]+?)(?:\.[a-z0-9.]+)$/i);
- return isNonNullable(m) ? editor.dom.encode(m[1]) : null;
- };
- var uniqueId = createIdGenerator("mceclip");
- var pasteImage = function (editor, imageItem) {
- var _a = parseDataUri(imageItem.uri),
- base64 = _a.data,
- type = _a.type;
- var id = uniqueId();
- var file = imageItem.blob;
- var img = new Image();
- img.src = imageItem.uri;
- if (isValidDataUriImage(editor, img)) {
- var blobCache = editor.editorUpload.blobCache;
- var blobInfo = void 0;
- var existingBlobInfo = blobCache.getByData(base64, type);
- if (!existingBlobInfo) {
- var useFileName =
- getImagesReuseFilename(editor) && isNonNullable(file.name);
- var name_1 = useFileName ? extractFilename(editor, file.name) : id;
- var filename = useFileName ? file.name : undefined;
- blobInfo = blobCache.create(id, file, base64, name_1, filename);
- blobCache.add(blobInfo);
- } else {
- blobInfo = existingBlobInfo;
- }
- pasteHtml$1(editor, '
', false);
- } else {
- pasteHtml$1(editor, '
', false);
- }
- };
- var isClipboardEvent = function (event) {
- return event.type === "paste";
- };
- var isDataTransferItem = function (item) {
- return isNonNullable(item.getAsFile);
- };
- var readFilesAsDataUris = function (items) {
- return global$3.all(
- map(items, function (item) {
- return new global$3(function (resolve) {
- var blob = isDataTransferItem(item) ? item.getAsFile() : item;
- var reader = new window.FileReader();
- reader.onload = function () {
- resolve({
- blob: blob,
- uri: reader.result,
- });
- };
- reader.readAsDataURL(blob);
- });
- })
- );
- };
- var isImage = function (editor) {
- var allowedExtensions = getAllowedImageFileTypes(editor);
- return function (file) {
- return (
- startsWith(file.type, "image/") &&
- exists(allowedExtensions, function (extension) {
- return getImageMimeType(extension) === file.type;
- })
- );
- };
- };
- var getImagesFromDataTransfer = function (editor, dataTransfer) {
- var items = dataTransfer.items
- ? map(from$1(dataTransfer.items), function (item) {
- return item.getAsFile();
- })
- : [];
- var files = dataTransfer.files ? from$1(dataTransfer.files) : [];
- return filter(items.length > 0 ? items : files, isImage(editor));
- };
- var pasteImageData = function (editor, e, rng) {
- var dataTransfer = isClipboardEvent(e) ? e.clipboardData : e.dataTransfer;
- if (getPasteDataImages(editor) && dataTransfer) {
- var images = getImagesFromDataTransfer(editor, dataTransfer);
- if (images.length > 0) {
- e.preventDefault();
- readFilesAsDataUris(images).then(function (fileResults) {
- if (rng) {
- editor.selection.setRng(rng);
- }
- each(fileResults, function (result) {
- pasteImage(editor, result);
- });
- });
- return true;
- }
- }
- return false;
- };
- var isBrokenAndroidClipboardEvent = function (e) {
- var clipboardData = e.clipboardData;
- return (
- navigator.userAgent.indexOf("Android") !== -1 &&
- clipboardData &&
- clipboardData.items &&
- clipboardData.items.length === 0
- );
- };
- var isKeyboardPasteEvent = function (e) {
- return (
- (global$4.metaKeyPressed(e) && e.keyCode === 86) ||
- (e.shiftKey && e.keyCode === 45)
- );
- };
- var registerEventHandlers = function (editor, pasteBin, pasteFormat) {
- var keyboardPasteEvent = value();
- var keyboardPastePressed = value();
- var keyboardPastePlainTextState;
- editor.on("keyup", keyboardPastePressed.clear);
- editor.on("keydown", function (e) {
- var removePasteBinOnKeyUp = function (e) {
- if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
- pasteBin.remove();
- }
- };
- if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
- keyboardPastePlainTextState = e.shiftKey && e.keyCode === 86;
- if (
- keyboardPastePlainTextState &&
- global$1.webkit &&
- navigator.userAgent.indexOf("Version/") !== -1
- ) {
- return;
- }
- e.stopImmediatePropagation();
- keyboardPasteEvent.set(e);
- keyboardPastePressed.set(true);
- if (global$1.ie && keyboardPastePlainTextState) {
- e.preventDefault();
- firePaste(editor, true);
- return;
- }
- pasteBin.remove();
- pasteBin.create();
- editor.once("keyup", removePasteBinOnKeyUp);
- editor.once("paste", function () {
- editor.off("keyup", removePasteBinOnKeyUp);
- });
- }
- });
- var insertClipboardContent = function (
- editor,
- clipboardContent,
- isKeyBoardPaste,
- plainTextMode,
- internal
- ) {
- var content;
- if (hasContentType(clipboardContent, "text/html")) {
- content = clipboardContent["text/html"];
- } else {
- content = pasteBin.getHtml();
- internal = internal ? internal : isMarked(content);
- if (pasteBin.isDefaultContent(content)) {
- plainTextMode = true;
- }
- }
- content = trimHtml(content);
- pasteBin.remove();
-
- const node = editor.selection.getNode();
- if (node && node.tagName === "PRE") plainTextMode = true;
-
- var isPlainTextHtml = internal === false && isPlainText(content);
- var isAbsoluteUrl$1 = isAbsoluteUrl(content);
- if (!content.length || (isPlainTextHtml && !isAbsoluteUrl$1)) {
- plainTextMode = true;
- }
- if (plainTextMode || isAbsoluteUrl$1) {
- if (hasContentType(clipboardContent, "text/plain") && isPlainTextHtml) {
- content = clipboardContent["text/plain"];
- } else {
- content = innerText(content);
- }
- }
- if (pasteBin.isDefaultContent(content)) {
- if (!isKeyBoardPaste) {
- editor.windowManager.alert(
- "Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents."
- );
- }
- return;
- }
- if (plainTextMode) {
- pasteText(editor, content);
- } else {
- pasteHtml$1(editor, content, internal);
- }
- };
- var getLastRng = function () {
- return pasteBin.getLastRng() || editor.selection.getRng();
- };
- editor.on("paste", function (e) {
- var isKeyboardPaste =
- keyboardPasteEvent.isSet() || keyboardPastePressed.isSet();
- if (isKeyboardPaste) {
- keyboardPasteEvent.clear();
- }
- var clipboardContent = getClipboardContent(editor, e);
- var plainTextMode =
- pasteFormat.get() === "text" || keyboardPastePlainTextState;
- var internal = hasContentType(clipboardContent, internalHtmlMime());
- keyboardPastePlainTextState = false;
- if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) {
- pasteBin.remove();
- return;
- }
- if (
- !hasHtmlOrText(clipboardContent) &&
- pasteImageData(editor, e, getLastRng())
- ) {
- pasteBin.remove();
- return;
- }
- if (!isKeyboardPaste) {
- e.preventDefault();
- }
- if (
- global$1.ie &&
- (!isKeyboardPaste || e.ieFake) &&
- !hasContentType(clipboardContent, "text/html")
- ) {
- pasteBin.create();
- editor.dom.bind(pasteBin.getEl(), "paste", function (e) {
- e.stopPropagation();
- });
- editor.getDoc().execCommand("Paste", false, null);
- clipboardContent["text/html"] = pasteBin.getHtml();
- }
- if (hasContentType(clipboardContent, "text/html")) {
- e.preventDefault();
- if (!internal) {
- internal = isMarked(clipboardContent["text/html"]);
- }
- insertClipboardContent(
- editor,
- clipboardContent,
- isKeyboardPaste,
- plainTextMode,
- internal
- );
- } else {
- global$2.setEditorTimeout(
- editor,
- function () {
- insertClipboardContent(
- editor,
- clipboardContent,
- isKeyboardPaste,
- plainTextMode,
- internal
- );
- },
- 0
- );
- }
- });
- };
- var registerEventsAndFilters = function (editor, pasteBin, pasteFormat) {
- registerEventHandlers(editor, pasteBin, pasteFormat);
- var src;
- editor.parser.addNodeFilter("img", function (nodes, name, args) {
- var isPasteInsert = function (args) {
- return args.data && args.data.paste === true;
- };
- var remove = function (node) {
- if (!node.attr("data-mce-object") && src !== global$1.transparentSrc) {
- node.remove();
- }
- };
- var isWebKitFakeUrl = function (src) {
- return src.indexOf("webkit-fake-url") === 0;
- };
- var isDataUri = function (src) {
- return src.indexOf("data:") === 0;
- };
- if (!getPasteDataImages(editor) && isPasteInsert(args)) {
- var i = nodes.length;
- while (i--) {
- src = nodes[i].attr("src");
- if (!src) {
- continue;
- }
- if (isWebKitFakeUrl(src)) {
- remove(nodes[i]);
- } else if (!getAllowHtmlDataUrls(editor) && isDataUri(src)) {
- remove(nodes[i]);
- }
- }
- }
- });
- };
-
- var getPasteBinParent = function (editor) {
- return global$1.ie && editor.inline ? document.body : editor.getBody();
- };
- var isExternalPasteBin = function (editor) {
- return getPasteBinParent(editor) !== editor.getBody();
- };
- var delegatePasteEvents = function (
- editor,
- pasteBinElm,
- pasteBinDefaultContent
- ) {
- if (isExternalPasteBin(editor)) {
- editor.dom.bind(pasteBinElm, "paste keyup", function (_e) {
- if (!isDefault(editor, pasteBinDefaultContent)) {
- editor.fire("paste");
- }
- });
- }
- };
- var create = function (editor, lastRngCell, pasteBinDefaultContent) {
- var dom = editor.dom,
- body = editor.getBody();
- lastRngCell.set(editor.selection.getRng());
- var pasteBinElm = editor.dom.add(
- getPasteBinParent(editor),
- "div",
- {
- id: "mcepastebin",
- class: "mce-pastebin",
- contentEditable: true,
- "data-mce-bogus": "all",
- style:
- "position: fixed; top: 50%; width: 10px; height: 10px; overflow: hidden; opacity: 0",
- },
- pasteBinDefaultContent
- );
- if (global$1.ie || global$1.gecko) {
- dom.setStyle(
- pasteBinElm,
- "left",
- dom.getStyle(body, "direction", true) === "rtl" ? 65535 : -65535
- );
- }
- dom.bind(pasteBinElm, "beforedeactivate focusin focusout", function (e) {
- e.stopPropagation();
- });
- delegatePasteEvents(editor, pasteBinElm, pasteBinDefaultContent);
- pasteBinElm.focus();
- editor.selection.select(pasteBinElm, true);
- };
- var remove = function (editor, lastRngCell) {
- if (getEl(editor)) {
- var pasteBinClone = void 0;
- var lastRng = lastRngCell.get();
- while ((pasteBinClone = editor.dom.get("mcepastebin"))) {
- editor.dom.remove(pasteBinClone);
- editor.dom.unbind(pasteBinClone);
- }
- if (lastRng) {
- editor.selection.setRng(lastRng);
- }
- }
- lastRngCell.set(null);
- };
- var getEl = function (editor) {
- return editor.dom.get("mcepastebin");
- };
- var getHtml = function (editor) {
- var copyAndRemove = function (toElm, fromElm) {
- toElm.appendChild(fromElm);
- editor.dom.remove(fromElm, true);
- };
- var pasteBinClones = global$5.grep(
- getPasteBinParent(editor).childNodes,
- function (elm) {
- return elm.id === "mcepastebin";
- }
- );
- var pasteBinElm = pasteBinClones.shift();
- global$5.each(pasteBinClones, function (pasteBinClone) {
- copyAndRemove(pasteBinElm, pasteBinClone);
- });
- var dirtyWrappers = editor.dom.select("div[id=mcepastebin]", pasteBinElm);
- for (var i = dirtyWrappers.length - 1; i >= 0; i--) {
- var cleanWrapper = editor.dom.create("div");
- pasteBinElm.insertBefore(cleanWrapper, dirtyWrappers[i]);
- copyAndRemove(cleanWrapper, dirtyWrappers[i]);
- }
- return pasteBinElm ? pasteBinElm.innerHTML : "";
- };
- var getLastRng = function (lastRng) {
- return lastRng.get();
- };
- var isDefaultContent = function (pasteBinDefaultContent, content) {
- return content === pasteBinDefaultContent;
- };
- var isPasteBin = function (elm) {
- return elm && elm.id === "mcepastebin";
- };
- var isDefault = function (editor, pasteBinDefaultContent) {
- var pasteBinElm = getEl(editor);
- return (
- isPasteBin(pasteBinElm) &&
- isDefaultContent(pasteBinDefaultContent, pasteBinElm.innerHTML)
- );
- };
- var PasteBin = function (editor) {
- var lastRng = Cell(null);
- var pasteBinDefaultContent = "%MCEPASTEBIN%";
- return {
- create: function () {
- return create(editor, lastRng, pasteBinDefaultContent);
- },
- remove: function () {
- return remove(editor, lastRng);
- },
- getEl: function () {
- return getEl(editor);
- },
- getHtml: function () {
- return getHtml(editor);
- },
- getLastRng: function () {
- return getLastRng(lastRng);
- },
- isDefault: function () {
- return isDefault(editor, pasteBinDefaultContent);
- },
- isDefaultContent: function (content) {
- return isDefaultContent(pasteBinDefaultContent, content);
- },
- };
- };
-
- var Clipboard = function (editor, pasteFormat) {
- var pasteBin = PasteBin(editor);
- editor.on("PreInit", function () {
- return registerEventsAndFilters(editor, pasteBin, pasteFormat);
- });
- return {
- pasteFormat: pasteFormat,
- pasteHtml: function (html, internalFlag) {
- return pasteHtml$1(editor, html, internalFlag);
- },
- pasteText: function (text) {
- return pasteText(editor, text);
- },
- pasteImageData: function (e, rng) {
- return pasteImageData(editor, e, rng);
- },
- getDataTransferItems: getDataTransferItems,
- hasHtmlOrText: hasHtmlOrText,
- hasContentType: hasContentType,
- };
- };
-
- var togglePlainTextPaste = function (editor, clipboard) {
- if (clipboard.pasteFormat.get() === "text") {
- clipboard.pasteFormat.set("html");
- firePastePlainTextToggle(editor, false);
- } else {
- clipboard.pasteFormat.set("text");
- firePastePlainTextToggle(editor, true);
- }
- editor.focus();
- };
-
- var register = function (editor, clipboard) {
- editor.addCommand("mceTogglePlainTextPaste", function () {
- togglePlainTextPaste(editor, clipboard);
- });
- editor.addCommand("mceInsertClipboardContent", function (ui, value) {
- if (value.content) {
- clipboard.pasteHtml(value.content, value.internal);
- }
- if (value.text) {
- clipboard.pasteText(value.text);
- }
- });
- };
-
- var hasWorkingClipboardApi = function (clipboardData) {
- return (
- global$1.iOS === false &&
- typeof (clipboardData === null || clipboardData === void 0
- ? void 0
- : clipboardData.setData) === "function"
- );
- };
- var setHtml5Clipboard = function (clipboardData, html, text) {
- if (hasWorkingClipboardApi(clipboardData)) {
- try {
- clipboardData.clearData();
- clipboardData.setData("text/html", html);
- clipboardData.setData("text/plain", text);
- clipboardData.setData(internalHtmlMime(), html);
- return true;
- } catch (e) {
- return false;
- }
- } else {
- return false;
- }
- };
- var setClipboardData = function (evt, data, fallback, done) {
- if (setHtml5Clipboard(evt.clipboardData, data.html, data.text)) {
- evt.preventDefault();
- done();
- } else {
- fallback(data.html, done);
- }
- };
- var fallback = function (editor) {
- return function (html, done) {
- var markedHtml = mark(html);
- var outer = editor.dom.create("div", {
- contenteditable: "false",
- "data-mce-bogus": "all",
- });
- var inner = editor.dom.create(
- "div",
- { contenteditable: "true" },
- markedHtml
- );
- editor.dom.setStyles(outer, {
- position: "fixed",
- top: "0",
- left: "-3000px",
- width: "1000px",
- overflow: "hidden",
- });
- outer.appendChild(inner);
- editor.dom.add(editor.getBody(), outer);
- var range = editor.selection.getRng();
- inner.focus();
- var offscreenRange = editor.dom.createRng();
- offscreenRange.selectNodeContents(inner);
- editor.selection.setRng(offscreenRange);
- global$2.setTimeout(function () {
- editor.selection.setRng(range);
- outer.parentNode.removeChild(outer);
- done();
- }, 0);
- };
- };
- var getData = function (editor) {
- return {
- html: editor.selection.getContent({ contextual: true }),
- text: editor.selection.getContent({ format: "text" }),
- };
- };
- var isTableSelection = function (editor) {
- return !!editor.dom.getParent(
- editor.selection.getStart(),
- "td[data-mce-selected],th[data-mce-selected]",
- editor.getBody()
- );
- };
- var hasSelectedContent = function (editor) {
- return !editor.selection.isCollapsed() || isTableSelection(editor);
- };
- var cut = function (editor) {
- return function (evt) {
- if (hasSelectedContent(editor)) {
- setClipboardData(evt, getData(editor), fallback(editor), function () {
- if (global$1.browser.isChrome() || global$1.browser.isFirefox()) {
- var rng_1 = editor.selection.getRng();
- global$2.setEditorTimeout(
- editor,
- function () {
- editor.selection.setRng(rng_1);
- editor.execCommand("Delete");
- },
- 0
- );
- } else {
- editor.execCommand("Delete");
- }
- });
- }
- };
- };
- var copy = function (editor) {
- return function (evt) {
- if (hasSelectedContent(editor)) {
- setClipboardData(evt, getData(editor), fallback(editor), noop);
- }
- };
- };
- var register$1 = function (editor) {
- editor.on("cut", cut(editor));
- editor.on("copy", copy(editor));
- };
-
- var global$b = tinymce.util.Tools.resolve("tinymce.dom.RangeUtils");
-
- var getCaretRangeFromEvent = function (editor, e) {
- return global$b.getCaretRangeFromPoint(
- e.clientX,
- e.clientY,
- editor.getDoc()
- );
- };
- var isPlainTextFileUrl = function (content) {
- var plainTextContent = content["text/plain"];
- return plainTextContent ? plainTextContent.indexOf("file://") === 0 : false;
- };
- var setFocusedRange = function (editor, rng) {
- editor.focus();
- editor.selection.setRng(rng);
- };
- var setup = function (editor, clipboard, draggingInternallyState) {
- if (shouldBlockDrop(editor)) {
- editor.on(
- "dragend dragover draggesture dragdrop drop drag",
- function (e) {
- e.preventDefault();
- e.stopPropagation();
- }
- );
- }
- if (!shouldPasteDataImages(editor)) {
- editor.on("drop", function (e) {
- var dataTransfer = e.dataTransfer;
- if (
- dataTransfer &&
- dataTransfer.files &&
- dataTransfer.files.length > 0
- ) {
- e.preventDefault();
- }
- });
- }
- editor.on("drop", function (e) {
- var rng = getCaretRangeFromEvent(editor, e);
- if (e.isDefaultPrevented() || draggingInternallyState.get()) {
- return;
- }
- var dropContent = clipboard.getDataTransferItems(e.dataTransfer);
- var internal = clipboard.hasContentType(dropContent, internalHtmlMime());
- if (
- (!clipboard.hasHtmlOrText(dropContent) ||
- isPlainTextFileUrl(dropContent)) &&
- clipboard.pasteImageData(e, rng)
- ) {
- return;
- }
- if (rng && shouldFilterDrop(editor)) {
- var content_1 =
- dropContent["mce-internal"] ||
- dropContent["text/html"] ||
- dropContent["text/plain"];
- if (content_1) {
- e.preventDefault();
- global$2.setEditorTimeout(editor, function () {
- editor.undoManager.transact(function () {
- if (dropContent["mce-internal"]) {
- editor.execCommand("Delete");
- }
- setFocusedRange(editor, rng);
- content_1 = trimHtml(content_1);
- if (!dropContent["text/html"]) {
- clipboard.pasteText(content_1);
- } else {
- clipboard.pasteHtml(content_1, internal);
- }
- });
- });
- }
- }
- });
- editor.on("dragstart", function (_e) {
- draggingInternallyState.set(true);
- });
- editor.on("dragover dragend", function (e) {
- if (
- shouldPasteDataImages(editor) &&
- draggingInternallyState.get() === false
- ) {
- e.preventDefault();
- setFocusedRange(editor, getCaretRangeFromEvent(editor, e));
- }
- if (e.type === "dragend") {
- draggingInternallyState.set(false);
- }
- });
- };
-
- var setup$1 = function (editor) {
- var plugin = editor.plugins.paste;
- var preProcess = getPreProcess(editor);
- if (preProcess) {
- editor.on("PastePreProcess", function (e) {
- preProcess.call(plugin, plugin, e);
- });
- }
- var postProcess = getPostProcess(editor);
- if (postProcess) {
- editor.on("PastePostProcess", function (e) {
- postProcess.call(plugin, plugin, e);
- });
- }
- };
-
- var addPreProcessFilter = function (editor, filterFunc) {
- editor.on("PastePreProcess", function (e) {
- e.content = filterFunc(editor, e.content, e.internal, e.wordContent);
- });
- };
- var addPostProcessFilter = function (editor, filterFunc) {
- editor.on("PastePostProcess", function (e) {
- filterFunc(editor, e.node);
- });
- };
- var removeExplorerBrElementsAfterBlocks = function (editor, html) {
- if (!isWordContent(html)) {
- return html;
- }
- var blockElements = [];
- global$5.each(
- editor.schema.getBlockElements(),
- function (block, blockName) {
- blockElements.push(blockName);
- }
- );
- var explorerBlocksRegExp = new RegExp(
- "(?:
[\\s\\r\\n]+|
)*(<\\/?(" +
- blockElements.join("|") +
- ")[^>]*>)(?:
[\\s\\r\\n]+|
)*",
- "g"
- );
- html = filter$1(html, [[explorerBlocksRegExp, "$1"]]);
- html = filter$1(html, [
- [/
/g, "
"],
- [/
/g, " "],
- [/
/g, "
"],
- ]);
- return html;
- };
- var removeWebKitStyles = function (editor, content, internal, isWordHtml) {
- if (isWordHtml || internal) {
- return content;
- }
- var webKitStylesSetting = getWebkitStyles(editor);
- var webKitStyles;
- if (
- shouldRemoveWebKitStyles(editor) === false ||
- webKitStylesSetting === "all"
- ) {
- return content;
- }
- if (webKitStylesSetting) {
- webKitStyles = webKitStylesSetting.split(/[, ]/);
- }
- if (webKitStyles) {
- var dom_1 = editor.dom,
- node_1 = editor.selection.getNode();
- content = content.replace(
- /(<[^>]+) style="([^"]*)"([^>]*>)/gi,
- function (all, before, value, after) {
- var inputStyles = dom_1.parseStyle(dom_1.decode(value));
- var outputStyles = {};
- if (webKitStyles === "none") {
- return before + after;
- }
- for (var i = 0; i < webKitStyles.length; i++) {
- var inputValue = inputStyles[webKitStyles[i]],
- currentValue = dom_1.getStyle(node_1, webKitStyles[i], true);
- if (/color/.test(webKitStyles[i])) {
- inputValue = dom_1.toHex(inputValue);
- currentValue = dom_1.toHex(currentValue);
- }
- if (currentValue !== inputValue) {
- outputStyles[webKitStyles[i]] = inputValue;
- }
- }
- outputStyles = dom_1.serializeStyle(outputStyles, "span");
- if (outputStyles) {
- return before + ' style="' + outputStyles + '"' + after;
- }
- return before + after;
- }
- );
- } else {
- content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, "$1$3");
- }
- content = content.replace(
- /(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi,
- function (all, before, value, after) {
- return before + ' style="' + value + '"' + after;
- }
- );
- return content;
- };
- var removeUnderlineAndFontInAnchor = function (editor, root) {
- editor
- .$("a", root)
- .find("font,u")
- .each(function (i, node) {
- editor.dom.remove(node, true);
- });
- };
- var setup$2 = function (editor) {
- if (global$1.webkit) {
- addPreProcessFilter(editor, removeWebKitStyles);
- }
- if (global$1.ie) {
- addPreProcessFilter(editor, removeExplorerBrElementsAfterBlocks);
- addPostProcessFilter(editor, removeUnderlineAndFontInAnchor);
- }
- };
-
- var makeSetupHandler = function (editor, clipboard) {
- return function (api) {
- api.setActive(clipboard.pasteFormat.get() === "text");
- var pastePlainTextToggleHandler = function (e) {
- return api.setActive(e.state);
- };
- editor.on("PastePlainTextToggle", pastePlainTextToggleHandler);
- return function () {
- return editor.off("PastePlainTextToggle", pastePlainTextToggleHandler);
- };
- };
- };
- var register$2 = function (editor, clipboard) {
- editor.ui.registry.addToggleButton("pastetext", {
- active: false,
- icon: "paste-text",
- tooltip: "Paste as text",
- onAction: function () {
- return editor.execCommand("mceTogglePlainTextPaste");
- },
- onSetup: makeSetupHandler(editor, clipboard),
- });
- editor.ui.registry.addToggleMenuItem("pastetext", {
- text: "Paste as text",
- icon: "paste-text",
- onAction: function () {
- return editor.execCommand("mceTogglePlainTextPaste");
- },
- onSetup: makeSetupHandler(editor, clipboard),
- });
- };
-
- function Plugin() {
- global.add("paste", function (editor) {
- if (hasProPlugin(editor) === false) {
- var draggingInternallyState = Cell(false);
- var pasteFormat = Cell(isPasteAsTextEnabled(editor) ? "text" : "html");
- var clipboard = Clipboard(editor, pasteFormat);
- var quirks = setup$2(editor);
- register$2(editor, clipboard);
- register(editor, clipboard);
- setup$1(editor);
- register$1(editor);
- setup(editor, clipboard, draggingInternallyState);
- return get(clipboard, quirks);
- }
- });
- }
-
- Plugin();
-})();
diff --git a/apps/web/src/components/editor/plugins/quickimage/index.js b/apps/web/src/components/editor/plugins/quickimage/index.js
deleted file mode 100644
index dfd8f6603..000000000
--- a/apps/web/src/components/editor/plugins/quickimage/index.js
+++ /dev/null
@@ -1 +0,0 @@
-import "./plugin";
diff --git a/apps/web/src/components/editor/plugins/quickimage/plugin.js b/apps/web/src/components/editor/plugins/quickimage/plugin.js
deleted file mode 100644
index 7b55395d8..000000000
--- a/apps/web/src/components/editor/plugins/quickimage/plugin.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import tinymce from "tinymce/tinymce";
-import Compressor from "compressorjs";
-
-(function () {
- tinymce.PluginManager.add("quickimage", function (editor, url) {
- /**
- * Plugin behaviour for when the Toolbar or Menu item is selected
- *
- * @private
- */
- function _onAction() {
- var input = document.createElement("input");
- input.setAttribute("type", "file");
- input.setAttribute("accept", "image/*");
- input.onchange = function () {
- var file = this.files[0];
- if (!file) return null;
-
- new Compressor(file, {
- quality: 0.6,
- mimeType: "image/jpeg",
- width: 1024,
- success(result) {
- var reader = new FileReader();
- reader.readAsDataURL(result);
-
- reader.onloadend = function () {
- var base64data = reader.result;
- var content = `
`;
- editor.insertContent(content);
- };
- },
- error(err) {
- console.error(err.message);
- },
- });
- };
- input.dispatchEvent(new MouseEvent("click"));
- }
-
- editor.ui.registry.addButton("image", {
- icon: "image",
- tooltip: "Insert image",
- onAction: _onAction,
- });
-
- editor.addCommand("InsertImage", function (ui, value) {
- _onAction();
- });
- });
-})();
diff --git a/apps/web/src/components/editor/plugins/shortcuts/index.js b/apps/web/src/components/editor/plugins/shortcuts/index.js
deleted file mode 100644
index bfc1fc786..000000000
--- a/apps/web/src/components/editor/plugins/shortcuts/index.js
+++ /dev/null
@@ -1 +0,0 @@
-import "./plugins";
diff --git a/apps/web/src/components/editor/plugins/shortcuts/plugins.js b/apps/web/src/components/editor/plugins/shortcuts/plugins.js
deleted file mode 100644
index 4560744fa..000000000
--- a/apps/web/src/components/editor/plugins/shortcuts/plugins.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import tinymce from "tinymce/tinymce";
-import {
- getCharacterRange,
- getNextCharacter,
- getPreviousCharacter,
- moveCaretTo,
-} from "../utils";
-
-const WRAP_CHARS = {
- '"': { start: '"', end: '"' },
- "[": { start: "[", end: "]" },
- "(": { start: "(", end: ")" },
- "{": { start: "{", end: "}" },
- "|": { start: "|", end: "|" },
- "`": { start: "`", end: "`" },
-};
-
-(function () {
- tinymce.PluginManager.add("shortcuts", function (editor, url) {
- editor.on("keydown", function (e) {
- const content = editor.selection.getContent();
- const node = editor.selection.getNode();
- if (node?.nodeName === "PRE") return;
-
- if (content) {
- if (e.key === "`") {
- e.preventDefault();
- editor.execCommand("mceCode");
- } else if (!!WRAP_CHARS[e.key]) {
- e.preventDefault();
- const char = WRAP_CHARS[e.key];
- editor.selection.setContent(`${char.start}${content}${char.end}`);
- }
- } else if (e.code === "Backspace") {
- const characterRange = getCharacterRange(node);
- const nextChar = getNextCharacter(node, characterRange);
- const prevChar = getPreviousCharacter(node, characterRange);
- const isWrapChar = !!WRAP_CHARS[nextChar];
- if (isWrapChar && nextChar === prevChar) {
- e.preventDefault();
- editor.execCommand("ForwardDelete");
- editor.execCommand("Delete");
- }
- } else if (!!WRAP_CHARS[e.key]) {
- e.preventDefault();
- const char = WRAP_CHARS[e.key];
- const characterRange = getCharacterRange(node);
- const nextChar = getNextCharacter(node, characterRange);
- const prevChar = getPreviousCharacter(node, characterRange);
-
- if (nextChar === e.key) {
- moveCaretTo(node, characterRange.start + 1, characterRange.end + 1);
- } else if (!prevChar.trim()) {
- editor.selection.setContent(`${char.start}${char.end}`);
- characterRange.start += char.start.length + char.end.length;
- characterRange.end += char.start.length + char.end.length;
- moveCaretTo(node, characterRange.start - 1, characterRange.end - 1);
- } else {
- editor.selection.setContent(`${e.key}`);
- }
- }
- });
- });
-})();
diff --git a/apps/web/src/components/editor/plugins/shortlink/index.js b/apps/web/src/components/editor/plugins/shortlink/index.js
deleted file mode 100644
index 9450f4277..000000000
--- a/apps/web/src/components/editor/plugins/shortlink/index.js
+++ /dev/null
@@ -1 +0,0 @@
-import "./plugin"
\ No newline at end of file
diff --git a/apps/web/src/components/editor/plugins/shortlink/plugin.js b/apps/web/src/components/editor/plugins/shortlink/plugin.js
deleted file mode 100644
index 109180bd2..000000000
--- a/apps/web/src/components/editor/plugins/shortlink/plugin.js
+++ /dev/null
@@ -1,725 +0,0 @@
-/**
- * Copyright (c) Tiny Technologies, Inc. All rights reserved.
- * Licensed under the LGPL or a commercial license.
- * For LGPL see License.txt in the project root for license information.
- * For commercial licenses see https://www.tiny.cloud/
- *
- * Version: 5.6.2 (2020-12-08)
- */
-import tinymce from "tinymce/tinymce";
-
-(function () {
- var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
-
- var global$1 = tinymce.util.Tools.resolve('tinymce.util.VK');
-
- var typeOf = function (x) {
- var t = typeof x;
- if (x === null) {
- return 'null';
- // eslint-disable-next-line no-mixed-operators
- } else if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) {
- return 'array';
- // eslint-disable-next-line no-mixed-operators
- } else if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) {
- return 'string';
- } else {
- return t;
- }
- };
- var isType = function (type) {
- return function (value) {
- return typeOf(value) === type;
- };
- };
- var isSimpleType = function (type) {
- return function (value) {
- return typeof value === type;
- };
- };
- var eq = function (t) {
- return function (a) {
- return t === a;
- };
- };
- var isString = isType('string');
- var isNull = eq(null);
- var isBoolean = isSimpleType('boolean');
-
- var assumeExternalTargets = function (editor) {
- var externalTargets = editor.getParam('link_assume_external_targets', false);
- if (isBoolean(externalTargets) && externalTargets) {
- return 1;
- } else if (isString(externalTargets) && (externalTargets === 'http' || externalTargets === 'https')) {
- return externalTargets;
- }
- return 0;
- };
- var hasContextToolbar = function (editor) {
- return editor.getParam('link_context_toolbar', false, 'boolean');
- };
- var getDefaultLinkTarget = function (editor) {
- return editor.getParam('default_link_target');
- };
- var allowUnsafeLinkTarget = function (editor) {
- return editor.getParam('allow_unsafe_link_target', false, 'boolean');
- };
-
- var appendClickRemove = function (link, evt) {
- document.body.appendChild(link);
- link.dispatchEvent(evt);
- document.body.removeChild(link);
- };
- var open = function (url) {
- var link = document.createElement('a');
- link.target = '_blank';
- link.href = url;
- link.rel = 'noreferrer noopener';
- var evt = document.createEvent('MouseEvents');
- evt.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
- appendClickRemove(link, evt);
- };
-
- var __assign = function () {
- __assign = Object.assign || function __assign(t) {
- for (var s, i = 1, n = arguments.length; i < n; i++) {
- s = arguments[i];
- for (var p in s)
- if (Object.prototype.hasOwnProperty.call(s, p))
- t[p] = s[p];
- }
- return t;
- };
- return __assign.apply(this, arguments);
- };
-
- var noop = function () {
- };
- var constant = function (value) {
- return function () {
- return value;
- };
- };
- var never = constant(false);
- var always = constant(true);
-
- var none = function () {
- return NONE;
- };
- var NONE = function () {
- var eq = function (o) {
- return o.isNone();
- };
- var call = function (thunk) {
- return thunk();
- };
- var id = function (n) {
- return n;
- };
- var me = {
- fold: function (n, _s) {
- return n();
- },
- is: never,
- isSome: never,
- isNone: always,
- getOr: id,
- getOrThunk: call,
- getOrDie: function (msg) {
- throw new Error(msg || 'error: getOrDie called on none.');
- },
- getOrNull: constant(null),
- getOrUndefined: constant(undefined),
- or: id,
- orThunk: call,
- map: none,
- each: noop,
- bind: none,
- exists: never,
- forall: always,
- filter: none,
- equals: eq,
- equals_: eq,
- toArray: function () {
- return [];
- },
- toString: constant('none()')
- };
- return me;
- }();
- var some = function (a) {
- var constant_a = constant(a);
- var self = function () {
- return me;
- };
- var bind = function (f) {
- return f(a);
- };
- var me = {
- fold: function (n, s) {
- return s(a);
- },
- is: function (v) {
- return a === v;
- },
- isSome: always,
- isNone: never,
- getOr: constant_a,
- getOrThunk: constant_a,
- getOrDie: constant_a,
- getOrNull: constant_a,
- getOrUndefined: constant_a,
- or: self,
- orThunk: self,
- map: function (f) {
- return some(f(a));
- },
- each: function (f) {
- f(a);
- },
- bind: bind,
- exists: bind,
- forall: bind,
- filter: function (f) {
- return f(a) ? me : NONE;
- },
- toArray: function () {
- return [a];
- },
- toString: function () {
- return 'some(' + a + ')';
- },
- equals: function (o) {
- return o.is(a);
- },
- equals_: function (o, elementEq) {
- return o.fold(never, function (b) {
- return elementEq(a, b);
- });
- }
- };
- return me;
- };
- var from = function (value) {
- return value === null || value === undefined ? NONE : some(value);
- };
- var Optional = {
- some: some,
- none: none,
- from: from
- };
-
- var each = function (xs, f) {
- for (var i = 0, len = xs.length; i < len; i++) {
- var x = xs[i];
- f(x, i);
- }
- };
- var foldl = function (xs, f, acc) {
- each(xs, function (x) {
- acc = f(acc, x);
- });
- return acc;
- };
-
- var keys = Object.keys;
- var hasOwnProperty = Object.hasOwnProperty;
- var each$1 = function (obj, f) {
- var props = keys(obj);
- for (var k = 0, len = props.length; k < len; k++) {
- var i = props[k];
- var x = obj[i];
- f(x, i);
- }
- };
- var objAcc = function (r) {
- return function (x, i) {
- r[i] = x;
- };
- };
- var internalFilter = function (obj, pred, onTrue, onFalse) {
- var r = {};
- each$1(obj, function (x, i) {
- (pred(x, i) ? onTrue : onFalse)(x, i);
- });
- return r;
- };
- var filter = function (obj, pred) {
- var t = {};
- internalFilter(obj, pred, objAcc(t), noop);
- return t;
- };
- var has = function (obj, key) {
- return hasOwnProperty.call(obj, key);
- };
-
- var global$2 = tinymce.util.Tools.resolve('tinymce.dom.TreeWalker');
-
- var global$3 = tinymce.util.Tools.resolve('tinymce.util.Tools');
-
- var isAnchor = function (elm) {
- return elm && elm.nodeName.toLowerCase() === 'a';
- };
- var isLink = function (elm) {
- return isAnchor(elm) && !!getHref(elm);
- };
- var collectNodesInRange = function (rng, predicate) {
- if (rng.collapsed) {
- return [];
- } else {
- var contents = rng.cloneContents();
- var walker = new global$2(contents.firstChild, contents);
- var elements = [];
- var current = contents.firstChild;
- do {
- if (predicate(current)) {
- elements.push(current);
- }
- // eslint-disable-next-line no-cond-assign
- } while (current = walker.next());
- return elements;
- }
- };
- var hasProtocol = function (url) {
- return /^\w+:/i.test(url);
- };
- var getHref = function (elm) {
- var href = elm.getAttribute('data-mce-href');
- return href ? href : elm.getAttribute('href');
- };
- var applyRelTargetRules = function (rel, isUnsafe) {
- var rules = ['noopener'];
- var rels = rel ? rel.split(/\s+/) : [];
- var toString = function (rels) {
- return global$3.trim(rels.sort().join(' '));
- };
- var addTargetRules = function (rels) {
- rels = removeTargetRules(rels);
- return rels.length > 0 ? rels.concat(rules) : rules;
- };
- var removeTargetRules = function (rels) {
- return rels.filter(function (val) {
- return global$3.inArray(rules, val) === -1;
- });
- };
- var newRels = isUnsafe ? addTargetRules(rels) : removeTargetRules(rels);
- return newRels.length > 0 ? toString(newRels) : '';
- };
- var trimCaretContainers = function (text) {
- return text.replace(/\uFEFF/g, '');
- };
- var getAnchorElement = function (editor, selectedElm) {
- selectedElm = selectedElm || editor.selection.getNode();
- if (isImageFigure(selectedElm)) {
- return editor.dom.select('a[href]', selectedElm)[0];
- } else {
- return editor.dom.getParent(selectedElm, 'a[href]');
- }
- };
- var getAnchorText = function (selection, anchorElm) {
- var text = anchorElm ? anchorElm.innerText || anchorElm.textContent : selection.getContent({ format: 'text' });
- return trimCaretContainers(text);
- };
- var hasLinks = function (elements) {
- return global$3.grep(elements, isLink).length > 0;
- };
- var hasLinksInSelection = function (rng) {
- return collectNodesInRange(rng, isLink).length > 0;
- };
- var isOnlyTextSelected = function (editor) {
- var inlineTextElements = editor.schema.getTextInlineElements();
- var isElement = function (elm) {
- return elm.nodeType === 1 && !isAnchor(elm) && !has(inlineTextElements, elm.nodeName.toLowerCase());
- };
- var elements = collectNodesInRange(editor.selection.getRng(), isElement);
- return elements.length === 0;
- };
- var isImageFigure = function (elm) {
- return elm && elm.nodeName === 'FIGURE' && /\bimage\b/i.test(elm.className);
- };
- var getLinkAttrs = function (data) {
- return foldl([
- 'title',
- 'rel',
- 'class',
- 'target'
- ], function (acc, key) {
- data[key].each(function (value) {
- acc[key] = value.length > 0 ? value : null;
- });
- return acc;
- }, { href: data.href });
- };
- var handleExternalTargets = function (href, assumeExternalTargets) {
- if ((assumeExternalTargets === 'http' || assumeExternalTargets === 'https') && !hasProtocol(href)) {
- return assumeExternalTargets + '://' + href;
- }
- return href;
- };
- var applyLinkOverrides = function (editor, linkAttrs) {
- var newLinkAttrs = __assign({}, linkAttrs);
- if (allowUnsafeLinkTarget(editor) === false) {
- var newRel = applyRelTargetRules(newLinkAttrs.rel, newLinkAttrs.target === '_blank');
- newLinkAttrs.rel = newRel ? newRel : null;
- }
- if (Optional.from(newLinkAttrs.target).isNone()) {
- newLinkAttrs.target = getDefaultLinkTarget(editor);
- }
- newLinkAttrs.href = handleExternalTargets(newLinkAttrs.href, assumeExternalTargets(editor));
- return newLinkAttrs;
- };
- var updateLink = function (editor, anchorElm, text, linkAttrs) {
- text.each(function (text) {
- if (anchorElm.hasOwnProperty('innerText')) {
- anchorElm.innerText = text;
- } else {
- anchorElm.textContent = text;
- }
- });
- editor.dom.setAttribs(anchorElm, linkAttrs);
- editor.selection.select(anchorElm);
- };
- var createLink = function (editor, selectedElm, text, linkAttrs) {
- if (isImageFigure(selectedElm)) {
- linkImageFigure(editor, selectedElm, linkAttrs);
- } else {
- text.fold(function () {
- editor.execCommand('mceInsertLink', false, linkAttrs);
- }, function (text) {
- editor.insertContent(editor.dom.createHTML('a', linkAttrs, editor.dom.encode(text)));
- });
- }
- };
- var linkDomMutation = function (editor, attachState, data) {
- var selectedElm = editor.selection.getNode();
- var anchorElm = getAnchorElement(editor, selectedElm);
- var linkAttrs = applyLinkOverrides(editor, getLinkAttrs(data));
- editor.undoManager.transact(function () {
- if (data.href === attachState.href) {
- attachState.attach();
- }
- if (anchorElm) {
- editor.focus();
- updateLink(editor, anchorElm, data.text, linkAttrs);
- } else {
- createLink(editor, selectedElm, data.text, linkAttrs);
- }
- });
- };
- var unlinkSelection = function (editor) {
- var dom = editor.dom, selection = editor.selection;
- var bookmark = selection.getBookmark();
- var rng = selection.getRng().cloneRange();
- var startAnchorElm = dom.getParent(rng.startContainer, 'a[href]', editor.getBody());
- var endAnchorElm = dom.getParent(rng.endContainer, 'a[href]', editor.getBody());
- if (startAnchorElm) {
- rng.setStartBefore(startAnchorElm);
- }
- if (endAnchorElm) {
- rng.setEndAfter(endAnchorElm);
- }
- selection.setRng(rng);
- editor.execCommand('unlink');
- selection.moveToBookmark(bookmark);
- };
- var unlinkDomMutation = function (editor) {
- editor.undoManager.transact(function () {
- var node = editor.selection.getNode();
- if (isImageFigure(node)) {
- unlinkImageFigure(editor, node);
- } else {
- unlinkSelection(editor);
- }
- editor.focus();
- });
- };
- var unwrapOptions = function (data) {
- var cls = data.class, href = data.href, rel = data.rel, target = data.target, text = data.text, title = data.title;
- return filter({
- class: cls.getOrNull(),
- href: href,
- rel: rel.getOrNull(),
- target: target.getOrNull(),
- text: text.getOrNull(),
- title: title.getOrNull()
- }, function (v, _k) {
- return isNull(v) === false;
- });
- };
- var link = function (editor, attachState, data) {
- editor.hasPlugin('rtc', true) ? editor.execCommand('createlink', false, unwrapOptions(data)) : linkDomMutation(editor, attachState, data);
- };
- var unlink = function (editor) {
- editor.hasPlugin('rtc', true) ? editor.execCommand('unlink') : unlinkDomMutation(editor);
- };
- var unlinkImageFigure = function (editor, fig) {
- var img = editor.dom.select('img', fig)[0];
- if (img) {
- var a = editor.dom.getParents(img, 'a[href]', fig)[0];
- if (a) {
- a.parentNode.insertBefore(img, a);
- editor.dom.remove(a);
- }
- }
- };
- var linkImageFigure = function (editor, fig, attrs) {
- var img = editor.dom.select('img', fig)[0];
- if (img) {
- var a = editor.dom.create('a', attrs);
- img.parentNode.insertBefore(a, img);
- a.appendChild(img);
- }
- };
-
- var getLink = function (editor, elm) {
- return editor.dom.getParent(elm, 'a[href]');
- };
- var getSelectedLink = function (editor) {
- return getLink(editor, editor.selection.getStart());
- };
- var hasOnlyAltModifier = function (e) {
- return e.altKey === true && e.shiftKey === false && e.ctrlKey === false && e.metaKey === false;
- };
- var gotoLink = function (editor, a) {
- if (a) {
- var href = getHref(a);
- if (/^#/.test(href)) {
- var targetEl = editor.$(href);
- if (targetEl.length) {
- editor.selection.scrollIntoView(targetEl[0], true);
- }
- } else {
- open(a.href);
- }
- }
- };
- var openDialog = function (editor) {
- return function () {
- editor.fire('contexttoolbar-show', { toolbarKey: 'quicklink' });
- };
- };
- var gotoSelectedLink = function (editor) {
- return function () {
- gotoLink(editor, getSelectedLink(editor));
- };
- };
- var setupGotoLinks = function (editor) {
- editor.on('click', function (e) {
- var link = getLink(editor, e.target);
- if (link && global$1.metaKeyPressed(e)) {
- e.preventDefault();
- gotoLink(editor, link);
- }
- });
- editor.on('keydown', function (e) {
- var link = getSelectedLink(editor);
- if (link && e.keyCode === 13 && hasOnlyAltModifier(e)) {
- e.preventDefault();
- gotoLink(editor, link);
- }
- });
- };
- var toggleState = function (editor, toggler) {
- editor.on('NodeChange', toggler);
- return function () {
- return editor.off('NodeChange', toggler);
- };
- };
- var toggleActiveState = function (editor) {
- return function (api) {
- return toggleState(editor, function () {
- api.setActive(!editor.mode.isReadOnly() && getAnchorElement(editor, editor.selection.getNode()) !== null);
- });
- };
- };
- var toggleEnabledState = function (editor) {
- return function (api) {
- var updateState = function () {
- return api.setDisabled(getAnchorElement(editor, editor.selection.getNode()) === null);
- };
- updateState();
- return toggleState(editor, updateState);
- };
- };
- var toggleUnlinkState = function (editor) {
- return function (api) {
- var hasLinks$1 = function (parents) {
- return hasLinks(parents) || hasLinksInSelection(editor.selection.getRng());
- };
- var parents = editor.dom.getParents(editor.selection.getStart());
- api.setDisabled(!hasLinks$1(parents));
- return toggleState(editor, function (e) {
- return api.setDisabled(!hasLinks$1(e.parents));
- });
- };
- };
-
- var register = function (editor) {
- editor.addCommand('mceLink', function () {
- openDialog(editor)();
- });
- };
-
- var setup = function (editor) {
- editor.addShortcut('Meta+K', '', function () {
- editor.execCommand('mceLink');
- });
- };
-
- var setupButtons = function (editor) {
- editor.ui.registry.addToggleButton('link', {
- icon: 'link',
- tooltip: 'Insert/edit link',
- onAction: openDialog(editor),
- onSetup: toggleActiveState(editor)
- });
- editor.ui.registry.addButton('openlink', {
- icon: 'new-tab',
- tooltip: 'Open link',
- onAction: gotoSelectedLink(editor),
- onSetup: toggleEnabledState(editor)
- });
- editor.ui.registry.addButton('unlink', {
- icon: 'unlink',
- tooltip: 'Remove link',
- onAction: function () {
- return unlink(editor);
- },
- onSetup: toggleUnlinkState(editor)
- });
- };
- var setupMenuItems = function (editor) {
- editor.ui.registry.addMenuItem('openlink', {
- text: 'Open link',
- icon: 'new-tab',
- onAction: gotoSelectedLink(editor),
- onSetup: toggleEnabledState(editor)
- });
- editor.ui.registry.addMenuItem('link', {
- icon: 'link',
- text: 'Link...',
- shortcut: 'Meta+K',
- onAction: openDialog(editor)
- });
- editor.ui.registry.addMenuItem('unlink', {
- icon: 'unlink',
- text: 'Remove link',
- onAction: function () {
- return unlink(editor);
- },
- onSetup: toggleUnlinkState(editor)
- });
- };
- var setupContextMenu = function (editor) {
- var inLink = 'link unlink openlink';
- var noLink = 'link';
- editor.ui.registry.addContextMenu('link', {
- update: function (element) {
- return hasLinks(editor.dom.getParents(element, 'a')) ? inLink : noLink;
- }
- });
- };
- var setupContextToolbars = function (editor) {
- var collapseSelectionToEnd = function (editor) {
- editor.selection.collapse(false);
- };
- var onSetupLink = function (buttonApi) {
- var node = editor.selection.getNode();
- buttonApi.setDisabled(!getAnchorElement(editor, node));
- return noop;
- };
- editor.ui.registry.addContextForm('quicklink', {
- launch: {
- type: 'contextformtogglebutton',
- icon: 'link',
- tooltip: 'Link',
- onSetup: toggleActiveState(editor)
- },
- label: 'Link',
- predicate: function (node) {
- return !!getAnchorElement(editor, node) && hasContextToolbar(editor);
- },
- initValue: function () {
- var elm = getAnchorElement(editor);
- return !!elm ? getHref(elm) : '';
- },
- commands: [
- {
- type: 'contextformtogglebutton',
- icon: 'link',
- tooltip: 'Link',
- primary: true,
- onSetup: function (buttonApi) {
- var node = editor.selection.getNode();
- buttonApi.setActive(!!getAnchorElement(editor, node));
- return toggleActiveState(editor)(buttonApi);
- },
- onAction: function (formApi) {
- var anchor = getAnchorElement(editor);
- var value = formApi.getValue();
- if (!anchor) {
- var attachState = {
- href: value,
- attach: noop
- };
- var onlyText = isOnlyTextSelected(editor);
- var text = onlyText ? Optional.some(getAnchorText(editor.selection, anchor)).filter(function (t) {
- return t.length > 0;
- }).or(Optional.from(value)) : Optional.none();
- link(editor, attachState, {
- href: value,
- text: text,
- title: Optional.none(),
- rel: Optional.none(),
- target: Optional.none(),
- class: Optional.none()
- });
- formApi.hide();
- } else {
- editor.undoManager.transact(function () {
- editor.dom.setAttrib(anchor, 'href', value);
- collapseSelectionToEnd(editor);
- formApi.hide();
- });
- }
- }
- },
- {
- type: 'contextformbutton',
- icon: 'unlink',
- tooltip: 'Remove link',
- onSetup: onSetupLink,
- onAction: function (formApi) {
- unlink(editor);
- formApi.hide();
- }
- },
- {
- type: 'contextformbutton',
- icon: 'new-tab',
- tooltip: 'Open link',
- onSetup: onSetupLink,
- onAction: function (formApi) {
- gotoSelectedLink(editor)();
- formApi.hide();
- }
- }
- ]
- });
- };
-
- function Plugin () {
- global.add('shortlink', function (editor) {
- setupButtons(editor);
- setupMenuItems(editor);
- setupContextMenu(editor);
- setupContextToolbars(editor);
- setupGotoLinks(editor);
- register(editor);
- setup(editor);
- });
- }
-
- Plugin();
-
-}());
diff --git a/apps/web/src/components/editor/plugins/utils.js b/apps/web/src/components/editor/plugins/utils.js
deleted file mode 100644
index 53e42eba2..000000000
--- a/apps/web/src/components/editor/plugins/utils.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import rangy from "rangy/lib/rangy-textrange";
-
-export function getCharacterRange(node) {
- if (!node) return;
- const ranges = rangy.getSelection().saveCharacterRanges(node);
- if (!ranges || !ranges.length) return;
- const { characterRange } = ranges[0];
- return characterRange;
-}
-
-export function getNextCharacter(node, range) {
- if (!range) return "";
- return (node.textContent || node.innerText).substring(
- range.end,
- range.end + 1
- );
-}
-
-export function getPreviousCharacter(node, range) {
- if (!range) return "";
- return (node.textContent || node.innerText).substring(
- range.start,
- range.start - 1
- );
-}
-
-export function moveCaretTo(node, index, endIndex) {
- const newCharacterRange = {
- characterRange: {
- start: index,
- end: endIndex || index,
- },
- };
-
- rangy.getSelection().restoreCharacterRanges(node, [newCharacterRange]);
-}
-
-export function persistSelection(node, action) {
- let saved = rangy.getSelection().saveCharacterRanges(node);
- action();
- rangy.getSelection().restoreCharacterRanges(node, saved);
-}
diff --git a/apps/web/src/components/editor/tinymce.js b/apps/web/src/components/editor/tinymce.js
index ea1eabde6..71e2b5eda 100644
--- a/apps/web/src/components/editor/tinymce.js
+++ b/apps/web/src/components/editor/tinymce.js
@@ -1,4 +1,8 @@
import React, { useEffect } from "react";
+import "./editor.css";
+import "@streetwritersco/tinymce-plugins/codeblock/styles.css";
+import "@streetwritersco/tinymce-plugins/inlinecode/styles.css";
+import "@streetwritersco/tinymce-plugins/collapsibleheaders/styles.css";
import "tinymce/tinymce";
import "tinymce/icons/default";
import "tinymce/themes/silver";
@@ -18,14 +22,14 @@ import "tinymce/plugins/noneditable";
import "tinymce/plugins/table";
import "tinymce/plugins/directionality";
import "tinymce/plugins/media";
-import "./plugins/code";
-import "./plugins/shortlink";
-import "./plugins/quickimage";
-import "./plugins/checklist";
-import "./plugins/collapsibleheaders";
-import "./plugins/paste";
-import "./plugins/shortcuts";
-import "./editor.css";
+import { processPastedContent } from "@streetwritersco/tinymce-plugins/codeblock";
+import "@streetwritersco/tinymce-plugins/inlinecode";
+import "@streetwritersco/tinymce-plugins/shortlink";
+import "@streetwritersco/tinymce-plugins/quickimage";
+import "@streetwritersco/tinymce-plugins/checklist";
+import "@streetwritersco/tinymce-plugins/collapsibleheaders";
+import "@streetwritersco/tinymce-plugins/paste";
+import "@streetwritersco/tinymce-plugins/shortcuts";
import { Editor } from "@tinymce/tinymce-react";
import { showBuyDialog } from "../../common/dialog-controller";
import { useStore as useThemeStore } from "../../stores/theme-store";
@@ -40,7 +44,7 @@ const markdownPatterns = [
{ start: "_", end: "_", format: "italic" },
{ start: "**", end: "**", format: "bold" },
{ start: "~~", end: "~~", format: "strikethrough" },
- { start: "`", end: "`", cmd: "mceCode" },
+ { start: "`", end: "`", cmd: "mceInsertInlineCode" },
{ start: "## ", format: "h2" },
{ start: "### ", format: "h3" },
{ start: "#### ", format: "h4" },
@@ -101,8 +105,14 @@ function useSkin() {
: [host + "/skins/notesnook-dark", host + "/skins/notesnook"];
}
-const plugins =
- "shortcuts checklist paste importcss searchreplace autolink directionality code quickimage shortlink media table hr advlist lists imagetools noneditable quickbars autoresize collapsibleheaders";
+const plugins = {
+ default:
+ "importcss searchreplace autolink directionality media table hr advlist lists imagetools noneditable quickbars autoresize",
+ custom:
+ "collapsibleheaders shortlink quickimage paste codeblock inlinecode shortcuts checklist",
+ pro: "textpattern",
+};
+
function TinyMCE(props) {
const {
changeInterval,
@@ -148,7 +158,9 @@ function TinyMCE(props) {
statusbar: false,
link_quicklink: true,
width: "100%",
- plugins: isUserPremium ? `${plugins} textpattern` : plugins,
+ plugins: isUserPremium
+ ? `${plugins.default} ${plugins.custom} ${plugins.pro}`
+ : plugins.default,
toolbar_mode: isTablet() ? "scrolling" : "sliding",
contextmenu: false,
quickbars_insert_toolbar: false,
@@ -211,15 +223,7 @@ function TinyMCE(props) {
fixed_toolbar_container: "#editorToolbar",
paste_postprocess: function (_, args) {
const { node } = args;
- if (node.childNodes) {
- for (let childNode of node.childNodes) {
- if (childNode.tagName === "PRE") {
- childNode.className = "hljs";
- const code = childNode.textContent || childNode.innerText;
- childNode.innerHTML = code;
- }
- }
- }
+ processPastedContent(node);
},
}}
onBeforeExecCommand={async (command) => {
diff --git a/apps/web/yarn.lock b/apps/web/yarn.lock
index 06433e98e..3a6c395fa 100644
--- a/apps/web/yarn.lock
+++ b/apps/web/yarn.lock
@@ -2079,6 +2079,14 @@
resolved "https://registry.yarnpkg.com/@stablelib/wipe/-/wipe-1.0.1.tgz#d21401f1d59ade56a62e139462a97f104ed19a36"
integrity sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==
+"@streetwritersco/tinymce-plugins@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@streetwritersco/tinymce-plugins/-/tinymce-plugins-1.0.0.tgz#05a5889a9cdad79b9ff01fc3f6d28febcebf2912"
+ integrity sha512-CBRQSF+6N2hIXb9mPnerkTb5Zr1qdQGzhNDcMT1l4ugUyvB2Yeb6dBy+tBgdeoJ3046jODDjPxUmQmSoGo3BGw==
+ dependencies:
+ highlight.js "^11.1.0"
+ rangy "^1.3.0"
+
"@styled-system/background@^5.1.2":
version "5.1.2"
resolved "https://registry.npmjs.org/@styled-system/background/-/background-5.1.2.tgz"
@@ -8608,19 +8616,6 @@ normalize-url@^3.0.0:
resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz"
integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
-notes-core@../notes-core/:
- version "6.8.0"
- dependencies:
- "@stablelib/blake2s" "^1.0.1"
- dayjs "^1.10.6"
- fast-sort "^2.0.1"
- lean-he "^2.1.2"
- no-internet "^1.5.2"
- qclone "^1.0.4"
- quill-delta-to-html "^0.12.0"
- showdown "https://github.com/thecodrr/showdown"
- spark-md5 "^3.0.1"
-
"notes-core@git+https://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:x-oauth-basic@github.com/streetwriters/notesnook-core.git":
version "6.8.0"
resolved "git+https://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:x-oauth-basic@github.com/streetwriters/notesnook-core.git#f3cc6b5dacac443966bccace43a7f98f13e367be"