From 0f3b671c9d0c70f4de3d3f858749b7f32d5c9d79 Mon Sep 17 00:00:00 2001 From: Seth Falco Date: Tue, 7 Nov 2023 22:09:38 +0000 Subject: [PATCH] fix(inlineStyles): empty css block created empty attribute --- lib/style.js | 35 ++++++++------------ package.json | 2 +- plugins/inlineStyles.js | 56 +++++++------------------------- test/plugins/inlineStyles.23.svg | 20 ++++++++++++ test/regression.js | 8 +---- yarn.lock | 10 +++--- 6 files changed, 51 insertions(+), 80 deletions(-) create mode 100644 test/plugins/inlineStyles.23.svg diff --git a/lib/style.js b/lib/style.js index eb8d93d8d..a8f3b9986 100644 --- a/lib/style.js +++ b/lib/style.js @@ -15,7 +15,7 @@ const csstree = require('css-tree'); const { - // @ts-ignore not defined in @types/csso + // @ts-ignore internal api syntax: { specificity }, } = require('csso'); const { visit, matches } = require('./xast.js'); @@ -47,9 +47,7 @@ const parseRule = (ruleNode, dynamic) => { } }); - /** - * @type {StylesheetRule[]} - */ + /** @type {StylesheetRule[]} */ const rules = []; csstree.walk(ruleNode.prelude, (node) => { if (node.type === 'Selector') { @@ -78,9 +76,7 @@ const parseRule = (ruleNode, dynamic) => { * @type {(css: string, dynamic: boolean) => Array} */ const parseStylesheet = (css, dynamic) => { - /** - * @type {Array} - */ + /** @type {Array} */ const rules = []; const ast = csstree.parse(css, { parseValue: false, @@ -111,9 +107,7 @@ const parseStylesheet = (css, dynamic) => { * @type {(css: string) => Array} */ const parseStyleDeclarations = (css) => { - /** - * @type {Array} - */ + /** @type {Array} */ const declarations = []; const ast = csstree.parse(css, { context: 'declarationList', @@ -135,9 +129,7 @@ const parseStyleDeclarations = (css) => { * @type {(stylesheet: Stylesheet, node: XastElement) => ComputedStyles} */ const computeOwnStyle = (stylesheet, node) => { - /** - * @type {ComputedStyles} - */ + /** @type {ComputedStyles} */ const computedStyle = {}; const importantStyles = new Map(); @@ -197,10 +189,12 @@ const computeOwnStyle = (stylesheet, node) => { }; /** - * Compares two selector specificities. - * extracted from https://github.com/keeganstreet/specificity/blob/main/specificity.js#L211 + * Compares selector specificities. + * Derived from https://github.com/keeganstreet/specificity/blob/8757133ddd2ed0163f120900047ff0f92760b536/specificity.js#L207 * - * @type {(a: Specificity, b: Specificity) => number} + * @param {Specificity} a + * @param {Specificity} b + * @returns {number} */ const compareSpecificity = (a, b) => { for (let i = 0; i < 4; i += 1) { @@ -213,18 +207,15 @@ const compareSpecificity = (a, b) => { return 0; }; +exports.compareSpecificity = compareSpecificity; /** * @type {(root: XastRoot) => Stylesheet} */ const collectStylesheet = (root) => { - /** - * @type {Array} - */ + /** @type {Array} */ const rules = []; - /** - * @type {Map} - */ + /** @type {Map} */ const parents = new Map(); visit(root, { element: { diff --git a/package.json b/package.json index 63bb49ec9..95e7f548d 100644 --- a/package.json +++ b/package.json @@ -122,7 +122,7 @@ "@rollup/plugin-commonjs": "^22.0.2", "@rollup/plugin-node-resolve": "^14.1.0", "@types/css-tree": "^2.0.0", - "@types/csso": "^5.0.1", + "@types/csso": "^5.0.2", "@types/jest": "^29.5.5", "del": "^6.0.0", "eslint": "^8.24.0", diff --git a/plugins/inlineStyles.js b/plugins/inlineStyles.js index 323286f75..81245edba 100644 --- a/plugins/inlineStyles.js +++ b/plugins/inlineStyles.js @@ -8,7 +8,7 @@ const csstree = require('css-tree'); const { - // @ts-ignore not defined in @types/csso + // @ts-ignore internal api syntax: { specificity }, } = require('csso'); const { @@ -16,49 +16,16 @@ const { querySelectorAll, detachNodeFromParent, } = require('../lib/xast.js'); +const { compareSpecificity } = require('../lib/style'); exports.name = 'inlineStyles'; exports.description = 'inline styles (additional options)'; /** - * Compares two selector specificities. - * extracted from https://github.com/keeganstreet/specificity/blob/main/specificity.js#L211 - * - * @type {(a: Specificity, b: Specificity) => number} - */ -const compareSpecificity = (a, b) => { - for (var i = 0; i < 4; i += 1) { - if (a[i] < b[i]) { - return -1; - } else if (a[i] > b[i]) { - return 1; - } - } - return 0; -}; - -/** - * Moves + merges styles from style elements to element styles - * - * Options - * onlyMatchedOnce (default: true) - * inline only selectors that match once - * - * removeMatchedSelectors (default: true) - * clean up matched selectors, - * leave selectors that hadn't matched - * - * useMqs (default: ['', 'screen']) - * what media queries to be used - * empty string element for styles outside media queries - * - * usePseudos (default: ['']) - * what pseudo-classes/-elements to be used - * empty string element for all non-pseudo-classes and/or -elements - * - * @author strarsis + * Merges styles from style nodes into inline styles. * * @type {import('./plugins-types').Plugin<'inlineStyles'>} + * @author strarsis */ exports.fn = (root, params) => { const { @@ -205,9 +172,7 @@ exports.fn = (root, params) => { for (const selector of sortedSelectors) { // match selectors const selectorText = csstree.generate(selector.item.data); - /** - * @type {Array} - */ + /** @type {Array} */ const matchedElements = []; try { for (const node of querySelectorAll(root, selectorText)) { @@ -232,9 +197,7 @@ exports.fn = (root, params) => { // apply + + + + + +@@@ + + + + + + diff --git a/test/regression.js b/test/regression.js index ade0928e8..81b6ac5d7 100644 --- a/test/regression.js +++ b/test/regression.js @@ -30,17 +30,11 @@ const runTests = async ({ list }) => { name.startsWith('w3c-svg-11-test-suite/svg/animate-') || // messed gradients name === 'w3c-svg-11-test-suite/svg/pservers-grad-18-b.svg' || - // animated filter - name === 'w3c-svg-11-test-suite/svg/filters-light-04-f.svg' || - // animated filter - name === 'w3c-svg-11-test-suite/svg/filters-composite-05-f.svg' || // removing wrapping breaks :first-child pseudo-class name === 'w3c-svg-11-test-suite/svg/styling-pres-04-f.svg' || // rect is converted to path which matches wrong styles name === 'w3c-svg-11-test-suite/svg/styling-css-08-f.svg' || - // external image - name === 'w3c-svg-11-test-suite/svg/struct-image-02-b.svg' || - // complex selectors are messed becase of converting shapes to paths + // complex selectors are messed because of converting shapes to paths name === 'w3c-svg-11-test-suite/svg/struct-use-10-f.svg' || name === 'w3c-svg-11-test-suite/svg/struct-use-11-f.svg' || name === 'w3c-svg-11-test-suite/svg/styling-css-01-b.svg' || diff --git a/yarn.lock b/yarn.lock index 4291a4d15..22db710f4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -958,12 +958,12 @@ __metadata: languageName: node linkType: hard -"@types/csso@npm:^5.0.1": - version: 5.0.1 - resolution: "@types/csso@npm:5.0.1" +"@types/csso@npm:^5.0.2": + version: 5.0.2 + resolution: "@types/csso@npm:5.0.2" dependencies: "@types/css-tree": "*" - checksum: 62c7e534dfde79c1bf3b3761baec06ac2aa2b568da9be4a548b95e709b65b3944b8ad4cd4d8926de2b4bb301b4f102fb0f8c1354cb203a92ebccf59e58c957a6 + checksum: b2e4d6a99b9c233eb7a963eaf333b748f5967f74b62b002cd4bffa0d7ba12a0c10500a03acc001c1b9f87ec67c20e0b49b16720064dd6a3641362bc7abb12386 languageName: node linkType: hard @@ -4563,7 +4563,7 @@ __metadata: "@rollup/plugin-node-resolve": ^14.1.0 "@trysound/sax": 0.2.0 "@types/css-tree": ^2.0.0 - "@types/csso": ^5.0.1 + "@types/csso": ^5.0.2 "@types/jest": ^29.5.5 commander: ^7.2.0 css-select: ^5.1.0