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 # build output
static/css/out.css dist/
static/learn # generated types
static/js/highlighter.js .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' 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') { stage('Build bundle') {
steps { steps {
sh 'bun bundle' sh 'bun run build'
} }
} }
stage('Deploy') { stage('Deploy') {
steps { 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", "name": "thp-docs",
"version": "1.0.0", "type": "module",
"description": "", "version": "0.0.1",
"main": "index.js",
"scripts": { "scripts": {
"generate": "md-docs", "dev": "astro dev",
"bundle": "bun build ./lexer/highlighter.ts --outdir ./static/js/ --format esm --minify", "start": "astro dev",
"dev": "concurrently -k \"tailwindcss -i ./tailwind.css -o ./static/css/out.css --watch\" \"serve ./static/ -l 3333\"", "build": "astro build",
"tailwind:watch": "tailwindcss -i ./tailwind.css -o ./static/css/out.css --watch", "preview": "astro preview",
"tailwind:build": "tailwindcss -i ./tailwind.css -o ./static/css/out.css" "astro": "astro"
}, },
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": { "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", "codejar": "^4.2.0",
"tailwindcss": "^3.2.7" "tailwindcss": "^3.4.3",
}, "typescript": "^5.4.5"
"devDependencies": {
"concurrently": "^8.2.0",
"serve": "^14.2.1",
"bun-types": "latest"
},
"peerDependencies": {
"typescript": "^5.0.0"
} }
} }

View File

@ -1,6 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
:root { :root {
--c-bg: #121212; --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 { lex } from "./lexer";
import { CodeJar } from "codejar" import {CodeJar as Codejar} from "codejar";
function thp_highlighter(editor: any) { export function thp_highlighter(editor: any) {
let code: string = editor.textContent; let code: string = editor.textContent;
let tokens = lex(code); let tokens = lex(code);
@ -15,7 +15,4 @@ function thp_highlighter(editor: any) {
editor.innerHTML = highlighted_code; editor.innerHTML = highlighted_code;
} }
// @ts-ignore export const CodeJar = Codejar;
window.thp_highlighter = thp_highlighter;
// @ts-ignore
window.CodeJar = CodeJar;

View File

@ -1,5 +1,5 @@
import type { Token } from "./lexer.ts"; import type { Token } from "./lexer";
import { is_identifier_char } from "./utils.ts"; import { is_identifier_char } from "./utils";
/** /**
* Scans an identifier, at the given position in the input string. * 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_identifier } from "./identifier_lexer";
import { scan_number } from "./number_lexer.ts"; import { scan_number } from "./number_lexer";
import { scan_string } from "./string_lexer.ts"; import { scan_string } from "./string_lexer";
import { is_digit, is_lowercase, is_uppercase } from "./utils.ts"; import { is_digit, is_lowercase, is_uppercase } from "./utils";
export type Token = { export type Token = {
v: string, v: string,

View File

@ -1,5 +1,5 @@
import type { Token } from "./lexer.ts"; import type { Token } from "./lexer";
import { is_digit } from "./utils.ts"; import { is_digit } from "./utils";
/** /**
* Scans a number, at the given position in the input string. * 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] { export function scan_string(input: string, starting_position: number): [Token, number] {
let value = "\""; 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 # Comments
Only these two: Only these two:

View File

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

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Hello world
---
# Hello, world! # Hello, world!
Create a file named `hello.thp` with the contents: 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 # Variables
thp distinguishes between mutable and immutable variables. thp distinguishes between mutable and immutable variables.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Tuples
---
# Tuples # Tuples
Uses `#()` just to avoid confusion with function calls and grouping (`()`). 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 # Nullable types
All datatypes in THP disallow the usage of `null` by default. 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 # Try expressions
```thp ```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 # Conditionals
- Only `Bool` are accepted. No truthy/falsy. - Only `Bool` are accepted. No truthy/falsy.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +1,8 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Function parameters
---
# 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
Welcome to the documentation of the THP programming languague. Welcome to the documentation of the THP programming languague.
@ -9,7 +59,7 @@ THP is a new programming language that compiles to PHP.
<br> <br>
This page discusses some of the design decitions of the language, 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. 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 # Install
## From scratch ## 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} */ /** @type {import('tailwindcss').Config} */
module.exports = { export default {
content: ["./static/**/*.html"], content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: { theme: {
extend: { extend: {
colors: { colors: {
"c-bg": "var(--c-bg)", "c-bg": "var(--c-bg)",
"c-text": "var(--c-text)", "c-text": "var(--c-text)",
@ -22,8 +22,8 @@ module.exports = {
"display": ["Inter", "'Josefin Sans'", "'Fugaz One'", "sans-serif"], "display": ["Inter", "'Josefin Sans'", "'Fugaz One'", "sans-serif"],
"body": ["Inter", "sans-serif"], "body": ["Inter", "sans-serif"],
}, },
}, },
corePlugins: { corePlugins: {
container: false container: false
}, },
plugins: [ plugins: [
@ -48,4 +48,3 @@ module.exports = {
} }
], ],
} }

View File

@ -1,27 +1,3 @@
{ {
"compilerOptions": { "extends": "astro/tsconfigs/strictest"
// 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
}
}