Skip to content

Commit fb51dc6

Browse files
committed
feat(purgecss-from-pug): returns ExtractorResultDetailed instead of selectors
1 parent d751980 commit fb51dc6

File tree

4 files changed

+83
-39
lines changed

4 files changed

+83
-39
lines changed

Diff for: jest.config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const config: JestConfigWithTsJest = {
1111
},
1212
testMatch: ["<rootDir>/__tests__/**/*test.ts"],
1313
transform: {
14-
"^.+.tsx?$": ["ts-jest",{}],
14+
"^.+.tsx?$": ["ts-jest", {}],
1515
},
1616
};
1717

Diff for: packages/purgecss-from-pug/__tests__/data.ts

+15
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,18 @@ export const TEST_1_CLASS = [
3030
];
3131

3232
export const TEST_1_ID = ["a-link", "blo"];
33+
34+
export const TEST_1_ATTRIBUTE_NAMES = ["class", "id", "type", "disabled"];
35+
36+
export const TEST_1_ATTRIBUTE_VALUES = [
37+
"test-container",
38+
"test-footer",
39+
"a-link",
40+
"first-class",
41+
"second-class",
42+
"enabled",
43+
"blo",
44+
"text",
45+
"true",
46+
"false",
47+
];

Diff for: packages/purgecss-from-pug/__tests__/index.test.ts

+27-14
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,48 @@
1-
import purgePug from "../src/index";
1+
import { purgeCSSFromPug } from "../src/index";
22

3-
import { TEST_1_CONTENT, TEST_1_TAG, TEST_1_CLASS, TEST_1_ID } from "./data";
3+
import {
4+
TEST_1_CONTENT,
5+
TEST_1_TAG,
6+
TEST_1_CLASS,
7+
TEST_1_ID,
8+
TEST_1_ATTRIBUTE_NAMES,
9+
TEST_1_ATTRIBUTE_VALUES,
10+
} from "./data";
411

5-
describe("purgePug", () => {
12+
describe("purgeCSSFromPug", () => {
613
describe("from a normal html document", () => {
714
it("finds tag selectors", () => {
8-
const received = purgePug(TEST_1_CONTENT);
15+
const received = purgeCSSFromPug(TEST_1_CONTENT);
916
for (const item of TEST_1_TAG) {
10-
expect(received.includes(item)).toBe(true);
17+
expect(received.tags.includes(item)).toBe(true);
1118
}
1219
});
1320

1421
it("finds classes selectors", () => {
15-
const received = purgePug(TEST_1_CONTENT);
22+
const received = purgeCSSFromPug(TEST_1_CONTENT);
1623
for (const item of TEST_1_CLASS) {
17-
expect(received.includes(item)).toBe(true);
24+
expect(received.classes.includes(item)).toBe(true);
1825
}
1926
});
2027

2128
it("finds id selectors", () => {
22-
const received = purgePug(TEST_1_CONTENT);
29+
const received = purgeCSSFromPug(TEST_1_CONTENT);
2330
for (const item of TEST_1_ID) {
24-
expect(received.includes(item)).toBe(true);
31+
expect(received.ids.includes(item)).toBe(true);
2532
}
2633
});
2734

28-
it("finds all selectors", () => {
29-
const received = purgePug(TEST_1_CONTENT);
30-
const selectors = [...TEST_1_TAG, ...TEST_1_CLASS, ...TEST_1_ID];
31-
for (const item of selectors) {
32-
expect(received.includes(item)).toBe(true);
35+
it("finds attributes names", () => {
36+
const received = purgeCSSFromPug(TEST_1_CONTENT);
37+
for (const item of TEST_1_ATTRIBUTE_NAMES) {
38+
expect(received.attributes.names.includes(item)).toBe(true);
39+
}
40+
});
41+
42+
it("finds attributes values", () => {
43+
const received = purgeCSSFromPug(TEST_1_CONTENT);
44+
for (const item of TEST_1_ATTRIBUTE_VALUES) {
45+
expect(received.attributes.values.includes(item)).toBe(true);
3346
}
3447
});
3548
});

Diff for: packages/purgecss-from-pug/src/index.ts

+40-24
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
import lex from "pug-lexer";
2+
import type { ExtractorResultDetailed } from "purgecss";
23

4+
const getAttributeTokenValues = (token: lex.AttributeToken): string[] => {
5+
if (typeof token.val === "string") {
6+
return (token.mustEscape ? token.val.replace(/"/g, "") : token.val).split(
7+
" ",
8+
);
9+
}
10+
return [];
11+
};
312
/**
413
* Get the potential selectors from Pug code
514
*
@@ -8,32 +17,39 @@ import lex from "pug-lexer";
817
*
918
* @public
1019
*/
11-
const purgeFromPug = (content: string): string[] => {
20+
export const purgeCSSFromPug = (content: string): ExtractorResultDetailed => {
1221
const tokens = lex(content);
13-
const selectors: string[] = [];
22+
const extractorResult: ExtractorResultDetailed = {
23+
attributes: {
24+
// always add to attributes, to handle things like [class*=foo]
25+
names: ["class", "id"],
26+
values: ["true", "false"],
27+
},
28+
classes: [],
29+
ids: [],
30+
tags: [],
31+
undetermined: [],
32+
};
1433
for (const token of tokens) {
15-
switch (token.type) {
16-
case "tag":
17-
case "id":
18-
case "class":
19-
selectors.push(...token.val.split(" "));
20-
break;
21-
case "attribute":
22-
if (token.name === "class" || token.name === "id") {
23-
if (typeof token.val !== "string") continue;
24-
selectors.push(
25-
...(token.mustEscape
26-
? token.val.replace(/"/g, "")
27-
: token.val
28-
).split(" "),
29-
);
30-
}
31-
break;
32-
default:
33-
break;
34+
if (token.type === "tag") {
35+
extractorResult.tags.push(token.val);
36+
} else if (token.type === "class") {
37+
extractorResult.classes.push(...token.val.split(" "));
38+
extractorResult.attributes.values.push(...token.val.split(" "));
39+
} else if (token.type === "id") {
40+
extractorResult.ids.push(token.val);
41+
extractorResult.attributes.values.push(token.val);
42+
} else if (token.type === "attribute") {
43+
const tokenValues = getAttributeTokenValues(token);
44+
if (token.name === "class") {
45+
extractorResult.classes.push(...tokenValues);
46+
} else if (token.name === "id") {
47+
extractorResult.ids.push(...tokenValues);
48+
} else {
49+
extractorResult.attributes.names.push(token.name);
50+
}
51+
extractorResult.attributes.values.push(...tokenValues);
3452
}
3553
}
36-
return selectors;
54+
return extractorResult;
3755
};
38-
39-
export default purgeFromPug;

0 commit comments

Comments
 (0)