[IMP] styles: handle & selector

This commit adds the support of the & selector.
This selector is useful to join a subrule with a parent selector.

example:

button {
  &:hover {
    background-color: red;
  }
}

will give

button:hover {
  background-color: red;
}
This commit is contained in:
mcm-odoo
2020-01-09 09:35:48 +01:00
committed by Géry Debongnie
parent 4a0d04e4ae
commit 74bd119bf5
3 changed files with 76 additions and 2 deletions
+46
View File
@@ -101,6 +101,52 @@ will be formatted as:
}
```
This extension brings another useful feature: the `&` selector which refers to
the parent selector. For example, we want our component to be red when hovered.
We would like to write something like:
```scss
.my-component {
display: block;
:hover {
color: red;
}
}
```
but it will be formatted as:
```css
.my-component {
display: block;
}
.my-component :hover {
color: red;
}
```
The `&` selector can be used to solve this problem:
```scss
.my-component {
display: block;
&:hover {
color: red;
}
}
```
will be formatted as:
```css
.my-component {
display: block;
}
.my-component:hover {
color: red;
}
```
Now, there is no additional processing done by the `css` tag. However, since it
is done in javascript at runtime, we actually have more power. For example:
+5 -2
View File
@@ -15,13 +15,16 @@ export function processSheet(str: string): string {
function generateSelector(stackIndex: number, parentSelector?: string) {
const parts: string[] = [];
for (const selector of selectorStack[stackIndex]) {
let part = parentSelector && parentSelector + ' ' + selector || selector;
let part = (parentSelector && parentSelector + " " + selector) || selector;
if (part.includes("&")) {
part = selector.replace(/&/g, parentSelector || "");
}
if (stackIndex < selectorStack.length - 1) {
part = generateSelector(stackIndex + 1, part);
}
parts.push(part);
}
return parts.join(', ');
return parts.join(", ");
}
function generateRules() {
if (rules.length) {
+25
View File
@@ -142,4 +142,29 @@ describe("styles and component", () => {
color: red;
}`);
});
test("handle & selector", async () => {
let sheet = processSheet(`.btn {
&.danger {
color: red;
}
}`);
expect(sheet).toBe(`.btn.danger {
color: red;
}`);
sheet = processSheet(`.some-class {
&.btn {
.other-class ~ & {
color: red;
}
}
}`);
expect(sheet).toBe(`.other-class ~ .some-class.btn {
color: red;
}`);
});
});