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>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<style>
|
<link rel="stylesheet" href="/css.css">
|
||||||
@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>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body style="background-color: #222;">
|
<body style="background-color: #222;">
|
||||||
<div id="content">
|
<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: content1">
|
||||||
<div class="content" style="grid-area: content2">content</div>
|
<h2>Things I like</h2>
|
||||||
<div class="content" style="grid-area: content3">content</div>
|
<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: footer1"><marquee>Footer</marquee></div>
|
||||||
<div class="footer" style="grid-area: footer2; text-align: center"><a
|
<div class="footer" style="grid-area: footer2; text-align: center">
|
||||||
href="https://nixwebr.ing/next/<name>">← prev</a> <a href="https://nixwebr.ing">nixwebr.ing</a>
|
<!-- <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>
|
<!-- <a href="https://nixwebr.ing/prev/<name>">next →</a> -->
|
||||||
|
webbringGg
|
||||||
</div>
|
</div>
|
||||||
<div class="footer" style="grid-area: footer3; text-align: center;">
|
<div class="footer" style="grid-area: footer3; text-align: center;">
|
||||||
<a href="https://512kb.club"><img style="aspect-ratio: 234.383/30" height=30
|
<!-- <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"
|
<!-- alt="a proud member of the green team of 512KB club" -->
|
||||||
src="https://512kb.club/assets/images/green-team.svg"></a>
|
<!-- src="https://512kb.club/assets/images/green-team.svg"></a> -->
|
||||||
|
aspirant of 512kb.club
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="background"></div>
|
<div id="background"></div>
|
||||||
|
<script src="/main.js"></script>
|
||||||
<script>
|
<script>
|
||||||
(() => {
|
generate_background();
|
||||||
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;
|
|
||||||
})()
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</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::{
|
use std::{
|
||||||
env::current_dir,
|
env::current_dir,
|
||||||
|
ffi::OsStr,
|
||||||
io::{BufRead, BufReader, Write},
|
io::{BufRead, BufReader, Write},
|
||||||
net::{TcpListener, TcpStream},
|
net::{TcpListener, TcpStream},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
|
@ -38,7 +39,16 @@ impl Request {
|
||||||
"POST" => RequestMethod::POST,
|
"POST" => RequestMethod::POST,
|
||||||
_ => panic!("Unknown method"),
|
_ => 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> {
|
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) {
|
fn handle_connection(mut stream: TcpStream) {
|
||||||
let buf_reader = BufReader::new(&stream);
|
let buf_reader = BufReader::new(&stream);
|
||||||
let http_request: Vec<_> = buf_reader
|
let http_request: Vec<_> = buf_reader
|
||||||
|
@ -83,13 +109,24 @@ fn handle_connection(mut stream: TcpStream) {
|
||||||
|
|
||||||
println!("Requested file: {:#?}", req.file());
|
println!("Requested file: {:#?}", req.file());
|
||||||
|
|
||||||
|
let mut response_content = vec![];
|
||||||
|
|
||||||
let response = match req.file() {
|
let response = match req.file() {
|
||||||
Some(path) => match std::fs::read_to_string(path) {
|
Some(path) => match std::fs::read(&path) {
|
||||||
Ok(content) => format!("HTTP/1.1 200 OK{0}Content-Length: {1}{0}{0}{content}", CLRF, content.len()),
|
Ok(content) => {
|
||||||
Err(e) => format!("HTTP/1.1 500{0}{0}{e}", CLRF),
|
let len = &content.len();
|
||||||
}
|
response_content = content;
|
||||||
None => format!("HTTP/1.1 500{0}{0}", CLRF),
|
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.as_bytes()).unwrap();
|
||||||
|
stream.write_all(&response_content).unwrap();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue