Skip to content

Commit 2b6516c

Browse files
committed
feat: Support markdown.parser.type attr in md
1 parent d2d4455 commit 2b6516c

File tree

6 files changed

+161
-36
lines changed

6 files changed

+161
-36
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package org.apache.zeppelin.markdown;
2+
3+
import org.markdown4j.Markdown4jProcessor;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
7+
import java.io.IOException;
8+
9+
/** Markdown Parser using markdown4j processor . */
10+
public class Markdown4jParser implements MarkdownParser {
11+
private final Logger logger = LoggerFactory.getLogger(Markdown4jParser.class);
12+
13+
private Markdown4jProcessor processor;
14+
15+
public Markdown4jParser() {
16+
processor = new Markdown4jProcessor();
17+
}
18+
19+
@Override
20+
public String render(String markdownText) {
21+
String html = "";
22+
23+
try {
24+
html = processor.process(markdownText);
25+
} catch (IOException e) {
26+
logger.error("Cannot parse markdown text to HTML using markdown4j", e);
27+
}
28+
29+
return html;
30+
}
31+
}

markdown/src/main/java/org/apache/zeppelin/markdown/MarkdownInterpreter.java

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import org.apache.zeppelin.interpreter.Interpreter;
2424
import org.apache.zeppelin.interpreter.InterpreterContext;
25+
import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
2526
import org.apache.zeppelin.interpreter.InterpreterResult;
2627
import org.apache.zeppelin.interpreter.InterpreterResult.Code;
2728
import org.apache.zeppelin.interpreter.InterpreterUtils;
@@ -33,17 +34,50 @@
3334

3435
/** MarkdownInterpreter interpreter for Zeppelin. */
3536
public class MarkdownInterpreter extends Interpreter {
36-
private final Logger logger = LoggerFactory.getLogger(MarkdownInterpreter.class);
37+
private static final Logger LOGGER = LoggerFactory.getLogger(MarkdownInterpreter.class);
3738

3839
private MarkdownParser parser;
3940

41+
/** Markdown Parser Type. */
42+
public enum MarkdownParserType {
43+
PEGDOWN {
44+
@Override
45+
public String toString() {
46+
return PARSER_TYPE_PEGDOWN;
47+
}
48+
},
49+
50+
MARKDOWN4j {
51+
@Override
52+
public String toString() {
53+
return PARSER_TYPE_MARKDOWN4J;
54+
}
55+
}
56+
}
57+
58+
public static final String MARKDOWN_PARSER_TYPE = "markdown.parser.type";
59+
public static final String PARSER_TYPE_PEGDOWN = "pegdown";
60+
public static final String PARSER_TYPE_MARKDOWN4J = "markdown4j";
61+
4062
public MarkdownInterpreter(Properties property) {
4163
super(property);
4264
}
4365

66+
public static MarkdownParser createMarkdownParser(String parserType) {
67+
LOGGER.debug("Creating " + parserType + " markdown interpreter");
68+
69+
if (MarkdownParserType.PEGDOWN.toString().equals(parserType)) {
70+
return new PegdownParser();
71+
} else {
72+
/** default parser. */
73+
return new Markdown4jParser();
74+
}
75+
}
76+
4477
@Override
4578
public void open() {
46-
parser = new PegdownParser();
79+
String parserType = getProperty(MARKDOWN_PARSER_TYPE);
80+
parser = createMarkdownParser(parserType);
4781
}
4882

4983
@Override
@@ -56,7 +90,7 @@ public InterpreterResult interpret(String markdownText, InterpreterContext inter
5690
try {
5791
html = parser.render(markdownText);
5892
} catch (Exception e) {
59-
logger.error("Exception in MarkdownInterpreter while interpret ", e);
93+
LOGGER.error("Exception in MarkdownInterpreter while interpret ", e);
6094
return new InterpreterResult(Code.ERROR, InterpreterUtils.getMostRelevantMessage(e));
6195
}
6296

markdown/src/main/java/org/apache/zeppelin/markdown/PegdownParser.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
import org.slf4j.Logger;
66
import org.slf4j.LoggerFactory;
77

8-
/** Pegdown Markdown Parser. */
8+
/** Markdown Parser using pegdown processor. */
99
public class PegdownParser implements MarkdownParser {
10-
private PegDownProcessor processor;
11-
1210
private final Logger logger = LoggerFactory.getLogger(PegdownParser.class);
1311

12+
private PegDownProcessor processor;
13+
1414
public PegdownParser() {
1515
int pegdownOptions = Extensions.ALL_WITH_OPTIONALS - Extensions.ANCHORLINKS;
1616
int parsingTimeoutAsMillis = 5000;
@@ -23,17 +23,19 @@ public String render(String markdownText) {
2323

2424
try {
2525
String parsed = processor.markdownToHtml(markdownText);
26-
if (null == parsed) throw new RuntimeException("Cannot parse markdown syntax string to HTML");
26+
if (null == parsed) {
27+
throw new RuntimeException("Cannot parse markdown text to HTML using pegdown");
28+
}
2729

2830
html = wrapWithMarkdownClassDiv(parsed);
2931
} catch (RuntimeException e) {
30-
logger.error("Failed to parsed markdown text", e);
32+
logger.error("Cannot parse markdown text to HTML using pegdown", e);
3133
}
3234

3335
return html;
3436
}
3537

36-
/** wrap with markdown class div to styling DOM using css */
38+
/** wrap with markdown class div to styling DOM using css. */
3739
public static String wrapWithMarkdownClassDiv(String html) {
3840
return new StringBuilder()
3941
.append("<div class=\"markdown-body\">\n")

markdown/src/main/resources/interpreter-setting.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@
22
{
33
"group": "md",
44
"name": "md",
5-
"className": "org.apache.zeppelin.markdown.Markdown",
6-
"properties": null
5+
"className": "org.apache.zeppelin.markdown.MarkdownInterpreter",
6+
"properties": {
7+
"markdown.parser.type": {
8+
"envName": "MARKDOWN_PARSER_TYPE",
9+
"propertyName": "markdown.parser.type",
10+
"defaultValue": "markdown4j",
11+
"description": "Markdown Parser Type. Available values: markdown4j, pegdown. Default = markdown4j"
12+
}
13+
}
714
}
815
]
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.zeppelin.markdown;
19+
20+
import org.apache.zeppelin.interpreter.InterpreterResult;
21+
import org.junit.After;
22+
import org.junit.Before;
23+
import org.junit.Test;
24+
25+
import java.util.Properties;
26+
27+
import static org.junit.Assert.assertEquals;
28+
29+
public class Markdown4jParserTest {
30+
31+
MarkdownInterpreter md;
32+
33+
@Before
34+
public void setUp() throws Exception {
35+
Properties props = new Properties();
36+
props.put(MarkdownInterpreter.MARKDOWN_PARSER_TYPE, MarkdownInterpreter.PARSER_TYPE_MARKDOWN4J);
37+
md = new MarkdownInterpreter(props);
38+
md.open();
39+
}
40+
41+
@After
42+
public void tearDown() throws Exception {
43+
md.close();
44+
}
45+
46+
@Test
47+
public void testStrikethrough() {
48+
InterpreterResult result = md.interpret("This is ~~deleted~~ text", null);
49+
assertEquals("<p>This is <s>deleted</s> text</p>\n", result.message());
50+
}
51+
}

markdown/src/test/java/org/apache/zeppelin/markdown/PegdownParserTest.java

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,64 +29,65 @@
2929

3030
public class PegdownParserTest {
3131

32-
MarkdownInterpreter pegdownInterpreter;
32+
MarkdownInterpreter md;
3333

3434
@Before
3535
public void setUp() throws Exception {
36-
pegdownInterpreter = new MarkdownInterpreter(new Properties());
37-
pegdownInterpreter.open();
36+
Properties props = new Properties();
37+
props.put(MarkdownInterpreter.MARKDOWN_PARSER_TYPE, MarkdownInterpreter.PARSER_TYPE_PEGDOWN);
38+
md = new MarkdownInterpreter(props);
39+
md.open();
3840
}
3941

4042
@After
4143
public void tearDown() throws Exception {
42-
pegdownInterpreter.close();
44+
md.close();
4345
}
4446

4547
@Test
4648
public void testHeader() {
47-
InterpreterResult r1 = pegdownInterpreter.interpret("# H1", null);
49+
InterpreterResult r1 = md.interpret("# H1", null);
4850
assertEquals(wrapWithMarkdownClassDiv("<h1>H1</h1>"), r1.message());
4951

50-
InterpreterResult r2 = pegdownInterpreter.interpret("## H2", null);
52+
InterpreterResult r2 = md.interpret("## H2", null);
5153
assertEquals(wrapWithMarkdownClassDiv("<h2>H2</h2>"), r2.message());
5254

53-
InterpreterResult r3 = pegdownInterpreter.interpret("### H3", null);
55+
InterpreterResult r3 = md.interpret("### H3", null);
5456
assertEquals(wrapWithMarkdownClassDiv("<h3>H3</h3>"), r3.message());
5557

56-
InterpreterResult r4 = pegdownInterpreter.interpret("#### H4", null);
58+
InterpreterResult r4 = md.interpret("#### H4", null);
5759
assertEquals(wrapWithMarkdownClassDiv("<h4>H4</h4>"), r4.message());
5860

59-
InterpreterResult r5 = pegdownInterpreter.interpret("##### H5", null);
61+
InterpreterResult r5 = md.interpret("##### H5", null);
6062
assertEquals(wrapWithMarkdownClassDiv("<h5>H5</h5>"), r5.message());
6163

62-
InterpreterResult r6 = pegdownInterpreter.interpret("###### H6", null);
64+
InterpreterResult r6 = md.interpret("###### H6", null);
6365
assertEquals(wrapWithMarkdownClassDiv("<h6>H6</h6>"), r6.message());
6466

65-
InterpreterResult r7 = pegdownInterpreter.interpret("Alt-H1\n" + "======", null);
67+
InterpreterResult r7 = md.interpret("Alt-H1\n" + "======", null);
6668
assertEquals(wrapWithMarkdownClassDiv("<h1>Alt-H1</h1>"), r7.message());
6769

68-
InterpreterResult r8 = pegdownInterpreter.interpret("Alt-H2\n" + "------", null);
70+
InterpreterResult r8 = md.interpret("Alt-H2\n" + "------", null);
6971
assertEquals(wrapWithMarkdownClassDiv("<h2>Alt-H2</h2>"), r8.message());
7072
}
7173

7274
@Test
7375
public void testStrikethrough() {
74-
InterpreterResult result = pegdownInterpreter.interpret("This is ~~deleted~~ text", null);
76+
InterpreterResult result = md.interpret("This is ~~deleted~~ text", null);
7577
assertEquals(
7678
wrapWithMarkdownClassDiv("<p>This is <del>deleted</del> text</p>"), result.message());
7779
}
7880

7981
@Test
8082
public void testItalics() {
81-
InterpreterResult result = pegdownInterpreter.interpret("This is *italics* text", null);
83+
InterpreterResult result = md.interpret("This is *italics* text", null);
8284
assertEquals(
8385
wrapWithMarkdownClassDiv("<p>This is <em>italics</em> text</p>"), result.message());
8486
}
8587

8688
@Test
8789
public void testStrongEmphasis() {
88-
InterpreterResult result =
89-
pegdownInterpreter.interpret("This is **strong emphasis** text", null);
90+
InterpreterResult result = md.interpret("This is **strong emphasis** text", null);
9091
assertEquals(
9192
wrapWithMarkdownClassDiv("<p>This is <strong>strong emphasis</strong> text</p>"),
9293
result.message());
@@ -108,7 +109,7 @@ public void testOrderedList() {
108109
.append("</ol>")
109110
.toString();
110111

111-
InterpreterResult result = pegdownInterpreter.interpret(input, null);
112+
InterpreterResult result = md.interpret(input, null);
112113
assertEquals(wrapWithMarkdownClassDiv(expected), result.message());
113114
}
114115

@@ -130,7 +131,7 @@ public void testUnorderedList() {
130131
.append("</ul>")
131132
.toString();
132133

133-
InterpreterResult result = pegdownInterpreter.interpret(input, null);
134+
InterpreterResult result = md.interpret(input, null);
134135
assertEquals(wrapWithMarkdownClassDiv(expected), result.message());
135136
}
136137

@@ -181,14 +182,13 @@ public void testLinks() {
181182
.append("<p>Some text to show that the reference links can follow later.</p>")
182183
.toString();
183184

184-
InterpreterResult result = pegdownInterpreter.interpret(input, null);
185+
InterpreterResult result = md.interpret(input, null);
185186
assertEquals(wrapWithMarkdownClassDiv(expected), result.message());
186187
}
187188

188189
@Test
189190
public void testInlineCode() {
190-
InterpreterResult result =
191-
pegdownInterpreter.interpret("Inline `code` has `back-ticks around` it.", null);
191+
InterpreterResult result = md.interpret("Inline `code` has `back-ticks around` it.", null);
192192
assertEquals(
193193
wrapWithMarkdownClassDiv(
194194
"<p>Inline <code>code</code> has <code>back-ticks around</code> it.</p>"),
@@ -198,7 +198,7 @@ public void testInlineCode() {
198198
@Test
199199
public void testBlockQuotes() {
200200
InterpreterResult r1 =
201-
pegdownInterpreter.interpret(
201+
md.interpret(
202202
"> Blockquotes are very handy in email to emulate reply text.\n"
203203
+ "> This line is part of the same quote.",
204204
null);
@@ -210,7 +210,7 @@ public void testBlockQuotes() {
210210
r1.message());
211211

212212
InterpreterResult r2 =
213-
pegdownInterpreter.interpret(
213+
md.interpret(
214214
"> This is a very long line that will still be quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can *put* **MarkdownInterpreter** into a blockquote. ",
215215
null);
216216
assertEquals(
@@ -256,7 +256,7 @@ public void testSimpleTable() {
256256
.append("</table>")
257257
.toString();
258258

259-
InterpreterResult result = pegdownInterpreter.interpret(input, null);
259+
InterpreterResult result = md.interpret(input, null);
260260
assertEquals(wrapWithMarkdownClassDiv(expected), result.message());
261261
}
262262

@@ -296,7 +296,7 @@ public void testAlignedTable() {
296296
.append("</table>")
297297
.toString();
298298

299-
InterpreterResult result = pegdownInterpreter.interpret(input, null);
299+
InterpreterResult result = md.interpret(input, null);
300300
assertEquals(wrapWithMarkdownClassDiv(expected), result.message());
301301
}
302302
}

0 commit comments

Comments
 (0)