summaryrefslogtreecommitdiffstats
path: root/devtools/client/fronts/css-properties.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/fronts/css-properties.js')
-rw-r--r--devtools/client/fronts/css-properties.js203
1 files changed, 203 insertions, 0 deletions
diff --git a/devtools/client/fronts/css-properties.js b/devtools/client/fronts/css-properties.js
new file mode 100644
index 0000000000..93e9d52900
--- /dev/null
+++ b/devtools/client/fronts/css-properties.js
@@ -0,0 +1,203 @@
+/* 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/. */
+
+"use strict";
+
+const {
+ FrontClassWithSpec,
+ registerFront,
+} = require("resource://devtools/shared/protocol.js");
+const {
+ cssPropertiesSpec,
+} = require("resource://devtools/shared/specs/css-properties.js");
+
+loader.lazyRequireGetter(
+ this,
+ "cssColors",
+ "resource://devtools/shared/css/color-db.js",
+ true
+);
+loader.lazyRequireGetter(
+ this,
+ "CSS_TYPES",
+ "resource://devtools/shared/css/constants.js",
+ true
+);
+loader.lazyRequireGetter(
+ this,
+ "isCssVariable",
+ "resource://devtools/shared/inspector/css-logic.js",
+ true
+);
+
+/**
+ * The CssProperties front provides a mechanism to have a one-time asynchronous
+ * load of a CSS properties database. This is then fed into the CssProperties
+ * interface that provides synchronous methods for finding out what CSS
+ * properties the current server supports.
+ */
+class CssPropertiesFront extends FrontClassWithSpec(cssPropertiesSpec) {
+ constructor(client, targetFront) {
+ super(client, targetFront);
+
+ // Attribute name from which to retrieve the actorID out of the target actor's form
+ this.formAttributeName = "cssPropertiesActor";
+ }
+
+ async initialize() {
+ const db = await super.getCSSDatabase();
+ this.cssProperties = new CssProperties(normalizeCssData(db));
+ }
+
+ destroy() {
+ this.cssProperties = null;
+ super.destroy();
+ }
+}
+
+/**
+ * Ask questions to a CSS database. This class does not care how the database
+ * gets loaded in, only the questions that you can ask to it.
+ * Prototype functions are bound to 'this' so they can be passed around as helper
+ * functions.
+ *
+ * @param {Object} db
+ * A database of CSS properties
+ * @param {Object} inheritedList
+ * The key is the property name, the value is whether or not
+ * that property is inherited.
+ */
+function CssProperties(db) {
+ this.properties = db.properties;
+
+ this.isKnown = this.isKnown.bind(this);
+ this.isInherited = this.isInherited.bind(this);
+ this.supportsType = this.supportsType.bind(this);
+}
+
+CssProperties.prototype = {
+ /**
+ * Checks to see if the property is known by the browser. This function has
+ * `this` already bound so that it can be passed around by reference.
+ *
+ * @param {String} property The property name to be checked.
+ * @return {Boolean}
+ */
+ isKnown(property) {
+ // Custom Property Names (aka CSS Variables) are case-sensitive; do not lowercase.
+ property = property.startsWith("--") ? property : property.toLowerCase();
+ return !!this.properties[property] || isCssVariable(property);
+ },
+
+ /**
+ * Checks to see if the property is an inherited one.
+ *
+ * @param {String} property The property name to be checked.
+ * @return {Boolean}
+ */
+ isInherited(property) {
+ return this.properties[property]?.isInherited;
+ },
+
+ /**
+ * Checks if the property supports the given CSS type.
+ *
+ * @param {String} property The property to be checked.
+ * @param {String} type One of the values from InspectorPropertyType.
+ * @return {Boolean}
+ */
+ supportsType(property, type) {
+ const id = CSS_TYPES[type];
+ return (
+ this.properties[property] &&
+ (this.properties[property].supports.includes(type) ||
+ this.properties[property].supports.includes(id))
+ );
+ },
+
+ /**
+ * Gets the CSS values for a given property name.
+ *
+ * @param {String} property The property to use.
+ * @return {Array} An array of strings.
+ */
+ getValues(property) {
+ return this.properties[property] ? this.properties[property].values : [];
+ },
+
+ /**
+ * Gets the CSS property names.
+ *
+ * @return {Array} An array of strings.
+ */
+ getNames(property) {
+ return Object.keys(this.properties);
+ },
+
+ /**
+ * Return a list of subproperties for the given property. If |name|
+ * does not name a valid property, an empty array is returned. If
+ * the property is not a shorthand property, then array containing
+ * just the property itself is returned.
+ *
+ * @param {String} name The property to query
+ * @return {Array} An array of subproperty names.
+ */
+ getSubproperties(name) {
+ // Custom Property Names (aka CSS Variables) are case-sensitive; do not lowercase.
+ name = name.startsWith("--") ? name : name.toLowerCase();
+ if (this.isKnown(name)) {
+ if (this.properties[name] && this.properties[name].subproperties) {
+ return this.properties[name].subproperties;
+ }
+ return [name];
+ }
+ return [];
+ },
+};
+
+/**
+ * Even if the target has the cssProperties actor, the returned data may not be in the
+ * same shape or have all of the data we need. This normalizes the data and fills in
+ * any missing information like color values.
+ *
+ * @return {Object} The normalized CSS database.
+ */
+function normalizeCssData(db) {
+ // If there is a `from` attributes, it means that it comes from RDP
+ // and it is not the client `generateCssProperties()` object passed by tests.
+ if (typeof db.from == "string") {
+ // This is where to put backward compat tweaks here to support old runtimes.
+ }
+
+ reattachCssColorValues(db);
+
+ return db;
+}
+
+/**
+ * Color values are omitted to save on space. Add them back here.
+ * @param {Object} The CSS database.
+ */
+function reattachCssColorValues(db) {
+ if (db.properties.color.values[0] === "COLOR") {
+ const colors = Object.keys(cssColors);
+
+ for (const name in db.properties) {
+ const property = db.properties[name];
+ // "values" can be undefined if {name} was not found in CSS_PROPERTIES_DB.
+ if (property.values && property.values[0] === "COLOR") {
+ property.values.shift();
+ property.values = property.values.concat(colors).sort();
+ }
+ }
+ }
+}
+
+module.exports = {
+ CssPropertiesFront,
+ CssProperties,
+ normalizeCssData,
+};
+registerFront(CssPropertiesFront);