feat: Support markdown.parser.type attr in md

This commit is contained in:
1ambda 2016-09-03 01:49:06 +09:00
parent d2d4455118
commit 2b6516cad3
6 changed files with 161 additions and 36 deletions

View file

@ -0,0 +1,31 @@
package org.apache.zeppelin.markdown;
import org.markdown4j.Markdown4jProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
/** Markdown Parser using markdown4j processor . */
public class Markdown4jParser implements MarkdownParser {
private final Logger logger = LoggerFactory.getLogger(Markdown4jParser.class);
private Markdown4jProcessor processor;
public Markdown4jParser() {
processor = new Markdown4jProcessor();
}
@Override
public String render(String markdownText) {
String html = "";
try {
html = processor.process(markdownText);
} catch (IOException e) {
logger.error("Cannot parse markdown text to HTML using markdown4j", e);
}
return html;
}
}

View file

@ -22,6 +22,7 @@ import java.util.Properties;
import org.apache.zeppelin.interpreter.Interpreter;
import org.apache.zeppelin.interpreter.InterpreterContext;
import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
import org.apache.zeppelin.interpreter.InterpreterResult;
import org.apache.zeppelin.interpreter.InterpreterResult.Code;
import org.apache.zeppelin.interpreter.InterpreterUtils;
@ -33,17 +34,50 @@ import org.slf4j.LoggerFactory;
/** MarkdownInterpreter interpreter for Zeppelin. */
public class MarkdownInterpreter extends Interpreter {
private final Logger logger = LoggerFactory.getLogger(MarkdownInterpreter.class);
private static final Logger LOGGER = LoggerFactory.getLogger(MarkdownInterpreter.class);
private MarkdownParser parser;
/** Markdown Parser Type. */
public enum MarkdownParserType {
PEGDOWN {
@Override
public String toString() {
return PARSER_TYPE_PEGDOWN;
}
},
MARKDOWN4j {
@Override
public String toString() {
return PARSER_TYPE_MARKDOWN4J;
}
}
}
public static final String MARKDOWN_PARSER_TYPE = "markdown.parser.type";
public static final String PARSER_TYPE_PEGDOWN = "pegdown";
public static final String PARSER_TYPE_MARKDOWN4J = "markdown4j";
public MarkdownInterpreter(Properties property) {
super(property);
}
public static MarkdownParser createMarkdownParser(String parserType) {
LOGGER.debug("Creating " + parserType + " markdown interpreter");
if (MarkdownParserType.PEGDOWN.toString().equals(parserType)) {
return new PegdownParser();
} else {
/** default parser. */
return new Markdown4jParser();
}
}
@Override
public void open() {
parser = new PegdownParser();
String parserType = getProperty(MARKDOWN_PARSER_TYPE);
parser = createMarkdownParser(parserType);
}
@Override
@ -56,7 +90,7 @@ public class MarkdownInterpreter extends Interpreter {
try {
html = parser.render(markdownText);
} catch (Exception e) {
logger.error("Exception in MarkdownInterpreter while interpret ", e);
LOGGER.error("Exception in MarkdownInterpreter while interpret ", e);
return new InterpreterResult(Code.ERROR, InterpreterUtils.getMostRelevantMessage(e));
}

View file

@ -5,12 +5,12 @@ import org.pegdown.PegDownProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Pegdown Markdown Parser. */
/** Markdown Parser using pegdown processor. */
public class PegdownParser implements MarkdownParser {
private PegDownProcessor processor;
private final Logger logger = LoggerFactory.getLogger(PegdownParser.class);
private PegDownProcessor processor;
public PegdownParser() {
int pegdownOptions = Extensions.ALL_WITH_OPTIONALS - Extensions.ANCHORLINKS;
int parsingTimeoutAsMillis = 5000;
@ -23,17 +23,19 @@ public class PegdownParser implements MarkdownParser {
try {
String parsed = processor.markdownToHtml(markdownText);
if (null == parsed) throw new RuntimeException("Cannot parse markdown syntax string to HTML");
if (null == parsed) {
throw new RuntimeException("Cannot parse markdown text to HTML using pegdown");
}
html = wrapWithMarkdownClassDiv(parsed);
} catch (RuntimeException e) {
logger.error("Failed to parsed markdown text", e);
logger.error("Cannot parse markdown text to HTML using pegdown", e);
}
return html;
}
/** wrap with markdown class div to styling DOM using css */
/** wrap with markdown class div to styling DOM using css. */
public static String wrapWithMarkdownClassDiv(String html) {
return new StringBuilder()
.append("<div class=\"markdown-body\">\n")

View file

@ -2,7 +2,14 @@
{
"group": "md",
"name": "md",
"className": "org.apache.zeppelin.markdown.Markdown",
"properties": null
"className": "org.apache.zeppelin.markdown.MarkdownInterpreter",
"properties": {
"markdown.parser.type": {
"envName": "MARKDOWN_PARSER_TYPE",
"propertyName": "markdown.parser.type",
"defaultValue": "markdown4j",
"description": "Markdown Parser Type. Available values: markdown4j, pegdown. Default = markdown4j"
}
}
}
]

View file

@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.zeppelin.markdown;
import org.apache.zeppelin.interpreter.InterpreterResult;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.Properties;
import static org.junit.Assert.assertEquals;
public class Markdown4jParserTest {
MarkdownInterpreter md;
@Before
public void setUp() throws Exception {
Properties props = new Properties();
props.put(MarkdownInterpreter.MARKDOWN_PARSER_TYPE, MarkdownInterpreter.PARSER_TYPE_MARKDOWN4J);
md = new MarkdownInterpreter(props);
md.open();
}
@After
public void tearDown() throws Exception {
md.close();
}
@Test
public void testStrikethrough() {
InterpreterResult result = md.interpret("This is ~~deleted~~ text", null);
assertEquals("<p>This is <s>deleted</s> text</p>\n", result.message());
}
}

View file

@ -29,64 +29,65 @@ import org.junit.Test;
public class PegdownParserTest {
MarkdownInterpreter pegdownInterpreter;
MarkdownInterpreter md;
@Before
public void setUp() throws Exception {
pegdownInterpreter = new MarkdownInterpreter(new Properties());
pegdownInterpreter.open();
Properties props = new Properties();
props.put(MarkdownInterpreter.MARKDOWN_PARSER_TYPE, MarkdownInterpreter.PARSER_TYPE_PEGDOWN);
md = new MarkdownInterpreter(props);
md.open();
}
@After
public void tearDown() throws Exception {
pegdownInterpreter.close();
md.close();
}
@Test
public void testHeader() {
InterpreterResult r1 = pegdownInterpreter.interpret("# H1", null);
InterpreterResult r1 = md.interpret("# H1", null);
assertEquals(wrapWithMarkdownClassDiv("<h1>H1</h1>"), r1.message());
InterpreterResult r2 = pegdownInterpreter.interpret("## H2", null);
InterpreterResult r2 = md.interpret("## H2", null);
assertEquals(wrapWithMarkdownClassDiv("<h2>H2</h2>"), r2.message());
InterpreterResult r3 = pegdownInterpreter.interpret("### H3", null);
InterpreterResult r3 = md.interpret("### H3", null);
assertEquals(wrapWithMarkdownClassDiv("<h3>H3</h3>"), r3.message());
InterpreterResult r4 = pegdownInterpreter.interpret("#### H4", null);
InterpreterResult r4 = md.interpret("#### H4", null);
assertEquals(wrapWithMarkdownClassDiv("<h4>H4</h4>"), r4.message());
InterpreterResult r5 = pegdownInterpreter.interpret("##### H5", null);
InterpreterResult r5 = md.interpret("##### H5", null);
assertEquals(wrapWithMarkdownClassDiv("<h5>H5</h5>"), r5.message());
InterpreterResult r6 = pegdownInterpreter.interpret("###### H6", null);
InterpreterResult r6 = md.interpret("###### H6", null);
assertEquals(wrapWithMarkdownClassDiv("<h6>H6</h6>"), r6.message());
InterpreterResult r7 = pegdownInterpreter.interpret("Alt-H1\n" + "======", null);
InterpreterResult r7 = md.interpret("Alt-H1\n" + "======", null);
assertEquals(wrapWithMarkdownClassDiv("<h1>Alt-H1</h1>"), r7.message());
InterpreterResult r8 = pegdownInterpreter.interpret("Alt-H2\n" + "------", null);
InterpreterResult r8 = md.interpret("Alt-H2\n" + "------", null);
assertEquals(wrapWithMarkdownClassDiv("<h2>Alt-H2</h2>"), r8.message());
}
@Test
public void testStrikethrough() {
InterpreterResult result = pegdownInterpreter.interpret("This is ~~deleted~~ text", null);
InterpreterResult result = md.interpret("This is ~~deleted~~ text", null);
assertEquals(
wrapWithMarkdownClassDiv("<p>This is <del>deleted</del> text</p>"), result.message());
}
@Test
public void testItalics() {
InterpreterResult result = pegdownInterpreter.interpret("This is *italics* text", null);
InterpreterResult result = md.interpret("This is *italics* text", null);
assertEquals(
wrapWithMarkdownClassDiv("<p>This is <em>italics</em> text</p>"), result.message());
}
@Test
public void testStrongEmphasis() {
InterpreterResult result =
pegdownInterpreter.interpret("This is **strong emphasis** text", null);
InterpreterResult result = md.interpret("This is **strong emphasis** text", null);
assertEquals(
wrapWithMarkdownClassDiv("<p>This is <strong>strong emphasis</strong> text</p>"),
result.message());
@ -108,7 +109,7 @@ public class PegdownParserTest {
.append("</ol>")
.toString();
InterpreterResult result = pegdownInterpreter.interpret(input, null);
InterpreterResult result = md.interpret(input, null);
assertEquals(wrapWithMarkdownClassDiv(expected), result.message());
}
@ -130,7 +131,7 @@ public class PegdownParserTest {
.append("</ul>")
.toString();
InterpreterResult result = pegdownInterpreter.interpret(input, null);
InterpreterResult result = md.interpret(input, null);
assertEquals(wrapWithMarkdownClassDiv(expected), result.message());
}
@ -181,14 +182,13 @@ public class PegdownParserTest {
.append("<p>Some text to show that the reference links can follow later.</p>")
.toString();
InterpreterResult result = pegdownInterpreter.interpret(input, null);
InterpreterResult result = md.interpret(input, null);
assertEquals(wrapWithMarkdownClassDiv(expected), result.message());
}
@Test
public void testInlineCode() {
InterpreterResult result =
pegdownInterpreter.interpret("Inline `code` has `back-ticks around` it.", null);
InterpreterResult result = md.interpret("Inline `code` has `back-ticks around` it.", null);
assertEquals(
wrapWithMarkdownClassDiv(
"<p>Inline <code>code</code> has <code>back-ticks around</code> it.</p>"),
@ -198,7 +198,7 @@ public class PegdownParserTest {
@Test
public void testBlockQuotes() {
InterpreterResult r1 =
pegdownInterpreter.interpret(
md.interpret(
"> Blockquotes are very handy in email to emulate reply text.\n"
+ "> This line is part of the same quote.",
null);
@ -210,7 +210,7 @@ public class PegdownParserTest {
r1.message());
InterpreterResult r2 =
pegdownInterpreter.interpret(
md.interpret(
"> 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. ",
null);
assertEquals(
@ -256,7 +256,7 @@ public class PegdownParserTest {
.append("</table>")
.toString();
InterpreterResult result = pegdownInterpreter.interpret(input, null);
InterpreterResult result = md.interpret(input, null);
assertEquals(wrapWithMarkdownClassDiv(expected), result.message());
}
@ -296,7 +296,7 @@ public class PegdownParserTest {
.append("</table>")
.toString();
InterpreterResult result = pegdownInterpreter.interpret(input, null);
InterpreterResult result = md.interpret(input, null);
assertEquals(wrapWithMarkdownClassDiv(expected), result.message());
}
}