Begin work on interactive code component
This commit is contained in:
parent
253e4bbb48
commit
1a7a0f1e3a
BIN
public/Iosevka/Bold.woff2
Normal file
BIN
public/Iosevka/Bold.woff2
Normal file
Binary file not shown.
BIN
public/Iosevka/Heavy.woff2
Normal file
BIN
public/Iosevka/Heavy.woff2
Normal file
Binary file not shown.
BIN
public/Iosevka/Regular.woff2
Normal file
BIN
public/Iosevka/Regular.woff2
Normal file
Binary file not shown.
@ -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 {
|
:root {
|
||||||
--c-bg: #121212;
|
--c-bg: #121212;
|
||||||
@ -49,7 +68,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pre, code {
|
pre, code {
|
||||||
font-family: Iosevka, 'Fira Code', monospace;
|
font-family: "Iosevka Fixed Web", "Iosevka Nerd Font", Iosevka, monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-effect-receiver {
|
.button-effect-receiver {
|
||||||
|
81
src/components/InteractiveCode.astro
Normal file
81
src/components/InteractiveCode.astro
Normal 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>
|
@ -6,7 +6,7 @@ import Sidebar from "../components/Sidebar.astro";
|
|||||||
|
|
||||||
const { frontmatter, headings } = Astro.props;
|
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.
|
// The index.md page must have a `pagesLayout` frontmatter, which declares the order of all the pages.
|
||||||
const indexSubpath = `/learn/index.md`;
|
const indexSubpath = `/learn/index.md`;
|
||||||
@ -35,7 +35,7 @@ function validateEntry(entry: PageEntry, basePath: string) {
|
|||||||
if (!entry.children) {
|
if (!entry.children) {
|
||||||
// Attempt to get the page title from frontmatter
|
// Attempt to get the page title from frontmatter
|
||||||
const pageData = posts.find((post) =>
|
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) {
|
if (pageData === undefined) {
|
||||||
@ -116,6 +116,10 @@ for (const entry of pagesIndex) {
|
|||||||
|
|
||||||
for (const e of [...code_elements]) {
|
for (const e of [...code_elements]) {
|
||||||
const el = e as HTMLElement;
|
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 pre_parent = el.parentElement!;
|
||||||
const new_div = document.createElement("div");
|
const new_div = document.createElement("div");
|
||||||
const code = el.innerText;
|
const code = el.innerText;
|
||||||
|
@ -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`
|
|
31
src/pages/learn/basics/hello-world.mdx
Normal file
31
src/pages/learn/basics/hello-world.mdx
Normal 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>
|
@ -19,7 +19,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
fontFamily: {
|
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"],
|
"display": ["Inter", "'Josefin Sans'", "'Fugaz One'", "sans-serif"],
|
||||||
"body": ["Inter", "sans-serif"],
|
"body": ["Inter", "sans-serif"],
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user