Skip to content

Commit

Permalink
Fix [class*=foo] with HTML extractor (#1133)
Browse files Browse the repository at this point in the history
* feat(purgecss-from-html): treat id and class as attr values too

Previously, the values of the id and class attributes were stored
only as ids and classes respsectively, which meant selectors like
[class*=foo] were spuriously removed because "foo" is only treated
as a class value, not an attribute value.

* add test for #1133

test that classes and ids are correctly added in attributes names and values.

---------

Co-authored-by: Floriel <Ffloriel@users.noreply.github.com>
  • Loading branch information
Gaelan and Ffloriel authored Feb 3, 2024
1 parent c56275f commit f79ef3d
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 5 deletions.
5 changes: 5 additions & 0 deletions packages/purgecss-from-html/__tests__/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ export const TEST_1_CLASS = ["test-container", "test-footer", "a-link"];

export const TEST_1_ID = ["a-link", "blo"];

export const TEST_1_ATTRIBUTES = {
NAMES: ["href", "id", "class", "type", "disabled"],
VALUES: ["#", "a-link", "a-link", "text", ...TEST_1_CLASS, ...TEST_1_ID]
}

export const TEST_2_CONTENT = `
<template>
<div id="app">
Expand Down
14 changes: 13 additions & 1 deletion packages/purgecss-from-html/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import purgehtml from "./../src/index";

import { TEST_1_CONTENT, TEST_1_TAG, TEST_1_CLASS, TEST_1_ID } from "./data";
import { TEST_1_CONTENT, TEST_1_TAG, TEST_1_CLASS, TEST_1_ID, TEST_1_ATTRIBUTES } from "./data";
import { TEST_2_CONTENT, TEST_2_TAG, TEST_2_CLASS, TEST_2_ID } from "./data";

describe("purgehtml", () => {
Expand All @@ -24,6 +24,18 @@ describe("purgehtml", () => {
expect(resultTest1.ids.includes(item)).toBe(true);
}
});

it("finds attributes names", () => {
for (const item of TEST_1_ATTRIBUTES.NAMES) {
expect(resultTest1.attributes.names.includes(item)).toBe(true);
}
});

it("finds attributes values", () => {
for (const item of TEST_1_ATTRIBUTES.VALUES) {
expect(resultTest1.attributes.values.includes(item)).toBe(true);
}
});
});

const resultTest2 = purgehtml(TEST_2_CONTENT);
Expand Down
6 changes: 3 additions & 3 deletions packages/purgecss-from-html/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ const getSelectorsInElement = (
result.classes.push(...value.split(" "));
} else if (name === "id") {
result.ids.push(...value.split(" "));
} else {
result.attributes.names.push(name);
result.attributes.values.push(...value.split(" "));
}
// always add to attributes, to handle things like [class*=foo]
result.attributes.names.push(name);
result.attributes.values.push(...value.split(" "));
}

return mergedExtractorResults(getSelectorsInNodes(element), result);
Expand Down
16 changes: 15 additions & 1 deletion packages/purgecss/__tests__/attributes.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
import { PurgeCSS } from "./../src/index";
import { ROOT_TEST_EXAMPLES } from "./utils";
import purgecssFromHtml from "purgecss-from-html";

describe("attributes", () => {
// we run this suite against both the default and HTML extractors, as the HTML
// extractor's more granular attribute handling can cause bugs
describe.each([
[[]],
[
[
{
extensions: ["html"],
extractor: purgecssFromHtml,
},
],
],
])("attributes", (extractors) => {
let purgedCSS: string;

beforeAll(async () => {
const resultsPurge = await new PurgeCSS().purge({
content: [`${ROOT_TEST_EXAMPLES}attributes/attribute_selector.html`],
css: [`${ROOT_TEST_EXAMPLES}attributes/attribute_selector.css`],
dynamicAttributes: ["aria-selected"],
extractors
});
purgedCSS = resultsPurge[0].css;
});
Expand Down

0 comments on commit f79ef3d

Please sign in to comment.