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

Commit dc77793

Browse files
authored
Merge pull request #283 from coderplanets/editor-list
feat(editor): list for read-only article
2 parents 02a934f + 5d13f1d commit dc77793

File tree

24 files changed

+856
-544
lines changed

24 files changed

+856
-544
lines changed

cover/excoveralls.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

lib/groupher_server/cms/delegates/community_sync.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ defmodule GroupherServer.CMS.Delegate.CommunitySync do
99
alias GroupherServer.CMS
1010

1111
alias Helper.ORM
12-
alias Helper.SpecType, as: T
12+
alias Helper.Types, as: T
1313

1414
alias CMS.{
1515
Community,
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
defmodule Helper.Converter.EditorToHTML.Class do
2+
@moduledoc """
3+
html article class names parsed from editor.js's json data
4+
5+
currently use https://editorjs.io/ as rich-text editor
6+
# NOTE: DONOT CHANGE ONCE SET, OTHERWISE IT WILL CAUSE INCOMPATIBILITY ISSUE
7+
"""
8+
9+
@doc """
10+
get all the class names of the parsed editor.js's html parts
11+
"""
12+
def article() do
13+
%{
14+
# root wrapper
15+
"viewer" => "article-viewer-wrapper",
16+
"unknow_block" => "unknow-block",
17+
"invalid_block" => "invalid-block",
18+
# header
19+
"header" => %{
20+
"wrapper" => "header-wrapper",
21+
"eyebrow_title" => "eyebrow-title",
22+
"footer_title" => "footer-title"
23+
},
24+
# list
25+
"list" => %{
26+
"wrapper" => "list-wrapper",
27+
"label" => "list-label",
28+
"label__default" => "list-label__default",
29+
"label__red" => "list-label__red",
30+
"label__green" => "list-label__green",
31+
"label__warn" => "list-label__warn",
32+
"unorder_list_prefix" => "list__item-unorder-prefix",
33+
"order_list_prefix" => "list__item-order-prefix",
34+
"list_item" => "list-item",
35+
"checklist_item" => "list-checklist__item",
36+
"checklist_checkbox" => "checklist__item-checkbox",
37+
"checklist_checkbox_checked" => "checklist__item-check-sign-checked",
38+
"checklist_checksign" => "checklist__item-check-sign",
39+
"text" => "list-item-text",
40+
"checklist_text" => "list-checklist__item-text",
41+
"indent_0" => "",
42+
"indent_1" => "list-indent-1",
43+
"indent_2" => "list-indent-2",
44+
"indent_3" => "list-indent-3"
45+
}
46+
}
47+
end
48+
end
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
defmodule Helper.Converter.EditorToHTML.Frags.Header do
2+
@moduledoc """
3+
parse editor.js's block fragments, use for test too
4+
5+
see https://editorjs.io/
6+
"""
7+
alias Helper.Types, as: T
8+
9+
alias Helper.Converter.EditorToHTML.Class
10+
11+
@class get_in(Class.article(), ["header"])
12+
13+
@spec get(T.editor_header()) :: T.html()
14+
def get(%{"eyebrowTitle" => eyebrow_title, "footerTitle" => footer_title} = data) do
15+
%{"text" => text, "level" => level} = data
16+
17+
wrapper_class = @class["wrapper"]
18+
eyebrow_class = @class["eyebrow_title"]
19+
footer_class = @class["footer_title"]
20+
21+
~s(<div class="#{wrapper_class}">
22+
<div class="#{eyebrow_class}">#{eyebrow_title}</div>
23+
<h#{level}>#{text}</h#{level}>
24+
<div class="#{footer_class}">#{footer_title}</div>
25+
</div>)
26+
end
27+
28+
def get(%{"eyebrowTitle" => eyebrow_title} = data) do
29+
%{"text" => text, "level" => level} = data
30+
31+
wrapper_class = @class["wrapper"]
32+
eyebrow_class = @class["eyebrow_title"]
33+
34+
~s(<div class="#{wrapper_class}">
35+
<div class="#{eyebrow_class}">#{eyebrow_title}</div>
36+
<h#{level}>#{text}</h#{level}>
37+
</div>)
38+
end
39+
40+
def get(%{"footerTitle" => footer_title} = data) do
41+
%{"text" => text, "level" => level} = data
42+
43+
wrapper_class = @class["wrapper"]
44+
footer_class = @class["footer_title"]
45+
46+
~s(<div class="#{wrapper_class}">
47+
<h#{level}>#{text}</h#{level}>
48+
<div class="#{footer_class}">#{footer_title}</div>
49+
</div>)
50+
end
51+
52+
def get(%{"text" => text, "level" => level}) do
53+
"<h#{level}>#{text}</h#{level}>"
54+
end
55+
end
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
defmodule Helper.Converter.EditorToHTML.Frags.List do
2+
@moduledoc """
3+
parse editor.js's block fragments, use for test too
4+
5+
see https://editorjs.io/
6+
"""
7+
alias Helper.Converter.EditorToHTML.Class
8+
alias Helper.Types, as: T
9+
10+
@class get_in(Class.article(), ["list"])
11+
12+
@spec get_item(:checklist | :unorder_list | :order_list, T.editor_list_item()) :: T.html()
13+
def get_item(:unorder_list, %{
14+
"hideLabel" => hide_label,
15+
"indent" => indent,
16+
"label" => label,
17+
"labelType" => label_type,
18+
"text" => text
19+
}) do
20+
prefix_frag = frag(:unorder_list_prefix)
21+
label_frag = if hide_label, do: "", else: frag(:label, label_type, indent, label)
22+
text_frag = frag(:text, text)
23+
24+
item_class = @class["list_item"]
25+
indent_class = @class["indent_#{indent}"]
26+
27+
~s(<div class="#{item_class} #{indent_class}">
28+
#{prefix_frag}
29+
#{label_frag}
30+
#{text_frag}
31+
</div>)
32+
end
33+
34+
def get_item(:order_list, %{
35+
"hideLabel" => hide_label,
36+
"indent" => indent,
37+
"label" => label,
38+
"labelType" => label_type,
39+
"prefixIndex" => prefix_index,
40+
"text" => text
41+
}) do
42+
prefix_frag = frag(:order_list_prefix, prefix_index)
43+
label_frag = if hide_label, do: "", else: frag(:label, label_type, indent, label)
44+
text_frag = frag(:text, text)
45+
46+
item_class = @class["list_item"]
47+
indent_class = @class["indent_#{indent}"]
48+
49+
~s(<div class="#{item_class} #{indent_class}">
50+
#{prefix_frag}
51+
#{label_frag}
52+
#{text_frag}
53+
</div>)
54+
end
55+
56+
def get_item(:checklist, %{
57+
"checked" => checked,
58+
"hideLabel" => hide_label,
59+
"indent" => indent,
60+
"label" => label,
61+
"labelType" => label_type,
62+
"text" => text
63+
}) do
64+
# local fragments
65+
checkbox_frag = frag(:checkbox, checked)
66+
label_frag = if hide_label, do: "", else: frag(:label, label_type, indent, label)
67+
text_frag = frag(:checkbox, :text, text)
68+
69+
item_class = @class["checklist_item"]
70+
indent_class = @class["indent_#{indent}"]
71+
72+
~s(<div class="#{item_class} #{indent_class}">
73+
#{checkbox_frag}
74+
#{label_frag}
75+
#{text_frag}
76+
</div>)
77+
end
78+
79+
@spec frag(:label, T.editor_list_label_type(), T.editor_list_indent(), String.t()) :: T.html()
80+
def frag(:label, label_type, indent, label) do
81+
label_class = @class["label"]
82+
label_type_class = @class["label__#{label_type}"]
83+
84+
~s(<div class="#{label_class} #{label_type_class}" data-index="#{indent}">
85+
#{label}
86+
</div>)
87+
end
88+
89+
@spec frag(:unorder_list_prefix) :: T.html()
90+
def frag(:unorder_list_prefix) do
91+
unorder_list_prefix_class = @class["unorder_list_prefix"]
92+
93+
~s(<div class="#{unorder_list_prefix_class}"></div>)
94+
end
95+
96+
@spec frag(:order_list_prefix, String.t()) :: T.html()
97+
def frag(:order_list_prefix, prefix_index) when is_binary(prefix_index) do
98+
order_list_prefix_class = @class["order_list_prefix"]
99+
100+
~s(<div class="#{order_list_prefix_class}">#{prefix_index}</div>)
101+
end
102+
103+
@spec frag(:checkbox, Boolean.t()) :: T.html()
104+
def frag(:checkbox, checked) when is_boolean(checked) do
105+
checked_svg = svg(:checked)
106+
107+
checkbox_class = @class["checklist_checkbox"]
108+
checkbox_checked_class = if checked, do: @class["checklist_checkbox_checked"], else: ""
109+
checkbox_checksign_class = @class["checklist_checksign"]
110+
111+
~s(<div class="#{checkbox_class} #{checkbox_checked_class}">
112+
<div class="#{checkbox_checksign_class}">
113+
#{checked_svg}
114+
</div>
115+
</div>)
116+
end
117+
118+
@spec frag(:text, String.t()) :: T.html()
119+
def frag(:text, text) when is_binary(text) do
120+
text_class = @class["text"]
121+
122+
~s(<div class="#{text_class}">
123+
#{text}
124+
</div>)
125+
end
126+
127+
@spec frag(:checkbox, :text, String.t()) :: T.html()
128+
def frag(:checkbox, :text, text) do
129+
text_class = @class["checklist_text"]
130+
131+
~s(<div class="#{text_class}">
132+
#{text}
133+
</div>)
134+
end
135+
136+
defp svg(type) do
137+
# workarround for https://github.com/rrrene/html_sanitize_ex/issues/48
138+
svg_frag(type) |> String.replace(" viewBox=\"", " viewbox=\"")
139+
end
140+
141+
defp svg_frag(:checked) do
142+
~s(<svg t="1592049095081" width="20px" height="20px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9783"><path d="M853.333333 256L384 725.333333l-213.333333-213.333333" p-id="9784"></path></svg>)
143+
end
144+
end
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!doctype html>
2+
3+
<html lang="en">
4+
<head>
5+
<meta charset="utf-8">
6+
7+
<title>The HTML5 Herald</title>
8+
<meta name="description" content="The HTML5 Herald">
9+
<meta name="author" content="SitePoint">
10+
11+
<link rel="stylesheet" href="./styles.css?v=1.0">
12+
<div id="article"></div>
13+
</head>
14+
15+
<body>
16+
<script src="./script.js"></script>
17+
</body>
18+
</html>

lib/helper/converter/editor_to_html/frontend_test/script.js

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)