Github Flavored Markdown + OSGi + dotCMS
Learn how to choose a Java markdown library and use OSGi with dotCMS.
Join the DZone community and get the full member experience.
Join For FreeAs a Java based CMS, dotCMS handles a lot of different use cases for managing and delivering content. Recently, we were asked if dotCMS can deliver Github flavored markdown content. We thought that this would be a great example of how easy it is to extend dotCMS with OSGi plugins. (As a side note, this blog - as seen on dotcms.com - is actually written using the plugin).
Markdown
Some background for developers stuck in 2008, Markdown is a text to html parser originally written by John Gruber. It provides a user a simple, small set of markup tags that is parsed and rendered as standard HTML for consumption by browsers or even less capable views or viewports. Github Flavored Markdown, or GFM, offers a few extensions for further formatting, including support for strikethrough, url auto-linking, syntax highlighting and tables, Because of the ubiquity of github as a coding resource, GFM has become a de facto standard for commenting, documentation and other online authoring tools that needs support for formatting, but want to limit, uh, “creativity”.
Choosing a Java Markdown Parsing Library
There are number of different Java markdown libraries to out there, including:
- Pegdown - Larger footprint, dependencies, slower, can hang in corner cases
- Markdown4j - nice, though seems abandoned
- TxtMark - small, fast though does not support GFM extensions
dotCMS decided to leverage TxtMark, by René Jeschke, which offers a fast, self contained Markdown implementation without external dependencies. Because TxtMark only supports “standard” Markdown, we also implemented the additions suggested by Bogdan Stefanescu for further Github markdown flavoring. We also added the ability to do code syntax highlighting by adding a class attribute to the <code> code block (and by using highlight.js)
Creating the OSGi Plugin
Most content rendered in dotCMS is parsed by Apache Velocity. dotCMS provides an OSGi extension point for developers to hook into Velocity and provide custom Velocity “Viewtools”, which are pure Java and can be used when rendering content, pages, a template or a widget (Viewtools can be thought of as the Velocity equivalent of a jsp taglib).
To get started, we copied the Viewtool OSGi example provided in the dotCMS source code. This gave us the foundation on which to build our plugin. We then copied the txtmark java files to our plugins src directory ./src/main/java
and added our our own package and Viewtool implementation called MarkdownTool.java
. This class implements theorg.apache.velocity.tools.view.tools.ViewTool
interface and exposes public methods for web developers to use when displaying content. The important method is parse(String markdown)
, and takes a String of markdown, gets a Markdown Processor and returns our String as marked up html.
Our final MarkdownTool
code could literally be as simple as this.
/**
* Parse a String for markdown
* @param parse
* @return
* @throws Throwable
*/
public String parse(String parse) throws Throwable {
return Processor.process(parse, Configuration.builder().forceExtentedProfile().build());
}
In order to register the Viewtool via OSGi for use by dotCMS, we need to create two additional classes, the MarkdownToolInfo
and the OSGi Activator
. The MarkdownToolInfo
declares the Velocity variable used to bind our Viewtool and the scope of the tool. Thescope of a Viewtool dictates when a Viewtool is instantiated and can be one of three values:
- application - loads on startup as a Singleton
- request - instantiated every visitor request, which gives you a handle on the request object
- session - once per visitor, added to the visitor session (not sure why someone would want to do this)
Our MarkdownToolInfo
class looks looks like
public String getKey() {
return "markdown";
}
public String getScope() {
return "request";
}
public Object getInstance(Object initData) {
MarkdownTool viewTool = new MarkdownTool();
viewTool.init(initData);
return viewTool;
}
The second additional class we need to create is a standard OSGi Activator class that is called when an OSGi plugin is initially loaded. This class extends dotCMS's GenericBundleActivator
which provides convenience methods to enable or register OSGi plugins in various parts of the dotCMS system. In this case, we register the Viewtool like so:
initializeServices(bundleContext);
registerViewToolService(bundleContext, new MarkdownToolInfo());
Building the plugin
Finally, in order to build our plugin, we need to futz with the ./build.gradle
file, which will build our OSGi manifest. Here we add our plugin name and point to the Bundle-Activator that we created in the above step. The important code looks like this:
jar {
manifest {
name = 'Markdown Viewtool'
instruction 'Bundle-Vendor', 'dotcms'
instruction 'Bundle-Description', 'dotCMS - Markdown'
instruction 'Bundle-DocURL', 'http://www.dotcms.com'
instruction 'Bundle-Activator', 'com.dotcms.osgi.markdown.Activator'
instruction 'DynamicImport-Package', '*'
instruction 'Import-Package', '*;version=0'
}
}
To build, we then run the Gradle wrapper
./gradlew clean jar
which builds and jars our osgi plugin. Once it is build, we upload the OSGi jar to your running dotCMS instance via the System > Dynamic Plugins screen. There you should then see the plugin register and become active
Using the Markdown Plugin
The nice thing about Velocity is that it makes easy things easy. So once our plugin is registered and active, using our new plugin on a template or page is easy and understandable for your web developers, e.g.
$markdown.parse("**Parse** *this* ~~string~~")
will result in
**Parse** *this* ~~string~~
Or when rendering a piece of content with a text field called “body”, something like :
$markdown.parse($content.body)
will parse the content object's body value and return the results.
Get the code
The code for the Markdown OSGi plugin can be found on dotCMS's github repos here:
Published at DZone with permission of Will Ezell, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments