Compare commits

...

5 commits

Author SHA1 Message Date
the-djmaze
aad651f2a1 Remove buggy Squire ImageResizer 2026-10-20 23:41:06 +02:00
the-djmaze
67a68915db Knockout use Reflection binding 2026-10-20 23:34:48 +02:00
the-djmaze
71287022ca Make Languages modal 10px wider 2026-10-20 23:33:40 +02:00
the-djmaze
3da27c3bc8 window.localStorage to localStorage 2026-10-20 23:33:07 +02:00
the-djmaze
020927cc56 Squire v2.4.9 2026-10-20 23:32:32 +02:00
6 changed files with 271 additions and 92 deletions

View file

@ -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);
}
};

View file

@ -1,6 +1,6 @@
#V-PopupsLanguages {
max-width: 710px;
max-width: 720px;
label {
display: inline-block;

View file

@ -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);

View file

@ -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");

View file

@ -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);

View file

@ -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 {