Bug 1731612 - [devtools] Display layer name in the rule view. r=jdescottes.

Differential Revision: https://phabricator.services.mozilla.com/D136620
This commit is contained in:
Nicolas Chevobbe 2022-01-26 13:01:47 +00:00
Родитель b1eb7ecce6
Коммит 8d7ccd7eda
7 изменённых файлов: 152 добавлений и 6 удалений

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

@ -154,6 +154,10 @@ class StyleRuleFront extends FrontClassWithSpec(styleRuleSpec) {
};
}
get layerName() {
return this._form.layerName;
}
_clearOriginalLocation() {
this._originalLocation = null;
}

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

@ -39,6 +39,8 @@ support-files =
doc_visited.html
doc_visited_in_media_query.html
doc_visited_with_style_attribute.html
doc_imported_anonymous_layer.css
doc_imported_named_layer.css
head.js
sjs_imported_stylesheet_edit.sjs
!/devtools/client/inspector/test/head.js
@ -106,6 +108,7 @@ skip-if = os == 'linux' # focusEditableField times out consistently on linux.
[browser_rules_keyframes-rule_01.js]
[browser_rules_keyframes-rule_02.js]
[browser_rules_keyframeLineNumbers.js]
[browser_rules_layer.js]
[browser_rules_lineNumbers.js]
[browser_rules_livepreview.js]
[browser_rules_mark_overridden_01.js]

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

@ -0,0 +1,81 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the rule-view content is correct when the page defines layers.
const TEST_URI = `
<style type="text/css">
@import url(${URL_ROOT_COM_SSL}doc_imported_anonymous_layer.css) layer;
@import url(${URL_ROOT_COM_SSL}doc_imported_named_layer.css) layer(importedLayer);
@layer myLayer {
h1 {
background-color: tomato;
color: lightgreen;
}
}
@layer {
h1 {
color: green;
font-variant: small-caps
}
}
</style>
<h1>Hello @layer!</h1>
`;
add_task(async function() {
await addTab(
"https://example.com/document-builder.sjs?html=" +
encodeURIComponent(TEST_URI)
);
const { inspector, view } = await openRuleView();
await selectNode("h1", inspector);
is(
getRuleViewParentDataTextByIndex(view, 1),
"@layer",
"text at index 1 contains anonymous layer."
);
is(
getRuleViewParentDataTextByIndex(view, 2),
"@layer myLayer",
"text at index 2 contains named layer."
);
is(
getRuleViewParentDataTextByIndex(view, 3),
"@layer importedLayer @media screen",
"text at index 3 contains imported stylesheet named layer."
);
// XXX: This is highlighting an issue with nested layers/media queries, where only the
// last item is displayed. This should be fixed in Bug 1751417, and this test case should
// then have `@layer importedLayer @media screen @layer in-imported-stylesheet`
is(
getRuleViewParentDataTextByIndex(view, 4),
"@layer in-imported-stylesheet",
"text at index 4 only contains the last layer it's in."
);
is(
getRuleViewParentDataTextByIndex(view, 5),
"@layer",
"text at index 5 contains imported stylesheet anonymous layer."
);
});
function getRuleViewParentDataElementByIndex(view, ruleIndex) {
return view.styleDocument.querySelector(
`.ruleview-rule:nth-of-type(${ruleIndex + 1}) .ruleview-rule-parent-data`
);
}
function getRuleViewParentDataTextByIndex(view, ruleIndex) {
return getRuleViewParentDataElementByIndex(view, ruleIndex)?.textContent;
}

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

@ -0,0 +1,4 @@
h1 {
color:cyan;
outline: 10px solid cyan;
}

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

@ -0,0 +1,12 @@
@media screen {
h1 {
color:tomato;
border: 10px dotted currentColor;
}
@layer in-imported-stylesheet {
h1 {
color: purple;
}
}
}

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

@ -135,14 +135,39 @@ RuleEditor.prototype = {
this.updateSourceLink();
if (this.rule.mediaText) {
const text = `@media ${this.rule.mediaText}`;
const hasMediaText = this.rule.mediaText;
const hasLayer = typeof this.rule.domRule.layerName !== "undefined";
if (hasMediaText || hasLayer) {
const parts = [];
if (hasLayer) {
// The layer can be anonymous, in such case its name is an empty string
parts.push(
`@layer${
this.rule.domRule.layerName ? " " + this.rule.domRule.layerName : ""
}`
);
}
if (hasMediaText) {
parts.push(`@media ${this.rule.mediaText}`);
}
// For now, we can only have at most a layer and a media query (if the rule stylesheet
// was imported with a layer name and the parent rule is a media query) so we can get
// await with displaying them one after the other.
// This might change with Bug 1751417 where we'll show the whole tree of media/layer
const text = parts.join(" ");
// We force the string to be LTR in CSS, but as @ is listed as having neutral
// directionality and starting a string with this char would default to RTL for that
// character (when in RTL locale), and then the next char (`m` of `media`, or `l` of `layer`)
// would start a new LTR visual run, since it is strongly LTR (through `direction` CSS property).
// To have the `@` properly displayed, we force LTR with \u202A
const title = `${text.replaceAll("@", "\u202A@")}`;
createChild(this.element, "span", {
class: "ruleview-rule-parent-data theme-link",
// We force the string to be LTR in CSS, but for some reason, the `@` char is seen
// as not part of the string in the tooltip, and is displayed "at the end" of the
// string in RTL locales. To workaround this, we force LTR with \u202D
title: `\u202A${text}`,
title,
textContent: text,
});
}

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

@ -61,6 +61,8 @@ loader.lazyRequireGetter(
true
);
loader.lazyRequireGetter(this, "ChromeUtils");
const XHTML_NS = "http://www.w3.org/1999/xhtml";
const SUPPORTED_RULE_TYPES = [
@ -330,6 +332,13 @@ const StyleRuleActor = protocol.ActorClassWithSpec(styleRuleSpec, {
form.media.push(this.rawRule.parentRule.media.item(i));
}
}
if (
ChromeUtils.getClassName(this.rawRule.parentRule) ===
"CSSLayerBlockRule"
) {
form.layerName = this.rawRule.parentRule.name;
}
}
if (this._parentSheet) {
if (this.pageStyle.hasStyleSheetWatcherSupport) {
@ -341,6 +350,14 @@ const StyleRuleActor = protocol.ActorClassWithSpec(styleRuleSpec, {
this._parentSheet
).actorID;
}
// Only override layerName if it wasn't set from the parent rule
if (
typeof this._parentSheet.ownerRule?.layerName !== "undefined" &&
form.layerName == undefined
) {
form.layerName = this._parentSheet.ownerRule.layerName;
}
}
// One tricky thing here is that other methods in this actor must