3 Commits

  1. 9
      CHANGELOG.md
  2. 47
      lib/mirage/markdown.ex
  3. 16
      lib/mirage_web/views/layout_view.ex
  4. 2
      mix.exs
  5. 2
      priv/repo/migrations/20210207200506_add_settings_data_3.exs
  6. 21
      test/mirage/notes_test.exs

9
CHANGELOG.md

@ -5,6 +5,15 @@ See [Conventional Commits](Https://conventionalcommits.org) for commit guideline
<!-- changelog -->
## [v0.17.0](https://git.inhji.de/inhji/mirage/compare/v0.16.0...v0.17.0) (2021-02-07)
### Features:
* support references with custom title
## [v0.16.0](https://git.inhji.de/inhji/mirage/compare/v0.15.0...v0.16.0) (2021-02-07)

47
lib/mirage/markdown.ex

@ -13,26 +13,45 @@ defmodule Mirage.Markdown do
end
end
@crossref_regex ~r/\[\[(?<id>\d+)\]\]/
@crossref_regex ~r/\[\[(?<id>\d+)(?:\|([\w\d\s]+))?\]\]/
def get_references(markdown) do
@crossref_regex
|> Regex.scan(markdown, capture: :all_but_first)
end
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)
markdown
|> get_references()
|> Enum.reduce(markdown, &replace_with_link/2)
|> Earmark.as_html!(options)
end
def replace_with_link([note_id, title], markdown) do
case Mirage.Notes.get_note(note_id) do
nil ->
markdown
note ->
Regex.replace(@crossref_regex, markdown, get_link(note.id, title), global: false)
end
end
def replace_with_link([note_id], markdown) do
case Mirage.Notes.get_note(note_id) do
nil ->
markdown
note ->
String.replace(markdown, "[[#{note_id}]]", get_link(note.id, note.title))
end
end
def get_link(id, title) do
link(title, to: "/notes/#{id}") |> safe_to_string()
end
end

16
lib/mirage_web/views/layout_view.ex

@ -2,16 +2,16 @@ defmodule MirageWeb.LayoutView do
use MirageWeb, :view
def set_favicon(icon) do
"data:image/svg+xml,#{favicon(icon) |> safe_to_string}"
"data:image/svg+xml,#{favicon(icon) |> safe_to_string}"
end
def favicon(icon) do
~E"""
<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22>
<text y=%22.9em%22 font-size=%2290%22>
<%= icon %>
</text>
</svg>
"""
~E"""
<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22>
<text y=%22.9em%22 font-size=%2290%22>
<%= icon %>
</text>
</svg>
"""
end
end

2
mix.exs

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

2
priv/repo/migrations/20210207200506_add_settings_data_3.exs

@ -21,4 +21,4 @@ defmodule Mirage.Repo.Migrations.AddSettingsData3 do
from(s in Setting, where: s.name in @settings)
|> repo().delete_all()
end
end
end

21
test/mirage/notes_test.exs

@ -11,6 +11,9 @@ defmodule Mirage.NotesTest do
@update_attrs_with_link %{
content: "some updated content with a reference [[@OWN_ID]] [[@NOTE_ID]]"
}
@update_attrs_with_link_and_title %{
content: "some updated content with a reference [[@OWN_ID|Link to myself]] [[@NOTE_ID]]"
}
@invalid_attrs %{content: nil}
def note_fixture(attrs \\ %{}) do
@ -67,6 +70,24 @@ defmodule Mirage.NotesTest do
assert note.content_html =~ "#{note.title}"
end
test "update_note/2 with a cross-ref link and title renders a link to the referenced note" do
note = note_fixture()
attrs =
Map.update!(@update_attrs_with_link_and_title, :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}|Link to myself]] [[#{note.id + 1}]]"
assert note.content_html =~ "Link to myself"
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)

Loading…
Cancel
Save