mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
feat: Support markdown.parser.type attr in md
This commit is contained in:
parent
d2d4455118
commit
2b6516cad3
6 changed files with 161 additions and 36 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue