2 Commits

  1. 9
      CHANGELOG.md
  2. 31
      lib/mirage/markdown.ex
  3. 4
      lib/mirage/notes.ex
  4. 2
      mix.exs
  5. 21
      test/mirage/notes_test.exs
  6. 2
      test/mirage_web/controllers/note_controller_test.exs

9
CHANGELOG.md

@ -5,6 +5,15 @@ See [Conventional Commits](Https://conventionalcommits.org) for commit guideline
<!-- changelog -->
## [v0.15.0](https://git.inhji.de/inhji/mirage/compare/v0.14.0...v0.15.0) (2021-02-07)
### Features:
* generate links from cross-ref markers
## [v0.14.0](https://git.inhji.de/inhji/mirage/compare/v0.13.0...v0.14.0) (2021-02-07)

31
lib/mirage/markdown.ex

@ -1,15 +1,38 @@
defmodule Mirage.Markdown do
import Phoenix.HTML.Link, only: [link: 2]
import Phoenix.HTML, only: [raw: 1, safe_to_string: 1]
import Ecto.Changeset, only: [get_change: 2, put_change: 3]
def maybe_render_markdown(changeset, markdown_field, html_field) do
if markdown = get_change(changeset, markdown_field) do
html = Earmark.as_html!(markdown, %Earmark.Options{
code_class_prefix: "lang- language-"
})
html = render(markdown)
put_change(changeset, html_field, html)
else
changeset
end
end
end
@crossref_regex ~r/\[\[(?<id>\d+)\]\]/
def render(markdown) do
options = %Earmark.Options{
code_class_prefix: "lang- language-"
}
@crossref_regex
|> Regex.scan(markdown, capture: :all_but_first)
|> List.flatten()
|> Enum.reduce(markdown, fn note_id, markdown ->
case Mirage.Notes.get_note(note_id) do
nil ->
markdown
note ->
a_element = link(note.title, to: "/notes/#{note.id}") |> safe_to_string()
String.replace(markdown, "[[#{note_id}]]", a_element)
end
end)
|> Earmark.as_html!(options)
end
end

4
lib/mirage/notes.ex

@ -6,7 +6,7 @@ defmodule Mirage.Notes do
import Ecto.Query, warn: false
alias Mirage.Repo
alias Mirage.Notes.{Note, Topic, Tags}
alias Mirage.Notes.{Note, Topic}
@note_preloads [:links, :topics]
@ -43,6 +43,8 @@ defmodule Mirage.Notes do
"""
def get_note!(id), do: Repo.get!(Note, id)
def get_note(id), do: Repo.get(Note, id)
def preload_note(note), do: Repo.preload(note, @note_preloads)
@doc """

2
mix.exs

@ -1,7 +1,7 @@
defmodule Mirage.MixProject do
use Mix.Project
@version "0.14.0"
@version "0.15.0"
def project do
[

21
test/mirage/notes_test.exs

@ -8,6 +8,9 @@ defmodule Mirage.NotesTest do
@valid_attrs %{content: "some content", title: "some title"}
@update_attrs %{content: "some updated content"}
@update_attrs_with_link %{
content: "some updated content with a reference [[@OWN_ID]] [[@NOTE_ID]]"
}
@invalid_attrs %{content: nil}
def note_fixture(attrs \\ %{}) do
@ -46,6 +49,24 @@ defmodule Mirage.NotesTest do
assert note.content == "some updated content"
end
test "update_note/2 with a cross-ref link renders a link to the referenced note" do
note = note_fixture()
attrs =
Map.update!(@update_attrs_with_link, :content, fn content ->
content
|> String.replace("@OWN_ID", to_string(note.id))
|> String.replace("@NOTE_ID", to_string(note.id + 1))
end)
assert {:ok, %Note{} = note} = Notes.update_note(note, attrs)
assert note.content ==
"some updated content with a reference [[#{note.id}]] [[#{note.id + 1}]]"
assert note.content_html =~ "#{note.title}"
end
test "update_note/2 with invalid data returns error changeset" do
note = note_fixture()
assert {:error, %Ecto.Changeset{}} = Notes.update_note(note, @invalid_attrs)

2
test/mirage_web/controllers/note_controller_test.exs

@ -65,7 +65,7 @@ defmodule MirageWeb.NoteControllerTest do
conn = get(conn, Routes.note_path(conn, :show, note))
assert html_response(conn, 200) =~ "some updated content"
assert html_response(conn, 200) =~ "some other tag"
refute html_response(conn, 200) =~ "some tag"
refute html_response(conn, 200) =~ "some tag"
end
test "renders errors when data is invalid", %{conn: conn, note: note} do

Loading…
Cancel
Save