diff --git a/Makefile b/Makefile
index 081557bbe..bf1f26f0d 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ build:
crystal build src/mint.cr -o mint -p && mv mint ~/.bin/mint && mint
test:
- crystal spec -p && bin/ameba
+ crystal spec -p --error-trace && bin/ameba
test-core:
crystal build src/mint.cr -o mint -p && cd core && ../mint test -b firefox && cd .. && rm mint
diff --git a/core/tests/Dom.mint b/core/tests/Dom.mint
index 95f3a84c1..8e3838ba8 100644
--- a/core/tests/Dom.mint
+++ b/core/tests/Dom.mint
@@ -105,7 +105,7 @@ component Test.Dom.Focus {
state shown : Bool = false
style input {
- display: {display};
+ display: #{display};
}
get display : String {
diff --git a/spec/compilers/access b/spec/compilers/access
index 731825c34..c08aee46e 100644
--- a/spec/compilers/access
+++ b/spec/compilers/access
@@ -15,16 +15,16 @@ const A = _R({
"name",
Decoder.string
]
-})
+});
class B extends _C {
render() {
let a = new A({
name: `test`
- })
+ });
- return a.name
+ return a.name;
}
-}
+};
-B.displayName = "Main"
+B.displayName = "Main";
diff --git a/spec/compilers/access_call b/spec/compilers/access_call
index 8679b24be..291b85083 100644
--- a/spec/compilers/access_call
+++ b/spec/compilers/access_call
@@ -26,34 +26,34 @@ component Main {
--------------------------------------------------------------------------------
class C extends _E {
constructor(_0) {
- super()
- this._0 = _0
- this.length = 1
+ super();
+ this._0 = _0;
+ this.length = 1;
}
-}
+};
class A extends _C {
a(b) {
- return b
+ return b;
}
render() {
- return _h("div", {})
+ return _h("div", {});
}
-}
+};
-A.displayName = "Test"
+A.displayName = "Test";
class B extends _C {
c() {
return (() => {
const _ = (() => {
- const _ = this._test
- return _s(_,(_) => _.a)
- })()
+ const _ = this._test;
+ return _s(_,(_) => _.a);
+ })();
- return _s(_,(_) => _(`asd`))
- })()
+ return _s(_,(_) => _(`asd`));
+ })();
}
render() {
@@ -63,8 +63,8 @@ class B extends _C {
_h(A, {
ref: (instance) => { this._test = new C(instance) }
})
- ])
+ ]);
}
-}
+};
-B.displayName = "Main"
+B.displayName = "Main";
diff --git a/spec/compilers/argument b/spec/compilers/argument
index 9bd4218ba..949f1df38 100644
--- a/spec/compilers/argument
+++ b/spec/compilers/argument
@@ -14,15 +14,15 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a(c, b) {
- return b
+ return b;
}
render() {
return (() => {
- this.a(``, 0)
- return ``
- })()
+ this.a(``, 0);
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/array_access b/spec/compilers/array_access
index 07e999905..5c426d600 100644
--- a/spec/compilers/array_access
+++ b/spec/compilers/array_access
@@ -24,20 +24,20 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return _at([`Hello`, `Blah`, `Joe`], 1)
+ return _at([`Hello`, `Blah`, `Joe`], 1);
}
b() {
- return _at([], 1)
+ return _at([], 1);
}
render() {
return (() => {
- this.a()
- this.b()
- return ``
- })()
+ this.a();
+ this.b();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/array_literal b/spec/compilers/array_literal
index 1565ad2ad..a59ad55ae 100644
--- a/spec/compilers/array_literal
+++ b/spec/compilers/array_literal
@@ -18,15 +18,15 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return [`Hello`, `Blah`, `Joe`]
+ return [`Hello`, `Blah`, `Joe`];
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/bool_literal_false b/spec/compilers/bool_literal_false
index f37c1a883..41514d240 100644
--- a/spec/compilers/bool_literal_false
+++ b/spec/compilers/bool_literal_false
@@ -14,15 +14,15 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return false
+ return false;
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/bool_literal_true b/spec/compilers/bool_literal_true
index 291bf420c..2d768d8e5 100644
--- a/spec/compilers/bool_literal_true
+++ b/spec/compilers/bool_literal_true
@@ -14,15 +14,15 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return true
+ return true;
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/case b/spec/compilers/case
index c6e6d5bc7..5cb2788cb 100644
--- a/spec/compilers/case
+++ b/spec/compilers/case
@@ -19,7 +19,7 @@ component Main {
class A extends _C {
a() {
return (() => {
- let b = `Hello`
+ let b = `Hello`;
if (_compare(b, `test`)) {
return true
@@ -27,16 +27,16 @@ class A extends _C {
return false
} else {
return false
- }
- })()
+ };
+ })();
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/case_with_enum_destructuring b/spec/compilers/case_with_enum_destructuring
index a80c09e1e..654efaf89 100644
--- a/spec/compilers/case_with_enum_destructuring
+++ b/spec/compilers/case_with_enum_destructuring
@@ -28,46 +28,46 @@ component Main {
--------------------------------------------------------------------------------
class B extends _E {
constructor(_0) {
- super()
- this._0 = _0
- this.length = 1
+ super();
+ this._0 = _0;
+ this.length = 1;
}
-}
+};
class C extends _E {
constructor(_0) {
- super()
- this._0 = _0
- this.length = 1
+ super();
+ this._0 = _0;
+ this.length = 1;
}
-}
+};
class A extends _C {
a(b) {
return (() => {
- let c = b
+ let c = b;
if (c instanceof C) {
- const d = c._0
+ const d = c._0;
return (() => {
- let e = d
+ let e = d;
if (e instanceof B) {
- const f = e._0
- return f
- }
- })()
- }
- })()
+ const f = e._0;
+ return f;
+ };
+ })();
+ };
+ })();
}
render() {
return (() => {
- this.a(new C(new B(``)))
- return ``
- })()
+ this.a(new C(new B(``)));
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/catch b/spec/compilers/catch
index 8d4165285..0abb51321 100644
--- a/spec/compilers/catch
+++ b/spec/compilers/catch
@@ -27,44 +27,44 @@ component Main {
--------------------------------------------------------------------------------
const B = new(class extends _M {
c(e) {
- return
+ return;
}
-})
+});
class A extends _C {
a() {
return (async () => {
- let _ = null
+ let _ = null;
try {
let b = await (async () => {
try {
return await B.c(`hello`)
} catch (_error) {
- let d = _error
- _ = null
- throw new DoError()
+ let d = _error;
+ _ = null;
+ throw new DoError();
}
- })()
+ })();
- _ = await null
+ _ = await null;
} catch (_error) {
if (!(_error instanceof DoError)) {
- console.warn(`Unhandled error in sequence expression:`)
- console.warn(_error)
+ console.warn(`Unhandled error in sequence expression:`);
+ console.warn(_error);
}
- }
+ };
- return _
- })()
+ return _;
+ })();
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/component b/spec/compilers/component
index 56e13ba11..89352d8f3 100644
--- a/spec/compilers/component
+++ b/spec/compilers/component
@@ -6,8 +6,8 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
render() {
- return _h("div", {})
+ return _h("div", {});
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/component_instance_access b/spec/compilers/component_instance_access
index 96b888f2f..059b22184 100644
--- a/spec/compilers/component_instance_access
+++ b/spec/compilers/component_instance_access
@@ -26,30 +26,30 @@ component Main {
--------------------------------------------------------------------------------
class C extends _E {
constructor(_0) {
- super()
- this._0 = _0
- this.length = 1
+ super();
+ this._0 = _0;
+ this.length = 1;
}
-}
+};
class A extends _C {
get a() {
- return `Instance`
+ return `Instance`;
}
render() {
- return _h("div", {})
+ return _h("div", {});
}
-}
+};
-A.displayName = "Instance"
+A.displayName = "Instance";
class B extends _C {
b() {
return (() => {
- const _ = this._instance
- return _s(_,(_) => _.a)
- })()
+ const _ = this._instance;
+ return _s(_,(_) => _.a);
+ })();
}
render() {
@@ -59,8 +59,8 @@ class B extends _C {
_h(A, {
ref: (instance) => { this._instance = new C(instance) }
})
- ])
+ ]);
}
-}
+};
-B.displayName = "Main"
+B.displayName = "Main";
diff --git a/spec/compilers/component_namespaced b/spec/compilers/component_namespaced
index 277e12d53..115fbbb05 100644
--- a/spec/compilers/component_namespaced
+++ b/spec/compilers/component_namespaced
@@ -12,16 +12,16 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
render() {
- return `test`
+ return `test`;
}
-}
+};
-A.displayName = "Ui.Dropdown"
+A.displayName = "Ui.Dropdown";
class B extends _C {
render() {
- return _h(A, {})
+ return _h(A, {});
}
-}
+};
-B.displayName = "Main"
+B.displayName = "Main";
diff --git a/spec/compilers/component_readonly b/spec/compilers/component_readonly
index 283fdc07a..3a97eb50c 100644
--- a/spec/compilers/component_readonly
+++ b/spec/compilers/component_readonly
@@ -14,29 +14,29 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
constructor(props) {
- super(props)
+ super(props);
this._d({
a: [
null,
false
]
- })
+ });
}
render() {
- return _h("div", {})
+ return _h("div", {});
}
-}
+};
-A.displayName = "Test"
+A.displayName = "Test";
class B extends _C {
render() {
return _h(A, {
a: true
- })
+ });
}
-}
+};
-B.displayName = "Main"
+B.displayName = "Main";
diff --git a/spec/compilers/component_with_provider b/spec/compilers/component_with_provider
index 15c817916..bbf261a00 100644
--- a/spec/compilers/component_with_provider
+++ b/spec/compilers/component_with_provider
@@ -22,17 +22,17 @@ component Main {
}
}
--------------------------------------------------------------------------------
-const A = _R({})
+const A = _R({});
const B = new(class extends _P {
attach() {
- return null
+ return null;
}
-})
+});
class C extends _C {
componentWillUnmount() {
- B._unsubscribe(this)
+ B._unsubscribe(this);
}
componentDidUpdate() {
@@ -47,7 +47,7 @@ class C extends _C {
}))
} else {
B._unsubscribe(this)
- }
+ };
}
componentDidMount() {
@@ -62,12 +62,12 @@ class C extends _C {
}))
} else {
B._unsubscribe(this)
- }
+ };
}
render() {
- return _h("div", {})
+ return _h("div", {});
}
-}
+};
-C.displayName = "Main"
+C.displayName = "Main";
diff --git a/spec/compilers/component_with_provider_and_lifecycle_functions b/spec/compilers/component_with_provider_and_lifecycle_functions
index 3f8512eb0..8f10ee8e9 100644
--- a/spec/compilers/component_with_provider_and_lifecycle_functions
+++ b/spec/compilers/component_with_provider_and_lifecycle_functions
@@ -34,18 +34,18 @@ component Main {
}
}
--------------------------------------------------------------------------------
-const A = _R({})
+const A = _R({});
const B = new(class extends _P {
attach() {
- return null
+ return null;
}
-})
+});
class C extends _C {
componentWillUnmount() {
- B._unsubscribe(this)
- return null
+ B._unsubscribe(this);
+ return null;
}
componentDidUpdate() {
@@ -60,9 +60,9 @@ class C extends _C {
}))
} else {
B._unsubscribe(this)
- }
+ };
- return null
+ return null;
}
componentDidMount() {
@@ -77,14 +77,14 @@ class C extends _C {
}))
} else {
B._unsubscribe(this)
- }
+ };
- return null
+ return null;
}
render() {
- return _h("div", {})
+ return _h("div", {});
}
-}
+};
-C.displayName = "Main"
+C.displayName = "Main";
diff --git a/spec/compilers/component_with_provider_and_store b/spec/compilers/component_with_provider_and_store
index 413c08e8d..1f0256000 100644
--- a/spec/compilers/component_with_provider_and_store
+++ b/spec/compilers/component_with_provider_and_store
@@ -32,24 +32,24 @@ component Main {
}
}
--------------------------------------------------------------------------------
-const A = _R({})
+const A = _R({});
const B = new(class extends _P {
attach() {
- return null
+ return null;
}
-})
+});
class C extends _C {
get d() {
- return D.c
+ return D.c;
}
- f (...params) { return D.e(...params) }
+ f (...params) { return D.e(...params); }
componentWillUnmount() {
- D._unsubscribe(this)
- B._unsubscribe(this)
+ D._unsubscribe(this);
+ B._unsubscribe(this);
}
componentDidUpdate() {
@@ -64,11 +64,11 @@ class C extends _C {
}))
} else {
B._unsubscribe(this)
- }
+ };
}
componentDidMount() {
- D._subscribe(this)
+ D._subscribe(this);
if (false) {
B._subscribe(this, new A({
@@ -81,30 +81,30 @@ class C extends _C {
}))
} else {
B._unsubscribe(this)
- }
+ };
}
render() {
- return _h("div", {})
+ return _h("div", {});
}
-}
+};
-C.displayName = "Main"
+C.displayName = "Main";
const D = new(class extends _S {
constructor() {
- super()
+ super();
this.state = {
c: ``
- }
+ };
}
get c() {
- return this.state.c
+ return this.state.c;
}
e() {
- return `hello`
+ return `hello`;
}
-})
+});
diff --git a/spec/compilers/css_definition b/spec/compilers/css_definition
index 43312f6cb..4a9925a08 100644
--- a/spec/compilers/css_definition
+++ b/spec/compilers/css_definition
@@ -1,6 +1,6 @@
component Main {
style test {
- margin: {margin}px 0px;
+ margin: #{margin}px 0px;
}
get margin : Number {
@@ -13,24 +13,30 @@ component Main {
}
--------------------------------------------------------------------------------
class A extends _C {
+ $a() {
+ const _ = {
+ [`--a-a`]: this.a + `px 0px`
+ };
+
+ return _;
+ }
+
get a() {
- return 10
+ return 10;
}
render() {
return _h("div", {
className: `a`,
- style: {
- [`--a-a`]: this.a + `px 0px`
- }
- })
+ style: _style([this.$a()])
+ });
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
_insertStyles(`
.a {
margin: var(--a-a);
}
-`)
+`);
diff --git a/spec/compilers/css_media b/spec/compilers/css_media
new file mode 100644
index 000000000..2ff155219
--- /dev/null
+++ b/spec/compilers/css_media
@@ -0,0 +1,55 @@
+component Main {
+ style test {
+ div {
+ color: #{color};
+ }
+
+ @media (screen) {
+ color: #{color};
+ }
+ }
+
+ get color : String {
+ "blue"
+ }
+
+ fun render : Html {
+
+ }
+}
+--------------------------------------------------------------------------------
+class A extends _C {
+ $a() {
+ const _ = {
+ [`--a-a`]: this.a,
+ [`--b-a`]: this.a
+ };
+
+ return _;
+ }
+
+ get a() {
+ return `blue`;
+ }
+
+ render() {
+ return _h("div", {
+ className: `a`,
+ style: _style([this.$a()])
+ });
+ }
+};
+
+A.displayName = "Main";
+
+_insertStyles(`
+.a div {
+ color: var(--a-a);
+}
+
+@media (screen) {
+ .a {
+ color: var(--b-a);
+ }
+}
+`);
diff --git a/spec/compilers/css_media_with_if b/spec/compilers/css_media_with_if
new file mode 100644
index 000000000..e3a94053a
--- /dev/null
+++ b/spec/compilers/css_media_with_if
@@ -0,0 +1,48 @@
+component Main {
+ style test {
+ color: yellow;
+
+ @media (max-width: 300px) {
+ if (true) {
+ color: red;
+ }
+ }
+ }
+
+ fun render : Html {
+
+ }
+}
+--------------------------------------------------------------------------------
+class A extends _C {
+ $a() {
+ const _ = {};
+
+ (true ? Object.assign(_, {
+ [`--a-a`]: `red`
+ }) : null);
+
+ return _;
+ }
+
+ render() {
+ return _h("div", {
+ className: `a`,
+ style: _style([this.$a()])
+ });
+ }
+};
+
+A.displayName = "Main";
+
+_insertStyles(`
+.a {
+ color: yellow;
+}
+
+@media (max-width: 300px) {
+ .a {
+ color: var(--a-a);
+ }
+}
+`);
diff --git a/spec/compilers/css_selector b/spec/compilers/css_selector
index 89cf40485..5302ec8a5 100644
--- a/spec/compilers/css_selector
+++ b/spec/compilers/css_selector
@@ -1,8 +1,9 @@
component Main {
style test {
- & div {
- color: {color};
+ div {
+ color: #{color};
}
+
&:focus {
color: red;
}
@@ -18,27 +19,29 @@ component Main {
}
--------------------------------------------------------------------------------
class A extends _C {
+ $a() {
+ const _ = {
+ [`--a-a`]: this.a
+ };
+
+ return _;
+ }
+
get a() {
- return `blue`
+ return `blue`;
}
render() {
return _h("div", {
className: `a`,
- style: {
- [`--a-a`]: this.a
- }
- })
+ style: _style([this.$a()])
+ });
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
_insertStyles(`
-.a {
-
-}
-
.a div {
color: var(--a-a);
}
@@ -46,4 +49,4 @@ _insertStyles(`
.a:focus {
color: red;
}
-`)
+`);
diff --git a/spec/compilers/css_with_arguments b/spec/compilers/css_with_arguments
new file mode 100644
index 000000000..39d38fcb4
--- /dev/null
+++ b/spec/compilers/css_with_arguments
@@ -0,0 +1,34 @@
+component Main {
+ style test(color : String) {
+ color: #{color};
+ }
+
+ fun render : Html {
+
+ }
+}
+--------------------------------------------------------------------------------
+class A extends _C {
+ $a(a) {
+ const _ = {
+ [`--a-a`]: a
+ };
+
+ return _;
+ }
+
+ render() {
+ return _h("div", {
+ className: `a`,
+ style: _style([this.$a(`red`)])
+ });
+ }
+};
+
+A.displayName = "Main";
+
+_insertStyles(`
+.a {
+ color: var(--a-a);
+}
+`);
diff --git a/spec/compilers/css_with_case b/spec/compilers/css_with_case
new file mode 100644
index 000000000..fa9eb02c4
--- /dev/null
+++ b/spec/compilers/css_with_case
@@ -0,0 +1,54 @@
+component Main {
+ style test {
+ color: yellow;
+
+ case ("a") {
+ "a" =>
+ color: red;
+
+ =>
+ color: blue;
+ }
+ }
+
+ fun render : Html {
+
+ }
+}
+--------------------------------------------------------------------------------
+class A extends _C {
+ $a() {
+ const _ = {};
+
+ (() => {
+ let a = `a`;
+
+ if (_compare(a, `a`)) {
+ Object.assign(_, {
+ [`--a-a`]: `red`
+ })
+ } else {
+ Object.assign(_, {
+ [`--a-a`]: `blue`
+ })
+ };
+ })();
+
+ return _;
+ }
+
+ render() {
+ return _h("div", {
+ className: `a`,
+ style: _style([this.$a()])
+ });
+ }
+};
+
+A.displayName = "Main";
+
+_insertStyles(`
+.a {
+ color: var(--a-a, yellow);
+}
+`);
diff --git a/spec/compilers/css_with_if b/spec/compilers/css_with_if
new file mode 100644
index 000000000..8b16632da
--- /dev/null
+++ b/spec/compilers/css_with_if
@@ -0,0 +1,44 @@
+component Main {
+ style test {
+ color: yellow;
+
+ if (true) {
+ color: red;
+ } else {
+ color: blue;
+ }
+ }
+
+ fun render : Html {
+
+ }
+}
+--------------------------------------------------------------------------------
+class A extends _C {
+ $a() {
+ const _ = {};
+
+ (true ? Object.assign(_, {
+ [`--a-a`]: `red`
+ }) : Object.assign(_, {
+ [`--a-a`]: `blue`
+ }));
+
+ return _;
+ }
+
+ render() {
+ return _h("div", {
+ className: `a`,
+ style: _style([this.$a()])
+ });
+ }
+};
+
+A.displayName = "Main";
+
+_insertStyles(`
+.a {
+ color: var(--a-a, yellow);
+}
+`);
diff --git a/spec/compilers/dce_remove_component_computed_property b/spec/compilers/dce_remove_component_computed_property
index cac50beb6..70322d3f2 100644
--- a/spec/compilers/dce_remove_component_computed_property
+++ b/spec/compilers/dce_remove_component_computed_property
@@ -10,8 +10,8 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
render() {
- return _h("div", {})
+ return _h("div", {});
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/dce_remove_component_function b/spec/compilers/dce_remove_component_function
index e6e130176..28cd03654 100644
--- a/spec/compilers/dce_remove_component_function
+++ b/spec/compilers/dce_remove_component_function
@@ -10,8 +10,8 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
render() {
- return _h("div", {})
+ return _h("div", {});
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/dce_remove_module_function b/spec/compilers/dce_remove_module_function
index 67c2335cc..4e782b251 100644
--- a/spec/compilers/dce_remove_module_function
+++ b/spec/compilers/dce_remove_module_function
@@ -16,14 +16,14 @@ component Main {
--------------------------------------------------------------------------------
const B = new(class extends _M {
a() {
- return ``
+ return ``;
}
-})
+});
class A extends _C {
render() {
- return B.a()
+ return B.a();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/dce_remove_where b/spec/compilers/dce_remove_where
index a5998a2e4..fc6f917c3 100644
--- a/spec/compilers/dce_remove_where
+++ b/spec/compilers/dce_remove_where
@@ -16,13 +16,13 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
get a() {
- let b = `Hello`
- return b
+ let b = `Hello`;
+ return b;
}
render() {
- return this.a
+ return this.a;
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/dce_style b/spec/compilers/dce_style
index bed97835f..4ba592246 100644
--- a/spec/compilers/dce_style
+++ b/spec/compilers/dce_style
@@ -10,8 +10,8 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
render() {
- return _h("div", {})
+ return _h("div", {});
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/decode b/spec/compilers/decode
index 93e2e857a..3a8dcf5f5 100644
--- a/spec/compilers/decode
+++ b/spec/compilers/decode
@@ -26,7 +26,7 @@ const A = _R({
"blah",
Decoder.string
]
-})
+});
const B = _R({
name: [
@@ -37,27 +37,27 @@ const B = _R({
"y",
((_)=>A.decode(_))
]
-})
+});
class C extends _C {
a(b) {
- return ((_)=>B.decode(_))(b)
+ return ((_)=>B.decode(_))(b);
}
render() {
return (() => {
- let _0 = this.a()
+ let _0 = this.a();
if (_0 instanceof Err) {
- let _error = _0._0
- return _catch_all()
- }
+ let _error = _0._0;
+ return _catch_all();
+ };
- _0._0
+ _0._0;
- return ``
- })()
+ return ``;
+ })();
}
-}
+};
-C.displayName = "Main"
+C.displayName = "Main";
diff --git a/spec/compilers/decoder b/spec/compilers/decoder
index f8bd548e6..c7fee9ec1 100644
--- a/spec/compilers/decoder
+++ b/spec/compilers/decoder
@@ -31,7 +31,7 @@ const A = _R({
"SIIIZEEE",
Decoder.number
]
-})
+});
const B = _R({
string: [
@@ -62,27 +62,27 @@ const B = _R({
"y",
((_)=>A.decode(_))
]
-})
+});
class C extends _C {
a(b) {
- return ((_)=>B.decode(_))(b)
+ return ((_)=>B.decode(_))(b);
}
render() {
return (() => {
- let _0 = this.a()
+ let _0 = this.a();
if (_0 instanceof Err) {
- let _error = _0._0
- return _catch_all()
- }
+ let _error = _0._0;
+ return _catch_all();
+ };
- _0._0
+ _0._0;
- return ``
- })()
+ return ``;
+ })();
}
-}
+};
-C.displayName = "Main"
+C.displayName = "Main";
diff --git a/spec/compilers/encode b/spec/compilers/encode
index a76cb0105..eb62f8870 100644
--- a/spec/compilers/encode
+++ b/spec/compilers/encode
@@ -26,22 +26,22 @@ const A = _R({
"age",
Decoder.number
]
-})
+});
class B extends _C {
a() {
return _encode(new A({
name: `Hello`,
age: 20
- }))
+ }));
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-B.displayName = "Main"
+B.displayName = "Main";
diff --git a/spec/compilers/enum b/spec/compilers/enum
index 72ddf8ff7..951d4bbcb 100644
--- a/spec/compilers/enum
+++ b/spec/compilers/enum
@@ -36,72 +36,72 @@ component Main {
--------------------------------------------------------------------------------
class B extends _E {
constructor() {
- super()
- this.length = 0
+ super();
+ this.length = 0;
}
-}
+};
class F extends _E {
constructor() {
- super()
- this.length = 0
+ super();
+ this.length = 0;
}
-}
+};
class D extends _E {
constructor(_0) {
- super()
- this._0 = _0
- this.length = 1
+ super();
+ this._0 = _0;
+ this.length = 1;
}
-}
+};
class E extends _E {
constructor(_0) {
- super()
- this._0 = _0
- this.length = 1
+ super();
+ this._0 = _0;
+ this.length = 1;
}
-}
+};
class G extends _E {
constructor(_0) {
- super()
- this._0 = _0
- this.length = 1
+ super();
+ this._0 = _0;
+ this.length = 1;
}
-}
+};
class C extends _E {
constructor(_0, _1) {
- super()
- this._0 = _0
- this._1 = _1
- this.length = 2
+ super();
+ this._0 = _0;
+ this._1 = _1;
+ this.length = 2;
}
-}
+};
class A extends _C {
a() {
- return new B()
+ return new B();
}
b() {
- return new C(``,``)
+ return new C(``,``);
}
c() {
- return new D(new E(``))
+ return new D(new E(``));
}
render() {
return (() => {
- this.a()
- this.b()
- this.c()
- return ``
- })()
+ this.a();
+ this.b();
+ this.c();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/env b/spec/compilers/env
index e3b649ff9..0c593f0f0 100644
--- a/spec/compilers/env
+++ b/spec/compilers/env
@@ -6,8 +6,8 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
render() {
- return `YES`
+ return `YES`;
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/finally b/spec/compilers/finally
index 64414f38e..b272f8cd2 100644
--- a/spec/compilers/finally
+++ b/spec/compilers/finally
@@ -19,29 +19,29 @@ component Main {
class A extends _C {
a() {
return (async () => {
- let _ = null
+ let _ = null;
try {
- _ = await null
+ _ = await null;
} catch (_error) {
if (!(_error instanceof DoError)) {
- console.warn(`Unhandled error in sequence expression:`)
- console.warn(_error)
+ console.warn(`Unhandled error in sequence expression:`);
+ console.warn(_error);
}
} finally {
null
- }
+ };
- return _
- })()
+ return _;
+ })();
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/for b/spec/compilers/for
index 0173cc4fa..37e3c214f 100644
--- a/spec/compilers/for
+++ b/spec/compilers/for
@@ -11,18 +11,18 @@ component Main {
class A extends _C {
render() {
return (() => {
- const _0 = []
- const _1 = [`A`, `B`]
+ const _0 = [];
+ const _1 = [`A`, `B`];
for (let a of _1) {
_0.push(_h("div", {}, [
a
]))
- }
+ };
- return _0
- })()
+ return _0;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/function b/spec/compilers/function
index 38f58f959..3eed54510 100644
--- a/spec/compilers/function
+++ b/spec/compilers/function
@@ -14,16 +14,16 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return true
+ return true;
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/function_call_simple b/spec/compilers/function_call_simple
index 15c2be949..5fe94d8ad 100644
--- a/spec/compilers/function_call_simple
+++ b/spec/compilers/function_call_simple
@@ -18,19 +18,19 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return `test`
+ return `test`;
}
b() {
- return this.a()
+ return this.a();
}
render() {
return (() => {
- this.b()
- return ``
- })()
+ this.b();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/function_call_with_arguments b/spec/compilers/function_call_with_arguments
index 0f8664f97..b79c08886 100644
--- a/spec/compilers/function_call_with_arguments
+++ b/spec/compilers/function_call_with_arguments
@@ -18,20 +18,20 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a(c, b) {
- return b
+ return b;
}
d() {
- return this.a(`Hello`, true)
+ return this.a(`Hello`, true);
}
render() {
return (() => {
- this.d()
- return ``
- })()
+ this.d();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/function_with_where b/spec/compilers/function_with_where
index d37048c7e..5b1f24cfd 100644
--- a/spec/compilers/function_with_where
+++ b/spec/compilers/function_with_where
@@ -17,17 +17,17 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- let b = `Asd`
- return b
+ let b = `Asd`;
+ return b;
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/get b/spec/compilers/get
index c63a47da0..cdaf514da 100644
--- a/spec/compilers/get
+++ b/spec/compilers/get
@@ -10,12 +10,12 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
get a() {
- return ``
+ return ``;
}
render() {
- return this.a
+ return this.a;
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/get_with_where b/spec/compilers/get_with_where
index ebb067b9e..05316ea4e 100644
--- a/spec/compilers/get_with_where
+++ b/spec/compilers/get_with_where
@@ -16,13 +16,13 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
get a() {
- let b = `Asd`
- return b
+ let b = `Asd`;
+ return b;
}
render() {
- return this.a
+ return this.a;
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/html_attribute_class b/spec/compilers/html_attribute_class
index b6f9886db..17259cdf8 100644
--- a/spec/compilers/html_attribute_class
+++ b/spec/compilers/html_attribute_class
@@ -9,8 +9,8 @@ class A extends _C {
render() {
return _h("div", {
className: `something`
- })
+ });
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/html_attribute_class_with_style b/spec/compilers/html_attribute_class_with_style
index fc43e0662..b826f2e05 100644
--- a/spec/compilers/html_attribute_class_with_style
+++ b/spec/compilers/html_attribute_class_with_style
@@ -13,14 +13,14 @@ class A extends _C {
render() {
return _h("div", {
className: `something` + ` a`
- })
+ });
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
_insertStyles(`
.a {
width: 100%;
}
-`)
+`);
diff --git a/spec/compilers/html_attribute_readonly b/spec/compilers/html_attribute_readonly
index e130578d9..e091dd70f 100644
--- a/spec/compilers/html_attribute_readonly
+++ b/spec/compilers/html_attribute_readonly
@@ -9,8 +9,8 @@ class A extends _C {
render() {
return _h("div", {
readOnly: true
- })
+ });
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/html_attribute_ref b/spec/compilers/html_attribute_ref
index 1b71e9d31..7d2209e4a 100644
--- a/spec/compilers/html_attribute_ref
+++ b/spec/compilers/html_attribute_ref
@@ -11,18 +11,18 @@ component Main {
--------------------------------------------------------------------------------
class B extends _E {
constructor(_0) {
- super()
- this._0 = _0
- this.length = 1
+ super();
+ this._0 = _0;
+ this.length = 1;
}
-}
+};
class A extends _C {
render() {
return _h("div", {
ref: (element) => { this._input = new B(element) }
- })
+ });
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/html_attribute_simple b/spec/compilers/html_attribute_simple
index b16bcd3e4..26f17c858 100644
--- a/spec/compilers/html_attribute_simple
+++ b/spec/compilers/html_attribute_simple
@@ -9,8 +9,8 @@ class A extends _C {
render() {
return _h("div", {
"title": `Hello`
- })
+ });
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/html_attribute_with_expression b/spec/compilers/html_attribute_with_expression
index cb8b2c85e..419923b57 100644
--- a/spec/compilers/html_attribute_with_expression
+++ b/spec/compilers/html_attribute_with_expression
@@ -9,8 +9,8 @@ class A extends _C {
render() {
return _h("div", {
"title": `Hello ` + `there!`
- })
+ });
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/html_component b/spec/compilers/html_component
index 7403019db..4df1e5738 100644
--- a/spec/compilers/html_component
+++ b/spec/compilers/html_component
@@ -12,16 +12,16 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
render() {
- return _h("div", {})
+ return _h("div", {});
}
-}
+};
-A.displayName = "Test"
+A.displayName = "Test";
class B extends _C {
render() {
- return _h(A, {})
+ return _h(A, {});
}
-}
+};
-B.displayName = "Main"
+B.displayName = "Main";
diff --git a/spec/compilers/html_expression b/spec/compilers/html_expression
index 6ee5f206d..659fd2859 100644
--- a/spec/compilers/html_expression
+++ b/spec/compilers/html_expression
@@ -8,8 +8,8 @@ class A extends _C {
render() {
return _h("div", {}, [
`Hello`
- ])
+ ]);
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/html_fragment b/spec/compilers/html_fragment
index daa9bf130..34b76bb81 100644
--- a/spec/compilers/html_fragment
+++ b/spec/compilers/html_fragment
@@ -18,8 +18,8 @@ class A extends _C {
key: `something`
}, [])
])
- ])
+ ]);
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/html_fragment_empty b/spec/compilers/html_fragment_empty
index d560560ae..7a2712a77 100644
--- a/spec/compilers/html_fragment_empty
+++ b/spec/compilers/html_fragment_empty
@@ -11,8 +11,8 @@ class A extends _C {
render() {
return _h("div", {}, [
null
- ])
+ ]);
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/html_with_custom_style b/spec/compilers/html_with_custom_style
index 595602abc..047cd4b9e 100644
--- a/spec/compilers/html_with_custom_style
+++ b/spec/compilers/html_with_custom_style
@@ -13,25 +13,25 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
constructor(props) {
- super(props)
+ super(props);
this._d({
b: [
null,
`blue`
]
- })
+ });
}
get a() {
- return
+ return;
}
render() {
return _h("div", {
style: _style([this.a])
- })
+ });
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/html_with_multiple_styles b/spec/compilers/html_with_multiple_styles
new file mode 100644
index 000000000..7eaaad503
--- /dev/null
+++ b/spec/compilers/html_with_multiple_styles
@@ -0,0 +1,34 @@
+component Main {
+ style one {
+ color: red;
+ }
+
+ style two {
+ color: blue;
+ }
+
+ fun render : Html {
+
+
+ }
+}
+--------------------------------------------------------------------------------
+class A extends _C {
+ render() {
+ return _h("div", {
+ className: `a b`
+ });
+ }
+};
+
+A.displayName = "Main";
+
+_insertStyles(`
+.a {
+ color: red;
+}
+
+.b {
+ color: blue;
+}
+`);
diff --git a/spec/compilers/html_with_pseudos b/spec/compilers/html_with_pseudos
index 12d4af0ff..2c486a9cc 100644
--- a/spec/compilers/html_with_pseudos
+++ b/spec/compilers/html_with_pseudos
@@ -3,16 +3,16 @@ component Main {
property background : String = "blue"
style test {
- background: {background};
+ background: #{background};
color: red;
&:hover {
- background: {hoverBackground};
+ background: #{hoverBackground};
color: cyan;
}
- & div {
- font-family: {"Hello"};
+ div {
+ font-family: #{"Hello"};
color: blue;
}
}
@@ -25,7 +25,7 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
constructor(props) {
- super(props)
+ super(props);
this._d({
b: [
@@ -36,22 +36,28 @@ class A extends _C {
null,
`blue`
]
- })
+ });
+ }
+
+ $a() {
+ const _ = {
+ [`--a-a`]: this.a,
+ [`--b-a`]: this.b,
+ [`--c-a`]: `Hello`
+ };
+
+ return _;
}
render() {
return _h("div", {
className: `a`,
- style: {
- [`--a-a`]: this.a,
- [`--a-b`]: this.b,
- [`--a-c`]: `Hello`
- }
- })
+ style: _style([this.$a()])
+ });
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
_insertStyles(`
.a {
@@ -60,12 +66,12 @@ _insertStyles(`
}
.a:hover {
- background: var(--a-b);
+ background: var(--b-a);
color: cyan;
}
.a div {
- font-family: var(--a-c);
+ font-family: var(--c-a);
color: blue;
}
-`)
+`);
diff --git a/spec/compilers/html_with_string_style b/spec/compilers/html_with_string_style
index 92b62385d..c0f17fdab 100644
--- a/spec/compilers/html_with_string_style
+++ b/spec/compilers/html_with_string_style
@@ -8,8 +8,8 @@ class A extends _C {
render() {
return _h("div", {
style: _style([`opacity:0;`])
- })
+ });
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/html_with_style b/spec/compilers/html_with_style
index d0b0a5ffb..6ddb4069e 100644
--- a/spec/compilers/html_with_style
+++ b/spec/compilers/html_with_style
@@ -1,9 +1,15 @@
component Main {
property background : String = "blue"
+ property color : String = "yellow"
style test {
- background: {background};
- color: red;
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
+ -webkit-touch-callout: none;
+
+ border-color: #{background};
+ background: #{background};
+ border: #{background};
+ color: #{color};
}
fun render : Html {
@@ -14,31 +20,48 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
constructor(props) {
- super(props)
+ super(props);
this._d({
a: [
null,
`blue`
+ ],
+ b: [
+ null,
+ `yellow`
]
- })
+ });
+ }
+
+ $a() {
+ const _ = {
+ [`--a-a`]: this.a,
+ [`--a-b`]: this.a,
+ [`--a-c`]: this.a,
+ [`--a-d`]: this.b
+ };
+
+ return _;
}
render() {
return _h("div", {
className: `a`,
- style: {
- [`--a-a`]: this.a
- }
- })
+ style: _style([this.$a()])
+ });
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
_insertStyles(`
.a {
- background: var(--a-a);
- color: red;
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
+ -webkit-touch-callout: none;
+ border-color: var(--a-a);
+ background: var(--a-b);
+ border: var(--a-c);
+ color: var(--a-d);
}
-`)
+`);
diff --git a/spec/compilers/html_with_style_and_custom_style b/spec/compilers/html_with_style_and_custom_style
index e86289ab5..7e5352949 100644
--- a/spec/compilers/html_with_style_and_custom_style
+++ b/spec/compilers/html_with_style_and_custom_style
@@ -6,7 +6,7 @@ component Main {
}
style test {
- background: {background};
+ background: #{background};
color: red;
}
@@ -18,35 +18,41 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
constructor(props) {
- super(props)
+ super(props);
this._d({
a: [
null,
`blue`
]
- })
+ });
+ }
+
+ $a() {
+ const _ = {
+ [`--a-a`]: this.a
+ };
+
+ return _;
}
get b() {
- return
+ return;
}
render() {
return _h("div", {
className: `a`,
- style: _style([{
- [`--a-a`]: this.a
- }, this.b])
- })
+ style: _style([this.$a(), this.b])
+ });
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
_insertStyles(`
.a {
background: var(--a-a);
color: red;
}
-`)
+`);
diff --git a/spec/compilers/if b/spec/compilers/if
index 085a2ef17..c76cee97e 100644
--- a/spec/compilers/if
+++ b/spec/compilers/if
@@ -18,15 +18,15 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return (_compare(`asd`, `asd2`) ? true : false)
+ return (_compare(`asd`, `asd2`) ? true : false);
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/indirect_connect b/spec/compilers/indirect_connect
index f804d3042..a24baf41c 100644
--- a/spec/compilers/indirect_connect
+++ b/spec/compilers/indirect_connect
@@ -21,52 +21,52 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
get c() {
- return B.b
+ return B.b;
}
componentWillUnmount() {
- B._unsubscribe(this)
+ B._unsubscribe(this);
}
componentDidMount() {
- B._subscribe(this)
+ B._subscribe(this);
}
render() {
- return C.a
+ return C.a;
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
const B = new(class extends _S {
constructor() {
- super()
+ super();
this.state = {
b: ``
- }
+ };
}
get b() {
- return this.state.b
+ return this.state.b;
}
d() {
- return `hello`
+ return `hello`;
}
-})
+});
const C = new(class extends _S {
constructor() {
- super()
+ super();
this.state = {
a: ``
- }
+ };
}
get a() {
- return this.state.a
+ return this.state.a;
}
-})
+});
diff --git a/spec/compilers/inline_function b/spec/compilers/inline_function
index f5bdaed55..86d4d9487 100644
--- a/spec/compilers/inline_function
+++ b/spec/compilers/inline_function
@@ -10,10 +10,10 @@ class A extends _C {
render() {
let a = () => {
return `Hello`
- }
+ };
- return a()
+ return a();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/inline_function_with_arguments b/spec/compilers/inline_function_with_arguments
index be247eb6a..5fe03a8bf 100644
--- a/spec/compilers/inline_function_with_arguments
+++ b/spec/compilers/inline_function_with_arguments
@@ -19,17 +19,17 @@ class A extends _C {
a() {
let b = (c) => {
return c
- }
+ };
- return b(`Joe`)
+ return b(`Joe`);
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/js b/spec/compilers/js
index 522972383..2dbf3760a 100644
--- a/spec/compilers/js
+++ b/spec/compilers/js
@@ -6,8 +6,8 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
render() {
- return ("Hello")
+ return ("Hello");
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/js_with_double_interpolation b/spec/compilers/js_with_double_interpolation
index a84ba5b89..1bbbe314d 100644
--- a/spec/compilers/js_with_double_interpolation
+++ b/spec/compilers/js_with_double_interpolation
@@ -10,12 +10,12 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a(b) {
- return b
+ return b;
}
render() {
- return ("Hello" + this.a(("World!")))
+ return ("Hello" + this.a(("World!")));
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/js_with_interpolation b/spec/compilers/js_with_interpolation
index fceadb4c8..2ac9f1c92 100644
--- a/spec/compilers/js_with_interpolation
+++ b/spec/compilers/js_with_interpolation
@@ -10,12 +10,12 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return `World!`
+ return `World!`;
}
render() {
- return ("Hello" + this.a())
+ return ("Hello" + this.a());
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/member_access b/spec/compilers/member_access
index 678a47fd1..68d1e5794 100644
--- a/spec/compilers/member_access
+++ b/spec/compilers/member_access
@@ -31,13 +31,13 @@ const A = _R({
"name",
Decoder.string
]
-})
+});
const C = new(class extends _M {
a(b, c) {
- return
+ return;
}
-})
+});
class B extends _C {
render() {
@@ -46,11 +46,11 @@ class B extends _C {
name: `Joe`
}), new A({
name: `Doe`
- })])
+ })]);
- return `asd`
- })()
+ return `asd`;
+ })();
}
-}
+};
-B.displayName = "Main"
+B.displayName = "Main";
diff --git a/spec/compilers/module b/spec/compilers/module
index 7b24e8a0d..1012b60c2 100644
--- a/spec/compilers/module
+++ b/spec/compilers/module
@@ -16,14 +16,14 @@ const B = new(class extends _M {
a() {
return _h("p", {}, [
`It should work`
- ])
+ ]);
}
-})
+});
class A extends _C {
render() {
- return B.a()
+ return B.a();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/module_access b/spec/compilers/module_access
index f98c811e5..18f22cb09 100644
--- a/spec/compilers/module_access
+++ b/spec/compilers/module_access
@@ -19,19 +19,19 @@ component Main {
--------------------------------------------------------------------------------
const B = new(class extends _M {
c() {
- return `Hello`
+ return `Hello`;
}
b() {
- return B.c
+ return B.c;
}
-})
+});
class A extends _C {
render() {
- let a = B.b()
- return a()
+ let a = B.b();
+ return a();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/module_access_get b/spec/compilers/module_access_get
index 24289f7e5..afe55394e 100644
--- a/spec/compilers/module_access_get
+++ b/spec/compilers/module_access_get
@@ -16,23 +16,23 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
render() {
- return B.a()
+ return B.a();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
const B = new(class extends _S {
constructor() {
- super()
- this.state = {}
+ super();
+ this.state = {};
}
get b() {
- return `Hello`
+ return `Hello`;
}
a() {
- return B.b
+ return B.b;
}
-})
+});
diff --git a/spec/compilers/module_access_subscriptions b/spec/compilers/module_access_subscriptions
index d41a72ef3..886ecf4e6 100644
--- a/spec/compilers/module_access_subscriptions
+++ b/spec/compilers/module_access_subscriptions
@@ -26,17 +26,17 @@ const A = _R({
"test",
Decoder.string
]
-})
+});
const B = new(class extends _P {
a(b) {
- return b
+ return b;
}
-})
+});
class C extends _C {
componentWillUnmount() {
- B._unsubscribe(this)
+ B._unsubscribe(this);
}
componentDidUpdate() {
@@ -46,7 +46,7 @@ class C extends _C {
}))
} else {
B._unsubscribe(this)
- }
+ };
}
componentDidMount() {
@@ -56,15 +56,15 @@ class C extends _C {
}))
} else {
B._unsubscribe(this)
- }
+ };
}
render() {
return (() => {
- B._subscriptions
- return B.a(`a`)
- })()
+ B._subscriptions;
+ return B.a(`a`);
+ })();
}
-}
+};
-C.displayName = "Main"
+C.displayName = "Main";
diff --git a/spec/compilers/module_call b/spec/compilers/module_call
index 49b746020..414577d8d 100644
--- a/spec/compilers/module_call
+++ b/spec/compilers/module_call
@@ -16,18 +16,18 @@ component Main {
--------------------------------------------------------------------------------
const B = new(class extends _M {
b(c) {
- return c
+ return c;
}
a() {
- return B.b(`Lorem ipsum dolor sit amet`)
+ return B.b(`Lorem ipsum dolor sit amet`);
}
-})
+});
class A extends _C {
render() {
- return B.a()
+ return B.a();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/module_call_piped b/spec/compilers/module_call_piped
index 571a59683..7f57941c6 100644
--- a/spec/compilers/module_call_piped
+++ b/spec/compilers/module_call_piped
@@ -17,18 +17,18 @@ component Main {
--------------------------------------------------------------------------------
const B = new(class extends _M {
b(c, d) {
- return c
+ return c;
}
a() {
- return B.b(`Lorem ipsum dolor sit amet`, true)
+ return B.b(`Lorem ipsum dolor sit amet`, true);
}
-})
+});
class A extends _C {
render() {
- return B.a()
+ return B.a();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/next_call b/spec/compilers/next_call
index f2eef6813..a379ef4a0 100644
--- a/spec/compilers/next_call
+++ b/spec/compilers/next_call
@@ -21,20 +21,20 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
constructor(props) {
- super(props)
+ super(props);
this.state = new Record({
b: `Joe`,
c: 24
- })
+ });
}
get b() {
- return this.state.b
+ return this.state.b;
}
get c() {
- return this.state.c
+ return this.state.c;
}
a() {
@@ -43,15 +43,15 @@ class A extends _C {
b: `Hello`,
c: 30
})), _resolve)
- })
+ });
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/number_literal_negative b/spec/compilers/number_literal_negative
index 4e42edab7..bd71d40fc 100644
--- a/spec/compilers/number_literal_negative
+++ b/spec/compilers/number_literal_negative
@@ -14,15 +14,15 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return -42
+ return -42;
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/number_literal_simple b/spec/compilers/number_literal_simple
index 6c9b28a72..11f280eb4 100644
--- a/spec/compilers/number_literal_simple
+++ b/spec/compilers/number_literal_simple
@@ -14,15 +14,15 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return 10
+ return 10;
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/number_literal_with_decimal b/spec/compilers/number_literal_with_decimal
index d1dc10856..0bb698a32 100644
--- a/spec/compilers/number_literal_with_decimal
+++ b/spec/compilers/number_literal_with_decimal
@@ -14,15 +14,15 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return 10.12
+ return 10.12;
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/operation_chanined b/spec/compilers/operation_chanined
index e4c131caf..16bb9d1d4 100644
--- a/spec/compilers/operation_chanined
+++ b/spec/compilers/operation_chanined
@@ -14,15 +14,15 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return _compare(`a`, `b`) && !_compare(true, false)
+ return _compare(`a`, `b`) && !_compare(true, false);
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/operation_simple b/spec/compilers/operation_simple
index c99e1c6cf..f01fcd5be 100644
--- a/spec/compilers/operation_simple
+++ b/spec/compilers/operation_simple
@@ -14,15 +14,15 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return _compare(`a`, `b`)
+ return _compare(`a`, `b`);
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/parallel_simple b/spec/compilers/parallel_simple
index 25b87250f..62facb8c2 100644
--- a/spec/compilers/parallel_simple
+++ b/spec/compilers/parallel_simple
@@ -20,11 +20,11 @@ component Main {
class A extends _C {
a() {
return (async () => {
- let _ = null
+ let _ = null;
try {
- let b = null
- let c = null
+ let b = null;
+ let c = null;
await Promise.all([
(async () => {
@@ -33,26 +33,26 @@ class A extends _C {
(async () => {
c = await `World`
})()
- ])
+ ]);
- _ = b + c
+ _ = b + c;
} catch (_error) {
if (!(_error instanceof DoError)) {
- console.warn(`Unhandled error in parallel expression:`)
- console.warn(_error)
+ console.warn(`Unhandled error in parallel expression:`);
+ console.warn(_error);
}
- }
+ };
- return _
- })()
+ return _;
+ })();
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/parallel_with_catch b/spec/compilers/parallel_with_catch
index ef13a56a0..db36589ee 100644
--- a/spec/compilers/parallel_with_catch
+++ b/spec/compilers/parallel_with_catch
@@ -35,68 +35,68 @@ component Main {
--------------------------------------------------------------------------------
const B = new(class extends _M {
c(h) {
- return
+ return;
}
-})
+});
class A extends _C {
a() {
return (async () => {
- let _ = null
+ let _ = null;
try {
- let b = null
- let e = null
- let f = null
+ let b = null;
+ let e = null;
+ let f = null;
await Promise.all([
(async () => {
try {
b = await B.c(`x`)
} catch (_error) {
- let d = _error
- _ = `hello`
- throw new DoError()
+ let d = _error;
+ _ = `hello`;
+ throw new DoError();
}
})(),
(async () => {
try {
e = await B.c(`y`)
} catch (_error) {
- let d = _error
- _ = `hello`
- throw new DoError()
+ let d = _error;
+ _ = `hello`;
+ throw new DoError();
}
})(),
(async () => {
try {
f = await B.c(0)
} catch (_error) {
- let g = _error
- _ = `asd`
- throw new DoError()
+ let g = _error;
+ _ = `asd`;
+ throw new DoError();
}
})()
- ])
+ ]);
- _ = `blah`
+ _ = `blah`;
} catch (_error) {
if (!(_error instanceof DoError)) {
- console.warn(`Unhandled error in parallel expression:`)
- console.warn(_error)
+ console.warn(`Unhandled error in parallel expression:`);
+ console.warn(_error);
}
- }
+ };
- return _
- })()
+ return _;
+ })();
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/parallel_with_catch_all b/spec/compilers/parallel_with_catch_all
index e0699cf80..cc96a1d70 100644
--- a/spec/compilers/parallel_with_catch_all
+++ b/spec/compilers/parallel_with_catch_all
@@ -33,19 +33,19 @@ component Main {
--------------------------------------------------------------------------------
const B = new(class extends _M {
c(f) {
- return
+ return;
}
-})
+});
class A extends _C {
a() {
return (async () => {
- let _ = null
+ let _ = null;
try {
- let b = null
- let d = null
- let e = null
+ let b = null;
+ let d = null;
+ let e = null;
await Promise.all([
(async () => {
@@ -57,25 +57,25 @@ class A extends _C {
(async () => {
e = await `World`
})()
- ])
+ ]);
- _ = d + e
+ _ = d + e;
} catch (_error) {
if (!(_error instanceof DoError)) {
return `Hmm...`
}
- }
+ };
- return _
- })()
+ return _;
+ })();
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/parenthesized_expression b/spec/compilers/parenthesized_expression
index c9bfdc6da..204643c13 100644
--- a/spec/compilers/parenthesized_expression
+++ b/spec/compilers/parenthesized_expression
@@ -14,15 +14,15 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return (true)
+ return (true);
}
render() {
return (() => {
- this.a()
- return ``
- })()
+ this.a();
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/partial_application b/spec/compilers/partial_application
index 6ef5b907b..4ed565a33 100644
--- a/spec/compilers/partial_application
+++ b/spec/compilers/partial_application
@@ -16,18 +16,18 @@ component Main {
--------------------------------------------------------------------------------
const B = new(class extends _M {
b(c, d) {
- return c
+ return c;
}
a() {
- return ((..._) => B.b(`test`, ..._))
+ return ((..._) => B.b(`test`, ..._));
}
-})
+});
class A extends _C {
render() {
- return B.a()(true)
+ return B.a()(true);
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/property b/spec/compilers/property
index 791e8397e..731cb5fab 100644
--- a/spec/compilers/property
+++ b/spec/compilers/property
@@ -8,19 +8,19 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
constructor(props) {
- super(props)
+ super(props);
this._d({
a: [
null,
`Joe`
]
- })
+ });
}
render() {
- return _h("div", {})
+ return _h("div", {});
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/record b/spec/compilers/record
index 7c4015439..8698ba847 100644
--- a/spec/compilers/record
+++ b/spec/compilers/record
@@ -29,22 +29,22 @@ const A = _R({
"b",
Decoder.number
]
-})
+});
class B extends _C {
a() {
return new A({
a: `Hello`,
b: 0
- })
+ });
}
render() {
return (() => {
- this.a()
- return _h("div", {})
- })()
+ this.a();
+ return _h("div", {});
+ })();
}
-}
+};
-B.displayName = "Main"
+B.displayName = "Main";
diff --git a/spec/compilers/record_field b/spec/compilers/record_field
index 7c4015439..8698ba847 100644
--- a/spec/compilers/record_field
+++ b/spec/compilers/record_field
@@ -29,22 +29,22 @@ const A = _R({
"b",
Decoder.number
]
-})
+});
class B extends _C {
a() {
return new A({
a: `Hello`,
b: 0
- })
+ });
}
render() {
return (() => {
- this.a()
- return _h("div", {})
- })()
+ this.a();
+ return _h("div", {});
+ })();
}
-}
+};
-B.displayName = "Main"
+B.displayName = "Main";
diff --git a/spec/compilers/record_update b/spec/compilers/record_update
index 6c1a48afb..72ca8d95b 100644
--- a/spec/compilers/record_update
+++ b/spec/compilers/record_update
@@ -23,11 +23,11 @@ const A = _R({
"name",
Decoder.string
]
-})
+});
class B extends _C {
constructor(props) {
- super(props)
+ super(props);
this._d({
b: [
@@ -36,21 +36,21 @@ class B extends _C {
name: `Doe`
})
]
- })
+ });
}
a() {
return _u(this.b, {
name: `John`
- })
+ });
}
render() {
return (() => {
- this.a()
- return _h("div", {})
- })()
+ this.a();
+ return _h("div", {});
+ })();
}
-}
+};
-B.displayName = "Main"
+B.displayName = "Main";
diff --git a/spec/compilers/route b/spec/compilers/route
index 9068599db..7bd073304 100644
--- a/spec/compilers/route
+++ b/spec/compilers/route
@@ -17,5 +17,5 @@ _program.addRoutes([
],
path: `/:name`
}
-])
+]);
diff --git a/spec/compilers/sequence_simple b/spec/compilers/sequence_simple
index 2735e6c1c..a7cab4958 100644
--- a/spec/compilers/sequence_simple
+++ b/spec/compilers/sequence_simple
@@ -17,27 +17,27 @@ component Main {
class A extends _C {
a() {
return (async () => {
- let _ = null
+ let _ = null;
try {
- _ = await null
+ _ = await null;
} catch (_error) {
if (!(_error instanceof DoError)) {
- console.warn(`Unhandled error in sequence expression:`)
- console.warn(_error)
+ console.warn(`Unhandled error in sequence expression:`);
+ console.warn(_error);
}
- }
+ };
- return _
- })()
+ return _;
+ })();
}
render() {
return (() => {
- this.a()
- return _h("div", {})
- })()
+ this.a();
+ return _h("div", {});
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/sequence_using_argument b/spec/compilers/sequence_using_argument
index c3e7c30bf..01695f4bf 100644
--- a/spec/compilers/sequence_using_argument
+++ b/spec/compilers/sequence_using_argument
@@ -19,46 +19,46 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
constructor(props) {
- super(props)
+ super(props);
this.state = new Record({
c: `ho`
- })
+ });
}
get c() {
- return this.state.c
+ return this.state.c;
}
a() {
return (async () => {
- let _ = null
+ let _ = null;
try {
- let b = await `hello`
+ let b = await `hello`;
_ = await new Promise((_resolve) => {
this.setState(_u(this.state, new Record({
c: b
})), _resolve)
- })
+ });
} catch (_error) {
if (!(_error instanceof DoError)) {
- console.warn(`Unhandled error in sequence expression:`)
- console.warn(_error)
+ console.warn(`Unhandled error in sequence expression:`);
+ console.warn(_error);
}
- }
+ };
- return _
- })()
+ return _;
+ })();
}
render() {
return (() => {
- this.a()
- return _h("div", {})
- })()
+ this.a();
+ return _h("div", {});
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/sequence_with_argument b/spec/compilers/sequence_with_argument
index b1b8a3107..3f19e418a 100644
--- a/spec/compilers/sequence_with_argument
+++ b/spec/compilers/sequence_with_argument
@@ -18,28 +18,28 @@ component Main {
class A extends _C {
a() {
return (async () => {
- let _ = null
+ let _ = null;
try {
- let b = await `hello`
- _ = await null
+ let b = await `hello`;
+ _ = await null;
} catch (_error) {
if (!(_error instanceof DoError)) {
- console.warn(`Unhandled error in sequence expression:`)
- console.warn(_error)
+ console.warn(`Unhandled error in sequence expression:`);
+ console.warn(_error);
}
- }
+ };
- return _
- })()
+ return _;
+ })();
}
render() {
return (() => {
- this.a()
- return _h("div", {})
- })()
+ this.a();
+ return _h("div", {});
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/sequence_with_catch b/spec/compilers/sequence_with_catch
index 9676ca56b..6650eba68 100644
--- a/spec/compilers/sequence_with_catch
+++ b/spec/compilers/sequence_with_catch
@@ -35,64 +35,64 @@ component Main {
--------------------------------------------------------------------------------
const B = new(class extends _M {
c(h) {
- return
+ return;
}
-})
+});
class A extends _C {
a() {
return (async () => {
- let _ = null
+ let _ = null;
try {
let b = await (async () => {
try {
return await B.c(`x`)
} catch (_error) {
- let d = _error
- _ = d
- throw new DoError()
+ let d = _error;
+ _ = d;
+ throw new DoError();
}
- })()
+ })();
let e = await (async () => {
try {
return await B.c(`y`)
} catch (_error) {
- let d = _error
- _ = d
- throw new DoError()
+ let d = _error;
+ _ = d;
+ throw new DoError();
}
- })()
+ })();
let f = await (async () => {
try {
return await B.c(0)
} catch (_error) {
- let g = _error
- _ = `asd`
- throw new DoError()
+ let g = _error;
+ _ = `asd`;
+ throw new DoError();
}
- })()
+ })();
- _ = await `blah`
+ _ = await `blah`;
} catch (_error) {
if (!(_error instanceof DoError)) {
- console.warn(`Unhandled error in sequence expression:`)
- console.warn(_error)
+ console.warn(`Unhandled error in sequence expression:`);
+ console.warn(_error);
}
- }
+ };
- return _
- })()
+ return _;
+ })();
}
render() {
return (() => {
- this.a()
- return _h("div", {})
- })()
+ this.a();
+ return _h("div", {});
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/sequence_with_finally b/spec/compilers/sequence_with_finally
index e0e6bfd5a..8d6ed4a7a 100644
--- a/spec/compilers/sequence_with_finally
+++ b/spec/compilers/sequence_with_finally
@@ -19,29 +19,29 @@ component Main {
class A extends _C {
a() {
return (async () => {
- let _ = null
+ let _ = null;
try {
- _ = await null
+ _ = await null;
} catch (_error) {
if (!(_error instanceof DoError)) {
- console.warn(`Unhandled error in sequence expression:`)
- console.warn(_error)
+ console.warn(`Unhandled error in sequence expression:`);
+ console.warn(_error);
}
} finally {
null
- }
+ };
- return _
- })()
+ return _;
+ })();
}
render() {
return (() => {
- this.a()
- return _h("div", {})
- })()
+ this.a();
+ return _h("div", {});
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/sequence_with_result_and_catch b/spec/compilers/sequence_with_result_and_catch
index 6ba4a9d8d..02194c1b0 100644
--- a/spec/compilers/sequence_with_result_and_catch
+++ b/spec/compilers/sequence_with_result_and_catch
@@ -26,46 +26,46 @@ component Main {
--------------------------------------------------------------------------------
const B = new(class extends _M {
b(d) {
- return (new Err(arguments[0]))
+ return (new Err(arguments[0]));
}
-})
+});
class A extends _C {
a() {
return (async () => {
- let _ = null
+ let _ = null;
try {
- let _0 = B.b(``)
+ let _0 = B.b(``);
if (_0 instanceof Err) {
- let _error = _0._0
+ let _error = _0._0;
- let c = _error
- _ = `test`
- throw new DoError()
- }
+ let c = _error;
+ _ = `test`;
+ throw new DoError();
+ };
- _0._0
+ _0._0;
- _ = await `test`
+ _ = await `test`;
} catch (_error) {
if (!(_error instanceof DoError)) {
- console.warn(`Unhandled error in sequence expression:`)
- console.warn(_error)
+ console.warn(`Unhandled error in sequence expression:`);
+ console.warn(_error);
}
- }
+ };
- return _
- })()
+ return _;
+ })();
}
render() {
return (() => {
- this.a()
- return _h("div", {})
- })()
+ this.a();
+ return _h("div", {});
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/sequence_with_result_and_catch_all b/spec/compilers/sequence_with_result_and_catch_all
index f421b208f..233df4e1c 100644
--- a/spec/compilers/sequence_with_result_and_catch_all
+++ b/spec/compilers/sequence_with_result_and_catch_all
@@ -26,41 +26,41 @@ component Main {
--------------------------------------------------------------------------------
const B = new(class extends _M {
b(c) {
- return (new Err(c))
+ return (new Err(c));
}
-})
+});
class A extends _C {
a() {
return (async () => {
- let _ = null
+ let _ = null;
try {
- let _0 = B.b(``)
+ let _0 = B.b(``);
if (_0 instanceof Err) {
throw _0._0
- }
+ };
- _0._0
+ _0._0;
- _ = await `test`
+ _ = await `test`;
} catch (_error) {
if (!(_error instanceof DoError)) {
_ = `test`
}
- }
+ };
- return _
- })()
+ return _;
+ })();
}
render() {
return (() => {
- this.a()
- return _h("div", {})
- })()
+ this.a();
+ return _h("div", {});
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/state b/spec/compilers/state
index 891c32d02..8c7858409 100644
--- a/spec/compilers/state
+++ b/spec/compilers/state
@@ -13,29 +13,29 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
constructor(props) {
- super(props)
+ super(props);
this.state = new Record({
b: `Hello`,
c: `0`
- })
+ });
}
get b() {
- return this.state.b
+ return this.state.b;
}
get c() {
- return this.state.c
+ return this.state.c;
}
a() {
- return this.b + this.c
+ return this.b + this.c;
}
render() {
- return this.a()
+ return this.a();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/statement b/spec/compilers/statement
index 77d501e25..446ad039f 100644
--- a/spec/compilers/statement
+++ b/spec/compilers/statement
@@ -12,10 +12,10 @@ component Main {
class A extends _C {
render() {
return (() => {
- let a = `hello`
- return a
- })()
+ let a = `hello`;
+ return a;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/store b/spec/compilers/store
index f29f8340e..f24b8a744 100644
--- a/spec/compilers/store
+++ b/spec/compilers/store
@@ -16,38 +16,38 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
get a() {
- return B.b
+ return B.b;
}
componentWillUnmount() {
- B._unsubscribe(this)
+ B._unsubscribe(this);
}
componentDidMount() {
- B._subscribe(this)
+ B._subscribe(this);
}
render() {
- return this.a
+ return this.a;
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
const B = new(class extends _S {
constructor() {
- super()
+ super();
this.state = {
b: ``
- }
+ };
}
get b() {
- return this.state.b
+ return this.state.b;
}
c() {
- return `hello`
+ return `hello`;
}
-})
+});
diff --git a/spec/compilers/store_with_get b/spec/compilers/store_with_get
index 64b1a45d6..67858cd72 100644
--- a/spec/compilers/store_with_get
+++ b/spec/compilers/store_with_get
@@ -16,38 +16,38 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
get a() {
- return B.b
+ return B.b;
}
componentWillUnmount() {
- B._unsubscribe(this)
+ B._unsubscribe(this);
}
componentDidMount() {
- B._subscribe(this)
+ B._subscribe(this);
}
render() {
- return this.a
+ return this.a;
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
const B = new(class extends _S {
constructor() {
- super()
+ super();
this.state = {
b: ``
- }
+ };
}
get b() {
- return this.state.b
+ return this.state.b;
}
get c() {
- return `hello`
+ return `hello`;
}
-})
+});
diff --git a/spec/compilers/string_literal_escaped b/spec/compilers/string_literal_escaped
index e1917867d..dd1f54844 100644
--- a/spec/compilers/string_literal_escaped
+++ b/spec/compilers/string_literal_escaped
@@ -6,8 +6,8 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
render() {
- return `Hello There "Joe"`
+ return `Hello There "Joe"`;
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/string_literal_simple b/spec/compilers/string_literal_simple
index 3d5a056f3..bc3217f7e 100644
--- a/spec/compilers/string_literal_simple
+++ b/spec/compilers/string_literal_simple
@@ -6,8 +6,8 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
render() {
- return `Hello There`
+ return `Hello There`;
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/string_literal_with_backtick b/spec/compilers/string_literal_with_backtick
index b516511ad..bbafeb2be 100644
--- a/spec/compilers/string_literal_with_backtick
+++ b/spec/compilers/string_literal_with_backtick
@@ -6,8 +6,8 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
render() {
- return `Hello There \`Joe\``
+ return `Hello There \`Joe\``;
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/try b/spec/compilers/try
index 24a525a5f..c5ef95f26 100644
--- a/spec/compilers/try
+++ b/spec/compilers/try
@@ -9,9 +9,9 @@ component Main {
class A extends _C {
render() {
return (() => {
- return `hello`
- })()
+ return `hello`;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/try_with_catch_all b/spec/compilers/try_with_catch_all
index 762e16805..ba36a0af6 100644
--- a/spec/compilers/try_with_catch_all
+++ b/spec/compilers/try_with_catch_all
@@ -19,9 +19,9 @@ component Main {
--------------------------------------------------------------------------------
const B = new(class extends _M {
b(c) {
- return (new Err(c))
+ return (new Err(c));
}
-})
+});
class A extends _C {
render() {
@@ -30,18 +30,18 @@ class A extends _C {
return `Blah`
}
- let _0 = B.b(`Blah`)
+ let _0 = B.b(`Blah`);
if (_0 instanceof Err) {
- let _error = _0._0
- return _catch_all()
- }
+ let _error = _0._0;
+ return _catch_all();
+ };
- let a = _0._0
+ let a = _0._0;
- return `Hello`
- })()
+ return `Hello`;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/try_with_catches b/spec/compilers/try_with_catches
index 7713bf4fd..f2153704f 100644
--- a/spec/compilers/try_with_catches
+++ b/spec/compilers/try_with_catches
@@ -19,27 +19,27 @@ component Main {
--------------------------------------------------------------------------------
const B = new(class extends _M {
b(d) {
- return (new Err(d))
+ return (new Err(d));
}
-})
+});
class A extends _C {
render() {
return (() => {
- let _0 = B.b(`Blah`)
+ let _0 = B.b(`Blah`);
if (_0 instanceof Err) {
- let _error = _0._0
+ let _error = _0._0;
- let c = _error
- return c
- }
+ let c = _error;
+ return c;
+ };
- let a = _0._0
+ let a = _0._0;
- return a
- })()
+ return a;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/try_with_statement b/spec/compilers/try_with_statement
index 77d501e25..446ad039f 100644
--- a/spec/compilers/try_with_statement
+++ b/spec/compilers/try_with_statement
@@ -12,10 +12,10 @@ component Main {
class A extends _C {
render() {
return (() => {
- let a = `hello`
- return a
- })()
+ let a = `hello`;
+ return a;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/variable_argument b/spec/compilers/variable_argument
index af8582607..635bc60b4 100644
--- a/spec/compilers/variable_argument
+++ b/spec/compilers/variable_argument
@@ -10,12 +10,12 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a(b) {
- return b
+ return b;
}
render() {
- return this.a(`X`)
+ return this.a(`X`);
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/variable_component_function b/spec/compilers/variable_component_function
index fad4627c9..35f8d6977 100644
--- a/spec/compilers/variable_component_function
+++ b/spec/compilers/variable_component_function
@@ -10,12 +10,12 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return `Hello`
+ return `Hello`;
}
render() {
- return this.a()
+ return this.a();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/variable_component_get b/spec/compilers/variable_component_get
index 5414c9837..34d2108eb 100644
--- a/spec/compilers/variable_component_get
+++ b/spec/compilers/variable_component_get
@@ -10,12 +10,12 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
get a() {
- return `Hello`
+ return `Hello`;
}
render() {
- return this.a
+ return this.a;
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/variable_component_property b/spec/compilers/variable_component_property
index 9a4ce4338..f249931f8 100644
--- a/spec/compilers/variable_component_property
+++ b/spec/compilers/variable_component_property
@@ -8,19 +8,19 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
constructor(props) {
- super(props)
+ super(props);
this._d({
a: [
null,
`Hello`
]
- })
+ });
}
render() {
- return this.a
+ return this.a;
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/variable_module_function b/spec/compilers/variable_module_function
index a9fbb4c87..e12495b01 100644
--- a/spec/compilers/variable_module_function
+++ b/spec/compilers/variable_module_function
@@ -18,20 +18,20 @@ component Main {
--------------------------------------------------------------------------------
const B = new(class extends _M {
c() {
- return `Hello`
+ return `Hello`;
}
b() {
- return B.c
+ return B.c;
}
-})
+});
class A extends _C {
render() {
- let a = B.b()
- return a()
+ let a = B.b();
+ return a();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/variable_where b/spec/compilers/variable_where
index b1b892b92..748d73cb8 100644
--- a/spec/compilers/variable_where
+++ b/spec/compilers/variable_where
@@ -13,14 +13,14 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- let b = `Hello`
- return b
+ let b = `Hello`;
+ return b;
}
render() {
- return this.a()
+ return this.a();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/void b/spec/compilers/void
index 2044b60df..5b318e585 100644
--- a/spec/compilers/void
+++ b/spec/compilers/void
@@ -14,15 +14,15 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- return null
+ return null;
}
render() {
return (() => {
- let b = this.a
- return ``
- })()
+ let b = this.a;
+ return ``;
+ })();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/where b/spec/compilers/where
index a924736e1..fc8d237fd 100644
--- a/spec/compilers/where
+++ b/spec/compilers/where
@@ -18,16 +18,16 @@ component Main {
--------------------------------------------------------------------------------
class A extends _C {
a() {
- let b = `Asd`
+ let b = `Asd`;
return _h("div", {}, [
b
- ])
+ ]);
}
render() {
- return this.a()
+ return this.a();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/compilers/with b/spec/compilers/with
index aaced2e13..d732b93b1 100644
--- a/spec/compilers/with
+++ b/spec/compilers/with
@@ -14,14 +14,14 @@ component Main {
--------------------------------------------------------------------------------
const B = new(class extends _M {
a() {
- return ``
+ return ``;
}
-})
+});
class A extends _C {
render() {
- return B.a()
+ return B.a();
}
-}
+};
-A.displayName = "Main"
+A.displayName = "Main";
diff --git a/spec/formatters/css_with_arguments b/spec/formatters/css_with_arguments
new file mode 100644
index 000000000..84184ded0
--- /dev/null
+++ b/spec/formatters/css_with_arguments
@@ -0,0 +1,18 @@
+component A {
+ styletest(name:String){background: red;color: blue;}
+
+ fun render : Html {
+
+ }
+}
+--------------------------------------------------------------------------------
+component A {
+ style test (name : String) {
+ background: red;
+ color: blue;
+ }
+
+ fun render : Html {
+
+ }
+}
diff --git a/spec/formatters/css_with_case b/spec/formatters/css_with_case
new file mode 100644
index 000000000..d77f77f8f
--- /dev/null
+++ b/spec/formatters/css_with_case
@@ -0,0 +1,31 @@
+component A {
+ style test {
+ case (true) {
+ false =>
+ background: red;
+ color: blue;
+
+ true => color: red;
+ }
+ }
+
+ fun render : Html {
+
+ }
+}
+--------------------------------------------------------------------------------
+component A {
+ style test {
+ case (true) {
+ false =>
+ background: red;
+ color: blue;
+
+ true => color: red;
+ }
+ }
+
+ fun render : Html {
+
+ }
+}
diff --git a/spec/formatters/css_with_comments b/spec/formatters/css_with_comments
index f548d3d1c..f774eb2c2 100644
--- a/spec/formatters/css_with_comments
+++ b/spec/formatters/css_with_comments
@@ -26,7 +26,7 @@ component A {
color: blue;
/* C */
- & selector {
+ selector {
/* D */
x: y;
diff --git a/spec/formatters/css_with_if b/spec/formatters/css_with_if
new file mode 100644
index 000000000..b2a627349
--- /dev/null
+++ b/spec/formatters/css_with_if
@@ -0,0 +1,23 @@
+component A {
+ styletest{background: red;color: blue;
+ if(true){color:yellow;}}
+
+ fun render : Html {
+
+ }
+}
+--------------------------------------------------------------------------------
+component A {
+ style test {
+ background: red;
+ color: blue;
+
+ if (true) {
+ color: yellow;
+ }
+ }
+
+ fun render : Html {
+
+ }
+}
diff --git a/spec/formatters/css_with_if_and_else b/spec/formatters/css_with_if_and_else
new file mode 100644
index 000000000..35f7465c7
--- /dev/null
+++ b/spec/formatters/css_with_if_and_else
@@ -0,0 +1,25 @@
+component A {
+ styletest{background: red;color: blue;
+ if(true){color:yellow;}else{color:brown;}}
+
+ fun render : Html {
+
+ }
+}
+--------------------------------------------------------------------------------
+component A {
+ style test {
+ background: red;
+ color: blue;
+
+ if (true) {
+ color: yellow;
+ } else {
+ color: brown;
+ }
+ }
+
+ fun render : Html {
+
+ }
+}
diff --git a/spec/formatters/css_with_interpolation b/spec/formatters/css_with_interpolation
index 53b23535c..109efd601 100644
--- a/spec/formatters/css_with_interpolation
+++ b/spec/formatters/css_with_interpolation
@@ -1,5 +1,5 @@
component A {
- styletest{background: { "red"
+ styletest{background: #{ "red"
};color: blue;}
fun render : Html {
@@ -9,7 +9,7 @@ component A {
--------------------------------------------------------------------------------
component A {
style test {
- background: {"red"};
+ background: #{"red"};
color: blue;
}
diff --git a/spec/formatters/css_with_selector b/spec/formatters/css_with_selector
index 72fa0fa6c..754f7643b 100644
--- a/spec/formatters/css_with_selector
+++ b/spec/formatters/css_with_selector
@@ -12,7 +12,7 @@ component A {
--------------------------------------------------------------------------------
component A {
style test {
- & div {
+ div {
color: red;
}
diff --git a/spec/formatters/html_style b/spec/formatters/html_style
new file mode 100644
index 000000000..9648108ad
--- /dev/null
+++ b/spec/formatters/html_style
@@ -0,0 +1,20 @@
+component Test {
+ style base(name : String, active : Bool) {
+ color: red;
+ }
+
+ fun render : Html {
+
+
+ }
+}
+--------------------------------------------------------------------------------
+component Test {
+ style base (name : String, active : Bool) {
+ color: red;
+ }
+
+ fun render : Html {
+
+ }
+}
diff --git a/spec/name_pool_spec.cr b/spec/name_pool_spec.cr
new file mode 100644
index 000000000..4edb89f60
--- /dev/null
+++ b/spec/name_pool_spec.cr
@@ -0,0 +1,13 @@
+require "./spec_helper"
+
+describe Mint::NamePool do
+ it "returns nex name" do
+ pool = Mint::NamePool(String, Mint::StyleBuilder::Selector).new
+ object = Mint::StyleBuilder::Selector.new
+
+ pool.of("a", object).should eq("a")
+ pool.of("a", object).should eq("a")
+ pool.of("b", object).should eq("b")
+ pool.of("c", object).should eq("c")
+ end
+end
diff --git a/spec/parsers/css_definition_spec.cr b/spec/parsers/css_definition_spec.cr
index 15fb52598..877afb0e9 100644
--- a/spec/parsers/css_definition_spec.cr
+++ b/spec/parsers/css_definition_spec.cr
@@ -7,16 +7,15 @@ describe "Css Definition" do
expect_ignore "A"
expect_ignore ":"
- expect_error "a", Mint::Parser::CssDefinitionExpectedColon
expect_error "a:", Mint::Parser::CssDefinitionExpectedSemicolon
expect_error "a: b", Mint::Parser::CssDefinitionExpectedSemicolon
- expect_error "a: {", Mint::Parser::CssInterpolationExpectedExpression
- expect_error "a: {a", Mint::Parser::CssInterpolationExpectedClosingBracket
+ expect_error "a: \#{", Mint::Parser::CssInterpolationExpectedExpression
+ expect_error "a: \#{a", Mint::Parser::CssInterpolationExpectedClosingBracket
- expect_ok "a: {a};"
- expect_ok "a: x {a} v;"
- expect_ok "a: x {a} v {a};"
- expect_ok "a: x {a}{a};"
+ expect_ok "a: \#{a};"
+ expect_ok "a: x \#{a} v;"
+ expect_ok "a: x \#{a} v \#{a};"
+ expect_ok "a: x \#{a}\#{a};"
expect_ok "a: b;"
expect_ok "-WebKit-Box: 0 red;"
expect_ok "-webit-box-shadow: 0 0 20px black;"
diff --git a/spec/parsers/css_interpolation_spec.cr b/spec/parsers/css_interpolation_spec.cr
index 9c99a3fb3..b85a998e8 100644
--- a/spec/parsers/css_interpolation_spec.cr
+++ b/spec/parsers/css_interpolation_spec.cr
@@ -6,12 +6,13 @@ describe "Css Interpolation" do
expect_ignore ""
expect_ignore "??"
expect_ignore "asd"
+ expect_ignore "{"
- expect_error "{", Mint::Parser::CssInterpolationExpectedExpression
- expect_error "{ ", Mint::Parser::CssInterpolationExpectedExpression
- expect_error "{a", Mint::Parser::CssInterpolationExpectedClosingBracket
- expect_error "{a ", Mint::Parser::CssInterpolationExpectedClosingBracket
+ expect_error "\#{", Mint::Parser::CssInterpolationExpectedExpression
+ expect_error "\#{ ", Mint::Parser::CssInterpolationExpectedExpression
+ expect_error "\#{a", Mint::Parser::CssInterpolationExpectedClosingBracket
+ expect_error "\#{a ", Mint::Parser::CssInterpolationExpectedClosingBracket
- expect_ok "{a}"
- expect_ok "{ a }"
+ expect_ok "\#{a}"
+ expect_ok "\#{ a }"
end
diff --git a/spec/parsers/css_selector_spec.cr b/spec/parsers/css_selector_spec.cr
index d0847a8ef..04357a565 100644
--- a/spec/parsers/css_selector_spec.cr
+++ b/spec/parsers/css_selector_spec.cr
@@ -3,14 +3,10 @@ require "../spec_helper"
describe "Css Selectors" do
subject css_selector
- expect_error "&v", Mint::Parser::CssSelectorSpaceAfterAmpersand
- expect_error "& ", Mint::Parser::CssSelectorExpectedName
- expect_error "& v", Mint::Parser::CssSelectorExpectedOpeningBracket
- expect_error "& v ", Mint::Parser::CssSelectorExpectedOpeningBracket
- expect_error "& v {", Mint::Parser::CssSelectorExpectedClosingBracket
- expect_error "& v { ", Mint::Parser::CssSelectorExpectedClosingBracket
- expect_error "& v { a: b;", Mint::Parser::CssSelectorExpectedClosingBracket
+ expect_error "v {", Mint::Parser::CssSelectorExpectedClosingBracket
+ expect_error "v { ", Mint::Parser::CssSelectorExpectedClosingBracket
+ expect_error "v { a: b;", Mint::Parser::CssSelectorExpectedClosingBracket
- expect_ok "& valami { }"
- expect_ok "& valami { a: b; }"
+ expect_ok "valami { }"
+ expect_ok "valami { a: b; }"
end
diff --git a/spec/parsers/html_element_spec.cr b/spec/parsers/html_element_spec.cr
index 1196f6782..d8b68e4d9 100644
--- a/spec/parsers/html_element_spec.cr
+++ b/spec/parsers/html_element_spec.cr
@@ -14,6 +14,8 @@ describe "Html Element" do
expect_error ""
+ expect_ok ""
+ expect_ok ""
expect_ok ""
expect_ok " "
expect_ok " "
diff --git a/spec/parsers/style_spec.cr b/spec/parsers/style_spec.cr
index 3064c9ef5..c14ff578c 100644
--- a/spec/parsers/style_spec.cr
+++ b/spec/parsers/style_spec.cr
@@ -15,6 +15,8 @@ describe "Component Style" do
expect_error "style t {", Mint::Parser::StyleExpectedClosingBracket
expect_error "style t { a: b;", Mint::Parser::StyleExpectedClosingBracket
expect_error "style t { a: b; ", Mint::Parser::StyleExpectedClosingBracket
+ expect_error "style t (name : String", Mint::Parser::StyleExpectedClosingParentheses
expect_ok "style t { a: b; }"
+ expect_ok "style t (name : String) { a: name; }"
end
diff --git a/spec/style_builder_spec.cr b/spec/style_builder_spec.cr
new file mode 100644
index 000000000..b149c74ec
--- /dev/null
+++ b/spec/style_builder_spec.cr
@@ -0,0 +1,66 @@
+require "./spec_helper"
+
+describe Mint::StyleBuilder do
+ it "builds simple styles" do
+ example =
+ <<-MINT
+ style test {
+ div, p {
+ background: red;
+
+ span, strong {
+ pre {
+ color: \#{"red"};
+ }
+ }
+
+ span, strong {
+ pre {
+ background: white;
+
+ @media (screen) {
+ color: blue;
+
+ a {
+ border: 1px solid red;
+ }
+ }
+ }
+ }
+ }
+
+ @media (screen) {
+ div, p {
+ font-size: 30px;
+
+ if (true) {
+ color: red;
+ }
+ }
+ }
+
+ @media (screen) {
+ div, p {
+ color: blue;
+ }
+
+ @media (print) {
+ div, p {
+ color: black;
+ border-radius: \#{10}px;
+ }
+ }
+ }
+ }
+ MINT
+
+ parser =
+ Mint::Parser.new(example.strip, "test.mint")
+
+ style =
+ parser.style.not_nil!
+
+ builder = Mint::StyleBuilder.new
+ builder.process(style)
+ end
+end
diff --git a/spec/type_checking/css_definition b/spec/type_checking/css_definition
index 4afc48306..5ca9bf6d2 100644
--- a/spec/type_checking/css_definition
+++ b/spec/type_checking/css_definition
@@ -1,10 +1,10 @@
component Main {
style test {
- color: {"blue"};
- color: {color};
+ color: #{"blue"};
+ color: #{color};
color: red;
- color: {0};
- top: {top};
+ color: #{0};
+ top: #{top};
}
get color : String {
@@ -22,7 +22,7 @@ component Main {
-------------------------------------------------------CssDefinitionTypeMismatch
component Main {
style test {
- color: {true};
+ color: #{true};
}
fun render : Html {
diff --git a/spec/type_checking/css_selector b/spec/type_checking/css_selector
index 7d772745b..5aabdc850 100644
--- a/spec/type_checking/css_selector
+++ b/spec/type_checking/css_selector
@@ -1,7 +1,7 @@
component Main {
style test {
& div {
- color: {color};
+ color: #{color};
}
&:focus {
@@ -21,7 +21,7 @@ component Main {
component Main {
style test {
& div {
- color: {color};
+ color: #{color};
}
&:focus {
color: red;
diff --git a/spec/type_checking/css_with_arguments b/spec/type_checking/css_with_arguments
new file mode 100644
index 000000000..6cf93a4e0
--- /dev/null
+++ b/spec/type_checking/css_with_arguments
@@ -0,0 +1,19 @@
+component Main {
+ style test(name : String) {
+ color: #{name};
+ }
+
+ fun render : Html {
+
+ }
+}
+-----------------------------------------------------------------VariableMissing
+component Main {
+ style test(name : String) {
+ color: #{name2};
+ }
+
+ fun render : Html {
+
+ }
+}
diff --git a/spec/type_checking/html_element_style b/spec/type_checking/html_element_style
index 4016536a2..ece1768f2 100644
--- a/spec/type_checking/html_element_style
+++ b/spec/type_checking/html_element_style
@@ -8,7 +8,7 @@ component Main {
}
}
---------------------------------------------------------HtmlElementNotFoundStyle
+---------------------------------------------------------------HtmlStyleNotFound
component Main {
fun render : Html {
diff --git a/spec/type_checking/html_style b/spec/type_checking/html_style
new file mode 100644
index 000000000..56578e702
--- /dev/null
+++ b/spec/type_checking/html_style
@@ -0,0 +1,39 @@
+component Main {
+ style base (name : String, active : Bool) {
+ color: red;
+ }
+
+ fun render : Html {
+
+ }
+}
+---------------------------------------------------HtmlStyleArgumentSizeMismatch
+component Main {
+ style base (name : String, active : Bool) {
+ color: red;
+ }
+
+ fun render : Html {
+
+ }
+}
+---------------------------------------------------HtmlStyleArgumentSizeMismatch
+component Main {
+ style base (name : String, active : Bool) {
+ color: red;
+ }
+
+ fun render : Html {
+
+ }
+}
+---------------------------------------------------HtmlStyleArgumentTypeMismatch
+component Main {
+ style base (name : String, active : Bool) {
+ color: red;
+ }
+
+ fun render : Html {
+
+ }
+}
diff --git a/src/all.cr b/src/all.cr
index c33144f78..5fcef0e03 100644
--- a/src/all.cr
+++ b/src/all.cr
@@ -32,6 +32,8 @@ require "./ast/node"
require "./ast/**"
require "./ast"
+require "./style_builder"
+
require "./type_checkers/**"
require "./type_checker"
diff --git a/src/ast/case_branch.cr b/src/ast/case_branch.cr
index 1700727cc..bbab8560b 100644
--- a/src/ast/case_branch.cr
+++ b/src/ast/case_branch.cr
@@ -3,7 +3,7 @@ module Mint
class CaseBranch < Node
getter match, expression
- def initialize(@expression : Expression,
+ def initialize(@expression : Node | Array(CssDefinition),
@match : Node | Nil,
@input : Data,
@from : Int32,
diff --git a/src/ast/css_media.cr b/src/ast/css_media.cr
index e4690dcf8..b5c56c014 100644
--- a/src/ast/css_media.cr
+++ b/src/ast/css_media.cr
@@ -1,10 +1,9 @@
module Mint
class Ast
class CssMedia < Node
- getter content, definitions, comments
+ getter content, body
- def initialize(@definitions : Array(CssDefinition),
- @comments : Array(Comment),
+ def initialize(@body : Array(Node),
@content : String,
@input : Data,
@from : Int32,
diff --git a/src/ast/css_selector.cr b/src/ast/css_selector.cr
index 82877f414..af7033434 100644
--- a/src/ast/css_selector.cr
+++ b/src/ast/css_selector.cr
@@ -1,11 +1,10 @@
module Mint
class Ast
class CssSelector < Node
- getter selectors, definitions, comments
+ getter selectors, body
- def initialize(@definitions : Array(CssDefinition),
- @comments : Array(Comment),
- @selectors : Array(String),
+ def initialize(@selectors : Array(String),
+ @body : Array(Node),
@input : Data,
@from : Int32,
@to : Int32)
diff --git a/src/ast/html_element.cr b/src/ast/html_element.cr
index c0e365181..9cd896ba7 100644
--- a/src/ast/html_element.cr
+++ b/src/ast/html_element.cr
@@ -1,12 +1,12 @@
module Mint
class Ast
class HtmlElement < Node
- getter attributes, children, style, tag, comments, ref
+ getter attributes, children, styles, tag, comments, ref
def initialize(@attributes : Array(HtmlAttribute),
@children : Array(HtmlContent),
@comments : Array(Comment),
- @style : Variable | Nil,
+ @styles : Array(HtmlStyle),
@ref : Variable | Nil,
@tag : Variable,
@input : Data,
diff --git a/src/ast/html_style.cr b/src/ast/html_style.cr
new file mode 100644
index 000000000..114d6c78a
--- /dev/null
+++ b/src/ast/html_style.cr
@@ -0,0 +1,14 @@
+module Mint
+ class Ast
+ class HtmlStyle < Node
+ getter name, arguments
+
+ def initialize(@arguments : Array(Expression),
+ @name : Variable,
+ @input : Data,
+ @from : Int32,
+ @to : Int32)
+ end
+ end
+ end
+end
diff --git a/src/ast/if.cr b/src/ast/if.cr
index 41aaaaa83..b52d45593 100644
--- a/src/ast/if.cr
+++ b/src/ast/if.cr
@@ -1,17 +1,21 @@
module Mint
class Ast
class If < Node
- getter condition, truthy, falsy
getter truthy_head_comments, truthy_tail_comments
getter falsy_head_comments, falsy_tail_comments
+ getter condition, branches
+
+ alias Branches = Tuple(Array(CssDefinition), Array(CssDefinition)) |
+ Tuple(Array(CssDefinition), Nil) |
+ Tuple(Array(CssDefinition), If) |
+ Tuple(Node, Node)
def initialize(@truthy_head_comments : Array(Comment),
@truthy_tail_comments : Array(Comment),
@falsy_head_comments : Array(Comment),
@falsy_tail_comments : Array(Comment),
- @condition : Expression,
- @truthy : Expression,
- @falsy : Expression,
+ @branches : Branches,
+ @condition : Node,
@input : Data,
@from : Int32,
@to : Int32)
diff --git a/src/ast/style.cr b/src/ast/style.cr
index 5ce5ff66c..6044a2f35 100644
--- a/src/ast/style.cr
+++ b/src/ast/style.cr
@@ -1,12 +1,10 @@
module Mint
class Ast
class Style < Node
- getter name, definitions, selectors, medias, comments
+ getter name, body, arguments
- def initialize(@definitions : Array(CssDefinition),
- @selectors : Array(CssSelector),
- @comments : Array(Comment),
- @medias : Array(CssMedia),
+ def initialize(@arguments : Array(Argument),
+ @body : Array(Node),
@name : Variable,
@input : Data,
@from : Int32,
diff --git a/src/compiler.cr b/src/compiler.cr
index 901dc1625..21f61ad4d 100644
--- a/src/compiler.cr
+++ b/src/compiler.cr
@@ -1,12 +1,13 @@
module Mint
class Compiler
- delegate dynamic_styles, styles, ast, types, variables, to: @artifacts
- delegate html_elements, medias, lookups, checked, cache, to: @artifacts
+ delegate lookups, checked, cache, to: @artifacts
+ delegate ast, types, variables, to: @artifacts
delegate record_field_lookup, to: @artifacts
- getter js
+ getter js, style_builder
def initialize(@artifacts : TypeChecker::Artifacts, @optimize = false)
+ @style_builder = StyleBuilder.new
@js = Js.new(optimize: @optimize)
@decoder = Decoder.new(@js)
end
diff --git a/src/compilers/case.cr b/src/compilers/case.cr
index 2df81ff52..4a155c906 100644
--- a/src/compilers/case.cr
+++ b/src/compilers/case.cr
@@ -1,6 +1,14 @@
module Mint
class Compiler
- def _compile(node : Ast::Case) : String
+ def compile(node : Ast::Case, block : Proc(String, String) | Nil = nil) : String
+ if checked.includes?(node)
+ _compile node, block
+ else
+ ""
+ end
+ end
+
+ def _compile(node : Ast::Case, block : Proc(String, String) | Nil = nil) : String
condition =
compile node.condition
@@ -11,7 +19,9 @@ module Mint
node
.branches
.sort_by(&.match.nil?.to_s)
- .map_with_index { |branch, index| compile branch, index, variable }
+ .map_with_index do |branch, index|
+ compile branch, index, variable, block
+ end
js.iif do
js.statements([condition_let, js.ifchain(body)])
diff --git a/src/compilers/case_branch.cr b/src/compilers/case_branch.cr
index 656bb4647..75cab3c47 100644
--- a/src/compilers/case_branch.cr
+++ b/src/compilers/case_branch.cr
@@ -1,16 +1,34 @@
module Mint
class Compiler
- def compile(node : Ast::CaseBranch, index : Int32, variable : String) : String
+ def compile(node : Ast::CaseBranch,
+ index : Int32,
+ variable : String,
+ block : Proc(String, String) | Nil = nil) : String
if checked.includes?(node)
- _compile node, index, variable
+ _compile node, index, variable, block
else
""
end
end
- def _compile(node : Ast::CaseBranch, index : Int32, variable : String) : String
+ def _compile(node : Ast::CaseBranch,
+ index : Int32,
+ variable : String,
+ block : Proc(String, String) | Nil = nil) : String
expression =
- compile node.expression
+ case item = node.expression
+ when Array(Ast::CssDefinition)
+ compiled =
+ if block
+ _compile item, block
+ else
+ "{}"
+ end
+ when Ast::Node
+ js.return(compile(item))
+ else
+ ""
+ end
if match = node.match
case match
@@ -24,7 +42,7 @@ module Mint
js.class_of(lookups[match])
js.if("#{variable} instanceof #{name}") do
- js.statements(variables + [js.return(expression)])
+ js.statements(variables + [expression])
end
else
compiled =
@@ -32,17 +50,17 @@ module Mint
if index == 0
js.if("_compare(#{variable}, #{compiled})") do
- js.return(expression)
+ expression
end
else
js.elseif("_compare(#{variable}, #{compiled})") do
- js.return(expression)
+ expression
end
end
end
else
js.else do
- js.return(expression)
+ expression
end
end
end
diff --git a/src/compilers/component.cr b/src/compilers/component.cr
index 31949e367..644ec189a 100644
--- a/src/compilers/component.cr
+++ b/src/compilers/component.cr
@@ -6,6 +6,11 @@ module Mint
compile node.styles, node
+ styles =
+ node.styles.map do |style_node|
+ style_builder.compile_style(style_node, self)
+ end.reject(&.empty?)
+
functions =
compile_component_functions node
@@ -58,7 +63,7 @@ module Mint
end
body =
- ([constructor] + gets + states + store_stuff + functions)
+ ([constructor] + styles + gets + states + store_stuff + functions)
.compact
js.statements([
@@ -81,11 +86,11 @@ module Mint
name = js.variable_of(key)
if store.states.find(&.name.value.==(original))
- memo << js.get(name, "return #{store_name}.#{id}")
+ memo << js.get(name, "return #{store_name}.#{id};")
elsif store.gets.any? { |get| get.name.value == original }
- memo << js.get(name, "return #{store_name}.#{id}")
+ memo << js.get(name, "return #{store_name}.#{id};")
elsif store.functions.any? { |func| func.name.value == original }
- memo << "#{name} (...params) { return #{store_name}.#{id}(...params) }"
+ memo << "#{name} (...params) { return #{store_name}.#{id}(...params); }"
end
end
end
diff --git a/src/compilers/css_body.cr b/src/compilers/css_body.cr
deleted file mode 100644
index ac166b5b4..000000000
--- a/src/compilers/css_body.cr
+++ /dev/null
@@ -1,53 +0,0 @@
-module Mint
- class Compiler
- def compile(selector : String, key : String,
- definitions : Array(Ast::CssDefinition),
- media = nil) : Hash(String, String)
- dynamics = {} of String => String
- regulars = {} of String => String
-
- definitions.each do |item|
- if item.value.any?(&.is_a?(Ast::CssInterpolation))
- name =
- js.style_next_property key
-
- variable =
- "--#{key}-#{name}"
-
- value = item.value.map do |part|
- case part
- when String
- "`#{part}`"
- else
- compile part
- end
- end.reject(&.empty?)
- .join(" + ")
-
- dynamics[variable] = value
- regulars[item.name] = "var(#{variable})"
- else
- value =
- item
- .value
- .select(&.is_a?(String))
- .join(" ")
-
- regulars[item.name] = value
- end
- end
-
- dynamic_styles[key] ||= {} of String => String
- dynamic_styles[key].merge!(dynamics)
-
- if media
- medias[media] ||= {} of String => Hash(String, String)
- medias[media][selector] ||= {} of String => String
- medias[media][selector].merge!(regulars)
- else
- styles[selector] ||= {} of String => String
- styles[selector].merge!(regulars)
- end
- end
- end
-end
diff --git a/src/compilers/html_element.cr b/src/compilers/html_element.cr
index ee2480a75..bf647ead5 100644
--- a/src/compilers/html_element.cr
+++ b/src/compilers/html_element.cr
@@ -1,5 +1,23 @@
module Mint
class Compiler
+ def compile(value : Array(Ast::CssInterpolation | String))
+ if value.any?(&.is_a?(Ast::CssInterpolation))
+ value.map do |part|
+ case part
+ when String
+ "`#{part}`"
+ else
+ compile part
+ end
+ end.reject(&.empty?)
+ .join(" + ")
+ else
+ value
+ .select(&.is_a?(String))
+ .join(" ")
+ end
+ end
+
def _compile(node : Ast::HtmlElement) : String
tag =
node.tag.value
@@ -22,23 +40,14 @@ module Mint
.map { |attribute| resolve(attribute) }
.reduce({} of String => String) { |memo, item| memo.merge(item) }
- component =
- html_elements[node]?
+ style_nodes =
+ node.styles.map { |item| lookups[item] }
class_name =
- if node.style && component
- js.style_of(lookups[node])
- end
-
- class_names =
- if class_name
- medias
- .values
- .map(&.keys)
- .flatten
- .select(&.starts_with?(class_name + "_"))
- .push(class_name)
- .join(" ")
+ if style_nodes.any?
+ style_nodes.map do |style_node|
+ style_builder.style_pool.of(style_node, nil)
+ end.join(" ")
end
class_name_attribute =
@@ -52,36 +61,36 @@ module Mint
end
classes =
- if class_names && class_name_attribute_value
- "#{class_name_attribute_value} + ` #{class_names}`"
+ if class_name && class_name_attribute_value
+ "#{class_name_attribute_value} + ` #{class_name}`"
elsif class_name_attribute_value
"#{class_name_attribute_value}"
- elsif class_names
- "`#{class_names}`"
+ elsif class_name
+ "`#{class_name}`"
end
attributes["className"] = classes if classes
- variables =
- if styles = dynamic_styles[class_name]?
- items =
- styles
- .each_with_object({} of String => String) { |(key, value), memo| memo["[`#{key}`]"] = value }
-
- js.object(items) unless items.empty?
- end
-
custom_styles = node
.attributes
.find(&.name.value.==("style"))
.try { |attribute| compile(attribute.value) }
- if custom_styles && variables
- attributes["style"] = "_style([#{variables}, #{custom_styles}])"
- elsif custom_styles
- attributes["style"] = "_style([#{custom_styles}])"
- elsif variables
- attributes["style"] = variables
+ styles = [] of String
+
+ node.styles.each do |item|
+ if style_builder.any?(lookups[item])
+ arguments =
+ compile item.arguments
+
+ styles << js.call("this.$#{class_name}", arguments)
+ end
+ end
+
+ styles << custom_styles if custom_styles
+
+ if styles.any?
+ attributes["style"] = "_style([#{styles.join(", ")}])"
end
node.ref.try do |ref|
diff --git a/src/compilers/if.cr b/src/compilers/if.cr
index 1d3938c5f..9d6ba17db 100644
--- a/src/compilers/if.cr
+++ b/src/compilers/if.cr
@@ -1,14 +1,56 @@
module Mint
class Compiler
- def _compile(node : Ast::If) : String
+ def _compile(items : Array(Ast::CssDefinition), block : Proc(String, String) | Nil)
+ compiled =
+ items.each_with_object({} of String => String) do |definition, memo|
+ variable =
+ if block
+ block.call(definition.name)
+ else
+ ""
+ end
+
+ value =
+ compile definition.value
+
+ memo["[`#{variable}`]"] = "`#{value}`"
+ end
+
+ "Object.assign(_, #{js.object(compiled)})"
+ end
+
+ def compile(node : Ast::If, block : Proc(String, String) | Nil = nil) : String
+ if checked.includes?(node)
+ _compile node, block
+ else
+ ""
+ end
+ end
+
+ def _compile(node : Ast::If, block : Proc(String, String) | Nil = nil) : String
condition =
compile node.condition
+ truthy_item, falsy_item =
+ node.branches
+
truthy =
- compile node.truthy
+ case item = truthy_item
+ when Array(Ast::CssDefinition)
+ _compile item, block: block
+ else
+ compile item
+ end
falsy =
- compile node.falsy
+ case item = falsy_item
+ when Array(Ast::CssDefinition)
+ _compile item, block: block
+ when Ast::Node
+ compile item
+ else
+ "null"
+ end
"(#{condition} ? #{truthy} : #{falsy})"
end
diff --git a/src/compilers/property.cr b/src/compilers/property.cr
index 5e1a76521..eee82642e 100644
--- a/src/compilers/property.cr
+++ b/src/compilers/property.cr
@@ -12,7 +12,7 @@ module Mint
js.variable_of(node)
body =
- "return this._p('#{prop_name}')"
+ "return this._p('#{prop_name}');"
js.get(name, body)
end
diff --git a/src/compilers/state.cr b/src/compilers/state.cr
index 66a48e09d..e9b22b2f4 100644
--- a/src/compilers/state.cr
+++ b/src/compilers/state.cr
@@ -4,7 +4,7 @@ module Mint
name =
js.variable_of(node)
- js.get(name, "return this.state.#{name}")
+ js.get(name, "return this.state.#{name};")
end
end
end
diff --git a/src/compilers/style.cr b/src/compilers/style.cr
index 60ba20859..34abf374a 100644
--- a/src/compilers/style.cr
+++ b/src/compilers/style.cr
@@ -15,20 +15,7 @@ module Mint
end
def _compile(node : Ast::Style, component : Ast::Component) : Nil
- prefix =
- js.style_of(node)
-
- compile prefix, prefix, node.definitions
-
- node.medias.each_with_index do |item, index|
- compile prefix + "_media_#{index}", prefix, item.definitions, item.content
- end
-
- node.selectors.each do |item|
- item.selectors.each do |selector|
- compile prefix + selector, prefix, item.definitions
- end
- end
+ style_builder.process node
end
end
end
diff --git a/src/compilers/top_level.cr b/src/compilers/top_level.cr
index 2dfb6b4f9..e748e9d68 100644
--- a/src/compilers/top_level.cr
+++ b/src/compilers/top_level.cr
@@ -69,35 +69,14 @@ module Mint
enums =
compile ast.enums
- media_css =
- medias.map do |condition, rules|
- selectors =
- rules.map do |name, items|
- definitions =
- items.map { |key, value| "#{key}: #{value};" }
-
- js.css_rule(".#{name}", definitions)
- end
-
- js.css_rule("@media #{condition}", selectors)
- end
-
- css =
- styles.map do |name, items|
- definitions =
- items.map { |key, value| "#{key}: #{value};" }
-
- js.css_rule(".#{name}", definitions)
- end
-
all_css =
- css + media_css
+ style_builder.compile
footer =
if all_css.empty?
""
else
- "_insertStyles(`\n#{js.css_rules(all_css)}\n`)"
+ "_insertStyles(`\n#{all_css}\n`)"
end
elements =
@@ -205,10 +184,10 @@ module Mint
const _E = mint.Enum;
const _s = (item, callback) => {
- if (item instanceof Nothing) {
+ if (item instanceof #{nothing}) {
return item
} else if (item instanceof #{just}) {
- return new #{just}(callback(item.value))
+ return new #{just}(callback(item._0))
} else {
return callback(item)
}
diff --git a/src/formatters/case_branch.cr b/src/formatters/case_branch.cr
index 1e86a0937..257b671c6 100644
--- a/src/formatters/case_branch.cr
+++ b/src/formatters/case_branch.cr
@@ -2,7 +2,14 @@ module Mint
class Formatter
def format(node : Ast::CaseBranch) : String
expression =
- format node.expression
+ case item = node.expression
+ when Array(Ast::CssDefinition)
+ list item
+ when Ast::Node
+ format item
+ else
+ ""
+ end
match =
format node.match
diff --git a/src/formatters/css_interpolation.cr b/src/formatters/css_interpolation.cr
index af7be5138..e105a962d 100644
--- a/src/formatters/css_interpolation.cr
+++ b/src/formatters/css_interpolation.cr
@@ -4,7 +4,7 @@ module Mint
body =
format node.expression
- "{#{body}}"
+ "\#{#{body}}"
end
end
end
diff --git a/src/formatters/css_media.cr b/src/formatters/css_media.cr
index 77ccc111b..5f9226ae5 100644
--- a/src/formatters/css_media.cr
+++ b/src/formatters/css_media.cr
@@ -1,11 +1,8 @@
module Mint
class Formatter
def format(node : Ast::CssMedia) : String
- items =
- node.definitions + node.comments
-
body =
- list items
+ list node.body
"@media #{node.content.strip} {\n#{indent(body)}\n}"
end
diff --git a/src/formatters/css_selector.cr b/src/formatters/css_selector.cr
index 5d5facee1..b0f64aa9b 100644
--- a/src/formatters/css_selector.cr
+++ b/src/formatters/css_selector.cr
@@ -4,14 +4,11 @@ module Mint
selectors =
node
.selectors
- .map { |item| "{item}" }
+ .map { |item| item.starts_with?(" ") ? item.lstrip : "{item}" }
.join(",\n")
- items =
- node.definitions + node.comments
-
body =
- list items
+ list node.body
"#{selectors} {\n#{indent(body)}\n}"
end
diff --git a/src/formatters/html_element.cr b/src/formatters/html_element.cr
index 63f6e2c0b..2cbecbc40 100644
--- a/src/formatters/html_element.cr
+++ b/src/formatters/html_element.cr
@@ -4,12 +4,9 @@ module Mint
tag =
format node.tag
- style =
- format node.style
-
prefix =
- if style
- "#{tag}::#{style}"
+ if styles = node.styles
+ "#{tag}#{format(styles, "")}"
else
tag
end
diff --git a/src/formatters/html_style.cr b/src/formatters/html_style.cr
new file mode 100644
index 000000000..32e5f218e
--- /dev/null
+++ b/src/formatters/html_style.cr
@@ -0,0 +1,20 @@
+module Mint
+ class Formatter
+ def format(node : Ast::HtmlStyle) : String
+ name =
+ node.name.value
+
+ arguments =
+ if node.arguments.any?
+ items =
+ format node.arguments, ", "
+
+ "(#{items})"
+ else
+ ""
+ end
+
+ "::#{name}#{arguments}"
+ end
+ end
+end
diff --git a/src/formatters/if.cr b/src/formatters/if.cr
index dbfb0ea47..1cbd7b50f 100644
--- a/src/formatters/if.cr
+++ b/src/formatters/if.cr
@@ -4,19 +4,34 @@ module Mint
condition =
format node.condition
+ truthy_item, falsy_item =
+ node.branches
+
truthy =
- list [node.truthy] + node.truthy_head_comments + node.truthy_tail_comments
+ case truthy_item
+ when Array(Ast::CssDefinition)
+ list truthy_item + node.truthy_head_comments + node.truthy_tail_comments
+ when Ast::Node
+ list [truthy_item] + node.truthy_head_comments + node.truthy_tail_comments
+ else
+ ""
+ end
falsy =
- if node.falsy.is_a?(Ast::If) &&
+ if falsy_item.is_a?(Ast::If) &&
node.falsy_head_comments.empty? &&
node.falsy_tail_comments.empty?
- format node.falsy
+ " else " + format(falsy_item)
else
body =
- list [node.falsy] + node.falsy_head_comments + node.falsy_tail_comments
+ case falsy_item
+ when Array(Ast::CssDefinition)
+ list falsy_item + node.falsy_head_comments + node.falsy_tail_comments
+ when Ast::Node
+ list [falsy_item] + node.falsy_head_comments + node.falsy_tail_comments
+ end
- "{\n#{indent(body)}\n}"
+ " else {\n#{indent(body)}\n}" if body
end
condition =
@@ -29,7 +44,7 @@ module Mint
condition
end
- "if (#{condition}) {\n#{indent(truthy)}\n} else #{falsy}"
+ "if (#{condition}) {\n#{indent(truthy)}\n}#{falsy}"
end
end
end
diff --git a/src/formatters/style.cr b/src/formatters/style.cr
index 3e22a0867..f07a64844 100644
--- a/src/formatters/style.cr
+++ b/src/formatters/style.cr
@@ -1,16 +1,27 @@
module Mint
class Formatter
def format(node : Ast::Style) : String
- items =
- node.definitions + node.selectors + node.medias + node.comments
-
name =
format node.name
body =
- list items
+ list node.body
+
+ arguments =
+ unless node.arguments.empty?
+ value =
+ format node.arguments
+
+ if value
+ .map { |string| replace_skipped(string) }
+ .map(&.size).sum > 50
+ "(\n#{indent(value.join(",\n"))}\n) "
+ else
+ "(#{value.join(", ")}) "
+ end
+ end
- "style #{name} {\n#{indent(body)}\n}"
+ "style #{name} #{arguments}{\n#{indent(body)}\n}"
end
end
end
diff --git a/src/js.cr b/src/js.cr
index 839b46fa3..61bed0e1d 100644
--- a/src/js.cr
+++ b/src/js.cr
@@ -204,6 +204,7 @@ module Mint
end
memo += item
+ memo += ";" unless memo.ends_with?(";")
memo
end
end
diff --git a/src/messages/css_definition_expected_colon.cr b/src/messages/css_definition_expected_colon.cr
deleted file mode 100644
index f14cfb5a9..000000000
--- a/src/messages/css_definition_expected_colon.cr
+++ /dev/null
@@ -1,13 +0,0 @@
-message CssDefinitionExpectedColon do
- title "Syntax Error"
-
- block do
- text "A CSS property and its value must be separated by a"
- bold "colon"
- code ":"
- end
-
- was_looking_for "colon", got, ":"
-
- snippet node
-end
diff --git a/src/messages/css_selector_expected_name.cr b/src/messages/css_selector_expected_name.cr
deleted file mode 100644
index 2f70fb871..000000000
--- a/src/messages/css_selector_expected_name.cr
+++ /dev/null
@@ -1,11 +0,0 @@
-message CssSelectorExpectedName do
- title "Syntax Error"
-
- block do
- text "A sub selector must define a selector after the ampersand."
- end
-
- was_looking_for "selector", got
-
- snippet node
-end
diff --git a/src/messages/css_selector_space_after_ampersand.cr b/src/messages/css_selector_space_after_ampersand.cr
deleted file mode 100644
index bd2b010b2..000000000
--- a/src/messages/css_selector_space_after_ampersand.cr
+++ /dev/null
@@ -1,13 +0,0 @@
-message CssSelectorSpaceAfterAmpersand do
- title "Syntax Error"
-
- block do
- text "There must be a space between the ampersand"
- code "&"
- text "and the selector, if it's not a pseudo one."
- end
-
- was_looking_for "space", got
-
- snippet node
-end
diff --git a/src/messages/html_style_argument_size_mismatch.cr b/src/messages/html_style_argument_size_mismatch.cr
new file mode 100644
index 000000000..aecfa09d5
--- /dev/null
+++ b/src/messages/html_style_argument_size_mismatch.cr
@@ -0,0 +1,12 @@
+message HtmlStyleArgumentSizeMismatch do
+ title "Type Error"
+
+ block do
+ text "The style takes"
+ bold size
+ text "arguments, while you tried to call it with"
+ bold call_size
+ end
+
+ snippet node, "You tried to call it here:"
+end
diff --git a/src/messages/html_style_argument_type_mismatch.cr b/src/messages/html_style_argument_type_mismatch.cr
new file mode 100644
index 000000000..22dc51625
--- /dev/null
+++ b/src/messages/html_style_argument_type_mismatch.cr
@@ -0,0 +1,14 @@
+message HtmlStyleArgumentTypeMismatch do
+ title "Type Error"
+
+ block do
+ text "The"
+ bold "#{index} argument"
+ text "to a style is causing a mismatch."
+ end
+
+ type_with_text expected, "The style is expecting the #{index} argument to be:"
+ type_with_text got, "Instead it is:"
+
+ snippet node, "You tried to call it here:"
+end
diff --git a/src/messages/html_style_expected_closing_parentheses.cr b/src/messages/html_style_expected_closing_parentheses.cr
new file mode 100644
index 000000000..d80f7b092
--- /dev/null
+++ b/src/messages/html_style_expected_closing_parentheses.cr
@@ -0,0 +1,15 @@
+message HtmlStyleExpectedClosingParentheses do
+ title "Syntax Error"
+
+ block do
+ text "The"
+ bold "arguments"
+ text "of a"
+ bold "style"
+ text "must be enclosed by parenthesis."
+ end
+
+ was_looking_for "closing parenthesis", got, ")"
+
+ snippet node
+end
diff --git a/src/messages/html_element_not_found_style.cr b/src/messages/html_style_not_found.cr
similarity index 81%
rename from src/messages/html_element_not_found_style.cr
rename to src/messages/html_style_not_found.cr
index c8432f47f..1bdc72a6f 100644
--- a/src/messages/html_element_not_found_style.cr
+++ b/src/messages/html_style_not_found.cr
@@ -1,4 +1,4 @@
-message HtmlElementNotFoundStyle do
+message HtmlStyleNotFound do
title "Type Error"
block do
diff --git a/src/messages/style_expected_closing_parentheses.cr b/src/messages/style_expected_closing_parentheses.cr
new file mode 100644
index 000000000..6e1b59ab3
--- /dev/null
+++ b/src/messages/style_expected_closing_parentheses.cr
@@ -0,0 +1,15 @@
+message StyleExpectedClosingParentheses do
+ title "Syntax Error"
+
+ block do
+ text "The"
+ bold "arguments"
+ text "of a"
+ bold "style"
+ text "must be enclosed by parenthesis."
+ end
+
+ was_looking_for "closing parenthesis", got, ")"
+
+ snippet node
+end
diff --git a/src/parser.cr b/src/parser.cr
index 7ed6b2ed2..549963ff6 100644
--- a/src/parser.cr
+++ b/src/parser.cr
@@ -143,6 +143,7 @@ module Mint
def keyword(word) : Bool
result = input[position, word.size]
+
if result == word
@position += word.size
true
diff --git a/src/parsers/case.cr b/src/parsers/case.cr
index 950b983aa..caf3727a5 100644
--- a/src/parsers/case.cr
+++ b/src/parsers/case.cr
@@ -7,7 +7,7 @@ module Mint
syntax_error CaseExpectedCondition
syntax_error CaseExpectedBranches
- def case_expression : Ast::Case | Nil
+ def case_expression(for_css : Bool = false) : Ast::Case | Nil
start do |start_position|
skip unless keyword "case"
@@ -25,7 +25,7 @@ module Mint
opening_bracket: CaseExpectedOpeningBracket,
closing_bracket: CaseExpectedClosingBracket
) do
- items = many { case_branch || comment }.compact
+ items = many { case_branch(for_css) || comment }.compact
raise CaseExpectedBranches if items.empty?
items
end
diff --git a/src/parsers/case_branch.cr b/src/parsers/case_branch.cr
index 59632554c..70be7257e 100644
--- a/src/parsers/case_branch.cr
+++ b/src/parsers/case_branch.cr
@@ -2,7 +2,7 @@ module Mint
class Parser
syntax_error CaseBranchExpectedExpression
- def case_branch : Ast::CaseBranch | Nil
+ def case_branch(for_css : Bool = false) : Ast::CaseBranch | Nil
start do |start_position|
unless keyword "=>"
match = enum_destructuring || expression
@@ -12,11 +12,16 @@ module Mint
whitespace
- raise CaseBranchExpectedExpression unless expression = self.expression
+ expression =
+ if for_css
+ many { css_definition }.compact
+ else
+ self.expression! CaseBranchExpectedExpression
+ end
Ast::CaseBranch.new(
match: match.as(Ast::EnumDestructuring | Ast::Expression | Nil),
- expression: expression.as(Ast::Expression),
+ expression: expression,
from: start_position,
to: position,
input: data)
diff --git a/src/parsers/css_definition.cr b/src/parsers/css_definition.cr
index f52e1b9c1..da6542b91 100644
--- a/src/parsers/css_definition.cr
+++ b/src/parsers/css_definition.cr
@@ -1,7 +1,6 @@
module Mint
class Parser
syntax_error CssDefinitionExpectedSemicolon
- syntax_error CssDefinitionExpectedColon
def css_definition : Ast::CssDefinition | Nil
start do |start_position|
@@ -12,12 +11,14 @@ module Mint
chars "a-zA-Z-"
end
- char ':', CssDefinitionExpectedColon
+ skip unless char! ':'
whitespace
value = many(parse_whitespace: false) do
- css_interpolation || gather { chars "^{;}" }
+ css_interpolation || gather do
+ consume_while char.in_set?("^;{\0") && !keyword_ahead("\#{")
+ end
end.compact
char ';', CssDefinitionExpectedSemicolon
diff --git a/src/parsers/css_interpolation.cr b/src/parsers/css_interpolation.cr
index 6fb63b615..2f27a5150 100644
--- a/src/parsers/css_interpolation.cr
+++ b/src/parsers/css_interpolation.cr
@@ -5,7 +5,7 @@ module Mint
def css_interpolation : Ast::CssInterpolation | Nil
start do |start_position|
- skip unless char! '{'
+ skip unless keyword "\#{"
whitespace
expression = expression! CssInterpolationExpectedExpression
diff --git a/src/parsers/css_media.cr b/src/parsers/css_media.cr
index dbe77c99e..8b0c82040 100644
--- a/src/parsers/css_media.cr
+++ b/src/parsers/css_media.cr
@@ -12,35 +12,22 @@ module Mint
whitespace! CssMediaExpectedSpaceAfterKeyword
- content = gather { chars "^{" }.to_s
+ content = gather { chars "^{" }.to_s.strip
- raise CssMediaExpectedName if content.strip.empty?
+ raise CssMediaExpectedName if content.empty?
body = block(
opening_bracket: CssMediaExpectedOpeningBracket,
closing_bracket: CssMediaExpectedClosingBracket) do
- many { css_definition || comment }.compact
- end
-
- definitions = [] of Ast::CssDefinition
- comments = [] of Ast::Comment
-
- body.each do |item|
- case item
- when Ast::CssDefinition
- definitions << item
- when Ast::Comment
- comments << item
- end
+ css_body
end
Ast::CssMedia.new(
- definitions: definitions,
from: start_position,
- comments: comments,
content: content,
to: position,
- input: data)
+ input: data,
+ body: body)
end
end
end
diff --git a/src/parsers/css_selector.cr b/src/parsers/css_selector.cr
index 00a469194..d32e0032d 100644
--- a/src/parsers/css_selector.cr
+++ b/src/parsers/css_selector.cr
@@ -2,62 +2,43 @@ module Mint
class Parser
syntax_error CssSelectorExpectedOpeningBracket
syntax_error CssSelectorExpectedClosingBracket
- syntax_error CssSelectorExpectedName
-
- syntax_error CssSelectorSpaceAfterAmpersand
def css_selector : Ast::CssSelector | Nil
start do |start_position|
- skip unless char == '&'
-
selectors = list(
terminator: '{',
separator: ','
- ) { css_selector_name }.compact
+ ) { css_selector_name }.reject(&.empty?)
+
+ skip unless selectors.any?
+ skip unless char == '{'
body = block(
opening_bracket: CssSelectorExpectedOpeningBracket,
closing_bracket: CssSelectorExpectedClosingBracket) do
- many { css_definition || comment }.compact
- end
-
- definitions = [] of Ast::CssDefinition
- comments = [] of Ast::Comment
-
- body.each do |item|
- case item
- when Ast::CssDefinition
- definitions << item
- when Ast::Comment
- comments << item
- end
+ css_body
end
Ast::CssSelector.new(
- definitions: definitions,
selectors: selectors,
from: start_position,
- comments: comments,
to: position,
- input: data)
+ input: data,
+ body: body)
end
end
def css_selector_name : String | Nil
- return unless char! '&'
-
- colon = char!(':')
- double_colon = keyword("::")
+ colon = nil
+ double_colon = nil
- if !colon && !double_colon
- whitespace! CssSelectorSpaceAfterAmpersand
+ if char! '&'
+ colon = char!(':')
+ double_colon = keyword("::")
end
- name = gather { chars "^,{" }
-
- raise CssSelectorExpectedName unless name
-
- name = name.strip
+ name =
+ gather { chars "^,{}" }.to_s.strip
if colon
":#{name}"
diff --git a/src/parsers/html_element.cr b/src/parsers/html_element.cr
index 452aff9b2..85e8f0fa7 100644
--- a/src/parsers/html_element.cr
+++ b/src/parsers/html_element.cr
@@ -15,8 +15,14 @@ module Mint
skip unless tag
- if keyword "::"
- style = variable_with_dashes! HtmlElementExpectedStyle
+ styles = [] of Ast::HtmlStyle
+
+ if keyword_ahead "::"
+ styles.concat(many(parse_whitespace: false) do
+ html_style
+ end.compact)
+
+ raise HtmlElementExpectedStyle if styles.empty?
end
ref = start do
@@ -37,7 +43,7 @@ module Mint
from: start_position,
children: children,
comments: comments,
- style: style,
+ styles: styles,
to: position,
input: data,
tag: tag,
diff --git a/src/parsers/html_style.cr b/src/parsers/html_style.cr
new file mode 100644
index 000000000..aa3298f31
--- /dev/null
+++ b/src/parsers/html_style.cr
@@ -0,0 +1,39 @@
+module Mint
+ class Parser
+ syntax_error HtmlStyleExpectedClosingParentheses
+
+ def html_style : Ast::HtmlStyle | Nil
+ start do |start_position|
+ name = start do
+ skip unless keyword "::"
+ skip unless value = variable_with_dashes
+ value
+ end
+
+ skip unless name
+
+ arguments = [] of Ast::Node
+
+ if char! '('
+ whitespace
+
+ list(terminator: ')', separator: ',') do
+ if item = expression
+ arguments << item
+ end
+ end
+
+ whitespace
+ char ')', HtmlStyleExpectedClosingParentheses
+ end
+
+ Ast::HtmlStyle.new(
+ arguments: arguments.compact,
+ from: start_position,
+ to: position,
+ input: data,
+ name: name)
+ end
+ end
+ end
+end
diff --git a/src/parsers/if.cr b/src/parsers/if.cr
index 023a23a8b..7a2c0ad30 100644
--- a/src/parsers/if.cr
+++ b/src/parsers/if.cr
@@ -11,7 +11,7 @@ module Mint
syntax_error IfExpectedCondition
syntax_error IfExpectedElse
- def if_expression : Ast::If | Nil
+ def if_expression(for_css = false) : Ast::If | Nil
start do |start_position|
skip unless keyword "if"
@@ -27,24 +27,36 @@ module Mint
opening_bracket: IfExpectedTruthyOpeningBracket,
closing_bracket: IfExpectedTruthyClosingBracket
) do
- expression! IfExpectedTruthyExpression
+ if for_css
+ many { css_definition }.compact
+ else
+ expression! IfExpectedTruthyExpression
+ end
end
- whitespace
- keyword! "else", IfExpectedElse
+ falsy_head_comments = [] of Ast::Comment
+ falsy_tail_comments = [] of Ast::Comment
+ falsy = nil
+
whitespace
- if falsy = if_expression
- falsy_head_comments = [] of Ast::Comment
- falsy_tail_comments = [] of Ast::Comment
- else
- falsy_head_comments, falsy, falsy_tail_comments =
- block_with_comments(
- opening_bracket: IfExpectedFalsyOpeningBracket,
- closing_bracket: IfExpectedFalsyClosingBracket
- ) do
- expression! IfExpectedFalsyExpression
- end
+ if !for_css || keyword_ahead "else"
+ keyword! "else", IfExpectedElse
+ whitespace
+
+ unless falsy = if_expression(for_css)
+ falsy_head_comments, falsy, falsy_tail_comments =
+ block_with_comments(
+ opening_bracket: IfExpectedFalsyOpeningBracket,
+ closing_bracket: IfExpectedFalsyClosingBracket
+ ) do
+ if for_css
+ many { css_definition }.compact
+ else
+ expression! IfExpectedFalsyExpression
+ end
+ end
+ end
end
Ast::If.new(
@@ -53,8 +65,7 @@ module Mint
falsy_head_comments: falsy_head_comments,
falsy_tail_comments: falsy_tail_comments,
condition: condition.as(Ast::Expression),
- truthy: truthy.as(Ast::Expression),
- falsy: falsy.as(Ast::Expression),
+ branches: {truthy, falsy},
from: start_position,
to: position,
input: data)
diff --git a/src/parsers/style.cr b/src/parsers/style.cr
index 97cafb263..9746e2fde 100644
--- a/src/parsers/style.cr
+++ b/src/parsers/style.cr
@@ -1,5 +1,6 @@
module Mint
class Parser
+ syntax_error StyleExpectedClosingParentheses
syntax_error StyleExpectedOpeningBracket
syntax_error StyleExpectedClosingBracket
syntax_error StyleExpectedName
@@ -9,44 +10,58 @@ module Mint
skip unless keyword "style"
whitespace
-
name = variable_with_dashes! StyleExpectedName
+ whitespace
+
+ arguments = [] of Ast::Argument
+
+ if char! '('
+ whitespace
+
+ arguments.concat list(
+ terminator: ')',
+ separator: ','
+ ) { argument }.compact
+
+ whitespace
+ char ')', StyleExpectedClosingParentheses
+ end
body = block(
opening_bracket: StyleExpectedOpeningBracket,
closing_bracket: StyleExpectedClosingBracket
) do
- many { css_definition || css_selector || css_media || comment }.compact
- end
-
- definitions = [] of Ast::CssDefinition
- selectors = [] of Ast::CssSelector
- comments = [] of Ast::Comment
- medias = [] of Ast::CssMedia
-
- body.each do |item|
- case item
- when Ast::CssDefinition
- definitions << item
- when Ast::CssSelector
- selectors << item
- when Ast::CssMedia
- medias << item
- when Ast::Comment
- comments << item
- end
+ css_body
end
Ast::Style.new(
- definitions: definitions,
- selectors: selectors,
from: start_position,
- comments: comments,
- medias: medias,
+ arguments: arguments,
to: position,
input: data,
+ body: body,
name: name)
end
end
+
+ def css_body
+ many {
+ comment ||
+ case_expression(for_css: true) ||
+ if_expression(for_css: true) ||
+ css_media ||
+ css_definition_or_selector
+ }.compact
+ end
+
+ def css_definition_or_selector
+ css_definition || css_selector
+ rescue definition_errror : CssDefinitionExpectedSemicolon
+ begin
+ css_selector
+ rescue
+ raise definition_errror
+ end
+ end
end
end
diff --git a/src/style_builder.cr b/src/style_builder.cr
new file mode 100644
index 000000000..f09746e7a
--- /dev/null
+++ b/src/style_builder.cr
@@ -0,0 +1,285 @@
+module Mint
+ # This is a name pool. It returns a unique identifier for a given item of a
+ # given base item.
+ #
+ # In Mint it's used to get variable names for blocks of selectors
+ # and CSS properties.
+ class NamePool(T, B)
+ INITIAL = 'a'.pred.to_s
+
+ @cache : Hash(Tuple(B, T), String) = {} of Tuple(B, T) => String
+ @current : Hash(B, String) = {} of B => String
+
+ def of(subject : T, base : B)
+ @cache[{base, subject}] ||= begin
+ @current[base] = (@current[base]? || INITIAL).succ
+ end
+ end
+ end
+
+ class PropertyValue
+ property default : String | Nil
+ property variable : String | Nil
+
+ def to_s
+ if variable && default
+ "var(#{variable}, #{default})"
+ elsif variable
+ "var(#{variable})"
+ else
+ default
+ end
+ end
+ end
+
+ # Compiles the variables of a style node into a computed property.
+ class VariableCompiler
+ delegate ifs, variables, variable_name, any?, style_pool, cases, to: @builder
+ delegate js, compile, to: @compiler
+
+ getter compiler : Compiler
+ getter builder : StyleBuilder
+
+ def initialize(@builder, @compiler)
+ end
+
+ def compile(node : Ast::Style)
+ return "" unless any?(node)
+
+ static =
+ variables[node]?
+ .try do |hash|
+ items =
+ hash
+ .each_with_object({} of String => String) do |(key, value), memo|
+ memo["[`#{key}`]"] = compile value
+ end
+
+ js.object(items) unless items.empty?
+ end || "{}"
+
+ compiled_conditions =
+ ifs
+ .select(&.first.==(node))
+ .merge(cases.select(&.first.==(node)))
+ .map do |(_, selector), conditions|
+ statements =
+ conditions.map do |item|
+ proc =
+ (Proc(String, String).new { |name|
+ variable =
+ variable_name name, selector
+
+ selector[name] ||= PropertyValue.new
+ selector[name].variable = variable
+
+ variable
+ }).as(Proc(String, String) | Nil)
+
+ case item
+ when Ast::If, Ast::Case
+ compile item, proc
+ else
+ ""
+ end
+ end
+
+ js.statements(statements)
+ end
+
+ arguments =
+ compile node.arguments
+
+ js.function("$" + style_pool.of(node, nil), arguments,
+ js.statements([[
+ js.const("_", static),
+ compiled_conditions,
+ js.return("_"),
+ ]].flatten.reject(&.empty?)))
+ end
+
+ def compile_branch(items : Array(Ast::CssDefinition), selector : StyleBuilder::Selector)
+ compiled =
+ items
+ .each_with_object({} of String => String) do |definition, memo|
+ variable =
+ variable_name definition.name, selector
+
+ selector[definition.name] ||= PropertyValue.new
+ selector[definition.name].variable = variable
+
+ value =
+ compile definition.value
+
+ memo["[`#{variable}`]"] = "`#{value}`"
+ end
+
+ js.object(compiled)
+ end
+ end
+
+ # This class is responsible to build the CSS of "style" tags by resolving
+ # nested media queries and selectors, handling cases of the same rules in
+ # different places.
+ class StyleBuilder
+ class Selector < Hash(String, PropertyValue)
+ getter id : String = Random::Secure.hex
+ end
+
+ getter selectors, property_pool, name_pool, style_pool, variables, ifs
+ getter cases
+
+ def initialize
+ # Three name pools so there would be no clashes,
+ # which also good for optimizations.
+ @property_pool = NamePool(String, String).new
+ @style_pool = NamePool(Ast::Node, Nil).new
+ @name_pool = NamePool(String, Nil).new
+
+ # This is the main data structure:
+ #
+ # Hash(Tuple(MediaQueries, Selectors), Selector)
+ #
+ # Basically it allows to identify a specific set of rules in a
+ # specific set of media queries in case their properties are
+ # defined in serveral places.
+ @selectors = {} of Tuple(Array(String), Array(String)) => Selector
+
+ # This hash contains variables for a specific "style" tag, which will
+ # be compiled by the compiler itself when compiling an HTML element
+ # which uses the specific style tag.
+ @variables = {} of Ast::Node => Hash(String, Array(String | Ast::CssInterpolation))
+ @cases = {} of Tuple(Ast::Node, Selector) => Array(Ast::Case)
+ @ifs = {} of Tuple(Ast::Node, Selector) => Array(Ast::If)
+ end
+
+ # Compiles the processed data into a CSS style sheet.
+ def compile
+ output = {} of Array(String) => Array(String)
+
+ selectors
+ .reject { |_, v| v.empty? }
+ .each do |(medias, rules), properties|
+ selector =
+ rules.join(",\n")
+
+ body =
+ properties
+ .map { |key, value| "#{key}: #{value.to_s};" }
+ .join("\n")
+
+ output[medias] ||= [] of String
+ output[medias] << "#{selector} {\n#{body.indent}\n}"
+ end
+
+ output.map do |medias, rules|
+ if medias.any?
+ "@media #{medias.join(" and ")} {\n#{rules.join("\n\n").indent}\n}"
+ else
+ rules.join("\n\n")
+ end
+ end.join("\n\n")
+ end
+
+ def compile_style(node : Ast::Style, compiler : Compiler)
+ VariableCompiler
+ .new(self, compiler)
+ .compile(node)
+ end
+
+ def any?(node : Ast::Node)
+ variables[node]? ||
+ ifs.any?(&.first.first.==(node)) ||
+ cases.any?(&.first.first.==(node))
+ end
+
+ def any?(node : Nil)
+ false
+ end
+
+ # The main entry point for processing a "style" tag.
+ def process(node : Ast::Style)
+ selectors =
+ ["." + style_pool.of(node, nil)]
+
+ process(node.body, selectors, [] of String, node)
+ end
+
+ # Processes a Ast::CssSelector
+ def process(node : Ast::CssSelector,
+ parents : Array(String),
+ media : Array(String),
+ style_node : Ast::Node)
+ selectors = [] of String
+
+ parents.each do |parent|
+ node.selectors.map do |item|
+ selectors << parent + item
+ end
+ end
+
+ process(node.body, selectors, media, style_node)
+ end
+
+ # Processes an Ast::Media
+ def process(node : Ast::CssMedia,
+ selectors : Array(String),
+ media : Array(String),
+ style_node : Ast::Node)
+ process(node.body, selectors, media + [node.content], style_node)
+ end
+
+ # Processes the body of a CSS Ast::Node.
+ def process(body : Array(Ast::Node),
+ selectors : Array(String),
+ media : Array(String),
+ style_node : Ast::Node)
+ # Create a selector for this specific state
+ selector =
+ @selectors[{media, selectors}] ||= Selector.new
+
+ body.each do |item|
+ case item
+ when Ast::CssDefinition
+ if item.value.any?(Ast::CssInterpolation)
+ # Get the name of the variable
+ variable =
+ variable_name(item.name, selector)
+
+ selector[item.name] ||= PropertyValue.new
+ selector[item.name].variable = variable
+
+ # Save the actual data for the variable for compiling later.
+ variables[style_node] ||= {} of String => Array(String | Ast::CssInterpolation)
+ variables[style_node][variable] = item.value
+ else
+ selector[item.name] ||= PropertyValue.new
+ selector[item.name].default = item.value.join("")
+ end
+ when Ast::CssSelector
+ process(item, selectors, media, style_node)
+ when Ast::CssMedia
+ process(item, selectors, media, style_node)
+ when Ast::Case
+ cases[{style_node, selector}] ||= [] of Ast::Case
+ cases[{style_node, selector}] << item
+ when Ast::If
+ ifs[{style_node, selector}] ||= [] of Ast::If
+ ifs[{style_node, selector}] << item
+ end
+ end
+ end
+
+ def variable_name(name, selector)
+ # Get the unique ID of the selector
+ block_id =
+ name_pool.of(selector.id, nil)
+
+ # Get the unique ID of the property
+ variable_id =
+ property_pool.of(name, selector.id)
+
+ "--#{block_id}-#{variable_id}"
+ end
+ end
+end
diff --git a/src/type_checker.cr b/src/type_checker.cr
index fb2d38d3e..8d42f2a3f 100644
--- a/src/type_checker.cr
+++ b/src/type_checker.cr
@@ -29,7 +29,7 @@ module Mint
property checking : Bool = true
- delegate types, variables, html_elements, ast, lookups, cache, to: artifacts
+ delegate types, variables, ast, lookups, cache, to: artifacts
delegate checked, record_field_lookup, to: artifacts
delegate component?, component, stateful?, to: scope
delegate format, to: formatter
diff --git a/src/type_checkers/artifacts.cr b/src/type_checkers/artifacts.cr
index 000337063..3398b130f 100644
--- a/src/type_checkers/artifacts.cr
+++ b/src/type_checkers/artifacts.cr
@@ -1,15 +1,11 @@
module Mint
class TypeChecker
class Artifacts
- getter types, variables, html_elements, dynamic_styles, styles
- getter ast, medias, lookups, cache, checked, record_field_lookup
+ getter ast, lookups, cache, checked, record_field_lookup
+ getter types, variables
def initialize(@ast : Ast,
- @html_elements = {} of Ast::HtmlElement => Ast::Component | Nil,
- @medias = {} of String => Hash(String, Hash(String, String)),
- @dynamic_styles = {} of String => Hash(String, String),
@record_field_lookup = {} of Ast::Node => String,
- @styles = {} of String => Hash(String, String),
@variables = {} of Ast::Node => Scope::Lookup,
@lookups = {} of Ast::Node => Ast::Node,
@types = {} of Ast::Node => Checkable,
diff --git a/src/type_checkers/case_branch.cr b/src/type_checkers/case_branch.cr
index a00b439b4..0b77f3468 100644
--- a/src/type_checkers/case_branch.cr
+++ b/src/type_checkers/case_branch.cr
@@ -3,6 +3,18 @@ module Mint
type_error CaseBranchNotMatchCondition
def check(node : Ast::CaseBranch, condition : Checkable) : Checkable
+ resolve_expression = ->{
+ case expression = node.expression
+ when Array(Ast::CssDefinition)
+ resolve expression
+ NEVER
+ when Ast::Node
+ resolve expression
+ else
+ NEVER
+ end
+ }
+
node.match.try do |item|
match = resolve item
@@ -38,10 +50,10 @@ module Mint
end
scope(variables) do
- resolve node.expression
+ resolve_expression.call
end
end
- end || resolve node.expression
+ end || resolve_expression.call
end
end
end
diff --git a/src/type_checkers/css_media.cr b/src/type_checkers/css_media.cr
index 8c41cccf9..7d7b82d33 100644
--- a/src/type_checkers/css_media.cr
+++ b/src/type_checkers/css_media.cr
@@ -1,7 +1,7 @@
module Mint
class TypeChecker
def check(node : Ast::CssMedia) : Checkable
- resolve node.definitions
+ resolve node.body
NEVER
end
diff --git a/src/type_checkers/css_selector.cr b/src/type_checkers/css_selector.cr
index d8baae2e9..b531a363f 100644
--- a/src/type_checkers/css_selector.cr
+++ b/src/type_checkers/css_selector.cr
@@ -1,7 +1,7 @@
module Mint
class TypeChecker
def check(node : Ast::CssSelector) : Checkable
- resolve node.definitions
+ resolve node.body
NEVER
end
diff --git a/src/type_checkers/html_element.cr b/src/type_checkers/html_element.cr
index 83216736e..20bcfc0a6 100644
--- a/src/type_checkers/html_element.cr
+++ b/src/type_checkers/html_element.cr
@@ -2,29 +2,14 @@ module Mint
class TypeChecker
type_error HtmlElementReferenceOutsideOfComponent
type_error HtmlElementStyleOutsideOfComponent
- type_error HtmlElementNotFoundStyle
def check(node : Ast::HtmlElement) : Checkable
- style =
- node.style
-
- if style
+ if node.styles.any?
raise HtmlElementStyleOutsideOfComponent, {
- "node" => style,
+ "node" => node,
} unless component?
- style_node =
- component.styles.find(&.name.value.==(style.value))
-
- raise HtmlElementNotFoundStyle, {
- "style" => style.value,
- "node" => style,
- } unless style_node
-
- resolve style_node
-
- lookups[node] = style_node
- html_elements[node] = component
+ resolve node.styles
end
node.ref.try do |ref|
diff --git a/src/type_checkers/html_style.cr b/src/type_checkers/html_style.cr
new file mode 100644
index 000000000..9e6035625
--- /dev/null
+++ b/src/type_checkers/html_style.cr
@@ -0,0 +1,46 @@
+module Mint
+ class TypeChecker
+ type_error HtmlStyleArgumentSizeMismatch
+ type_error HtmlStyleArgumentTypeMismatch
+ type_error HtmlStyleNotFound
+
+ def check(node : Ast::HtmlStyle) : Checkable
+ style =
+ component.styles.find(&.name.value.==(node.name.value))
+
+ raise HtmlStyleNotFound, {
+ "style" => node.name.value,
+ "node" => node,
+ } unless style
+
+ resolve style
+
+ raise HtmlStyleArgumentSizeMismatch, {
+ "size" => style.arguments.size.to_s,
+ "call_size" => node.arguments.size.to_s,
+ "node" => node,
+ } unless style.arguments.size == node.arguments.size
+
+ style.arguments
+ .zip(node.arguments)
+ .each_with_index do |(style_arg, call_arg), index|
+ style_arg_type =
+ resolve(style_arg)
+
+ call_arg_type =
+ resolve(call_arg)
+
+ raise HtmlStyleArgumentTypeMismatch, {
+ "index" => ordinal(index + 1),
+ "expected" => style_arg_type,
+ "got" => call_arg_type,
+ "node" => node,
+ } unless Comparer.compare(style_arg_type, call_arg_type)
+ end
+
+ lookups[node] = style
+
+ NEVER
+ end
+ end
+end
diff --git a/src/type_checkers/if.cr b/src/type_checkers/if.cr
index aafd5dfca..964c9f399 100644
--- a/src/type_checkers/if.cr
+++ b/src/type_checkers/if.cr
@@ -7,25 +7,36 @@ module Mint
condition =
resolve node.condition
- truthy =
- resolve node.truthy
-
- falsy =
- resolve node.falsy
-
raise IfConditionTypeMismatch, {
"node" => node.condition,
"got" => condition,
"expected" => BOOL,
} unless Comparer.compare(condition, BOOL)
- raise IfElseTypeMismatch, {
- "node" => node.falsy,
- "expected" => truthy,
- "got" => falsy,
- } unless Comparer.compare(truthy, falsy)
+ truthy_item, falsy_item =
+ node.branches
+
+ if truthy_item.is_a?(Ast::Node) &&
+ falsy_item.is_a?(Ast::Node)
+ truthy =
+ resolve truthy_item.as(Ast::Node)
+
+ falsy =
+ resolve falsy_item.as(Ast::Node)
+
+ raise IfElseTypeMismatch, {
+ "node" => falsy_item.as(Ast::Node),
+ "expected" => truthy,
+ "got" => falsy,
+ } unless Comparer.compare(truthy, falsy)
+
+ truthy
+ else
+ resolve truthy_item
+ falsy_item.try { |data| resolve data }
- truthy
+ NEVER
+ end
end
end
end
diff --git a/src/type_checkers/scope.cr b/src/type_checkers/scope.cr
index 2ec111b46..46e93e06c 100644
--- a/src/type_checkers/scope.cr
+++ b/src/type_checkers/scope.cr
@@ -8,6 +8,7 @@ module Mint
Ast::Provider |
Ast::Module |
Ast::Store |
+ Ast::Style |
Ast::Get
alias Level = Tuple(Ast::Node | Checkable, Node)
@@ -38,6 +39,8 @@ module Mint
node.name
when Ast::Function
node.name.value
+ when Ast::Style
+ node.name.value
else
"" # Cannot happen
end
@@ -107,6 +110,10 @@ module Mint
node.where.try(&.statements.find(&.name.value.==(variable)))
end
+ def find(variable : String, node : Ast::Style)
+ node.arguments.find(&.name.value.==(variable))
+ end
+
def find(variable : String, node : Ast::Get)
node.where.try(&.statements.find(&.name.value.==(variable)))
end
diff --git a/src/type_checkers/style.cr b/src/type_checkers/style.cr
index a7f19f605..f8015107e 100644
--- a/src/type_checkers/style.cr
+++ b/src/type_checkers/style.cr
@@ -1,11 +1,12 @@
module Mint
class TypeChecker
def check(node : Ast::Style) : Checkable
- resolve node.definitions
- resolve node.selectors
- resolve node.medias
+ scope node do
+ resolve node.arguments
+ resolve node.body
- NEVER
+ NEVER
+ end
end
end
end