Bug 1581008: Add inactive CSS message for properties that are impossible to override. r=pbro,fluent-reviewers,flod

Depends on D45624

Differential Revision: https://phabricator.services.mozilla.com/D45625

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Daisuke Akatsuka 2019-09-26 01:53:40 +00:00
parent b591abf5e0
commit fa5347f328
6 changed files with 121 additions and 18 deletions

View File

@ -33,6 +33,8 @@ inactive-css-property-because-of-display = <strong>{ $property }</strong> has no
inactive-css-not-display-block-on-floated = The <strong>display</strong> value has been changed by the engine to <strong>block</strong> because the element is <strong>floated<strong>.
inactive-css-property-is-impossible-to-override-in-visited = Its impossible to override <strong>{ $property }</strong> due to <strong>:visited</strong> restriction.
## In the Rule View when a CSS property cannot be successfully applied we display
## an icon. When this icon is hovered this message is displayed to explain how
## the problem can be solved.

View File

@ -79,13 +79,13 @@ class InactiveCssTooltipHelper {
*/
getTemplate(data, tooltip) {
const XHTML_NS = "http://www.w3.org/1999/xhtml";
const { fixId, msgId, numFixProps, property, display } = data;
const { fixId, msgId, numFixProps, property, display, learnMoreURL } = data;
const { doc } = tooltip;
const documentURL =
learnMoreURL || `https://developer.mozilla.org/docs/Web/CSS/${property}`;
this._currentTooltip = tooltip;
this._currentUrl =
`https://developer.mozilla.org/docs/Web/CSS/${property}` +
`?utm_source=devtools&utm_medium=inspector-inactive-css`;
this._currentUrl = `${documentURL}?utm_source=devtools&utm_medium=inspector-inactive-css`;
const templateNode = doc.createElementNS(XHTML_NS, "template");

View File

@ -33,6 +33,7 @@ const {
getBindingElementAndPseudo,
getCSSStyleRules,
l10n,
hasVisitedState,
isAgentStylesheet,
isAuthorStylesheet,
isUserStylesheet,
@ -724,6 +725,11 @@ CssLogic.href = function(sheet) {
return href;
};
/**
* Returns true if the given node has visited state.
*/
CssLogic.hasVisitedState = hasVisitedState;
/**
* A safe way to access cached bits of information about a stylesheet.
*

View File

@ -101,8 +101,6 @@ const BOLD_FONT_WEIGHT = 700;
// Offset (in px) to avoid cutting off text edges of italic fonts.
const FONT_PREVIEW_OFFSET = 4;
const NS_EVENT_STATE_VISITED = 1 << 24;
/**
* The PageStyle actor lets the client look at the styles on a page, as
* they are applied to a given node.
@ -725,7 +723,7 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
const domRules = InspectorUtils.getCSSStyleRules(
node,
pseudo,
_hasVisitedState(node)
CssLogic.hasVisitedState(node)
);
if (!domRules) {
@ -843,7 +841,7 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
const { bindingElement, pseudo } = CssLogic.getBindingElementAndPseudo(
element
);
const relevantLinkVisited = _hasVisitedState(bindingElement);
const relevantLinkVisited = CssLogic.hasVisitedState(bindingElement);
entry.matchedSelectors = [];
for (let i = 0; i < selectors.length; i++) {
@ -2249,10 +2247,3 @@ function getTextAtLineColumn(text, line, column) {
}
exports.getTextAtLineColumn = getTextAtLineColumn;
function _hasVisitedState(node) {
return (
!!(InspectorUtils.getContentState(node) & NS_EVENT_STATE_VISITED) ||
InspectorUtils.hasPseudoClassLock(node, ":visited")
);
}

View File

@ -5,12 +5,33 @@
"use strict";
const Services = require("Services");
const InspectorUtils = require("InspectorUtils");
loader.lazyRequireGetter(
this,
"CssLogic",
"devtools/server/actors/inspector/css-logic",
true
);
const INACTIVE_CSS_ENABLED = Services.prefs.getBoolPref(
"devtools.inspector.inactive.css.enabled",
false
);
const VISITED_MDN_LINK = "https://developer.mozilla.org/docs/Web/CSS/:visited";
const VISITED_INVALID_PROPERTIES = allCssPropertiesExcept([
"color",
"background-color",
"border-color",
"border-bottom-color",
"border-left-color",
"border-right-color",
"border-top-color",
"column-rule-color",
"outline-color",
]);
class InactivePropertyHelper {
/**
* A list of rules for when CSS properties have no effect.
@ -195,6 +216,15 @@ class InactivePropertyHelper {
msgId: "inactive-css-not-display-block-on-floated",
numFixProps: 2,
},
// The property is impossible to override due to :visited restriction.
{
invalidProperties: VISITED_INVALID_PROPERTIES,
when: () => this.isVisitedRule(),
fixId: "learn-more",
msgId: "inactive-css-property-is-impossible-to-override-in-visited",
numFixProps: 1,
learnMoreURL: VISITED_MDN_LINK,
},
];
}
@ -239,6 +269,9 @@ class InactivePropertyHelper {
* The number of properties we suggest in the fixId string.
* @return {String} object.property
* The inactive property name.
* @return {String} object.learnMoreURL
* An optional link if we need to open an other link than
* the default MDN property one.
* @return {Boolean} object.used
* true if the property is used.
*/
@ -253,6 +286,7 @@ class InactivePropertyHelper {
let fixId = "";
let msgId = "";
let numFixProps = 0;
let learnMoreURL = null;
let used = true;
this.VALIDATORS.some(validator => {
@ -260,9 +294,7 @@ class InactivePropertyHelper {
let isRuleConcerned = false;
if (validator.invalidProperties) {
isRuleConcerned =
validator.invalidProperties === "*" ||
validator.invalidProperties.includes(property);
isRuleConcerned = validator.invalidProperties.includes(property);
}
if (!isRuleConcerned) {
@ -277,6 +309,7 @@ class InactivePropertyHelper {
fixId = validator.fixId;
msgId = validator.msgId;
numFixProps = validator.numFixProps;
learnMoreURL = validator.learnMoreURL;
used = false;
return true;
@ -300,6 +333,7 @@ class InactivePropertyHelper {
msgId,
numFixProps,
property,
learnMoreURL,
used,
};
}
@ -627,6 +661,39 @@ class InactivePropertyHelper {
return !!this.getParentGridElement(this.node);
}
isVisitedRule() {
if (!CssLogic.hasVisitedState(this.node)) {
return false;
}
const selectors = CssLogic.getSelectors(this.cssRule);
if (!selectors.some(s => s.endsWith(":visited"))) {
return false;
}
const { bindingElement, pseudo } = CssLogic.getBindingElementAndPseudo(
this.node
);
for (let i = 0; i < selectors.length; i++) {
if (
!selectors[i].endsWith(":visited") &&
InspectorUtils.selectorMatchesElement(
bindingElement,
this.cssRule,
i,
pseudo,
true
)
) {
// Match non :visited selector.
return false;
}
}
return true;
}
getParentGridElement(node) {
// The documentElement can't be a grid item, only a container, so bail out.
if (node.flattenedTreeParentNode === node.ownerDocument) {
@ -672,3 +739,23 @@ class InactivePropertyHelper {
}
exports.inactivePropertyHelper = new InactivePropertyHelper();
/**
* Returns all CSS property names except given properties.
*
* @param {Array} - propertiesToIgnore
* Array of property ignored.
* @return {Array}
* Array of all CSS property name except propertiesToIgnore.
*/
function allCssPropertiesExcept(propertiesToIgnore) {
const properties = new Set(
InspectorUtils.getCSSPropertyNames({ includeAliases: true })
);
for (const name of propertiesToIgnore) {
properties.delete(name);
}
return [...properties];
}

View File

@ -553,3 +553,20 @@ function getCSSStyleRules(node) {
return rules;
}
exports.getCSSStyleRules = getCSSStyleRules;
/**
* Returns true if the given node has visited state.
*/
function hasVisitedState(node) {
if (!node) {
return false;
}
const NS_EVENT_STATE_VISITED = 1 << 24;
return (
!!(InspectorUtils.getContentState(node) & NS_EVENT_STATE_VISITED) ||
InspectorUtils.hasPseudoClassLock(node, ":visited")
);
}
exports.hasVisitedState = hasVisitedState;