mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-10-24 22:25:09 +03:00
Compare commits
5 commits
8667af700d
...
aad651f2a1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aad651f2a1 | ||
|
|
67a68915db | ||
|
|
71287022ca | ||
|
|
3da27c3bc8 | ||
|
|
020927cc56 |
6 changed files with 271 additions and 92 deletions
|
|
@ -58,10 +58,9 @@ const
|
|||
*/
|
||||
publicKeysItem = 'openpgp-public-keys',
|
||||
privateKeysItem = 'openpgp-private-keys',
|
||||
storage = window.localStorage,
|
||||
loadOpenPgpKeys = async itemname => {
|
||||
let keys = [], key,
|
||||
armoredKeys = JSON.parse(storage.getItem(itemname)),
|
||||
armoredKeys = JSON.parse(localStorage.getItem(itemname)),
|
||||
i = arrayLength(armoredKeys);
|
||||
while (i--) try {
|
||||
key = await openpgp.readKey({armoredKey:armoredKeys[i]});
|
||||
|
|
@ -74,9 +73,9 @@ const
|
|||
storeOpenPgpKeys = (keys, section) => {
|
||||
let armoredKeys = keys.map(item => item.armor);
|
||||
if (armoredKeys.length) {
|
||||
storage.setItem(section, JSON.stringify(armoredKeys));
|
||||
localStorage.setItem(section, JSON.stringify(armoredKeys));
|
||||
} else {
|
||||
storage.removeItem(section);
|
||||
localStorage.removeItem(section);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#V-PopupsLanguages {
|
||||
|
||||
max-width: 710px;
|
||||
max-width: 720px;
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
|
|
|
|||
|
|
@ -1624,11 +1624,11 @@ ko.bindingProvider = new class
|
|||
// Deprecated: with is no longer recommended
|
||||
var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString),
|
||||
functionBody = "with($data){return{" + rewrittenBindings + "}}";
|
||||
bindingFunction = new Function("$context", "$root", "$parent", "$data", "$element", functionBody);
|
||||
bindingFunction = new Function("$context", "$root", "$parent", "$data", functionBody);
|
||||
bindingCache.set(cacheKey, bindingFunction);
|
||||
}
|
||||
return bindingFunction(bindingContext,
|
||||
bindingContext["$root"], bindingContext["$parent"], bindingContext["$data"] || {}, node
|
||||
bindingContext["$root"], bindingContext["$parent"], bindingContext["$data"] || {}
|
||||
);
|
||||
*/
|
||||
if (!bindingFunction) {
|
||||
|
|
@ -1643,7 +1643,8 @@ ko.bindingProvider = new class
|
|||
bindingContext,
|
||||
{
|
||||
has: () => true,
|
||||
get: (target, key) => target[key] || target['$data'][key]
|
||||
// get: (target, key) => target['$data'][key] || target[key]
|
||||
get: (target, key) => Reflect.has(target['$data'], key) ? target['$data'][key] : target[key]
|
||||
}
|
||||
);
|
||||
return bindingFunction(bindingContext);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ b),a.__ko__hasDomDataOptionValue__=!0,a.value="number"===typeof b?b:"");break;ca
|
|||
1),m=e.match(a),k=-1,l="/"):40===p||123===p||91===p?++h:41===p||125===p||93===p?--h:n||f.length||34!==p&&39!==p||(l=l.slice(1,-1));f.push(l)}if(0<h)throw Error("Unbalanced parentheses, braces, or brackets");}g.push("'$data':()=>$data");return g.join(",")},dc:(e,g)=>-1<e.findIndex(m=>m.key==g),Ha:(e,g,m,f,h,k)=>{g&&c.V(g)?!c.wb(g)||k&&g.L()===h||g(h):(console.log(`"${f}" should contain observable in ${e.outerHTML.replace(/>.+/,">")}`),m.get("$data")[f]=h)}}})();(()=>{function a(f){return 8==f.nodeType&&
|
||||
e.test(f.nodeValue)}function b(f){return 8==f.nodeType&&g.test(f.nodeValue)}function d(f,h){for(var k=f,l=1,p=[];k=k.nextSibling;){if(b(k)&&(c.g.l.set(k,m,!0),!--l))return p;p.push(k);a(k)&&++l}if(!h)throw Error("Cannot find closing comment tag to match: "+f.nodeValue);return null}var e=/^\s*ko(?:\s+([\s\S]+))?\s*$/,g=/^\s*\/ko\s*$/,m="__ko_matchedEndComment__";c.s={aa:{},childNodes:f=>a(f)?d(f):f.childNodes,ka:f=>{a(f)?(f=d(f))&&[...f].forEach(h=>c.removeNode(h)):c.g.Ra(f)},qa:(f,h)=>{a(f)?(c.s.ka(f),
|
||||
f.after(...h)):c.g.qa(f,h)},Vb:(f,h,k)=>{k?k.after(h):a(f)?f.nextSibling.before(h):f.prepend(h)},firstChild:f=>{if(a(f))return f=f.nextSibling,!f||b(f)?null:f;let h=f.firstChild;if(h&&b(h))throw Error("Found invalid end comment, as the first child of "+f);return h},nextSibling:f=>{if(a(f)){var h=d(f,void 0);f=h?(h.length?h[h.length-1]:f).nextSibling:null}if((h=f.nextSibling)&&b(h)){if(b(h)&&!c.g.l.get(h,m))throw Error("Found end comment without a matching opening comment, as child of "+f);return null}return h},
|
||||
Rb:a,bc:f=>(f=f.nodeValue.match(e))?f[1]:null}})();const S=new Map,la=a=>{switch(a.nodeType){case 1:return a.getAttribute("data-bind");case 8:return c.s.bc(a)}return null};c.pb=new class{Yb(a){switch(a.nodeType){case 1:return null!=a.getAttribute("data-bind");case 8:return c.s.Rb(a)}return!1}Pb(a,b){if(a=la(a))try{let d=S.get(a);d||(d=new Function("$context","with($context){return{"+c.ma.Zb(a)+"}}"),S.set(a,d));b=new Proxy(b,{has:()=>!0,get:(e,g)=>e[g]||e.$data[g]});return d(b)}catch(d){throw d.message=
|
||||
Rb:a,bc:f=>(f=f.nodeValue.match(e))?f[1]:null}})();const S=new Map,la=a=>{switch(a.nodeType){case 1:return a.getAttribute("data-bind");case 8:return c.s.bc(a)}return null};c.pb=new class{Yb(a){switch(a.nodeType){case 1:return null!=a.getAttribute("data-bind");case 8:return c.s.Rb(a)}return!1}Pb(a,b){if(a=la(a))try{let d=S.get(a);d||(d=new Function("$context","with($context){return{"+c.ma.Zb(a)+"}}"),S.set(a,d));b=new Proxy(b,{has:()=>!0,get:(e,g)=>Reflect.has(e.$data,g)?e.$data[g]:e[g]});return d(b)}catch(d){throw d.message=
|
||||
"Unable to parse bindings.\nBindings value: "+a+"\nMessage: "+d.message,d;}return null}};const G=Symbol("_subscribable"),H=Symbol("_ancestorBindingInfo"),T=Symbol("_dataDependency"),U={},I=c.g.l.Z();c.i={};c.ba=class{constructor(a,b,d,e){var g=this,m=a===U,f=m?void 0:a,h="function"==typeof f&&!c.V(f),k=e?.dataDependency;a=()=>{var p=h?f():f;p=c.g.h(p);b?(c.g.extend(g,b),H in b&&(g[H]=b[H])):g.$root=p;g[G]=l;m?p=g.$data:g.$data=p;d?.(g,b,p);if(b?.[G]&&!c.u.m().Ta(b[G]))b[G]();k&&(g[T]=k);return g.$data};
|
||||
if(e?.exportDependencies)a();else{var l=c.yb(a);l.L();l.isActive()?l.la=null:g[G]=void 0}}createChildContext(a,b){return new c.ba(a,this,(d,e)=>{d.$parent=e.$data;b.extend?.(d)},b)}extend(a,b){return new c.ba(U,this,d=>c.g.extend(d,"function"==typeof a?a(d):a),b)}};const V=a=>{a=c.g.l.get(a,I);var b=a?.D;b&&(a.D=null,b.xb())};class ma{constructor(a,b,d){this.H=a;this.da=b;this.ua=new Set;this.F=!1;b.D||c.g.N.ha(a,V);d?.D&&(d.D.ua.add(a),this.Aa=d)}xb(){this.Aa?.D?.Nb(this.H)}Nb(a){this.ua.delete(a);
|
||||
this.ua.size||this.sb?.()}sb(){this.F=!0;this.da.D&&!this.ua.size&&(this.da.D=null,c.g.N.Za(this.H,V),c.j.notify(this.H,c.j.ca),this.xb())}}c.j={F:"childrenComplete",ca:"descendantsComplete",subscribe:(a,b,d,e,g)=>{var m=c.g.l.Sa(a,I,{});m.xa||(m.xa=new c.P);g?.notifyImmediately&&m.Wa[b]&&c.u.I(d,e,[a]);return m.xa.subscribe(d,e,b)},notify:(a,b)=>{var d=c.g.l.get(a,I);if(d&&(d.Wa[b]=!0,d.xa?.B(a,b),b==c.j.F))if(d.D)d.D.sb();else if(void 0===d.D&&d.xa?.oa(c.j.ca))throw Error("descendantsComplete event not supported for bindings on this node");
|
||||
|
|
|
|||
|
|
@ -39,11 +39,11 @@ ko.bindingProvider = new class
|
|||
// Deprecated: with is no longer recommended
|
||||
var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString),
|
||||
functionBody = "with($data){return{" + rewrittenBindings + "}}";
|
||||
bindingFunction = new Function("$context", "$root", "$parent", "$data", "$element", functionBody);
|
||||
bindingFunction = new Function("$context", "$root", "$parent", "$data", functionBody);
|
||||
bindingCache.set(cacheKey, bindingFunction);
|
||||
}
|
||||
return bindingFunction(bindingContext,
|
||||
bindingContext["$root"], bindingContext["$parent"], bindingContext["$data"] || {}, node
|
||||
bindingContext["$root"], bindingContext["$parent"], bindingContext["$data"] || {}
|
||||
);
|
||||
*/
|
||||
if (!bindingFunction) {
|
||||
|
|
@ -58,7 +58,8 @@ ko.bindingProvider = new class
|
|||
bindingContext,
|
||||
{
|
||||
has: () => true,
|
||||
get: (target, key) => target[key] || target['$data'][key]
|
||||
// get: (target, key) => target['$data'][key] || target[key]
|
||||
get: (target, key) => Reflect.has(target['$data'], key) ? target['$data'][key] : target[key]
|
||||
}
|
||||
);
|
||||
return bindingFunction(bindingContext);
|
||||
|
|
|
|||
338
vendors/squire2/dist/squire-raw.js
vendored
338
vendors/squire2/dist/squire-raw.js
vendored
|
|
@ -45,6 +45,7 @@
|
|||
// source/Constants.ts
|
||||
var ELEMENT_NODE = 1;
|
||||
var TEXT_NODE = 3;
|
||||
var COMMENT_NODE = 8;
|
||||
var DOCUMENT_FRAGMENT_NODE = 11;
|
||||
var ZWS = "\u200B";
|
||||
var ua = navigator.userAgent;
|
||||
|
|
@ -55,7 +56,7 @@
|
|||
var isWebKit = /WebKit\//.test(ua);
|
||||
var ctrlKey = isMac || isIOS ? "Meta-" : "Ctrl-";
|
||||
var cantFocusEmptyTextNodes = isWebKit;
|
||||
var notWS = /[^ \t\r\n]/;
|
||||
var notWS = /[^ \t\r\n\u200B]/;
|
||||
|
||||
// source/node/Category.ts
|
||||
var inlineNodeNames = /^(?:#text|A(?:BBR|CRONYM)?|B(?:R|D[IO])?|C(?:ITE|ODE)|D(?:ATA|EL|FN)|EM|FONT|HR|I(?:MG|NS)?|KBD|Q|R(?:P|T|UBY)|S(?:AMP|MALL|PAN|TR(?:IKE|ONG)|U[BP])?|TIME|U|VAR|WBR)$/;
|
||||
|
|
@ -71,6 +72,7 @@
|
|||
var isLeaf = (node) => leafNodeNames.has(node.nodeName);
|
||||
var getNodeCategory = (node) => {
|
||||
switch (node.nodeType) {
|
||||
case COMMENT_NODE:
|
||||
case TEXT_NODE:
|
||||
return INLINE;
|
||||
case ELEMENT_NODE:
|
||||
|
|
@ -252,11 +254,12 @@
|
|||
return nodeStartAfterStart && nodeEndBeforeEnd;
|
||||
}
|
||||
};
|
||||
var canDescendInto = (node) => node instanceof Text || node.nodeType === ELEMENT_NODE && !isLeaf(node);
|
||||
var moveRangeBoundariesDownTree = (range) => {
|
||||
let { startContainer, startOffset, endContainer, endOffset } = range;
|
||||
while (!(startContainer instanceof Text)) {
|
||||
let child = startContainer.childNodes[startOffset];
|
||||
if (!child || isLeaf(child)) {
|
||||
if (!child || !canDescendInto(child)) {
|
||||
if (startOffset) {
|
||||
child = startContainer.childNodes[startOffset - 1];
|
||||
if (child instanceof Text) {
|
||||
|
|
@ -278,7 +281,7 @@
|
|||
if (endOffset) {
|
||||
while (!(endContainer instanceof Text)) {
|
||||
const child = endContainer.childNodes[endOffset - 1];
|
||||
if (!child || isLeaf(child)) {
|
||||
if (!child || !canDescendInto(child)) {
|
||||
if (child && child.nodeName === "BR" && !isLineBreak(child)) {
|
||||
--endOffset;
|
||||
continue;
|
||||
|
|
@ -291,7 +294,7 @@
|
|||
} else {
|
||||
while (!(endContainer instanceof Text)) {
|
||||
const child = endContainer.firstChild;
|
||||
if (!child || isLeaf(child)) {
|
||||
if (!child || !canDescendInto(child)) {
|
||||
break;
|
||||
}
|
||||
endContainer = child;
|
||||
|
|
@ -368,7 +371,7 @@
|
|||
replace(classNames, family) {
|
||||
return createElement("SPAN", {
|
||||
class: classNames.fontFamily,
|
||||
style: "font-family:" + family
|
||||
style: { fontFamily: family }
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
@ -377,7 +380,7 @@
|
|||
replace(classNames, size) {
|
||||
return createElement("SPAN", {
|
||||
class: classNames.fontSize,
|
||||
style: "font-size:" + size
|
||||
style: { fontSize: size }
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
@ -557,6 +560,9 @@
|
|||
};
|
||||
var fixContainer = (container) => {
|
||||
let wrapper = null;
|
||||
if (/^(?:TABLE|TBODY|TR|TH|TD|P)/.test(container.nodeName)) {
|
||||
return container;
|
||||
}
|
||||
[...container.childNodes].forEach((child) => {
|
||||
if (isInline(child)) {
|
||||
wrapper || (wrapper = createElement("DIV"));
|
||||
|
|
@ -566,10 +572,13 @@
|
|||
wrapper = null;
|
||||
}
|
||||
});
|
||||
wrapper && container.append(wrapper);
|
||||
wrapper && container.append(fixCursor(wrapper));
|
||||
return container;
|
||||
};
|
||||
var split = (node, offset, stopNode, root) => {
|
||||
if (!stopNode.contains(node)) {
|
||||
throw new Error("split: stopNode does not contain node");
|
||||
}
|
||||
if (node instanceof Text && node !== stopNode) {
|
||||
if (typeof offset !== "number") {
|
||||
throw new Error("Offset must be a number to split text node!");
|
||||
|
|
@ -1020,7 +1029,7 @@
|
|||
}
|
||||
moveRangeBoundariesDownTree(range);
|
||||
range.collapse(false);
|
||||
const stopPoint = getClosest(range.endContainer, root, "BLOCKQUOTE") || root;
|
||||
let stopPoint = getClosest(range.endContainer, root, "BLOCKQUOTE") || root;
|
||||
let block = getStartBlockOfRange(range, root);
|
||||
let blockContentsAfterSplit = null;
|
||||
const firstBlockInFrag = getNextBlock(frag, frag);
|
||||
|
|
@ -1054,11 +1063,15 @@
|
|||
}
|
||||
}
|
||||
mergeWithBlock(container, firstBlockInFrag, range, root);
|
||||
offset = Array.from(container.parentNode.childNodes).indexOf(
|
||||
container
|
||||
) + 1;
|
||||
container = container.parentNode;
|
||||
range.setEnd(container, offset);
|
||||
if (container === root) {
|
||||
range.setEnd(root, getLength(root));
|
||||
} else {
|
||||
offset = Array.from(container.parentNode.childNodes).indexOf(
|
||||
container
|
||||
) + 1;
|
||||
container = container.parentNode;
|
||||
range.setEnd(container, offset);
|
||||
}
|
||||
}
|
||||
if (getLength(frag)) {
|
||||
if (replaceBlock && block) {
|
||||
|
|
@ -1066,6 +1079,13 @@
|
|||
range.collapse(false);
|
||||
detach(block);
|
||||
}
|
||||
if (!stopPoint.contains(range.endContainer)) {
|
||||
if (!root.contains(range.endContainer)) {
|
||||
range.setEnd(root, getLength(root));
|
||||
range.collapse(false);
|
||||
}
|
||||
stopPoint = getClosest(range.endContainer, root, "BLOCKQUOTE") || root;
|
||||
}
|
||||
moveRangeBoundariesUpTree(range, stopPoint, stopPoint, root);
|
||||
let nodeAfterSplit = split(
|
||||
range.endContainer,
|
||||
|
|
@ -1149,29 +1169,25 @@
|
|||
|
||||
// source/Clipboard.ts
|
||||
var indexOf = Array.prototype.indexOf;
|
||||
var extractRangeToClipboard = (event, range, root, removeRangeFromDocument, toCleanHTML, toPlainText, plainTextOnly) => {
|
||||
const clipboardData = event.clipboardData;
|
||||
if (!clipboardData) {
|
||||
return false;
|
||||
}
|
||||
var extractRange = (range, root, removeRangeFromDocument, toCleanHTML, toPlainText) => {
|
||||
let text = toPlainText ? "" : getTextContentsOfRange(range);
|
||||
const startBlock = getStartBlockOfRange(range, root);
|
||||
const endBlock = getEndBlockOfRange(range, root);
|
||||
let parent = range.commonAncestorContainer;
|
||||
let copyRoot = root;
|
||||
if (startBlock === endBlock && startBlock?.contains(range.commonAncestorContainer)) {
|
||||
if (startBlock === endBlock && startBlock?.contains(parent)) {
|
||||
copyRoot = startBlock;
|
||||
}
|
||||
let contents;
|
||||
if (removeRangeFromDocument) {
|
||||
contents = deleteContentsOfRange(range, root);
|
||||
if (!parent.isConnected) {
|
||||
parent = range.commonAncestorContainer;
|
||||
}
|
||||
} else {
|
||||
range = range.cloneRange();
|
||||
moveRangeBoundariesDownTree(range);
|
||||
moveRangeBoundariesUpTree(range, copyRoot, copyRoot, root);
|
||||
contents = range.cloneContents();
|
||||
}
|
||||
let parent = range.commonAncestorContainer;
|
||||
if (parent instanceof Text) {
|
||||
while (parent && !(parent instanceof Element)) {
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
while (parent && parent !== copyRoot) {
|
||||
|
|
@ -1183,7 +1199,7 @@
|
|||
let html;
|
||||
if (contents.childNodes.length === 1 && contents.childNodes[0] instanceof Text) {
|
||||
text = contents.childNodes[0].data.replace(/ /g, " ");
|
||||
plainTextOnly = true;
|
||||
html = void 0;
|
||||
} else {
|
||||
const node = createElement("DIV");
|
||||
node.append(contents);
|
||||
|
|
@ -1195,15 +1211,34 @@
|
|||
if (toPlainText && html !== void 0) {
|
||||
text = toPlainText(html);
|
||||
}
|
||||
if (text === html) {
|
||||
html = void 0;
|
||||
}
|
||||
if (isWin) {
|
||||
text = text.replace(/\r?\n/g, "\r\n");
|
||||
}
|
||||
if (!plainTextOnly && html && text !== html) {
|
||||
if (html) {
|
||||
html = "<!-- squire -->" + html;
|
||||
}
|
||||
return [text, html];
|
||||
};
|
||||
var extractRangeToClipboard = (event, range, root, removeRangeFromDocument, toCleanHTML, toPlainText, plainTextOnly) => {
|
||||
const clipboardData = event.clipboardData;
|
||||
if (!clipboardData) {
|
||||
return false;
|
||||
}
|
||||
let [text, html] = extractRange(
|
||||
range,
|
||||
root,
|
||||
removeRangeFromDocument,
|
||||
toCleanHTML,
|
||||
toPlainText
|
||||
);
|
||||
event.preventDefault();
|
||||
if (!plainTextOnly && html) {
|
||||
clipboardData.setData("text/html", html);
|
||||
}
|
||||
clipboardData.setData("text/plain", text);
|
||||
event.preventDefault();
|
||||
return true;
|
||||
};
|
||||
var _onCut = function(event) {
|
||||
|
|
@ -1251,7 +1286,11 @@
|
|||
var _onPaste = function(event) {
|
||||
const clipboardData = event.clipboardData;
|
||||
const items = clipboardData.items;
|
||||
const choosePlain = this._isShiftDown;
|
||||
const choosePlain = this._isShiftDown || !!getNearest(
|
||||
this.getSelection().commonAncestorContainer,
|
||||
this._root,
|
||||
"PRE"
|
||||
);
|
||||
let hasRTF = false;
|
||||
let hasImage = false;
|
||||
let plainItem = null;
|
||||
|
|
@ -1270,7 +1309,7 @@
|
|||
hasImage = true;
|
||||
}
|
||||
}
|
||||
if (hasImage && !(hasRTF && htmlItem)) {
|
||||
if (hasImage && !(hasRTF && htmlItem) && !plainItem) {
|
||||
event.preventDefault();
|
||||
this.fireEvent("pasteImage", {
|
||||
clipboardData
|
||||
|
|
@ -1284,42 +1323,122 @@
|
|||
});
|
||||
} else if (plainItem) {
|
||||
plainItem.getAsString((text) => {
|
||||
let isLink = false;
|
||||
const range = this.getSelection();
|
||||
if (!range.collapsed && notWS.test(range.toString())) {
|
||||
const match = this.linkRegExp.exec(text);
|
||||
isLink = !!match && match[0].length === text.length;
|
||||
}
|
||||
if (isLink) {
|
||||
this.makeLink(text);
|
||||
} else {
|
||||
this.insertPlainText(text, true);
|
||||
const isLink = !!match && match[0].length === text.length;
|
||||
if (isLink) {
|
||||
const href = match[1] ? /^(?:ht|f)tps?:/i.test(match[1]) ? match[1] : "http://" + match[1] : "mailto:" + match[0];
|
||||
this.makeLink(href);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.insertPlainText(text, true);
|
||||
});
|
||||
}
|
||||
};
|
||||
var _onDragStart = function() {
|
||||
const range = this.getSelection();
|
||||
if (range && !range.collapsed && this._root.contains(range.commonAncestorContainer)) {
|
||||
this._dragRange = range.cloneRange();
|
||||
} else {
|
||||
this._dragRange = null;
|
||||
}
|
||||
};
|
||||
var _onDragEnd = function() {
|
||||
this._dragRange = null;
|
||||
};
|
||||
var getCaretRangeFromPoint = (x, y, root) => {
|
||||
let range = null;
|
||||
const doc = document;
|
||||
if (doc.caretPositionFromPoint) {
|
||||
const pos = doc.caretPositionFromPoint(x, y);
|
||||
if (pos) {
|
||||
range = document.createRange();
|
||||
range.setStart(pos.offsetNode, pos.offset);
|
||||
range.collapse(true);
|
||||
}
|
||||
} else if (doc.caretRangeFromPoint) {
|
||||
range = doc.caretRangeFromPoint(x, y);
|
||||
}
|
||||
if (range && !root.contains(range.commonAncestorContainer)) {
|
||||
return null;
|
||||
}
|
||||
return range;
|
||||
};
|
||||
var pointIsWithinRange = (point, source) => {
|
||||
return point.compareBoundaryPoints(Range.START_TO_START, source) >= 0 && point.compareBoundaryPoints(Range.END_TO_END, source) <= 0;
|
||||
};
|
||||
var _onDrop = function(event) {
|
||||
if (!event.dataTransfer) {
|
||||
const dataTransfer = event.dataTransfer;
|
||||
if (!dataTransfer) {
|
||||
return;
|
||||
}
|
||||
const types = event.dataTransfer.types;
|
||||
let l = types.length;
|
||||
const types = dataTransfer.types;
|
||||
let hasPlain = false;
|
||||
let hasHTML = false;
|
||||
while (l--) {
|
||||
switch (types[l]) {
|
||||
for (let i = 0, l = types.length; i < l; i += 1) {
|
||||
switch (types[i]) {
|
||||
case "text/plain":
|
||||
hasPlain = true;
|
||||
break;
|
||||
case "text/html":
|
||||
hasHTML = true;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (hasHTML || hasPlain && this.saveUndoState) {
|
||||
this.saveUndoState();
|
||||
if (!hasPlain && !hasHTML) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
const root = this._root;
|
||||
let dropRange = getCaretRangeFromPoint(event.clientX, event.clientY, root);
|
||||
const dragRange = this._dragRange;
|
||||
this._dragRange = null;
|
||||
if (!dropRange) {
|
||||
return;
|
||||
}
|
||||
let text, html;
|
||||
if (dragRange) {
|
||||
if (pointIsWithinRange(dropRange, dragRange)) {
|
||||
return;
|
||||
}
|
||||
this._recordUndoState(dragRange, this._isInUndoState);
|
||||
const bookmark = document.createComment("");
|
||||
dropRange.insertNode(bookmark);
|
||||
this._getRangeAndRemoveBookmark(dragRange);
|
||||
[text, html] = extractRange(
|
||||
dragRange,
|
||||
root,
|
||||
dataTransfer.dropEffect !== "copy",
|
||||
this._config.willCutCopy,
|
||||
this._config.toPlainText
|
||||
);
|
||||
bookmark.replaceWith(
|
||||
createElement("INPUT", {
|
||||
id: this.startSelectionId,
|
||||
type: "hidden"
|
||||
}),
|
||||
createElement("INPUT", {
|
||||
id: this.endSelectionId,
|
||||
type: "hidden"
|
||||
})
|
||||
);
|
||||
this._getRangeAndRemoveBookmark(dropRange);
|
||||
resetNodeCategoryCache();
|
||||
} else {
|
||||
this.saveUndoState(dropRange);
|
||||
if (hasHTML) {
|
||||
html = dataTransfer.getData("text/html");
|
||||
} else {
|
||||
text = dataTransfer.getData("text/plain");
|
||||
}
|
||||
}
|
||||
this.setSelection(dropRange);
|
||||
if (html !== void 0) {
|
||||
this.insertHTML(html, true);
|
||||
} else if (text !== void 0) {
|
||||
this.insertPlainText(text, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1639,8 +1758,9 @@
|
|||
}
|
||||
key = modifiers + key;
|
||||
const range = this.getSelection();
|
||||
if (this._keyHandlers[key]) {
|
||||
this._keyHandlers[key](this, event, range);
|
||||
const handler = this._keyHandlers[key];
|
||||
if (handler) {
|
||||
handler(this, event, range);
|
||||
} else if (!range.collapsed && !event.ctrlKey && !event.metaKey && key.length === 1) {
|
||||
this.saveUndoState(range);
|
||||
deleteContentsOfRange(range, this._root);
|
||||
|
|
@ -1667,7 +1787,7 @@
|
|||
do {
|
||||
if (node.nodeName === "CODE") {
|
||||
let next = node.nextSibling;
|
||||
if (!(next instanceof Text)) {
|
||||
if (!(next instanceof Text) || next.length === 0) {
|
||||
const textNode = document.createTextNode("\xA0");
|
||||
node.parentNode.insertBefore(textNode, next);
|
||||
next = textNode;
|
||||
|
|
@ -1761,6 +1881,7 @@
|
|||
|
||||
// source/Editor.ts
|
||||
var Squire = class {
|
||||
// _imageResizer: ImageResizer;
|
||||
constructor(root, config) {
|
||||
/**
|
||||
* Subscribing to these events won't automatically add a listener to the
|
||||
|
|
@ -1843,6 +1964,7 @@
|
|||
this._mayHaveZWS = false;
|
||||
this._lastAnchorNode = null;
|
||||
this._lastFocusNode = null;
|
||||
this._lastPathRange = null;
|
||||
this._path = "";
|
||||
this._events = /* @__PURE__ */ new Map();
|
||||
this._undoIndex = -1;
|
||||
|
|
@ -1861,6 +1983,9 @@
|
|||
this.addEventListener("cut", _onCut);
|
||||
this.addEventListener("copy", _onCopy);
|
||||
this.addEventListener("paste", _onPaste);
|
||||
this._dragRange = null;
|
||||
this.addEventListener("dragstart", _onDragStart);
|
||||
this.addEventListener("dragend", _onDragEnd);
|
||||
this.addEventListener("drop", _onDrop);
|
||||
this.addEventListener(
|
||||
"keydown",
|
||||
|
|
@ -1963,7 +2088,7 @@
|
|||
event.preventDefault();
|
||||
this.bold();
|
||||
break;
|
||||
case "formaItalic":
|
||||
case "formatItalic":
|
||||
event.preventDefault();
|
||||
this.italic();
|
||||
break;
|
||||
|
|
@ -2157,9 +2282,11 @@
|
|||
}
|
||||
_getRangeAndRemoveBookmark(range) {
|
||||
const root = this._root;
|
||||
const start = root.querySelector("#" + this.startSelectionId);
|
||||
const end = root.querySelector("#" + this.endSelectionId);
|
||||
if (start && end) {
|
||||
const starts = root.querySelectorAll("#" + this.startSelectionId);
|
||||
const ends = root.querySelectorAll("#" + this.endSelectionId);
|
||||
const start = starts[0];
|
||||
const end = ends[0];
|
||||
if (start && end && !!(start.compareDocumentPosition(end) & Node.DOCUMENT_POSITION_FOLLOWING)) {
|
||||
let startContainer = start.parentNode;
|
||||
let endContainer = end.parentNode;
|
||||
const startOffset = Array.from(startContainer.childNodes).indexOf(
|
||||
|
|
@ -2194,6 +2321,12 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < starts.length; i += 1) {
|
||||
starts[i].remove();
|
||||
}
|
||||
for (let i = 0; i < ends.length; i += 1) {
|
||||
ends[i].remove();
|
||||
}
|
||||
return range || null;
|
||||
}
|
||||
getSelection() {
|
||||
|
|
@ -2279,10 +2412,23 @@
|
|||
}
|
||||
_updatePathOnEvent() {
|
||||
if (this._isFocused) {
|
||||
this._updatePath(this.getSelection());
|
||||
const lastPathRange = this._lastPathRange;
|
||||
const selection = this.getSelection();
|
||||
if (!lastPathRange || !lastPathRange.commonAncestorContainer.isConnected || selection.compareBoundaryPoints(
|
||||
0,
|
||||
// Range.START_TO_START,
|
||||
lastPathRange
|
||||
) !== 0 || selection.compareBoundaryPoints(
|
||||
2,
|
||||
//Range.END_TO_END
|
||||
lastPathRange
|
||||
) !== 0) {
|
||||
this._updatePath(selection);
|
||||
}
|
||||
}
|
||||
}
|
||||
_updatePath(range, force) {
|
||||
this._lastPathRange = range.cloneRange();
|
||||
const anchor = range.startContainer;
|
||||
const focus = range.endContainer;
|
||||
let newPath;
|
||||
|
|
@ -2422,9 +2568,16 @@
|
|||
return this;
|
||||
}
|
||||
saveUndoState(range) {
|
||||
range || (range = this.getSelection());
|
||||
let rangeIsFromSelection = false;
|
||||
if (!range) {
|
||||
range = this.getSelection();
|
||||
rangeIsFromSelection = true;
|
||||
}
|
||||
this._recordUndoState(range, this._isInUndoState);
|
||||
this._getRangeAndRemoveBookmark(range);
|
||||
if (rangeIsFromSelection) {
|
||||
this.setSelection(range);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
undo() {
|
||||
|
|
@ -2484,14 +2637,26 @@
|
|||
}
|
||||
getHTML(withBookmark) {
|
||||
let range;
|
||||
if (withBookmark) {
|
||||
range = this.getSelection();
|
||||
this._saveRangeToBookmark(range);
|
||||
}
|
||||
const html = this._getRawHTML().replace(/\u200B/g, "");
|
||||
if (withBookmark) {
|
||||
this._getRangeAndRemoveBookmark(range);
|
||||
}
|
||||
let html = "";
|
||||
this.modifyDocument(() => {
|
||||
if (withBookmark) {
|
||||
range = this.getSelection();
|
||||
this._saveRangeToBookmark(range);
|
||||
}
|
||||
const resizeContainer = this._root.querySelector(
|
||||
".squire-image-resize-container"
|
||||
);
|
||||
if (resizeContainer) {
|
||||
resizeContainer.remove();
|
||||
}
|
||||
html = this._getRawHTML().replace(/\u200B/g, "");
|
||||
if (resizeContainer) {
|
||||
this._root.append(resizeContainer);
|
||||
}
|
||||
if (withBookmark) {
|
||||
this._getRangeAndRemoveBookmark(range);
|
||||
}
|
||||
});
|
||||
return html;
|
||||
}
|
||||
setHTML(html) {
|
||||
|
|
@ -2640,20 +2805,6 @@
|
|||
insertPlainText(plainText, isPaste) {
|
||||
const range = this.getSelection();
|
||||
if (range.collapsed && getClosest(range.startContainer, this._root, "PRE")) {
|
||||
const startContainer = range.startContainer;
|
||||
let offset = range.startOffset;
|
||||
let textNode;
|
||||
if (!startContainer || !(startContainer instanceof Text)) {
|
||||
const text = document.createTextNode("");
|
||||
startContainer.insertBefore(
|
||||
text,
|
||||
startContainer.childNodes[offset]
|
||||
);
|
||||
textNode = text;
|
||||
offset = 0;
|
||||
} else {
|
||||
textNode = startContainer;
|
||||
}
|
||||
let doInsert = true;
|
||||
if (isPaste) {
|
||||
const event = new CustomEvent("willPaste", {
|
||||
|
|
@ -2667,6 +2818,27 @@
|
|||
doInsert = !event.defaultPrevented;
|
||||
}
|
||||
if (doInsert) {
|
||||
this.saveUndoState(range);
|
||||
const startContainer = range.startContainer;
|
||||
let offset = range.startOffset;
|
||||
let textNode;
|
||||
if (startContainer instanceof Text) {
|
||||
textNode = startContainer;
|
||||
} else {
|
||||
let nodeBeforeCursor = offset ? startContainer.childNodes[offset - 1] : null;
|
||||
if (nodeBeforeCursor instanceof Text) {
|
||||
textNode = nodeBeforeCursor;
|
||||
offset = textNode.length;
|
||||
} else {
|
||||
const text = document.createTextNode("");
|
||||
startContainer.insertBefore(
|
||||
text,
|
||||
startContainer.childNodes[offset]
|
||||
);
|
||||
textNode = text;
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
textNode.insertData(offset, plainText);
|
||||
range.setStart(textNode, offset + plainText.length);
|
||||
range.collapse(true);
|
||||
|
|
@ -3038,8 +3210,11 @@
|
|||
// --- Block formatting
|
||||
_ensureBottomLine() {
|
||||
const root = this._root;
|
||||
const last = root.lastElementChild;
|
||||
if (!last || last.nodeName !== this._config.blockTag || !isBlock(last)) {
|
||||
let last = root;
|
||||
do {
|
||||
last = last.lastElementChild;
|
||||
} while (last && isContainer(last));
|
||||
if (!last || !isBlock(last)) {
|
||||
root.append(this.createDefaultBlock());
|
||||
}
|
||||
}
|
||||
|
|
@ -3076,10 +3251,11 @@
|
|||
if (block && (parent = getClosest(block, root, "PRE"))) {
|
||||
moveRangeBoundariesDownTree(range);
|
||||
node = range.startContainer;
|
||||
const offset2 = range.startOffset;
|
||||
let offset2 = range.startOffset;
|
||||
if (!(node instanceof Text)) {
|
||||
node = document.createTextNode("");
|
||||
parent.insertBefore(node, parent.firstChild);
|
||||
offset2 = 0;
|
||||
}
|
||||
if (!lineBreakOnly && node instanceof Text && (node.data.charAt(offset2 - 1) === "\n" || rangeDoesStartAtBlockBoundary(range, root)) && (node.data.charAt(offset2) === "\n" || rangeDoesEndAtBlockBoundary(range, root))) {
|
||||
node.deleteData(offset2 && offset2 - 1, offset2 ? 2 : 1);
|
||||
|
|
@ -3101,7 +3277,9 @@
|
|||
range.setStart(node, 0);
|
||||
} else {
|
||||
node.insertData(offset2, "\n");
|
||||
fixCursor(parent);
|
||||
if (!node.nextSibling) {
|
||||
parent.append(createElement("BR"));
|
||||
}
|
||||
if (node.length === offset2 + 1) {
|
||||
range.setStartAfter(node);
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue