mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Squire paste image working again.
https://github.com/the-djmaze/snappymail/issues/1389#issuecomment-2389678680
This commit is contained in:
parent
fafaaf21b1
commit
d6ef5ff70a
3 changed files with 112 additions and 79 deletions
|
|
@ -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')) {
|
||||||
|
|
|
||||||
38
dev/External/SquireUI.js
vendored
38
dev/External/SquireUI.js
vendored
|
|
@ -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());
|
||||||
|
|
|
||||||
37
vendors/squire2/dist/squire-raw.js
vendored
37
vendors/squire2/dist/squire-raw.js
vendored
|
|
@ -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("&").split("<").join("<").split(">").join(">").split('"').join(""");
|
return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue