Compare commits

...

3 Commits

Author SHA1 Message Date
42b724966d Update jenkinsfile to build astro site 2024-04-23 10:18:38 -05:00
db5ebbb807 Rewrite in Astrojs 2024-04-23 10:16:51 -05:00
0fd81d31e3 small changes 2024-04-23 10:15:21 -05:00
65 changed files with 773 additions and 401 deletions

28
.gitignore vendored
View File

@ -1,4 +1,24 @@
node_modules
static/css/out.css
static/learn
static/js/highlighter.js
# build output
dist/
# generated types
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
# macOS-specific files
.DS_Store
# jetbrains setting folder
.idea/

View File

@ -9,23 +9,14 @@ pipeline {
sh 'bun i'
}
}
stage('Build tailwind') {
environment {
PATH = "${env.WORKSPACE}/node_modules/.bin:${env.PATH}"
}
steps {
sh 'md-docs'
sh './node_modules/.bin/tailwindcss -i ./tailwind.css -o ./static/css/out.css --minify'
}
}
stage('Build bundle') {
steps {
sh 'bun bundle'
sh 'bun run build'
}
}
stage('Deploy') {
steps {
sh 'cp -r ./static/* /var/www/thp-docs/'
sh 'cp -r ./dist/* /var/www/thp-docs/'
}
}
}

47
README.md Normal file
View File

@ -0,0 +1,47 @@
# Astro Starter Kit: Minimal
```sh
npm create astro@latest -- --template minimal
```
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/minimal)
[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/minimal)
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/minimal/devcontainer.json)
> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun!
## 🚀 Project Structure
Inside of your Astro project, you'll see the following folders and files:
```text
/
├── public/
├── src/
│ └── pages/
│ └── index.astro
└── package.json
```
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
Any static assets, like images, can be placed in the `public/` directory.
## 🧞 Commands
All commands are run from the root of the project, from a terminal:
| Command | Action |
| :------------------------ | :----------------------------------------------- |
| `npm install` | Installs dependencies |
| `npm run dev` | Starts local dev server at `localhost:4321` |
| `npm run build` | Build your production site to `./dist/` |
| `npm run preview` | Preview your build locally, before deploying |
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
| `npm run astro -- --help` | Get help using the Astro CLI |
## 👀 Want to learn more?
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).

12
astro.config.mjs Normal file
View File

@ -0,0 +1,12 @@
import { defineConfig } from 'astro/config';
import tailwind from "@astrojs/tailwind";
import mdx from "@astrojs/mdx";
// https://astro.build/config
export default defineConfig({
integrations: [tailwind(), mdx()],
markdown: {
syntaxHighlight: false,
},
});

BIN
bun.lockb

Binary file not shown.

View File

@ -1,11 +0,0 @@
input: md
output: static
template: static/template.html
headings:
h1: text-4xl mb-4 mt-8 font-display opacity-90 font-black text-c-text-2
h2: text-2xl mt-10 mb-4 font-display opacity-90 font-bold text-c-text-2
h3: text-xl mt-10 mb-4 font-display opacity-90 text-c-text-2
file_tree_title_classes: "uppercase font-display text-c-text-2 font-medium"
link_classes: text-blue-500 hover:underline

View File

@ -1,5 +0,0 @@
# Operators
Some common operators

View File

@ -1,4 +0,0 @@
# Blocks
Blocks :D

View File

@ -1,72 +0,0 @@
path: ""
name: ""
has_index: true
children:
- path: index
name: Index
- path: install
name: Install
- path: basics
name: Basics
children:
- path: hello-world
name: Hello, world!
- name: Variables
path: variables
- path: datatypes
name: Datatypes
- path: comments
name: Comments
- name: Flow control
path: flow-control
children:
- name: Blocks
path: blocks
- name: Conditionals
path: conditionals
- name: Loops
path: loops
- name: Match
path: match
- name: Data structures
path: data-structures
children:
- name: Tuples
path: tuples
- name: Arrays
path: arrays
- name: Maps
path: maps
- name: Enums
path: enums
- name: Functions
path: functions
children:
- name: Declaration
path: declaration
- name: Parameter references
path: parameters
- name: Higher-order functions
path: higher-order
- name: Lambdas
path: lambdas
- name: Error handling
path: error-handling
children:
- name: Nullable types
path: "null"
- name: Try expressions
path: try
- name: Classes
path: classes
children:
- name: Definition
path: definition
- name: Static
path: static
- name: Interfaces
path: interfaces
- name: Anonymous classes
path: anonymous
- name: Magic
path: magic

View File

@ -1,29 +1,22 @@
{
"name": "docs",
"version": "1.0.0",
"description": "",
"main": "index.js",
"name": "thp-docs",
"type": "module",
"version": "0.0.1",
"scripts": {
"generate": "md-docs",
"bundle": "bun build ./lexer/highlighter.ts --outdir ./static/js/ --format esm --minify",
"dev": "concurrently -k \"tailwindcss -i ./tailwind.css -o ./static/css/out.css --watch\" \"serve ./static/ -l 3333\"",
"tailwind:watch": "tailwindcss -i ./tailwind.css -o ./static/css/out.css --watch",
"tailwind:build": "tailwindcss -i ./tailwind.css -o ./static/css/out.css"
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@types/bun": "^1.0.10",
"@astrojs/check": "^0.5.10",
"@astrojs/mdx": "^2.3.0",
"@astrojs/tailwind": "^5.1.0",
"@types/bun": "^1.0.12",
"astro": "^4.6.1",
"codejar": "^4.2.0",
"tailwindcss": "^3.2.7"
},
"devDependencies": {
"concurrently": "^8.2.0",
"serve": "^14.2.1",
"bun-types": "latest"
},
"peerDependencies": {
"typescript": "^5.0.0"
"tailwindcss": "^3.4.3",
"typescript": "^5.4.5"
}
}

View File

@ -1,6 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--c-bg: #121212;

39
public/css/pages.css Normal file
View File

@ -0,0 +1,39 @@
.markdown h1 {
font-size: 2.25rem;
line-height: 2.5rem;
margin-bottom: 1rem;
margin-top: 2rem;
font-family: Inter, sans-serif;
opacity: 0.9;
font-weight: 900;
color: var(--c-text-2);
}
.markdown h2 {
/* use these tailwind classes: text-2xl mt-10 mb-4 font-display opacity-90 font-bold text-c-text-2 */
font-size: 1.5rem;
line-height: 2rem;
margin-bottom: 1rem;
margin-top: 2.5rem;
font-family: Inter, sans-serif;
opacity: 0.9;
font-weight: 700;
color: var(--c-text-2);
}
.markdown ul {
list-style-type: disc;
list-style-position: inside;
}
.markdown ul li {
padding: 0.5rem 0;
}
.markdown pre {
margin: 0.5em 0;
padding: 0.75em 0.75em;
color: var(--code-theme-color);
background: var(--code-theme-bg-color);
}

9
public/favicon.svg Normal file
View File

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
<style>
path { fill: #000; }
@media (prefers-color-scheme: dark) {
path { fill: #FFF; }
}
</style>
</svg>

After

Width:  |  Height:  |  Size: 749 B

View File

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -0,0 +1,19 @@
<nav class="fixed w-full top-0 h-12 border-b border-[rgba(150,150,150,0.25)] bg-c-nav-bg backdrop-blur-md z-20">
<div class="container mx-auto h-full w-full flex items-center">
<a href="/" class="inline-block px-4 font-display font-black text-2xl hover:underline">
<span class="text-[#F5A9B8]">t</span><span>h</span><span class="text-[#5BCEFA]">p</span>
</a>
<a href="/learn/" class="hidden lg:inline-block px-4 font-display font-bold-text-xl hover:underline">
Learn
</a>
<a href="/how-to/" class="hidden lg:inline-block px-4 font-display font-bold-text-xl hover:underline">
How to guides
</a>
<a href="/reference/" class="hidden lg:inline-block px-4 font-display font-bold-text-xl hover:underline">
Language reference
</a>
<a href="/api/" class="hidden lg:inline-block px-4 font-display font-bold-text-xl hover:underline">
Stdlib API
</a>
</div>
</nav>

View File

@ -0,0 +1,39 @@
---
import type { PageEntry } from "../layouts/PagesLayout.astro";
const entry: PageEntry = Astro.props.entry;
const basePath: string = Astro.props.basePath;
const entryPath = entry.path === "index"? "": entry.path;
---
{
!entry.children && (
<li>
<a
class="inline-block rounded-2xl w-full hover:bg-neutral-200 dark:hover:bg-neutral-800 transition-colors px-3 py-2"
href={`${basePath}${entryPath}`}
>
{entry.title}
</a>
</li>
)
}
{
entry.children && (
<>
<div class="mt-6 px-3 py-1 uppercase font-display text-c-text-2 font-medium">
{entry.title}
</div>
<ul class="my-1">
{entry.children!.map((nextEntry) => (
<Astro.self
entry={nextEntry}
basePath={`${basePath}${entry.path}/`}
/>
))}
</ul>
</>
)
}

39
src/components/TOC.astro Normal file
View File

@ -0,0 +1,39 @@
---
// github.com/rezahedi/rezahedi.dev/blob/main/src/components/TOC.astro
import TOCHeading from "./TOCHeading.astro";
const { headings } = Astro.props;
const toc = buildHierarchy(headings);
function buildHierarchy(headings: any) {
const toc: any[] = [];
const parentHeadings = new Map();
if (!headings) return toc;
headings.forEach((h: any) => {
const heading = { ...h, subheadings: [] };
parentHeadings.set(heading.depth, heading);
// Change 2 to 1 if your markdown includes your <h1>
if (heading.depth === 1) {
toc.push(heading);
} else {
parentHeadings.get(heading.depth - 1).subheadings.push(heading);
}
});
return toc;
}
---
{
toc && toc.length > 0 && (
<nav class="article-toc">
<ul>
{toc.map((heading) => (
<TOCHeading heading={heading} />
))}
</ul>
</nav>
)
}

View File

@ -0,0 +1,19 @@
---
// github.com/rezahedi/rezahedi.dev/blob/main/src/components/TOCHeading.astro
const { heading } = Astro.props;
---
<li>
<a class="inline-block py-1" href={"#" + heading.slug}>
{heading.text}
</a>
{
heading.subheadings.length > 0 && (
<ul class="px-2">
{heading.subheadings.map((subheading: any) => (
<Astro.self heading={subheading} />
))}
</ul>
)
}
</li>

1
src/env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="astro/client" />

View File

@ -0,0 +1,31 @@
---
const {title} = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{title ?? "THP: Typed Hypertext Processor"}</title>
<link rel="stylesheet" href="/css/global.css" />
<link rel="stylesheet" href="/css/pages.css">
<link rel="stylesheet" href="/css/xcode-colors.css" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Fira+Sans:wght@400;500;600;700;800;900&family=Fira+Code&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap"
rel="stylesheet"
/>
</head>
<body class="bg-c-bg text-c-text">
<slot />
</body>
</html>

View File

@ -0,0 +1,146 @@
---
import Navbar from "../components/Navbar.astro";
import BaseLayout from "./BaseLayout.astro";
import TOC from "../components/TOC.astro";
import Sidebar from "../components/Sidebar.astro";
const { frontmatter, headings } = Astro.props;
const posts = await Astro.glob("../pages/learn/**/*.md");
// The index.md page must have a `pagesLayout` frontmatter, which declares the order of all the pages.
const indexSubpath = `/learn/index.md`;
const indexPage = posts.find((post) => post.file.endsWith(indexSubpath));
if (indexPage === undefined) {
throw new Error(`No index page found at ${indexSubpath}`);
}
export type PageEntry = {
path: string;
title?: string;
children?: Array<PageEntry>;
};
const pagesIndex: Array<PageEntry> | undefined =
indexPage.frontmatter.pagesLayout;
if (pagesIndex === undefined) {
console.error(indexPage.frontmatter);
throw new Error(`No pagesLayout frontmatter found in ${indexSubpath}`);
}
function validateEntry(entry: PageEntry, basePath: string) {
if (!entry.children) {
// Attempt to get the page title from frontmatter
const pageData = posts.find((post) =>
post.file.endsWith(entry.path + ".md"),
);
if (pageData === undefined) {
console.error(entry);
console.error(entry.path + ".md");
throw new Error(`No page found at ${entry.path}`);
}
// set the title
entry.title = pageData.frontmatter.title ?? "Title not set";
return;
}
// Recursively search for children
if (!entry.title) {
console.log(entry);
throw new Error(
`No title found in ${basePath + entry.path}, which is a folder and requires it.`,
);
}
const folderName = entry.title;
entry.children.forEach((child) =>
validateEntry(child, basePath + "/" + folderName),
);
}
for (const entry of pagesIndex) {
validateEntry(entry, `/learn/`);
}
---
<BaseLayout title={frontmatter.title}>
<Navbar />
<div class="lg:grid lg:grid-cols-[14rem_auto_12rem] container mx-auto">
<div class="pt-12 lg:h-screen lg:sticky top-0">
<nav
id="sidebar"
class="py-4 pr-2 overflow-x-scroll lg:h-[calc(100vh-3rem)]"
>
{
pagesIndex.map((entry) => (
<Sidebar entry={entry} basePath="/learn/" />
))
}
</nav>
</div>
<main class="lg:py-[3.5rem] lg:pl-12 lg:pr-4 markdown min-w-0">
<slot />
</main>
<div class="lg:pt-12 pt-4 max-h-screen overflow-x-scroll sticky top-0">
<nav class="rounded-md lg:mt-10">
<h2 class="font-display font-medium pb-2 text-c-text-2">
On this page
</h2>
<TOC headings={headings} />
</nav>
</div>
</div>
<script>
import { thp_highlighter, CodeJar } from "../lexer/highlighter";
// Add an editor to all code samples
const code_elements = document.querySelectorAll(".language-thp");
for (const e of [...code_elements]) {
const el = e as HTMLElement;
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>
// Highlight the current url of the sidebar
document.addEventListener("DOMContentLoaded", () => {
let current_uri = window.location.pathname;
const sidebar = document.getElementById("sidebar")!;
const links = sidebar.querySelectorAll("a");
for (const link of [...links]) {
if (link.getAttribute("href") === current_uri) {
console.log(sidebar.offsetTop);
console.log(link.offsetTop);
sidebar.scrollTop = link.offsetTop - sidebar.offsetTop - 250;
link.classList.add("bg-pink-200", "dark:bg-pink-950");
break;
}
}
});
</script>
</BaseLayout>

View File

@ -1,7 +1,7 @@
import {lex} from "./lexer.ts";
import { CodeJar } from "codejar"
import { lex } from "./lexer";
import {CodeJar as Codejar} from "codejar";
function thp_highlighter(editor: any) {
export function thp_highlighter(editor: any) {
let code: string = editor.textContent;
let tokens = lex(code);
@ -15,7 +15,4 @@ function thp_highlighter(editor: any) {
editor.innerHTML = highlighted_code;
}
// @ts-ignore
window.thp_highlighter = thp_highlighter;
// @ts-ignore
window.CodeJar = CodeJar;
export const CodeJar = Codejar;

View File

@ -1,5 +1,5 @@
import type { Token } from "./lexer.ts";
import { is_identifier_char } from "./utils.ts";
import type { Token } from "./lexer";
import { is_identifier_char } from "./utils";
/**
* Scans an identifier, at the given position in the input string.

View File

@ -1,7 +1,7 @@
import { scan_identifier } from "./identifier_lexer.ts";
import { scan_number } from "./number_lexer.ts";
import { scan_string } from "./string_lexer.ts";
import { is_digit, is_lowercase, is_uppercase } from "./utils.ts";
import { scan_identifier } from "./identifier_lexer";
import { scan_number } from "./number_lexer";
import { scan_string } from "./string_lexer";
import { is_digit, is_lowercase, is_uppercase } from "./utils";
export type Token = {
v: string,

View File

@ -1,5 +1,5 @@
import type { Token } from "./lexer.ts";
import { is_digit } from "./utils.ts";
import type { Token } from "./lexer";
import { is_digit } from "./utils";
/**
* Scans a number, at the given position in the input string.

View File

@ -1,4 +1,4 @@
import type { Token } from "./lexer.ts";
import type { Token } from "./lexer";
export function scan_string(input: string, starting_position: number): [Token, number] {
let value = "\"";

125
src/pages/index.astro Normal file
View File

@ -0,0 +1,125 @@
---
import BaseLayout from "../layouts/BaseLayout.astro";
import Navbar from "../components/Navbar.astro";
---
<BaseLayout>
<Navbar />
<div
class="container mx-auto lg:py-16 py-2 lg:grid 2xl:grid-cols-[auto_32rem] lg:grid-cols-[auto_36rem] gap-4 lg:px-10 px-2"
>
<div class="lg:pl-10 table">
<div class="table-cell align-middle">
<h1
class="font-display font-bold text-c-text-2 lg:text-5xl text-3xl lg:text-left text-center leading-tight"
>
A modern, type safe,
<br class="hidden lg:inline-block" />
secure language
<br class="hidden lg:inline-block" />
compiled to PHP
</h1>
<p class="font-display text-c-text text-xl pt-6 lg:pr-12">
Inspired by Rust, Zig and Swift, THP has a modern syntax,
semantics, type system and stdlib.
</p>
<br />
<br />
<div class="text-center">
<a
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"
href="/learn/"
>
Tutorial
</a>
<a
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"
href="/install/"
>
Install
</a>
</div>
</div>
</div>
<div
class="bg-[var(--code-theme-bg-color)] lg:p-6 p-2 rounded-lg relative"
>
<span
class="absolute lg:inline-block hidden h-[35rem] w-[35rem] -z-10 top-1/2 left-1/2 rounded-full
transform -translate-x-1/2 -translate-y-1/2"
style="background-image: conic-gradient(from 180deg at 50% 50%,#5BCEFA 0deg,#a853ba 180deg,#F5A9B8 1turn);
filter: blur(75px); opacity: 0.75;"
>
</span>
<svg
xmlns="http://www.w3.org/2000/svg"
width="54"
height="14"
viewBox="0 0 54 14"
>
<g fill="none" fill-rule="evenodd" transform="translate(1 1)">
<circle
cx="6"
cy="6"
r="6"
fill="#FF5F56"
stroke="#E0443E"
stroke-width=".5"></circle>
<circle
cx="26"
cy="6"
r="6"
fill="#FFBD2E"
stroke="#DEA123"
stroke-width=".5"></circle>
<circle
cx="46"
cy="6"
r="6"
fill="#27C93F"
stroke="#1AAB29"
stroke-width=".5"></circle>
</g>
</svg>
<div class="h-1"></div>
<div id="editor" class="font-mono language-thp"></div>
</div>
</div>
<script>
import { thp_highlighter, CodeJar } from "../lexer/highlighter";
let jar = CodeJar(document.getElementById("editor")!, thp_highlighter, {
tab: " ",
});
jar.updateCode(
`// Actual generics & sum types
fun find_person(Int person_id) -> Result[String, String] {
// Easy, explicit error bubbling
try Person::find_by_id(person_id)
}
val id = POST::get("person_id") ?? exit("Null person_id")
// Errors as values
val person = try find_person(person_id: id) with error {
eprint("Error: {error}")
exit("Person not found")
}
// First class HTML-like templates & components
print(
<a href="/person/reports/{person.id}">
welcome, {person.name}
</a>
)
// And more!`,
);
</script>
</BaseLayout>

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Comments
---
# Comments
Only these two:

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Datatypes
---
# Datatypes
Datatypes's first character are always uppercase.

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Hello world
---
# Hello, world!
Create a file named `hello.thp` with the contents:

View File

@ -0,0 +1,10 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Install
---
# Operators
Some common operators

View File

@ -1,3 +1,9 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Variables
---
# Variables
thp distinguishes between mutable and immutable variables.

View File

@ -1,3 +1,7 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Anonymous classes
---
# Anonymous classes

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Classes
---
# Classes
Basically kotlin syntax.

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Interfaces
---
# Interfaces

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Magic methods
---
# Magic methods
Don't get special treatment.

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Static
---
# Static in classes

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Arrays
---
# Arrays
Use square brackets as usual.

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Enums
---
# Enums (Tagged unions)
## Basic enums

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Maps
---
# Maps
Also known as Associative Arrays, or Objects in other languages.

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Tuples
---
# Tuples
Uses `#()` just to avoid confusion with function calls and grouping (`()`).

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Nullable types
---
# Nullable types
All datatypes in THP disallow the usage of `null` by default.

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Try expressions
---
# Try expressions
```thp

View File

@ -0,0 +1,9 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Blocks
---
# Blocks
Blocks :D

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Conditionals
---
# Conditionals
- Only `Bool` are accepted. No truthy/falsy.

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Loops
---
# Loops
## For loop

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Match
---
# Match
## Syntax

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Declaration
---
# Declaration

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Higher Order Functions
---
# Higher Order functions

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Lambdas
---
# Lambdas / Anonymous functions

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Function parameters
---
# Function parameters

View File

@ -1,3 +1,53 @@
---
layout: ../../layouts/PagesLayout.astro
title: Welcome
pagesLayout:
- path: index
- path: install
- path: basics
title: Basics
children:
- path: hello-world
- path: variables
- path: datatypes
- path: comments
- path: flow-control
title: Flow control
children:
- path: blocks
- path: conditionals
- path: loops
- path: match
- path: data-structures
title: Data structures
children:
- path: tuples
- path: arrays
- path: maps
- path: enums
- path: functions
title: Functions
children:
- path: declaration
- path: parameters
- path: higher-order
- path: lambdas
- path: error-handling
title: Error handling
children:
- path: "null"
- path: try
- path: classes
title: Classes
children:
- path: definition
- path: static
- path: interfaces
- path: anonymous
- path: magic
---
# Welcome
Welcome to the documentation of the THP programming languague.
@ -9,7 +59,7 @@ THP is a new programming language that compiles to PHP.
<br>
This page discusses some of the design decitions of the language,
if you want to install THP go to the [installation guide](/installation-guide)
if you want to install THP go to the [installation guide](install)
If you want to learn the language, go to the learn section.

View File

@ -1,3 +1,8 @@
---
layout: ../../layouts/PagesLayout.astro
title: Install
---
# Install
## From scratch

View File

@ -1,122 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>THP: Typed Hypertext Processor</title>
<!-- Tailwind output -->
<link href="/css/out.css" rel="stylesheet">
<link rel="stylesheet" href="/css/xcode-colors.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Fira+Sans:wght@400;500;600;700;800;900&family=Fira+Code&display=swap"
rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap" rel="stylesheet">
</head>
<body class="bg-c-bg text-c-text">
<nav class="sticky top-0 h-12 border-b border-[rgba(150,150,150,0.25)] bg-c-nav-bg backdrop-blur-md z-20">
<div class="container mx-auto h-full w-full flex items-center">
<a href="/" class="inline-block px-4 font-display font-black text-2xl hover:underline">
<span class="text-[#F5A9B8]">t</span><span>h</span><span class="text-[#5BCEFA]">p</span>
</a>
<a href="/learn/" class="hidden lg:inline-block px-4 font-display font-bold-text-xl hover:underline">
Learn
</a>
<a href="/how-to/" class="hidden lg:inline-block px-4 font-display font-bold-text-xl hover:underline">
How to guides
</a>
<a href="/reference/" class="hidden lg:inline-block px-4 font-display font-bold-text-xl hover:underline">
Language reference
</a>
<a href="/api/" class="hidden lg:inline-block px-4 font-display font-bold-text-xl hover:underline">
Stdlib API
</a>
</div>
</nav>
<div class="container mx-auto lg:py-16 py-2 lg:grid 2xl:grid-cols-[auto_32rem] lg:grid-cols-[auto_36rem] gap-4 lg:px-10 px-2">
<div class="lg:pl-10 table">
<div class="table-cell align-middle">
<h1 class="font-display font-bold text-c-text-2 lg:text-5xl text-3xl lg:text-left text-center leading-tight">
A modern, type safe,
<br class="hidden lg:inline-block">
secure language
<br class="hidden lg:inline-block">
compiled to PHP
</h1>
<p class="font-display text-c-text text-xl pt-6 lg:pr-12">
Inspired by Rust, Zig and Swift, THP has a modern syntax, semantics,
type system and stdlib.
</p>
<br>
<br>
<div class="text-center">
<a 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" href="/learn/">
Tutorial
</a>
<a 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" href="/install/">
Install
</a>
</div>
</div>
</div>
<div class="bg-[var(--code-theme-bg-color)] lg:p-6 p-2 rounded-lg relative">
<span class="absolute lg:inline-block hidden h-[35rem] w-[35rem] -z-10 top-1/2 left-1/2 rounded-full
transform -translate-x-1/2 -translate-y-1/2" style="background-image: conic-gradient(from 180deg at 50% 50%,#5BCEFA 0deg,#a853ba 180deg,#F5A9B8 1turn);
filter: blur(75px); opacity: 0.75;">
</span>
<svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14">
<g fill="none" fill-rule="evenodd" transform="translate(1 1)">
<circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle>
<circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle>
<circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle>
</g>
</svg>
<div class="h-1"></div>
<div id="editor" class="font-mono language-thp"></div>
</div>
</div>
<script src="/js/highlighter.js"></script>
<script>
let jar = CodeJar(document.getElementById("editor"), thp_highlighter, {
tab: " ",
});
jar.updateCode(
`// Actual generics & sum types
fun find_person(Int person_id) -> Result[String, String] {
// Easy, explicit error bubbling
try Person::find_by_id(person_id)
}
val id = POST::get("person_id") ?? exit("Null person_id")
// Errors as values
val person = try find_person(person_id: id) with error {
eprint("Error: {error}")
exit("Person not found")
}
// First class HTML-like templates & components
print(
<a href="/person/reports/{person.id}">
welcome, {person.name}
</a>
)
// And more!`
)
</script>
</body>
</html>

View File

@ -1,97 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>THP: Typed Hypertext Processor</title>
<!-- Tailwind output -->
<link href="/css/out.css" rel="stylesheet">
<link rel="stylesheet" href="/css/xcode-colors.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Fira+Sans:wght@400;500;600;700;800;900&family=Fira+Code&display=swap"
rel="stylesheet">
</head>
<body class="bg-c-bg text-c-text">
<nav class="fixed w-screen top-0 h-12 border-b border-[rgba(150,150,150,0.25)] bg-c-nav-bg backdrop-blur-md z-20">
<div class="container mx-auto h-full w-full flex items-center">
<a href="/" class="font-display font-bold text-2xl">
<span class="text-[#F5A9B8]">t</span><span>h</span><span class="text-[#5BCEFA]">p</span>
</a>
</div>
</nav>
<div class="lg:grid lg:grid-cols-[14rem_auto_12rem] container mx-auto">
<div class="pt-12 lg:h-screen lg:sticky top-0">
<nav id="sidebar" class="py-4 pr-2 overflow-x-scroll lg:h-[calc(100vh-3rem)]"
>
{{pages}}
</nav>
</div>
<main class="lg:py-[3.5rem] lg:pl-12 lg:pr-4 markdown min-w-0">
{{markdown}}
</main>
<div class="lg:pt-12 pt-4 max-h-screen overflow-x-scroll sticky top-0">
<nav class="rounded-md lg:mt-10">
<h2 class="font-display font-medium pb-2 text-c-text-2">On this page</h2>
{{sidebar}}
</nav>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
let current_uri = window.location.pathname;
if (!current_uri.endsWith("/") && !current_uri.endsWith(".html")) {
current_uri += ".html";
}
const sidebar = document.getElementById("sidebar");
const links = sidebar.querySelectorAll("a");
for (const link of [...links]) {
if (link.getAttribute("href") === current_uri) {
console.log(sidebar.offsetTop);
console.log(link.offsetTop);
const viewport_middle = window.innerHeight / 2;
sidebar.scrollTop = link.offsetTop - sidebar.offsetTop - 250;
link.classList.add("bg-pink-200", "dark:bg-pink-950");
// link.scrollIntoView({ behavior: "instant", block: "nearest", inline: "nearest" });
break;
}
}
});
</script>
<script src="/js/highlighter.js"></script>
<script>
// Add an editor to all code samples
const code_elements = document.querySelectorAll(".language-thp");
for (const el of [...code_elements]) {
const pre_parent = el.parentElement;
const new_div = document.createElement("div");
const code = el.innerText;
el.parentElement.classList.add("language-thp");
pre_parent.removeChild(el);
pre_parent.appendChild(new_div);
CodeJar(new_div, thp_highlighter, {
tab: " "
}).updateCode(code);
}
</script>
</body>
</html>

View File

@ -1,8 +1,8 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./static/**/*.html"],
theme: {
extend: {
export default {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: {
extend: {
colors: {
"c-bg": "var(--c-bg)",
"c-text": "var(--c-text)",
@ -22,8 +22,8 @@ module.exports = {
"display": ["Inter", "'Josefin Sans'", "'Fugaz One'", "sans-serif"],
"body": ["Inter", "sans-serif"],
},
},
corePlugins: {
},
corePlugins: {
container: false
},
plugins: [
@ -48,4 +48,3 @@ module.exports = {
}
],
}

View File

@ -1,27 +1,3 @@
{
"compilerOptions": {
// Enable latest features
"lib": ["ESNext"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
// Some stricter flags
"noUnusedLocals": true,
"noUnusedParameters": true,
"noPropertyAccessFromIndexSignature": true
}
}
"extends": "astro/tsconfigs/strictest"
}