unvendor: Replace morphdom

e03e32d66a628fbe3565720f76eb5bbe0fced667

Cohee <18619528+Cohee1207@users.noreply.github.com>

6 files changed, +12 -792Ignore whitespace
package-lock.json+7 -0
@@ -47,6 +47,7 @@
4747 "lodash": "^4.17.21",
4848 "mime-types": "^2.1.35",
4949 "moment": "^2.30.1",
50+ "morphdom": "^2.7.4",
5051 "multer": "^1.4.5-lts.1",
5152 "node-fetch": "^3.3.2",
5253 "node-persist": "^4.0.1",
@@ -5784,6 +5785,12 @@
57845785 "node": "*"
57855786 }
57865787 },
5788+ "node_modules/morphdom": {
5789+ "version": "2.7.4",
5790+ "resolved": "https://registry.npmjs.org/morphdom/-/morphdom-2.7.4.tgz",
5791+ "integrity": "sha512-ATTbWMgGa+FaMU3FhnFYB6WgulCqwf6opOll4CBzmVDTLvPMmUPrEv8CudmLPK0MESa64+6B89fWOxP3+YIlxQ==",
5792+ "license": "MIT"
5793+ },
57875794 "node_modules/ms": {
57885795 "version": "2.0.0",
57895796 "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
package.json+1 -0
@@ -37,6 +37,7 @@
3737 "lodash": "^4.17.21",
3838 "mime-types": "^2.1.35",
3939 "moment": "^2.30.1",
40+ "morphdom": "^2.7.4",
4041 "multer": "^1.4.5-lts.1",
4142 "node-fetch": "^3.3.2",
4243 "node-persist": "^4.0.1",
public/lib.js+3 -0
@@ -20,6 +20,7 @@ import moment from 'moment';
2020import seedrandom from 'seedrandom';
2121import * as Popper from '@popperjs/core';
2222import droll from 'droll';
23+import morphdom from 'morphdom';
2324
2425/**
2526 * Expose the libraries to the 'window' object.
@@ -96,6 +97,7 @@ export default {
9697 seedrandom,
9798 Popper,
9899 droll,
100+ morphdom,
99101};
100102
101103export {
@@ -118,4 +120,5 @@ export {
118120 seedrandom,
119121 Popper,
120122 droll,
123+ morphdom,
121124};
public/scripts/extensions/quick-reply/lib/morphdom-esm.js+0 -769
@@ -1,769 +0,0 @@
1-var DOCUMENT_FRAGMENT_NODE = 11;
2-
3-function morphAttrs(fromNode, toNode) {
4- var toNodeAttrs = toNode.attributes;
5- var attr;
6- var attrName;
7- var attrNamespaceURI;
8- var attrValue;
9- var fromValue;
10-
11- // document-fragments dont have attributes so lets not do anything
12- if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE || fromNode.nodeType === DOCUMENT_FRAGMENT_NODE) {
13- return;
14- }
15-
16- // update attributes on original DOM element
17- for (var i = toNodeAttrs.length - 1; i >= 0; i--) {
18- attr = toNodeAttrs[i];
19- attrName = attr.name;
20- attrNamespaceURI = attr.namespaceURI;
21- attrValue = attr.value;
22-
23- if (attrNamespaceURI) {
24- attrName = attr.localName || attrName;
25- fromValue = fromNode.getAttributeNS(attrNamespaceURI, attrName);
26-
27- if (fromValue !== attrValue) {
28- if (attr.prefix === 'xmlns'){
29- attrName = attr.name; // It's not allowed to set an attribute with the XMLNS namespace without specifying the `xmlns` prefix
30- }
31- fromNode.setAttributeNS(attrNamespaceURI, attrName, attrValue);
32- }
33- } else {
34- fromValue = fromNode.getAttribute(attrName);
35-
36- if (fromValue !== attrValue) {
37- fromNode.setAttribute(attrName, attrValue);
38- }
39- }
40- }
41-
42- // Remove any extra attributes found on the original DOM element that
43- // weren't found on the target element.
44- var fromNodeAttrs = fromNode.attributes;
45-
46- for (var d = fromNodeAttrs.length - 1; d >= 0; d--) {
47- attr = fromNodeAttrs[d];
48- attrName = attr.name;
49- attrNamespaceURI = attr.namespaceURI;
50-
51- if (attrNamespaceURI) {
52- attrName = attr.localName || attrName;
53-
54- if (!toNode.hasAttributeNS(attrNamespaceURI, attrName)) {
55- fromNode.removeAttributeNS(attrNamespaceURI, attrName);
56- }
57- } else {
58- if (!toNode.hasAttribute(attrName)) {
59- fromNode.removeAttribute(attrName);
60- }
61- }
62- }
63-}
64-
65-var range; // Create a range object for efficently rendering strings to elements.
66-var NS_XHTML = 'http://www.w3.org/1999/xhtml';
67-
68-var doc = typeof document === 'undefined' ? undefined : document;
69-var HAS_TEMPLATE_SUPPORT = !!doc && 'content' in doc.createElement('template');
70-var HAS_RANGE_SUPPORT = !!doc && doc.createRange && 'createContextualFragment' in doc.createRange();
71-
72-function createFragmentFromTemplate(str) {
73- var template = doc.createElement('template');
74- template.innerHTML = str;
75- return template.content.childNodes[0];
76-}
77-
78-function createFragmentFromRange(str) {
79- if (!range) {
80- range = doc.createRange();
81- range.selectNode(doc.body);
82- }
83-
84- var fragment = range.createContextualFragment(str);
85- return fragment.childNodes[0];
86-}
87-
88-function createFragmentFromWrap(str) {
89- var fragment = doc.createElement('body');
90- fragment.innerHTML = str;
91- return fragment.childNodes[0];
92-}
93-
94-/**
95- * This is about the same
96- * var html = new DOMParser().parseFromString(str, 'text/html');
97- * return html.body.firstChild;
98- *
99- * @method toElement
100- * @param {String} str
101- */
102-function toElement(str) {
103- str = str.trim();
104- if (HAS_TEMPLATE_SUPPORT) {
105- // avoid restrictions on content for things like `<tr><th>Hi</th></tr>` which
106- // createContextualFragment doesn't support
107- // <template> support not available in IE
108- return createFragmentFromTemplate(str);
109- } else if (HAS_RANGE_SUPPORT) {
110- return createFragmentFromRange(str);
111- }
112-
113- return createFragmentFromWrap(str);
114-}
115-
116-/**
117- * Returns true if two node's names are the same.
118- *
119- * NOTE: We don't bother checking `namespaceURI` because you will never find two HTML elements with the same
120- * nodeName and different namespace URIs.
121- *
122- * @param {Element} a
123- * @param {Element} b The target element
124- * @return {boolean}
125- */
126-function compareNodeNames(fromEl, toEl) {
127- var fromNodeName = fromEl.nodeName;
128- var toNodeName = toEl.nodeName;
129- var fromCodeStart, toCodeStart;
130-
131- if (fromNodeName === toNodeName) {
132- return true;
133- }
134-
135- fromCodeStart = fromNodeName.charCodeAt(0);
136- toCodeStart = toNodeName.charCodeAt(0);
137-
138- // If the target element is a virtual DOM node or SVG node then we may
139- // need to normalize the tag name before comparing. Normal HTML elements that are
140- // in the "http://www.w3.org/1999/xhtml"
141- // are converted to upper case
142- if (fromCodeStart <= 90 && toCodeStart >= 97) { // from is upper and to is lower
143- return fromNodeName === toNodeName.toUpperCase();
144- } else if (toCodeStart <= 90 && fromCodeStart >= 97) { // to is upper and from is lower
145- return toNodeName === fromNodeName.toUpperCase();
146- } else {
147- return false;
148- }
149-}
150-
151-/**
152- * Create an element, optionally with a known namespace URI.
153- *
154- * @param {string} name the element name, e.g. 'div' or 'svg'
155- * @param {string} [namespaceURI] the element's namespace URI, i.e. the value of
156- * its `xmlns` attribute or its inferred namespace.
157- *
158- * @return {Element}
159- */
160-function createElementNS(name, namespaceURI) {
161- return !namespaceURI || namespaceURI === NS_XHTML ?
162- doc.createElement(name) :
163- doc.createElementNS(namespaceURI, name);
164-}
165-
166-/**
167- * Copies the children of one DOM element to another DOM element
168- */
169-function moveChildren(fromEl, toEl) {
170- var curChild = fromEl.firstChild;
171- while (curChild) {
172- var nextChild = curChild.nextSibling;
173- toEl.appendChild(curChild);
174- curChild = nextChild;
175- }
176- return toEl;
177-}
178-
179-function syncBooleanAttrProp(fromEl, toEl, name) {
180- if (fromEl[name] !== toEl[name]) {
181- fromEl[name] = toEl[name];
182- if (fromEl[name]) {
183- fromEl.setAttribute(name, '');
184- } else {
185- fromEl.removeAttribute(name);
186- }
187- }
188-}
189-
190-var specialElHandlers = {
191- OPTION: function(fromEl, toEl) {
192- var parentNode = fromEl.parentNode;
193- if (parentNode) {
194- var parentName = parentNode.nodeName.toUpperCase();
195- if (parentName === 'OPTGROUP') {
196- parentNode = parentNode.parentNode;
197- parentName = parentNode && parentNode.nodeName.toUpperCase();
198- }
199- if (parentName === 'SELECT' && !parentNode.hasAttribute('multiple')) {
200- if (fromEl.hasAttribute('selected') && !toEl.selected) {
201- // Workaround for MS Edge bug where the 'selected' attribute can only be
202- // removed if set to a non-empty value:
203- // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12087679/
204- fromEl.setAttribute('selected', 'selected');
205- fromEl.removeAttribute('selected');
206- }
207- // We have to reset select element's selectedIndex to -1, otherwise setting
208- // fromEl.selected using the syncBooleanAttrProp below has no effect.
209- // The correct selectedIndex will be set in the SELECT special handler below.
210- parentNode.selectedIndex = -1;
211- }
212- }
213- syncBooleanAttrProp(fromEl, toEl, 'selected');
214- },
215- /**
216- * The "value" attribute is special for the <input> element since it sets
217- * the initial value. Changing the "value" attribute without changing the
218- * "value" property will have no effect since it is only used to the set the
219- * initial value. Similar for the "checked" attribute, and "disabled".
220- */
221- INPUT: function(fromEl, toEl) {
222- syncBooleanAttrProp(fromEl, toEl, 'checked');
223- syncBooleanAttrProp(fromEl, toEl, 'disabled');
224-
225- if (fromEl.value !== toEl.value) {
226- fromEl.value = toEl.value;
227- }
228-
229- if (!toEl.hasAttribute('value')) {
230- fromEl.removeAttribute('value');
231- }
232- },
233-
234- TEXTAREA: function(fromEl, toEl) {
235- var newValue = toEl.value;
236- if (fromEl.value !== newValue) {
237- fromEl.value = newValue;
238- }
239-
240- var firstChild = fromEl.firstChild;
241- if (firstChild) {
242- // Needed for IE. Apparently IE sets the placeholder as the
243- // node value and vise versa. This ignores an empty update.
244- var oldValue = firstChild.nodeValue;
245-
246- if (oldValue == newValue || (!newValue && oldValue == fromEl.placeholder)) {
247- return;
248- }
249-
250- firstChild.nodeValue = newValue;
251- }
252- },
253- SELECT: function(fromEl, toEl) {
254- if (!toEl.hasAttribute('multiple')) {
255- var selectedIndex = -1;
256- var i = 0;
257- // We have to loop through children of fromEl, not toEl since nodes can be moved
258- // from toEl to fromEl directly when morphing.
259- // At the time this special handler is invoked, all children have already been morphed
260- // and appended to / removed from fromEl, so using fromEl here is safe and correct.
261- var curChild = fromEl.firstChild;
262- var optgroup;
263- var nodeName;
264- while(curChild) {
265- nodeName = curChild.nodeName && curChild.nodeName.toUpperCase();
266- if (nodeName === 'OPTGROUP') {
267- optgroup = curChild;
268- curChild = optgroup.firstChild;
269- } else {
270- if (nodeName === 'OPTION') {
271- if (curChild.hasAttribute('selected')) {
272- selectedIndex = i;
273- break;
274- }
275- i++;
276- }
277- curChild = curChild.nextSibling;
278- if (!curChild && optgroup) {
279- curChild = optgroup.nextSibling;
280- optgroup = null;
281- }
282- }
283- }
284-
285- fromEl.selectedIndex = selectedIndex;
286- }
287- }
288-};
289-
290-var ELEMENT_NODE = 1;
291-var DOCUMENT_FRAGMENT_NODE$1 = 11;
292-var TEXT_NODE = 3;
293-var COMMENT_NODE = 8;
294-
295-function noop() {}
296-
297-function defaultGetNodeKey(node) {
298- if (node) {
299- return (node.getAttribute && node.getAttribute('id')) || node.id;
300- }
301-}
302-
303-function morphdomFactory(morphAttrs) {
304-
305- return function morphdom(fromNode, toNode, options) {
306- if (!options) {
307- options = {};
308- }
309-
310- if (typeof toNode === 'string') {
311- if (fromNode.nodeName === '#document' || fromNode.nodeName === 'HTML' || fromNode.nodeName === 'BODY') {
312- var toNodeHtml = toNode;
313- toNode = doc.createElement('html');
314- toNode.innerHTML = toNodeHtml;
315- } else {
316- toNode = toElement(toNode);
317- }
318- } else if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE$1) {
319- toNode = toNode.firstElementChild;
320- }
321-
322- var getNodeKey = options.getNodeKey || defaultGetNodeKey;
323- var onBeforeNodeAdded = options.onBeforeNodeAdded || noop;
324- var onNodeAdded = options.onNodeAdded || noop;
325- var onBeforeElUpdated = options.onBeforeElUpdated || noop;
326- var onElUpdated = options.onElUpdated || noop;
327- var onBeforeNodeDiscarded = options.onBeforeNodeDiscarded || noop;
328- var onNodeDiscarded = options.onNodeDiscarded || noop;
329- var onBeforeElChildrenUpdated = options.onBeforeElChildrenUpdated || noop;
330- var skipFromChildren = options.skipFromChildren || noop;
331- var addChild = options.addChild || function(parent, child){ return parent.appendChild(child); };
332- var childrenOnly = options.childrenOnly === true;
333-
334- // This object is used as a lookup to quickly find all keyed elements in the original DOM tree.
335- var fromNodesLookup = Object.create(null);
336- var keyedRemovalList = [];
337-
338- function addKeyedRemoval(key) {
339- keyedRemovalList.push(key);
340- }
341-
342- function walkDiscardedChildNodes(node, skipKeyedNodes) {
343- if (node.nodeType === ELEMENT_NODE) {
344- var curChild = node.firstChild;
345- while (curChild) {
346-
347- var key = undefined;
348-
349- if (skipKeyedNodes && (key = getNodeKey(curChild))) {
350- // If we are skipping keyed nodes then we add the key
351- // to a list so that it can be handled at the very end.
352- addKeyedRemoval(key);
353- } else {
354- // Only report the node as discarded if it is not keyed. We do this because
355- // at the end we loop through all keyed elements that were unmatched
356- // and then discard them in one final pass.
357- onNodeDiscarded(curChild);
358- if (curChild.firstChild) {
359- walkDiscardedChildNodes(curChild, skipKeyedNodes);
360- }
361- }
362-
363- curChild = curChild.nextSibling;
364- }
365- }
366- }
367-
368- /**
369- * Removes a DOM node out of the original DOM
370- *
371- * @param {Node} node The node to remove
372- * @param {Node} parentNode The nodes parent
373- * @param {Boolean} skipKeyedNodes If true then elements with keys will be skipped and not discarded.
374- * @return {undefined}
375- */
376- function removeNode(node, parentNode, skipKeyedNodes) {
377- if (onBeforeNodeDiscarded(node) === false) {
378- return;
379- }
380-
381- if (parentNode) {
382- parentNode.removeChild(node);
383- }
384-
385- onNodeDiscarded(node);
386- walkDiscardedChildNodes(node, skipKeyedNodes);
387- }
388-
389- // // TreeWalker implementation is no faster, but keeping this around in case this changes in the future
390- // function indexTree(root) {
391- // var treeWalker = document.createTreeWalker(
392- // root,
393- // NodeFilter.SHOW_ELEMENT);
394- //
395- // var el;
396- // while((el = treeWalker.nextNode())) {
397- // var key = getNodeKey(el);
398- // if (key) {
399- // fromNodesLookup[key] = el;
400- // }
401- // }
402- // }
403-
404- // // NodeIterator implementation is no faster, but keeping this around in case this changes in the future
405- //
406- // function indexTree(node) {
407- // var nodeIterator = document.createNodeIterator(node, NodeFilter.SHOW_ELEMENT);
408- // var el;
409- // while((el = nodeIterator.nextNode())) {
410- // var key = getNodeKey(el);
411- // if (key) {
412- // fromNodesLookup[key] = el;
413- // }
414- // }
415- // }
416-
417- function indexTree(node) {
418- if (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE$1) {
419- var curChild = node.firstChild;
420- while (curChild) {
421- var key = getNodeKey(curChild);
422- if (key) {
423- fromNodesLookup[key] = curChild;
424- }
425-
426- // Walk recursively
427- indexTree(curChild);
428-
429- curChild = curChild.nextSibling;
430- }
431- }
432- }
433-
434- indexTree(fromNode);
435-
436- function handleNodeAdded(el) {
437- onNodeAdded(el);
438-
439- var curChild = el.firstChild;
440- while (curChild) {
441- var nextSibling = curChild.nextSibling;
442-
443- var key = getNodeKey(curChild);
444- if (key) {
445- var unmatchedFromEl = fromNodesLookup[key];
446- // if we find a duplicate #id node in cache, replace `el` with cache value
447- // and morph it to the child node.
448- if (unmatchedFromEl && compareNodeNames(curChild, unmatchedFromEl)) {
449- curChild.parentNode.replaceChild(unmatchedFromEl, curChild);
450- morphEl(unmatchedFromEl, curChild);
451- } else {
452- handleNodeAdded(curChild);
453- }
454- } else {
455- // recursively call for curChild and it's children to see if we find something in
456- // fromNodesLookup
457- handleNodeAdded(curChild);
458- }
459-
460- curChild = nextSibling;
461- }
462- }
463-
464- function cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey) {
465- // We have processed all of the "to nodes". If curFromNodeChild is
466- // non-null then we still have some from nodes left over that need
467- // to be removed
468- while (curFromNodeChild) {
469- var fromNextSibling = curFromNodeChild.nextSibling;
470- if ((curFromNodeKey = getNodeKey(curFromNodeChild))) {
471- // Since the node is keyed it might be matched up later so we defer
472- // the actual removal to later
473- addKeyedRemoval(curFromNodeKey);
474- } else {
475- // NOTE: we skip nested keyed nodes from being removed since there is
476- // still a chance they will be matched up later
477- removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);
478- }
479- curFromNodeChild = fromNextSibling;
480- }
481- }
482-
483- function morphEl(fromEl, toEl, childrenOnly) {
484- var toElKey = getNodeKey(toEl);
485-
486- if (toElKey) {
487- // If an element with an ID is being morphed then it will be in the final
488- // DOM so clear it out of the saved elements collection
489- delete fromNodesLookup[toElKey];
490- }
491-
492- if (!childrenOnly) {
493- // optional
494- var beforeUpdateResult = onBeforeElUpdated(fromEl, toEl);
495- if (beforeUpdateResult === false) {
496- return;
497- } else if (beforeUpdateResult instanceof HTMLElement) {
498- fromEl = beforeUpdateResult;
499- // reindex the new fromEl in case it's not in the same
500- // tree as the original fromEl
501- // (Phoenix LiveView sometimes returns a cloned tree,
502- // but keyed lookups would still point to the original tree)
503- indexTree(fromEl);
504- }
505-
506- // update attributes on original DOM element first
507- morphAttrs(fromEl, toEl);
508- // optional
509- onElUpdated(fromEl);
510-
511- if (onBeforeElChildrenUpdated(fromEl, toEl) === false) {
512- return;
513- }
514- }
515-
516- if (fromEl.nodeName !== 'TEXTAREA') {
517- morphChildren(fromEl, toEl);
518- } else {
519- specialElHandlers.TEXTAREA(fromEl, toEl);
520- }
521- }
522-
523- function morphChildren(fromEl, toEl) {
524- var skipFrom = skipFromChildren(fromEl, toEl);
525- var curToNodeChild = toEl.firstChild;
526- var curFromNodeChild = fromEl.firstChild;
527- var curToNodeKey;
528- var curFromNodeKey;
529-
530- var fromNextSibling;
531- var toNextSibling;
532- var matchingFromEl;
533-
534- // walk the children
535- outer: while (curToNodeChild) {
536- toNextSibling = curToNodeChild.nextSibling;
537- curToNodeKey = getNodeKey(curToNodeChild);
538-
539- // walk the fromNode children all the way through
540- while (!skipFrom && curFromNodeChild) {
541- fromNextSibling = curFromNodeChild.nextSibling;
542-
543- if (curToNodeChild.isSameNode && curToNodeChild.isSameNode(curFromNodeChild)) {
544- curToNodeChild = toNextSibling;
545- curFromNodeChild = fromNextSibling;
546- continue outer;
547- }
548-
549- curFromNodeKey = getNodeKey(curFromNodeChild);
550-
551- var curFromNodeType = curFromNodeChild.nodeType;
552-
553- // this means if the curFromNodeChild doesnt have a match with the curToNodeChild
554- var isCompatible = undefined;
555-
556- if (curFromNodeType === curToNodeChild.nodeType) {
557- if (curFromNodeType === ELEMENT_NODE) {
558- // Both nodes being compared are Element nodes
559-
560- if (curToNodeKey) {
561- // The target node has a key so we want to match it up with the correct element
562- // in the original DOM tree
563- if (curToNodeKey !== curFromNodeKey) {
564- // The current element in the original DOM tree does not have a matching key so
565- // let's check our lookup to see if there is a matching element in the original
566- // DOM tree
567- if ((matchingFromEl = fromNodesLookup[curToNodeKey])) {
568- if (fromNextSibling === matchingFromEl) {
569- // Special case for single element removals. To avoid removing the original
570- // DOM node out of the tree (since that can break CSS transitions, etc.),
571- // we will instead discard the current node and wait until the next
572- // iteration to properly match up the keyed target element with its matching
573- // element in the original tree
574- isCompatible = false;
575- } else {
576- // We found a matching keyed element somewhere in the original DOM tree.
577- // Let's move the original DOM node into the current position and morph
578- // it.
579-
580- // NOTE: We use insertBefore instead of replaceChild because we want to go through
581- // the `removeNode()` function for the node that is being discarded so that
582- // all lifecycle hooks are correctly invoked
583- fromEl.insertBefore(matchingFromEl, curFromNodeChild);
584-
585- // fromNextSibling = curFromNodeChild.nextSibling;
586-
587- if (curFromNodeKey) {
588- // Since the node is keyed it might be matched up later so we defer
589- // the actual removal to later
590- addKeyedRemoval(curFromNodeKey);
591- } else {
592- // NOTE: we skip nested keyed nodes from being removed since there is
593- // still a chance they will be matched up later
594- removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);
595- }
596-
597- curFromNodeChild = matchingFromEl;
598- curFromNodeKey = getNodeKey(curFromNodeChild);
599- }
600- } else {
601- // The nodes are not compatible since the "to" node has a key and there
602- // is no matching keyed node in the source tree
603- isCompatible = false;
604- }
605- }
606- } else if (curFromNodeKey) {
607- // The original has a key
608- isCompatible = false;
609- }
610-
611- isCompatible = isCompatible !== false && compareNodeNames(curFromNodeChild, curToNodeChild);
612- if (isCompatible) {
613- // We found compatible DOM elements so transform
614- // the current "from" node to match the current
615- // target DOM node.
616- // MORPH
617- morphEl(curFromNodeChild, curToNodeChild);
618- }
619-
620- } else if (curFromNodeType === TEXT_NODE || curFromNodeType == COMMENT_NODE) {
621- // Both nodes being compared are Text or Comment nodes
622- isCompatible = true;
623- // Simply update nodeValue on the original node to
624- // change the text value
625- if (curFromNodeChild.nodeValue !== curToNodeChild.nodeValue) {
626- curFromNodeChild.nodeValue = curToNodeChild.nodeValue;
627- }
628-
629- }
630- }
631-
632- if (isCompatible) {
633- // Advance both the "to" child and the "from" child since we found a match
634- // Nothing else to do as we already recursively called morphChildren above
635- curToNodeChild = toNextSibling;
636- curFromNodeChild = fromNextSibling;
637- continue outer;
638- }
639-
640- // No compatible match so remove the old node from the DOM and continue trying to find a
641- // match in the original DOM. However, we only do this if the from node is not keyed
642- // since it is possible that a keyed node might match up with a node somewhere else in the
643- // target tree and we don't want to discard it just yet since it still might find a
644- // home in the final DOM tree. After everything is done we will remove any keyed nodes
645- // that didn't find a home
646- if (curFromNodeKey) {
647- // Since the node is keyed it might be matched up later so we defer
648- // the actual removal to later
649- addKeyedRemoval(curFromNodeKey);
650- } else {
651- // NOTE: we skip nested keyed nodes from being removed since there is
652- // still a chance they will be matched up later
653- removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);
654- }
655-
656- curFromNodeChild = fromNextSibling;
657- } // END: while(curFromNodeChild) {}
658-
659- // If we got this far then we did not find a candidate match for
660- // our "to node" and we exhausted all of the children "from"
661- // nodes. Therefore, we will just append the current "to" node
662- // to the end
663- if (curToNodeKey && (matchingFromEl = fromNodesLookup[curToNodeKey]) && compareNodeNames(matchingFromEl, curToNodeChild)) {
664- // MORPH
665- if(!skipFrom){ addChild(fromEl, matchingFromEl); }
666- morphEl(matchingFromEl, curToNodeChild);
667- } else {
668- var onBeforeNodeAddedResult = onBeforeNodeAdded(curToNodeChild);
669- if (onBeforeNodeAddedResult !== false) {
670- if (onBeforeNodeAddedResult) {
671- curToNodeChild = onBeforeNodeAddedResult;
672- }
673-
674- if (curToNodeChild.actualize) {
675- curToNodeChild = curToNodeChild.actualize(fromEl.ownerDocument || doc);
676- }
677- addChild(fromEl, curToNodeChild);
678- handleNodeAdded(curToNodeChild);
679- }
680- }
681-
682- curToNodeChild = toNextSibling;
683- curFromNodeChild = fromNextSibling;
684- }
685-
686- cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey);
687-
688- var specialElHandler = specialElHandlers[fromEl.nodeName];
689- if (specialElHandler) {
690- specialElHandler(fromEl, toEl);
691- }
692- } // END: morphChildren(...)
693-
694- var morphedNode = fromNode;
695- var morphedNodeType = morphedNode.nodeType;
696- var toNodeType = toNode.nodeType;
697-
698- if (!childrenOnly) {
699- // Handle the case where we are given two DOM nodes that are not
700- // compatible (e.g. <div> --> <span> or <div> --> TEXT)
701- if (morphedNodeType === ELEMENT_NODE) {
702- if (toNodeType === ELEMENT_NODE) {
703- if (!compareNodeNames(fromNode, toNode)) {
704- onNodeDiscarded(fromNode);
705- morphedNode = moveChildren(fromNode, createElementNS(toNode.nodeName, toNode.namespaceURI));
706- }
707- } else {
708- // Going from an element node to a text node
709- morphedNode = toNode;
710- }
711- } else if (morphedNodeType === TEXT_NODE || morphedNodeType === COMMENT_NODE) { // Text or comment node
712- if (toNodeType === morphedNodeType) {
713- if (morphedNode.nodeValue !== toNode.nodeValue) {
714- morphedNode.nodeValue = toNode.nodeValue;
715- }
716-
717- return morphedNode;
718- } else {
719- // Text node to something else
720- morphedNode = toNode;
721- }
722- }
723- }
724-
725- if (morphedNode === toNode) {
726- // The "to node" was not compatible with the "from node" so we had to
727- // toss out the "from node" and use the "to node"
728- onNodeDiscarded(fromNode);
729- } else {
730- if (toNode.isSameNode && toNode.isSameNode(morphedNode)) {
731- return;
732- }
733-
734- morphEl(morphedNode, toNode, childrenOnly);
735-
736- // We now need to loop over any keyed nodes that might need to be
737- // removed. We only do the removal if we know that the keyed node
738- // never found a match. When a keyed node is matched up we remove
739- // it out of fromNodesLookup and we use fromNodesLookup to determine
740- // if a keyed node has been matched up or not
741- if (keyedRemovalList) {
742- for (var i=0, len=keyedRemovalList.length; i<len; i++) {
743- var elToRemove = fromNodesLookup[keyedRemovalList[i]];
744- if (elToRemove) {
745- removeNode(elToRemove, elToRemove.parentNode, false);
746- }
747- }
748- }
749- }
750-
751- if (!childrenOnly && morphedNode !== fromNode && fromNode.parentNode) {
752- if (morphedNode.actualize) {
753- morphedNode = morphedNode.actualize(fromNode.ownerDocument || doc);
754- }
755- // If we had to swap out the from node with a new node because the old
756- // node was not compatible with the target node then we need to
757- // replace the old DOM node in the original DOM tree. This is only
758- // possible if the original DOM node was part of a DOM tree which
759- // we know is the case if it has a parent node.
760- fromNode.parentNode.replaceChild(morphedNode, fromNode);
761- }
762-
763- return morphedNode;
764- };
765-}
766-
767-var morphdom = morphdomFactory(morphAttrs);
768-
769-export default morphdom;
public/scripts/extensions/quick-reply/lib/morphdom.LICENSE.txt+0 -21
@@ -1,21 +0,0 @@
1-The MIT License (MIT)
2-
3-Copyright (c) Patrick Steele-Idem <pnidem@gmail.com> (psteeleidem.com)
4-
5-Permission is hereby granted, free of charge, to any person obtaining a copy
6-of this software and associated documentation files (the "Software"), to deal
7-in the Software without restriction, including without limitation the rights
8-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9-copies of the Software, and to permit persons to whom the Software is
10-furnished to do so, subject to the following conditions:
11-
12-The above copyright notice and this permission notice shall be included in
13-all copies or substantial portions of the Software.
14-
15-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21-THE SOFTWARE.
21 \ No newline at end of file
public/scripts/extensions/quick-reply/src/QuickReply.js+1 -2
@@ -1,4 +1,4 @@
11import { hljs, morphdom } from '../../../../lib.js';
22import { POPUP_RESULT, POPUP_TYPE, Popup } from '../../../popup.js';
33import { setSlashCommandAutoComplete } from '../../../slash-commands.js';
44import { SlashCommandAbortController } from '../../../slash-commands/SlashCommandAbortController.js';
@@ -12,7 +12,6 @@ import { SlashCommandParserError } from '../../../slash-commands/SlashCommandPar
1212import { SlashCommandScope } from '../../../slash-commands/SlashCommandScope.js';
1313import { debounce, delay, getSortableDelay, showFontAwesomePicker } from '../../../utils.js';
1414import { log, quickReplyApi, warn } from '../index.js';
15-import morphdom from '../lib/morphdom-esm.js';
1615import { QuickReplyContextLink } from './QuickReplyContextLink.js';
1716import { QuickReplySet } from './QuickReplySet.js';
1817import { ContextMenu } from './ui/ctx/ContextMenu.js';