Skip to content

Commit f3b63e9

Browse files
committed
Website: fix markdown rendering issue (slug & newlines)
1 parent e325cfd commit f3b63e9

2 files changed

Lines changed: 186 additions & 84 deletions

File tree

‎website/src/components/JsonBodyRenderer.re‎

Lines changed: 102 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
open Belt;
12
open ReactNative;
23

34
type htmlProps = {
@@ -30,14 +31,14 @@ let rec jsTreeToReason = (jsChild: t) =>
3031
let props = jsChild##p;
3132
let children =
3233
switch (Js.Undefined.toOption(jsChild##c)) {
33-
| Some(c) => c->Belt.Array.map(jsTreeToReason)
34+
| Some(c) => c->Array.map(jsTreeToReason)
3435
| None => [||]
3536
};
3637
Element(tag, props, children);
3738
| _ => Empty
3839
};
3940

40-
let stringMapPartial = (f, s) => {
41+
let stringMapPartial = (s, f) => {
4142
let b = Buffer.create(String.length(s));
4243
s
4344
|> String.iter(c =>
@@ -49,76 +50,126 @@ let stringMapPartial = (f, s) => {
4950
b->Buffer.contents;
5051
};
5152

52-
let lastSiblingHasLineBreaking = ref(false);
53+
// let cleanupNewlines = s =>
54+
// s->stringMapPartial(char => char === '\n' ? None : Some(char));
55+
let cleanupNewlines = s =>
56+
s->stringMapPartial(char => char === '\n' ? Some(' ') : Some(char));
5357

54-
let cleanupNewlines = (string, siblingHasLineBreaking) =>
55-
stringMapPartial(
56-
char =>
57-
char === '\n' && siblingHasLineBreaking
58-
? None : Some(char === '\n' ? ' ' : char),
59-
string,
60-
);
58+
let optionalCleanString = (s, keepNewlines) => {
59+
let sc = keepNewlines ? s : cleanupNewlines(s)->Js.String.trim;
60+
sc === "" ? None : Some(sc);
61+
};
62+
63+
let keepNewlines = ref(false);
6164

62-
let cleanupNewlinesPre = (string, siblingHasLineBreaking) =>
63-
stringMapPartial(
64-
char => char === '\n' && siblingHasLineBreaking ? None : Some(char),
65-
string,
66-
);
65+
let inlineBreakIfParentIsInline = parentTag => {
66+
switch (parentTag) {
67+
| "li" => <Html.Br />
68+
| _ => React.null
69+
};
70+
};
6771

68-
let rec renderChild = (parentTag, index: int, child) => {
69-
/* @todo we can do better */
72+
let rec renderChild = (~keepNewlines=false, parentTag, index: int, child) => {
73+
/* @todo we can do better for the key */
7074
let key = index->string_of_int;
71-
let siblingHasLineBreaking = lastSiblingHasLineBreaking^;
72-
lastSiblingHasLineBreaking := false;
73-
let renderChildren = (parentTag, children) =>
74-
if (children->Belt.Array.length == 0) {
75-
React.null;
76-
} else {
77-
children->Belt.Array.mapWithIndex(renderChild(parentTag))->React.array;
78-
};
75+
76+
let renderChildren = (~keepNewlines, parentTag, children) =>
77+
children->Array.length > 0
78+
? children
79+
->Array.mapWithIndex(renderChild(~keepNewlines, parentTag))
80+
->React.array
81+
: React.null;
82+
7983
switch (child) {
8084
| String(string) =>
8185
switch (parentTag) {
82-
| "ul" => React.null
8386
| "ol" => React.null
87+
| "ul" => React.null
8488
| "li" =>
85-
<Html.Text>
86-
{cleanupNewlines(string, siblingHasLineBreaking)->React.string}
87-
</Html.Text>
88-
| "code" =>
89-
cleanupNewlinesPre(string, siblingHasLineBreaking)->React.string
90-
| _ => cleanupNewlines(string, siblingHasLineBreaking)->React.string
89+
string
90+
->optionalCleanString(keepNewlines)
91+
->Option.map(s => <Html.TextNode> s->React.string </Html.TextNode>)
92+
->Option.getWithDefault(React.null)
93+
| _ =>
94+
string
95+
->optionalCleanString(keepNewlines)
96+
->Option.map(React.string)
97+
->Option.getWithDefault(React.null)
9198
}
9299
| Element(tag, props, children) =>
93100
switch (tag) {
94101
/* html tags */
95102
| "a" =>
96-
<Html.A key href=props##href> {renderChildren(tag, children)} </Html.A>
97-
| "h1" => <Html.H1 key> {renderChildren(tag, children)} </Html.H1>
98-
| "h2" => <Html.H2 key> {renderChildren(tag, children)} </Html.H2>
99-
| "h3" => <Html.H3 key> {renderChildren(tag, children)} </Html.H3>
100-
| "h4" => <Html.H4 key> {renderChildren(tag, children)} </Html.H4>
101-
| "h5" => <Html.H5 key> {renderChildren(tag, children)} </Html.H5>
102-
| "h6" => <Html.H6 key> {renderChildren(tag, children)} </Html.H6>
103-
| "p" => <Html.P key> {renderChildren(tag, children)} </Html.P>
104-
| "ul" => <Html.Ul key> {renderChildren(tag, children)} </Html.Ul>
105-
| "li" => <Html.Li key> {renderChildren(tag, children)} </Html.Li>
103+
<Html.A key props>
104+
{renderChildren(~keepNewlines, tag, children)}
105+
</Html.A>
106+
| "h1" =>
107+
<Html.H1 key props>
108+
{renderChildren(~keepNewlines, tag, children)}
109+
</Html.H1>
110+
| "h2" =>
111+
<Html.H2 key props>
112+
{renderChildren(~keepNewlines, tag, children)}
113+
</Html.H2>
114+
| "h3" =>
115+
<Html.H3 key props>
116+
{renderChildren(~keepNewlines, tag, children)}
117+
</Html.H3>
118+
| "h4" =>
119+
<Html.H4 key props>
120+
{renderChildren(~keepNewlines, tag, children)}
121+
</Html.H4>
122+
| "h5" =>
123+
<Html.H5 key props>
124+
{renderChildren(~keepNewlines, tag, children)}
125+
</Html.H5>
126+
| "h6" =>
127+
<Html.H6 key props>
128+
{renderChildren(~keepNewlines, tag, children)}
129+
</Html.H6>
130+
| "p" =>
131+
<Html.P key props>
132+
{renderChildren(~keepNewlines, tag, children)}
133+
</Html.P>
134+
| "ol" =>
135+
<>
136+
{inlineBreakIfParentIsInline(parentTag)}
137+
<Html.Ul key props>
138+
{renderChildren(~keepNewlines, tag, children)}
139+
</Html.Ul>
140+
</>
141+
| "ul" =>
142+
<>
143+
{inlineBreakIfParentIsInline(parentTag)}
144+
<Html.Ul key props>
145+
{renderChildren(~keepNewlines, tag, children)}
146+
</Html.Ul>
147+
</>
148+
| "li" =>
149+
<Html.Li key props>
150+
{renderChildren(~keepNewlines, tag, children)}
151+
</Html.Li>
106152
| "blockquote" =>
107-
<Html.BlockQuote key> {renderChildren(tag, children)} </Html.BlockQuote>
153+
<Html.BlockQuote key props>
154+
{renderChildren(~keepNewlines, tag, children)}
155+
</Html.BlockQuote>
108156
| "pre" =>
109-
<Html.Pre key props> {renderChildren(tag, children)} </Html.Pre>
157+
<Html.Pre key props>
158+
{renderChildren(~keepNewlines=true, tag, children)}
159+
</Html.Pre>
110160
| "code" =>
111161
switch (parentTag) {
112162
| "pre" =>
113163
<Html.CodeBlock key props>
114-
{renderChildren(tag, children)}
164+
{renderChildren(~keepNewlines, tag, children)}
115165
</Html.CodeBlock>
116-
| _ => <Html.Code key> {renderChildren(tag, children)} </Html.Code>
166+
| _ =>
167+
<Html.Code key>
168+
{renderChildren(~keepNewlines, tag, children)}
169+
</Html.Code>
117170
}
118-
| "br" =>
119-
lastSiblingHasLineBreaking := true;
120-
<Html.Br key />;
121-
| "hr" => <Html.Hr key />
171+
| "br" => <Html.Br key props />
172+
| "hr" => <Html.Hr key props />
122173
| _ =>
123174
ReactDOMRe.createElement(
124175
tag,
@@ -128,7 +179,7 @@ let rec renderChild = (parentTag, index: int, child) => {
128179
->Js.Obj.assign({"key": key})
129180
->Js.Obj.assign(props),
130181
),
131-
[|renderChildren(tag, children)|],
182+
[|renderChildren(~keepNewlines, tag, children)|],
132183
)
133184
}
134185
| Empty => React.null

0 commit comments

Comments
 (0)