/** * TinyMCE version 6.4.1 (2023-03-29) */ (function () { 'use strict'; var global$2 = tinymce.util.Tools.resolve('tinymce.PluginManager'); const hasProto = (v, constructor, predicate) => { var _a; if (predicate(v, constructor.prototype)) { return true; } else { return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name; } }; const typeOf = x => { const t = typeof x; if (x === null) { return 'null'; } else if (t === 'object' && Array.isArray(x)) { return 'array'; } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) { return 'string'; } else { return t; } }; const isType = type => value => typeOf(value) === type; const isSimpleType = type => value => typeof value === type; const isString = isType('string'); const isBoolean = isSimpleType('boolean'); const isNullable = a => a === null || a === undefined; const isNonNullable = a => !isNullable(a); const isFunction = isSimpleType('function'); const option = name => editor => editor.options.get(name); const register = editor => { const registerOption = editor.options.register; const toolbarProcessor = defaultValue => value => { const valid = isBoolean(value) || isString(value); if (valid) { if (isBoolean(value)) { return { value: value ? defaultValue : '', valid }; } else { return { value: value.trim(), valid }; } } else { return { valid: false, message: 'Must be a boolean or string.' }; } }; const defaultSelectionToolbar = 'bold italic | quicklink h2 h3 blockquote'; registerOption('quickbars_selection_toolbar', { processor: toolbarProcessor(defaultSelectionToolbar), default: defaultSelectionToolbar }); const defaultInsertToolbar = 'quickimage quicktable'; registerOption('quickbars_insert_toolbar', { processor: toolbarProcessor(defaultInsertToolbar), default: defaultInsertToolbar }); const defaultImageToolbar = 'alignleft aligncenter alignright'; registerOption('quickbars_image_toolbar', { processor: toolbarProcessor(defaultImageToolbar), default: defaultImageToolbar }); }; const getTextSelectionToolbarItems = option('quickbars_selection_toolbar'); const getInsertToolbarItems = option('quickbars_insert_toolbar'); const getImageToolbarItems = option('quickbars_image_toolbar'); let unique = 0; const generate = prefix => { const date = new Date(); const time = date.getTime(); const random = Math.floor(Math.random() * 1000000000); unique++; return prefix + '_' + random + unique + String(time); }; const insertTable = (editor, columns, rows) => { editor.execCommand('mceInsertTable', false, { rows, columns }); }; const insertBlob = (editor, base64, blob) => { const blobCache = editor.editorUpload.blobCache; const blobInfo = blobCache.create(generate('mceu'), blob, base64); blobCache.add(blobInfo); editor.insertContent(editor.dom.createHTML('img', { src: blobInfo.blobUri() })); }; const blobToBase64 = blob => { return new Promise(resolve => { const reader = new FileReader(); reader.onloadend = () => { resolve(reader.result.split(',')[1]); }; reader.readAsDataURL(blob); }); }; var global$1 = tinymce.util.Tools.resolve('tinymce.Env'); var global = tinymce.util.Tools.resolve('tinymce.util.Delay'); const pickFile = editor => new Promise(resolve => { const fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.accept = 'image/*'; fileInput.style.position = 'fixed'; fileInput.style.left = '0'; fileInput.style.top = '0'; fileInput.style.opacity = '0.001'; document.body.appendChild(fileInput); const changeHandler = e => { resolve(Array.prototype.slice.call(e.target.files)); }; fileInput.addEventListener('change', changeHandler); const cancelHandler = e => { const cleanup = () => { var _a; resolve([]); (_a = fileInput.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(fileInput); }; if (global$1.os.isAndroid() && e.type !== 'remove') { global.setEditorTimeout(editor, cleanup, 0); } else { cleanup(); } editor.off('focusin remove', cancelHandler); }; editor.on('focusin remove', cancelHandler); fileInput.click(); }); const setupButtons = editor => { editor.ui.registry.addButton('quickimage', { icon: 'image', tooltip: 'Insert image', onAction: () => { pickFile(editor).then(files => { if (files.length > 0) { const blob = files[0]; blobToBase64(blob).then(base64 => { insertBlob(editor, base64, blob); }); } }); } }); editor.ui.registry.addButton('quicktable', { icon: 'table', tooltip: 'Insert table', onAction: () => { insertTable(editor, 2, 2); } }); }; const constant = value => { return () => { return value; }; }; const never = constant(false); class Optional { constructor(tag, value) { this.tag = tag; this.value = value; } static some(value) { return new Optional(true, value); } static none() { return Optional.singletonNone; } fold(onNone, onSome) { if (this.tag) { return onSome(this.value); } else { return onNone(); } } isSome() { return this.tag; } isNone() { return !this.tag; } map(mapper) { if (this.tag) { return Optional.some(mapper(this.value)); } else { return Optional.none(); } } bind(binder) { if (this.tag) { return binder(this.value); } else { return Optional.none(); } } exists(predicate) { return this.tag && predicate(this.value); } forall(predicate) { return !this.tag || predicate(this.value); } filter(predicate) { if (!this.tag || predicate(this.value)) { return this; } else { return Optional.none(); } } getOr(replacement) { return this.tag ? this.value : replacement; } or(replacement) { return this.tag ? this : replacement; } getOrThunk(thunk) { return this.tag ? this.value : thunk(); } orThunk(thunk) { return this.tag ? this : thunk(); } getOrDie(message) { if (!this.tag) { throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None'); } else { return this.value; } } static from(value) { return isNonNullable(value) ? Optional.some(value) : Optional.none(); } getOrNull() { return this.tag ? this.value : null; } getOrUndefined() { return this.value; } each(worker) { if (this.tag) { worker(this.value); } } toArray() { return this.tag ? [this.value] : []; } toString() { return this.tag ? `some(${ this.value })` : 'none()'; } } Optional.singletonNone = new Optional(false); typeof window !== 'undefined' ? window : Function('return this;')(); const ELEMENT = 1; const name = element => { const r = element.dom.nodeName; return r.toLowerCase(); }; const has = (element, key) => { const dom = element.dom; return dom && dom.hasAttribute ? dom.hasAttribute(key) : false; }; var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => { if (is(scope, a)) { return Optional.some(scope); } else if (isFunction(isRoot) && isRoot(scope)) { return Optional.none(); } else { return ancestor(scope, a, isRoot); } }; const fromHtml = (html, scope) => { const doc = scope || document; const div = doc.createElement('div'); div.innerHTML = html; if (!div.hasChildNodes() || div.childNodes.length > 1) { const message = 'HTML does not have a single root node'; console.error(message, html); throw new Error(message); } return fromDom(div.childNodes[0]); }; const fromTag = (tag, scope) => { const doc = scope || document; const node = doc.createElement(tag); return fromDom(node); }; const fromText = (text, scope) => { const doc = scope || document; const node = doc.createTextNode(text); return fromDom(node); }; const fromDom = node => { if (node === null || node === undefined) { throw new Error('Node cannot be null or undefined'); } return { dom: node }; }; const fromPoint = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom); const SugarElement = { fromHtml, fromTag, fromText, fromDom, fromPoint }; const is = (element, selector) => { const dom = element.dom; if (dom.nodeType !== ELEMENT) { return false; } else { const elem = dom; if (elem.matches !== undefined) { return elem.matches(selector); } else if (elem.msMatchesSelector !== undefined) { return elem.msMatchesSelector(selector); } else if (elem.webkitMatchesSelector !== undefined) { return elem.webkitMatchesSelector(selector); } else if (elem.mozMatchesSelector !== undefined) { return elem.mozMatchesSelector(selector); } else { throw new Error('Browser lacks native selectors'); } } }; const ancestor$1 = (scope, predicate, isRoot) => { let element = scope.dom; const stop = isFunction(isRoot) ? isRoot : never; while (element.parentNode) { element = element.parentNode; const el = SugarElement.fromDom(element); if (predicate(el)) { return Optional.some(el); } else if (stop(el)) { break; } } return Optional.none(); }; const closest$2 = (scope, predicate, isRoot) => { const is = (s, test) => test(s); return ClosestOrAncestor(is, ancestor$1, scope, predicate, isRoot); }; const closest$1 = (scope, predicate, isRoot) => closest$2(scope, predicate, isRoot).isSome(); const ancestor = (scope, selector, isRoot) => ancestor$1(scope, e => is(e, selector), isRoot); const closest = (scope, selector, isRoot) => { const is$1 = (element, selector) => is(element, selector); return ClosestOrAncestor(is$1, ancestor, scope, selector, isRoot); }; const addToEditor$1 = editor => { const insertToolbarItems = getInsertToolbarItems(editor); if (insertToolbarItems.length > 0) { editor.ui.registry.addContextToolbar('quickblock', { predicate: node => { const sugarNode = SugarElement.fromDom(node); const textBlockElementsMap = editor.schema.getTextBlockElements(); const isRoot = elem => elem.dom === editor.getBody(); return !has(sugarNode, 'data-mce-bogus') && closest(sugarNode, 'table,[data-mce-bogus="all"]', isRoot).fold(() => closest$1(sugarNode, elem => name(elem) in textBlockElementsMap && editor.dom.isEmpty(elem.dom), isRoot), never); }, items: insertToolbarItems, position: 'line', scope: 'editor' }); } }; const addToEditor = editor => { const isEditable = node => editor.dom.getContentEditableParent(node) !== 'false'; const isImage = node => node.nodeName === 'IMG' || node.nodeName === 'FIGURE' && /image/i.test(node.className); const imageToolbarItems = getImageToolbarItems(editor); if (imageToolbarItems.length > 0) { editor.ui.registry.addContextToolbar('imageselection', { predicate: isImage, items: imageToolbarItems, position: 'node' }); } const textToolbarItems = getTextSelectionToolbarItems(editor); if (textToolbarItems.length > 0) { editor.ui.registry.addContextToolbar('textselection', { predicate: node => !isImage(node) && !editor.selection.isCollapsed() && isEditable(node), items: textToolbarItems, position: 'selection', scope: 'editor' }); } }; var Plugin = () => { global$2.add('quickbars', editor => { register(editor); setupButtons(editor); addToEditor$1(editor); addToEditor(editor); }); }; Plugin(); })();