Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 39 additions & 21 deletions lib/CSSStyleDeclaration.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,19 @@
* https://github.com/NV/CSSOM
*/
"use strict";
const CSSOM = require("rrweb-cssom");
const allExtraProperties = require("./allExtraProperties");
const { shorthandProperties } = require("./shorthandProperties");
const allProperties = require("./generated/allProperties");
const implementedProperties = require("./generated/implementedProperties");
const generatedProperties = require("./generated/properties");
const { hasVarFunc, parseKeyword, parseShorthand, prepareValue, splitValue } = require("./parsers");
const {
hasVarFunc,
isValidPropertyValue,
parseCSS,
parseShorthand,
prepareValue,
splitValue
} = require("./parsers");
const { dashedToCamelCase } = require("./utils/camelize");
const { getPropertyDescriptor } = require("./utils/propertyDescriptors");
const { asciiLowercase } = require("./utils/strings");
Expand Down Expand Up @@ -157,21 +163,37 @@ class CSSStyleDeclaration {
return;
}
this._setInProgress = true;
let dummyRule;
try {
dummyRule = CSSOM.parse(`#bogus{${value}}`).cssRules[0].style;
const valueObj = parseCSS(
value,
{
context: "declarationList",
parseValue: false
},
true
);
if (valueObj?.children) {
for (const item of valueObj.children) {
const {
important,
property,
value: { value: rawValue }
} = item;
const isCustomProperty = property.startsWith("--");
if (
isCustomProperty ||
hasVarFunc(rawValue) ||
isValidPropertyValue(property, rawValue)
) {
this.setProperty(property, rawValue, important ? "important" : "");
} else {
this.removeProperty(property);
}
}
}
} catch {
// Malformed css, just return.
return;
}
for (let i = 0; i < dummyRule.length; i++) {
const property = dummyRule[i];
this.setProperty(
property,
dummyRule.getPropertyValue(property),
dummyRule.getPropertyPriority(property)
);
}
this._setInProgress = false;
if (typeof this._onChange === "function") {
this._onChange(this.cssText);
Expand Down Expand Up @@ -505,22 +527,18 @@ Object.defineProperties(CSSStyleDeclaration.prototype, {
if (part) {
part = `-${part}`;
}
const shorthandProp = `${prefix}${part}`;
let parts = [];
if (val === "") {
parts.push(val);
} else {
const key = parseKeyword(val);
if (key) {
parts.push(key);
} else {
parts.push(...splitValue(val));
}
} else if (isValidPropertyValue(shorthandProp, val)) {
parts.push(...splitValue(val));
}
if (!parts.length || parts.length > positions.length || !parts.every(isValid)) {
return;
}
parts = parts.map((p) => parser(p));
this._setProperty(`${prefix}${part}`, parts.join(" "));
this._setProperty(shorthandProp, parts.join(" "));
switch (positions.length) {
case 4:
if (parts.length === 1) {
Expand Down
37 changes: 34 additions & 3 deletions lib/parsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
*/
"use strict";

const { resolve: resolveColor, utils } = require("@asamuzakjp/css-color");
const {
resolve: resolveColor,
utils: { cssCalc, isColor, resolveGradient, splitValue }
} = require("@asamuzakjp/css-color");
const { next: syntaxes } = require("@csstools/css-syntax-patches-for-csstree");
const csstree = require("css-tree");
const { asciiLowercase } = require("./utils/strings");

const { cssCalc, isColor, resolveGradient, splitValue } = utils;

// CSS global values
// @see https://drafts.csswg.org/css-cascade-5/#defaulting-keywords
const GLOBAL_VALUE = Object.freeze(["initial", "inherit", "unset", "revert", "revert-layer"]);
Expand Down Expand Up @@ -111,6 +114,9 @@ const getNumericType = function getNumericType(val) {
return NUM_TYPE.UNDEFINED;
};

// Patch css-tree
const cssTree = csstree.fork(syntaxes);

// Prepare stringified value.
exports.prepareValue = function prepareValue(value, globalObject = globalThis) {
// `null` is converted to an empty string.
Expand Down Expand Up @@ -508,6 +514,31 @@ exports.parseShorthand = function parseShorthand(val, shorthandFor, preserve = f
return obj;
};

exports.parseCSS = function parseCSS(val, opt, toObject = false) {
const ast = cssTree.parse(val, opt);
if (toObject) {
return cssTree.toPlainObject(ast);
}
return ast;
};

// Returns `false` for custom property and/or var().
exports.isValidPropertyValue = function isValidPropertyValue(prop, val) {
// cssTree.lexer does not support deprecated system colors
// @see https://github.com/w3c/webref/issues/1519#issuecomment-3120290261
if (SYS_COLOR.includes(asciiLowercase(val))) {
if (/^(?:-webkit-)?(?:[a-z][a-z\d]*-)*color$/i.test(prop)) {
return true;
}
return false;
}
const ast = exports.parseCSS(val, {
context: "value"
});
const { error, matched } = cssTree.lexer.matchProperty(prop, ast);
return error === null && matched !== null;
};

// Returns `false` for global values, e.g. "inherit".
exports.isValidColor = function isValidColor(val) {
if (SYS_COLOR.includes(asciiLowercase(val))) {
Expand Down
Loading