Added documentation for authoring and testing extensions

This commit is contained in:
Titus 2012-06-20 21:35:47 -06:00
parent 22056db9a7
commit 2be5e4ff7d

View File

@ -232,6 +232,78 @@ Once installed the tests can be run from the project root using:
New test cases can easily be added. Create a markdown file (ending in `.md`) which contains the markdown to test. Create a `.html` file of the exact same name. It will automatically be tested when the tests are executed with `mocha`.
Creating Markdown Extensions
----------------------------
A showdown extension is simply a function which returns an array of extensions. Each single extension can be one of two types:
- Language Extension -- Language extensions are ones that that 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 -- After showdown has run, and generated HTML, an output modifier would change that HTML. For example, say you wanted to change `<div class="header">` to be `<header>`, that would be an output modifier.
Each extension can provide two combinations of interfaces for showdown.
#### 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 substituation, 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.
#### Regex/Replace Example
``` js
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).
#### Filter Example
``` js
var demo = function(converter) {
return [
// Replace escaped @ symbols
{ type: 'lang', 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.
``` js
(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.
``` js
(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 filder using the md/html format and they will automatically be run when tests are run.
Credits
---------------------------