1
0
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:
Bogdan Chadkin
2021-08-22 16:18:55 +03:00
committed by GitHub
parent 98c023bdb0
commit 6cb2f7034f
2 changed files with 66 additions and 18 deletions

View File

@ -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;
} }

View File

@ -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 (