-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Extensions
Showdown allows additional functionality to be loaded via extensions.
<script src="src/showdown.js" />
<script src="src/extensions/twitter.js" />
var converter = new showdown.Converter({ extensions: ['twitter'] });
// 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] });
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 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: '@' }
];
}
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, '@');
}}
];
}
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;
}());
Showdown does the following escape/normalization:
- Replaces
~
(tilde) with~T
- Replaces
$
(dollar sign) with~D
- Normalizes line endings (
\r
,\r\n
are converted into\n
) - uses
\r
as a char placeholder
This happens before language extensions are run, which means that if your extension relies on any of those chars, you have to take this into consideration and make the appropriate modifications.
This only applies to language extensions since these chars are unescaped before output extensions are run.
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.