diff --git a/lib/style.js b/lib/style.js index 32222d4a..02a86839 100644 --- a/lib/style.js +++ b/lib/style.js @@ -78,7 +78,10 @@ const parseStylesheet = (css, dynamic) => { * @type {Array} */ const rules = []; - const ast = csstree.parse(css); + const ast = csstree.parse(css, { + parseValue: false, + parseAtrulePrelude: false, + }); csstree.walk(ast, (cssNode) => { if (cssNode.type === 'Rule') { rules.push(parseRule(cssNode, dynamic || false)); @@ -100,6 +103,30 @@ const parseStylesheet = (css, dynamic) => { return rules; }; +/** + * @type {(css: string) => Array} + */ +const parseStyleDeclarations = (css) => { + /** + * @type {Array} + */ + 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, node: XastElement) => ComputedStyles} */ @@ -143,10 +170,12 @@ const computeOwnStyle = (stylesheet, node) => { } // collect inline styles - // @ts-ignore node.style is hidden from pubilc usage - for (const [name, { value, priority }] of node.style.properties) { + const styleDeclarations = + node.attributes.style == null + ? [] + : parseStyleDeclarations(node.attributes.style); + for (const { name, value, important } of styleDeclarations) { const computed = computedStyle[name]; - const important = priority === 'important'; if (computed && computed.type === 'dynamic') { continue; } diff --git a/plugins/inlineStyles.js b/plugins/inlineStyles.js index 7e2c755d..8f23bd34 100644 --- a/plugins/inlineStyles.js +++ b/plugins/inlineStyles.js @@ -148,32 +148,51 @@ exports.fn = function (root, opts) { if (selector.rule === null) { 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 csstree.walk(selector.rule, { visit: 'Declaration', - enter: function (styleCsstreeDeclaration) { + enter(ruleDeclaration) { // existing inline styles have higher priority // no inline styles, external styles, external 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 - var styleDeclaration = cssTools.csstreeToStyleDeclaration( - styleCsstreeDeclaration + const matchedItem = styleDeclarationItems.get( + ruleDeclaration.property ); - if ( - selectedEl.style.getPropertyValue(styleDeclaration.name) !== null && - selectedEl.style.getPropertyPriority(styleDeclaration.name) >= - styleDeclaration.priority + const ruleDeclarationItem = + styleDeclarationList.children.createItem(ruleDeclaration); + if (matchedItem == null) { + 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 (