48 lines
1.3 KiB
Elixir
48 lines
1.3 KiB
Elixir
defmodule Wiki.Content.Renderer do
|
|
alias Wiki.Repo
|
|
alias Wiki.Content.Page
|
|
alias WikiWeb.Router.Helpers, as: Routes
|
|
alias WikiWeb.Endpoint
|
|
import Ecto.Query
|
|
|
|
@spec render(Page.t()) :: String.t()
|
|
def render(page) do
|
|
page.content
|
|
|> replace_page_links(page)
|
|
|> render_markdown()
|
|
end
|
|
|
|
@page_link_regex ~r/\[\[.*?\]\]/
|
|
|
|
@spec replace_page_links(content :: String.t(), root_page :: Page.t()) :: String.t()
|
|
defp replace_page_links(content, root_page) do
|
|
String.replace(content, @page_link_regex, fn match ->
|
|
title = String.slice(match, 2..-3)
|
|
lower_title = String.downcase(title)
|
|
|
|
path =
|
|
from(p in Page)
|
|
|> where([p], p.user_id == ^root_page.user_id)
|
|
|> where([p], fragment("lower(?)", p.title) == ^lower_title)
|
|
|> select([p], p.id)
|
|
|> Repo.one()
|
|
|> case do
|
|
nil ->
|
|
Routes.page_path(Endpoint, :new, title: title)
|
|
|
|
linked_page_id ->
|
|
Routes.page_path(Endpoint, :show, linked_page_id)
|
|
end
|
|
|
|
# convert link to markdown, because [[title]] -> link transformation happens before markdown parsing
|
|
"[#{title}](#{path})"
|
|
end)
|
|
end
|
|
|
|
@spec render_markdown(content :: String.t()) :: String.t()
|
|
defp render_markdown(content) do
|
|
{:ok, html, _errors} = Earmark.as_html(content)
|
|
html
|
|
end
|
|
end
|