D build.exs => build.exs +0 -371
@@ 1,371 0,0 @@
-require Mix
-require EEx
-
-Mix.install([
- {:tzdata, "~> 1.1"},
- {:mustache, "~> 0.5.0"}
-])
-
-Calendar.put_time_zone_database(Tzdata.TimeZoneDatabase)
-
-defmodule Git do
- def get_file_commit(path) do
- {ts_string, 0} = System.cmd("git", ["log", "--format=%ct", path])
- String.to_integer(String.trim_trailing(ts_string))
- end
-end
-
-defmodule Templates do
- binfo_template = """
- commit=<%= commit %>lightningcss=<%= lightningcss %>html_minifier_next=<%= html_minifier_next %>uglifyjs=<%= uglifyjs %>build_time=<%= build_time %>
- """
-
- pastelink_template = """
- <a href="/<%= location %>.html"><%= name %></a> | <%= date %>
- """
-
- EEx.function_from_string(
- :def,
- :build_info,
- binfo_template,
- [
- :commit,
- :lightningcss,
- :html_minifier_next,
- :uglifyjs,
- :build_time
- ]
- )
-
- EEx.function_from_string(
- :def,
- :pastelink,
- pastelink_template,
- [
- :location,
- :name,
- :date
- ]
- )
-
- def ogp(title, url, description) do
- """
- <meta property="og:type" content="website">
- <meta property="og:title" content="#{title}">
- <meta property="og:url" content="#{url}">
- <meta property="og:image" content="https://m1kadev.nl/static/logo.png">
- <meta property="og:description" content="#{description}">
- <meta property="og:locale" content="en_GB" />
- <meta property="og:site_name" content="m1kadev.nl" />
- """
- end
-end
-
-defmodule Builders do
- def html(input_path) do
- output_path = String.replace_prefix(input_path, "src", "build")
-
- {_, 0} =
- System.cmd("html-minifier-next", [
- "--preset",
- "conservative",
- "-o",
- output_path,
- input_path
- ])
- end
-
- def css(input_path) do
- output_path = "build/" <> input_path
-
- {_, 0} =
- System.cmd("lightningcss", [
- "-m",
- "-o",
- output_path,
- input_path
- ])
- end
-
- def js(input_path) do
- output_path = "build/" <> input_path
-
- {_, 0} =
- System.cmd("uglifyjs", [
- "-c",
- "-o",
- output_path,
- input_path
- ])
- end
-
- def fxg(input_path, template, bricks) do
- own_template =
- input_path
- |> String.replace_prefix("pages", "templates/pages")
- |> String.replace_suffix("fxg", "html")
-
- case File.read(own_template) do
- {:ok, ctemplate} -> _fxg(input_path, ctemplate, bricks)
- _ -> _fxg(input_path, template, bricks)
- end
- end
-
- def paste(input_path, template, bricks) do
- {:ok, code} = File.read(input_path)
- IO.inspect(code)
-
- output = "build/" <> input_path <> ".html"
-
- lang = Path.extname(input_path) |> String.slice(1..-1//1)
- file = Path.basename(input_path)
- time = FileX.createdf(input_path)
-
- result =
- Mustache.render(
- template,
- Map.merge(
- %{
- filename: file,
- about_paste: "Created on " <> time,
- language: "<script src=\"static/" <> lang <> ".min.js\"></script>",
- codetag: "<pre><code class=\"language-" <> lang <> "\">",
- code: code,
- ogp:
- Templates.ogp(file, "https://m1kadev.nl/pastes/#{file}.html", "Created on " <> time)
- },
- bricks
- )
- )
-
- IO.inspect(input_path)
-
- :ok = File.write(output, result)
- end
-
- defp _fxg(input_path, template, bricks) do
- output_path =
- String.replace_prefix(input_path, "pages", "build")
- |> String.replace_suffix("fxg", "html")
-
- name =
- case Path.basename(input_path) |> Path.rootname() do
- "index" -> "home"
- x -> x
- end
-
- {content, 0} = System.cmd("fxg", [input_path])
-
- ogp =
- Templates.ogp(
- name,
- "https://m1kadev.nl/#{String.replace_prefix(output_path, "build/", "")}",
- ""
- )
-
- output =
- Mustache.render(
- template,
- Map.merge(
- %{
- fxg_content: content,
- location: name,
- ogp: ogp
- },
- bricks
- )
- )
-
- IO.inspect(output_path)
- :ok = File.write(output_path, output)
- end
-
- def thought(path, unix) do
- thought = File.read!(path)
- name = String.replace_prefix(path, "thoughts/", "")
-
- date = DateTime.from_unix!(unix) |> Calendar.strftime("%d/%m/%y (%H:%M)")
-
- """
- <div class="thought">
- <h3><a href="/thoughts/#{FileX.sanitised_name(name)}.html">#{name}</a></h3>
- <span>#{thought}</span>
- <small> -mika, #{date}</small>
- </div>
- """
- end
-end
-
-defmodule FileX do
- def createdf(path) do
- {:ok, %File.Stat{mtime: {{y, m, d}, _}}} = File.stat(path, time: :local)
- "#{d}/#{m}/#{y}"
- end
-
- def created(path) do
- {:ok, %File.Stat{mtime: x}} = File.stat(path, time: :posix)
- x
- end
-
- def sanitised_name(path) do
- Path.basename(path)
- |> String.trim_trailing(".html")
- |> String.replace("-", "_")
- |> String.replace(" ", "_")
- end
-end
-
-{commit, 0} = System.cmd("git", ["rev-parse", "HEAD"])
-
-{lightningcss, 0} = System.cmd("lightningcss", ["-V"])
-
-{html_minifier_next, 0} = System.cmd("html-minifier-next", ["-V"])
-
-{uglifyjs, 0} = System.cmd("uglifyjs", ["-V"])
-
-File.rm_rf("build")
-
-File.mkdir_p!("build")
-
-bricks =
- Path.wildcard("bricks/*.html")
- |> Map.new(fn x -> {FileX.sanitised_name(x), File.read!(x)} end)
-
-{:ok, main_template} = File.read("templates/base.html")
-
-Path.wildcard("pages/**/*.fxg")
-|> Task.async_stream(fn file -> Builders.fxg(file, main_template, bricks) end)
-|> Enum.to_list()
-
-File.mkdir_p!("build/static")
-
-Path.wildcard("static/**/*")
-|> Task.async_stream(fn file -> File.cp(file, "build/" <> file) end)
-|> Enum.to_list()
-
-File.mkdir_p!("build/scripts")
-
-Path.wildcard("scripts/**/*.js")
-|> Task.async_stream(fn file -> Builders.js(file) end)
-|> Enum.to_list()
-
-File.mkdir_p!("build/styles")
-
-Path.wildcard("styles/**/*.css")
-|> Task.async_stream(fn file -> Builders.css(file) end)
-|> Enum.to_list()
-
-File.mkdir_p("build/pastes")
-
-{:ok, paste_template} = File.read("templates/paste.html")
-
-pastes =
- Path.wildcard("pastes/**/*")
- |> Enum.map(fn path -> {path, Git.get_file_commit(path)} end)
- |> Enum.sort_by(fn {_, t} -> t end, :desc)
- |> Enum.map(fn {path, _} -> path end)
-
-pastes
-|> Task.async_stream(fn file -> Builders.paste(file, paste_template, bricks) end)
-|> Enum.to_list()
-
-paste_data =
- Map.new(pastes, fn x -> {x, FileX.createdf(x)} end)
- |> Enum.map(fn {x, y} -> Templates.pastelink(x, x, y) end)
- |> Enum.join("<br>")
-
-pastes_header = """
-<h1>my pastes</h1>
-<p>random code snippets i found useful or wanted to save :))</p>
-<hr>
-"""
-
-# main_template
-# |> String.replace("<content />", pastes_header <> "<p>" <> paste_data <> "</p>")
-paste_index =
- Mustache.render(
- main_template,
- Map.merge(bricks, %{
- fxg_content: pastes_header <> "<p>" <> paste_data <> "</p>",
- location: "pastes",
- ogp:
- Templates.ogp(
- "thoughts",
- "https://m1kadev.nl/pastes",
- "random code snippets i found useful or wanted to save :))"
- )
- })
- )
-
-File.write("build/pastes/index.html", paste_index)
-
-File.mkdir_p("build/thoughts")
-
-thoughts_template = File.read!("templates/thoughts.html")
-thought_template = File.read!("templates/thought.html")
-
-thought_paths =
- Path.wildcard("thoughts/**/*")
- |> Enum.map(fn path -> {path, Git.get_file_commit(path)} end)
- |> Enum.sort_by(fn {_, t} -> t end, :desc)
-
-thoughts = Enum.map(thought_paths, fn {path, date} -> Builders.thought(path, date) end)
-
-thoughts_html =
- Mustache.render(
- thoughts_template,
- Map.merge(bricks, %{
- fxg_content: Enum.join(thoughts, "<hr>"),
- location: "thoughts",
- ogp:
- Templates.ogp(
- "thoughts",
- "https://m1kadev.nl/thoughts",
- "important thoughts that needed publishing"
- )
- })
- )
-
-for {thought, {path, time}} <- Enum.zip(thoughts, thought_paths) do
- thought = FileX.sanitised_name(path)
- output_path = "build/thoughts/" <> thought <> ".html"
-
- when_said = DateTime.from_unix!(time) |> Calendar.strftime("%H:%M, %d/%m/%y")
- thought_txt = File.read!(path)
-
- thought_html =
- Mustache.render(
- thought_template,
- Map.merge(bricks, %{
- fxg_content: thought_txt,
- thought: thought,
- date: when_said,
- ogp:
- Templates.ogp(
- thought,
- "https://m1kadev.nl/#{String.replace_prefix(output_path, "build/", "")}",
- String.replace(thought_txt, "\"", """)
- )
- })
- )
-
- File.write(output_path, thought_html)
-end
-
-File.write("build/thoughts/index.html", thoughts_html)
-
-File.copy("favicon.ico", "build/favicon.ico")
-
-{:ok, date} = DateTime.now("Europe/Amsterdam")
-build_time = Calendar.strftime(date, "%H:%M:%S %d/%m/%y")
-
-File.write(
- "build/info.txt",
- Templates.build_info(
- commit,
- lightningcss |> String.split_at(13) |> elem(1),
- html_minifier_next,
- uglifyjs |> String.split_at(10) |> elem(1),
- build_time
- )
-)
A kethel/.formatter.exs => kethel/.formatter.exs +4 -0
@@ 0,0 1,4 @@
+# Used by "mix format"
+[
+ inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
+]
A kethel/.gitignore => kethel/.gitignore +23 -0
@@ 0,0 1,23 @@
+# The directory Mix will write compiled artifacts to.
+/_build/
+
+# If you run "mix test --cover", coverage assets end up here.
+/cover/
+
+# The directory Mix downloads your dependencies sources to.
+/deps/
+
+# Where third-party dependencies like ExDoc output generated docs.
+/doc/
+
+# If the VM crashes, it generates a dump, let's ignore it too.
+erl_crash.dump
+
+# Also ignore archive artifacts (built via "mix archive.build").
+*.ez
+
+# Ignore package tarball (built via "mix hex.build").
+kethel-*.tar
+
+# Temporary files, for example, from tests.
+/tmp/
A kethel/lib/bricks.ex => kethel/lib/bricks.ex +17 -0
@@ 0,0 1,17 @@
+defmodule Bricks do
+ @typedoc "A path, relative to mix.exs"
+ @type relative_path() :: String.t()
+
+ @typedoc "The name of the brick"
+ @type brick_name() :: String.t()
+
+ @typedoc "A valid mustache template"
+ @type mustache() :: String.t()
+
+ @spec collect(relative_path()) :: %{brick_name() => mustache()}
+ def collect(folder) do
+ Path.wildcard(folder <> "/bricks/*.thtml")
+ |> Enum.map(fn brick -> { brick, File.read!(brick) } end)
+ |> Enum.map(fn { brick, contents } -> { Path.basename(brick) |> Path.rootname(), contents } end) # "../bricks/base_header.html" would beccome just "base_header"
+ end
+ end
A kethel/main.exs => kethel/main.exs +11 -0
@@ 0,0 1,11 @@
+args = System.argv()
+
+folder = Enum.at(args, 1)
+
+if folder != nil do
+ IO.inspect(folder)
+ bricks = Bricks.collect(folder)
+ IO.inspect(bricks)
+else
+ IO.puts(:stderr, "The root project folder should be provided on the command line")
+end
A kethel/mix.exs => kethel/mix.exs +20 -0
@@ 0,0 1,20 @@
+defmodule Kethel.MixProject do
+ use Mix.Project
+
+ def project do
+ [
+ app: :kethel,
+ version: "0.1.0",
+ elixir: "~> 1.18",
+ start_permanent: Mix.env() == :prod,
+ deps: deps()
+ ]
+ end
+
+ defp deps do
+ [
+ { :tzdata, "~> 1.1" },
+ { :mustache, "~> 0.5.0" }
+ ]
+ end
+end
A kethel/mix.lock => kethel/mix.lock +12 -0
@@ 0,0 1,12 @@
+%{
+ "certifi": {:hex, :certifi, "2.15.0", "0e6e882fcdaaa0a5a9f2b3db55b1394dba07e8d6d9bcad08318fb604c6839712", [:rebar3], [], "hexpm", "b147ed22ce71d72eafdad94f055165c1c182f61a2ff49df28bcc71d1d5b94a60"},
+ "hackney": {:hex, :hackney, "1.25.0", "390e9b83f31e5b325b9f43b76e1a785cbdb69b5b6cd4e079aa67835ded046867", [:rebar3], [{:certifi, "~> 2.15.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.4", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "7209bfd75fd1f42467211ff8f59ea74d6f2a9e81cbcee95a56711ee79fd6b1d4"},
+ "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
+ "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
+ "mimerl": {:hex, :mimerl, "1.4.0", "3882a5ca67fbbe7117ba8947f27643557adec38fa2307490c4c4207624cb213b", [:rebar3], [], "hexpm", "13af15f9f68c65884ecca3a3891d50a7b57d82152792f3e19d88650aa126b144"},
+ "mustache": {:hex, :mustache, "0.5.1", "1bfee8a68a8e72d47616541a93a632ae1684c1abc17c9eb5f7bfecb78d7496e5", [:mix], [], "hexpm", "524c9bbb6080a52d7b6806436b4e269e0224c785a228faf3293ef30a75016bfa"},
+ "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
+ "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
+ "tzdata": {:hex, :tzdata, "1.1.3", "b1cef7bb6de1de90d4ddc25d33892b32830f907e7fc2fccd1e7e22778ab7dfbc", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "d4ca85575a064d29d4e94253ee95912edfb165938743dbf002acdf0dcecb0c28"},
+ "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.1", "a48703a25c170eedadca83b11e88985af08d35f37c6f664d6dcfb106a97782fc", [:rebar3], [], "hexpm", "b3a917854ce3ae233619744ad1e0102e05673136776fb2fa76234f3e03b23642"},
+}