fixed a typo or two
This commit is contained in:
parent
eff065466a
commit
d54c1f996c
100
public/css.css
Normal file
100
public/css.css
Normal file
|
@ -0,0 +1,100 @@
|
|||
@import url(https://fonts.bunny.net/css?family=chivo-mono:500);
|
||||
|
||||
:root {
|
||||
--background: #2e3440;
|
||||
--background-text: #3b4252;
|
||||
--border: #5e81ac;
|
||||
--border2: #b48ead;
|
||||
--text: #eceff4;
|
||||
--link: #88c0d0;
|
||||
--link-visited: #81a1c1;
|
||||
|
||||
--padding: 10px 20px;
|
||||
--margin: 4px;
|
||||
--gap: 10px;
|
||||
|
||||
--radius: 4px;
|
||||
}
|
||||
|
||||
code {
|
||||
background: var(--background-text);
|
||||
color: var(--text);
|
||||
padding: 2px 4px;
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
|
||||
html {
|
||||
color: var(--text);
|
||||
background-color: var(--background);
|
||||
font-family: 'Chivo Mono', monospace;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: initial !important;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link);
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: var(--link-visited);
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
min-width: 100vw;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
#content {
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"header1 header1 header1"
|
||||
"content1 content2 content2"
|
||||
"footer1 footer2 footer3"
|
||||
;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-gap: var(--gap);
|
||||
padding: var(--padding);
|
||||
}
|
||||
|
||||
#content>div {
|
||||
background: var(--background);
|
||||
border: 4px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
padding: var(--padding);
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
#content>div:nth-child(3n+1) {
|
||||
border: 4px solid var(--border2);
|
||||
}
|
||||
|
||||
#background {
|
||||
position: fixed;
|
||||
z-index: -3;
|
||||
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
||||
color: var(--background-text);
|
||||
opacity: 0.3;
|
||||
|
||||
aspect-ratio: 1/1;
|
||||
|
||||
transform-origin: top;
|
||||
transform: scale(150%) rotate(-20deg) translateY(-25%);
|
||||
|
||||
align-content: center;
|
||||
text-align: center;
|
||||
}
|
|
@ -2,131 +2,53 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<style>
|
||||
@import url(https://fonts.bunny.net/css?family=azeret-mono:500);
|
||||
|
||||
:root {
|
||||
--background: #2e3440;
|
||||
--background-text: #3b4252;
|
||||
--border: #5e81ac;
|
||||
--border2: #b48ead;
|
||||
--text: #eceff4;
|
||||
--link: #88c0d0;
|
||||
--link-visited: #81a1c1;
|
||||
|
||||
--padding: 10px 20px;
|
||||
--margin: 4px;
|
||||
--gap: 10px;
|
||||
|
||||
--radius: 4px;
|
||||
}
|
||||
|
||||
html {
|
||||
color: var(--text);
|
||||
background-color: var(--background);
|
||||
font-family: 'Azeret Mono', monospace;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: initial !important;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link);
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: var(--link-visited);
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
min-width: 100vw;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#content {
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"header1 header1 header1"
|
||||
"content1 content2 content3"
|
||||
"footer1 footer2 footer3"
|
||||
;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-gap: var(--gap);
|
||||
padding: var(--padding);
|
||||
}
|
||||
|
||||
#content>div {
|
||||
background: var(--background);
|
||||
border: 4px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
padding: var(--padding);
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
#content>div:nth-child(2n) {
|
||||
border: 4px solid var(--border2);
|
||||
}
|
||||
|
||||
#background {
|
||||
position: fixed;
|
||||
z-index: -3;
|
||||
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
||||
color: var(--background-text);
|
||||
opacity: 0.3;
|
||||
|
||||
aspect-ratio: 1/1;
|
||||
|
||||
transform-origin: top;
|
||||
transform: scale(150%) rotate(-20deg) translateY(-25%);
|
||||
|
||||
align-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/css.css">
|
||||
</head>
|
||||
|
||||
<body style="background-color: #222;">
|
||||
<div id="content">
|
||||
<div class="header" style="grid-area: header1">something something snorre.net</div>
|
||||
<div class="header" style="grid-area: header1; text-align: center">
|
||||
<h1>SpoodyThe<span style="color:var(--background-text)">.</span>One</h1>
|
||||
</div>
|
||||
|
||||
<div class="content" style="grid-area: content1">content</div>
|
||||
<div class="content" style="grid-area: content2">content</div>
|
||||
<div class="content" style="grid-area: content3">content</div>
|
||||
<div class="content" style="grid-area: content1">
|
||||
<h2>Things I like</h2>
|
||||
<ul>
|
||||
<li><a href="https://myanimelist.net/animelist/unplowed">Anime</a></li>
|
||||
<li>Programming</li>
|
||||
<li>Gaming</li>
|
||||
<li>Vim motions</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="content" style="grid-area: content2">
|
||||
<h2>Projects I've finished</h2>
|
||||
<ul>
|
||||
<li><a href="/posts?post=openbirch">Openbirch</a><br>(made it to an alpha release)</li>
|
||||
<li><a href="/posts?post=minecraft-proxy">Minecraft server
|
||||
hibernator</a></li>
|
||||
<li><a href="https://gitlab.com/SpoodyTheOne/the-wheel">Wheel of names drinking game</a><br>(scraping the bottom
|
||||
of the barrel for finished projects)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- <div class="content" style="grid-area: content3">content</div> -->
|
||||
|
||||
<div class="footer" style="grid-area: footer1">cool fucking footer</div>
|
||||
<div class="footer" style="grid-area: footer2; text-align: center"><a
|
||||
href="https://nixwebr.ing/next/<name>">← prev</a> <a href="https://nixwebr.ing">nixwebr.ing</a>
|
||||
<a href="https://nixwebr.ing/prev/<name>">next →</a>
|
||||
<div class="footer" style="grid-area: footer1"><marquee>Footer</marquee></div>
|
||||
<div class="footer" style="grid-area: footer2; text-align: center">
|
||||
<!-- <a href="https://nixwebr.ing/next/<name>">← prev</a> <a href="https://nixwebr.ing">nixwebr.ing</a> -->
|
||||
<!-- <a href="https://nixwebr.ing/prev/<name>">next →</a> -->
|
||||
webbringGg
|
||||
</div>
|
||||
<div class="footer" style="grid-area: footer3; text-align: center;">
|
||||
<a href="https://512kb.club"><img style="aspect-ratio: 234.383/30" height=30
|
||||
alt="a proud member of the green team of 512KB club"
|
||||
src="https://512kb.club/assets/images/green-team.svg"></a>
|
||||
<!-- <a href="https://512kb.club"><img style="aspect-ratio: 234.383/30" height=30 -->
|
||||
<!-- alt="a proud member of the green team of 512KB club" -->
|
||||
<!-- src="https://512kb.club/assets/images/green-team.svg"></a> -->
|
||||
aspirant of 512kb.club
|
||||
</div>
|
||||
</div>
|
||||
<div id="background"></div>
|
||||
<script src="/main.js"></script>
|
||||
<script>
|
||||
(() => {
|
||||
let str = "";
|
||||
let terms = "${i} :3 Nix Linux Test Portchain Programming Rust C++ Openbirch Godot".split(" ");
|
||||
for (let i = 0; i < 5000; i++) {
|
||||
let idx = Math.floor(Math.random() * terms.length);
|
||||
str += terms[idx] + " ";
|
||||
}
|
||||
document.getElementById("background").innerText = str;
|
||||
})()
|
||||
generate_background();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
|
15
public/main.js
Normal file
15
public/main.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
const generate_background = ((terms) => {
|
||||
let str = "";
|
||||
terms = terms == null ? "${i} :3 Nix Linux Test Portchain Programming Rust C++ Openbirch Godot".split(" ") : terms;
|
||||
for (let i = 0; i < 5000; i++) {
|
||||
let idx = Math.floor(Math.random() * terms.length);
|
||||
str += terms[idx] + " ";
|
||||
}
|
||||
|
||||
|
||||
let idx = Math.floor(Math.random() * terms.length);
|
||||
document.getElementById("background").innerText = str;
|
||||
try {
|
||||
document.querySelector(".footer>marquee").innerText = terms[idx] + " Footer";
|
||||
} catch (e) {}
|
||||
})
|
228
public/md2html.js
Normal file
228
public/md2html.js
Normal file
|
@ -0,0 +1,228 @@
|
|||
const md2tokens = (markdown, newline) => {
|
||||
// Simple lexer and parser
|
||||
let i = 0;
|
||||
let current_string = "";
|
||||
newline = newline == null ? true : newline;
|
||||
let newline_count = newline ? 1 : 0;
|
||||
|
||||
let tokens = [];
|
||||
|
||||
let match = (c) => {
|
||||
if (c == markdown[i]) {
|
||||
i++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
let advance = () => {
|
||||
i++;
|
||||
if (i < markdown.length)
|
||||
return true
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
let capture_until = (c) => {
|
||||
let capture = "";
|
||||
while (markdown[i] != c && markdown.length > i) {
|
||||
capture += markdown[i];
|
||||
i++;
|
||||
}
|
||||
return capture;
|
||||
}
|
||||
|
||||
let finish = (type) => {
|
||||
if (current_string.trim().length == 0) {
|
||||
current_string = "";
|
||||
return;
|
||||
}
|
||||
|
||||
tokens.push({ type: type == null ? "span" : type, content: current_string })
|
||||
current_string = "";
|
||||
}
|
||||
|
||||
let def = () => {
|
||||
current_string += markdown[i];
|
||||
newline = false;
|
||||
newline_count = 0;
|
||||
}
|
||||
|
||||
while (i < markdown.length) {
|
||||
switch (markdown[i]) {
|
||||
case '\\':
|
||||
i++;
|
||||
current_string += markdown[i];
|
||||
break;
|
||||
|
||||
case '*':
|
||||
finish();
|
||||
advance();
|
||||
let depth_em = 1;
|
||||
let type = "em";
|
||||
if (match("*")) {
|
||||
type = "bold";
|
||||
depth_em = 2;
|
||||
}
|
||||
|
||||
let found_match = () => {
|
||||
for (let j = 0; j < depth_em; j++) {
|
||||
if (markdown[i + j] != "*")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
while (!found_match()) {
|
||||
current_string += markdown[i];
|
||||
if (!advance())
|
||||
break;
|
||||
}
|
||||
|
||||
advance();
|
||||
|
||||
finish(type);
|
||||
break;
|
||||
|
||||
case "#":
|
||||
if (!newline) {
|
||||
def();
|
||||
break;
|
||||
}
|
||||
|
||||
finish();
|
||||
let depth_he = 0;
|
||||
do {
|
||||
depth_he++;
|
||||
|
||||
} while (match("#"));
|
||||
|
||||
while (markdown[i] != "\n" && markdown.length > i) {
|
||||
current_string += markdown[i];
|
||||
i++
|
||||
}
|
||||
|
||||
tokens.push({ type: "header", level: depth_he, content: current_string });
|
||||
current_string = "";
|
||||
break;
|
||||
|
||||
case '!':
|
||||
if (markdown[i + 1] != "[") {
|
||||
def();
|
||||
break;
|
||||
}
|
||||
|
||||
finish();
|
||||
advance();
|
||||
advance();
|
||||
let alt_text = capture_until("]");
|
||||
advance();
|
||||
if (!match("(")) {
|
||||
current_string = `![${alt_text}]`;
|
||||
def();
|
||||
break;
|
||||
}
|
||||
|
||||
let url = capture_until("\"");
|
||||
advance();
|
||||
let title = capture_until("\"");
|
||||
advance();
|
||||
if (!match(")")) {
|
||||
current_string = `;
|
||||
break;
|
||||
}
|
||||
|
||||
tokens.push({type:"image", alt: alt_text, url: url, title: title})
|
||||
break;
|
||||
|
||||
case '-':
|
||||
if (!newline) {
|
||||
def();
|
||||
break;
|
||||
}
|
||||
|
||||
let items = [];
|
||||
|
||||
advance();
|
||||
|
||||
do {
|
||||
let text = capture_until("\n");
|
||||
advance();
|
||||
items.push(md2tokens(text, false));
|
||||
} while (match("-"));
|
||||
|
||||
tokens.push({type:"ul", items: items});
|
||||
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
if (newline_count > 2)
|
||||
break;
|
||||
|
||||
newline = true;
|
||||
newline_count++;
|
||||
finish();
|
||||
tokens.push({ type: "newline" })
|
||||
break;
|
||||
|
||||
case '`':
|
||||
finish();
|
||||
advance();
|
||||
current_string = capture_until("`");
|
||||
finish("inlinecode");
|
||||
break;
|
||||
|
||||
default:
|
||||
def()
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
finish();
|
||||
|
||||
console.log(tokens);
|
||||
|
||||
return tokens;
|
||||
};
|
||||
|
||||
const tokens2html = (tokens) => {
|
||||
let output = "";
|
||||
|
||||
for (let token of tokens) {
|
||||
switch (token.type) {
|
||||
case "span":
|
||||
output += `<span>${token.content}</span>`;
|
||||
break
|
||||
case "bold":
|
||||
output += `<b>${token.content}</b>`
|
||||
break;
|
||||
case "em":
|
||||
output += `<i>${token.content}</i>`
|
||||
break;
|
||||
case "header":
|
||||
output += `<h${token.level}>${token.content}</h${token.level}>`
|
||||
break;
|
||||
case "newline":
|
||||
output += "<br>"
|
||||
break;
|
||||
case "image":
|
||||
output += `<p style="text-align:center"><img src="${token.url}" alt="${token.alt}"></p>`;
|
||||
break
|
||||
case "ul":
|
||||
console.log(token);
|
||||
output += "<ul>";
|
||||
for (let item of token.items) {
|
||||
output += `<li>${tokens2html(item)}</li>`
|
||||
}
|
||||
output += "</ul>";
|
||||
break;
|
||||
case "inlinecode":
|
||||
output += `<code>${token.content}</code>`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
66
public/posts/index.html
Normal file
66
public/posts/index.html
Normal file
|
@ -0,0 +1,66 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="./css.css">
|
||||
<style>
|
||||
#content {
|
||||
grid-template-areas:
|
||||
"header header2"
|
||||
"content content"
|
||||
"footer2 footer"
|
||||
;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
img {
|
||||
background-color: var(--background-text);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body style="background-color: #222;">
|
||||
<div id="content">
|
||||
<div class="header" style="grid-area: header; text-align: center">
|
||||
<a href="/" style="color: inherit; text-decoration: inherit"><h1>SpoodyThe<span style="color:var(--background-text)">.</span>One</h1></a>
|
||||
</div>
|
||||
<div class="content" style="grid-area: content; text-align: left">
|
||||
</div>
|
||||
<div class="footer" style="grid-area: footer; text-align: center">
|
||||
<h4><a href="#">Back to the top</a></h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="background"></div>
|
||||
<script src="/main.js"></script>
|
||||
<script src="/md2html.js"></script>
|
||||
<script>
|
||||
(async () => {
|
||||
// let terms = "Functions Vectors Evaluate Isolate Solve Matrix Tensor Calculus Derivation Limit Procedures Scopes Statements Interpreter Parser Lexer".split(" ");
|
||||
// generate_background(terms);
|
||||
// document.querySelector(".header").innerHTML = md2html({{}});
|
||||
try {
|
||||
let post = new URLSearchParams(window.location.search).get("post");
|
||||
let response = await fetch(`/posts/${post}.md`);
|
||||
let content = await response.text();
|
||||
|
||||
if (response.status != 200) {
|
||||
content = `Error Exception Null\n#Unknown post '${post}'`
|
||||
}
|
||||
|
||||
let lines = content.split("\n");
|
||||
let terms = lines.shift();
|
||||
content = lines.join("\n");
|
||||
|
||||
generate_background(terms.split(" "));
|
||||
|
||||
document.getElementsByClassName("content")[0].innerHTML = tokens2html(md2tokens(content));
|
||||
} catch (e) {
|
||||
document.getElementsByClassName("content")[0].innerText = e;
|
||||
throw e;
|
||||
}
|
||||
})()
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
13
public/posts/openbirch.md
Normal file
13
public/posts/openbirch.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
Functions Vectors Evaluate Isolate Solve Matrix Tensor Calculus Derivation Limit Procedures Scopes Statements Interpreter Parser Lexer
|
||||
# Openbirch
|
||||
Openbirch is a programming language that I made together with my friend from school.
|
||||
It was an attempt at making a CAS tool to use instead of Maple (the UX is terrible).
|
||||
|
||||
The biggest challenge besides creating a programming language was creating a programming language
|
||||
where any variable could be undefined at runtime, but still used to define other variables.
|
||||
|
||||
An example of this would be `x := 2*y`. Here `y` is not defined, but it is still used to define `x`.
|
||||
|
||||
This was a unique challenge that was solved by representing everything as a *tree*
|
||||
|
||||

|
BIN
public/test.png
Normal file
BIN
public/test.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 275 KiB |
49
src/main.rs
49
src/main.rs
|
@ -1,5 +1,6 @@
|
|||
use std::{
|
||||
env::current_dir,
|
||||
ffi::OsStr,
|
||||
io::{BufRead, BufReader, Write},
|
||||
net::{TcpListener, TcpStream},
|
||||
path::PathBuf,
|
||||
|
@ -38,7 +39,16 @@ impl Request {
|
|||
"POST" => RequestMethod::POST,
|
||||
_ => panic!("Unknown method"),
|
||||
},
|
||||
path: Some(parts.next().expect("Invalid request").to_string()),
|
||||
path: Some(
|
||||
parts
|
||||
.next()
|
||||
.expect("Invalid request")
|
||||
.to_string()
|
||||
.split("?")
|
||||
.next()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
),
|
||||
}
|
||||
}
|
||||
pub fn file(&self) -> Option<PathBuf> {
|
||||
|
@ -65,6 +75,22 @@ impl Request {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_mime_type<'a>(extension: Option<&'a OsStr>) -> String {
|
||||
if extension.is_none() {
|
||||
return "text/text".to_string();
|
||||
}
|
||||
|
||||
let s = extension.unwrap().to_str();
|
||||
match s {
|
||||
Some("js") => "text/javascript".to_string(),
|
||||
Some("md") => "text/markdown".to_string(),
|
||||
Some("css") => "text/css".to_string(),
|
||||
Some("html") => "text/html".to_string(),
|
||||
Some("png") => "image/png".to_string(),
|
||||
_ => "text/text".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_connection(mut stream: TcpStream) {
|
||||
let buf_reader = BufReader::new(&stream);
|
||||
let http_request: Vec<_> = buf_reader
|
||||
|
@ -83,13 +109,24 @@ fn handle_connection(mut stream: TcpStream) {
|
|||
|
||||
println!("Requested file: {:#?}", req.file());
|
||||
|
||||
let mut response_content = vec![];
|
||||
|
||||
let response = match req.file() {
|
||||
Some(path) => match std::fs::read_to_string(path) {
|
||||
Ok(content) => format!("HTTP/1.1 200 OK{0}Content-Length: {1}{0}{0}{content}", CLRF, content.len()),
|
||||
Err(e) => format!("HTTP/1.1 500{0}{0}{e}", CLRF),
|
||||
}
|
||||
None => format!("HTTP/1.1 500{0}{0}", CLRF),
|
||||
Some(path) => match std::fs::read(&path) {
|
||||
Ok(content) => {
|
||||
let len = &content.len();
|
||||
response_content = content;
|
||||
format!(
|
||||
"HTTP/1.1 200 OK{0}Content-Type: {2}{0}Content-Length: {1}{0}{0}",
|
||||
CLRF,
|
||||
len,
|
||||
get_mime_type(path.extension())
|
||||
)},
|
||||
Err(e) => format!("HTTP/1.1 404{0}{0}{e}", CLRF),
|
||||
},
|
||||
None => format!("HTTP/1.1 404{0}{0}", CLRF),
|
||||
};
|
||||
|
||||
stream.write_all(response.as_bytes()).unwrap();
|
||||
stream.write_all(&response_content).unwrap();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue