Skip to content

Commit b40eb39

Browse files
committed
Improve down with referenced links
1 parent 3b051c4 commit b40eb39

File tree

2 files changed

+84
-14
lines changed

2 files changed

+84
-14
lines changed

apps/components_guide_web/lib/components_guide_web/views/down_view.ex

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,13 @@ defmodule ComponentsGuideWeb.DownView do
22
use ComponentsGuideWeb, :view
33

44
defmodule ParserState do
5-
defstruct html: [], italics: nil, bold: nil, link: nil
5+
defstruct html: [], italics: nil, bold: nil, link: nil, link_references: %{}
66

7-
@spec parse(binary) ::
8-
{:safe,
9-
binary
10-
| maybe_improper_list(
11-
binary | maybe_improper_list(any, binary | []) | byte,
12-
binary | []
13-
)}
14-
def parse(input) when is_binary(input) do
15-
next(%__MODULE__{}, input)
7+
def parse(input, options) when is_binary(input) do
8+
%__MODULE__{
9+
link_references: Access.get(options, :links, %{})
10+
}
11+
|> next(input)
1612
end
1713

1814
# Links
@@ -40,24 +36,61 @@ defmodule ComponentsGuideWeb.DownView do
4036
|> next(rest)
4137
end
4238

39+
defp next(state = %__MODULE__{link: {:ready_for_url, text_chars}}, <<"["::utf8>> <> rest) do
40+
%__MODULE__{state | link: {:capturing_url_reference, text_chars, []}}
41+
|> next(rest)
42+
end
43+
44+
defp next(state = %__MODULE__{link: {:ready_for_url, text_chars}}, rest) do
45+
text = text_chars |> Enum.reverse() |> List.to_string()
46+
url = Map.get(state.link_references, text, "")
47+
anchor_html = Phoenix.HTML.Link.link(text, to: url) |> Phoenix.HTML.safe_to_string()
48+
49+
%__MODULE__{state | html: [anchor_html | state.html], link: nil}
50+
|> next(rest)
51+
end
52+
4353
defp next(
4454
state = %__MODULE__{link: {:capturing_url, text_chars, url_chars}},
4555
<<")"::utf8>> <> rest
4656
) do
4757
text = text_chars |> Enum.reverse() |> List.to_string()
4858
url = url_chars |> Enum.reverse() |> List.to_string()
59+
anchor_html = Phoenix.HTML.Link.link(text, to: url) |> Phoenix.HTML.safe_to_string()
4960

61+
%__MODULE__{state | html: [anchor_html | state.html], link: nil}
62+
|> next(rest)
63+
end
64+
65+
defp next(
66+
state = %__MODULE__{link: {:capturing_url, text_chars, url_chars}},
67+
<<char::utf8>> <> rest
68+
) do
69+
%__MODULE__{state | link: {:capturing_url, text_chars, [char | url_chars]}}
70+
|> next(rest)
71+
end
72+
73+
defp next(
74+
state = %__MODULE__{link: {:capturing_url_reference, text_chars, url_reference_chars}},
75+
<<"]"::utf8>> <> rest
76+
) do
77+
text = text_chars |> Enum.reverse() |> List.to_string()
78+
url_reference = url_reference_chars |> Enum.reverse() |> List.to_string()
79+
url = Map.get(state.link_references, url_reference, "")
5080
anchor_html = Phoenix.HTML.Link.link(text, to: url) |> Phoenix.HTML.safe_to_string()
5181

5282
%__MODULE__{state | html: [anchor_html | state.html], link: nil}
5383
|> next(rest)
5484
end
5585

5686
defp next(
57-
state = %__MODULE__{link: {:capturing_url, link_chars, url_chars}},
87+
state = %__MODULE__{link: {:capturing_url_reference, text_chars, url_reference_chars}},
5888
<<char::utf8>> <> rest
5989
) do
60-
%__MODULE__{state | link: {:capturing_url, link_chars, [char | url_chars]}}
90+
%__MODULE__{
91+
state
92+
| link: {:capturing_url_reference, text_chars, [char | url_reference_chars]}
93+
}
6194
|> next(rest)
6295
end
6396

@@ -106,7 +139,7 @@ defmodule ComponentsGuideWeb.DownView do
106139
end
107140
end
108141

109-
def down(input) when is_binary(input) do
110-
ParserState.parse(input)
142+
def down(input, options \\ %{}) when is_binary(input) do
143+
ParserState.parse(input, options)
111144
end
112145
end

apps/components_guide_web/test/collected_live_web/views/down_view_test.exs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,42 @@ defmodule ComponentsGuideWeb.DownViewTest do
2525
assert Subject.down("text with [link](https://example.org/) somewhere") ==
2626
raw("text with <a href=\"https://example.org/\">link</a> somewhere")
2727
end
28+
29+
test "link with self as reference" do
30+
assert Subject.down("text with [link somewhere] interesting",
31+
links: %{
32+
"link somewhere" => "https://example.org/"
33+
}
34+
) ==
35+
raw("text with <a href=\"https://example.org/\">link somewhere</a> interesting")
36+
end
37+
38+
test "link with text as reference" do
39+
assert Subject.down("text with [link somewhere][example org] interesting",
40+
links: %{
41+
"example org" => "https://example.org/"
42+
}
43+
) ==
44+
raw("text with <a href=\"https://example.org/\">link somewhere</a> interesting")
45+
end
46+
47+
test "link with number as reference" do
48+
assert Subject.down("text with [link somewhere][1] interesting",
49+
links: %{
50+
"1" => "https://example.org/"
51+
}
52+
) ==
53+
raw("text with <a href=\"https://example.org/\">link somewhere</a> interesting")
54+
end
55+
56+
test "multiple links" do
57+
assert Subject.down("text with [link somewhere] interesting and [another one] to visit",
58+
links: %{
59+
"link somewhere" => "https://example.org/somewhere",
60+
"another one" => "https://example.org/another"
61+
}
62+
) ==
63+
raw("text with <a href=\"https://example.org/somewhere\">link somewhere</a> interesting and <a href=\"https://example.org/another\">another one</a> to visit")
64+
end
2865
end
2966
end

0 commit comments

Comments
 (0)