mirror of
https://github.com/svg/svgo.git
synced 2025-07-31 07:44:22 +03:00
Drop node.style usages (#1534)
Parsing inline styles with csstree in place is easier. Caching does not add much value here.
This commit is contained in:
37
lib/style.js
37
lib/style.js
@ -78,7 +78,10 @@ const parseStylesheet = (css, dynamic) => {
|
|||||||
* @type {Array<StylesheetRule>}
|
* @type {Array<StylesheetRule>}
|
||||||
*/
|
*/
|
||||||
const rules = [];
|
const rules = [];
|
||||||
const ast = csstree.parse(css);
|
const ast = csstree.parse(css, {
|
||||||
|
parseValue: false,
|
||||||
|
parseAtrulePrelude: false,
|
||||||
|
});
|
||||||
csstree.walk(ast, (cssNode) => {
|
csstree.walk(ast, (cssNode) => {
|
||||||
if (cssNode.type === 'Rule') {
|
if (cssNode.type === 'Rule') {
|
||||||
rules.push(parseRule(cssNode, dynamic || false));
|
rules.push(parseRule(cssNode, dynamic || false));
|
||||||
@ -100,6 +103,30 @@ const parseStylesheet = (css, dynamic) => {
|
|||||||
return rules;
|
return rules;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {(css: string) => Array<StylesheetDeclaration>}
|
||||||
|
*/
|
||||||
|
const parseStyleDeclarations = (css) => {
|
||||||
|
/**
|
||||||
|
* @type {Array<StylesheetDeclaration>}
|
||||||
|
*/
|
||||||
|
const declarations = [];
|
||||||
|
const ast = csstree.parse(css, {
|
||||||
|
context: 'declarationList',
|
||||||
|
parseValue: false,
|
||||||
|
});
|
||||||
|
csstree.walk(ast, (cssNode) => {
|
||||||
|
if (cssNode.type === 'Declaration') {
|
||||||
|
declarations.push({
|
||||||
|
name: cssNode.property,
|
||||||
|
value: csstree.generate(cssNode.value),
|
||||||
|
important: cssNode.important === true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return declarations;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {(stylesheet: Array<StylesheetRule>, node: XastElement) => ComputedStyles}
|
* @type {(stylesheet: Array<StylesheetRule>, node: XastElement) => ComputedStyles}
|
||||||
*/
|
*/
|
||||||
@ -143,10 +170,12 @@ const computeOwnStyle = (stylesheet, node) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// collect inline styles
|
// collect inline styles
|
||||||
// @ts-ignore node.style is hidden from pubilc usage
|
const styleDeclarations =
|
||||||
for (const [name, { value, priority }] of node.style.properties) {
|
node.attributes.style == null
|
||||||
|
? []
|
||||||
|
: parseStyleDeclarations(node.attributes.style);
|
||||||
|
for (const { name, value, important } of styleDeclarations) {
|
||||||
const computed = computedStyle[name];
|
const computed = computedStyle[name];
|
||||||
const important = priority === 'important';
|
|
||||||
if (computed && computed.type === 'dynamic') {
|
if (computed && computed.type === 'dynamic') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -148,32 +148,51 @@ exports.fn = function (root, opts) {
|
|||||||
if (selector.rule === null) {
|
if (selector.rule === null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
const styleDeclarationList = csstree.parse(
|
||||||
|
selectedEl.attributes.style == null ? '' : selectedEl.attributes.style,
|
||||||
|
{
|
||||||
|
context: 'declarationList',
|
||||||
|
parseValue: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const styleDeclarationItems = new Map();
|
||||||
|
csstree.walk(styleDeclarationList, {
|
||||||
|
visit: 'Declaration',
|
||||||
|
enter(node, item) {
|
||||||
|
styleDeclarationItems.set(node.property, item);
|
||||||
|
},
|
||||||
|
});
|
||||||
// merge declarations
|
// merge declarations
|
||||||
csstree.walk(selector.rule, {
|
csstree.walk(selector.rule, {
|
||||||
visit: 'Declaration',
|
visit: 'Declaration',
|
||||||
enter: function (styleCsstreeDeclaration) {
|
enter(ruleDeclaration) {
|
||||||
// existing inline styles have higher priority
|
// existing inline styles have higher priority
|
||||||
// no inline styles, external styles, external styles used
|
// no inline styles, external styles, external styles used
|
||||||
// inline styles, external styles same priority as inline styles, inline styles used
|
// inline styles, external styles same priority as inline styles, inline styles used
|
||||||
// inline styles, external styles higher priority than inline styles, external styles used
|
// inline styles, external styles higher priority than inline styles, external styles used
|
||||||
var styleDeclaration = cssTools.csstreeToStyleDeclaration(
|
const matchedItem = styleDeclarationItems.get(
|
||||||
styleCsstreeDeclaration
|
ruleDeclaration.property
|
||||||
);
|
);
|
||||||
if (
|
const ruleDeclarationItem =
|
||||||
selectedEl.style.getPropertyValue(styleDeclaration.name) !== null &&
|
styleDeclarationList.children.createItem(ruleDeclaration);
|
||||||
selectedEl.style.getPropertyPriority(styleDeclaration.name) >=
|
if (matchedItem == null) {
|
||||||
styleDeclaration.priority
|
styleDeclarationList.children.append(ruleDeclarationItem);
|
||||||
|
} else if (
|
||||||
|
matchedItem.data.important !== true &&
|
||||||
|
ruleDeclaration.important === true
|
||||||
) {
|
) {
|
||||||
return;
|
styleDeclarationList.children.replace(
|
||||||
|
matchedItem,
|
||||||
|
ruleDeclarationItem
|
||||||
|
);
|
||||||
|
styleDeclarationItems.set(
|
||||||
|
ruleDeclaration.property,
|
||||||
|
ruleDeclarationItem
|
||||||
|
);
|
||||||
}
|
}
|
||||||
selectedEl.style.setProperty(
|
|
||||||
styleDeclaration.name,
|
|
||||||
styleDeclaration.value,
|
|
||||||
styleDeclaration.priority
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
selectedEl.attributes.style = csstree.generate(styleDeclarationList);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
Reference in New Issue
Block a user