A .dockerignore => .dockerignore +10 -0
@@ 0,0 1,10 @@
+/build/
+/fxg/target/
+/kethel/_build/
+/kethel/deps/
+/.vscode/
+Dockerfile
+LICENSE
+TODO
+README.md
+/deploy.sh<
\ No newline at end of file
M .gitignore => .gitignore +2 -1
@@ 1,2 1,3 @@
/build
-/static/*.min.*>
\ No newline at end of file
+/static/*.min.*
+/deploy.sh<
\ No newline at end of file
D => +0 -13
@@ 1,13 0,0 @@
<footer>
<div id="metadata">
<p>Deployed from commit <code><span class="from-commit-short"></span></code>, on <span
class="build-date"></span>. built with lightningcss <span class="lightningcss"></span>,
html-minifier-next <span class="html-minifier-next"></span>, and uglifyjs <span
class="uglifyjs"></span> </p>
</div>
<div id="lynx">
<a href="https://github.com/m1kadev">
<img src="/static/github-mark-white.svg" width="32" height="32" alt="GitHub logo">
</a>
</div>
</footer>
\ No newline at end of file
D => +0 -10
@@ 1,10 0,0 @@
<footer>
<div id="metadata">
<p>Deployed from commit <code><span class="from-commit-short"></span></code>, on <span class="build-date"></span> </p>
</div>
<div id="lynx">
<a href="https://github.com/m1kadev">
<img src="/static/github-mark-white.svg" width="32" height="32" alt="GitHub logo">
</a>
</div>
</footer>
\ No newline at end of file
M bricks/navbar.thtml => bricks/navbar.thtml +14 -9
@@ 1,12 1,17 @@
-<div id="mark">
- <h3>.nl</h3>
- <h1>m1kadev</h1>
- <nav>
- <hr>
+<header>
+<div id="wordmark">
+ <span><i>www.</i><span>m1kadev.nl</span></span>
+</div>
+<nav>
+ <h3>on this site</h3>
+ <div class="link-group">
<a href="/">home</a>
<a href="/projects.html">projects</a>
- <a href="/thoughts/">thoughts</a>
- <hr>
+ <a href="/thoughts">thoughts</a>
<a href="/colophon.html">colophon</a>
- </nav>
-</div>
+ </div>
+ <!-- <h3>on this page</h3>
+ <div class="link-group">
+ </div> -->
+</nav>
+</header><
\ No newline at end of file
M fxg => fxg +1 -1
@@ 1,1 1,1 @@
-Subproject commit 61eb93988888de008c12e2fee91d079a91c69b7f
+Subproject commit b4bac3cd6faf1adaee7cd333e476c15090e4861b
M kethel/lib/bricks.ex => kethel/lib/bricks.ex +22 -2
@@ 12,7 12,27 @@ defmodule Bricks do
@spec collect(relative_path()) :: bricks()
def collect(folder) do
- Path.wildcard(folder <> "/bricks/*.thtml")
- |> Map.new(fn x -> {FileX.trimmed_filename(x), File.read!(x)} end)
+ from_files =
+ Path.wildcard(folder <> "/bricks/*.thtml")
+ |> Map.new(fn x -> {FileX.trimmed_filename(x), File.read!(x)} end)
+
+ {lcss_version, 0} = System.cmd("npx", ["lightningcss", "-V"])
+ {hmn_version, 0} = System.cmd("npx", ["html-minifier-next", "-V"])
+ {ujs_version, 0} = System.cmd("npx", ["uglifyjs", "-V"])
+ {git_commit, 0} = System.cmd("git", ["rev-parse", "HEAD"])
+
+ {build_date, 0} = System.cmd("date", ["+%H:%M %d/%m/%y"])
+ {e_build_date, 0} = System.cmd("date", ["+%H:%M:%S %d/%m/%y"])
+
+ footer = """
+ Built from commit <a href="https://codeberg.org/m1ka/www.m1kadev.nl/commit/#{git_commit}">#{git_commit |> binary_slice(0..7)}</a>, on #{build_date}
+ """
+
+ extended_footer = """
+ Built from commit <a href="https://codeberg.org/m1ka/www.m1kadev.nl/commit/#{git_commit}">#{git_commit |> String.trim()}</a>, using lightningcss #{lcss_version},
+ html-minifier-next version #{hmn_version}, uglifyjs version #{ujs_version}, on #{e_build_date}
+ """
+
+ Map.merge(%{footer: footer, extended_footer: extended_footer}, from_files)
end
end
M kethel/lib/pages.ex => kethel/lib/pages.ex +6 -2
@@ 29,10 29,12 @@ defmodule Pages do
@spec compile(%Pages{}) :: none()
def compile(pages) do
t_begin = System.monotonic_time(:millisecond)
+
Task.async_stream(pages.source_files, fn page -> compile_file(pages, page) end)
|> Enum.to_list()
+
t_end = System.monotonic_time(:millisecond)
- t_end - t_begin
+ t_end - t_begin
end
# doc "compiles a file, already read into process memory. Does not return the binary, but instantly writes it to disk"
@@ 49,8 51,10 @@ defmodule Pages do
{:error, err} -> raise err
end
+ location = page_path |> binary_slice(1..byte_size(page_data))
+
mustache_context =
- Map.merge(%{fxg_content: invoke_fxg(page_data), location: page_path}, pages.bricks)
+ Map.merge(%{fxg_content: invoke_fxg(page_data), location: location}, pages.bricks)
page_rendered = Mustache.render(template, mustache_context)
File.write!(output_path, page_rendered)
M kethel/lib/thoughts.ex => kethel/lib/thoughts.ex +32 -11
@@ 1,5 1,5 @@
defmodule Thoughts do
- defstruct [:thoughts, :template, :bricks, :project_root, :index_template, :inline_template ]
+ defstruct [:thoughts, :template, :bricks, :project_root, :index_template, :inline_template]
@spec urlify(binary()) :: binary()
defp urlify(name) do
@@ 20,7 20,7 @@ defmodule Thoughts do
thoughts:
Path.wildcard("#{project_root}/thoughts/*")
|> Enum.map(fn path -> {path, get_file_commit_date(path), File.read!(path)} end)
- |> Enum.sort_by(fn {_, date, _ } -> date end, :desc),
+ |> Enum.sort_by(fn {_, date, _} -> date end, :desc),
inline_template: File.read!("#{project_root}/templates/inline_thought.thtml"),
template: File.read!("#{project_root}/templates/thought.thtml"),
index_template: File.read!("#{project_root}/templates/thoughts.thtml"),
@@ 41,14 41,22 @@ defmodule Thoughts do
thoughts.thoughts
|> Task.async_stream(fn thought ->
- compile_file(thought, thoughts.template, thoughts.bricks, thoughts.project_root) end)
+ compile_file(thought, thoughts.template, thoughts.bricks, thoughts.project_root)
+ end)
|> Enum.to_list()
# generate index
- index_content = thoughts.thoughts
+ index_content =
+ thoughts.thoughts
|> Enum.map(fn thought -> inline_thought(thought, thoughts) end)
|> Enum.join()
- index = Mustache.render(thoughts.index_template, Map.merge(thoughts.bricks, %{fxg_content: index_content}))
+
+ index =
+ Mustache.render(
+ thoughts.index_template,
+ Map.merge(thoughts.bricks, %{fxg_content: index_content})
+ )
+
File.write!("#{thoughts.project_root}/build/thoughts/index.html", index)
IO.puts("[COMPILED] #{thoughts.project_root}/build/thoughts/index.html")
@@ 58,15 66,18 @@ defmodule Thoughts do
defp inline_thought({path, date, thought}, context) do
stripped_name = String.replace_prefix(path, "#{context.project_root}/thoughts/", "")
- location = "https://m1kadev.nl/thoughts/#{urlify(stripped_name)}.html"
+ location = "/thoughts/#{urlify(stripped_name)}.html"
title = "<a href=\"#{location}\">#{stripped_name}</a>"
- Mustache.render(context.inline_template, %{name: title, date: date, thought: thought})
+ pretty_date = date |> DateTime.from_unix!() |> Calendar.strftime("%A, %H:%M (%Y/%m/%d)")
+
+ Mustache.render(context.inline_template, %{name: title, date: pretty_date, thought: thought})
end
defp compile_file({path, date, thought}, template, bricks, project_root) do
name = trim_abs_path(path, project_root)
output_path = "#{project_root}/build/thoughts/#{urlify(name)}.html"
- mustache_context = Map.merge(bricks, %{thought: thought, name: name, date: date})
+ pretty_date = date |> DateTime.from_unix!() |> Calendar.strftime("%A, %H:%M (%Y/%M/%d)")
+ mustache_context = Map.merge(bricks, %{thought: thought, name: name, date: pretty_date})
File.write!(output_path, Mustache.render(template, mustache_context))
IO.puts("[COMPILED] #{path} -> #{output_path}")
@@ 74,16 85,26 @@ defmodule Thoughts do
def get_file_commit_date(path) do
{ts_string, 0} = System.cmd("git", ["log", "--format=%ct", path])
+
String.trim_trailing(ts_string)
- |> String.to_integer()
+ |> String.to_integer()
end
def to_rss({path, date, thought}, template, project_root) do
location = String.replace_prefix(path, project_root <> "/thoughts/", "")
link = "https://m1kadev.nl/thoughts/" <> urlify(location) <> ".html"
- rfc_date = date
+
+ rfc_date =
+ date
|> DateTime.from_unix!()
|> Calendar.strftime("%a, %d %b %Y %H:%M:%S %Z")
- Mustache.render(template, %{title: location, date: rfc_date, description: thought, category: "thoughts", link: link } )
+
+ Mustache.render(template, %{
+ title: location,
+ date: rfc_date,
+ description: thought,
+ category: "thoughts",
+ link: link
+ })
end
end
M kethel/main.exs => kethel/main.exs +0 -17
@@ 61,23 61,6 @@ if folder != nil do
IO.puts("[COMPILED] #{project_root}/build/rss.xml")
- {lcss_version, 0} = System.cmd("npx", ["lightningcss", "-V"])
- {hmn_version, 0} = System.cmd("npx", ["html-minifier-next", "-V"])
- {ujs_version, 0} = System.cmd("npx", ["uglifyjs", "-V"])
- {git_commit, 0} = System.cmd("git", ["rev-parse", "HEAD"])
-
- {build_date, 0} = System.cmd("date", ["+%H:%M %d/%m/%y"])
-
- info_txt = """
- commit=#{git_commit}
- lightningcss=#{lcss_version}
- html_minifier_next=#{hmn_version}
- uglifyjs=#{ujs_version}
- build_time=#{build_date}
- """
-
- File.write!("#{project_root}/build/info.txt", info_txt)
-
IO.puts("[COMPILED] #{project_root}/build/info.txt")
IO.puts("Finalising...")
M nginx.conf => nginx.conf +1 -1
@@ 19,7 19,7 @@ http {
listen 8080;
root /data/www;
index index.html;
- server_name localhost;
+ server_name www.m1kadev.nl;
client_max_body_size 32m;
error_page 500 502 503 503 /50x.html;
location = /50x.html {
D scripts/loadBuildData.js => scripts/loadBuildData.js +0 -17
@@ 1,17 0,0 @@
-const fromCommit = Array.from(document.getElementsByClassName("from-commit-short"));
-const buildDate = Array.from(document.getElementsByClassName("build-date"));
-const htmlMinifierNext = Array.from(document.getElementsByClassName("html-minifier-next"));
-const lightningcss = Array.from(document.getElementsByClassName("lightningcss"));
-const uglifyjs = Array.from(document.getElementsByClassName("uglifyjs"));
-
-fetch("/info.txt").then(async data => {
- const res = await data.text();
- let map = new Map();
- res.split("\n").map(x => x.split("=", 2)).map(([k, v]) => map[k] = v);
-
- fromCommit.forEach(e => e.innerHTML = map["commit"].substr(0, 8));
- buildDate.forEach(e => e.innerHTML = map["build_time"]);
- htmlMinifierNext.forEach(e => e.innerHTML = map["html_minifier_next"]);
- lightningcss.forEach(e => e.innerHTML = map["lightningcss"]);
- uglifyjs.forEach(e => e.innerHTML = map["uglifyjs"]);
-});
D scripts/showMotd.js => scripts/showMotd.js +0 -10
@@ 1,10 0,0 @@
-const motdElement = document.getElementById("motd").children[0];
-
-fetch("/static/motds").then(async rres => {
- const res = (await rres.text());
- const motds = res.split("\n").map(motd => motd.split("#", 2));
- let motd = motds[Math.floor(Math.random() * motds.length)];
- console.log(motd);
- motdElement.innerHTML = motd[0].trimEnd();
- motdElement.setAttribute("title", motd[1].trimStart());
-});>
\ No newline at end of file
M styles/base.css => styles/base.css +127 -72
@@ 1,110 1,165 @@
-@import url('https://fonts.googleapis.com/css2?family=Gothic+A1&family=Space+Grotesk:wght@300..700&display=swap');
-
:root {
- --bg-colour: #272640;
- --txt-colour: #fae9d3;
+ --serif-font: "Castilo MT", serif;
+ --sans-serif-font: "SF Pro", "Segoe UI", sans-serif;
+ color-scheme: light dark;
+ --fg-color: light-dark(#121413, #eeeeee);
+ --bg-color: light-dark(#eeeeee, #121413);
+ --accent-color: #ee41b4;
}
-body,
-html {
- background-color: var(--bg-colour);
- margin: 0px;
+body {
+ color: var(--fg-color);
+ background-color: var(--bg-color);
+ font-family: var(--serif-font);
+ width: max-content;
+ margin: 0;
}
-body {
- display: flex;
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-family: var(--sans-serif-font);
+ margin: 0;
+ border-bottom: .1rem solid var(--fg-color);
+ padding: .5rem;
+ font-weight: normal;
+ font-style: italic;
}
-h1 {
- margin: 0px;
+a {
+ color: var(--accent-color);
}
-#mark {
- font-family: "Space Grotesk", sans-serif;
- font-optical-sizing: auto;
- font-weight: 300;
- font-style: normal;
- display: inline-block;
- color: var(--txt-colour);
- margin-top: 1em;
- margin-left: 1em;
+a:visited {
+ color: var(--accent-color);
}
-#mark>h3 {
- margin: 0px;
- text-align: right;
- font-weight: 300;
+header {
+ width: 100vw;
}
-#mark>h1 {
- font-weight: 400;
+#wordmark {
+ border-bottom: .1rem solid var(--fg-color);
+ text-align: right;
+ padding: .5rem;
}
-#content {
- font-family: "Gothic A1", sans-serif;
- color: var(--txt-colour);
- width: 50vw;
+#wordmark>span {
+ width: min-content;
+ display: block;
margin-left: auto;
- margin-right: auto;
}
-main>h2 {
- font-weight: normal;
+#wordmark>span>i {
+ text-align: left;
+ display: block;
}
-main>p {
- font-weight: lighter;
+#wordmark>span>span {
+ text-align: left;
+ display: block;
+ font-family: var(--sans-serif-font);
+ font-size: 1.5rem;
}
-main {
- background-color: #00000080;
- width: 60vw;
- position: absolute;
- left: 20vw;
- top: 0px;
- padding: 2em;
+nav {
+ font-size: 1.2rem;
}
-footer {
- display: flex;
- justify-content: space-between;
+nav>h3 {
+ font-weight: normal;
+ font-size: 1.2rem;
}
-#lynx {
- justify-content: right;
+main {
+ width: 100vw;
}
-a {
- color: var(--txt-colour);
+p {
+ border-bottom: .1rem solid var(--fg-color);
+ padding-right: calc(-450px + 100%);
+ padding-bottom: .5rem;
+ padding-top: .5rem;
+ padding-left: .5rem;
+ margin: 0;
}
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- text-decoration: underline #ffffff80;
+.link-group {
+ border-bottom: .1rem solid var(--fg-color);
+ background-color: var(--fg-color);
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ align-items: end;
+ align-items: center;
+ justify-content: center;
+ gap: .1rem;
}
-#mark>h1,
-#mark>h3 {
- text-decoration: none;
+.link-group::after {
+ background-color: var(--bg-color);
}
-nav {
- font-family: "Gothic A1", sans-serif;
- font-size: large;
- color: var(--txt-colour);
- padding-top: 1em;
-}
-nav>a {
- display: block;
- text-align: right;
- position: relative;
+.link-group>a {
+ padding: .4rem .6rem;
+ display: inline;
+ background-color: var(--bg-color);
+ width: max-content;
+ text-align: center;
+ flex-grow: 1;
}
-nav>a {
- padding: .1em;
+footer {
+ padding: .5rem;
+ width: 450px;
+}
+
+@media (min-width: 900px) {
+
+ .link-group {
+ flex-direction: column;
+ padding: .5rem;
+ background-color: var(--bg-color);
+ align-items: end
+ }
+
+ .link-group>a {
+ padding: 0;
+ display: block;
+ width: max-content;
+ border-right: 0 solid transparent;
+ text-align: right;
+ }
+
+ body {
+ display: flex;
+ width: 100vw;
+ min-height: 100vh;
+ }
+
+ main {
+ border-left: .1rem solid var(--fg-color);
+ width: initial;
+ flex: 1;
+ }
+
+ header {
+ width: min-content;
+ }
+
+ nav>h3 {
+ min-width: max-content;
+ }
+
+ nav {
+ text-align: right;
+ }
+
+ nav>a {
+ text-align: right;
+ }
}=
\ No newline at end of file
D styles/index.css => styles/index.css +0 -14
@@ 1,14 0,0 @@
-#motd {
- color: var(--txt-colour);
- font-family: "Space Grotesk", sans-serif;
-}
-
-#motd>h2 {
- position: relative;
- float: right;
- writing-mode: vertical-rl;
- text-decoration: none;
- margin: 0;
- padding: .5em;
- height: 67vh;
-}>
\ No newline at end of file
D styles/thought.css => styles/thought.css +0 -15
@@ 1,15 0,0 @@
-h2 {
- margin: 0px;
- padding-bottom: .5em;
-}
-
-#thought {
- display: block;
- padding-left: 1.5em;
- font-style: italic;
-}
-
-small {
- text-align: right;
- display: block;
-}>
\ No newline at end of file
M styles/thoughts.css => styles/thoughts.css +2 -23
@@ 1,25 1,4 @@
-.thought {
+p>small {
display: block;
- /*background-color: #00000050;*/
- padding-left: 1em;
- padding-right: 1em;
-}
-
-.thought>h3 {
- padding-top: .2em;
-}
-
-.thought>span {
- display: block;
- padding-left: .5em;
- font-style: italic;
-}
-
-.thought>small {
text-align: right;
- display: block;
-}
-
-main hr:first-of-type {
- display: none;
-}
+}<
\ No newline at end of file
M templates/base.thtml => templates/base.thtml +5 -15
@@ 2,29 2,19 @@
<html lang="en-GB">
<head>
-
{{ &base_header }}
-
{{ &highlight }}
-
<title>{{ location }} - m1kadev</title>
-
{{ &ogp }}
-
</head>
<body>
-
{{ &navbar }}
-
- <div id="content">
- <main>
- {{ &fxg_content }}
- <hr>
+ <main>
+ {{ &fxg_content }}
+ <footer>
{{ &footer }}
- </main>
- </div>
-
+ </footer>
+ </main>
</body>
-
</html>=
\ No newline at end of file
M templates/inline_thought.thtml => templates/inline_thought.thtml +3 -4
@@ 1,8 1,7 @@
-<hr>
<div class="thought">
<h2> {{ &name }} </h2>
- <span>
+ <p>
{{ thought }}
- </span>
- <small>-mika, {{ date }}</small>
+ <small>-mika, {{ date }} </small>
+ </p>
</div>
M templates/pages/colophon.thtml => templates/pages/colophon.thtml +7 -16
@@ 2,28 2,19 @@
<html lang="en-GB">
<head>
-
{{ &base_header }}
-
- <title> {{ location }} - m1kadev.nl</title>
-
+ {{ &highlight }}
+ <title>{{ location }} - m1kadev</title>
{{ &ogp }}
-
-
</head>
<body>
-
{{ &navbar }}
-
- <div id="content">
- <main>
- {{ &fxg_content }}
- <hr>
+ <main>
+ {{ &fxg_content }}
+ <footer>
{{ &extended_footer }}
- </main>
- </div>
-
+ </footer>
+ </main>
</body>
-
</html>=
\ No newline at end of file
D templates/pages/index.thtml => templates/pages/index.thtml +0 -36
@@ 1,36 0,0 @@
-<!DOCTYPE html>
-<html lang="en-GB">
-
-<head>
-
- {{ &base_header }}
-
- {{ &highlight }}
-
- <script src="/static/rs.min.js"></script>
- <script src="/scripts/showMotd.js" defer></script>
- <link rel="stylesheet" href="/styles/index.css">
-
- <title>{{ location }} - m1kadev</title>
-
- {{ &ogp }}
-</head>
-
-<body>
-
- {{ &navbar }}
-
- <div id="content">
- <main>
- {{ &fxg_content }}
- <hr>
- {{ &footer }}
- </main>
- </div>
-
- <div id="motd">
- <h2></h2>
- </div>
-</body>
-
-</html>>
\ No newline at end of file
D templates/paste.thtml => templates/paste.thtml +0 -32
@@ 1,32 0,0 @@
-<!DOCTYPE html>
-<html lang="en-GB">
-
-<head>
- {{ &base_header }}
-
- {{ &language }}
- {{ &highlight }}
-
- <title>{{ filename }} - m1kadev</title>
-
- {{ &ogp }}
-
-</head>
-
-<body>
-
- {{ &navbar }}
-
- <div id="content">
- <main>
- <h1>{{ filename }}</h1>
- <p>{{ about_paste }}</p>
- <hr>
- {{ &codetag }}{{ code }}</code></pre>
- <hr>
- {{ &footer }}
- </main>
- </div>
-</body>
-
-</html>>
\ No newline at end of file
M templates/thought.thtml => templates/thought.thtml +11 -18
@@ 2,33 2,26 @@
<html lang="en-GB">
<head>
-
{{ &base_header }}
-
- <link rel="stylesheet" href="/styles/thought.css">
-
+ <link rel="stylesheet" href="/styles/thoughts.css">
<title> {{ name }} - m1kadev</title>
-
{{ &ogp }}
-
</head>
<body>
-
{{ &navbar }}
-
- <div id="content">
- <main>
- <h2> {{ name }} </h2>
- <span id="thought">
+ <main>
+ <div class="thought">
+ <h2> {{ &name }} </h2>
+ <p>
{{ thought }}
- </span>
- <small>-mika, {{ date }}</small>
- <hr>
+ <small>-mika, {{ date }} </small>
+ </p>
+ </div>
+ <footer>
{{ &footer }}
- </main>
- </div>
-
+ </footer>
+ </main>
</body>
</html>=
\ No newline at end of file
M templates/thoughts.thtml => templates/thoughts.thtml +8 -19
@@ 2,32 2,21 @@
<html lang="en-GB">
<head>
-
{{ &base_header }}
-
{{ &highlight }}
-
+ <title>thoughts - m1kadev</title>
<link rel="stylesheet" href="/styles/thoughts.css">
-
- <title> {{ location }} - m1kadev</title>
-
{{ &ogp }}
-
</head>
<body>
-
{{ &navbar }}
-
- <div id="content">
- <main>
- <h1>thoughts :3</h1>
- {{ &fxg_content }}
- <hr>
+ <main>
+ <h1>my thoughts :3</h1>
+ {{ &fxg_content }}
+ <footer>
{{ &footer }}
- </main>
- </div>
-
+ </footer>
+ </main>
</body>
-
-</html>>
\ No newline at end of file
+x</html><
\ No newline at end of file