Begin work on interactive code component

master
Araozu 2024-05-19 19:11:24 -05:00
parent 253e4bbb48
commit 1a7a0f1e3a
9 changed files with 139 additions and 18 deletions

BIN
public/Iosevka/Bold.woff2 Normal file

Binary file not shown.

BIN
public/Iosevka/Heavy.woff2 Normal file

Binary file not shown.

Binary file not shown.

View File

@ -1,3 +1,22 @@
/* Iosevka web */
@font-face {
font-family: "Iosevka Fixed Web";
font-display: swap;
font-weight: 400;
font-stretch: normal;
font-style: normal;
src: url("/Iosevka/Regular.woff2") format("woff2");
}
@font-face {
font-family: 'Iosevka Fixed Web';
font-display: swap;
font-weight: 700;
font-stretch: normal;
font-style: normal;
src: url('/Iosevka/Bold.woff2') format('woff2');
}
:root {
--c-bg: #121212;
@ -49,7 +68,7 @@ body {
}
pre, code {
font-family: Iosevka, 'Fira Code', monospace;
font-family: "Iosevka Fixed Web", "Iosevka Nerd Font", Iosevka, monospace;
}
.button-effect-receiver {

View File

@ -0,0 +1,81 @@
---
const {code} = Astro.props;
let c = trimAndDedent(code as string);
/**
* Performs the following:
* - Removes the first & last line, if they are empty
* - Picks the indentation level from the first non-white line
* - Dedents the following lines
*/
function trimAndDedent(input: string): string {
let lines = input.split("\n");
// Remove empty lines at the start
while (lines[0] === "") {
lines = lines.slice(1);
}
// Get indentation level
let indentationLevel = 0;
for (const char of lines[0]!) {
if (char === " ") {
indentationLevel += 1;
} else {
break;
}
}
// Enforce indentation, or trim
for (let i = 0; i < lines.length; i += 1) {
// If the line is empty, continue
const characters = lines[i]!.split("");
if (characters.length === 0) {
continue;
}
// If all characters are whitespace, append just a newline
const nonWhitespace = characters.find((x) => x !== " ");
if (nonWhitespace === undefined) {
lines[i] = "";
continue;
}
// Enforce indentation
if (characters.length < indentationLevel) {
throw new Error("Invalid indentation while parsing THP code: " + lines[i]);
}
let currentIndentation = 0;
for (const c of characters) {
if (c === " ") { currentIndentation += 1 }
else {break;}
}
if (currentIndentation < indentationLevel) {
throw new Error("Invalid indentation while parsing THP code: " + lines[i]);
}
lines[i] = characters.slice(4).join("");
}
// Remove empty lines at the end
let endPosition = lines.length - 1;
while (true) {
if (lines[endPosition] === "") {
lines = lines.slice(0, -1);
endPosition -= 1;
} else {
break;
}
}
return lines.join("\n");
}
---
<div>
Interactive code :D
<pre class="language-thp" data-disabled><code>{c}</code></pre>
</div>

View File

@ -6,7 +6,7 @@ import Sidebar from "../components/Sidebar.astro";
const { frontmatter, headings } = Astro.props;
const posts = await Astro.glob("../pages/learn/**/*.md");
const posts = await Astro.glob("../pages/learn/**/*.{md,mdx}");
// The index.md page must have a `pagesLayout` frontmatter, which declares the order of all the pages.
const indexSubpath = `/learn/index.md`;
@ -35,7 +35,7 @@ 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"),
post.file.endsWith(entry.path + ".md") || post.file.endsWith(entry.path + ".mdx"),
);
if (pageData === undefined) {
@ -116,6 +116,10 @@ for (const entry of pagesIndex) {
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;

View File

@ -1,14 +0,0 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Hello world
---
# Hello, world!
Create a file named `hello.thp` with the contents:
```thp
print("Hello, world!")
```
Then run `thp hello.thp`

View File

@ -0,0 +1,31 @@
---
layout: ../../../layouts/PagesLayout.astro
title: Hello world
---
import InteractiveCode from "../../../components/InteractiveCode.astro";
# Hello, world!
Create a file named `hello.thp` with the contents:
```thp
print("Hello, world!")
```
Then run `thp hello.thp`
## Try
<InteractiveCode
code={`
val x = 322
var y = 322
fun f() {
print("gaaaa")
}
`}
attr="aa"
></InteractiveCode>

View File

@ -19,7 +19,7 @@ export default {
}
},
fontFamily: {
"mono": ["Iosevka", "'Iosevka Nerd Font'", "'Fira Code'", "monospace"],
"mono": ["'Iosevka Fixed Web'", "Iosevka", "'Iosevka Nerd Font'", "monospace"],
"display": ["Inter", "'Josefin Sans'", "'Fugaz One'", "sans-serif"],
"body": ["Inter", "sans-serif"],
},