Skip to content

Extensions

Estevão Soares dos Santos edited this page May 28, 2015 · 12 revisions

Showdown allows additional functionality to be loaded via extensions.

Client-side Extension Usage

<script src="src/showdown.js" />
<script src="src/extensions/twitter.js" />

var converter = new showdown.Converter({ extensions: ['twitter'] });

Server-side Extension Usage

// Using a bundled extension
var Showdown = require('showdown');
var converter = new showdown.Converter({ extensions: ['twitter'] });

// Using a custom extension
var mine = require('./custom-extensions/mine');
var converter = new showdown.Converter({ extensions: ['twitter', mine] });

List of known extensions

  • twitter
  • table
  • prettify
  • github

Community

Creating Markdown Extensions

A showdown extension is simply a function which returns an array of language extensions and/or output modifiers:

  • Language Extension -- Language extensions are specified with the lang type, and add new markdown syntax to showdown. For example, say you wanted ^^youtube http://www.youtube.com/watch?v=oHg5SJYRHA0 to automatically render as an embedded YouTube video, that would be a language extension.
  • Output Modifiers -- Output Modifiers are specified with the output type. After showdown has generated HTML, an output modifier can make changes to the generated HTML. For example, if you wanted to change <div class="header"> to be <header>, you could implement an output modifier.

Each showdown extension can provide language extensions and/or output modifiers.

Regex/Replace

Regex/replace style extensions are very similar to javascripts string.replace function. Two properties are given, regex and replace. regex is a string and replace can be either a string or a function. If replace is a string, it can use the $1 syntax for group substitution, exactly as if it were making use of string.replace (internally it does this actually); The value of regex is assumed to be a global replacement.

Example:

var demo = function(converter) {
  return [
    // Replace escaped @ symbols
    { type: 'lang', regex: '\\@', replace: '@' }
  ];
}

Filter

Alternately, if you'd just like to do everything yourself, you can specify a filter which is a callback with a single input parameter, text (the current source text within the showdown engine).

Example:

var demo = function(converter) {
  return [
    // Replace escaped @ symbols
    { type: 'lang', filter: function(text) {
      return text.replace(/\\@/g, '@');
    }}
  ];
}

Implementation Concerns

One bit which should be taken into account is maintaining both client-side and server-side compatibility. This can be achieved with a few lines of boilerplate code. First, to prevent polluting the global scope for client-side code, the extension definition should be wrapped in a self-executing function.

(function(){
  // Your extension here
}());

Second, client-side extensions should add a property onto Showdown.extensions which matches the name of the file. As an example, a file named demo.js should then add Showdown.extensions.demo. Server-side extensions can simply export themselves.

(function(){
  var demo = function(converter) {
    // ... extension code here ...
  };

  // Client-side export
  if (typeof window !== 'undefined' && window.showdown && window.showdown.extensions) {
    window.Showdown.extensions.demo = demo;
  }
  // Server-side export
  if (typeof module !== 'undefined') module.exports = demo;
}());

Testing Extensions

The showdown test runner is setup to automatically test cases for extensions. To add test cases for an extension, create a new folder under ./test/extensions which matches the name of the .js file in ./src/extensions. Place any test cases into the filter using the md/html format and they will automatically be run when tests are run.