Skip to content

Commit 3b051c4

Browse files
committed
Improve down parsing
1 parent aa68e55 commit 3b051c4

File tree

2 files changed

+91
-18
lines changed

2 files changed

+91
-18
lines changed

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

Lines changed: 76 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ defmodule ComponentsGuideWeb.DownView do
22
use ComponentsGuideWeb, :view
33

44
defmodule ParserState do
5-
defstruct bold: false, italics: false, html: []
5+
defstruct html: [], italics: nil, bold: nil, link: nil
66

77
@spec parse(binary) ::
88
{:safe,
@@ -15,33 +15,93 @@ defmodule ComponentsGuideWeb.DownView do
1515
next(%__MODULE__{}, input)
1616
end
1717

18-
defp next(state = %__MODULE__{italics: true}, <<"_"::utf8>> <> rest) do
19-
%__MODULE__{state | html: [state.html], italics: false}
18+
# Links
19+
20+
defp next(state = %__MODULE__{link: nil}, <<"["::utf8>> <> rest) do
21+
%__MODULE__{state | link: {:capturing_text, []}}
2022
|> next(rest)
2123
end
2224

23-
defp next(state = %__MODULE__{italics: false}, <<"_"::utf8>> <> rest) do
24-
%__MODULE__{state | html: ["<em1>" | state.html], italics: true}
25+
defp next(state = %__MODULE__{link: {:capturing_text, text_chars}}, <<"]"::utf8>> <> rest) do
26+
%__MODULE__{state | link: {:ready_for_url, text_chars}}
2527
|> next(rest)
2628
end
2729

28-
defp next(state = %__MODULE__{}, <<char::utf8>> <> rest) do
29-
%__MODULE__{state | html: [<<char::utf8>> | state.html]}
30+
defp next(
31+
state = %__MODULE__{link: {:capturing_text, text_chars}},
32+
<<char::utf8>> <> rest
33+
) do
34+
%__MODULE__{state | link: {:capturing_text, [char | text_chars]}}
35+
|> next(rest)
36+
end
37+
38+
defp next(state = %__MODULE__{link: {:ready_for_url, text_chars}}, <<"("::utf8>> <> rest) do
39+
%__MODULE__{state | link: {:capturing_url, text_chars, []}}
40+
|> next(rest)
41+
end
42+
43+
defp next(
44+
state = %__MODULE__{link: {:capturing_url, text_chars, url_chars}},
45+
<<")"::utf8>> <> rest
46+
) do
47+
text = text_chars |> Enum.reverse() |> List.to_string()
48+
url = url_chars |> Enum.reverse() |> List.to_string()
49+
50+
anchor_html = Phoenix.HTML.Link.link(text, to: url) |> Phoenix.HTML.safe_to_string()
51+
52+
%__MODULE__{state | html: [anchor_html | state.html], link: nil}
53+
|> next(rest)
54+
end
55+
56+
defp next(
57+
state = %__MODULE__{link: {:capturing_url, link_chars, url_chars}},
58+
<<char::utf8>> <> rest
59+
) do
60+
%__MODULE__{state | link: {:capturing_url, link_chars, [char | url_chars]}}
61+
|> next(rest)
62+
end
63+
64+
# Bold
65+
66+
defp next(state = %__MODULE__{bold: nil}, <<"**"::utf8>> <> rest) do
67+
%__MODULE__{state | html: ["<strong>" | state.html], bold: "**"}
3068
|> next(rest)
3169
end
3270

33-
defp next(state = %__MODULE__{italics: italics}, "") do
34-
html = Enum.reverse(state.html) |> Enum.join()
71+
defp next(state = %__MODULE__{bold: "**"}, <<"**"::utf8>> <> rest) do
72+
%__MODULE__{state | html: ["</strong>" | state.html], bold: nil}
73+
|> next(rest)
74+
end
75+
76+
# Italics
77+
78+
defp next(state = %__MODULE__{italics: nil}, <<"_"::utf8>> <> rest) do
79+
%__MODULE__{state | html: ["<em>" | state.html], italics: "_"}
80+
|> next(rest)
81+
end
82+
83+
defp next(state = %__MODULE__{italics: "_"}, <<"_"::utf8>> <> rest) do
84+
%__MODULE__{state | html: ["</em>" | state.html], italics: nil}
85+
|> next(rest)
86+
end
3587

36-
html =
37-
case italics do
38-
true ->
39-
html <> "</em>"
88+
defp next(state = %__MODULE__{italics: nil}, <<"*"::utf8>> <> rest) do
89+
%__MODULE__{state | html: ["<em>" | state.html], italics: "*"}
90+
|> next(rest)
91+
end
92+
93+
defp next(state = %__MODULE__{italics: "*"}, <<"*"::utf8>> <> rest) do
94+
%__MODULE__{state | html: ["</em>" | state.html], italics: nil}
95+
|> next(rest)
96+
end
4097

41-
false ->
42-
html
43-
end
98+
defp next(state = %__MODULE__{}, <<char::utf8>> <> rest) do
99+
%__MODULE__{state | html: [<<char::utf8>> | state.html]}
100+
|> next(rest)
101+
end
44102

103+
defp next(state = %__MODULE__{}, "") do
104+
html = state.html |> Enum.reverse() |> Enum.join()
45105
Phoenix.HTML.raw(html)
46106
end
47107
end

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,21 @@ defmodule ComponentsGuideWeb.DownViewTest do
99
assert Subject.down("plain text") == raw("plain text")
1010
end
1111

12-
test "italics" do
13-
assert Subject.down("plain _text_") == raw("plain <em>text</em>")
12+
test "italics with _" do
13+
assert Subject.down("text _italics_ normal") == raw("text <em>italics</em> normal")
14+
end
15+
16+
test "italics with *" do
17+
assert Subject.down("text *italics* normal") == raw("text <em>italics</em> normal")
18+
end
19+
20+
test "bold with **" do
21+
assert Subject.down("text **bold** normal") == raw("text <strong>bold</strong> normal")
22+
end
23+
24+
test "link with inline url" do
25+
assert Subject.down("text with [link](https://example.org/) somewhere") ==
26+
raw("text with <a href=\"https://example.org/\">link</a> somewhere")
1427
end
1528
end
1629
end

0 commit comments

Comments
 (0)