diff --git a/dev/External/SquireUI.js b/dev/External/SquireUI.js index ef0f638df..c22da1d0b 100644 --- a/dev/External/SquireUI.js +++ b/dev/External/SquireUI.js @@ -19,6 +19,8 @@ const htmlToPlain = html => rl.Utils.htmlToPlain(html).trim(), plainToHtml = text => rl.Utils.plainToHtml(text), + forEachObjectValue = (obj, fn) => Object.values(obj).forEach(fn), + getFragmentOfChildren = parent => { let frag = doc.createDocumentFragment(); frag.append(...parent.childNodes); @@ -127,37 +129,43 @@ class SquireUI html: 'B', cmd: () => this.doAction('bold'), key: 'B', - hint: 'Bold' + hint: 'Bold', + matches: 'B,STRONT' }, italic: { html: 'I', cmd: () => this.doAction('italic'), key: 'I', - hint: 'Italic' + hint: 'Italic', + matches: 'I' }, underline: { html: 'U', cmd: () => this.doAction('underline'), key: 'U', - hint: 'Underline' + hint: 'Underline', + matches: 'U' }, strike: { html: 'S', cmd: () => this.doAction('strikethrough'), key: 'Shift + 7', - hint: 'Strikethrough' + hint: 'Strikethrough', + matches: 'S' }, sub: { html: 'Xₙ', cmd: () => this.doAction('subscript'), key: 'Shift + 5', - hint: 'Subscript' + hint: 'Subscript', + matches: 'SUB' }, sup: { html: 'Xⁿ', cmd: () => this.doAction('superscript'), key: 'Shift + 6', - hint: 'Superscript' + hint: 'Superscript', + matches: 'SUP' } }, block: { @@ -165,13 +173,15 @@ class SquireUI html: '#', cmd: () => this.doList('OL'), key: 'Shift + 8', - hint: 'Ordered list' + hint: 'Ordered list', + matches: 'OL' }, ul: { html: '⋮', cmd: () => this.doList('UL'), key: 'Shift + 9', - hint: 'Unordered list' + hint: 'Unordered list', + matches: 'UL' }, quote: { html: '"', @@ -179,7 +189,8 @@ class SquireUI let parent = squire.getSelectionClosest('UL,OL,BLOCKQUOTE')?.nodeName; ('BLOCKQUOTE' == parent) ? squire.decreaseQuoteLevel() : squire.increaseQuoteLevel(); }, - hint: 'Blockquote' + hint: 'Blockquote', + matches: 'BLOCKQUOTE' }, indentDecrease: { html: '⇤', @@ -204,7 +215,8 @@ class SquireUI url.length ? squire.makeLink(url) : (node && squire.removeLink()); } }, - hint: 'Link' + hint: 'Link', + matches: 'A' }, imageUrl: { html: '🖼️', @@ -213,12 +225,14 @@ class SquireUI src = prompt("Image", node?.src || "https://"); src?.length ? squire.insertImage(src) : (node && squire.detach(node)); }, - hint: 'Image URL' + hint: 'Image URL', + matches: 'IMG' }, imageUpload: { html: '📂️', cmd: () => browseImage.click(), hint: 'Image select', + matches: 'IMG' } }, /* @@ -241,7 +255,10 @@ class SquireUI }, source: { html: '👁', - cmd: () => this.setMode('source' == this.mode ? 'wysiwyg' : 'source'), + cmd: btn => { + this.setMode('source' == this.mode ? 'wysiwyg' : 'source'); + btn.classList.toggle('active', 'source' == this.mode); + }, hint: i18n('EDITOR/TEXT_SWITCHER_SOURCE', 'Source') } } @@ -362,15 +379,21 @@ class SquireUI container.append(toolbar, wysiwyg, plain); + squire.addEventListener('pathChange', e => { + forEachObjectValue(actions, entries => { + forEachObjectValue(entries, cfg => { +// cfg.matches && cfg.input.classList.toggle('active', e.element && e.element.matches(cfg.matches)); + cfg.matches && cfg.input.classList.toggle('active', e.element && e.element.closestWithin(cfg.matches, squire.getRoot())); + }); + }); + }); /* - squire.addEventListener('dragover', ); - squire.addEventListener('drop', ); - squire.addEventListener('pathChange', ); - squire.addEventListener('cursor', ); - squire.addEventListener('select', ); - squire.addEventListener('input', ); - squire.addEventListener( 'keydown keyup', monitorShiftKey ) - squire.addEventListener( 'keydown', onKey ) + squire.addEventListener('cursor', e => { + console.dir({cursor:e.range}); + }); + squire.addEventListener('select', e => { + console.dir({select:e.range}); + }); */ // CKEditor gimmicks used by HtmlEditor @@ -393,11 +416,11 @@ class SquireUI fn = {UL:'makeUnorderedList',OL:'makeOrderedList'}; (parent == type) ? this.squire.removeList() : this.squire[fn[type]](); } - +/* testPresenceinSelection(format, validation) { return validation.test(this.squire.getPath()) || this.squire.hasFormat(format); } - +*/ setMode(mode) { if (this.mode != mode) { let cl = this.container.classList, source = 'source' == this.mode; diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Traits/ResponseParser.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Traits/ResponseParser.php index 3bcf37bd6..d7fb040ea 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Traits/ResponseParser.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Traits/ResponseParser.php @@ -266,8 +266,7 @@ trait ResponseParser $oImapResponse, true, $sPreviousAtomUpperCase, '[' ); - if (null !== $sListBlock) - { + if (null !== $sListBlock) { $sAtomBuilder .= $sListBlock.']'; } diff --git a/vendors/squire/build/squire-raw.js b/vendors/squire/build/squire-raw.js index 59ef49c7e..0a83aa740 100644 --- a/vendors/squire/build/squire-raw.js +++ b/vendors/squire/build/squire-raw.js @@ -76,7 +76,8 @@ const BLOCK = 2, CONTAINER = 3, - isLeaf = node => node.nodeType === ELEMENT_NODE && !!leafNodeNames[ node.nodeName ], + isElement = node => node.nodeType === ELEMENT_NODE, + isLeaf = node => isElement(node) && !!leafNodeNames[ node.nodeName ], getNodeCategory = node => { switch (node.nodeType) { @@ -157,7 +158,7 @@ const let path = '', style; if (node && node !== root) { path = getPath(node.parentNode, root); - if (node.nodeType === ELEMENT_NODE) { + if (isElement(node)) { path += (path ? '>' : '') + node.nodeName; if (node.id) { path += '#' + node.id; @@ -395,7 +396,7 @@ const frags.push(empty(child)); } } - else if (child.nodeType === ELEMENT_NODE) { + else if (isElement(child)) { child.append(...frags.reverse()); frags = []; _mergeInlines(child, fakeRange); @@ -407,7 +408,7 @@ const if (node.nodeType === TEXT_NODE) { node = node.parentNode; } - if (node.nodeType === ELEMENT_NODE) { + if (isElement(node)) { let fakeRange = { startContainer: range.startContainer, startOffset: range.startOffset, @@ -425,7 +426,7 @@ const let parent, last, offset; while ((parent = container.parentNode) && parent !== root && - parent.nodeType === ELEMENT_NODE && + isElement(parent) && parent.childNodes.length === 1) { container = parent; } @@ -485,7 +486,7 @@ const getNodeBefore = (node, offset) => { let children = node.childNodes; - while (offset && node.nodeType === ELEMENT_NODE) { + while (offset && isElement(node)) { node = children[ offset - 1 ]; children = node.childNodes; offset = children.length; @@ -494,7 +495,7 @@ const }, getNodeAfter = (node, offset) => { - if (node.nodeType === ELEMENT_NODE) { + if (isElement(node)) { let children = node.childNodes; if (offset < children.length) { node = children[ offset ]; @@ -1221,7 +1222,7 @@ const // Focus cursor // If there's a / etc. at the beginning of the split // make sure we focus inside it. - while (nodeAfterSplit.nodeType === ELEMENT_NODE) { + while (isElement(nodeAfterSplit)) { let child = nodeAfterSplit.firstChild, next; @@ -1525,7 +1526,7 @@ const child; while (l--) { child = children[l]; - if (child.nodeType === ELEMENT_NODE && !isLeaf(child)) { + if (isElement(child) && !isLeaf(child)) { removeEmptyInlines(child); if (!child.firstChild && isInline(child)) { child.remove(); @@ -1538,7 +1539,7 @@ const // --- - notWSTextNode = node => node.nodeType === ELEMENT_NODE ? node.nodeName === 'BR' : notWS.test(node.data), + notWSTextNode = node => isElement(node) ? node.nodeName === 'BR' : notWS.test(node.data), isLineBreak = (br, isLBIfEmptyBlock) => { let walker, block = br.parentNode; while (isInline(block)) { @@ -2139,7 +2140,7 @@ let keyHandlers = { moveRangeBoundariesUpTree(range, root, root, root); cursorContainer = range.endContainer; cursorOffset = range.endOffset; - if (cursorContainer.nodeType === ELEMENT_NODE) { + if (isElement(cursorContainer)) { nodeAfterCursor = cursorContainer.childNodes[ cursorOffset ]; if (nodeAfterCursor?.nodeName === 'IMG') { event.preventDefault(); @@ -2660,15 +2661,15 @@ class Squire if (range) { let anchor = range.startContainer, focus = range.endContainer, - newPath; + newPath, node; if (force || anchor !== this._lastAnchorNode || focus !== this._lastFocusNode) { this._lastAnchorNode = anchor; this._lastFocusNode = focus; - newPath = (anchor && focus) ? (anchor === focus ? - getPath(focus, this._root) : '(selection)') : ''; + node = anchor === focus ? focus : null; + newPath = (anchor && focus) ? (node ? getPath(focus, this._root) : '(selection)') : ''; if (this._path !== newPath) { this._path = newPath; - this.fireEvent('pathChange', { path: newPath }); + this.fireEvent('pathChange', { path: newPath, element: isElement(node) ? node : node.parentElement }); } } this.fireEvent(range.collapsed ? 'cursor' : 'select', {