Blogs

Developing a Github Flavored Markdown Plugin

Will Ezell

As 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 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.

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 the org.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. The scope 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:

https://github.com/dotCMS/plugin-viewtool-markdown

Will Ezell
Chief Technology Officer
October 29, 2015

Filed Under:

github markdown osgi

Recommended Reading

Headless CMS vs Hybrid CMS: How dotCMS Goes Beyond Headless

What’s the difference between a headless CMS and a hybrid CMS, and which one is best suited for an enterprise?

Why Global Brands Need a Multi-tenant CMS

Maintaining or achieving a global presence requires effective use of resources, time and money. Single-tenant CMS solutions were once the go-to choices for enterprises to reach out to different market...

14 Benefits of Cloud Computing and Terminology Glossary to Get You Started

What is cloud computing, and what benefits does the cloud bring to brands who are entering into the IoT era?