diff --git a/src/components/docs/Info.astro b/src/components/docs/Info.astro new file mode 100644 index 0000000..7d86c24 --- /dev/null +++ b/src/components/docs/Info.astro @@ -0,0 +1,4 @@ +
+
Inspired by Rust, Zig and Kotlin, THP has a modern syntax, semantics, type system and stdlib.
diff --git a/src/pages/learn/index.mdx b/src/pages/learn/index.mdx index e558562..0097fcf 100644 --- a/src/pages/learn/index.mdx +++ b/src/pages/learn/index.mdx @@ -52,6 +52,9 @@ pagesLayout: title: Templating children: - path: intro + - path: components + - path: props + - path: control-flow --- import InteractiveCode from "../../components/InteractiveCode.astro"; import Code from "../../components/Code.astro" diff --git a/src/pages/learn/templating/components.mdx b/src/pages/learn/templating/components.mdx new file mode 100644 index 0000000..0b29cca --- /dev/null +++ b/src/pages/learn/templating/components.mdx @@ -0,0 +1,194 @@ +--- +layout: ../../../layouts/DocsLayout.astro +title: Components +--- +import Code from "../../../components/Code.astro" +import Info from "../../../components/docs/Info.astro" + +# Components + +Like React, a component is any function that returns `HTML`. + + HTML
+{
+ Hello templates!
+}
+`} />
+
+Inside the HTML tags you can (mostly) write the HTML you already
+know.
+
+## Text interpolation
+
+Interpolation inside HTML works the same way as string interpolation.
+Use brackets to insert an expression to the HTML:
+
+ HTML
+{
+ val name = "John"
+
+ Hello {name}!
+}
+`} />
+
+```html
+Hello John!
+```
+
+You can use any expression that can be converted to a `String` inside,
+like conditionals.
+
+ HTML
+{
+ val name = "John"
+ val is_vip = true
+
+
+ {if is_vip {"Welcome"} else {"Hi"}}
+ {name}!
+
+}
+`} />
+
+```html
+Welcome John!
+```
+
+## Raw HTML
+
+Text interpolated is always escaped:
+
+ HTML
+{
+ val user_input = "BOLD"
+
+ answer: {user_input}
+}
+`} />
+```html
+answer: <b>BOLD</b>
+```
+
+To include raw html use the `raw-html` attribute (subject to change):
+
+ HTML
+{
+ val user_input = "BOLD"
+
+ answer:
+}
+`} />
+```html
+answer: BOLD
+```
+
+
+## Dynamic attributes
+
+TODO: boolean attributes
+
+Normal attributes (plain strings) work as you'd expect:
+
+ HTML
+{
+
+}
+`} />
+```html
+
+```
+
+Dynamic attributes are used when you want to use values from code.
+For those use brackets instead of double quotes:
+
+ HTML
+{
+ val button_class = if true {"blue"} else {"yellow"}
+
+ // Note the braces
+
+}
+`} />
+```html
+
+```
+
+
+
+## Fragments
+
+An HTML expression consist of a single tag that may have children inside.
+If you need to return multiple tags at once you can use fragments.
+
+
+The following code doesn't work as you would expect:
+
+ HTML
+{
+ hello
// This is an error, an ignored expression
+ world
+}
+`} />
+
+Each `` is a single expression, they are not grouped.
+And since we cannot have unused expressions, the code will not compile.
+
+To have these two `
` tags as a single expression use a fragment:
+`<>>`
+
+ HTML
+{
+ // This is the root "element"
+ <>
+ hello
// Now these two are together
+ world
+ >
+}
+`} />
+```html
+hello
+world
+```
+
+## Composition
+
+To use a component inside another component call them as if it were an
+html tag:
+
+ HTML
+{
+ I am the user
+}
+
+fun MyComponent() -> HTML
+{
+ <>
+ status
+ // Here we are using the other component
+ >
+}
+`} />
+```html
+status
+world
+```
+
+
+
diff --git a/src/pages/learn/templating/control-flow.mdx b/src/pages/learn/templating/control-flow.mdx
new file mode 100644
index 0000000..c5303a9
--- /dev/null
+++ b/src/pages/learn/templating/control-flow.mdx
@@ -0,0 +1,9 @@
+---
+layout: ../../../layouts/DocsLayout.astro
+title: Control flow
+---
+import Code from "../../../components/Code.astro"
+import Info from "../../../components/docs/Info.astro"
+
+# Control flow
+
diff --git a/src/pages/learn/templating/intro.mdx b/src/pages/learn/templating/intro.mdx
index 7653f57..f8bce58 100644
--- a/src/pages/learn/templating/intro.mdx
+++ b/src/pages/learn/templating/intro.mdx
@@ -3,6 +3,7 @@ layout: ../../../layouts/DocsLayout.astro
title: Introduction
---
import Code from "../../../components/Code.astro"
+import Info from "../../../components/docs/Info.astro"
# THP templating
@@ -62,7 +63,7 @@ and compose them.
The following would be the equivalent in THP:
Html {
+fun Button(String name) -> HTML {
@@ -74,7 +75,7 @@ way around, so you can have arbitrary logic in the component.
HTML {
// Get info from the database
val user = try Model::get_user(name)
else {
@@ -87,13 +88,13 @@ fun User(String name) {
Hello {user.name}!
Here are your transactions:
- #for t in user.transactions {
+ @for t in user.transactions {
}
}
-fun TransactionItem(Transaction t) {
+fun TransactionItem(Transaction t) -> HTML {
{t.date} - {t.name} ({t.price})
@@ -101,3 +102,67 @@ fun TransactionItem(Transaction t) {
`} />
+## Is this a JavaScript Front-End Framework?
+
+**No**
+
+This is an HTML templating solution. All the code is run in the backend,
+generates static HTML and sends it to the browser. There is no
+reactivity, hooks, signals, etc.
+
+If you need reactivity on the front-end and want to use this templating
+take a look at [htmx](https://htmx.org/), [Alpine.js](https://alpinejs.dev/)
+and [hyperscript](https://hyperscript.org/).
+
+
+
+## Styling
+
+We don't provide any syntax or facility for styling.
+However, this component model is good to use with TailwindCSS.
+
+
+## Conversion
+
+
+ TBD: This is a draft, subject to change.
+
+
+HTML expressions will be compiled to plain strings, and
+those will be then composed.
+
+ HTML {
+ val user = Model::get_user(name)
+
+
+}
+`} />
+
+```php
+function Sample(name) {
+ $user = Model::get_user(name);
+
+ $__expr_1 = "";
+ if ($user !== null) {
+ $__expr_2 = user.name;
+ $__expr_1 = "Hello {$name} (id {$__expr_2})";
+ } else {
+ $__expr_1 = "Not logged in";
+ }
+
+ return ""
+}
+```
+
+
+
diff --git a/src/pages/learn/templating/props.mdx b/src/pages/learn/templating/props.mdx
new file mode 100644
index 0000000..a50eb9b
--- /dev/null
+++ b/src/pages/learn/templating/props.mdx
@@ -0,0 +1,156 @@
+---
+layout: ../../../layouts/DocsLayout.astro
+title: Props
+---
+import Code from "../../../components/Code.astro"
+import Info from "../../../components/docs/Info.astro"
+
+# Props
+
+Props are used to send data to a children component.
+
+THP's components can receive any datatype as props,
+and they are defined as normal parameters.
+
+For example, to receive a `String` declare it as a
+parameter:
+
+ HTML
+{
+ Hello {name}!
+}
+`} />
+
+And to send its value type the parameter name as an attribute:
+
+ HTML
+{
+
+
+
+}
+`} />
+
+```html
+Hello Rose
+```
+
+You can have as many props as you'd like, of any datatype:
+
+ HTML
+{
+ // ...
+}
+`} />
+
+## Static props
+
+If the prop has a type `String` you can use a normal attribute.
+
+ HTML
+{
+
+ // name is a String, so we use ""
+
+
+}
+`} />
+
+
+## Dynamic props
+
+However, if the prop has any other datatype you must use a
+dynamic attribute (`{}`)
+
+ HTML
+{
+ // ...
+}
+
+fun Home() -> HTML
+{
+ val my_cat = Cat("Michifu")
+
+
+
+
+}
+`} />
+
+
+## Components as props
+
+If for some reason you want to use a component as a prop
+use the `HTML` datatype:
+
+ HTML
+{
+ <>
+ Sup
+ {child}
+ >
+}
+`} />
+
+This, however, means that your prop component must be declared
+as an attribute:
+
+ HTML
+{
+
+ I am the child} />
+
+}
+`} />
+
+```html
+
+ Sup
+ I am the child
+
+```
+
+A better solution may be to use slots.
+
+## Slots
+
+Slots allow you to write html inside a component tag.
+
+ HTML
+{
+
+}
+
+fun Home() -> HTML
+{
+
+
+ buy now!
+
+
+}
+`} />
+```html
+
+
+
+```
+
+
+
+