diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/mail/components/compose/content/dialogs/EdInsSrc.js | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | comm/mail/components/compose/content/dialogs/EdInsSrc.js | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/comm/mail/components/compose/content/dialogs/EdInsSrc.js b/comm/mail/components/compose/content/dialogs/EdInsSrc.js new file mode 100644 index 0000000000..d00f119ed7 --- /dev/null +++ b/comm/mail/components/compose/content/dialogs/EdInsSrc.js @@ -0,0 +1,162 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Insert Source HTML dialog */ + +/* import-globals-from ../editorUtilities.js */ +/* import-globals-from EdDialogCommon.js */ + +var gFullDataStrings = new Map(); +var gShortDataStrings = new Map(); +var gListenerAttached = false; + +window.addEventListener("load", Startup); + +document.addEventListener("dialogaccept", onAccept); +document.addEventListener("dialogcancel", onCancel); + +function Startup() { + let editor = GetCurrentEditor(); + if (!editor) { + window.close(); + return; + } + + document + .querySelector("dialog") + .getButton("accept") + .removeAttribute("default"); + + // Create dialog object to store controls for easy access + gDialog.srcInput = document.getElementById("srcInput"); + + // Attach a paste listener so we can detect pasted data URIs we need to shorten. + gDialog.srcInput.addEventListener("paste", onPaste); + + let selection; + try { + selection = editor.outputToString( + "text/html", + kOutputFormatted | kOutputSelectionOnly | kOutputWrap + ); + } catch (e) {} + if (selection) { + selection = selection.replace(/<body[^>]*>/, "").replace(/<\/body>/, ""); + + // Shorten data URIs for display. + selection = replaceDataURIs(selection); + + if (selection) { + gDialog.srcInput.value = selection; + } + } + // Set initial focus + gDialog.srcInput.focus(); + SetWindowLocation(); +} + +function replaceDataURIs(input) { + return input.replace( + /(data:.+;base64,)([^"' >]+)/gi, + function (match, nonDataPart, dataPart) { + if (gShortDataStrings.has(dataPart)) { + // We found the exact same data URI, just return the shortened URI. + return nonDataPart + gShortDataStrings.get(dataPart); + } + + let l = 5; + let key; + // Normally we insert the ellipsis after five characters but if it's not unique + // we include more data. + do { + key = + dataPart.substr(0, l) + "…" + dataPart.substr(dataPart.length - 10); + l++; + } while (gFullDataStrings.has(key) && l < dataPart.length - 10); + gFullDataStrings.set(key, dataPart); + gShortDataStrings.set(dataPart, key); + + // Attach listeners. In case anyone copies/cuts from the HTML window, + // we want to restore the data URI on the clipboard. + if (!gListenerAttached) { + gDialog.srcInput.addEventListener("copy", onCopyOrCut); + gDialog.srcInput.addEventListener("cut", onCopyOrCut); + gListenerAttached = true; + } + + return nonDataPart + key; + } + ); +} + +function onCopyOrCut(event) { + let startPos = gDialog.srcInput.selectionStart; + if (startPos == undefined) { + return; + } + let endPos = gDialog.srcInput.selectionEnd; + let clipboard = gDialog.srcInput.value.substring(startPos, endPos); + + // Add back the original data URIs we stashed away earlier. + clipboard = clipboard.replace( + /(data:.+;base64,)([^"' >]+)/gi, + function (match, nonDataPart, key) { + if (!gFullDataStrings.has(key)) { + // User changed data URI. + return match; + } + return nonDataPart + gFullDataStrings.get(key); + } + ); + event.clipboardData.setData("text/plain", clipboard); + if (event.type == "cut") { + // We have to cut the selection manually. + gDialog.srcInput.value = + gDialog.srcInput.value.substr(0, startPos) + + gDialog.srcInput.value.substr(endPos); + } + event.preventDefault(); +} + +function onPaste(event) { + let startPos = gDialog.srcInput.selectionStart; + if (startPos == undefined) { + return; + } + let endPos = gDialog.srcInput.selectionEnd; + let clipboard = event.clipboardData.getData("text/plain"); + + // We do out own paste by replacing the selection with the pre-processed + // clipboard data. + gDialog.srcInput.value = + gDialog.srcInput.value.substr(0, startPos) + + replaceDataURIs(clipboard) + + gDialog.srcInput.value.substr(endPos); + event.preventDefault(); +} + +function onAccept(event) { + let html = gDialog.srcInput.value; + if (!html) { + event.preventDefault(); + return; + } + + // Add back the original data URIs we stashed away earlier. + html = html.replace( + /(data:.+;base64,)([^"' >]+)/gi, + function (match, nonDataPart, key) { + if (!gFullDataStrings.has(key)) { + // User changed data URI. + return match; + } + return nonDataPart + gFullDataStrings.get(key); + } + ); + + try { + GetCurrentEditor().insertHTML(html); + } catch (e) {} + SaveWindowLocation(); +} |