File: docs/tutorials/add-default-class-to-html.md
Add default class for each HTML element
Many people use CSS kits like Bootstrap, Semantic UI, or others that require default name classes for HTML elements:
<h1 class="ui large header">1st Heading</h1>
<h2 class="ui medium header">2nd Heading</h2>
<li class="ui item">first item</li>
<li class="ui item">second item</li>Showdown does not support this out-of-the-box. But you can create an extension for this:
const showdown = require('showdown');
const classMap = {
h1: 'ui large header',
h2: 'ui medium header',
ul: 'ui list',
li: 'ui item'
}
const bindings = Object.keys(classMap)
.map(key => ({
type: 'output',
regex: new RegExp(`<${key}(.*)>`, 'g'),
replace: `<${key} class="${classMap[key]}" $1>`
}));
const conv = new showdown.Converter({
extensions: [...bindings]
});
const text = `
# 1st Heading
## 2nd Heading
- first item
- second item
`;With this extension, the output will be as follows:
โโโโโ<h1 class="ui large header">1st Heading</h1>โโโโโ
โโโโโ<h2 class="ui medium header">2nd Heading</h2>โโโโโ
โโโโโโโโโโ
โโโโโ<li class="ui item">first item</li>โโโโโ
โโโโโ<li class="ui item">second item</li>โโโโโ
โโโโโโโโโโCredits
- Initial creator: @zusamann, (original issue).
- Updated by @Kameelridder, (original issue).
File: docs/tutorials/index.md
Tutorials
- Add default class for each HTML element
- Markdown editor with Showdown
- Use language and output extensions on the same block
File: docs/tutorials/use-both-extension-types-together.md
Use language and output extensions on the same block
Overview
Showdown allows you to define and use any number of extensions that act on the same block. These extensions can be executed sequentially or at different moments.
This enables you to pre-parse/mark a block of text but defer any modifications for the last by using a combination of language and output extensions.
This is useful if you, for example, don't want Showdown to parse the contents of your new language construct.
Example
Let's say you create an extension that captures everything between %start% and %end%. However, that content should not be modified by Showdown. Obviously, you can use `` tags but that is beside the point.
Although Showdown doesn't have any flag to prevent parsing the content of an extension, the same effect can be easily achieved by using lang and output extensions together.
!!! example ""
The fully working example you can see in Fiddle.
Code
Create your extensions with the following content:
showdown.extension('myExt', function() {
var matches = [];
return [
{
type: 'lang',
regex: /%start%([^]+?)%end%/gi,
replace: function(s, match) {
matches.push(match);
var n = matches.length - 1;
return '%PLACEHOLDER' + n + '%';
}
},
{
type: 'output',
filter: function (text) {
for (var i=0; i< matches.length; ++i) {
var pat = '%PLACEHOLDER' + i + '% *<\/p>';
text = text.replace(new RegExp(pat, 'gi'), matches[i]);
}
//reset array
matches = [];
return text;
}
}
]
});In this example, you created a lang extension that:
- Checks for the pseudo tags
%start%and%end%. - Extracts everything in between the tags.
- Saves the content between the tags in a variable.
- Replaces the saved content with a placeholder to identify the exact position of the extracted text.
and an output extension that replaces the placeholder with the saved content, once Showdown is finished parsing.
!!! note "Modern equivalent"
lang/output extensions are deprecated in favor of listener extensions. The same pattern can be written as listeners on the document-level makehtml.onPreParse and makehtml.onEnd events โ they receive a showdown.Event whose input holds the text and which you transform by returning the new string:
```js
showdown.extension('myExt', function () {
var matches = [];
return [{
type: 'listener',
listeners: {
// capture + placeholder, before parsing
'makehtml.onPreParse': function (evt) {
return evt.input.replace(/%start%([^]+?)%end%/gi, function (s, match) {
matches.push(match);
return '%PLACEHOLDER' + (matches.length - 1) + '%';
});
},
// restore, after parsing
'makehtml.onEnd': function (evt) {
var text = evt.input;
for (var i = 0; i < matches.length; ++i) {
text = text.replace(new RegExp('%PLACEHOLDER' + i + '% *<\/p>', 'gi'), matches[i]);
}
matches = [];
return text;
}
}
}];
});
```File: docs/cli.md
Showdown comes bundled with a Command-line interface (CLI) tool that allows you to run Showdown converter from the command line.
Requirements
Quick start guide
Check that Showdown CLI is accessible.
If you installed Showdown globally via
npm install showdown -g, you can access the CLI tool help by typingshowdown -hin the command line:=== "input"
text```sh showdown -h ```=== "output"
text``` Usage: showdown <command> [options] CLI to Showdownjs markdown parser v3.0.0 Options: -V, --version output the version number -q, --quiet Quiet mode. Only print errors -m, --mute Mute mode. Does not print anything -v, --verbose Verbose mode. Print extra information about the conversion --color Force colored output even when the output is not a terminal --no-color Disable colored output -h, --help display help for command Commands: makehtml [options] Converts markdown into html makemarkdown [options] Converts html into markdown help [command] display help for command ```If you installed Showdown locally via
npm install showdown, open the folder where Showdown is installed, and typenode ./bin/showdown.js -hin the command line:=== "input"
text```sh node ./bin/showdown.js -h ```=== "output"
text``` Usage: showdown <command> [options] CLI to Showdownjs markdown parser v3.0.0 Options: -V, --version output the version number -q, --quiet Quiet mode. Only print errors -m, --mute Mute mode. Does not print anything -v, --verbose Verbose mode. Print extra information about the conversion --color Force colored output even when the output is not a terminal --no-color Disable colored output -h, --help display help for command Commands: makehtml [options] Converts markdown into html makemarkdown [options] Converts html into markdown help [command] display help for command ```
Use
makehtmlcommand to convert your document to HTML. For example:!!! example "Convert
foo.mdintobar.html"text```sh showdown makehtml -i foo.md -o bar.html ```
Commands
`makehtml`
Convert a Markdown input into HTML.
Usage
showdown makehtml [options]Options
`-i / --input`
Short format:
-iAlias:
--inputDescription: Input source. One or more
.mdfiles (or glob patterns). If omitted or empty, reads fromstdin.Notes:
- Multiple inputs can be passed at once:
-i a.md b.md c.md. - Glob patterns (
*,?) are supported. Your shell normally expands them; on Windows (or
when the pattern is quoted) Showdown expands a single-level pattern itself, e.g.-i "*.md".
- Multiple inputs can be passed at once:
Examples:
!!! example ""
text```sh // Read from stdin and output to stdout showdown makehtml -i // Read from the foo.md file and output to stdout showdown makehtml --input foo.md // Convert several files at once showdown makehtml -i a.md b.md -o out/ // Convert every markdown file in the current directory showdown makehtml -i *.md -o out/ ```
`-o/--output`
Short format:
-oAlias:
--outputDescription: Output target. Usually a
.htmlfile. If omitted or empty, writes tostdout.Multiple inputs (batch mode):
- If
-ois a directory (an existing directory, or a path ending in a separator such
asout/), each result is written there using the source basename with the extension
swapped (foo.mdโfoo.html). The directory is created if it does not exist. - If
-ois omitted, each result is written beside its source file. - Passing a single output file with multiple inputs is an error (it would overwrite itself).
- Batch conversion continues past individual file errors and exits non-zero if any file failed.
- If
A single input can also be sent to a directory the same way (e.g.
-o out/writesout/<name>.html).Example:
!!! example ""
text```sh // Read from the foo.md file and output to bar.html showdown makehtml -i foo.md -o bar.html // Convert many files into an output directory showdown makehtml -i *.md -o build/ ```
`-a/--append`
Short format:
-aAlias:
--appendDescription: Append data to output instead of overwriting.
Example:
!!! example ""
text```sh showdown makehtml -a ```
`-u/--encoding`
Short format:
-uAlias:
--encodingDescription: Specify the input encoding.
Example:
!!! example ""
text```sh showdown makehtml -u UTF8 ```
`-y/--output-encoding`
Short format:
-yAlias:
--output-encodingDescription: Specify the output encoding. Defaults to
utf8.Example:
!!! example ""
text```sh showdown makehtml -i foo.md -o bar.html -y latin1 ```
`-e/--extensions`
Short format:
-eAlias:
--extensionsDescription: Load the specified extension(s). Each value is a path to a Node-compatible
extension (relative, absolute, or~/-prefixed), or the name of an installed npm package
(a bare specifier is passed straight torequire()).Example:
!!! example ""
text```sh showdown makehtml -e ~/twitter.js -e ~/youtube.js showdown makehtml -e showdown-katex # an installed npm package ```
`-p/--flavor`
Short format:
-pAlias:
--flavorDescription: Run with a predetermined flavor of options. Defaults to
vanilla.Available flavors:
gfm,original,commonmark,vanilla(githubis a backwards-compatible
alias forgfm). Use--list-flavorsto print the list at any time. An unrecognised flavor is
reported as an error listing the valid flavors.Example:
!!! example ""
text```sh showdown makehtml -i foo.md -o bar.html -p github showdown makehtml --list-flavors ```
`-c/--config`
Short format:
-cAlias:
--configDescription: Enable or disable parser options.
Introduced in:
2.0.1(Breaking change. See theExtra optionssection below)Value handling:
- A bare option name enables a boolean option:
-c strikethrough. - Booleans can also be set explicitly with
=true/=false. Use=falseto disable an
option that a flavor enables, e.g.-p gfm -c tables=false. - Number options take a numeric value:
-c headerLevelStart=2. - String options take a string value:
-c ghMentionsLink=https://github.com/{u}. - Values are coerced to the option's declared type. Unknown option names and values that
do not match the option type are reported as warnings and ignored.
- A bare option name enables a boolean option:
Example:
!!! example ""
text```sh showdown makehtml -i foo.md -o bar.html -c strikethrough showdown makehtml -i foo.md -o bar.html -c strikethrough -c emoji showdown makehtml -i foo.md -o bar.html -c headerLevelStart=2 showdown makehtml -i foo.md -o bar.html -p gfm -c tables=false ```
`--config-help`
Description: Print every Showdown parser option โ with its default value and description โ then
exit without converting. Use it to discover what you can pass to-c.Example:
!!! example ""
text```sh showdown makehtml --config-help ```
`--list-flavors`
Description: List the available flavors (the default,
vanilla, is marked) and exit
without converting.Example:
!!! example ""
text```sh showdown makehtml --list-flavors ```
`makemarkdown`
Convert an HTML input into Markdown (the reverse of makehtml).
Usage
showdown makemarkdown [options]Options
makemarkdown accepts the same options as makehtml: -i/--input, -o/--output,-a/--append, -u/--encoding, -y/--output-encoding, -e/--extensions, -p/--flavor,-c/--config, --config-help and --list-flavors. Here the input is HTML and the output is Markdown.
Examples:
!!! example ""
text```sh // Read from stdin and output to stdout showdown makemarkdown -i // Convert foo.html into bar.md showdown makemarkdown -i foo.html -o bar.md ```
Output verbosity and color
These are global flags โ place them before the command (showdown -v makehtml ...) or after it,
they apply to both makehtml and makemarkdown.
`-q/--quiet`
- Description: Quiet mode. Suppresses informational messages; only errors (and the final
DONE!) are printed.
`-m/--mute`
- Description: Mute mode. Suppresses everything, including error messages. The converted output is still produced.
`-v/--verbose`
Description: Verbose mode. Prints extra diagnostic information (resolved input files, per-file
source -> targetmappings in batch mode, input sizes and total time). Ignored when-q/-mis set.Example:
!!! example ""
text```sh showdown makehtml -v -i *.md -o build/ ```
`--color` / `--no-color`
- Description: Controls colorization of the status/diagnostic messages (the converted output itself
is never colored). - Default: color is enabled automatically only when the message stream is a terminal (TTY). The
NO_COLORandFORCE_COLORenvironment variables are honored. --colorforces colored output even when the output is redirected;--no-colordisables it.
Extra options
Starting from the version 2.0.1, CLI the format of passing extra options has changed. Please make the necessary changes to your code, if required.
=== "since v2.0.1"
```sh
showdown makehtml -i foo.md -o bar.html -c strikethrough -c emoji
```=== "before v2.0.1"
```sh
showdown makehtml -i foo.md -o bar.html --strikethrough --emoji
```You can specify any of the supported options, and they will be passed to the converter.
The above commands are equivalent of doing:
var conv = new showdown.Converter({strikethrough: true, emoji: true});!!! note ""
The CLI runs with the vanilla flavor by default, which is the same set of defaults used by
the node and browser builds. This means a few options, such as ghCodeBlocks, ellipsis and
encodeEmails, are enabled out of the box. Use a different flavor with -p or override
individual options with -c <option>=true|false.
File: docs/create-extension.md
A Showdown extension is a function that returns an array of sub-extensions (henceforth called "sub-extensions"). The modern, recommended kind is the listener sub-extension, which hooks the event system; the older lang and output kinds are still supported but deprecated.
var myext = function () {
var myext1 = {
type: 'listener',
listeners: {
'makehtml.blockquote.onCapture': function (evt) {
evt.attributes['class'] = 'fancy-quote';
return evt;
}
}
};
var myext2 = {
/* extension code */
};
return [myext1, myext2];
}Each sub-extension (myext1 and myext2 in the example above) should be an object that defines the behavior of the corresponding sub-extension.
Sub-extension object properties
A sub-extension object should have a type property that defines the type of the sub-extension, plus:
- for the
listenertype: alistenersproperty; - for the legacy
lang/outputtypes: eitherregexandreplaceproperties or afilterproperty.
Type
Type is a required property that defines the nature of the corresponding sub-extensions. It takes one of three values, listener being the recommended one:
listener: listener extension to hook the event system and inspect or modify a sub-parser's captures, matches, attributes, or output mid-conversion. This is the main extension mode and the one to reach for in new code.Unlike the legacy
lang/outputextensions, alistenerextension does not useregex/replaceorfilter. Instead, it defines alistenersobject. See Listener extensions below.!!! example "When to use
listenertype"textFor example, if you want to add a `class` attribute to every blockquote, or rewrite the captured text of a specific construct without re-implementing its sub-parser.
The remaining two types are the legacy extension modes. They still work, but each one now runs as a thin wrapper over a document-level event, and loading one logs a deprecation warning โ prefer a listener extension instead.
lang(deprecated): language extension to add new Markdown syntax to Showdown.langextensions have the highest priority in the subparser order, so they are called after escaping and normalizing the input text and before calling any other subparser (or extension).!!! example "When to use
langtype"textFor example, if you want the `^^youtube http://www.youtube.com/watch?v=oHg5SJYRHA0` syntax to automatically be rendered as an embedded YouTube video.!!! warning "Deprecated"
langextensions are now sugar over the event system: each one is registered as a listener on themakehtml.onPreParseevent. They are deprecated and loading one logs a deprecation warning โ prefer writing alistenerextension onmakehtml.onPreParse(ormakehtml.onStartif you need the raw, pre-escape source) directly.output(deprecated): output extension (or modifier) to alter the HTML output generated by Showdown.outputextensions have the lowest priority in the subparser order, so they are called right before the cleanup step and after calling all other subparsers.!!! example "When to use
outputtype"textFor example, if you want the `` to become `<header>`.!!! warning "Deprecated"
outputextensions are now sugar over the event system: each one is registered as a listener on themakehtml.onEndevent. They are deprecated and loading one logs a deprecation warning โ prefer writing alistenerextension onmakehtml.onEnddirectly.
Listener extensions
A listener sub-extension hooks the event system. Instead of regex/replace or filter, it defines a listeners property: an object that maps event names to callback functions.
showdown.extension('addBlockquoteClass', function () {
return [{
type: 'listener',
listeners: {
'makehtml.blockquote.onCapture': function (evt) {
// add a class attribute to every blockquote
evt.attributes['class'] = 'fancy-quote';
return evt;
}
}
}];
});
var converter = new showdown.Converter({ extensions: ['addBlockquoteClass'] });Each callback receives a showdown.Event object and must return it (after any modifications). What you can read or change depends on the event โ see the event types and their property tables.
!!! warning ""
The listeners property is required for listener extensions and must be a hash of [event name]: [callback function]. An invalid shape throws on registration.
!!! hint "converter.listen() vs a listener extension"
A listener extension is the reusable, registrable form. If you only need to attach a one-off handler to a single converter, you can call converter.listen(eventName, callback) directly instead.
Regex and replace
!!! warning "Legacy modes"
The regex/replace and filter properties described in this and the next section apply only to the deprecated lang and output extension types. In new code, prefer a listener extension instead.
regex/replace properties are similar to the Javascript's string.replace function and work the same way:
regex: astringor aRegExpobject.If
regexis astring, it will automatically be assigned ag(global) modifier, that is, all matches of that string will be replaced.replaceastringor afunction.If
replaceis astring, you can use the$1syntax for group substitution, exactly as if it were making use ofstring.replace.
!!! example "Regex and replace example"
In this example, all the occurrences of `markdown` will be replaced with `showndown`.
```js
var myext = {
type: 'lang',
regex: /markdown/g,
replace: 'showdown'
};
```Filter
Alternately, if you'd like to have more control over the modification process, you can use filter property.
This property should be used as a function that acts as a callback. The callback should receive the following parameters:
text: the source text within the Showdown's engine.converter: the full instance of the current Showdown's converter object.options: the options used to initialize the converter
!!! warning ""
The filter function should return the transformed text. If it returns nothing, your transformation is silently skipped and the text passes through unchanged.
!!! note ""
lang/output extensions now run as listeners on the document-level makehtml.onPreParse / makehtml.onEnd events, so the options passed to filter is a read-only copy of the converter's options. Reading it works as before; mutating it has no effect on the conversion (mutating options was never supported anyway).
!!! example "Filter example"
```js
var myext = {
type: 'lang',
filter: function (text, converter, options) {
// ... do stuff to text ...
return text;
}
};
```!!! warning "Use filter with care"
Although Filter extensions are more powerful, they have a few pitfalls that you should keep in mind before using them, especially regarding the `converter` parameter.
Since the `converter` parameter passed to the filter function is the fully initialized instance, any change made to it will be propagated outside the scope of the filter function and will remain there until a new converter instance is created. So, **it is not recommended to make ANY change to the converter object**.
Another aspect is that if you call the `converter` recursively, it will call your extension itself at some point. It may lead to infinite recursion in some circumstances, and it's up to you to prevent this. A simple solution is to place a kind of safeguard to disable your extension if it's called more than x times:
```js
var x = 0;
var myext = {
type: 'lang',
filter: function (text, converter) {
if (x < 3) {
++x;
someSubText = converter.makeHtml(someSubText);
}
}
};
```Register an extension
To let Showdown know what extensions are available, you need to register them in the Showdown global object.
To register an extension, call the showdown.extension function with two parameters: the first one is the extension name; the second one is the actual extension.
showdown.extension('myext', myext);Test an extension
An extension is tested the same way as any other Showdown behavior: instantiate aConverter configured with the extension and assert on the output ofmakeHtml().
var showdown = require('showdown');
showdown.extension('myext', myExtension);
var converter = new showdown.Converter({ extensions: ['myext'] });
converter.makeHtml('markdown') === 'showdown'; // assert this!!! hint ""
The project's own behavioral tests are data-driven fixture pairs: for every
<name>.md file there is a sibling <name>.html with the expected output (see the
suites under test/functional/makehtml/). If you contribute an extension to Showdown,
follow that pattern by adding a fixture pair and wiring up a converter configured with
your extension.
Additional information
Utilities (`showdown.helper`)
You may come across a showdown.helper object exposing utilities such as escapeHTMLEntities,isString, regexes and various string/URL helpers. showdown.helper is internal machinery:
it carries no stability guarantees across releases and may change, be renamed, or disappear
without notice. It is not part of the supported extension API. Build your extensions on the
event system (listener extensions) instead โ that is the supported surface for
inspecting and modifying a conversion, and the one we keep stable.
Escape and normalization
Showdown performs the following escape/normalization:
- Replaces
ยจ(trema) withยจT - Replaces
$(dollar sign) withยจD - Normalizes line endings (
\r,\r\nare converted into\n) - Uses
\ras a char placeholder
!!! note ""
This only applies to language extensions since these chars are unescaped before output extensions are run.
!!! warning ""
Keep in mind that these modifications happen **before language extensions** are run, so if your extension relies on any of those chars, you have to make the appropriate adjustments.Implementation concerns
One of the concerns is maintaining both client-side and server-side compatibility. You can do this with a few lines of boilerplate code.:
(function (extension) {
if (typeof showdown !== 'undefined') {
// global (browser or node.js global)
extension(showdown);
} else if (typeof define === 'function' && define.amd) {
// AMD
define(['showdown'], extension);
} else if (typeof exports === 'object') {
// Node, CommonJS-like
module.exports = extension(require('showdown'));
} else {
// showdown was not found so an error is thrown
throw Error('Could not find showdown library');
}
}(function (showdown) {
// loading extension into showdown
showdown.extension('myext', function () {
var myext = { /* ... actual extension code ... */ };
return [myext];
});
}));In the code above, the extension definition is wrapped in a self-executing function to prevent pollution of the global scope. It has another benefit of creating several scope layers that can be useful for interaction between sub-extensions global-wise or local-wise.
It is also loaded conditionally to make it compatible with different loading mechanisms (such as browser, CommonJS, or AMD).