Skip to content
This repository was archived by the owner on Nov 8, 2022. It is now read-only.

Commit 02a934f

Browse files
authored
Merge pull request #264 from coderplanets/editor-thing
refactor(new-editor): editor.js convert & parse
2 parents 7497a6a + 0d43e6a commit 02a934f

23 files changed

+1256
-273
lines changed

.iex.exs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# see: https://github.com/blackode/elixir-tips#loading-project-module-aliases-iexexs
2+
alias Helper.Converter.EditorToHTML

Makefile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,8 @@ test.watch.wip:
171171
# test.watch not work now, see: https://github.com/lpil/mix-test.watch/issues/116
172172
# mix test.watch --only wip --stale
173173
test.watch.wip2:
174-
mix test --listen-on-stdin --stale --trace --only wip2
174+
mix test --listen-on-stdin --stale --only wip2
175175
# mix test.watch --only wip2
176-
mix test.watch --only wip2
177176
test.watch.bug:
178177
mix test.watch --only bug
179178
test.report:

lib/helper/converter/assets/delimiter_icons.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
defmodule Helper.Converter.EditorToHtml.Assets.DelimiterIcons do
1+
defmodule Helper.Converter.EditorToHTML.Assets.DelimiterIcons do
22
@moduledoc """
33
svg icons for delimiter block
44
NOTE: those svg should be sync with frontend svg
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
defmodule Helper.Converter.EditorToHTML.Header do
2+
@moduledoc """
3+
parse editor.js's header block
4+
5+
see https://editorjs.io/
6+
"""
7+
8+
# @behaviour Helper.Converter.EditorToHTML.Parser
9+
10+
defmacro __using__(_opts) do
11+
quote do
12+
alias Helper.Metric
13+
14+
@clazz Metric.Article.class_names(:html)
15+
16+
defp parse_block(%{
17+
"type" => "header",
18+
"data" =>
19+
%{
20+
"text" => text,
21+
"level" => level,
22+
"eyebrowTitle" => eyebrow_title,
23+
"footerTitle" => footer_title
24+
} = data
25+
}) do
26+
"""
27+
<div class="#{@clazz.header.wrapper}">
28+
<div class="#{@clazz.header.eyebrow_title}">#{eyebrow_title}</div>
29+
<h#{level}>#{text}</h#{level}>
30+
<div class="#{@clazz.header.footer_title}">#{footer_title}</div>
31+
</div>
32+
"""
33+
end
34+
35+
defp parse_block(%{
36+
"type" => "header",
37+
"data" =>
38+
%{
39+
"text" => text,
40+
"level" => level,
41+
"eyebrowTitle" => eyebrow_title
42+
} = data
43+
}) do
44+
"""
45+
<div class="#{@clazz.header.wrapper}">
46+
<div class="#{@clazz.header.eyebrow_title}">#{eyebrow_title}</div>
47+
<h#{level}>#{text}</h#{level}>
48+
</div>
49+
"""
50+
end
51+
52+
defp parse_block(%{
53+
"type" => "header",
54+
"data" =>
55+
%{
56+
"text" => text,
57+
"level" => level,
58+
"footerTitle" => footer_title
59+
} = data
60+
}) do
61+
"""
62+
<div class="#{@clazz.header.wrapper}">
63+
<h#{level}>#{text}</h#{level}>
64+
<div class="#{@clazz.header.footer_title}">#{footer_title}</div>
65+
</div>
66+
"""
67+
end
68+
69+
defp parse_block(%{
70+
"type" => "header",
71+
"data" => %{
72+
"text" => text,
73+
"level" => level
74+
}
75+
}) do
76+
"<h#{level}>#{text}</h#{level}>"
77+
end
78+
end
79+
end
80+
end
Lines changed: 28 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,58 @@
1-
defmodule Helper.Converter.EditorToHtml do
1+
# defmodule Helper.Converter.EditorToHTML.Parser do
2+
# @moduledoc false
3+
4+
# # TODO: map should be editor_block
5+
# @callback parse_block(editor_json :: Map.t()) :: String.t()
6+
# end
7+
8+
defmodule Helper.Converter.EditorToHTML do
29
@moduledoc """
310
parse editor.js's json data to raw html and sanitize it
411
512
see https://editorjs.io/
613
"""
7-
alias Helper.Converter.HtmlSanitizer
8-
alias Helper.Converter.EditorToHtml.Assets
9-
alias Helper.Utils
1014

11-
alias Assets.{DelimiterIcons}
15+
use Helper.Converter.EditorToHTML.Header
16+
use Helper.Converter.EditorToHTML.Paragraph
17+
use Helper.Converter.EditorToHTML.List
18+
19+
alias Helper.Converter.EditorToHTML.Validator
20+
alias Helper.Converter.{EditorToHTML, HtmlSanitizer}
21+
alias Helper.{Metric, Utils}
22+
23+
alias EditorToHTML.Assets.{DelimiterIcons}
1224

13-
@html_class_prefix "cps-viewer"
25+
@clazz Metric.Article.class_names(:html)
1426

1527
@spec to_html(binary | maybe_improper_list) :: false | {:ok, <<_::64, _::_*8>>}
1628
def to_html(string) when is_binary(string) do
1729
with {:ok, parsed} = string_to_json(string),
18-
true <- valid_editor_data?(parsed) do
30+
{:ok, _} <- Validator.is_valid(parsed) do
1931
content =
2032
Enum.reduce(parsed["blocks"], "", fn block, acc ->
2133
clean_html = block |> parse_block |> HtmlSanitizer.sanitize()
2234
acc <> clean_html
2335
end)
2436

25-
{:ok, "<div class=\"#{@html_class_prefix}\">#{content}<div>"}
37+
{:ok, "<div class=\"#{@clazz.viewer}\">#{content}<div>"}
2638
end
2739
end
2840

41+
@doc "used for markdown ast to editor"
2942
def to_html(editor_blocks) when is_list(editor_blocks) do
3043
content =
3144
Enum.reduce(editor_blocks, "", fn block, acc ->
3245
clean_html = block |> Utils.keys_to_strings() |> parse_block |> HtmlSanitizer.sanitize()
3346
acc <> clean_html
3447
end)
3548

36-
{:ok, "<div class=\"#{@html_class_prefix}\">#{content}<div>"}
37-
end
38-
39-
# IO.inspect(data, label: "parse header")
40-
defp parse_block(%{"type" => "header", "data" => data}) do
41-
text = get_in(data, ["text"])
42-
level = get_in(data, ["level"])
43-
44-
"<h#{level} class=\"#{@html_class_prefix}-header\">#{text}</h#{level}>"
49+
{:ok, "<div class=\"#{@clazz.viewer}\">#{content}<div>"}
4550
end
4651

47-
# IO.inspect(data, label: "parse paragraph")
48-
defp parse_block(%{"type" => "paragraph", "data" => data}) do
49-
text = get_in(data, ["text"])
50-
51-
"<p class=\"#{@html_class_prefix}-paragraph\">#{text}</p>"
52-
end
53-
54-
# IO.inspect(data, label: "parse image")
5552
defp parse_block(%{"type" => "image", "data" => data}) do
5653
url = get_in(data, ["file", "url"])
5754

58-
"<div class=\"#{@html_class_prefix}-image\"><img src=\"#{url}\"></div>"
55+
"<div class=\"#{@clazz.viewer}-image\"><img src=\"#{url}\"></div>"
5956
# |> IO.inspect(label: "iamge ret")
6057
end
6158

@@ -77,7 +74,6 @@ defmodule Helper.Converter.EditorToHtml do
7774
"<ol>#{content}</ol>"
7875
end
7976

80-
# IO.inspect(items, label: "checklist items")
8177
# TODO: add item class
8278
defp parse_block(%{"type" => "checklist", "data" => %{"items" => items}}) do
8379
content =
@@ -94,31 +90,31 @@ defmodule Helper.Converter.EditorToHtml do
9490
end
9591
end)
9692

97-
"<div class=\"#{@html_class_prefix}-checklist\">#{content}</div>"
93+
"<div class=\"#{@clazz.viewer}-checklist\">#{content}</div>"
9894
# |> IO.inspect(label: "jjj")
9995
end
10096

10197
defp parse_block(%{"type" => "delimiter", "data" => %{"type" => type}}) do
10298
svg_icon = DelimiterIcons.svg(type)
10399

104100
# TODO: left-wing, righ-wing staff
105-
{:skip_sanitize, "<div class=\"#{@html_class_prefix}-delimiter\">#{svg_icon}</div>"}
101+
{:skip_sanitize, "<div class=\"#{@clazz.viewer}-delimiter\">#{svg_icon}</div>"}
106102
end
107103

108104
# IO.inspect(data, label: "parse linkTool")
109105
# TODO: parse the link-card info
110106
defp parse_block(%{"type" => "linkTool", "data" => data}) do
111107
link = get_in(data, ["link"])
112108

113-
"<div class=\"#{@html_class_prefix}-linker\"><a href=\"#{link}\" target=\"_blank\">#{link}</a></div>"
109+
"<div class=\"#{@clazz.viewer}-linker\"><a href=\"#{link}\" target=\"_blank\">#{link}</a></div>"
114110
# |> IO.inspect(label: "linkTool ret")
115111
end
116112

117113
# IO.inspect(data, label: "parse quote")
118114
defp parse_block(%{"type" => "quote", "data" => data}) do
119115
text = get_in(data, ["text"])
120116

121-
"<div class=\"#{@html_class_prefix}-quote\">#{text}</div>"
117+
"<div class=\"#{@clazz.viewer}-quote\">#{text}</div>"
122118
# |> IO.inspect(label: "quote ret")
123119
end
124120

@@ -132,18 +128,8 @@ defmodule Helper.Converter.EditorToHtml do
132128
end
133129

134130
defp parse_block(_block) do
135-
# IO.puts("[unknow block]")
136-
"[unknow block]"
131+
"<div class=\"#{@clazz.unknow_block}\">[unknow block]</div>"
137132
end
138133

139134
def string_to_json(string), do: Jason.decode(string)
140-
141-
defp valid_editor_data?(map) when is_map(map) do
142-
Map.has_key?(map, "time") and
143-
Map.has_key?(map, "version") and
144-
Map.has_key?(map, "blocks") and
145-
is_list(map["blocks"]) and
146-
is_binary(map["version"]) and
147-
is_integer(map["time"])
148-
end
149135
end

0 commit comments

Comments
 (0)