Skip to content

Commit c7d8f8c

Browse files
committed
Test attribute selector
1 parent 2e285de commit c7d8f8c

File tree

5 files changed

+190
-33
lines changed

5 files changed

+190
-33
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# glory-svelte-preprocess
22

3-
A svelte preprocess for safely minimizing CSS class footprint for unbeliveable performance gain. :rocket: :rocket: :rocket:
3+
A svelte preprocess minimize CSS class footprint with statical analysis for unbeliveable performance gain. :rocket: :rocket: :rocket:
4+
5+
## Disclaimers
6+
7+
Although this preprocess has been tested extensively, this is not stable yet and expect a bug or two given the complexity of the whole process. Do open an issue and let me know if something go south, and I will try to fix as fast as I can.
48

59
## tldr;
610

src/helper.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,27 +210,32 @@ export const matchWithSelector = (element, selector) => {
210210
case "AttributeSelector": {
211211
const attr = getAttribute(element, selector.name.name);
212212
const attrValue = attr.value[0];
213+
const unquoted = selector.value.value.replace(/(^["']|["']$)/g, "");
213214
switch (selector.matcher) {
214215
case "=": {
215-
return (
216-
attrValue.raw === selector.value.value.replace(/(^["']|["']$)/g, "")
217-
);
216+
return attrValue.raw === unquoted;
218217
}
219218

220-
// TODO: Unhandled
219+
// TODO: Fix as it will match hyphen as well
221220
case "~=": {
221+
return new RegExp(`\\b${unquoted}\\b`).test(attrValue.raw)
222222
}
223223

224+
// TODO: Fix as it will match hyphen as well
224225
case "|=": {
226+
return new RegExp(`\\b${unquoted}\\b`).test(attrValue.raw)
225227
}
226228

227229
case "^=": {
230+
return attrValue.raw.startsWith(unquoted);
228231
}
229232

230233
case "$=": {
234+
return attrValue.raw.endsWith(unquoted);
231235
}
232236

233237
case "*=": {
238+
return attrValue.raw.includes(unquoted);
234239
}
235240

236241
default: {

src/transformer.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ const isTargetElement = (selectorNode, node, linker) => {
4141
}
4242
} else {
4343
const isMatch = matchWithSelector(curNode, selector);
44-
console.log(combinator, isMatch, curNode, selector);
4544
if (isMatch) {
4645
selector = r.prev();
4746
matchCount++;

test/issue2.spec.js

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -249,33 +249,6 @@ describe("when given a rule with pseudo element", function () {
249249
});
250250
});
251251

252-
describe("when given a rule with attribute selector", function () {
253-
it("should add class to the correct tag", function () {
254-
const code = `
255-
<style>
256-
[href="https://example.org"]{
257-
color: #ff3e00;
258-
}
259-
</style><div><a href="https://example.org"></a></div>`;
260-
261-
const filename = "/src/routes/index.svelte";
262-
263-
const result = wrappedPreprocessor(code, filename).code;
264-
265-
expect(result.replace(/\s/g, "")).toBe(
266-
`<style>
267-
:global(.a){
268-
color: #ff3e00;
269-
}
270-
</style>
271-
<div>
272-
<a href="https://example.org" class="a"></a>
273-
</div>
274-
`.replace(/\s/g, "")
275-
);
276-
});
277-
});
278-
279252
describe("when given a rule with :not pseudo selector", function () {
280253
it("should transform the html correctly", function () {
281254
const code = `

test/issue3.spec.js

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import wrappedPreprocessor from "./wrapper.js";
2+
3+
describe("when given a rule with attribute selector", function () {
4+
describe("when given a matcher of =", function () {
5+
it("should add class to the correct tag", function () {
6+
const code = `
7+
<style>
8+
[href="https://example.org"]{
9+
color: #ff3e00;
10+
}
11+
</style><div><a href="https://example.org"></a></div>`;
12+
13+
const filename = "/src/routes/index.svelte";
14+
15+
const result = wrappedPreprocessor(code, filename).code;
16+
17+
expect(result.replace(/\s/g, "")).toBe(
18+
`<style>
19+
:global(.a){
20+
color: #ff3e00;
21+
}
22+
</style>
23+
<div>
24+
<a href="https://example.org" class="a"></a>
25+
</div>
26+
`.replace(/\s/g, "")
27+
);
28+
});
29+
});
30+
});
31+
32+
describe("when given a rule with attribute selector", function () {
33+
describe("when given a matcher of ^=", () => {
34+
it("should add class to the correct tag", function () {
35+
const code = `
36+
<style>
37+
[title^="hello"]{
38+
color: #ff3e00;
39+
}
40+
</style><div><div><img title="hello world" /></div></div>`;
41+
42+
const filename = "/src/routes/index.svelte";
43+
44+
const result = wrappedPreprocessor(code, filename).code;
45+
46+
expect(result.replace(/\s/g, "")).toBe(
47+
`<style>
48+
:global(.a){
49+
color: #ff3e00;
50+
}
51+
</style>
52+
<div>
53+
<div><img title="hello world" class="a" /></div>
54+
</div>
55+
`.replace(/\s/g, "")
56+
);
57+
});
58+
});
59+
});
60+
61+
describe("when given a rule with attribute selector", function () {
62+
describe("when given a matcher of $=", () => {
63+
it("should add class to the correct tag", function () {
64+
const code = `
65+
<style>
66+
[href$="org"]{
67+
color: #ff3e00;
68+
}
69+
</style><div><a href="https://example.org"></a><a href="http://hello.org"></a></div>`;
70+
71+
const filename = "/src/routes/index.svelte";
72+
73+
const result = wrappedPreprocessor(code, filename).code;
74+
75+
expect(result.replace(/\s/g, "")).toBe(
76+
`<style>
77+
:global(.a){
78+
color: #ff3e00;
79+
}
80+
</style>
81+
<div>
82+
<a href="https://example.org" class="a"></a>
83+
<a href="http://hello.org" class="a"></a>
84+
</div>
85+
`.replace(/\s/g, "")
86+
);
87+
});
88+
});
89+
});
90+
91+
describe("when given a rule with attribute selector", function () {
92+
describe("when given a matcher of *=", () => {
93+
it("should add class to the correct tag", function () {
94+
const code = `
95+
<style>
96+
[title*="bar"]{
97+
color: #ff3e00;
98+
}
99+
</style><div><img title="hellobarworld" /></div>`;
100+
101+
const filename = "/src/routes/index.svelte";
102+
103+
const result = wrappedPreprocessor(code, filename).code;
104+
105+
expect(result.replace(/\s/g, "")).toBe(
106+
`<style>
107+
:global(.a){
108+
color: #ff3e00;
109+
}
110+
</style>
111+
<div>
112+
<img title="hellobarworld" class="a"/>
113+
</div>
114+
`.replace(/\s/g, "")
115+
);
116+
});
117+
});
118+
});
119+
120+
describe("when given a rule with attribute selector", function () {
121+
describe("when given a matcher of ~=", () => {
122+
it("should add class to the correct tag", function () {
123+
const code = `
124+
<style>
125+
[title~="bar"]{
126+
color: #ff3e00;
127+
}
128+
</style><div><img title="hello bar world" /></div>`;
129+
130+
const filename = "/src/routes/index.svelte";
131+
132+
const result = wrappedPreprocessor(code, filename).code;
133+
134+
expect(result.replace(/\s/g, "")).toBe(
135+
`<style>
136+
:global(.a){
137+
color: #ff3e00;
138+
}
139+
</style>
140+
<div>
141+
<img title="hello bar world" class="a"/>
142+
</div>
143+
`.replace(/\s/g, "")
144+
);
145+
});
146+
});
147+
});
148+
149+
describe("when given a rule with attribute selector", function () {
150+
describe("when given a matcher of |=", () => {
151+
it("should add class to the correct tag", function () {
152+
const code = `
153+
<style>
154+
[title|="friend"]{
155+
color: #ff3e00;
156+
}
157+
</style><div><img title="foo-friend-bar" /></div>`;
158+
159+
const filename = "/src/routes/index.svelte";
160+
161+
const result = wrappedPreprocessor(code, filename).code;
162+
163+
expect(result.replace(/\s/g, "")).toBe(
164+
`<style>
165+
:global(.a){
166+
color: #ff3e00;
167+
}
168+
</style>
169+
<div>
170+
<img title="foo-friend-bar" class="a"/>
171+
</div>
172+
`.replace(/\s/g, "")
173+
);
174+
});
175+
});
176+
});

0 commit comments

Comments
 (0)