Bug 1297633 - Fixed editing of SVG elements in Inspector. r=jdescottes

Differential Revision: https://phabricator.services.mozilla.com/D102844
This commit is contained in:
Sebastian Zartner 2021-02-10 20:45:44 +00:00
Родитель a5bf84f203
Коммит c1b72d4f7a
4 изменённых файлов: 110 добавлений и 8 удалений

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

@ -1767,7 +1767,9 @@ MarkupView.prototype = {
this.cancelReselectOnRemoved();
// Get the removedNode index in its parent node to reselect the right node.
const isHTMLTag = removedNode.tagName.toLowerCase() === "html";
const isRootElement = ["html", "svg"].includes(
removedNode.tagName.toLowerCase()
);
const oldContainer = this.getContainer(removedNode);
const parentContainer = this.getContainer(removedNode.parentNode());
const childIndex = parentContainer
@ -1781,7 +1783,7 @@ MarkupView.prototype = {
mutation.removed && mutation.removed.some(n => n === removedNode);
if (
mutation.type === "childList" &&
(containsRemovedNode || isHTMLTag)
(containsRemovedNode || isRootElement)
) {
isNodeRemovalMutation = true;
break;
@ -1798,7 +1800,7 @@ MarkupView.prototype = {
// selection.
if (
this.inspector.selection.nodeFront === parentContainer.node ||
(this.inspector.selection.nodeFront === removedNode && isHTMLTag)
(this.inspector.selection.nodeFront === removedNode && isRootElement)
) {
const childContainers = parentContainer.getChildContainers();
if (childContainers?.[childIndex]) {

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

@ -166,6 +166,7 @@ skip-if = verify
[browser_markup_html_edit_01.js]
[browser_markup_html_edit_02.js]
[browser_markup_html_edit_03.js]
[browser_markup_html_edit_04.js]
[browser_markup_html_edit_undo-redo.js]
[browser_markup_image_tooltip.js]
[browser_markup_image_tooltip_mutations.js]

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

@ -0,0 +1,97 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that outerHTML editing keybindings work as expected and that the <svg>
// root element can be edited correctly.
const TEST_URL =
"data:image/svg+xml," +
'<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">' +
'<circle cx="50" cy="50" r="50"/>' +
"</svg>";
requestLongerTimeout(2);
add_task(async function() {
const { inspector, testActor } = await openInspectorForURL(TEST_URL);
inspector.markup._frame.focus();
info("Check that editing the <svg> element works like other nodes");
await testDocumentElement(inspector, testActor);
info("Check (again) that editing the <svg> element works like other nodes");
await testDocumentElement2(inspector, testActor);
});
async function testDocumentElement(inspector, testActor) {
const currentDocElementOuterHTML = await testActor.eval(
"document.documentElement.outerHTML"
);
const docElementSVG =
'<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">' +
'<rect x="10" y="10" width="180" height="180"/>' +
"</svg>";
const docElementFront = await inspector.markup.walker.documentElement();
const onReselected = inspector.markup.once("reselectedonremoved");
await inspector.markup.updateNodeOuterHTML(
docElementFront,
docElementSVG,
currentDocElementOuterHTML
);
await onReselected;
is(
await testActor.getAttribute("svg", "width"),
"200",
"<svg> width has been updated"
);
is(
await testActor.getAttribute("svg", "height"),
"200",
"<svg> height has been updated"
);
is(
await testActor.getProperty("svg", "outerHTML"),
docElementSVG,
"<svg> markup has been updated"
);
}
async function testDocumentElement2(inspector, testActor) {
const currentDocElementOuterHTML = await testActor.eval(
"document.documentElement.outerHTML"
);
const docElementSVG =
'<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">' +
'<ellipse cx="150" cy="150" rx="150" ry="100"/>' +
"</svg>";
const docElementFront = await inspector.markup.walker.documentElement();
const onReselected = inspector.markup.once("reselectedonremoved");
inspector.markup.updateNodeOuterHTML(
docElementFront,
docElementSVG,
currentDocElementOuterHTML
);
await onReselected;
is(
await testActor.getAttribute("svg", "width"),
"300",
"<svg> width has been updated"
);
is(
await testActor.getAttribute("svg", "height"),
"300",
"<svg> height has been updated"
);
is(
await testActor.getProperty("svg", "outerHTML"),
docElementSVG,
"<svg> markup has been updated"
);
}

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

@ -1708,7 +1708,9 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
// created nodes can be adopted into rawNode.parentNode.
parser = new win.DOMParser();
}
const parsedDOM = parser.parseFromString(value, "text/html");
const mimeType = rawNode.tagName === "svg" ? "image/svg+xml" : "text/html";
const parsedDOM = parser.parseFromString(value, mimeType);
const parentNode = rawNode.parentNode;
// Special case for head and body. Setting document.body.outerHTML
@ -1730,8 +1732,8 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
rawNode.outerHTML = value;
}
} else if (node.isDocumentElement()) {
// Unable to set outerHTML on the document element. Fall back by
// setting attributes manually, then replace the body and head elements.
// Unable to set outerHTML on the document element. Fall back by
// setting attributes manually. Then replace all the child nodes.
const finalAttributeModifications = [];
const attributeModifications = {};
for (const attribute of rawNode.attributes) {
@ -1747,8 +1749,8 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
});
}
node.modifyAttributes(finalAttributeModifications);
rawNode.replaceChild(parsedDOM.head, rawNode.querySelector("head"));
rawNode.replaceChild(parsedDOM.body, rawNode.querySelector("body"));
rawNode.replaceChildren(...parsedDOM.firstElementChild.childNodes);
} else {
// eslint-disable-next-line no-unsanitized/property
rawNode.outerHTML = value;