mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Squire use double quotes as in original source
This commit is contained in:
parent
c61f4a6918
commit
4bb1e24222
1 changed files with 128 additions and 123 deletions
251
vendors/squire/build/squire-raw.js
vendored
251
vendors/squire/build/squire-raw.js
vendored
|
|
@ -82,7 +82,7 @@ const
|
||||||
return !isLeaf(node) && (
|
return !isLeaf(node) && (
|
||||||
node.nodeType === node2.nodeType &&
|
node.nodeType === node2.nodeType &&
|
||||||
node.nodeName === node2.nodeName &&
|
node.nodeName === node2.nodeName &&
|
||||||
node.nodeName !== 'A' &&
|
node.nodeName !== "A" &&
|
||||||
node.className === node2.className &&
|
node.className === node2.className &&
|
||||||
node.style?.cssText === node2.style?.cssText
|
node.style?.cssText === node2.style?.cssText
|
||||||
);
|
);
|
||||||
|
|
@ -333,14 +333,14 @@ const
|
||||||
[...container.childNodes].forEach(child => {
|
[...container.childNodes].forEach(child => {
|
||||||
isBR = child.nodeName === "BR";
|
isBR = child.nodeName === "BR";
|
||||||
if (!isBR && child.parentNode == root && isInline(child)
|
if (!isBR && child.parentNode == root && isInline(child)
|
||||||
// && (blockTag !== 'DIV' || (child.matches && !child.matches(phrasingElements)))
|
// && (blockTag !== "DIV" || (child.matches && !child.matches(phrasingElements)))
|
||||||
) {
|
) {
|
||||||
wrapper = wrapper || createElement("DIV");
|
wrapper = wrapper || createElement("DIV");
|
||||||
wrapper.append(child);
|
wrapper.append(child);
|
||||||
} else if (isBR || wrapper) {
|
} else if (isBR || wrapper) {
|
||||||
wrapper = wrapper || createElement("DIV");
|
wrapper = wrapper || createElement("DIV");
|
||||||
fixCursor(wrapper);
|
fixCursor(wrapper);
|
||||||
child[isBR ? 'replaceWith' : 'before'](wrapper);
|
child[isBR ? "replaceWith" : "before"](wrapper);
|
||||||
wrapper = null;
|
wrapper = null;
|
||||||
}
|
}
|
||||||
isContainer(child) && fixContainer(child, root);
|
isContainer(child) && fixContainer(child, root);
|
||||||
|
|
@ -495,32 +495,32 @@ const
|
||||||
styleToSemantic = {
|
styleToSemantic = {
|
||||||
fontWeight: {
|
fontWeight: {
|
||||||
regexp: /^bold|^700/i,
|
regexp: /^bold|^700/i,
|
||||||
replace: () => createElement('B')
|
replace: () => createElement("B")
|
||||||
},
|
},
|
||||||
fontStyle: {
|
fontStyle: {
|
||||||
regexp: /^italic/i,
|
regexp: /^italic/i,
|
||||||
replace: () => createElement('I')
|
replace: () => createElement("I")
|
||||||
},
|
},
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
regexp: notWS,
|
regexp: notWS,
|
||||||
replace: (doc, family) => createElement('SPAN', {
|
replace: (doc, family) => createElement("SPAN", {
|
||||||
style: 'font-family:' + family
|
style: 'font-family:' + family
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
fontSize: {
|
fontSize: {
|
||||||
regexp: notWS,
|
regexp: notWS,
|
||||||
replace: (doc, size) => createElement('SPAN', {
|
replace: (doc, size) => createElement("SPAN", {
|
||||||
style: 'font-size:' + size
|
style: 'font-size:' + size
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
textDecoration: {
|
textDecoration: {
|
||||||
regexp: /^underline/i,
|
regexp: /^underline/i,
|
||||||
replace: () => createElement('U')
|
replace: () => createElement("U")
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
textDecoration: {
|
textDecoration: {
|
||||||
regexp: /^line-through/i,
|
regexp: /^line-through/i,
|
||||||
replace: doc => createElement('S')
|
replace: doc => createElement("S")
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
},
|
},
|
||||||
|
|
@ -563,14 +563,14 @@ const
|
||||||
},
|
},
|
||||||
fontSizes = {
|
fontSizes = {
|
||||||
1: 'x-small',
|
1: 'x-small',
|
||||||
2: 'small',
|
2: "small",
|
||||||
3: 'medium',
|
3: "medium",
|
||||||
4: 'large',
|
4: "large",
|
||||||
5: 'x-large',
|
5: 'x-large',
|
||||||
6: 'xx-large',
|
6: 'xx-large',
|
||||||
7: 'xxx-large',
|
7: 'xxx-large',
|
||||||
'-1': 'smaller',
|
'-1': "smaller",
|
||||||
'+1': 'larger'
|
'+1': "larger"
|
||||||
},
|
},
|
||||||
stylesRewriters = {
|
stylesRewriters = {
|
||||||
STRONG: replaceWithTag("B"),
|
STRONG: replaceWithTag("B"),
|
||||||
|
|
@ -582,7 +582,7 @@ const
|
||||||
let face = node.face,
|
let face = node.face,
|
||||||
size = node.size,
|
size = node.size,
|
||||||
color = node.color,
|
color = node.color,
|
||||||
newTag = createElement('SPAN'),
|
newTag = createElement("SPAN"),
|
||||||
css = newTag.style;
|
css = newTag.style;
|
||||||
newTag.style.cssText = node.style.cssText;
|
newTag.style.cssText = node.style.cssText;
|
||||||
if (face) {
|
if (face) {
|
||||||
|
|
@ -606,7 +606,7 @@ const
|
||||||
// CODE:
|
// CODE:
|
||||||
// SAMP:
|
// SAMP:
|
||||||
TT: node => {
|
TT: node => {
|
||||||
let el = createElement('SPAN', {
|
let el = createElement("SPAN", {
|
||||||
style: 'font-family:menlo,consolas,"courier new",monospace'
|
style: 'font-family:menlo,consolas,"courier new",monospace'
|
||||||
});
|
});
|
||||||
node.replaceWith(el);
|
node.replaceWith(el);
|
||||||
|
|
@ -650,7 +650,7 @@ const
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (childLength) {
|
if (childLength) {
|
||||||
cleanTree(child, preserveWS || (nodeName === 'PRE'));
|
cleanTree(child, preserveWS || (nodeName === "PRE"));
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -667,7 +667,7 @@ const
|
||||||
walker.currentNode = child;
|
walker.currentNode = child;
|
||||||
while (sibling = walker.previousPONode()) {
|
while (sibling = walker.previousPONode()) {
|
||||||
nodeName = sibling.nodeName;
|
nodeName = sibling.nodeName;
|
||||||
if (nodeName === 'IMG' || (nodeName === '#text' && notWS.test(sibling.data))) {
|
if (nodeName === "IMG" || (nodeName === '#text' && notWS.test(sibling.data))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!isInline(sibling)) {
|
if (!isInline(sibling)) {
|
||||||
|
|
@ -680,7 +680,7 @@ const
|
||||||
if (endsWithWS) {
|
if (endsWithWS) {
|
||||||
walker.currentNode = child;
|
walker.currentNode = child;
|
||||||
while (sibling = walker.nextNode()) {
|
while (sibling = walker.nextNode()) {
|
||||||
if (nodeName === 'IMG' || (nodeName === '#text' && notWS.test(sibling.data))) {
|
if (nodeName === "IMG" || (nodeName === '#text' && notWS.test(sibling.data))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!isInline(sibling)) {
|
if (!isInline(sibling)) {
|
||||||
|
|
@ -724,7 +724,7 @@ const
|
||||||
// elements at the end of each block will then have them added back in a later
|
// elements at the end of each block will then have them added back in a later
|
||||||
// fixCursor method call.
|
// fixCursor method call.
|
||||||
cleanupBRs = (node, root, keepForBlankLine) => {
|
cleanupBRs = (node, root, keepForBlankLine) => {
|
||||||
const brs = node.querySelectorAll('BR');
|
const brs = node.querySelectorAll("BR");
|
||||||
let l = brs.length;
|
let l = brs.length;
|
||||||
let br, parent;
|
let br, parent;
|
||||||
while (l--) {
|
while (l--) {
|
||||||
|
|
@ -1081,7 +1081,7 @@ const
|
||||||
range.collapse(); // collapse to end
|
range.collapse(); // collapse to end
|
||||||
|
|
||||||
// Where will we split up to? First blockquote parent, otherwise root.
|
// Where will we split up to? First blockquote parent, otherwise root.
|
||||||
stopPoint = getClosest(range.endContainer, root, 'BLOCKQUOTE') || root;
|
stopPoint = getClosest(range.endContainer, root, "BLOCKQUOTE") || root;
|
||||||
|
|
||||||
// Merge the contents of the first block in the frag with the focused block.
|
// Merge the contents of the first block in the frag with the focused block.
|
||||||
// If there are contents in the block after the focus point, collect this
|
// If there are contents in the block after the focus point, collect this
|
||||||
|
|
@ -1269,7 +1269,7 @@ const
|
||||||
setClipboardData = (event, contents, root) => {
|
setClipboardData = (event, contents, root) => {
|
||||||
let clipboardData = event.clipboardData;
|
let clipboardData = event.clipboardData;
|
||||||
let body = doc.body;
|
let body = doc.body;
|
||||||
let node = createElement('div');
|
let node = createElement("div");
|
||||||
let html, text;
|
let html, text;
|
||||||
|
|
||||||
node.append(contents);
|
node.append(contents);
|
||||||
|
|
@ -1280,7 +1280,7 @@ const
|
||||||
// calculating innerText, even though they don't actually affect
|
// calculating innerText, even though they don't actually affect
|
||||||
// display, so we need to remove them first.
|
// display, so we need to remove them first.
|
||||||
cleanupBRs(node, root, true);
|
cleanupBRs(node, root, true);
|
||||||
node.setAttribute('style',
|
node.setAttribute("style",
|
||||||
'position:fixed;overflow:hidden;bottom:100%;right:100%;');
|
'position:fixed;overflow:hidden;bottom:100%;right:100%;');
|
||||||
body.append(node);
|
body.append(node);
|
||||||
text = (node.innerText || node.textContent).replace(NBSP, ' '); // Replace nbsp with regular space
|
text = (node.innerText || node.textContent).replace(NBSP, ' '); // Replace nbsp with regular space
|
||||||
|
|
@ -1371,7 +1371,7 @@ const
|
||||||
// plain text.
|
// plain text.
|
||||||
} else if (type === 'text/plain' || type === 'text/uri-list') {
|
} else if (type === 'text/plain' || type === 'text/uri-list') {
|
||||||
plainItem = item;
|
plainItem = item;
|
||||||
} else if (item.kind === 'file' && /^image\/(png|jpeg|webp)/.test(type)) {
|
} else if (item.kind === "file" && /^image\/(png|jpeg|webp)/.test(type)) {
|
||||||
imageItem = item;
|
imageItem = item;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -1380,8 +1380,8 @@ const
|
||||||
if (imageItem) {
|
if (imageItem) {
|
||||||
let reader = new FileReader();
|
let reader = new FileReader();
|
||||||
reader.onload = event => {
|
reader.onload = event => {
|
||||||
let img = createElement('img', {src: event.target.result}),
|
let img = createElement("img", {src: event.target.result}),
|
||||||
canvas = createElement('canvas'),
|
canvas = createElement("canvas"),
|
||||||
ctx = canvas.getContext('2d');
|
ctx = canvas.getContext('2d');
|
||||||
img.onload = ()=>{
|
img.onload = ()=>{
|
||||||
ctx.drawImage(img, 0, 0);
|
ctx.drawImage(img, 0, 0);
|
||||||
|
|
@ -1452,7 +1452,7 @@ const
|
||||||
// it removes the div and replaces it with just a <br> inside the
|
// it removes the div and replaces it with just a <br> inside the
|
||||||
// root. Detach the <br>; the _ensureBottomLine call will insert a new
|
// root. Detach the <br>; the _ensureBottomLine call will insert a new
|
||||||
// block.
|
// block.
|
||||||
if (node === self._root && (node = node.firstChild) && node.nodeName === 'BR') {
|
if (node === self._root && (node = node.firstChild) && node.nodeName === "BR") {
|
||||||
detach(node);
|
detach(node);
|
||||||
}
|
}
|
||||||
self._ensureBottomLine();
|
self._ensureBottomLine();
|
||||||
|
|
@ -1511,7 +1511,7 @@ const
|
||||||
else if (current) {
|
else if (current) {
|
||||||
let parent = getClosest(current, root, 'UL,OL,BLOCKQUOTE');
|
let parent = getClosest(current, root, 'UL,OL,BLOCKQUOTE');
|
||||||
if (parent) {
|
if (parent) {
|
||||||
return ('BLOCKQUOTE' === parent.nodeName)
|
return ("BLOCKQUOTE" === parent.nodeName)
|
||||||
// Break blockquote
|
// Break blockquote
|
||||||
? self.decreaseQuoteLevel(range)
|
? self.decreaseQuoteLevel(range)
|
||||||
// Break list
|
// Break list
|
||||||
|
|
@ -1606,7 +1606,7 @@ const
|
||||||
|
|
||||||
// We need to apply the backspace/delete handlers regardless of control key modifiers.
|
// We need to apply the backspace/delete handlers regardless of control key modifiers.
|
||||||
// ctrl-shift-key or meta-shift-key
|
// ctrl-shift-key or meta-shift-key
|
||||||
if (key !== 'backspace' && key !== 'delete') {
|
if (key !== "backspace" && key !== "delete") {
|
||||||
if (event.shiftKey) { key = 'shift-' + key; }
|
if (event.shiftKey) { key = 'shift-' + key; }
|
||||||
if (event[osKey]) { key = ctrlKey + key; }
|
if (event[osKey]) { key = ctrlKey + key; }
|
||||||
// if (event.altKey) { key = 'alt-' + key; }
|
// if (event.altKey) { key = 'alt-' + key; }
|
||||||
|
|
@ -1637,7 +1637,7 @@ const
|
||||||
range = createRange(root.insertBefore(
|
range = createRange(root.insertBefore(
|
||||||
this.createDefaultBlock(), nextElement
|
this.createDefaultBlock(), nextElement
|
||||||
), 0);
|
), 0);
|
||||||
if (nextElement.tagName === 'BR') {
|
if (nextElement.tagName === "BR") {
|
||||||
// delete it because a new <br> is created by createDefaultBlock()
|
// delete it because a new <br> is created by createDefaultBlock()
|
||||||
root.removeChild(nextElement);
|
root.removeChild(nextElement);
|
||||||
}
|
}
|
||||||
|
|
@ -1658,9 +1658,9 @@ const
|
||||||
if (range.collapsed && rangeDoesStartAtBlockBoundary(range, root)) {
|
if (range.collapsed && rangeDoesStartAtBlockBoundary(range, root)) {
|
||||||
node = getStartBlockOfRange(range, root);
|
node = getStartBlockOfRange(range, root);
|
||||||
// Iterate through the block's parents
|
// Iterate through the block's parents
|
||||||
while ((parent = node.parentNode)) {
|
while (parent = node.parentNode) {
|
||||||
// If we find a UL or OL (so are in a list, node must be an LI)
|
// If we find a UL or OL (so are in a list, node must be an LI)
|
||||||
if (parent.nodeName === 'UL' || parent.nodeName === 'OL') {
|
if (parent.nodeName === "UL" || parent.nodeName === "OL") {
|
||||||
// Then increase the list level
|
// Then increase the list level
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
self.increaseListLevel(range);
|
self.increaseListLevel(range);
|
||||||
|
|
@ -1697,7 +1697,7 @@ const
|
||||||
let node = range.endContainer;
|
let node = range.endContainer;
|
||||||
if (range.collapsed && range.endOffset === getLength(node)) {
|
if (range.collapsed && range.endOffset === getLength(node)) {
|
||||||
do {
|
do {
|
||||||
if (node.nodeName === 'A') {
|
if (node.nodeName === "A") {
|
||||||
range.setStartAfter(node);
|
range.setStartAfter(node);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1725,14 +1725,14 @@ const
|
||||||
self[method]();
|
self[method]();
|
||||||
},
|
},
|
||||||
|
|
||||||
blockTag = 'DIV',
|
blockTag = "DIV",
|
||||||
DOCUMENT_POSITION_PRECEDING = 2, // Node.DOCUMENT_POSITION_PRECEDING
|
DOCUMENT_POSITION_PRECEDING = 2, // Node.DOCUMENT_POSITION_PRECEDING
|
||||||
|
|
||||||
NBSP = '\u00A0',
|
NBSP = '\u00A0',
|
||||||
|
|
||||||
win = doc.defaultView,
|
win = doc.defaultView,
|
||||||
|
|
||||||
osKey = isMac ? 'metaKey' : 'ctrlKey',
|
osKey = isMac ? "metaKey" : "ctrlKey",
|
||||||
|
|
||||||
filterAccept = NodeFilter.FILTER_ACCEPT,
|
filterAccept = NodeFilter.FILTER_ACCEPT,
|
||||||
/*
|
/*
|
||||||
|
|
@ -1765,7 +1765,7 @@ const
|
||||||
|
|
||||||
setAttributes = (node, props) => {
|
setAttributes = (node, props) => {
|
||||||
props && Object.entries(props).forEach(([k,v]) => {
|
props && Object.entries(props).forEach(([k,v]) => {
|
||||||
if ('style' === k && typeof v === 'object') {
|
if ("style" === k && typeof v === "object") {
|
||||||
Object.entries(v).forEach(([k,v]) => node.style[k] = v);
|
Object.entries(v).forEach(([k,v]) => node.style[k] = v);
|
||||||
} else if (v != null) {
|
} else if (v != null) {
|
||||||
node.setAttribute(k, v);
|
node.setAttribute(k, v);
|
||||||
|
|
@ -1777,14 +1777,14 @@ const
|
||||||
|
|
||||||
newContentWalker = root => createTreeWalker(root,
|
newContentWalker = root => createTreeWalker(root,
|
||||||
SHOW_ELEMENT_OR_TEXT,
|
SHOW_ELEMENT_OR_TEXT,
|
||||||
node => isTextNode(node) ? notWS.test(node.data) : node.nodeName === 'IMG'
|
node => isTextNode(node) ? notWS.test(node.data) : node.nodeName === "IMG"
|
||||||
),
|
),
|
||||||
|
|
||||||
didError = error => console.error(error),
|
didError = error => console.error(error),
|
||||||
|
|
||||||
detachUneditableNode = (node, root) => {
|
detachUneditableNode = (node, root) => {
|
||||||
let parent;
|
let parent;
|
||||||
while ((parent = node.parentNode)) {
|
while (parent = node.parentNode) {
|
||||||
if (parent === root || parent.isContentEditable) {
|
if (parent === root || parent.isContentEditable) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1868,23 +1868,23 @@ const
|
||||||
endSelectionId = 'squire-selection-end',
|
endSelectionId = 'squire-selection-end',
|
||||||
|
|
||||||
createBookmarkNodes = () => [
|
createBookmarkNodes = () => [
|
||||||
createElement('INPUT', {
|
createElement("INPUT", {
|
||||||
id: startSelectionId,
|
id: startSelectionId,
|
||||||
type: 'hidden'
|
type: "hidden"
|
||||||
}),
|
}),
|
||||||
createElement('INPUT', {
|
createElement("INPUT", {
|
||||||
id: endSelectionId,
|
id: endSelectionId,
|
||||||
type: 'hidden'
|
type: "hidden"
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
|
|
||||||
// --- Block formatting ---
|
// --- Block formatting ---
|
||||||
|
|
||||||
tagAfterSplit = {
|
tagAfterSplit = {
|
||||||
DT: 'DD',
|
DT: "DD",
|
||||||
DD: 'DT',
|
DD: "DT",
|
||||||
LI: 'LI',
|
LI: "LI",
|
||||||
PRE: 'PRE'
|
PRE: "PRE"
|
||||||
},
|
},
|
||||||
|
|
||||||
getListSelection = (range, root) => {
|
getListSelection = (range, root) => {
|
||||||
|
|
@ -1918,12 +1918,12 @@ const
|
||||||
node, tag, prev, newLi;
|
node, tag, prev, newLi;
|
||||||
|
|
||||||
while (node = walker.nextNode()) {
|
while (node = walker.nextNode()) {
|
||||||
if (node.parentNode.nodeName === 'LI') {
|
if (node.parentNode.nodeName === "LI") {
|
||||||
node = node.parentNode;
|
node = node.parentNode;
|
||||||
walker.currentNode = node.lastChild;
|
walker.currentNode = node.lastChild;
|
||||||
}
|
}
|
||||||
if (node.nodeName !== 'LI') {
|
if (node.nodeName !== "LI") {
|
||||||
newLi = createElement('LI');
|
newLi = createElement("LI");
|
||||||
if (node.dir) {
|
if (node.dir) {
|
||||||
newLi.dir = node.dir;
|
newLi.dir = node.dir;
|
||||||
}
|
}
|
||||||
|
|
@ -1976,19 +1976,19 @@ const
|
||||||
linkRegExp = /\b(?:((https?:\/\/)?(?:www\d{0,3}\.|[a-z0-9][a-z0-9.-]*\.[a-z]{2,}\/)(?:[^\s()<>]+|\([^\s()<>]+\))+(?:[^\s?&`!()[\]{};:'".,<>«»“”‘’]|\([^\s()<>]+\)))|([\w\-.%+]+@(?:[\w-]+\.)+[a-z]{2,}\b(?:\?[^&?\s]+=[^\s?&`!()[\]{};:'".,<>«»“”‘’]+(?:&[^&?\s]+=[^\s?&`!()[\]{};:'".,<>«»“”‘’]+)*)?))/i,
|
linkRegExp = /\b(?:((https?:\/\/)?(?:www\d{0,3}\.|[a-z0-9][a-z0-9.-]*\.[a-z]{2,}\/)(?:[^\s()<>]+|\([^\s()<>]+\))+(?:[^\s?&`!()[\]{};:'".,<>«»“”‘’]|\([^\s()<>]+\)))|([\w\-.%+]+@(?:[\w-]+\.)+[a-z]{2,}\b(?:\?[^&?\s]+=[^\s?&`!()[\]{};:'".,<>«»“”‘’]+(?:&[^&?\s]+=[^\s?&`!()[\]{};:'".,<>«»“”‘’]+)*)?))/i,
|
||||||
|
|
||||||
addLinks = (frag, root) => {
|
addLinks = (frag, root) => {
|
||||||
let walker = createTreeWalker(frag, SHOW_TEXT, node => !getClosest(node, root, 'A'));
|
let walker = createTreeWalker(frag, SHOW_TEXT, node => !getClosest(node, root, "A"));
|
||||||
let node, data, parent, match, index, endIndex, child;
|
let node, data, parent, match, index, endIndex, child;
|
||||||
while ((node = walker.nextNode())) {
|
while (node = walker.nextNode()) {
|
||||||
data = node.data;
|
data = node.data;
|
||||||
parent = node.parentNode;
|
parent = node.parentNode;
|
||||||
while ((match = linkRegExp.exec(data))) {
|
while (match = linkRegExp.exec(data)) {
|
||||||
index = match.index;
|
index = match.index;
|
||||||
endIndex = index + match[0].length;
|
endIndex = index + match[0].length;
|
||||||
if (index) {
|
if (index) {
|
||||||
child = doc.createTextNode(data.slice(0, index));
|
child = doc.createTextNode(data.slice(0, index));
|
||||||
parent.insertBefore(child, node);
|
parent.insertBefore(child, node);
|
||||||
}
|
}
|
||||||
child = createElement('A', {
|
child = createElement("A", {
|
||||||
href: match[1]
|
href: match[1]
|
||||||
? (match[2] ? match[1] : 'https://' + match[1])
|
? (match[2] ? match[1] : 'https://' + match[1])
|
||||||
: 'mailto:' + match[0]
|
: 'mailto:' + match[0]
|
||||||
|
|
@ -2009,22 +2009,22 @@ if (!isMac && !isIOS) {
|
||||||
keyHandlers.pagedown = self => self._moveCursorTo(false);
|
keyHandlers.pagedown = self => self._moveCursorTo(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
keyHandlers[ctrlKey + 'b'] = mapKeyToFormat('B');
|
keyHandlers[ctrlKey + "b"] = mapKeyToFormat("B");
|
||||||
keyHandlers[ctrlKey + 'i'] = mapKeyToFormat('I');
|
keyHandlers[ctrlKey + "i"] = mapKeyToFormat("I");
|
||||||
keyHandlers[ctrlKey + 'u'] = mapKeyToFormat('U');
|
keyHandlers[ctrlKey + "u"] = mapKeyToFormat("U");
|
||||||
keyHandlers[ctrlKey + 'shift-7'] = mapKeyToFormat('S');
|
keyHandlers[ctrlKey + 'shift-7'] = mapKeyToFormat("S");
|
||||||
keyHandlers[ctrlKey + 'shift-5'] = mapKeyToFormat('SUB', 'SUP');
|
keyHandlers[ctrlKey + 'shift-5'] = mapKeyToFormat("SUB", "SUP");
|
||||||
keyHandlers[ctrlKey + 'shift-6'] = mapKeyToFormat('SUP', 'SUB');
|
keyHandlers[ctrlKey + 'shift-6'] = mapKeyToFormat("SUP", "SUB");
|
||||||
keyHandlers[ctrlKey + 'shift-8'] = toggleList('UL', 'makeUnorderedList');
|
keyHandlers[ctrlKey + 'shift-8'] = toggleList("UL", "makeUnorderedList");
|
||||||
keyHandlers[ctrlKey + 'shift-9'] = toggleList('OL', 'makeOrderedList');
|
keyHandlers[ctrlKey + 'shift-9'] = toggleList("OL", "makeOrderedList");
|
||||||
keyHandlers[ctrlKey + '['] = changeIndentationLevel('decrease');
|
keyHandlers[ctrlKey + '['] = changeIndentationLevel("decrease");
|
||||||
keyHandlers[ctrlKey + ']'] = changeIndentationLevel('increase');
|
keyHandlers[ctrlKey + ']'] = changeIndentationLevel("increase");
|
||||||
keyHandlers[ctrlKey + 'd'] = mapKeyTo('toggleCode');
|
keyHandlers[ctrlKey + "d"] = mapKeyTo("toggleCode");
|
||||||
keyHandlers[ctrlKey + 'y'] = mapKeyTo('redo');
|
keyHandlers[ctrlKey + "y"] = mapKeyTo("redo");
|
||||||
//keyHandlers[ctrlKey + 'z'] = mapKeyTo('undo');
|
//keyHandlers[ctrlKey + "z"] = mapKeyTo("undo");
|
||||||
keyHandlers[ctrlKey + 'shift-z'] = mapKeyTo('redo');
|
keyHandlers[ctrlKey + 'shift-z'] = mapKeyTo("redo");
|
||||||
keyHandlers['redo'] = mapKeyTo('redo');
|
keyHandlers["redo"] = mapKeyTo("redo");
|
||||||
//keyHandlers['undo'] = mapKeyTo('undo');
|
//keyHandlers["undo"] = mapKeyTo("undo");
|
||||||
|
|
||||||
class EditStack extends Array
|
class EditStack extends Array
|
||||||
{
|
{
|
||||||
|
|
@ -2044,11 +2044,11 @@ class EditStack extends Array
|
||||||
}
|
}
|
||||||
|
|
||||||
stateChanged(/*canUndo, canRedo*/) {
|
stateChanged(/*canUndo, canRedo*/) {
|
||||||
this.squire.fireEvent('undoStateChange', {
|
this.squire.fireEvent("undoStateChange", {
|
||||||
canUndo: this.index > 0,
|
canUndo: this.index > 0,
|
||||||
canRedo: this.index + 1 < this.length
|
canRedo: this.index + 1 < this.length
|
||||||
});
|
});
|
||||||
this.squire.fireEvent('input');
|
this.squire.fireEvent("input");
|
||||||
}
|
}
|
||||||
|
|
||||||
docWasChanged() {
|
docWasChanged() {
|
||||||
|
|
@ -2056,7 +2056,7 @@ class EditStack extends Array
|
||||||
this.inUndoState = false;
|
this.inUndoState = false;
|
||||||
this.stateChanged(/*true, false*/);
|
this.stateChanged(/*true, false*/);
|
||||||
} else
|
} else
|
||||||
this.squire.fireEvent('input');
|
this.squire.fireEvent("input");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -2344,7 +2344,7 @@ class Squire
|
||||||
let handlers = this._events[type];
|
let handlers = this._events[type];
|
||||||
if (!handlers) {
|
if (!handlers) {
|
||||||
handlers = this._events[type] = [];
|
handlers = this._events[type] = [];
|
||||||
customEvents[type] || this._root.addEventListener(type, this, {capture:true,passive:'touchstart'===type});
|
customEvents[type] || this._root.addEventListener(type, this, {capture:true,passive:"touchstart"===type});
|
||||||
}
|
}
|
||||||
handlers.push(fn);
|
handlers.push(fn);
|
||||||
});
|
});
|
||||||
|
|
@ -2725,7 +2725,7 @@ class Squire
|
||||||
// After inserting the fragment, check whether the cursor is inside
|
// After inserting the fragment, check whether the cursor is inside
|
||||||
// an <a> element and if so if there is an equivalent cursor
|
// an <a> element and if so if there is an equivalent cursor
|
||||||
// position after the <a> element. If there is, move it there.
|
// position after the <a> element. If there is, move it there.
|
||||||
moveRangeBoundaryOutOf(range, 'A', root);
|
moveRangeBoundaryOutOf(range, "A", root);
|
||||||
|
|
||||||
this._ensureBottomLine();
|
this._ensureBottomLine();
|
||||||
|
|
||||||
|
|
@ -2778,7 +2778,7 @@ class Squire
|
||||||
}
|
}
|
||||||
|
|
||||||
insertImage(src, attributes) {
|
insertImage(src, attributes) {
|
||||||
const img = createElement('IMG', mergeObjects({
|
const img = createElement("IMG", mergeObjects({
|
||||||
src: src
|
src: src
|
||||||
}, attributes, true));
|
}, attributes, true));
|
||||||
this.insertElement(img);
|
this.insertElement(img);
|
||||||
|
|
@ -2787,7 +2787,7 @@ class Squire
|
||||||
|
|
||||||
insertPlainText(plainText, isPaste) {
|
insertPlainText(plainText, isPaste) {
|
||||||
const range = this.getSelection();
|
const 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 node = range.startContainer;
|
||||||
let offset = range.startOffset;
|
let offset = range.startOffset;
|
||||||
let text;
|
let text;
|
||||||
|
|
@ -2969,8 +2969,8 @@ class Squire
|
||||||
range.commonAncestorContainer,
|
range.commonAncestorContainer,
|
||||||
SHOW_ELEMENT_OR_TEXT,
|
SHOW_ELEMENT_OR_TEXT,
|
||||||
node => (isTextNode(node) ||
|
node => (isTextNode(node) ||
|
||||||
node.nodeName === 'BR' ||
|
node.nodeName === "BR" ||
|
||||||
node.nodeName === 'IMG'
|
node.nodeName === "IMG"
|
||||||
) && isNodeContainedInRange(range, node)
|
) && isNodeContainedInRange(range, node)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -3078,7 +3078,7 @@ class Squire
|
||||||
// in a clone of the tag we're removing and we're done.
|
// in a clone of the tag we're removing and we're done.
|
||||||
if (!isNodeContainedInRange(range, node)) {
|
if (!isNodeContainedInRange(range, node)) {
|
||||||
// Ignore bookmarks and empty text nodes
|
// Ignore bookmarks and empty text nodes
|
||||||
if (node.nodeName !== 'INPUT' && (!isText || node.data)) {
|
if (node.nodeName !== "INPUT" && (!isText || node.data)) {
|
||||||
toWrap.push([exemplar, node]);
|
toWrap.push([exemplar, node]);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -3139,12 +3139,12 @@ class Squire
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
bold() { this.toggleTag('B'); }
|
bold() { this.toggleTag("B"); }
|
||||||
italic() { this.toggleTag('I'); }
|
italic() { this.toggleTag("I"); }
|
||||||
underline() { this.toggleTag('U'); }
|
underline() { this.toggleTag("U"); }
|
||||||
strikethrough() { this.toggleTag('S'); }
|
strikethrough() { this.toggleTag("S"); }
|
||||||
subscript() { this.toggleTag('SUB', 'SUP'); }
|
subscript() { this.toggleTag("SUB", "SUP"); }
|
||||||
superscript() { this.toggleTag('SUP', 'SUB'); }
|
superscript() { this.toggleTag("SUP", "SUB"); }
|
||||||
|
|
||||||
makeLink(url, attributes) {
|
makeLink(url, attributes) {
|
||||||
const range = this.getSelection();
|
const range = this.getSelection();
|
||||||
|
|
@ -3286,7 +3286,7 @@ class Squire
|
||||||
}
|
}
|
||||||
block = getClosest(block, root, "LI") || block;
|
block = getClosest(block, root, "LI") || block;
|
||||||
if (isEmptyBlock(block) && (parent = getClosest(block, root, 'UL,OL,BLOCKQUOTE'))) {
|
if (isEmptyBlock(block) && (parent = getClosest(block, root, 'UL,OL,BLOCKQUOTE'))) {
|
||||||
return 'BLOCKQUOTE' === parent.nodeName
|
return "BLOCKQUOTE" === parent.nodeName
|
||||||
// Break blockquote
|
// Break blockquote
|
||||||
? self.modifyBlocks((/* frag */) => self.createDefaultBlock(createBookmarkNodes(self)), range)
|
? self.modifyBlocks((/* frag */) => self.createDefaultBlock(createBookmarkNodes(self)), range)
|
||||||
// Break list
|
// Break list
|
||||||
|
|
@ -3395,7 +3395,7 @@ class Squire
|
||||||
do {
|
do {
|
||||||
next = startLi === endLi ? null : startLi.nextSibling;
|
next = startLi === endLi ? null : startLi.nextSibling;
|
||||||
newParent.append(startLi);
|
newParent.append(startLi);
|
||||||
} while ((startLi = next));
|
} while (startLi = next);
|
||||||
next = newParent.nextSibling;
|
next = newParent.nextSibling;
|
||||||
next && mergeContainers(next, root);
|
next && mergeContainers(next, root);
|
||||||
|
|
||||||
|
|
@ -3429,7 +3429,7 @@ class Squire
|
||||||
list.nextSibling :
|
list.nextSibling :
|
||||||
split(list, endLi.nextSibling, newParent, root);
|
split(list, endLi.nextSibling, newParent, root);
|
||||||
|
|
||||||
if (newParent !== root && newParent.nodeName === 'LI') {
|
if (newParent !== root && newParent.nodeName === "LI") {
|
||||||
newParent = newParent.parentNode;
|
newParent = newParent.parentNode;
|
||||||
while (insertBefore) {
|
while (insertBefore) {
|
||||||
next = insertBefore.nextSibling;
|
next = insertBefore.nextSibling;
|
||||||
|
|
@ -3443,11 +3443,11 @@ class Squire
|
||||||
do {
|
do {
|
||||||
next = startLi === endLi ? null : startLi.nextSibling;
|
next = startLi === endLi ? null : startLi.nextSibling;
|
||||||
startLi.remove();
|
startLi.remove();
|
||||||
if (makeNotList && startLi.nodeName === 'LI') {
|
if (makeNotList && startLi.nodeName === "LI") {
|
||||||
startLi = this.createDefaultBlock([empty(startLi)]);
|
startLi = this.createDefaultBlock([empty(startLi)]);
|
||||||
}
|
}
|
||||||
newParent.insertBefore(startLi, insertBefore);
|
newParent.insertBefore(startLi, insertBefore);
|
||||||
} while ((startLi = next));
|
} while (startLi = next);
|
||||||
}
|
}
|
||||||
|
|
||||||
list.firstChild || detach(list);
|
list.firstChild || detach(list);
|
||||||
|
|
@ -3462,11 +3462,11 @@ class Squire
|
||||||
}
|
}
|
||||||
|
|
||||||
makeUnorderedList() {
|
makeUnorderedList() {
|
||||||
return this.modifyBlocks(frag => makeList(this, frag, 'UL')).focus();
|
return this.modifyBlocks(frag => makeList(this, frag, "UL")).focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
makeOrderedList() {
|
makeOrderedList() {
|
||||||
return this.modifyBlocks(frag => makeList(this, frag, 'OL')).focus();
|
return this.modifyBlocks(frag => makeList(this, frag, "OL")).focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
removeList() {
|
removeList() {
|
||||||
|
|
@ -3479,11 +3479,9 @@ class Squire
|
||||||
list.replaceWith(listFrag);
|
list.replaceWith(listFrag);
|
||||||
});
|
});
|
||||||
|
|
||||||
frag.querySelectorAll('LI').forEach(item => {
|
frag.querySelectorAll("LI").forEach(item => {
|
||||||
if (isBlock(item)) {
|
if (isBlock(item)) {
|
||||||
item.replaceWith(
|
item.replaceWith(this.createDefaultBlock([empty(item)]));
|
||||||
this.createDefaultBlock([empty(item)])
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
fixContainer(item, root);
|
fixContainer(item, root);
|
||||||
item.replaceWith(empty(item));
|
item.replaceWith(empty(item));
|
||||||
|
|
@ -3498,7 +3496,11 @@ class Squire
|
||||||
|
|
||||||
increaseQuoteLevel(range) {
|
increaseQuoteLevel(range) {
|
||||||
return this.modifyBlocks(
|
return this.modifyBlocks(
|
||||||
frag => createElement('BLOCKQUOTE', null, [frag]),
|
frag => createElement(
|
||||||
|
"BLOCKQUOTE",
|
||||||
|
null,
|
||||||
|
[frag]
|
||||||
|
),
|
||||||
range
|
range
|
||||||
).focus();
|
).focus();
|
||||||
}
|
}
|
||||||
|
|
@ -3506,9 +3508,11 @@ class Squire
|
||||||
decreaseQuoteLevel(range) {
|
decreaseQuoteLevel(range) {
|
||||||
return this.modifyBlocks(
|
return this.modifyBlocks(
|
||||||
frag => {
|
frag => {
|
||||||
Array.prototype.filter.call(frag.querySelectorAll('blockquote'), el =>
|
Array.prototype.filter.call(frag.querySelectorAll("blockquote"), el =>
|
||||||
!getClosest(el.parentNode, frag, 'BLOCKQUOTE')
|
!getClosest(el.parentNode, frag, "BLOCKQUOTE")
|
||||||
).forEach(el => el.replaceWith(empty(el)));
|
).forEach(el =>
|
||||||
|
el.replaceWith(empty(el))
|
||||||
|
);
|
||||||
return frag;
|
return frag;
|
||||||
},
|
},
|
||||||
range
|
range
|
||||||
|
|
@ -3526,59 +3530,60 @@ class Squire
|
||||||
let walker = getBlockWalker(frag, root);
|
let walker = getBlockWalker(frag, root);
|
||||||
let node;
|
let node;
|
||||||
// 1. Extract inline content; drop all blocks and contains.
|
// 1. Extract inline content; drop all blocks and contains.
|
||||||
while ((node = walker.nextNode())) {
|
while (node = walker.nextNode()) {
|
||||||
// 2. Replace <br> with \n in content
|
// 2. Replace <br> with \n in content
|
||||||
node.querySelectorAll('BR').forEach(br => {
|
node.querySelectorAll("BR").forEach(br => {
|
||||||
if (!isLineBreak(br, false)) {
|
if (!isLineBreak(br, false)) {
|
||||||
detach(br);
|
detach(br);
|
||||||
} else {
|
} else {
|
||||||
br.replaceWith(doc.createTextNode('\n'));
|
br.replaceWith(doc.createTextNode("\n"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 3. Remove <code>; its format clashes with <pre>
|
// 3. Remove <code>; its format clashes with <pre>
|
||||||
node.querySelectorAll('CODE').forEach(el => detach(el));
|
node.querySelectorAll("CODE").forEach(el => detach(el));
|
||||||
if (output.childNodes.length) {
|
if (output.childNodes.length) {
|
||||||
output.append(doc.createTextNode('\n'));
|
output.append(doc.createTextNode("\n"));
|
||||||
}
|
}
|
||||||
output.append(empty(node));
|
output.append(empty(node));
|
||||||
}
|
}
|
||||||
// 4. Replace nbsp with regular sp
|
// 4. Replace nbsp with regular sp
|
||||||
walker = createTreeWalker(output, SHOW_TEXT);
|
walker = createTreeWalker(output, SHOW_TEXT);
|
||||||
while ((node = walker.nextNode())) {
|
while (node = walker.nextNode()) {
|
||||||
node.data = node.data.replace(NBSP, ' '); // nbsp -> sp
|
node.data = node.data.replace(NBSP, ' '); // nbsp -> sp
|
||||||
}
|
}
|
||||||
output.normalize();
|
output.normalize();
|
||||||
return fixCursor(createElement('PRE',
|
return fixCursor(
|
||||||
null, [
|
createElement("PRE", null, [
|
||||||
output
|
output
|
||||||
]));
|
])
|
||||||
|
);
|
||||||
}, range).focus();
|
}, range).focus();
|
||||||
}
|
}
|
||||||
return this.changeFormat({ tag: 'CODE' }, null, range);
|
return this.changeFormat({ tag: "CODE" }, null, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeCode() {
|
removeCode() {
|
||||||
let range = this.getSelection();
|
let range = this.getSelection();
|
||||||
let ancestor = range.commonAncestorContainer;
|
let ancestor = range.commonAncestorContainer;
|
||||||
let inPre = getClosest(ancestor, this._root, 'PRE');
|
let inPre = getClosest(ancestor, this._root, "PRE");
|
||||||
if (inPre) {
|
if (inPre) {
|
||||||
return this.modifyBlocks(frag => {
|
return this.modifyBlocks(frag => {
|
||||||
let root = this._root;
|
let root = this._root;
|
||||||
let pres = frag.querySelectorAll('PRE');
|
let pres = frag.querySelectorAll("PRE");
|
||||||
let l = pres.length;
|
let l = pres.length;
|
||||||
let pre, walker, node, value, contents, index;
|
let pre, walker, node, value, contents, index;
|
||||||
while (l--) {
|
while (l--) {
|
||||||
pre = pres[l];
|
pre = pres[l];
|
||||||
walker = createTreeWalker(pre, SHOW_TEXT);
|
walker = createTreeWalker(pre, SHOW_TEXT);
|
||||||
while ((node = walker.nextNode())) {
|
while (node = walker.nextNode()) {
|
||||||
value = node.data;
|
value = node.data;
|
||||||
value = value.replace(/ (?=)/g, NBSP); // sp -> nbsp
|
value = value.replace(/ (?=)/g, NBSP); // sp -> nbsp
|
||||||
contents = doc.createDocumentFragment();
|
contents = doc.createDocumentFragment();
|
||||||
while ((index = value.indexOf('\n')) > -1) {
|
while ((index = value.indexOf("\n")) > -1) {
|
||||||
contents.append(
|
contents.append(
|
||||||
doc.createTextNode(value.slice(0, index))
|
doc.createTextNode(value.slice(0, index))
|
||||||
);
|
);
|
||||||
contents.append(createElement('BR'));
|
contents.append(createElement("BR"));
|
||||||
value = value.slice(index + 1);
|
value = value.slice(index + 1);
|
||||||
}
|
}
|
||||||
node.before(contents);
|
node.before(contents);
|
||||||
|
|
@ -3590,11 +3595,11 @@ class Squire
|
||||||
return frag;
|
return frag;
|
||||||
}, range).focus();
|
}, range).focus();
|
||||||
}
|
}
|
||||||
return this.changeFormat(null, { tag: 'CODE' }, range);
|
return this.changeFormat(null, { tag: "CODE" }, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleCode() {
|
toggleCode() {
|
||||||
return (this.hasFormat('PRE') || this.hasFormat('CODE'))
|
return (this.hasFormat("PRE") || this.hasFormat("CODE"))
|
||||||
? this.removeCode()
|
? this.removeCode()
|
||||||
: this.code();
|
: this.code();
|
||||||
}
|
}
|
||||||
|
|
@ -3611,7 +3616,7 @@ class Squire
|
||||||
// --- Formatting ---
|
// --- Formatting ---
|
||||||
|
|
||||||
setStyle(style) {
|
setStyle(style) {
|
||||||
this.setAttribute('style', style);
|
this.setAttribute("style", style);
|
||||||
}
|
}
|
||||||
|
|
||||||
setAttribute(name, value) {
|
setAttribute(name, value) {
|
||||||
|
|
@ -3619,7 +3624,7 @@ class Squire
|
||||||
let start = range?.startContainer || {};
|
let start = range?.startContainer || {};
|
||||||
let end = range ? range.endContainer : 0;
|
let end = range ? range.endContainer : 0;
|
||||||
// When the selection is all the text inside an element, set style on the element itself
|
// When the selection is all the text inside an element, set style on the element itself
|
||||||
if ('dir' == name || (isTextNode(start) && 0 === range.startOffset && start === end && end.length === range.endOffset)) {
|
if ("dir" == name || (isTextNode(start) && 0 === range.startOffset && start === end && end.length === range.endOffset)) {
|
||||||
this.saveUndoState(range);
|
this.saveUndoState(range);
|
||||||
setAttributes(start.parentNode, {[name]: value});
|
setAttributes(start.parentNode, {[name]: value});
|
||||||
this.setRange(range);
|
this.setRange(range);
|
||||||
|
|
@ -3627,7 +3632,7 @@ class Squire
|
||||||
// Else create a span element
|
// Else create a span element
|
||||||
else {
|
else {
|
||||||
this.changeFormat({
|
this.changeFormat({
|
||||||
tag: 'SPAN',
|
tag: "SPAN",
|
||||||
attributes: {[name]: value}
|
attributes: {[name]: value}
|
||||||
}, null, range);
|
}, null, range);
|
||||||
}
|
}
|
||||||
|
|
@ -3638,9 +3643,9 @@ class Squire
|
||||||
|
|
||||||
changeIndentationLevel(direction) {
|
changeIndentationLevel(direction) {
|
||||||
let parent = this.getSelectionClosest('UL,OL,BLOCKQUOTE');
|
let parent = this.getSelectionClosest('UL,OL,BLOCKQUOTE');
|
||||||
if (parent || 'increase' === direction) {
|
if (parent || "increase" === direction) {
|
||||||
let method = (!parent || 'BLOCKQUOTE' === parent.nodeName) ? 'Quote' : 'List';
|
let method = (!parent || "BLOCKQUOTE" === parent.nodeName) ? "Quote" : "List";
|
||||||
this[direction + method + 'Level']();
|
this[direction + method + "Level"]();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue