mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[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:
@@ -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
|
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:
|
is done in javascript at runtime, we actually have more power. For example:
|
||||||
|
|
||||||
|
|||||||
@@ -15,13 +15,16 @@ export function processSheet(str: string): string {
|
|||||||
function generateSelector(stackIndex: number, parentSelector?: string) {
|
function generateSelector(stackIndex: number, parentSelector?: string) {
|
||||||
const parts: string[] = [];
|
const parts: string[] = [];
|
||||||
for (const selector of selectorStack[stackIndex]) {
|
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) {
|
if (stackIndex < selectorStack.length - 1) {
|
||||||
part = generateSelector(stackIndex + 1, part);
|
part = generateSelector(stackIndex + 1, part);
|
||||||
}
|
}
|
||||||
parts.push(part);
|
parts.push(part);
|
||||||
}
|
}
|
||||||
return parts.join(', ');
|
return parts.join(", ");
|
||||||
}
|
}
|
||||||
function generateRules() {
|
function generateRules() {
|
||||||
if (rules.length) {
|
if (rules.length) {
|
||||||
|
|||||||
@@ -142,4 +142,29 @@ describe("styles and component", () => {
|
|||||||
color: red;
|
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;
|
||||||
|
}`);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user