Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] |important modifier for style directive #7489

Merged
merged 5 commits into from
Oct 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 @@ -1095,7 +1095,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;
Expand All @@ -1104,7 +1104,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 @@ -387,6 +387,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>