Squire paste image working again.

https://github.com/the-djmaze/snappymail/issues/1389#issuecomment-2389678680
This commit is contained in:
the-djmaze 2024-10-06 17:32:47 +02:00
parent fafaaf21b1
commit d6ef5ff70a
3 changed files with 112 additions and 79 deletions

View file

@ -360,7 +360,7 @@ export const
}); });
*/ */
isMsg && [...tmpl.content.querySelectorAll('*')].forEach(oElement => { [...tmpl.content.querySelectorAll('*')].forEach(oElement => {
const name = oElement.tagName, const name = oElement.tagName,
oStyle = oElement.style; oStyle = oElement.style;
@ -485,71 +485,73 @@ export const
*/ */
let skipStyle = false; let skipStyle = false;
value = delAttribute('src'); if (isMsg) {
if (value) { value = isMsg && delAttribute('src');
if ('IMG' === name) { if (value) {
oElement.loading = 'lazy'; if ('IMG' === name) {
let attachment; oElement.loading = 'lazy';
if (value.startsWith('cid:')) let attachment;
{ if (value.startsWith('cid:'))
value = value.slice(4); {
setAttribute('data-x-src-cid', value); value = value.slice(4);
attachment = findAttachmentByCid(value); setAttribute('data-x-src-cid', value);
if (attachment?.download) { attachment = findAttachmentByCid(value);
oElement.src = attachment.linkPreview(); if (attachment?.download) {
oElement.title += ' ('+attachment.fileName+')'; oElement.src = attachment.linkPreview();
attachment.isInline(true); oElement.title += ' ('+attachment.fileName+')';
attachment.isLinked(true); attachment.isInline(true);
attachment.isLinked(true);
}
} }
} else if ((attachment = findLocationByCid(value)))
else if ((attachment = findLocationByCid(value))) {
{ if (attachment.download) {
if (attachment.download) { oElement.src = attachment.linkPreview();
oElement.src = attachment.linkPreview(); attachment.isLinked(true);
attachment.isLinked(true); }
} }
} else if (detectHiddenImages
else if (detectHiddenImages && ((oStyle.maxHeight && 3 > pInt(oStyle.maxHeight)) // TODO: issue with 'in'
&& ((oStyle.maxHeight && 3 > pInt(oStyle.maxHeight)) // TODO: issue with 'in' || (oStyle.maxWidth && 3 > pInt(oStyle.maxWidth)) // TODO: issue with 'in'
|| (oStyle.maxWidth && 3 > pInt(oStyle.maxWidth)) // TODO: issue with 'in' || (oStyle.width && 2 > pInt(oStyle.width))
|| (oStyle.width && 2 > pInt(oStyle.width)) || [
|| [ 'email.microsoftemail.com/open',
'email.microsoftemail.com/open', 'github.com/notifications/beacon/',
'github.com/notifications/beacon/', '/track/open', // mandrillapp.com list-manage.com
'/track/open', // mandrillapp.com list-manage.com 'google-analytics.com'
'google-analytics.com' ].filter(uri => value.toLowerCase().includes(uri)).length
].filter(uri => value.toLowerCase().includes(uri)).length )) {
)) { skipStyle = true;
skipStyle = true; oStyle.display = 'none';
oStyle.display = 'none'; // setAttribute('style', 'display:none');
// setAttribute('style', 'display:none'); setAttribute('data-x-src-hidden', value);
setAttribute('data-x-src-hidden', value); // result.tracking = true;
// result.tracking = true; }
} else if (httpre.test(value))
else if (httpre.test(value)) {
{ let src = stripTracking(value);
let src = stripTracking(value); if (src != value) {
if (src != value) { result.tracking = true;
result.tracking = true; setAttribute('data-x-src-tracking', value);
setAttribute('data-x-src-tracking', value); }
setAttribute('data-x-src', src);
result.hasExternals = true;
oElement.alt || (oElement.alt = src.replace(/^.+\/([^/?]+).*$/, '$1').slice(-20));
}
else if (value.startsWith('data:image/'))
{
oElement.src = value;
}
else
{
setAttribute('data-x-src-broken', value);
} }
setAttribute('data-x-src', src);
result.hasExternals = true;
oElement.alt || (oElement.alt = src.replace(/^.+\/([^/?]+).*$/, '$1').slice(-20));
}
else if (value.startsWith('data:image/'))
{
oElement.src = value;
} }
else else
{ {
setAttribute('data-x-src-broken', value); setAttribute('data-x-src-broken', value);
} }
} }
else
{
setAttribute('data-x-src-broken', value);
}
} }
if (hasAttribute('background')) { if (hasAttribute('background')) {

View file

@ -386,6 +386,44 @@ class SquireUI
changes.redo.input.disabled = !e.detail.canRedo; changes.redo.input.disabled = !e.detail.canRedo;
}); });
squire.addEventListener('pasteImage', e => {
const items = e.detail.clipboardData.items;
let l = items.length;
while (l--) {
const item = items[l];
if (/^image\/(png|jpeg|webp)/.test(item.type)) {
let reader = new FileReader();
reader.onload = event => {
let img = createElement("img"),
canvas = createElement("canvas"),
ctx = canvas.getContext('2d');
img.onload = ()=>{
ctx.drawImage(img, 0, 0);
let width = img.width, height = img.height;
if (width > height) {
// Landscape
if (width > 1024) {
height = height * 1024 / width;
width = 1024;
}
} else if (height > 1024) {
// Portrait
width = width * 1024 / height;
height = 1024;
}
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
squire.insertHTML('<img alt="" style="width:100%;max-width:'+width+'px" src="'+canvas.toDataURL()+'">', true);
};
img.src = event.target.result;
}
reader.readAsDataURL(item.getAsFile());
break;
}
}
});
actions.font.fontSize.input.selectedIndex = actions.font.fontSize.defaultValueIndex; actions.font.fontSize.input.selectedIndex = actions.font.fontSize.defaultValueIndex;
// squire.addEventListener('focus', () => shortcuts.off()); // squire.addEventListener('focus', () => shortcuts.off());

View file

@ -58,7 +58,7 @@
var notWS = /[^ \t\r\n]/; var notWS = /[^ \t\r\n]/;
// source/node/Category.ts // 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(?:FRAME|MG|NPUT|NS)?|KBD|Q|R(?:P|T|UBY)|S(?:AMP|MALL|PAN|TR(?:IKE|ONG)|U[BP])?|TIME|U|VAR|WBR)$/; 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)$/;
var leafNodeNames = /* @__PURE__ */ new Set(["BR", "HR", "IMG"]); var leafNodeNames = /* @__PURE__ */ new Set(["BR", "HR", "IMG"]);
var UNKNOWN = 0; var UNKNOWN = 0;
var INLINE = 1; var INLINE = 1;
@ -198,7 +198,7 @@
// okay if data is 'undefined' here. // okay if data is 'undefined' here.
notWS.test(node.data) notWS.test(node.data)
); );
var isLineBreak = (br, isLBIfEmptyBlock) => { var isLineBreak = (br) => {
let block = br.parentNode; let block = br.parentNode;
while (isInline(block)) { while (isInline(block)) {
block = block.parentNode; block = block.parentNode;
@ -209,7 +209,7 @@
notWSTextNode notWSTextNode
); );
walker.currentNode = br; walker.currentNode = br;
return !!walker.nextNode() || isLBIfEmptyBlock && !walker.previousNode(); return !!walker.nextNode();
}; };
var removeZWS = (root, keepNode) => { var removeZWS = (root, keepNode) => {
const walker = createTreeWalker(root, SHOW_TEXT); const walker = createTreeWalker(root, SHOW_TEXT);
@ -267,7 +267,7 @@
textChild = prev; textChild = prev;
} }
startContainer = textChild; startContainer = textChild;
startOffset = textChild.data.length; startOffset = textChild.length;
} }
} }
break; break;
@ -279,7 +279,7 @@
while (!(endContainer instanceof Text)) { while (!(endContainer instanceof Text)) {
const child = endContainer.childNodes[endOffset - 1]; const child = endContainer.childNodes[endOffset - 1];
if (!child || isLeaf(child)) { if (!child || isLeaf(child)) {
if (child && child.nodeName === "BR" && !isLineBreak(child, false)) { if (child && child.nodeName === "BR" && !isLineBreak(child)) {
--endOffset; --endOffset;
continue; continue;
} }
@ -323,7 +323,7 @@
if (endContainer === endMax || endContainer === root) { if (endContainer === endMax || endContainer === root) {
break; break;
} }
if (endContainer.nodeType !== TEXT_NODE && endContainer.childNodes[endOffset] && endContainer.childNodes[endOffset].nodeName === "BR" && !isLineBreak(endContainer.childNodes[endOffset], false)) { if (endContainer.nodeType !== TEXT_NODE && endContainer.childNodes[endOffset] && endContainer.childNodes[endOffset].nodeName === "BR" && !isLineBreak(endContainer.childNodes[endOffset])) {
++endOffset; ++endOffset;
} }
if (endOffset !== getLength(endContainer)) { if (endOffset !== getLength(endContainer)) {
@ -529,30 +529,23 @@
if (isInline(child) && !child.firstChild) { if (isInline(child) && !child.firstChild) {
node.removeChild(child); node.removeChild(child);
} }
} else if (child instanceof Text && !child.data) { } else if (child instanceof Text && !child.length) {
node.removeChild(child); node.removeChild(child);
} }
} }
}; };
var cleanupBRs = (node) => { var cleanupBRs = (node) => {
const brs = node.querySelectorAll("BR"); const brs = node.querySelectorAll("BR:last-child");
const brBreaksLine = [];
let l = brs.length; let l = brs.length;
for (let i = 0; i < l; ++i) {
brBreaksLine[i] = isLineBreak(brs[i], false);
}
while (l--) { while (l--) {
const br = brs[l]; const br = brs[l];
const parent = br.parentNode; if (!isLineBreak(br)) {
if (parent) { br.remove();
if (!brBreaksLine[l]) {
detach(br);
}
} }
} }
}; };
var escapeHTML = (text) => { var escapeHTML = (text) => {
return text.split("&").join("&amp;").split("<").join("&lt;").split(">").join("&gt;").split('"').join("&quot;"); return text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");
}; };
// source/node/MergeSplit.ts // source/node/MergeSplit.ts
@ -980,7 +973,7 @@
const iterator = createTreeWalker(root, SHOW_ELEMENT_OR_TEXT); const iterator = createTreeWalker(root, SHOW_ELEMENT_OR_TEXT);
let afterNode = startContainer; let afterNode = startContainer;
let afterOffset = startOffset; let afterOffset = startOffset;
if (!(afterNode instanceof Text) || afterOffset === afterNode.data.length) { if (!(afterNode instanceof Text) || afterOffset === afterNode.length) {
afterNode = getAdjacentInlineNode(iterator, "nextNode", afterNode); afterNode = getAdjacentInlineNode(iterator, "nextNode", afterNode);
afterOffset = 0; afterOffset = 0;
} }
@ -993,7 +986,7 @@
afterNode || (startContainer instanceof Text ? startContainer : startContainer.childNodes[startOffset] || startContainer) afterNode || (startContainer instanceof Text ? startContainer : startContainer.childNodes[startOffset] || startContainer)
); );
if (beforeNode instanceof Text) { if (beforeNode instanceof Text) {
beforeOffset = beforeNode.data.length; beforeOffset = beforeNode.length;
} }
} }
let node = null; let node = null;
@ -3171,7 +3164,7 @@
nodeAfterSplit = child; nodeAfterSplit = child;
break; break;
} }
while (child && child instanceof Text && !child.data) { while (child && child instanceof Text && !child.length) {
next = child.nextSibling; next = child.nextSibling;
if (!next || next.nodeName === "BR") { if (!next || next.nodeName === "BR") {
break; break;
@ -3517,7 +3510,7 @@
const brBreaksLine = []; const brBreaksLine = [];
let l = nodes.length; let l = nodes.length;
for (let i = 0; i < l; ++i) { for (let i = 0; i < l; ++i) {
brBreaksLine[i] = isLineBreak(nodes[i], false); brBreaksLine[i] = isLineBreak(nodes[i]);
} }
while (l--) { while (l--) {
const br = nodes[l]; const br = nodes[l];