~mika/www.m1kadev.nl

eb04e0878ed5ee04d0cf78dc9d7e18e8424a4baa — m1kadev 6 months ago 6f77896
kethel: add rss feed support
M kethel/lib/pages.ex => kethel/lib/pages.ex +3 -0
@@ 28,8 28,11 @@ 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 
  end

  # doc "compiles a file, already read into process memory. Does not return the binary, but instantly writes it to disk"

A kethel/lib/scriprs => kethel/lib/scriprs +0 -0
M kethel/lib/scripts.ex => kethel/lib/scripts.ex +4 -1
@@ 27,13 27,16 @@ defmodule Scripts do
  end

  def compile(scripts) do
    t_begin = System.monotonic_time(:millisecond)

    ensure_file_structure(scripts.project_root)

    scripts.scripts
    |> Task.async_stream(fn script -> compile_file(script, scripts.project_root) end)
    |> Enum.map(fn {:ok, val} -> val end)

    :ok
    t_end = System.monotonic_time(:millisecond)
    t_end - t_begin
  end

  # data | npx lightningcss -m

M kethel/lib/styles.ex => kethel/lib/styles.ex +5 -0
@@ 27,11 27,16 @@ defmodule Styles do
  end

  def compile(styles) do
    t_begin = System.monotonic_time(:millisecond)

    ensure_file_structure(styles.project_root)

    styles.styles
    |> Task.async_stream(fn style -> compile_file(style, styles.project_root) end)
    |> Enum.map(fn {:ok, val} -> val end)

    t_end = System.monotonic_time(:millisecond)
    t_end - t_begin
  end

  # data | npx lightningcss -m

M kethel/lib/thoughts.ex => kethel/lib/thoughts.ex +22 -12
@@ 14,12 14,13 @@ defmodule Thoughts do
    binary_part(path, begin, byte_size(path) - begin)
  end

  @spec collect(binary(), %{binary() => binary()}) :: %{}
  @spec collect(binary(), %{binary() => binary()}) :: %Thoughts{}
  def collect(project_root, bricks) do
    %Thoughts{
      thoughts:
        Path.wildcard("#{project_root}/thoughts/*")
        |> Enum.map(fn path -> {path, File.read!(path)} end),
        |> Enum.map(fn path -> {path, get_file_commit_date(path), File.read!(path)} end)
        |> Enum.sort_by(fn {_, date, _ } -> date end, :desc),
      template: File.read!("#{project_root}/templates/thought.thtml"),
      bricks: bricks,
      project_root: project_root


@@ 31,21 32,23 @@ defmodule Thoughts do
    File.mkdir_p!("#{project_root}/build/thoughts/")
  end

  @spec compile(%Thoughts{}) :: :ok
  @spec compile(%Thoughts{}) :: pos_integer()
  def compile(thoughts) do
    t_begin = System.monotonic_time(:millisecond)
    ensure_folders(thoughts.project_root)

    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()

    t_end = System.monotonic_time(:millisecond)

    t_end - t_begin
  end

  defp compile_file({path, thought}, template, bricks, project_root) do
  defp compile_file({path, date, thought}, template, bricks, project_root) do
    name = trim_abs_path(path, project_root)
    # unix timestamp
    date = get_file_commit_date(path)
    output_path = "#{project_root}/build/thoughts/#{urlify(name)}.html"
    mustache_context = Map.merge(bricks, %{thought: thought, name: name, date: date})



@@ 55,10 58,17 @@ 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()
  end

    time =
      String.to_integer(String.trim_trailing(ts_string))
      |> DateTime.from_unix!()
      |> Calendar.strftime("%d/%m/%y (%H:%M)")
  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
    |> 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 } ) 
  end
end

M kethel/main.exs => kethel/main.exs +33 -2
@@ 8,6 8,8 @@ if folder != nil do
  File.rm_rf!("#{project_root}/build")
  File.mkdir_p("#{project_root}/build")

  collection_time_start = System.monotonic_time(:millisecond)

  # other contents depend on this, so we cant async it
  bricks = Bricks.collect(project_root)



@@ 22,21 24,50 @@ if folder != nil do
  [styles, pages, scripts, thoughts] =
    Task.await_many([styles_task, pages_task, scripts_task, thoughts_task], :infinity)

  collection_time_end = System.monotonic_time(:millisecond)

  compilation_time_start = System.monotonic_time(:millisecond)
  
  pages_compile_task = Task.async(fn -> Pages.compile(pages) end)
  styles_compile_task = Task.async(fn -> Styles.compile(styles) end)
  scripts_compile_task = Task.async(fn -> Scripts.compile(scripts) end)
  thoughts_compile_task = Task.async(fn -> Thoughts.compile(thoughts) end)

  Task.await_many(
  [ pages_time, styles_time, scripts_time, thoughts_time] = Task.await_many(
    [
      pages_compile_task,
      styles_compile_task,
      statics_task,
      scripts_compile_task,
      thoughts_compile_task
    ],
    :infinity
  )

  compilation_time_end = System.monotonic_time(:millisecond)

  rss_header = File.read!("#{project_root}/rss/feed.txml")
  rss_footer = "</channel></rss>"
  rss_item_template = File.read!("#{project_root}/rss/item.txml")

  rss_thoughts = thoughts.thoughts
    |> Enum.take(10)
    |> Enum.map(fn thought -> Thoughts.to_rss(thought, rss_item_template, project_root) end)
    |> Enum.join();

  File.write!("#{project_root}/build/rss.xml", rss_header <> rss_thoughts <> rss_footer)

  IO.puts("[COMPILED] #{project_root}/build/rss.xml")

  IO.puts("Finalising...");

  File.cp!("#{project_root}/favicon.ico", "#{project_root}/build/favicon.ico")
  IO.puts("")
  IO.puts(:stderr, "===== BUILD RESULTS =====")
  IO.puts(:stderr, "FILE READING (*.collect()) | #{collection_time_end - collection_time_start}ms") 
  IO.puts(:stderr, "Root page (compile)        | #{pages_time}ms")
  IO.puts(:stderr, "Styles (compile)           | #{styles_time}ms")
  IO.puts(:stderr, "Scripts (compile)          | #{scripts_time}ms")
  IO.puts(:stderr, "Thoughts (compile)         | #{thoughts_time}ms")
else
  IO.puts(:stderr, "The root project folder should be provided on the command line")
end

A rss/feed.txml => rss/feed.txml +1 -0
@@ 0,0 1,1 @@
<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>m1kadev.nl updates :3</title><description>placeholder description</description><language>en</language>

A rss/item.txml => rss/item.txml +1 -0
@@ 0,0 1,1 @@
<item><title>{{title}}</title><description>{{description}}</description><link>{{link}}</link><pubDate>{{date}}</pubDate><category>{{category}}</category></item>