From 6391db2962bc730524fe462bd87bb28f4619e603 Mon Sep 17 00:00:00 2001 From: Cosmin Popovici Date: Fri, 9 Dec 2022 00:43:32 +0200 Subject: [PATCH] refactor: removing unused css --- src/transformers/index.js | 3 +- src/transformers/removeInlinedSelectors.js | 37 ++++++----- src/transformers/removeUnusedCss.js | 14 ++--- test/expected/components/kitchen-sink.html | 2 + test/test-posthtml.js | 6 +- test/test-transformers.js | 72 ++++++---------------- 6 files changed, 53 insertions(+), 81 deletions(-) diff --git a/src/transformers/index.js b/src/transformers/index.js index cee5d921..68b88331 100644 --- a/src/transformers/index.js +++ b/src/transformers/index.js @@ -28,7 +28,6 @@ exports.process = async (html, config) => { html = await inline(html, config) html = await shorthandInlineCSS(html, config) html = await removeUnusedCSS(html, config) - html = await removeInlinedClasses(html, config) html = await removeInlineSizes(html, config) html = await removeInlineBgColor(html, config) html = await removeAttributes(html, config) @@ -54,7 +53,7 @@ exports.addURLParams = (html, config) => addURLParams(html, config, true) exports.preventWidows = (html, config) => preventWidows(html, config) exports.replaceStrings = (html, config) => replaceStrings(html, config, true) exports.safeClassNames = (html, config) => safeClassNames(html, config, true) -exports.removeUnusedCSS = (html, config) => removeUnusedCSS(html, config, true) +exports.removeUnusedCSS = (html, config) => removeUnusedCSS(html, config) exports.removeAttributes = (html, config) => removeAttributes(html, config, true) exports.attributeToStyle = (html, config) => attributeToStyle(html, config, true) exports.removeInlineSizes = (html, config) => removeInlineSizes(html, config, true) diff --git a/src/transformers/removeInlinedSelectors.js b/src/transformers/removeInlinedSelectors.js index a0ecfe6d..1a4f6ebf 100644 --- a/src/transformers/removeInlinedSelectors.js +++ b/src/transformers/removeInlinedSelectors.js @@ -20,16 +20,26 @@ const plugin = posthtmlOptions => tree => { // For each style tag... if (node.tag === 'style') { const {root} = postcss().process(node.content) + const preservedClasses = [] - root.walkRules(rule => { - // Skip media queries and such... - if (rule.parent.type === 'atrule') { - return + // Preserve selectors in at rules + root.walkAtRules(rule => { + if (['media', 'supports'].includes(rule.name)) { + rule.walkRules(rule => { + preservedClasses.push(rule.selector) + }) } + }) + root.walkRules(rule => { const {selector} = rule const prop = get(rule.nodes[0], 'prop') + // Preserve pseudo selectors + if (selector.includes(':')) { + preservedClasses.push(selector) + } + try { // If we find the selector in the HTML... tree.match(matchHelper(selector), n => { @@ -39,23 +49,16 @@ const plugin = posthtmlOptions => tree => { // If the class is in the style attribute (inlined), remove it if (has(styleAttr, prop)) { - // Remove the class attribute - remove(classAttr, s => selector.includes(s)) + // Remove the class as long as it's not a preserved class + if (!preservedClasses.some(item => item.endsWith(selector) || item.startsWith(selector))) { + remove(classAttr, classToRemove => selector.includes(classToRemove)) + } // Remove the rule in the

H1 in fill:template

diff --git a/test/test-posthtml.js b/test/test-posthtml.js index 0ee1e1bc..496a5545 100644 --- a/test/test-posthtml.js +++ b/test/test-posthtml.js @@ -60,7 +60,8 @@ test('components', async t => { components: { folders: ['test/stubs/layouts', 'test/stubs/components'] } - } + }, + removeUnusedCSS: false }, beforeRender(html, config) { config.foo = 'bar' @@ -89,7 +90,8 @@ test('components (backwards compatibility)', async t => { delimiters: ['[[', ']]'] } } - } + }, + removeUnusedCSS: false } } diff --git a/test/test-transformers.js b/test/test-transformers.js index 9cb74b9a..f7299244 100644 --- a/test/test-transformers.js +++ b/test/test-transformers.js @@ -162,7 +162,11 @@ test('remove unused CSS', async t => { @@ -172,70 +176,38 @@ test('remove unused CSS', async t => { ` - const enabledResult = ` + const withOptionsResult = ` + .foo:hover {color: blue} + .bar-baz {color: blue}
test div with some text
` - const withOptionsResult = ` + const unsetResult = ` + .foo:hover {color: blue}
test div with some text
` - const enabled = await Maizzle.removeUnusedCSS(html) const disabled = await Maizzle.removeUnusedCSS(html, {removeUnusedCSS: false}) const withOptions = await Maizzle.removeUnusedCSS(html, {whitelist: ['.bar*']}) + const unset = await Maizzle.removeUnusedCSS(html) - t.is(enabled, enabledResult) t.is(disabled, html) t.is(withOptions, withOptionsResult) -}) - -test('remove unused CSS (disabled)', async t => { - const html = ` - - - - - -
test div with some text
- - ` - - const result = ` - - - - - -
test div with some text
- - ` - - const disabled = await Maizzle.removeUnusedCSS(html, {removeUnusedCSS: false}) - const unset = await Maizzle.removeUnusedCSS(html) - - t.is(disabled, result) - t.is(unset, result) + t.is(unset, unsetResult) }) test('remove attributes', async t => { @@ -539,13 +511,9 @@ test('remove inlined selectors', async t => { color: #00a8ff; } - .m-0 {margin: 0} - - .mb-4 {margin-bottom: 16px} - - .mt-0 {margin-top: 0} - - .remove {color: red} + .padded { + padding: 0 20px; + } [data-ogsc] .hidden {display: none} @@ -569,10 +537,10 @@ test('remove inlined selectors', async t => { -
-

Title

+
+

Title

-
text
+
text
` @@ -599,10 +567,10 @@ test('remove inlined selectors', async t => { -
-

Title

+
+

Title

-
text
+
text
`