Skip to content

Instantly share code, notes, and snippets.

@clartaq
Created December 16, 2018 22:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save clartaq/dc08421bf860668b9ee88884e9bdbd47 to your computer and use it in GitHub Desktop.
Save clartaq/dc08421bf860668b9ee88884e9bdbd47 to your computer and use it in GitHub Desktop.
Custom flexmark-java LinkRenderer for CWiki (not used)
package cwiki.extensions;
import com.vladsch.flexmark.ext.wikilink.WikiLink;
import com.vladsch.flexmark.ext.wikilink.internal.WikiLinkOptions;
import com.vladsch.flexmark.html.CustomNodeRenderer;
import com.vladsch.flexmark.html.HtmlWriter;
import com.vladsch.flexmark.html.renderer.*;
import com.vladsch.flexmark.util.options.DataHolder;
import com.vladsch.flexmark.util.sequence.BasedSequence;
import java.util.HashSet;
import java.util.Set;
import static com.vladsch.flexmark.util.sequence.CharSubSequence.of;
public class CWikiLinkRenderer implements NodeRenderer {
// From: https://stackoverflow.com/questions/724043/http-url-address-encoding-in-java
/**
* Percent-encodes a string so it's suitable for use in a URL Path (not a query string / form encode, which uses + for spaces, etc)
*/
private static String percentEncode(String encodeMe) {
if (encodeMe == null) {
return "";
}
String encoded = encodeMe.replace("%", "%25");
encoded = encoded.replace(" ", "%20");
encoded = encoded.replace("!", "%21");
encoded = encoded.replace("#", "%23");
encoded = encoded.replace("$", "%24");
encoded = encoded.replace("&", "%26");
encoded = encoded.replace("'", "%27");
encoded = encoded.replace("(", "%28");
encoded = encoded.replace(")", "%29");
encoded = encoded.replace("*", "%2A");
encoded = encoded.replace("+", "%2B");
encoded = encoded.replace(",", "%2C");
encoded = encoded.replace("/", "%2F");
encoded = encoded.replace(":", "%3A");
encoded = encoded.replace(";", "%3B");
encoded = encoded.replace("=", "%3D");
encoded = encoded.replace("?", "%3F");
encoded = encoded.replace("@", "%40");
encoded = encoded.replace("[", "%5B");
encoded = encoded.replace("]", "%5D");
return encoded;
}
public static class Factory implements DelegatingNodeRendererFactory {
@Override
public NodeRenderer create(final DataHolder options) {
return new CWikiLinkRenderer();
}
@Override
public Set<Class<? extends NodeRendererFactory>> getDelegates() {
///Set<Class<? extends NodeRendererFactory>> set = new HashSet<Class<? extends NodeRendererFactory>>();
// add node renderer factory classes to which this renderer will delegate some of its rendering
// core node renderer is assumed to have all depend it so there is no need to add it
//set.add(WikiLinkNodeRenderer.Factory.class);
//return set;
// return null if renderer does not delegate or delegates only to core node renderer
return null;
}
}
@Override
public Set<NodeRenderingHandler<?>> getNodeRenderingHandlers() {
HashSet<NodeRenderingHandler<?>> set = new HashSet<NodeRenderingHandler<?>>();
set.add(new NodeRenderingHandler<WikiLink>(WikiLink.class, new CustomNodeRenderer<WikiLink>() {
@Override
public void render(WikiLink node, NodeRendererContext context, HtmlWriter html) {
String encodedLink = percentEncode(node.getLink().toString());
BasedSequence newLink = of(encodedLink);
DataHolder options = context.getOptions();
WikiLinkOptions wlo = new WikiLinkOptions(options);
node.setLink(newLink, wlo.allowAnchors, wlo.allowAnchorEscape);
context.delegateRender();
}
}));
return set;
}
}
package cwiki.extensions;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.util.options.MutableDataHolder;
public class CWikiLinkRendererExtension implements HtmlRenderer.HtmlRendererExtension {
@Override
public void rendererOptions(final MutableDataHolder options) {
// add any configuration settings to options you want to apply to everything, here
}
@Override
public void extend(final HtmlRenderer.Builder rendererBuilder, final String rendererType) {
rendererBuilder.nodeRendererFactory(new CWikiLinkRenderer.Factory());
}
public static CWikiLinkRendererExtension create() {
return new CWikiLinkRendererExtension();
}
}
(ns cwiki.test.extensions.CWikiLinkRendererTest
(:require [clojure.test :refer :all])
(:import (com.vladsch.flexmark.ext.gfm.strikethrough StrikethroughExtension)
(com.vladsch.flexmark.ext.tables TablesExtension)
(com.vladsch.flexmark.ext.footnotes FootnoteExtension)
(com.vladsch.flexmark.ext.wikilink WikiLinkExtension)
(com.vladsch.flexmark.html HtmlRenderer HtmlRenderer$Builder)
(com.vladsch.flexmark.parser Parser Parser$Builder)
(com.vladsch.flexmark.util KeepType)
(com.vladsch.flexmark.util.options MutableDataSet)
(cwiki.extensions CWikiLinkRendererExtension)
(java.util ArrayList)))
;-------------------------------------------------------------------------------
; Test fixtures.
;-------------------------------------------------------------------------------
; All of these extensions are not really needed but are here so that the test
; environment is more similar to the actual use in the program.
(def options (-> (MutableDataSet.)
(.set Parser/REFERENCES_KEEP KeepType/LAST)
(.set HtmlRenderer/INDENT_SIZE (Integer/valueOf 2))
(.set HtmlRenderer/PERCENT_ENCODE_URLS true)
(.set TablesExtension/COLUMN_SPANS false)
(.set TablesExtension/MIN_HEADER_ROWS (Integer/valueOf 1))
(.set TablesExtension/MAX_HEADER_ROWS (Integer/valueOf 1))
(.set TablesExtension/APPEND_MISSING_COLUMNS true)
(.set TablesExtension/DISCARD_EXTRA_COLUMNS true)
(.set TablesExtension/WITH_CAPTION false)
(.set TablesExtension/HEADER_SEPARATOR_COLUMN_MATCH true)
(.set WikiLinkExtension/ALLOW_ANCHOR_ESCAPE true)
(.set WikiLinkExtension/ALLOW_ANCHORS true)
(.set WikiLinkExtension/LINK_FIRST_SYNTAX true)
(.set WikiLinkExtension/LINK_ESCAPE_CHARS "")
(.set Parser/EXTENSIONS (ArrayList.
[(FootnoteExtension/create)
(StrikethroughExtension/create)
(WikiLinkExtension/create)
(CWikiLinkRendererExtension/create)
(TablesExtension/create)]))))
(def parser (.build ^Parser$Builder (Parser/builder options)))
(def renderer (.build ^HtmlRenderer$Builder (HtmlRenderer/builder options)))
;-------------------------------------------------------------------------------
; Utilities
;-------------------------------------------------------------------------------
(defn- convert-markdown-to-html
"Convert the markdown formatted input string to html
and return it."
[mkdn]
(->> mkdn
(.parse parser)
(.render renderer)))
;-------------------------------------------------------------------------------
; Tests
;-------------------------------------------------------------------------------
(deftest wikilink-encoding-test
(testing "Testing the get-option-value function."
(is (= "<p>some text</p>\n" (convert-markdown-to-html "some text")))
(is (= "<p>a link to the <a href=\"Front%20Page\">Front Page</a>.</p>\n"
(convert-markdown-to-html "a link to the [[Front Page]].")))
(is (= "<p><a href=\"link%20part\">text part</a></p>\n"
(convert-markdown-to-html "[[link part|text part]]")))
(is (= "<p><a href=\"What%20is%20A%2FB%20Testing%3F\">What is A/B Testing?</a></p>\n"
(convert-markdown-to-html "[[What is A/B Testing?]]")))))
@clartaq
Copy link
Author

clartaq commented Dec 16, 2018

These files are custom LinkRenderer, LinkRendererExtension, and test files for flexmark-java. They are used in conjunction with the WikiLinkExtension that already exists in the flexmark project. They were an experiment for use in a personal wiki program. They allowed page titles including punctuation characters to be used as URLs to link to the named pages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment