Cleanup unused Squire code

This commit is contained in:
the-djmaze 2023-02-20 13:12:09 +01:00
parent e56d1cf5c6
commit 8a63ae05ef
2 changed files with 1257 additions and 1370 deletions

View file

@ -27,11 +27,6 @@ const
SquireDefaultConfig = {
/*
blockTag: 'P',
undo: {
documentSizeThreshold: -1, // -1 means no threshold
undoLimit: -1 // -1 means no limit
},
addLinks: true // allow_smart_html_links
*/
sanitizeToDOMFragment: (html, isPaste/*, squire*/) => {
@ -379,7 +374,6 @@ class SquireUI
squire.addEventListener('cursor', );
squire.addEventListener('select', );
squire.addEventListener('input', );
squire.addEventListener('willPaste', );
squire.addEventListener( 'keydown keyup', monitorShiftKey )
squire.addEventListener( 'keydown', onKey )
*/

View file

@ -11,6 +11,7 @@
(doc => {
const
blockTag = 'DIV',
DOCUMENT_POSITION_PRECEDING = 2, // Node.DOCUMENT_POSITION_PRECEDING
ELEMENT_NODE = 1, // Node.ELEMENT_NODE,
TEXT_NODE = 3, // Node.TEXT_NODE,
@ -152,10 +153,10 @@ const
return null;
},
getPath = ( node, root, config ) => {
getPath = (node, root) => {
let path = '', style;
if (node && node !== root) {
path = getPath( node.parentNode, root, config );
path = getPath(node.parentNode, root);
if (node.nodeType === ELEMENT_NODE) {
path += (path ? '>' : '') + node.nodeName;
if (node.id) {
@ -284,7 +285,7 @@ const
[...container.children].forEach(child => {
isBR = child.nodeName === 'BR';
if (!isBR && isInline(child)
// && (root.__squire__._config.blockTag !== 'DIV' || (child.matches && !child.matches(phrasingElements)))
// && (blockTag !== 'DIV' || (child.matches && !child.matches(phrasingElements)))
) {
wrapper = wrapper || createElement('div');
wrapper.append(child);
@ -1070,8 +1071,7 @@ const
node = node.parentNode;
}
parent = node;
while ( isInline( parent ) &&
( !parent.textContent || parent.textContent === ZWS ) ) {
while (isInline(parent) && (!parent.textContent || parent.textContent === ZWS)) {
node = parent;
parent = node.parentNode;
}
@ -1095,8 +1095,7 @@ const
// it removes the div and replaces it with just a <br> inside the
// root. Detach the <br>; the _ensureBottomLine call will insert a new
// block.
if ( node === self._root &&
( node = node.firstChild ) && node.nodeName === 'BR' ) {
if (node === self._root && (node = node.firstChild) && node.nodeName === 'BR') {
detach(node);
}
self._ensureBottomLine();
@ -1126,9 +1125,7 @@ const
// Remove any zws so we don't think there's content in an empty
// block.
self._recordUndoState(range, false);
if ( self._config.addLinks ) {
addLinks( range.startContainer, root, self );
}
self._config.addLinks && addLinks(range.startContainer, root, self);
self._removeZWS();
self._getRangeAndRemoveBookmark(range);
@ -1229,9 +1226,7 @@ const
// Don't continue links over a block break; unlikely to be the
// desired outcome.
if ( nodeAfterSplit.nodeName === 'A' &&
( !nodeAfterSplit.textContent ||
nodeAfterSplit.textContent === ZWS ) ) {
if (nodeAfterSplit.nodeName === 'A' && (!nodeAfterSplit.textContent || nodeAfterSplit.textContent === ZWS)) {
child = doc.createTextNode('');
nodeAfterSplit.replaceWith(child);
nodeAfterSplit = child;
@ -1436,7 +1431,7 @@ const
and whitespace nodes.
2. Convert inline tags into our preferred format.
*/
cleanTree = ( node, config, preserveWS ) => {
cleanTree = (node, preserveWS) => {
let children = node.childNodes,
nonInlineParent, i, l, child, nodeName, nodeType, childLength;
// startsWithWS, endsWithWS, data, sibling;
@ -1467,8 +1462,7 @@ const
continue;
}
if (childLength) {
cleanTree( child, config,
preserveWS || ( nodeName === 'PRE' ) );
cleanTree(child, preserveWS || (nodeName === 'PRE'));
}
/*
} else {
@ -1485,9 +1479,7 @@ const
walker.currentNode = child;
while (sibling = previousPONode(walker)) {
nodeName = sibling.nodeName;
if ( nodeName === 'IMG' ||
( nodeName === '#text' &&
notWS.test( sibling.data ) ) ) {
if (nodeName === 'IMG' || (nodeName === '#text' && notWS.test(sibling.data))) {
break;
}
if (!isInline(sibling)) {
@ -1500,9 +1492,7 @@ const
if (endsWithWS) {
walker.currentNode = child;
while (sibling = walker.nextNode()) {
if ( nodeName === 'IMG' ||
( nodeName === '#text' &&
notWS.test( sibling.data ) ) ) {
if (nodeName === 'IMG' || (nodeName === '#text' && notWS.test(sibling.data))) {
break;
}
if (!isInline(sibling)) {
@ -1555,8 +1545,7 @@ const
}
walker = createTreeWalker(block, SHOW_ELEMENT_OR_TEXT, notWSTextNode);
walker.currentNode = br;
return !!walker.nextNode() ||
( isLBIfEmptyBlock && !walker.previousNode() );
return !!walker.nextNode() || (isLBIfEmptyBlock && !walker.previousNode());
},
// <br> elements are treated specially, and differently depending on the
@ -1589,8 +1578,7 @@ const
// The (non-standard but supported enough) innerText property is based on the
// render tree in Firefox and possibly other browsers, so we must insert the
// DOM node into the document to ensure the text part is correct.
setClipboardData =
( event, contents, root ) => {
setClipboardData = (event, contents, root) => {
let clipboardData = event.clipboardData;
let body = doc.body;
let node = createElement('div');
@ -1650,8 +1638,7 @@ const
let walker = createTreeWalker(root, SHOW_TEXT);
let parent, node, index;
while (node = walker.nextNode()) {
while ( ( index = node.data.indexOf( ZWS ) ) > -1 &&
( !keepNode || node.parentNode !== keepNode ) ) {
while ((index = node.data.indexOf(ZWS)) > -1 && (!keepNode || node.parentNode !== keepNode)) {
if (node.length === 1) {
do {
parent = node.parentNode;
@ -1693,7 +1680,7 @@ const
},
splitBlock = (self, block, node, offset) => {
let splitTag = tagAfterSplit[ block.nodeName ] || self._config.blockTag,
let splitTag = tagAfterSplit[ block.nodeName ] || blockTag,
nodeAfterSplit = split(node, offset, block.parentNode, self._root);
// Make sure the new node is the correct type.
@ -1838,9 +1825,7 @@ function onKey ( event ) {
if (this._keyHandlers[ key ]) {
this._keyHandlers[ key ](this, event, range);
// !event.isComposing stops us from blatting Kana-Kanji conversion in Safari
} else if ( !range.collapsed && !event.isComposing &&
!event[osKey] &&
key.length === 1 ) {
} else if (!range.collapsed && !event.isComposing && !event[osKey] && key.length === 1) {
// Record undo checkpoint.
this.saveUndoState(range);
// Delete the selection
@ -2207,9 +2192,7 @@ let keyHandlers = {
space: (self, _, range) => {
let root = self._root;
self._recordUndoState(range, false);
if ( self._config.addLinks ) {
addLinks( range.startContainer, root, self );
}
self._config.addLinks && addLinks(range.startContainer, root, self);
self._getRangeAndRemoveBookmark(range);
/*
// If the cursor is at the end of a link (<a>foo|</a>) then move it
@ -2223,8 +2206,7 @@ let keyHandlers = {
range.setStartAfter(node);
break;
}
} while ( !node.nextSibling &&
( node = node.parentNode ) && node !== root );
} while (!node.nextSibling && (node = node.parentNode) && node !== root);
}
*/
// Delete the selection if not collapsed
@ -2474,27 +2456,15 @@ class Squire
}
setConfig(config) {
config = mergeObjects({
blockTag: 'DIV',
this._config = mergeObjects({
addLinks: true
}, config, true);
if ( typeof config.sanitizeToDOMFragment !== 'function' ) {
config.sanitizeToDOMFragment = null;
}
// Users may specify block tag in lower case
config.blockTag = config.blockTag.toUpperCase();
this._config = config;
return this;
}
createDefaultBlock(children) {
let config = this._config;
return fixCursor(
createElement( config.blockTag, null, children ),
createElement(blockTag, null, children),
this._root
);
}
@ -2527,9 +2497,7 @@ class Squire
}
}
if (handlers) {
if ( !event ) {
event = {};
}
event = event || {};
if (event.type !== type) {
event.type = type;
}
@ -2539,11 +2507,7 @@ class Squire
while (l--) {
obj = handlers[l];
try {
if ( obj.handleEvent ) {
obj.handleEvent( event );
} else {
obj.call( this, event );
}
obj.handleEvent ? obj.handleEvent(event) : obj.call(this, event);
} catch (error) {
error.details = 'Squire: fireEvent error. Event type: ' + type;
didError(error);
@ -2699,12 +2663,11 @@ class Squire
let anchor = range.startContainer,
focus = range.endContainer,
newPath;
if ( force || anchor !== this._lastAnchorNode ||
focus !== this._lastFocusNode ) {
if (force || anchor !== this._lastAnchorNode || focus !== this._lastFocusNode) {
this._lastAnchorNode = anchor;
this._lastFocusNode = focus;
newPath = (anchor && focus) ? (anchor === focus ?
getPath( focus, this._root, this._config ) : '(selection)' ) : '';
getPath(focus, this._root) : '(selection)') : '';
if (this._path !== newPath) {
this._path = newPath;
this.fireEvent('pathChange', { path: newPath });
@ -2739,8 +2702,7 @@ class Squire
insertNodeInRange(range, endNode);
// In a collapsed range, the start is sometimes inserted after the end!
if ( startNode.compareDocumentPosition( endNode ) &
DOCUMENT_POSITION_PRECEDING ) {
if (startNode.compareDocumentPosition(endNode) & DOCUMENT_POSITION_PRECEDING) {
startNode.id = endSelectionId;
endNode.id = startSelectionId;
temp = startNode;
@ -2913,8 +2875,7 @@ class Squire
fontInfo.color = attr;
++seenAttributes;
}
if ( !fontInfo.backgroundColor &&
( attr = style.backgroundColor ) ) {
if (!fontInfo.backgroundColor && (attr = style.backgroundColor)) {
fontInfo.backgroundColor = attr;
++seenAttributes;
}
@ -3077,8 +3038,7 @@ class Squire
// in a clone of the tag we're removing and we're done.
if (!isNodeContainedInRange(range, node)) {
// Ignore bookmarks and empty text nodes
if ( node.nodeName !== 'INPUT' &&
( !isText || node.data ) ) {
if (node.nodeName !== 'INPUT' && (!isText || node.data)) {
toWrap.push([ exemplar, node ]);
}
return;
@ -3311,8 +3271,7 @@ class Squire
_ensureBottomLine () {
let root = this._root;
let last = root.lastElementChild;
if ( !last ||
last.nodeName !== this._config.blockTag || !isBlock( last ) ) {
if (!last || last.nodeName !== blockTag || !isBlock(last)) {
root.append(this.createDefaultBlock());
}
}
@ -3326,13 +3285,8 @@ class Squire
_setHTML (html) {
let root = this._root;
let node = root;
let sanitizeToDOMFragment = this._config.sanitizeToDOMFragment;
if ( sanitizeToDOMFragment ) {
empty( node );
node.appendChild( sanitizeToDOMFragment( html, false, this ) );
} else {
node.innerHTML = html;
}
empty(root);
root.appendChild(this._config.sanitizeToDOMFragment(html, false));
do {
fixCursor(node, root);
} while (node = getNextBlock(node, root));
@ -3350,22 +3304,12 @@ class Squire
}
setHTML(html) {
let config = this._config;
let sanitizeToDOMFragment = config.sanitizeToDOMFragment;
let root = this._root;
let div, frag, child;
let root = this._root,
// Parse HTML into DOM tree
if ( sanitizeToDOMFragment ) {
frag = sanitizeToDOMFragment( html, false, this );
} else {
div = createElement( 'DIV' );
div.innerHTML = html;
frag = doc.createDocumentFragment();
frag.append( empty( div ) );
}
frag = this._config.sanitizeToDOMFragment(html, false),
child;
cleanTree( frag, config );
cleanTree(frag);
cleanupBRs(frag, root, false);
fixContainer(frag, root);
@ -3459,55 +3403,28 @@ class Squire
// insertTreeFragmentIntoRange will delete the selection so that it is replaced
// by the html being inserted.
insertHTML(html, isPaste) {
let config = this._config;
let sanitizeToDOMFragment = config.sanitizeToDOMFragment;
let range = this.getSelection();
let startFragmentIndex, endFragmentIndex;
let div, frag, root, node, event;
// Edge doesn't just copy the fragment, but includes the surrounding guff
// including the full <head> of the page. Need to strip this out.
if (isPaste) {
startFragmentIndex = html.indexOf( '<!--StartFragment-->' );
let startFragmentIndex = html.indexOf('<!--StartFragment-->'),
endFragmentIndex = html.lastIndexOf('<!--EndFragment-->');
if (startFragmentIndex > -1 && endFragmentIndex > -1) {
html = html.slice(startFragmentIndex + 20, endFragmentIndex);
}
}
if ( sanitizeToDOMFragment ) {
frag = sanitizeToDOMFragment( html, isPaste, this );
} else {
// Wrap with <tr> if html contains dangling <td> tags
if ( /<\/td>((?!<\/tr>)[\s\S])*$/i.test( html ) ) {
html = '<TR>' + html + '</TR>';
}
// Wrap with <table> if html contains dangling <tr> tags
if ( /<\/tr>((?!<\/table>)[\s\S])*$/i.test( html ) ) {
html = '<TABLE>' + html + '</TABLE>';
}
// Parse HTML into DOM tree
div = createElement( 'DIV' );
div.innerHTML = html;
frag = doc.createDocumentFragment();
frag.append( empty( div ) );
}
let frag = this._config.sanitizeToDOMFragment(html, isPaste);
// Record undo checkpoint
this.saveUndoState(range);
try {
root = this._root;
node = frag;
event = {
fragment: frag,
preventDefault: function () {
this.defaultPrevented = true;
},
defaultPrevented: false
};
let root = this._root, node = frag;
addLinks(frag, frag, this);
cleanTree( frag, config );
cleanTree(frag);
cleanupBRs(frag, root, false);
removeEmptyInlines(frag);
frag.normalize();
@ -3516,10 +3433,7 @@ class Squire
fixCursor(node, root);
}
isPaste && this.fireEvent( 'willPaste', event );
if ( !event.defaultPrevented ) {
insertTreeFragmentIntoRange( range, event.fragment, root );
insertTreeFragmentIntoRange(range, frag, root);
range.collapse(false);
// After inserting the fragment, check whether the cursor is inside
@ -3528,7 +3442,6 @@ class Squire
moveRangeBoundaryOutOf(range, 'A', root);
this._ensureBottomLine();
}
this.setSelection(range);
this._updatePath(range, true);
@ -3542,41 +3455,28 @@ class Squire
insertPlainText(plainText, isPaste) {
let range = this.getSelection();
if ( range.collapsed &&
getClosest( range.startContainer, this._root, 'PRE' ) ) {
if (range.collapsed && getClosest(range.startContainer, this._root, 'PRE')) {
let node = range.startContainer;
let offset = range.startOffset;
let text, event;
let text;
if (node?.nodeType !== TEXT_NODE) {
text = doc.createTextNode('');
node?.childNodes[ offset ].before(text);
node = text;
offset = 0;
}
event = {
text: plainText,
preventDefault: function () {
this.defaultPrevented = true;
},
defaultPrevented: false
};
isPaste && this.fireEvent( 'willPaste', event );
if ( !event.defaultPrevented ) {
plainText = event.text;
node.insertData(offset, plainText);
range.setStart(node, offset + plainText.length);
range.collapse(true);
}
this.setSelection(range);
return this;
}
let lines = plainText.split( '\n' );
let config = this._config;
let tag = config.blockTag;
let closeBlock = '</' + tag + '>';
let openBlock = '<' + tag + '>';
let i = lines.length, line;
let lines = plainText.split(/\r?\n/),
closeBlock = '</' + blockTag + '>',
openBlock = '<' + blockTag + '>',
i = lines.length,
line;
while (i--) {
line = escapeHTML(lines[i]).replace(/ (?=)/g, '&nbsp;');
@ -3596,13 +3496,9 @@ class Squire
makeLink(url, attributes) {
let range = this.getSelection();
if (range.collapsed) {
let protocolEnd = url.indexOf( ':' ) + 1;
if ( protocolEnd ) {
while ( url[ protocolEnd ] === '/' ) { ++protocolEnd; }
}
insertNodeInRange(
range,
doc.createTextNode( url.slice( protocolEnd ) )
doc.createTextNode(url.replace(/^[^:]*:\/*/, ''))
);
}
attributes = mergeObjects(
@ -3737,12 +3633,9 @@ class Squire
}
toggleCode() {
if ( this.hasFormat( 'PRE' ) || this.hasFormat( 'CODE' ) ) {
this.removeCode();
} else {
this.code();
}
return this;
return (this.hasFormat('PRE') || this.hasFormat('CODE'))
? this.removeCode()
: this.code();
}
// ---