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 = ""; - 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"