You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
384 lines
12 KiB
384 lines
12 KiB
/** |
|
* TinyMCE version 6.4.2 (2023-04-26) |
|
*/ |
|
|
|
(function () { |
|
'use strict'; |
|
|
|
var global = 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$1 = type => value => typeOf(value) === type; |
|
const isSimpleType = type => value => typeof value === type; |
|
const isString = isType$1('string'); |
|
const isBoolean = isSimpleType('boolean'); |
|
const isNullable = a => a === null || a === undefined; |
|
const isNonNullable = a => !isNullable(a); |
|
const isFunction = isSimpleType('function'); |
|
const isNumber = isSimpleType('number'); |
|
|
|
const compose1 = (fbc, fab) => a => fbc(fab(a)); |
|
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); |
|
|
|
const map = (xs, f) => { |
|
const len = xs.length; |
|
const r = new Array(len); |
|
for (let i = 0; i < len; i++) { |
|
const x = xs[i]; |
|
r[i] = f(x, i); |
|
} |
|
return r; |
|
}; |
|
const each = (xs, f) => { |
|
for (let i = 0, len = xs.length; i < len; i++) { |
|
const x = xs[i]; |
|
f(x, i); |
|
} |
|
}; |
|
const filter = (xs, pred) => { |
|
const r = []; |
|
for (let i = 0, len = xs.length; i < len; i++) { |
|
const x = xs[i]; |
|
if (pred(x, i)) { |
|
r.push(x); |
|
} |
|
} |
|
return r; |
|
}; |
|
|
|
const DOCUMENT = 9; |
|
const DOCUMENT_FRAGMENT = 11; |
|
const ELEMENT = 1; |
|
const TEXT = 3; |
|
|
|
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'); |
|
} |
|
} |
|
}; |
|
|
|
typeof window !== 'undefined' ? window : Function('return this;')(); |
|
|
|
const name = element => { |
|
const r = element.dom.nodeName; |
|
return r.toLowerCase(); |
|
}; |
|
const type = element => element.dom.nodeType; |
|
const isType = t => element => type(element) === t; |
|
const isElement = isType(ELEMENT); |
|
const isText = isType(TEXT); |
|
const isDocument = isType(DOCUMENT); |
|
const isDocumentFragment = isType(DOCUMENT_FRAGMENT); |
|
const isTag = tag => e => isElement(e) && name(e) === tag; |
|
|
|
const owner = element => SugarElement.fromDom(element.dom.ownerDocument); |
|
const documentOrOwner = dos => isDocument(dos) ? dos : owner(dos); |
|
const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom); |
|
const children$2 = element => map(element.dom.childNodes, SugarElement.fromDom); |
|
|
|
const rawSet = (dom, key, value) => { |
|
if (isString(value) || isBoolean(value) || isNumber(value)) { |
|
dom.setAttribute(key, value + ''); |
|
} else { |
|
console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom); |
|
throw new Error('Attribute value was not simple'); |
|
} |
|
}; |
|
const set = (element, key, value) => { |
|
rawSet(element.dom, key, value); |
|
}; |
|
const remove = (element, key) => { |
|
element.dom.removeAttribute(key); |
|
}; |
|
|
|
const isShadowRoot = dos => isDocumentFragment(dos) && isNonNullable(dos.dom.host); |
|
const supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode); |
|
const getRootNode = supported ? e => SugarElement.fromDom(e.dom.getRootNode()) : documentOrOwner; |
|
const getShadowRoot = e => { |
|
const r = getRootNode(e); |
|
return isShadowRoot(r) ? Optional.some(r) : Optional.none(); |
|
}; |
|
const getShadowHost = e => SugarElement.fromDom(e.dom.host); |
|
|
|
const inBody = element => { |
|
const dom = isText(element) ? element.dom.parentNode : element.dom; |
|
if (dom === undefined || dom === null || dom.ownerDocument === null) { |
|
return false; |
|
} |
|
const doc = dom.ownerDocument; |
|
return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost)); |
|
}; |
|
|
|
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 ancestor = (scope, selector, isRoot) => ancestor$1(scope, e => is(e, selector), isRoot); |
|
|
|
const isSupported = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue); |
|
|
|
const get = (element, property) => { |
|
const dom = element.dom; |
|
const styles = window.getComputedStyle(dom); |
|
const r = styles.getPropertyValue(property); |
|
return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r; |
|
}; |
|
const getUnsafeProperty = (dom, property) => isSupported(dom) ? dom.style.getPropertyValue(property) : ''; |
|
|
|
const getDirection = element => get(element, 'direction') === 'rtl' ? 'rtl' : 'ltr'; |
|
|
|
const children$1 = (scope, predicate) => filter(children$2(scope), predicate); |
|
|
|
const children = (scope, selector) => children$1(scope, e => is(e, selector)); |
|
|
|
const getParentElement = element => parent(element).filter(isElement); |
|
const getNormalizedBlock = (element, isListItem) => { |
|
const normalizedElement = isListItem ? ancestor(element, 'ol,ul') : Optional.some(element); |
|
return normalizedElement.getOr(element); |
|
}; |
|
const isListItem = isTag('li'); |
|
const setDir = (editor, dir) => { |
|
const selectedBlocks = editor.selection.getSelectedBlocks(); |
|
if (selectedBlocks.length > 0) { |
|
each(selectedBlocks, block => { |
|
const blockElement = SugarElement.fromDom(block); |
|
const isBlockElementListItem = isListItem(blockElement); |
|
const normalizedBlock = getNormalizedBlock(blockElement, isBlockElementListItem); |
|
const normalizedBlockParent = getParentElement(normalizedBlock); |
|
normalizedBlockParent.each(parent => { |
|
const parentDirection = getDirection(parent); |
|
if (parentDirection !== dir) { |
|
set(normalizedBlock, 'dir', dir); |
|
} else if (getDirection(normalizedBlock) !== dir) { |
|
remove(normalizedBlock, 'dir'); |
|
} |
|
if (isBlockElementListItem) { |
|
const listItems = children(normalizedBlock, 'li[dir]'); |
|
each(listItems, listItem => remove(listItem, 'dir')); |
|
} |
|
}); |
|
}); |
|
editor.nodeChanged(); |
|
} |
|
}; |
|
|
|
const register$1 = editor => { |
|
editor.addCommand('mceDirectionLTR', () => { |
|
setDir(editor, 'ltr'); |
|
}); |
|
editor.addCommand('mceDirectionRTL', () => { |
|
setDir(editor, 'rtl'); |
|
}); |
|
}; |
|
|
|
const getNodeChangeHandler = (editor, dir) => api => { |
|
const nodeChangeHandler = e => { |
|
const element = SugarElement.fromDom(e.element); |
|
api.setActive(getDirection(element) === dir); |
|
}; |
|
editor.on('NodeChange', nodeChangeHandler); |
|
return () => editor.off('NodeChange', nodeChangeHandler); |
|
}; |
|
const register = editor => { |
|
editor.ui.registry.addToggleButton('ltr', { |
|
tooltip: 'Left to right', |
|
icon: 'ltr', |
|
onAction: () => editor.execCommand('mceDirectionLTR'), |
|
onSetup: getNodeChangeHandler(editor, 'ltr') |
|
}); |
|
editor.ui.registry.addToggleButton('rtl', { |
|
tooltip: 'Right to left', |
|
icon: 'rtl', |
|
onAction: () => editor.execCommand('mceDirectionRTL'), |
|
onSetup: getNodeChangeHandler(editor, 'rtl') |
|
}); |
|
}; |
|
|
|
var Plugin = () => { |
|
global.add('directionality', editor => { |
|
register$1(editor); |
|
register(editor); |
|
}); |
|
}; |
|
|
|
Plugin(); |
|
|
|
})();
|
|
|