Remove client side syntax highlighting
This commit is contained in:
parent
631acc8122
commit
ebf62bcd5c
@ -1,7 +1,11 @@
|
|||||||
---
|
---
|
||||||
import { leftTrimDedent } from "./utils";
|
import { leftTrimDedent } from "./utils";
|
||||||
|
import { thp_highlighter } from "../lexer/highlighter";
|
||||||
|
|
||||||
const { thpcode } = Astro.props;
|
const { thpcode } = Astro.props;
|
||||||
|
const html_code = thp_highlighter(leftTrimDedent(thpcode).join("\n"));
|
||||||
---
|
---
|
||||||
|
|
||||||
<pre class="language-thp" data-language="thp"><code class="language-thp">{leftTrimDedent(thpcode).join("\n")}</code></pre>
|
<pre
|
||||||
|
class="language-thp"
|
||||||
|
data-language="thp"><code class="language-thp" set:html={html_code} /><span class="absolute top-2 right-2 inline-block text-sm select-none opacity-75">thp</span></pre>
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
---
|
---
|
||||||
import { trimAndDedent } from "./utils";
|
import Code from "./Code.astro"
|
||||||
|
|
||||||
const { thpcode } = Astro.props;
|
const { thpcode } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="flex h-full py-8 items-center">
|
<div class="flex h-full py-8 items-center">
|
||||||
<div class="p-4 w-full">
|
<div class="p-4 w-full">
|
||||||
<pre
|
<Code thpcode={thpcode} />
|
||||||
class="language-thp"
|
|
||||||
data-language="thp"><code class="language-thp">{trimAndDedent(thpcode).join("\n")}</code></pre>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { lex } from "../lexer/lexer";
|
import { lex } from "../lexer/lexer";
|
||||||
import type { Instruction } from "../thp_machine/machine_parser";
|
import type { Instruction } from "../thp_machine/machine_parser";
|
||||||
import { parse_str } from "../thp_machine/machine_parser";
|
import { parse_str } from "../thp_machine/machine_parser";
|
||||||
import { trimAndDedent } from "./utils";
|
import { leftTrimDedent } from "./utils";
|
||||||
const { code, steps } = Astro.props;
|
const { code, steps } = Astro.props;
|
||||||
|
|
||||||
function highlightCode(lines: Array<string>): string {
|
function highlightCode(lines: Array<string>): string {
|
||||||
@ -31,7 +31,7 @@ function highlightCode(lines: Array<string>): string {
|
|||||||
return outLines.join("\n");
|
return outLines.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
const codeHtml = highlightCode(trimAndDedent(code));
|
const codeHtml = highlightCode(leftTrimDedent(code));
|
||||||
let instructionSet: Array<Array<Instruction>>;
|
let instructionSet: Array<Array<Instruction>>;
|
||||||
try {
|
try {
|
||||||
instructionSet = parse_str(steps);
|
instructionSet = parse_str(steps);
|
||||||
|
@ -5,70 +5,6 @@
|
|||||||
* - Picks the indentation level from the first non-white line
|
* - Picks the indentation level from the first non-white line
|
||||||
* - Dedents the following lines
|
* - Dedents the following lines
|
||||||
*/
|
*/
|
||||||
export function trimAndDedent(input: string): Array<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;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function leftTrimDedent(input: string): Array<string> {
|
export function leftTrimDedent(input: string): Array<string> {
|
||||||
let lines = input.split("\n");
|
let lines = input.split("\n");
|
||||||
let output: Array<string> = [];
|
let output: Array<string> = [];
|
||||||
|
@ -1,48 +1,4 @@
|
|||||||
import { thp_highlighter, CodeJar } from "../lexer/highlighter";
|
import { thp_highlighter, CodeJar } from "../lexer/highlighter";
|
||||||
|
|
||||||
/**
|
export function highlightOnDom() {}
|
||||||
* 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");
|
|
||||||
let code = el.innerHTML;
|
|
||||||
|
|
||||||
// Replace all < with < and all > with >
|
|
||||||
code = code.replace(/</g, "<").replace(/>/g, ">");
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
import { lex } from "./lexer";
|
import { lex } from "./lexer";
|
||||||
import {CodeJar as Codejar} from "codejar";
|
|
||||||
|
|
||||||
export function thp_highlighter(editor: any) {
|
|
||||||
let code: string = editor.textContent;
|
|
||||||
|
|
||||||
|
export function thp_highlighter(code: string) {
|
||||||
let tokens = lex(code);
|
let tokens = lex(code);
|
||||||
|
|
||||||
let highlighted_code = "";
|
let highlighted_code = "";
|
||||||
@ -12,7 +9,5 @@ export function thp_highlighter(editor: any) {
|
|||||||
highlighted_code += `<span class="token ${token.token_type}">${token.v}</span>`;
|
highlighted_code += `<span class="token ${token.token_type}">${token.v}</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.innerHTML = highlighted_code;
|
return highlighted_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CodeJar = Codejar;
|
|
||||||
|
@ -2,6 +2,28 @@
|
|||||||
import BaseLayout from "../layouts/BaseLayout.astro";
|
import BaseLayout from "../layouts/BaseLayout.astro";
|
||||||
import Navbar from "../components/Navbar.astro";
|
import Navbar from "../components/Navbar.astro";
|
||||||
import HeroSection from "../components/HeroSection.astro";
|
import HeroSection from "../components/HeroSection.astro";
|
||||||
|
import { thp_highlighter } from "../lexer/highlighter";
|
||||||
|
import { leftTrimDedent } from "../components/utils";
|
||||||
|
|
||||||
|
const thpcode = `union Animal {
|
||||||
|
Dog(String),
|
||||||
|
Cat(String, Int),
|
||||||
|
}
|
||||||
|
|
||||||
|
val cat_name = Post::get("cat_name") ?? "Michifu"
|
||||||
|
val my_cat = Animal::Cat(cat_name, 9)
|
||||||
|
|
||||||
|
try change_fur_color(cat) else die("Not a cat")
|
||||||
|
|
||||||
|
match random_animal()
|
||||||
|
case Dog(name)
|
||||||
|
{
|
||||||
|
print("{name} has 1 live ")
|
||||||
|
}
|
||||||
|
case Cat(name, lives)
|
||||||
|
{
|
||||||
|
print("{name} has {lives}")
|
||||||
|
}`;
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout>
|
<BaseLayout>
|
||||||
@ -95,7 +117,9 @@ import HeroSection from "../components/HeroSection.astro";
|
|||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<div class="h-1"></div>
|
<div class="h-1"></div>
|
||||||
<div id="editor" class="font-mono language-thp"></div>
|
<div id="editor" class="font-mono language-thp">
|
||||||
|
<pre set:html={thp_highlighter(leftTrimDedent(thpcode).join("\n"))}></pre>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -194,38 +218,4 @@ import HeroSection from "../components/HeroSection.astro";
|
|||||||
<br>
|
<br>
|
||||||
Nullable types must be explicitly checked before using them.
|
Nullable types must be explicitly checked before using them.
|
||||||
</HeroSection>
|
</HeroSection>
|
||||||
|
|
||||||
<script>
|
|
||||||
import { thp_highlighter, CodeJar } from "../lexer/highlighter";
|
|
||||||
|
|
||||||
let jar = CodeJar(document.getElementById("editor")!, thp_highlighter, {
|
|
||||||
tab: " ",
|
|
||||||
});
|
|
||||||
|
|
||||||
jar.updateCode(
|
|
||||||
`union Animal {
|
|
||||||
Dog(String),
|
|
||||||
Cat(String, Int),
|
|
||||||
}
|
|
||||||
|
|
||||||
val cat_name = Post::get("cat_name") ?? "Michifu"
|
|
||||||
val my_cat = Animal::Cat(cat_name, 9)
|
|
||||||
|
|
||||||
try change_fur_color(cat) else die("Not a cat")
|
|
||||||
|
|
||||||
match random_animal()
|
|
||||||
case Dog(name)
|
|
||||||
{
|
|
||||||
print("{name} has 1 live ")
|
|
||||||
}
|
|
||||||
case Cat(name, lives)
|
|
||||||
{
|
|
||||||
print("{name} has {lives}")
|
|
||||||
}`,
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
import { highlightOnDom } from "../layouts/thpHighlighter";
|
|
||||||
document.addEventListener("DOMContentLoaded", highlightOnDom);
|
|
||||||
</script>
|
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
@ -101,6 +101,3 @@ fun TransactionItem(Transaction t) {
|
|||||||
`} />
|
`} />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user