feat: improve landpage ui
This commit is contained in:
parent
c43361dbb7
commit
0b5b424e95
@ -1,11 +1,11 @@
|
|||||||
---
|
---
|
||||||
import Code from "./Code.astro"
|
import Code from "./Code.astro"
|
||||||
|
|
||||||
const { thpcode, no_warnings } = Astro.props;
|
const { thpcode, no_warnings, level } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="flex h-full py-8 items-center">
|
<div class="flex h-full md:py-8 items-center">
|
||||||
<div class="p-4 w-full">
|
<div class="p-4 w-full">
|
||||||
<Code thpcode={thpcode} no_warnings={no_warnings} />
|
<Code thpcode={thpcode} no_warnings={no_warnings} level={level} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
---
|
---
|
||||||
|
import { HighlightLevel } from "../lexer/types";
|
||||||
import CodeEditor from "./CodeEditor.astro";
|
import CodeEditor from "./CodeEditor.astro";
|
||||||
|
|
||||||
const { title, thpcode, subtitle } = Astro.props;
|
const { title, thpcode } = Astro.props;
|
||||||
|
|
||||||
if (!subtitle) {
|
|
||||||
throw new Error("subtitle is required");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!thpcode) {
|
if (!thpcode) {
|
||||||
throw new Error("thpcode is required");
|
throw new Error("thpcode is required");
|
||||||
@ -17,20 +14,26 @@ if (!title) {
|
|||||||
---
|
---
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="bg-c-thp text-c-bg">
|
<div
|
||||||
<h1 class="container mx-auto font-medium py-8 text-3xl font-display">
|
class="md:bg-c-thp md:text-c-bg text-c-thp border-t-4 border-b-4 border-c-thp"
|
||||||
{subtitle} <span class="font-black">{title}</span>
|
>
|
||||||
|
<h1
|
||||||
|
class="container mx-auto font-medium md:py-8 py-4 px-4 md:text-3xl text-2xl font-display"
|
||||||
|
>
|
||||||
|
✅ <span class="font-black">{title}</span>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container mx-auto lg:grid lg:grid-cols-2 gap-4">
|
<div class="container mx-auto lg:grid lg:grid-cols-2 gap-4">
|
||||||
<div class="px-8 py-12 flex h-full items-center">
|
<div class="md:px-8 md:py-12 px-4 pt-6 flex h-full items-center">
|
||||||
<div>
|
<div>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<CodeEditor
|
||||||
<CodeEditor thpcode={thpcode} no_warnings={true} />
|
thpcode={thpcode}
|
||||||
</div>
|
no_warnings={true}
|
||||||
|
level={HighlightLevel.Lexic}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,18 +4,16 @@ import Navbar from "../components/Navbar.astro";
|
|||||||
import HeroSection from "../components/HeroSection.astro";
|
import HeroSection from "../components/HeroSection.astro";
|
||||||
import { native_highlighter } from "../lexer/highlighter";
|
import { native_highlighter } from "../lexer/highlighter";
|
||||||
import { leftTrimDedent } from "../components/utils";
|
import { leftTrimDedent } from "../components/utils";
|
||||||
|
import { HighlightLevel } from "../lexer/types";
|
||||||
|
|
||||||
const thpcode = `union Animal {
|
const thpcode = `union Animal {
|
||||||
Dog(String),
|
Dog(String),
|
||||||
Cat(String, Int),
|
Cat(String, Int),
|
||||||
}
|
}
|
||||||
|
|
||||||
val cat_name = Post::get("cat_name") ?? "Michifu"
|
val my_pet = try Pets::get_first()
|
||||||
val my_cat = Animal::Cat(cat_name, 9)
|
|
||||||
|
|
||||||
try change_fur_color(cat) else die("Not a cat")
|
match my_pet
|
||||||
|
|
||||||
match random_animal()
|
|
||||||
case Dog(name)
|
case Dog(name)
|
||||||
{
|
{
|
||||||
print("{name} has 1 live ")
|
print("{name} has 1 live ")
|
||||||
@ -25,7 +23,10 @@ case Cat(name, lives)
|
|||||||
print("{name} has {lives}")
|
print("{name} has {lives}")
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
const [thp_html] = await native_highlighter(leftTrimDedent(thpcode).join("\n"));
|
const [thp_html] = await native_highlighter(
|
||||||
|
leftTrimDedent(thpcode).join("\n"),
|
||||||
|
HighlightLevel.Lexic,
|
||||||
|
);
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout>
|
<BaseLayout>
|
||||||
@ -49,21 +50,18 @@ const [thp_html] = await native_highlighter(leftTrimDedent(thpcode).join("\n"));
|
|||||||
Inspired by Rust, Zig and Kotlin, THP has a modern syntax,
|
Inspired by Rust, Zig and Kotlin, THP has a modern syntax,
|
||||||
semantics, type system and stdlib.
|
semantics, type system and stdlib.
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<div class="text-center pb-4">
|
||||||
<br />
|
|
||||||
<div class="text-center">
|
|
||||||
<a
|
<a
|
||||||
class="inline-block font-display text-lg rounded-full border-2 border-pink-400 py-2 px-8
|
class="inline-block font-display text-lg rounded-full border-2 border-pink-400 py-2 px-8
|
||||||
transition-colors hover:text-black hover:bg-pink-400"
|
transition-colors hover:text-black hover:bg-pink-400 mt-2"
|
||||||
href="/learn/"
|
href="/learn/"
|
||||||
>
|
>
|
||||||
Tutorial
|
Learn
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
class="inline-block font-display text-lg border-2 border-sky-400 py-2 px-8 mx-6 rounded-full
|
class="inline-block font-display text-lg border-2 border-sky-400 py-2 px-8 mx-6 rounded-full
|
||||||
transition-colors hover:text-black hover:bg-sky-400"
|
transition-colors hover:text-black hover:bg-sky-400 mt-2 opacity-50 cursor-not-allowed"
|
||||||
href="/install/"
|
|
||||||
>
|
>
|
||||||
Install
|
Install
|
||||||
</a>
|
</a>
|
||||||
@ -71,10 +69,10 @@ const [thp_html] = await native_highlighter(leftTrimDedent(thpcode).join("\n"));
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="table">
|
<div>
|
||||||
<div class="table-cell align-middle">
|
<div class="flex h-full justify-center items-center">
|
||||||
<div
|
<div
|
||||||
class="bg-[var(--code-theme-bg-color)] lg:p-6 p-2 rounded-lg relative w-full"
|
class="bg-[var(--code-theme-bg-color)] lg:p-6 p-2 rounded-lg w-full max-w-[30rem] relative"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="absolute lg:inline-block hidden h-[35rem] w-[35rem] -z-10 top-1/2 left-1/2 rounded-full
|
class="absolute lg:inline-block hidden h-[35rem] w-[35rem] -z-10 top-1/2 left-1/2 rounded-full
|
||||||
@ -83,7 +81,6 @@ const [thp_html] = await native_highlighter(leftTrimDedent(thpcode).join("\n"));
|
|||||||
filter: blur(75px); opacity: 0.75;"
|
filter: blur(75px); opacity: 0.75;"
|
||||||
>
|
>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="54"
|
width="54"
|
||||||
@ -120,16 +117,17 @@ const [thp_html] = await native_highlighter(leftTrimDedent(thpcode).join("\n"));
|
|||||||
</svg>
|
</svg>
|
||||||
<div class="h-1"></div>
|
<div class="h-1"></div>
|
||||||
<div id="editor" class="font-mono language-thp">
|
<div id="editor" class="font-mono language-thp">
|
||||||
<pre set:html={thp_html}></pre>
|
<pre set:html={thp_html} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="h-8 md:hidden"></div>
|
||||||
|
|
||||||
<HeroSection
|
<HeroSection
|
||||||
subtitle="We've got"
|
title="Generics & Types"
|
||||||
title="generics"
|
|
||||||
thpcode={`
|
thpcode={`
|
||||||
Array[Int] numbers = [0, 1, 2, 3, 4, 5]
|
Array[Int] numbers = [0, 1, 2, 3, 4, 5]
|
||||||
|
|
||||||
@ -148,21 +146,15 @@ const [thp_html] = await native_highlighter(leftTrimDedent(thpcode).join("\n"));
|
|||||||
val result = mock() as String
|
val result = mock() as String
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
THP enforces type safety at compile time and, at the programmer's
|
Type safety is enforced at compile time. Everything
|
||||||
request, at runtime.
|
has a specific type. There is no `mixed`.
|
||||||
<br />
|
<br>
|
||||||
<br />
|
<br>
|
||||||
Everything has a type. There are generics. No implicit type conversions.
|
You can use generics where neccesary.
|
||||||
No <code>mixed</code>. No client <code>Any</code> .Type inference included.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
All possible checks are made at compile time. Runtime checks have a small
|
|
||||||
performance penalty.
|
|
||||||
</HeroSection>
|
</HeroSection>
|
||||||
|
|
||||||
<HeroSection
|
<HeroSection
|
||||||
subtitle="We've got"
|
title="Tagged unions"
|
||||||
title="tagged unions"
|
|
||||||
thpcode={`
|
thpcode={`
|
||||||
union DirEntry {
|
union DirEntry {
|
||||||
File(String),
|
File(String),
|
||||||
@ -174,15 +166,14 @@ const [thp_html] = await native_highlighter(leftTrimDedent(thpcode).join("\n"));
|
|||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
Make invalid state irrepresentable.
|
Make invalid state irrepresentable.
|
||||||
<br>
|
<br />
|
||||||
Model data in a type-safe way.
|
Model data in a type-safe way.
|
||||||
<br>
|
<br />
|
||||||
Ensure all cases are handled.
|
Ensure all cases are handled.
|
||||||
</HeroSection>
|
</HeroSection>
|
||||||
|
|
||||||
<HeroSection
|
<HeroSection
|
||||||
subtitle="We've got"
|
title="Pattern matching"
|
||||||
title="pattern matching"
|
|
||||||
thpcode={`
|
thpcode={`
|
||||||
match test_file
|
match test_file
|
||||||
case DirEntry::File(filename)
|
case DirEntry::File(filename)
|
||||||
@ -197,15 +188,14 @@ const [thp_html] = await native_highlighter(leftTrimDedent(thpcode).join("\n"));
|
|||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
Match on values, tuples, enums, unions, types etc.
|
Match on values, tuples, enums, unions, types etc.
|
||||||
<br>
|
<br />
|
||||||
Guards available!
|
Guards available!
|
||||||
</HeroSection>
|
</HeroSection>
|
||||||
|
|
||||||
<HeroSection
|
<HeroSection
|
||||||
subtitle="We've got"
|
title="Null safety"
|
||||||
title="null safety"
|
|
||||||
thpcode={`
|
thpcode={`
|
||||||
String? username = Globals::Post::get("username")
|
String? username = Post::get("username")
|
||||||
|
|
||||||
if username?
|
if username?
|
||||||
{
|
{
|
||||||
@ -214,10 +204,29 @@ const [thp_html] = await native_highlighter(leftTrimDedent(thpcode).join("\n"));
|
|||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
Nulls are explicit and require handling. Types are nullable, and they
|
Nulls are explicit and require handling. Types can be nullable,
|
||||||
are used everywhere they are needed.
|
and they must be checked before usage.
|
||||||
|
<br>
|
||||||
|
The stdlib makes extensive use of them.
|
||||||
|
</HeroSection>
|
||||||
|
|
||||||
|
<HeroSection
|
||||||
|
title="Errors as values"
|
||||||
|
thpcode={`
|
||||||
|
val user_id = POST::get("id")
|
||||||
|
val user = try User::find(user_id)
|
||||||
|
catch DBException e
|
||||||
|
{
|
||||||
|
log_error(e.message)
|
||||||
|
return page(.{}, 404)
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
Exceptions are values and don't disrupt
|
||||||
|
control flow.
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
Nullable types must be explicitly checked before using them.
|
Errors cannot be ignored, and we have
|
||||||
|
syntax sugar to ease them.
|
||||||
</HeroSection>
|
</HeroSection>
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
Loading…
Reference in New Issue
Block a user