~mika/www.m1kadev.nl

20252f200b736548f407cd78a972a47ab7c9479d — m1ka 3 months ago 6c5467b
Import new stylesheets, should work in docker prod environmeny
24 files changed, 251 insertions(+), 358 deletions(-)

A .dockerignore
M .gitignore
D bricks/extended-footer.thtml
D bricks/footer.thtml
M bricks/navbar.thtml
M fxg
M kethel/lib/bricks.ex
M kethel/lib/pages.ex
M kethel/lib/thoughts.ex
M kethel/main.exs
M nginx.conf
D scripts/loadBuildData.js
D scripts/showMotd.js
M styles/base.css
D styles/index.css
D styles/thought.css
M styles/thoughts.css
M templates/base.thtml
M templates/inline_thought.thtml
M templates/pages/colophon.thtml
D templates/pages/index.thtml
D templates/paste.thtml
M templates/thought.thtml
M templates/thoughts.thtml
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 bricks/extended-footer.thtml => bricks/extended-footer.thtml +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 bricks/footer.thtml => bricks/footer.thtml +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