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

Commit d2d1d0d

Browse files
committed
refactor(editor): basic table export done
1 parent 3e529d5 commit d2d1d0d

File tree

10 files changed

+268
-8
lines changed

10 files changed

+268
-8
lines changed

lib/helper/converter/editor_to_html/class.ex

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ defmodule Helper.Converter.EditorToHTML.Class do
4343
"indent_1" => "list-indent-1",
4444
"indent_2" => "list-indent-2",
4545
"indent_3" => "list-indent-3"
46+
},
47+
"table" => %{
48+
"wrapper" => "table-wrapper",
49+
"cell" => "table-cell",
50+
"align_center" => "align-center",
51+
"align_left" => "align-left",
52+
"align_right" => "align-right"
4653
}
4754
}
4855
end
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
defmodule Helper.Converter.EditorToHTML.Frags.Table 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(), ["table"])
11+
12+
def get_row(group_items) do
13+
tr_content =
14+
Enum.reduce(group_items, "", fn item, acc ->
15+
acc <> frag(:td, item)
16+
end)
17+
18+
~s(<tr>#{tr_content}</tr>)
19+
end
20+
21+
def frag(:td, item) do
22+
%{
23+
"align" => align,
24+
# "isZebraStripe" => isZebraStripe,
25+
"text" => text
26+
} = item
27+
28+
IO.inspect(Map.has_key?(item, "width"), label: "the width")
29+
30+
cell_class = @class["cell"]
31+
align_class = get_align_class(align)
32+
33+
case Map.has_key?(item, "width") do
34+
true ->
35+
style = ~s(width: #{Map.get(item, "width")})
36+
~s(<td style="#{style}"><div class="#{cell_class} #{align_class}">#{text}</div></td>)
37+
38+
false ->
39+
~s(<td><div class="#{cell_class} #{align_class}">#{text}</div></td>)
40+
end
41+
end
42+
43+
defp get_align_class("center"), do: @class["align_center"]
44+
defp get_align_class("right"), do: @class["align_right"]
45+
defp get_align_class(_), do: @class["align_left"]
46+
end

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

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

lib/helper/converter/editor_to_html/frontend_test/styles.css

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,65 @@ body {
204204
}
205205

206206
/* list block end */
207+
208+
/* table block */
209+
.article-viewer-wrapper table {
210+
width: 100%;
211+
border-collapse: collapse;
212+
table-layout: fixed;
213+
border-spacing: 0;
214+
box-sizing: border-box;
215+
216+
display: table;
217+
text-indent: initial;
218+
white-space: normal;
219+
line-height: normal;
220+
font-weight: normal;
221+
font-size: medium;
222+
font-style: normal;
223+
color: -internal-quirk-inherit;
224+
text-align: start;
225+
border-color: grey;
226+
font-variant: normal;
227+
}
228+
229+
.article-viewer-wrapper tbody {
230+
display: table-row-group;
231+
vertical-align: middle;
232+
border-color: inherit;
233+
}
234+
235+
.article-viewer-wrapper tr {
236+
display: table-row;
237+
vertical-align: inherit;
238+
border-color: inherit;
239+
}
240+
241+
.article-viewer-wrapper table tbody tr th,
242+
table td {
243+
position: relative;
244+
border: 1px solid #dbdbe2;
245+
font-size: 15px;
246+
}
247+
248+
td {
249+
display: table-cell;
250+
vertical-align: inherit;
251+
}
252+
253+
.article-viewer-wrapper table .table-cell {
254+
padding: 12px 10px;
255+
vertical-align: top;
256+
}
257+
258+
.article-viewer-wrapper table .align-left {
259+
text-align: left;
260+
}
261+
.article-viewer-wrapper table .align-center {
262+
text-align: center;
263+
}
264+
.article-viewer-wrapper table .align-right {
265+
text-align: right;
266+
}
267+
268+
/* table block end */

lib/helper/converter/editor_to_html/index.ex

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,27 @@ defmodule Helper.Converter.EditorToHTML do
6565
~s(<div class="#{list_wrapper_class}">#{items_content}</div>)
6666
end
6767

68+
defp parse_block(%{"type" => "table", "data" => data}) do
69+
%{"items" => items, "columnCount" => column_count} = data
70+
71+
groupped_items = Enum.split(items, column_count) |> Tuple.to_list()
72+
73+
rows_content =
74+
Enum.reduce(groupped_items, "", fn group, acc ->
75+
acc <> Frags.Table.get_row(group)
76+
end)
77+
78+
table_wrapper_class = get_in(@root_class, ["table", "wrapper"])
79+
80+
~s(<div class="#{table_wrapper_class}">
81+
<table>
82+
<tbody>
83+
#{rows_content}
84+
</tbody>
85+
</table>
86+
</div>)
87+
end
88+
6889
# defp parse_block(%{"type" => "image", "data" => data}) do
6990
# url = get_in(data, ["file", "url"])
7091

lib/helper/converter/editor_to_html/validator/editor_schema.ex

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ defmodule Helper.Converter.EditorToHTML.Validator.EditorSchema do
99
@valid_list_label_type ["green", "red", "warn", "default"]
1010
@valid_list_indent [0, 1, 2, 3]
1111

12+
# table
13+
@valid_table_align ["left", "center", "right"]
14+
1215
def get("editor") do
1316
%{
1417
"time" => [:number],
@@ -43,6 +46,18 @@ defmodule Helper.Converter.EditorToHTML.Validator.EditorSchema do
4346
]
4447
end
4548

49+
def get("table") do
50+
[
51+
parent: %{"columnCount" => [:number], "items" => [:list]},
52+
item: %{
53+
"text" => [:string],
54+
"align" => [enum: @valid_table_align],
55+
"isZebraStripe" => [:boolean],
56+
"width" => [:string, required: false]
57+
}
58+
]
59+
end
60+
4661
def get(_) do
4762
%{}
4863
end

lib/helper/converter/editor_to_html/validator/index.ex

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ defmodule Helper.Converter.EditorToHTML.Validator do
88

99
# blocks with no children items
1010
@simple_blocks ["header", "paragraph"]
11-
# blocks with "mode" and "items" fields
12-
@complex_blocks ["list"]
11+
# blocks with "items" fields
12+
@complex_blocks ["list", "table"]
1313

14+
@spec is_valid(map) :: {:error, map} | {:ok, :pass}
1415
def is_valid(data) when is_map(data) do
1516
with {:ok, _} <- validate_editor_fmt(data),
1617
blocks <- Map.get(data, "blocks") do
@@ -82,7 +83,10 @@ defmodule Helper.Converter.EditorToHTML.Validator do
8283

8384
defp validate_with(block, parent_schema, item_schema, data) do
8485
with {:ok, _} <- validate_with(block, parent_schema, data),
85-
%{"mode" => mode, "items" => items} <- data do
86+
%{"items" => items} <- data do
87+
# most block with items will have mode field, if not, just ignore
88+
mode = Map.get(data, "mode", "")
89+
8690
Enum.each(items, fn item ->
8791
validate_with("#{block}(#{mode})", item_schema, item)
8892
end)

lib/helper/converter/html_sanitizer.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ defmodule Helper.Converter.HtmlSanitizer do
3838
Meta.allow_tag_with_these_attributes("ol", ["class"])
3939
Meta.allow_tag_with_these_attributes("li", ["class"])
4040

41+
# table
42+
Meta.allow_tag_with_these_attributes("table", [])
43+
Meta.allow_tag_with_these_attributes("tbody", [])
44+
Meta.allow_tag_with_these_attributes("tr", [])
45+
Meta.allow_tag_with_these_attributes("td", ["style"])
46+
4147
Meta.allow_tag_with_these_attributes("svg", [
4248
"t",
4349
"p-id",

test/helper/converter/editor_to_html_test/header_test.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ defmodule GroupherServer.Test.Helper.Converter.EditorToHTML.Header do
7171
],
7272
"version" => "2.15.0"
7373
}
74-
@tag :wip2
74+
@tag :wip
7575
test "full header parse should work" do
7676
{:ok, editor_string} = Jason.encode(@editor_json)
7777
{:ok, converted} = Parser.to_html(editor_string)
@@ -88,7 +88,7 @@ defmodule GroupherServer.Test.Helper.Converter.EditorToHTML.Header do
8888
"time" => 1_567_250_876_713,
8989
"version" => "2.15.0"
9090
}
91-
@tag :wip2
91+
@tag :wip
9292
test "optional field should valid properly" do
9393
json =
9494
Map.merge(@editor_json, %{
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
defmodule GroupherServer.Test.Helper.Converter.EditorToHTML.Table do
2+
@moduledoc false
3+
4+
use GroupherServerWeb.ConnCase, async: true
5+
6+
alias Helper.Converter.EditorToHTML, as: Parser
7+
alias Helper.Converter.EditorToHTML.Class
8+
alias Helper.Utils
9+
10+
@root_class Class.article()
11+
@class get_in(@root_class, ["list"])
12+
13+
describe "[table block unit]" do
14+
defp set_items(column_count, items) do
15+
editor_json = %{
16+
"time" => 1_567_250_876_713,
17+
"blocks" => [
18+
%{
19+
"type" => "table",
20+
"data" => %{
21+
"columnCount" => column_count,
22+
"items" => items
23+
}
24+
}
25+
],
26+
"version" => "2.15.0"
27+
}
28+
end
29+
30+
@tag :wip2
31+
test "basic table parse should work" do
32+
editor_json =
33+
set_items(4, [
34+
%{
35+
"align" => "left",
36+
"isZebraStripe" => false,
37+
"text" => "cell 0"
38+
},
39+
%{
40+
"align" => "center",
41+
"isZebraStripe" => false,
42+
"text" => "cell 1",
43+
"width" => "180px"
44+
},
45+
%{
46+
"align" => "right",
47+
"isZebraStripe" => false,
48+
"text" => "cell 2"
49+
},
50+
%{
51+
"align" => "left",
52+
"isZebraStripe" => false,
53+
"text" => "cell 3"
54+
},
55+
%{
56+
"align" => "left",
57+
"isZebraStripe" => false,
58+
"text" => "cell 4"
59+
},
60+
%{
61+
"align" => "left",
62+
"isZebraStripe" => false,
63+
"text" => "cell 5"
64+
},
65+
%{
66+
"align" => "left",
67+
"isZebraStripe" => false,
68+
"text" => ""
69+
}
70+
])
71+
72+
{:ok, editor_string} = Jason.encode(editor_json)
73+
{:ok, converted} = Parser.to_html(editor_string)
74+
75+
IO.inspect(converted, label: "table >>")
76+
77+
# unorder_list_prefix_class = @class["unorder_list_prefix"]
78+
# assert Utils.str_occurence(converted, unorder_list_prefix_class) == 3
79+
end
80+
81+
# @tag :wip
82+
# test "invalid list mode parse should raise error message" do
83+
# editor_json = set_items("invalid-mode", [])
84+
# {:ok, editor_string} = Jason.encode(editor_json)
85+
# {:error, err_msg} = Parser.to_html(editor_string)
86+
87+
# assert err_msg == [
88+
# %{
89+
# block: "list",
90+
# field: "mode",
91+
# message: "should be: checklist | order_list | unorder_list"
92+
# }
93+
# ]
94+
# end
95+
end
96+
end

0 commit comments

Comments
 (0)