Stable state. Starting to build out ugly frontend.
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
defmodule AlchemistMarkdown do
|
||||
def to_html(markdown \\ "", opts \\ [])
|
||||
|
||||
def to_html(markdown, _opts) do
|
||||
markdown
|
||||
|> hrs
|
||||
|> divs
|
||||
|> Earmark.as_html!(earmark_options())
|
||||
|> HtmlSanitizeEx.html5()
|
||||
|> smalls
|
||||
|> bigs
|
||||
end
|
||||
|
||||
# for now, we'll just replace H1 and H2 tags with H3s, but as the site grows and it becomes necessary, we'll add more restrictions to commenters.
|
||||
def to_commenter_html(markdown) do
|
||||
to_html(markdown)
|
||||
|> h3_is_max
|
||||
end
|
||||
|
||||
# Earmark doesn't support adding CSS classes to divs yet
|
||||
def divs(text) do
|
||||
matcher = ~r{(^|\n)::div((\.[\w-]*)*) ?(.*?)(\n):/div ?}s
|
||||
matches = Regex.run(matcher, text)
|
||||
|
||||
case matches do
|
||||
nil ->
|
||||
text
|
||||
|
||||
[matched_part, _, classes, _, inner_md | _tail] ->
|
||||
classname = classes |> String.split(".", trim: true) |> Enum.join(" ")
|
||||
html = "<div class=#{classname}>#{to_html(inner_md)}</div>"
|
||||
String.replace(text, matched_part, html)
|
||||
end
|
||||
end
|
||||
|
||||
def bigs(text) do
|
||||
replace_unless_pre(text, ~r/\+\+(.+)\+\+/, "<big>\\1</big>")
|
||||
end
|
||||
|
||||
def hrs(text) do
|
||||
Regex.replace(~r{(^|\n)([-*])( *\2 *)+\2}s, text, "\\1<hr />")
|
||||
end
|
||||
|
||||
def h3_is_max(text) do
|
||||
text = Regex.replace(~r{<h1([^<]*>(.*)<\/)h1>}s, text, "<h3\\1h3>")
|
||||
Regex.replace(~r{<h2([^<]*>(.*)<\/)h2>}s, text, "<h3\\1h3>")
|
||||
end
|
||||
|
||||
# Replace the input text based on the regex and replacement text provided
|
||||
# ... except leave everything inside <pre> blocks as is
|
||||
def replace_unless_pre(text, rexp, replacement) do
|
||||
Regex.split(~r|<pre[^<]*>.*<\/pre>|s, text, include_captures: true)
|
||||
|> Enum.map(fn str ->
|
||||
case String.starts_with?(str, "<pre") do
|
||||
true -> str
|
||||
_ -> Regex.replace(rexp, str, replacement)
|
||||
end
|
||||
end)
|
||||
|> Enum.join("")
|
||||
end
|
||||
|
||||
def smalls(text) do
|
||||
replace_unless_pre(text, ~r/--(.+)--/, "<small>\\1</small>")
|
||||
end
|
||||
|
||||
defp earmark_options() do
|
||||
%Earmark.Options{
|
||||
code_class_prefix: "lang-",
|
||||
smartypants: false
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -34,8 +34,8 @@ defmodule LogsrvApi do
|
||||
end
|
||||
end
|
||||
|
||||
def read(page) do
|
||||
@repo.read(page)
|
||||
def read(entry) do
|
||||
@repo.read(entry)
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
defmodule LogsrvApi.Filesystem do
|
||||
alias LogsrvApi.{Journal, Page}
|
||||
|
||||
def to_date(str) do
|
||||
def to_date(str) when is_bitstring(str) do
|
||||
str
|
||||
|> String.replace(~r/\..*/,"")
|
||||
|> String.replace("_","-")
|
||||
|> Date.from_iso8601()
|
||||
end
|
||||
def to_date(date) do
|
||||
{:ok, date}
|
||||
end
|
||||
|
||||
def dir do
|
||||
Application.get_env(:logsrv_api, :dir) <> "/"
|
||||
end
|
||||
@@ -41,8 +45,14 @@ defmodule LogsrvApi.Filesystem do
|
||||
def get!(Journal, date) do
|
||||
Enum.find(all(Journal), fn(entry) -> entry.date === date end)
|
||||
end
|
||||
def get!(Page, title) do
|
||||
Enum.find(all(Page), fn(entry) -> entry.title === title end)
|
||||
def get!(Page, filename) do
|
||||
Enum.find(all(Page), fn(entry) -> entry.filename === filename end)
|
||||
end
|
||||
|
||||
def read(entry) do
|
||||
entry.type
|
||||
|> locate(entry.filename)
|
||||
|> File.read!
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -7,13 +7,15 @@ defmodule LogsrvApi.Page do
|
||||
|> String.replace(~r/\.md$/,"")
|
||||
|> String.replace("%2F","/")
|
||||
|
||||
date_modified = Page |> Filesystem.locate(fd)
|
||||
%{mtime: mtime} = (Page |> Filesystem.locate(fd) |> File.stat!)
|
||||
date_modified = mtime |> NaiveDateTime.from_erl!() |> DateTime.from_naive!("Etc/UTC")
|
||||
tags = [:fun]
|
||||
|
||||
%{
|
||||
type: Page,
|
||||
title: title |> String.capitalize(),
|
||||
filename: fd,
|
||||
date_modified: date_modified,
|
||||
date: date_modified,
|
||||
tags: tags
|
||||
}
|
||||
end
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
defmodule LogsrvWeb.PostController do
|
||||
use LogsrvWeb, :controller
|
||||
import LogsrvApi
|
||||
|
||||
def index(conn, _params) do
|
||||
pages = LogsrvApi.pages()
|
||||
journals = LogsrvApi.journals()
|
||||
render(conn, "index.html", pages: pages, journals: journals)
|
||||
render(conn, "index.html", pages: pages(), journals: journals())
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
pages = LogsrvApi.pages()
|
||||
journals = LogsrvApi.journals()
|
||||
post = LogsrvApi.get_by_id(id)
|
||||
content = post |> LogsrvApi.read
|
||||
render(conn, "post.html", post: post, pages: pages, journals: journals, content: content)
|
||||
post = id |> get_by_id
|
||||
content = post |> read
|
||||
render(conn, "post.html", post: post, pages: pages(), journals: journals(), content: content)
|
||||
end
|
||||
|
||||
def home(conn, _params) do
|
||||
homepage = get_by_id("contents.md")
|
||||
content = homepage |> read
|
||||
render(conn, "post.html", post: homepage, pages: pages(), journals: journals(), content: content)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,7 +17,9 @@ defmodule LogsrvWeb.Router do
|
||||
scope "/", LogsrvWeb do
|
||||
pipe_through :browser
|
||||
|
||||
get "/", PostController, :index
|
||||
get "/", PostController, :home
|
||||
get "/index", PostController, :index
|
||||
get "/post/:id", PostController, :show
|
||||
end
|
||||
|
||||
# Other scopes may use custom stacks.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="en" data-theme="dark">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
@@ -7,19 +7,22 @@
|
||||
<meta name="csrf-token" content={csrf_token_value()}>
|
||||
<%= live_title_tag assigns[:page_title] || "LogsrvWeb", suffix: " · Phoenix Framework" %>
|
||||
<link phx-track-static rel="stylesheet" href={Routes.static_path(@conn, "/assets/app.css")}/>
|
||||
<link phx-track-static rel="stylesheet" href={Routes.static_path(@conn, "/assets/bear.css")}/>
|
||||
<script defer phx-track-static type="text/javascript" src={Routes.static_path(@conn, "/assets/app.js")}></script>
|
||||
</head>
|
||||
<body>
|
||||
<body><div id="root"><div class="theme-inner"><div id="app-container">
|
||||
<header>
|
||||
<section class="container" style="flex-direction:row-reverse;">
|
||||
<img style="padding:1em;border-radius:1em;" src={Routes.static_path(@conn, "/images/logseq-logo.png")} alt="Logo"/>
|
||||
<div><a href="/"><img style="padding:1em;border-radius:1em;" src={Routes.static_path(@conn, "/images/logseq-logo.png")} alt="Logo"/></a></div>
|
||||
<div>
|
||||
<ul>
|
||||
<li> <b>Directory:</b> <%= LogsrvApi.Filesystem.dir %> </li>
|
||||
<li> <b>Journals:</b> <%= @pages |> length %> </li>
|
||||
<li> <b>Pages:</b> <%= @journals |> length %> </li>
|
||||
</ul>
|
||||
</section>
|
||||
</ul></div>
|
||||
<div> <a href="/pages"><h3>Pages</h3></a> </div><div> <a href="/journals"><h3>Journals</h3></a> </div>
|
||||
</section>
|
||||
</header>
|
||||
<%= @inner_content %>
|
||||
</body>
|
||||
</div></div></div> </body>
|
||||
</html>
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
</article>
|
||||
</section>
|
||||
<section class="row">
|
||||
<%= content(@post.filename) %>
|
||||
<%= raw @content |> AlchemistMarkdown.to_html |> cleanup %>
|
||||
</section>
|
||||
@@ -6,9 +6,8 @@ defmodule LogsrvWeb.PostView do
|
||||
"/post/#{post.filename}"
|
||||
end
|
||||
|
||||
def content(post) do
|
||||
IO.puts(post.filename)
|
||||
post.filename |> Journal.locate |> LogsrvApi.read
|
||||
def cleanup(str) do
|
||||
str
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user