Skip to content

Commit

Permalink
[feat] |important modifier for style directive (#7489)
Browse files Browse the repository at this point in the history
* important modifier for style directive

* docs

* Exclude third param if false
third param for set_style is optional

* Remove unused test

Runtime test doesn't work because of weird behaviour of computed style
the puppeteer test should cover it

* remove unnecessary test

Co-authored-by: tanhauhau <lhtan93@gmail.com>
  • Loading branch information
gtm-nayan and tanhauhau committed Oct 13, 2022
1 parent ff6e1c3 commit bee1851
Show file tree
Hide file tree
Showing 15 changed files with 153 additions and 7 deletions.
3 changes: 3 additions & 0 deletions site/content/docs/03-template-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,9 @@ The `style:` directive provides a shorthand for setting multiple styles on an el
<!-- Multiple styles can be included -->
<div style:color style:width="12rem" style:background-color={darkMode ? "black" : "white"}>...</div>
<!-- Styles can be marked as important -->
<div style:color|important="red">...</div>
```

---
Expand Down
6 changes: 5 additions & 1 deletion src/compiler/compile/compiler_errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,5 +281,9 @@ export default {
invalid_component_style_directive: {
code: 'invalid-component-style-directive',
message: 'Style directives cannot be used on components'
}
},
invalid_style_directive_modifier: (valid: string) => ({
code: 'invalid-style-directive-modifier',
message: `Valid modifiers for style directives are: ${valid}`
})
};
27 changes: 26 additions & 1 deletion src/compiler/compile/nodes/StyleDirective.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,42 @@
import { TemplateNode } from '../../interfaces';
import list from '../../utils/list';
import compiler_errors from '../compiler_errors';
import Component from '../Component';
import { nodes_to_template_literal } from '../utils/nodes_to_template_literal';
import Expression from './shared/Expression';
import Node from './shared/Node';
import TemplateScope from './shared/TemplateScope';

const valid_modifiers = new Set(['important']);

export default class StyleDirective extends Node {
type: 'StyleDirective';
name: string;
modifiers: Set<string>;
expression: Expression;
should_cache: boolean;

constructor(component: Component, parent: Node, scope: TemplateScope, info: TemplateNode) {
constructor(
component: Component,
parent: Node,
scope: TemplateScope,
info: TemplateNode
) {
super(component, parent, scope, info);

this.name = info.name;
this.modifiers = new Set(info.modifiers);

for (const modifier of this.modifiers) {
if (!valid_modifiers.has(modifier)) {
component.error(
this,
compiler_errors.invalid_style_directive_modifier(
list([...valid_modifiers])
)
);
}
}

// Convert the value array to an expression so it's easier to handle
// the StyleDirective going forward.
Expand All @@ -34,6 +56,9 @@ export default class StyleDirective extends Node {
this.expression = new Expression(component, this, scope, raw_expression);
this.should_cache = raw_expression.expressions.length > 0;
}
}

get important() {
return this.modifiers.has('important');
}
}
4 changes: 2 additions & 2 deletions src/compiler/compile/render_dom/wrappers/Element/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1100,7 +1100,7 @@ export default class ElementWrapper extends Wrapper {
add_styles(block: Block) {
const has_spread = this.node.attributes.some(attr => attr.is_spread);
this.node.styles.forEach((style_directive) => {
const { name, expression, should_cache } = style_directive;
const { name, expression, should_cache, important } = style_directive;

const snippet = expression.manipulate(block);
let cached_snippet: Identifier | undefined;
Expand All @@ -1109,7 +1109,7 @@ export default class ElementWrapper extends Wrapper {
block.add_variable(cached_snippet, snippet);
}

const updater = b`@set_style(${this.var}, "${name}", ${should_cache ? cached_snippet : snippet}, false)`;
const updater = b`@set_style(${this.var}, "${name}", ${should_cache ? cached_snippet : snippet}, ${important ? 1 : null})`;

block.chunks.hydrate.push(updater);

Expand Down
5 changes: 4 additions & 1 deletion src/compiler/compile/render_ssr/handlers/Element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ export default function (node: Element, renderer: Renderer, options: RenderOptio
class_expression_list.reduce((lhs, rhs) => x`${lhs} + ' ' + ${rhs}`);

const style_expression_list = node.styles.map(style_directive => {
const { name, expression: { node: expression } } = style_directive;
let { name, important, expression: { node: expression } } = style_directive;
if (important) {
expression = x`${expression} + ' !important'`;
}
return p`"${name}": ${expression}`;
});

Expand Down
1 change: 1 addition & 0 deletions src/compiler/parse/state/tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ function read_attribute(parser: Parser, unique_names: Set<string>) {
end,
type,
name: directive_name,
modifiers,
value
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div style:color|important={myColor}></div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"html": {
"start": 0,
"end": 43,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 43,
"type": "Element",
"name": "div",
"attributes": [
{
"start": 5,
"end": 36,
"type": "StyleDirective",
"name": "color",
"modifiers": [
"important"
],
"value": [
{
"start": 27,
"end": 36,
"type": "MustacheTag",
"expression": {
"type": "Identifier",
"start": 28,
"end": 35,
"loc": {
"start": {
"line": 1,
"column": 28
},
"end": {
"line": 1,
"column": 35
}
},
"name": "myColor"
}
}
]
}
],
"children": []
}
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
"end": 16,
"type": "StyleDirective",
"name": "color",
"modifiers": [],
"value": true
}
],
"children": []
}
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"end": 22,
"type": "StyleDirective",
"name": "color",
"modifiers": [],
"value": [
{
"start": 18,
Expand Down Expand Up @@ -45,6 +46,7 @@
"start": 35,
"end": 52,
"type": "StyleDirective",
"modifiers": [],
"name": "color",
"value": [
{
Expand Down Expand Up @@ -77,6 +79,7 @@
"end": 80,
"type": "StyleDirective",
"name": "color",
"modifiers": [],
"value": [
{
"start": 77,
Expand Down Expand Up @@ -108,6 +111,7 @@
"end": 120,
"type": "StyleDirective",
"name": "color",
"modifiers": [],
"value": [
{
"start": 106,
Expand Down Expand Up @@ -160,6 +164,7 @@
"end": 160,
"type": "StyleDirective",
"name": "color",
"modifiers": [],
"value": [
{
"start": 146,
Expand Down Expand Up @@ -212,6 +217,7 @@
"end": 198,
"type": "StyleDirective",
"name": "color",
"modifiers": [],
"value": [
{
"start": 185,
Expand Down Expand Up @@ -264,6 +270,7 @@
"end": 245,
"type": "StyleDirective",
"name": "color",
"modifiers": [],
"value": [
{
"start": 223,
Expand Down Expand Up @@ -352,4 +359,4 @@
}
]
}
}
}
1 change: 1 addition & 0 deletions test/parser/samples/attribute-style-directive/output.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"end": 26,
"type": "StyleDirective",
"name": "color",
"modifiers": [],
"value": [
{
"start": 17,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export default {
html: `
<h1 class="svelte-szzkfu" style="background-color: red;">hello</h1>
<h1 class="svelte-szzkfu" style="background-color: red !important;">hello</h1>
`,

ssrHtml: `
<h1 class="svelte-szzkfu" style="background-color: red;">hello</h1>
<h1 class="svelte-szzkfu" style="background-color: red !important;">hello</h1>
`,

test({ assert, target, window, component }) {
const h1s = target.querySelectorAll('h1');

assert.equal(window.getComputedStyle(h1s[0])['backgroundColor'], 'rgb(0, 0, 255)');
assert.equal(window.getComputedStyle(h1s[1])['backgroundColor'], 'rgb(255, 0, 0)');

component.color = 'yellow';
assert.equal(window.getComputedStyle(h1s[0])['backgroundColor'], 'rgb(0, 0, 255)');
assert.equal(window.getComputedStyle(h1s[1])['backgroundColor'], 'rgb(255, 255, 0)');
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script>
export let color = 'red'
</script>

<h1 style:background-color={color} >hello</h1>
<h1 style:background-color|important="{color}">hello</h1>

<style>
h1 {
background-color: blue !important;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[{
"message": "Valid modifiers for style directives are: important",
"code": "invalid-style-directive-modifier",
"start": {
"line": 1,
"column": 8,
"character": 8
},
"end": {
"line": 1,
"column": 29,
"character": 29
},
"pos": 8
}]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<button style:color|bad='red'></button>

0 comments on commit bee1851

Please sign in to comment.