Skip to content

Commit 2683fda

Browse files
committed
fix: πŸ› inline :local without a scope not working
βœ… Closes: #238
1 parent 61cde16 commit 2683fda

File tree

2 files changed

+68
-19
lines changed

2 files changed

+68
-19
lines changed

Diff for: β€Žsrc/modules/globalifySelector.ts

+34-19
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable line-comment-position */
12
/*
23
* Split a selector string (ex: div > foo ~ .potato) by
34
* separators: space, >, +, ~ and comma (maybe not needed)
@@ -10,28 +11,42 @@ const combinatorPattern = /(?<!\\)(?:\\\\)*([ >+~,]\s*)(?![^[]+\]|\d)/g;
1011
export function globalifySelector(selector: string) {
1112
const parts = selector.trim().split(combinatorPattern);
1213

13-
const modifiedSelector = parts
14-
.map((selectorPart: string, index: number) => {
15-
// if this is the separator
16-
if (index % 2 !== 0) {
17-
return selectorPart;
18-
}
14+
const newSelector = [];
1915

20-
if (selectorPart === '') {
21-
return selectorPart;
22-
}
16+
for (let i = 0; i < parts.length; i++) {
17+
const part = parts[i];
2318

24-
if (selectorPart.startsWith(':local')) {
25-
return selectorPart.replace(/:local\((.+?)\)/g, '$1');
26-
}
19+
// if this is a separator or a :global
20+
if (i % 2 !== 0 || part === '' || part.startsWith(':global')) {
21+
newSelector.push(part);
22+
continue;
23+
}
2724

28-
if (selectorPart.startsWith(':global')) {
29-
return selectorPart;
30-
}
25+
// :local() with scope
26+
if (part.startsWith(':local(')) {
27+
newSelector.push(part.replace(/:local\((.+?)\)/g, '$1'));
28+
continue;
29+
}
3130

32-
return `:global(${selectorPart})`;
33-
})
34-
.join('');
31+
// :local inlined in a selector
32+
if (part.startsWith(':local')) {
33+
// + 2 to ignore the :local and space combinator
34+
const startIndex = i + 2;
35+
let endIndex = parts.findIndex(
36+
(p, idx) => idx > startIndex && p.startsWith(':global'),
37+
);
3538

36-
return modifiedSelector;
39+
endIndex = endIndex === -1 ? parts.length - 1 : endIndex;
40+
41+
newSelector.push(...parts.slice(startIndex, endIndex + 1));
42+
43+
i = endIndex;
44+
45+
continue;
46+
}
47+
48+
newSelector.push(`:global(${part})`);
49+
}
50+
51+
return newSelector.join('');
3752
}

Diff for: β€Žtest/transformers/globalStyle.test.ts

+34
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,40 @@ describe('transformer - globalStyle', () => {
8888

8989
expect(preprocessed.toString()).toContain(`:global(.test) div{}`);
9090
});
91+
92+
it(':local allows the rest of selectors to be local', async () => {
93+
const template = `<style global>
94+
.test :local div *::before {}
95+
.test :local div + a:hover {}
96+
</style>`;
97+
98+
const opts = autoProcess();
99+
const preprocessed = await preprocess(template, opts);
100+
101+
expect(preprocessed.toString()).toContain(
102+
`:global(.test) div *::before {}`,
103+
);
104+
expect(preprocessed.toString()).toContain(
105+
`:global(.test) div + a:hover {}`,
106+
);
107+
});
108+
109+
it(':local allows the rest of selectors to be local until the next :global', async () => {
110+
const template = `<style global>
111+
.test :local main > :global section div::before {}
112+
.test :local div > .potato :global(p) a:hover {}
113+
</style>`;
114+
115+
const opts = autoProcess();
116+
const preprocessed = await preprocess(template, opts);
117+
118+
expect(preprocessed.toString()).toContain(
119+
`:global(.test) main > :global(section) :global(div::before) {}`,
120+
);
121+
expect(preprocessed.toString()).toContain(
122+
`:global(.test) div > .potato :global(p) :global(a:hover) {}`,
123+
);
124+
});
91125
});
92126

93127
describe('global selector', () => {

0 commit comments

Comments
Β (0)