Bug 1315440 - Follow-up: Fix advance edit when shortened data URIs are used. r=mkmelin

This commit is contained in:
Jorg K 2016-11-09 23:56:29 +01:00
Родитель 58abf93dce
Коммит 9d381b420b
3 изменённых файлов: 81 добавлений и 86 удалений

Просмотреть файл

@ -30,6 +30,8 @@ var gOriginalSrc = "";
var gHaveDocumentUrl = false;
var gTimerID;
var gValidateTab;
var gFullDataURI;
var gListenerAttached = false;
// These must correspond to values in EditorDialog.css for each theme
// (unfortunately, setting "style" attribute here doesn't work!)
@ -68,13 +70,52 @@ function ImageStartup()
gDialog.OkButton = document.documentElement.getButton("accept");
}
function onCopyOrCut(event) {
// Put the original data URI onto the clipboard in case the value
// is a shortened data URI.
let startPos = gDialog.srcInput.selectionStart;
if (startPos == undefined)
return;
let endPos = gDialog.srcInput.selectionEnd;
let selection = gDialog.srcInput.value.substring(startPos, endPos).trim();
// Test that a) the user selected the whole value,
// b) the value is a data URI,
// c) it contains the ellipsis we added. Otherwise it could be
// a new value that the user pasted in.
if (selection == gDialog.srcInput.value.trim() &&
/^data:/i.test(selection) && selection.includes("…")) {
event.clipboardData.setData("text/plain", gFullDataURI);
if (event.type == "cut") {
// We have to cut the selection manually. Since we tested that
// everything was selected, we can just reset the field.
gDialog.srcInput.value = "";
}
event.preventDefault();
}
}
// Set dialog widgets with attribute data
// We get them from globalElement copy so this can be used
// by AdvancedEdit(), which is shared by all property dialogs
function InitImage()
{
// Set the controls to the image's attributes
gDialog.srcInput.value = globalElement.getAttribute("src");
var src = globalElement.getAttribute("src");
// Shorten data URIs for display.
gDialog.srcInput.value = src.replace(/(data:[^;]*;base64,)(.*)/i,
function(match, nonDataPart, dataPart) {
if (!gListenerAttached) {
gDialog.srcInput.addEventListener("copy", onCopyOrCut);
gDialog.srcInput.addEventListener("cut", onCopyOrCut);
gListenerAttached = true;
}
gDialog.srcInput.setAttribute("tooltip", "shortenedDataURI");
gFullDataURI = src;
return nonDataPart + dataPart.substring(0, 5) + "…" +
dataPart.substring(dataPart.length - 30);
});
// Set "Relativize" checkbox according to current URL state
SetRelativeCheckbox();
@ -278,6 +319,11 @@ function LoadPreviewImage()
var imageSrc = TrimString(gDialog.srcInput.value);
if (!imageSrc)
return;
if (/^data:/i.test(imageSrc) && imageSrc.includes("…"))
{
// Restore URIs from the original.
imageSrc = gFullDataURI;
}
try {
// Remove the image URL from image cache so it loads fresh
@ -458,16 +504,25 @@ function ValidateImage()
// We must convert to "file:///" or "http://" format else image doesn't load!
let src = gDialog.srcInput.value.trim();
var checkbox = document.getElementById("MakeRelativeCheckbox");
try
{
if (checkbox && !checkbox.checked)
{
src = Services.uriFixup.createFixupURI(src, Components.interfaces.nsIURIFixup.FIXUP_FLAG_NONE).spec;
}
} catch (e) { }
globalElement.setAttribute("src", src);
if (/^data:/i.test(src) && src.includes("…"))
{
// Restore shortened URIs from the original.
src = gFullDataURI;
}
else
{
var checkbox = document.getElementById("MakeRelativeCheckbox");
try
{
if (checkbox && !checkbox.checked)
{
src = Services.uriFixup.createFixupURI(src, Components.interfaces.nsIURIFixup.FIXUP_FLAG_NONE).spec;
}
} catch (e) { }
globalElement.setAttribute("src", src);
}
let title = gDialog.titleInput.value.trim();
if (title)

Просмотреть файл

@ -23,14 +23,15 @@ function Startup()
// 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)
{
gDialog.srcInput.addEventListener("paste", onPaste);
selection = (selection.replace(/<body[^>]*>/,"")).replace(/<\/body>/,"");
// Shorten data URIs for display.
@ -47,12 +48,12 @@ function Startup()
function replaceDataURIs(input)
{
return input.replace(/(src|href)(="data:[^;]*;base64,)([^"]+)/gi,
function(match, attr, nonDataPart, dataPart) {
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 attr + nonDataPart + gShortDataStrings.get(dataPart);
return nonDataPart + gShortDataStrings.get(dataPart);
}
let l = 5;
@ -68,23 +69,16 @@ function replaceDataURIs(input)
// 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", onCopy);
gDialog.srcInput.addEventListener("cut", onCut);
gDialog.srcInput.addEventListener("copy", onCopyOrCut);
gDialog.srcInput.addEventListener("cut", onCopyOrCut);
gListenerAttached = true;
}
return attr + nonDataPart + key;
return nonDataPart + key;
});
}
function onCut(event) {
commonCopyCut(event, true);
}
function onCopy(event) {
commonCopyCut(event, false);
}
function commonCopyCut(event, isCut)
function onCopyOrCut(event)
{
let startPos = gDialog.srcInput.selectionStart;
if (startPos == undefined)
@ -93,14 +87,14 @@ function commonCopyCut(event, isCut)
let clipboard = gDialog.srcInput.value.substring(startPos, endPos);
// Add back the original data URIs we stashed away earlier.
clipboard = clipboard.replace(/(data:[^;]*;base64,)([^"]+)/gi,
clipboard = clipboard.replace(/(data:[^;]*;base64,)([^"' >]+)/gi,
function(match, nonDataPart, key) {
if (!gFullDataStrings.has(key))
return match; // user changed data URI
return nonDataPart + gFullDataStrings.get(key);
});
event.clipboardData.setData("text/plain", clipboard);
if (isCut) {
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);
@ -131,11 +125,11 @@ function onAccept()
return false;
// Add back the original data URIs we stashed away earlier.
html = html.replace(/(src|href)(="data:[^;]*;base64,)([^"]+)/gi,
function(match, attr, nonDataPart, key) {
html = html.replace(/(data:[^;]*;base64,)([^"' >]+)/gi,
function(match, nonDataPart, key) {
if (!gFullDataStrings.has(key))
return match; // user changed data URI
return attr + nonDataPart + gFullDataStrings.get(key);
return nonDataPart + gFullDataStrings.get(key);
});
try {

Просмотреть файл

@ -48,19 +48,8 @@
}
}
}
addEventListener("load", OnLoadOverlay, false);
function OnAcceptOverlay()
{
// Restore data URI. We need to restore if there is a data URI and we
// find the ellipsis we added. The user could have pasted a full new
// data URI which we don't want to lose.
if (/^data:/i.test(gMsgCompInputElement.value.trim()) &&
gMsgCompInputElement.value.includes("...")) {
gMsgCompInputElement.value = gMsgCompPrevInputValue;
}
}
addEventListener("dialogaccept", OnAcceptOverlay, false);
addEventListener("load", OnLoadOverlay, false);
function SetAttachCheckbox()
{
@ -114,49 +103,6 @@
attach = (mozDoNotSend != "true");
gMsgCompAttachSourceElement.checked = attach;
// Shorten data URIs for display. Let's not use an ellipsis character
// since this will look funny in the advanced edit dialogue.
gMsgCompInputElement.value = gMsgCompInputElement
.value.replace(/(data:[^;]*;base64,)(.*)/i,
function(match, nonDataPart, dataPart) {
gMsgCompInputElement.addEventListener("copy", onCopy);
gMsgCompInputElement.addEventListener("cut", onCut);
gMsgCompInputElement.setAttribute("tooltip", "shortenedDataURI");
return nonDataPart + dataPart.substring(0, 5) + "..." +
dataPart.substring(dataPart.length - 30);
});
}
}
function onCut(event) {
commonCopyCut(event, true);
}
function onCopy(event) {
commonCopyCut(event, false);
}
function commonCopyCut(event, isCut) {
// Put the original data URI onto the clipboard in case the value
// is a shortened data URI.
let startPos = gMsgCompInputElement.selectionStart;
if (startPos == undefined)
return;
let endPos = gMsgCompInputElement.selectionEnd;
let selection = gMsgCompInputElement.value.substring(startPos, endPos).trim();
// Test that a) the user selected the whole value,
// b) the value is a data URI,
// c) it contains the ellipsis we added. Otherwise it could be
// a new value that the user pasted in.
if (selection == gMsgCompInputElement.value.trim() &&
/^data:/i.test(selection) && selection.includes("...")) {
event.clipboardData.setData("text/plain", gMsgCompPrevInputValue);
if (isCut) {
// We have to cut the selection manually. Since we tested that
// everything was selected, we can just reset the field.
gMsgCompInputElement.value = "";
}
event.preventDefault();
}
}