Fix scoped CSS selector when class contains a colon (#383)
* fix scoped selector when using escaped colon * update scoped styles test * add changeset * update `scopeRule` test * update `scopeRule` test * update css minifier to account for windows-style line breaks
This commit is contained in:
parent
2d854092a4
commit
e0989c696a
5 changed files with 17 additions and 2 deletions
5
.changeset/twenty-numbers-complain.md
Normal file
5
.changeset/twenty-numbers-complain.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix scoped CSS selector when class contains a colon
|
|
@ -82,7 +82,7 @@ export function scopeRule(selector: string, className: string) {
|
||||||
|
|
||||||
// scope everything else
|
// scope everything else
|
||||||
let newSelector = value;
|
let newSelector = value;
|
||||||
const pseudoIndex = newSelector.indexOf(':');
|
const pseudoIndex = newSelector.search(/(?<!\\):/);
|
||||||
if (pseudoIndex > 0) {
|
if (pseudoIndex > 0) {
|
||||||
// if there’s a pseudoclass (:focus or ::before)
|
// if there’s a pseudoclass (:focus or ::before)
|
||||||
ss = head + newSelector.substring(0, pseudoIndex) + c + newSelector.substr(pseudoIndex) + tail;
|
ss = head + newSelector.substring(0, pseudoIndex) + c + newSelector.substr(pseudoIndex) + tail;
|
||||||
|
|
|
@ -27,6 +27,8 @@ ScopedStyles('Scopes rules correctly', () => {
|
||||||
from: 'from', // ignore keyframe keywords (below)
|
from: 'from', // ignore keyframe keywords (below)
|
||||||
to: 'to',
|
to: 'to',
|
||||||
'55%': '55%',
|
'55%': '55%',
|
||||||
|
'.class\\:class': `.class\\:class.${className}`, // classes can contain special characters if escaped
|
||||||
|
'.class\\:class:focus': `.class\\:class.${className}:focus`,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const [given, expected] of Object.entries(tests)) {
|
for (const [given, expected] of Object.entries(tests)) {
|
||||||
|
|
|
@ -9,7 +9,7 @@ const StylesSSR = suite('Styles SSR');
|
||||||
function cssMinify(css) {
|
function cssMinify(css) {
|
||||||
return css
|
return css
|
||||||
.trim() // remove whitespace
|
.trim() // remove whitespace
|
||||||
.replace(/\n\s*/g, '') // collapse lines
|
.replace(/\r?\n\s*/g, '') // collapse lines
|
||||||
.replace(/\s*\{/g, '{') // collapse selectors
|
.replace(/\s*\{/g, '{') // collapse selectors
|
||||||
.replace(/:\s*/g, ':') // collapse attributes
|
.replace(/:\s*/g, ':') // collapse attributes
|
||||||
.replace(/;}/g, '}'); // collapse block
|
.replace(/;}/g, '}'); // collapse block
|
||||||
|
@ -121,6 +121,9 @@ StylesSSR('Astro scoped styles', async ({ runtime }) => {
|
||||||
|
|
||||||
assert.match(el1.attr('class'), `blue ${scopedClass}`);
|
assert.match(el1.attr('class'), `blue ${scopedClass}`);
|
||||||
assert.match(el2.attr('class'), `visible ${scopedClass}`);
|
assert.match(el2.attr('class'), `visible ${scopedClass}`);
|
||||||
|
|
||||||
|
const { contents: css } = await runtime.load('/_astro/src/components/Astro.astro.css');
|
||||||
|
assert.match(cssMinify(css.toString()), `.blue.${scopedClass}{color:powderblue}.color\\:blue.${scopedClass}{color:powderblue}.visible.${scopedClass}{display:block}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
StylesSSR.run();
|
StylesSSR.run();
|
||||||
|
|
|
@ -8,6 +8,10 @@ let visible = true;
|
||||||
color: powderblue;
|
color: powderblue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.color\:blue {
|
||||||
|
color: powderblue;
|
||||||
|
}
|
||||||
|
|
||||||
.visible {
|
.visible {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
@ -16,3 +20,4 @@ let visible = true;
|
||||||
<div id="class">I’m just used to get the Scoped class</div>
|
<div id="class">I’m just used to get the Scoped class</div>
|
||||||
<div id="dynamic-class" class={blue ? 'blue' : 'notblue'}>I change colors</div>
|
<div id="dynamic-class" class={blue ? 'blue' : 'notblue'}>I change colors</div>
|
||||||
{visible && <div id="dynamic-vis" class="visible">I disappear</div>}
|
{visible && <div id="dynamic-vis" class="visible">I disappear</div>}
|
||||||
|
<div id="colon-class" class="color:blue">I am blue</div>
|
||||||
|
|
Loading…
Reference in a new issue