Skip to content

Commit

Permalink
Move from peg markdown to flexmark.
Browse files Browse the repository at this point in the history
  • Loading branch information
mkalus committed Jul 28, 2021
1 parent 73abd10 commit 3fd58fe
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 56 deletions.
8 changes: 4 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,11 @@
<artifactId>thymeleaf</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>
<!-- Pegdown markdown parser -->
<!-- Flexmark markdown parser -->
<dependency>
<groupId>org.pegdown</groupId>
<artifactId>pegdown</artifactId>
<version>1.6.0</version>
<groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-all</artifactId>
<version>0.62.2</version>
</dependency>

<!-- OrientDB -->
Expand Down
54 changes: 2 additions & 52 deletions src/main/java/org/segrada/controller/PageController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@

import com.google.inject.Singleton;
import com.sun.jersey.api.view.Viewable;
import org.parboiled.common.StringUtils;
import org.pegdown.FastEncoder;
import org.pegdown.LinkRenderer;
import org.pegdown.PegDownProcessor;
import org.pegdown.ast.ExpImageNode;
import org.pegdown.ast.ExpLinkNode;
import org.segrada.rendering.markdown.PageMarkdownRenderer;

import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletRequest;
Expand Down Expand Up @@ -167,51 +162,6 @@ private String renderPageContent(String page, String language, String contextPat
return "IOEXCEPTION: " + e.getMessage();
}

// create markdown renderer
PegDownProcessor markdownParser = new PegDownProcessor();

// render markdown to HTML
return markdownParser.markdownToHtml(sb.toString(), new PageLinkRenderer(contextPath));
}

/**
* link renderer for page context
*/
private class PageLinkRenderer extends LinkRenderer {
private final String contextPath;

public PageLinkRenderer(String contextPath) {
this.contextPath = contextPath;
}

@Override
public Rendering render(ExpLinkNode node, String text) {
// do not change links starting with http
if (node.url.startsWith("http")) // add external class
return super.render(node, text).withAttribute("class", "sg-link-external");

// add context path to url
String url = contextPath + "/page/" + node.url;
// cut away .md suffix if needed
if (url.endsWith(".md")) url = url.substring(0, url.length() - 3);

LinkRenderer.Rendering rendering = new LinkRenderer.Rendering(url, text);
rendering = rendering.withAttribute("class", "sg-data-add");
return StringUtils.isEmpty(node.title)?rendering:rendering.withAttribute("title", FastEncoder.encode(node.title));
}

@Override
public Rendering render(ExpImageNode node, String text) {
// do not change links starting with http
if (node.url.startsWith("http")) return super.render(node, text);

// add context path to url
String url = contextPath + "/page/img/" + node.url;
// cut away .png suffix if needed //TODO: make this work nicely
if (url.endsWith(".png")) url = url.substring(0, url.length() - 4);

LinkRenderer.Rendering rendering = new LinkRenderer.Rendering(url, text);
return StringUtils.isEmpty(node.title)?rendering:rendering.withAttribute("title", FastEncoder.encode(node.title));
}
return PageMarkdownRenderer.render(sb.toString(), contextPath);
}
}
134 changes: 134 additions & 0 deletions src/main/java/org/segrada/rendering/markdown/PageMarkdownRenderer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package org.segrada.rendering.markdown;

import com.vladsch.flexmark.ast.Image;
import com.vladsch.flexmark.ast.Link;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.html.HtmlRenderer.Builder;
import com.vladsch.flexmark.html.HtmlRenderer.HtmlRendererExtension;
import com.vladsch.flexmark.html.LinkResolver;
import com.vladsch.flexmark.html.LinkResolverFactory;
import com.vladsch.flexmark.html.renderer.LinkResolverBasicContext;
import com.vladsch.flexmark.html.renderer.LinkStatus;
import com.vladsch.flexmark.html.renderer.ResolvedLink;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.data.DataHolder;
import com.vladsch.flexmark.util.data.MutableDataHolder;
import com.vladsch.flexmark.util.data.MutableDataSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collections;
import java.util.Set;

public class PageMarkdownRenderer {
// markdown data holder with custom extension + more extensions defined below
final private static DataHolder OPTIONS = new MutableDataSet()
.set(Parser.EXTENSIONS, Collections.singletonList(CustomExtension.create())).toImmutable();

// markdown parser and renderer
static final Parser PARSER = Parser.builder(OPTIONS).build();
static final HtmlRenderer RENDERER = HtmlRenderer.builder(OPTIONS).build();

// context path
static private String contextPath;

public static class PageLinkResolver implements LinkResolver {
@Override
public @NotNull ResolvedLink resolveLink(@NotNull Node node, @NotNull LinkResolverBasicContext linkResolverBasicContext, @NotNull ResolvedLink link) {
// Links
if (node instanceof Link) {
String url = link.getUrl();

// external link
if (url.startsWith("http")) {// add external class
link.getMutableAttributes().addValue("class", "sg-link-external");
return link.withStatus(LinkStatus.VALID).withUrl(url);
}

// add context path to url
url = PageMarkdownRenderer.contextPath + "/page/" + url;
// cut away .md suffix if needed
if (url.endsWith(".md")) url = url.substring(0, url.length() - 3);

link.getMutableAttributes().addValue("class", "sg-data-add");
if (link.getTitle() == null || link.getTitle().equals("")) {
return link.withStatus(LinkStatus.VALID).withUrl(url).withTitle(((Link) node).getText());
}
return link.withStatus(LinkStatus.VALID).withUrl(url);
}

// Images
if (node instanceof Image) {
String url = link.getUrl();

// do not change links starting with http
if (url.startsWith("http"))
return link.withStatus(LinkStatus.VALID).withUrl(url);

// add context path to url
url = PageMarkdownRenderer.contextPath + "/page/img/" + url;
// cut away .png suffix if needed
if (url.endsWith(".png")) url = url.substring(0, url.length() - 4);

if (link.getTitle() == null || link.getTitle().equals("")) {
return link.withStatus(LinkStatus.VALID).withUrl(url).withTitle(((Image) node).getTitle());
}
return link.withStatus(LinkStatus.VALID).withUrl(url);
}

return link;
}

public static class Factory implements LinkResolverFactory {
@Override
public @Nullable Set<Class<?>> getAfterDependents() {
return null;
}

@Override
public @Nullable Set<Class<?>> getBeforeDependents() {
return null;
}

@Override
public boolean affectsGlobalScope() {
return false;
}

@Override
public @NotNull LinkResolver apply(@NotNull LinkResolverBasicContext context) {
return new PageLinkResolver();
}
}
}

static class CustomExtension implements HtmlRendererExtension {
@Override
public void rendererOptions(@NotNull MutableDataHolder options) {

}

@Override
public void extend(@NotNull Builder htmlRendererBuilder, @NotNull String rendererType) {
htmlRendererBuilder.linkResolverFactory(new PageLinkResolver.Factory());
}

static CustomExtension create() {
return new CustomExtension();
}
}

/**
* renders markdown to HTML
*
* @param markdown source
* @param contextPath source
* @return html
*/
public static String render(String markdown, String contextPath) {
PageMarkdownRenderer.contextPath = contextPath;

return RENDERER.render(PARSER.parse(markdown));
}
}

0 comments on commit 3fd58fe

Please sign in to comment.