Compare commits
3 Commits
79bdee91d0
...
4dc0b8524f
Author | SHA1 | Date | |
---|---|---|---|
4dc0b8524f | |||
946dbd6098 | |||
493845a213 |
@ -7,6 +7,6 @@ import mdx from "@astrojs/mdx";
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
integrations: [tailwind(), mdx()],
|
integrations: [tailwind(), mdx()],
|
||||||
markdown: {
|
markdown: {
|
||||||
syntaxHighlight: false,
|
syntaxHighlight: "prism",
|
||||||
},
|
},
|
||||||
});
|
});
|
31
src/layouts/ApiLayout.astro
Normal file
31
src/layouts/ApiLayout.astro
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
import Navbar from "../components/Navbar.astro";
|
||||||
|
import BaseLayout from "./BaseLayout.astro";
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout>
|
||||||
|
<Navbar />
|
||||||
|
|
||||||
|
<div class="lg:grid lg:grid-cols-[14rem_auto_12rem] lg:container mx-auto">
|
||||||
|
<div
|
||||||
|
id="sidebar"
|
||||||
|
class="pt-12 h-screen lg:sticky top-0 fixed z-10 bg-c-bg w-60 lg:w-auto border-r-2 lg:border-0
|
||||||
|
border-c-border-1 -translate-x-64 lg:translate-x-0 transition-transform"
|
||||||
|
>
|
||||||
|
<nav class="py-4 pr-2 overflow-x-scroll h-[calc(100vh-3rem)]">
|
||||||
|
<a href="/">Home page</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<main
|
||||||
|
class="py-[3.5rem] lg:pl-12 lg:pr-4 markdown min-w-0 small-container mx-auto"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {highlightOnDom} from "./thpHighlighter";
|
||||||
|
document.addEventListener("DOMContentLoaded", highlightOnDom);
|
||||||
|
</script>
|
||||||
|
</BaseLayout>
|
@ -108,31 +108,8 @@ for (const entry of pagesIndex) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { thp_highlighter, CodeJar } from "../lexer/highlighter";
|
import {highlightOnDom} from "./thpHighlighter";
|
||||||
// Add an editor to all code samples
|
document.addEventListener("DOMContentLoaded", highlightOnDom);
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
const code_elements = document.querySelectorAll(".language-thp");
|
|
||||||
|
|
||||||
for (const e of [...code_elements]) {
|
|
||||||
const el = e as HTMLElement;
|
|
||||||
// Some elements with .language-thp don't want to be processed
|
|
||||||
if (e.getAttribute("data-disabled") !== null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const pre_parent = el.parentElement!;
|
|
||||||
const new_div = document.createElement("div");
|
|
||||||
const code = el.innerText;
|
|
||||||
|
|
||||||
el.parentElement!.className = "language-thp";
|
|
||||||
pre_parent.removeChild(el);
|
|
||||||
pre_parent.appendChild(new_div);
|
|
||||||
|
|
||||||
CodeJar(new_div, thp_highlighter, {
|
|
||||||
tab: " ",
|
|
||||||
}).updateCode(code);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
// Highlight the current url of the sidebar
|
// Highlight the current url of the sidebar
|
||||||
|
45
src/layouts/thpHighlighter.ts
Normal file
45
src/layouts/thpHighlighter.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { thp_highlighter, CodeJar } from "../lexer/highlighter";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlights all THP code snippets mounted in the DOM with class .language-thp
|
||||||
|
*
|
||||||
|
* It assumes that the code is inside: <pre class="language-thp"><code>...
|
||||||
|
*/
|
||||||
|
export function highlightOnDom() {
|
||||||
|
const code_elements = document.querySelectorAll("code.language-thp");
|
||||||
|
|
||||||
|
for (const e of [...code_elements]) {
|
||||||
|
const el = e as HTMLElement;
|
||||||
|
// Some elements with .language-thp don't want to be processed
|
||||||
|
if (e.getAttribute("data-disabled") !== null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pre_parent = el.parentElement!;
|
||||||
|
const new_div = document.createElement("div");
|
||||||
|
const code = el.innerText;
|
||||||
|
|
||||||
|
el.parentElement!.className = "language-thp";
|
||||||
|
pre_parent.removeChild(el);
|
||||||
|
pre_parent.appendChild(new_div);
|
||||||
|
|
||||||
|
// Create and append a language name indicator
|
||||||
|
|
||||||
|
CodeJar(new_div, thp_highlighter, {
|
||||||
|
tab: " ",
|
||||||
|
}).updateCode(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pre_elements = document.querySelectorAll("pre");
|
||||||
|
for (const pre_el of pre_elements) {
|
||||||
|
const language = pre_el.getAttribute("data-language");
|
||||||
|
if (language === null) { continue; }
|
||||||
|
|
||||||
|
// Create a visual indicador
|
||||||
|
const indicator = document.createElement("span");
|
||||||
|
indicator.className = "absolute top-2 right-2 inline-block text-sm select-none opacity-75";
|
||||||
|
indicator.innerText = language;
|
||||||
|
pre_el.appendChild(indicator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
38
src/pages/api/index.md
Normal file
38
src/pages/api/index.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
layout: ../../layouts/ApiLayout.astro
|
||||||
|
---
|
||||||
|
|
||||||
|
# module `std`
|
||||||
|
|
||||||
|
## The THP standard library
|
||||||
|
|
||||||
|
This module contains many functions, classes, constant & enums
|
||||||
|
commonly used in THP programs. These can be used directly,
|
||||||
|
without having to import them.
|
||||||
|
|
||||||
|
This module is not a 1:1 map of the global PHP scope. Instead,
|
||||||
|
this module contains all those members organized into classes,
|
||||||
|
objects or other modules.
|
||||||
|
|
||||||
|
For example, to find if a string contains another, in PHP you'd do:
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
if (str_contains("abc", "a")) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In THP there is no `str_contains` function. Instead, you'd call the
|
||||||
|
`contains` method on the string:
|
||||||
|
|
||||||
|
```thp
|
||||||
|
if "abc".contains("a")
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -100,25 +100,28 @@ import Navbar from "../components/Navbar.astro";
|
|||||||
});
|
});
|
||||||
|
|
||||||
jar.updateCode(
|
jar.updateCode(
|
||||||
`// Actual generics & sum types
|
`// Sum types
|
||||||
fun find_person(Int person_id) -> Result[String, String] {
|
enum Animal {
|
||||||
// Easy, explicit error bubbling
|
Dog(String),
|
||||||
try Person::find_by_id(person_id)
|
Cat(String, Int),
|
||||||
}
|
}
|
||||||
|
|
||||||
val id = POST::get("person_id") ?? exit("Null person_id")
|
// Null safety
|
||||||
// Errors as values
|
val cat_name = Post::get("cat_name") ?? "Michi"
|
||||||
val person = try find_person(person_id: id) with error {
|
val cat1 = Animal::Cat(cat_name, 9)
|
||||||
eprint("Error: {error}")
|
|
||||||
exit("Person not found")
|
// Errors as values, easy handling
|
||||||
}
|
val cat2 = try clone_cat(cat) else die("Not a cat")
|
||||||
|
|
||||||
|
// Pattern matching
|
||||||
|
match random_animal()
|
||||||
|
case Dog(name) { print("{name} has 1 live ") }
|
||||||
|
case Cat(name, lives) { print("{name} has {lives}") }
|
||||||
|
|
||||||
// First class HTML-like templates & components
|
// First class HTML-like templates & components
|
||||||
print(
|
|
||||||
<a href="/person/reports/{person.id}">
|
<a href="/person/reports/{person.id}">
|
||||||
welcome, {person.name}
|
welcome, {person.name}
|
||||||
</a>
|
</a>
|
||||||
)
|
|
||||||
// And more!`,
|
// And more!`,
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
@ -151,7 +151,7 @@ In the previous example:
|
|||||||
|
|
||||||
### Try/else
|
### Try/else
|
||||||
|
|
||||||
Try/return will assign a new value if an expression fails.
|
Try/else will assign a new value if an expression fails.
|
||||||
|
|
||||||
<InteractiveCode
|
<InteractiveCode
|
||||||
code={`
|
code={`
|
||||||
|
Loading…
Reference in New Issue
Block a user