omitExtraWLInCodeBlocks: {
describe: 'Omit the default extra whiteline added to code blocks',
describe: 'Turn on/off generated header id',
describe: 'Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to true will add a generic \'section-\' prefix',
describe: 'Setting this option to true will prevent showdown from modifying the prefix. This might result in malformed IDs (if, for instance, the " char is used in the prefix)',
describe: 'Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)',
describe: 'Remove only spaces, \' and " from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids',
describe: 'The header blocks level start',
describe: 'Turn on/off image dimension parsing',
describe: 'Turn on/off GFM autolink style',
excludeTrailingPunctuationFromURLs: {
describe: 'Excludes trailing punctuation from links generated with autoLinking',
literalMidWordUnderscores: {
describe: 'Parse midword underscores as literal underscores',
literalMidWordAsterisks: {
describe: 'Parse midword asterisks as literal asterisks',
describe: 'Turn on/off strikethrough support',
describe: 'Turn on/off tables support',
describe: 'Add an id to table headers',
describe: 'Turn on/off GFM fenced code blocks support',
describe: 'Turn on/off GFM tasklist support',
describe: 'Prevents weird effects in live previews due to incomplete input',
description: 'Tries to smartly fix indentation in es6 strings',
disableForced4SpacesIndentedSublists: {
description: 'Disables the requirement of indenting nested sublists by 4 spaces',
description: 'Parses simple line breaks as <br> (GFM Style)',
requireSpaceBeforeHeadingText: {
description: 'Makes adding a space between `#` and the header text mandatory (GFM Style)',
description: 'Enables github @mentions',
defaultValue: 'https://github.com/{u}',
description: 'Changes the link generated by @mentions. Only applies if ghMentions option is enabled.',
description: 'Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities',
description: 'Open all links in new windows',
backslashEscapesHTMLTags: {
description: 'Support for HTML Tag escaping. ex: \<div>foo\</div>',
description: 'Enable emoji support. Ex: `this is a :smile: emoji`',
description: 'Enable support for underline. Syntax is double or triple underscores: `__underline word__`. With this option enabled, underscores no longer parses into `<em>` and `<strong>`',
description: 'Outputs a complete html document, including `<html>`, `<head>` and `<body>` tags',
description: 'Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).',
splitAdjacentBlockquotes: {
description: 'Split adjacent blockquote blocks',
return JSON.parse(JSON.stringify(defaultOptions));
for (var opt in defaultOptions) {
if (defaultOptions.hasOwnProperty(opt)) {
ret[opt] = defaultOptions[opt].defaultValue;
function allOptionsOn () {
var options = getDefaultOpts(true),
for (var opt in options) {
if (options.hasOwnProperty(opt)) {
* Created by Tivie on 06-01-2015.
globalOptions = getDefaultOpts(true),
omitExtraWLInCodeBlocks: true,
simplifiedAutoLink: true,
excludeTrailingPunctuationFromURLs: true,
literalMidWordUnderscores: true,
disableForced4SpacesIndentedSublists: true,
requireSpaceBeforeHeadingText: true,
ghCompatibleHeaderId: true,
backslashEscapesHTMLTags: true,
splitAdjacentBlockquotes: true
omitExtraWLInCodeBlocks: true,
parseImgDimensions: true,
simplifiedAutoLink: true,
excludeTrailingPunctuationFromURLs: true,
literalMidWordUnderscores: true,
requireSpaceBeforeHeadingText: true,
vanilla: getDefaultOpts(true),
* TODO LEGACY SUPPORT CODE
showdown.extensions = {};
showdown.setOption = function (key, value) {
globalOptions[key] = value;
showdown.getOption = function (key) {
return globalOptions[key];
showdown.getOptions = function () {
* Reset global options to the default values
showdown.resetOptions = function () {
globalOptions = getDefaultOpts(true);
* Set the flavor showdown should use as default
showdown.setFlavor = function (name) {
if (!flavor.hasOwnProperty(name)) {
throw Error(name + ' flavor was not found');
var preset = flavor[name];
for (var option in preset) {
if (preset.hasOwnProperty(option)) {
globalOptions[option] = preset[option];
* Get the currently set flavor
showdown.getFlavor = function () {
* Get the options of a specified flavor. Returns undefined if the flavor was not found
* @param {string} name Name of the flavor
* @returns {{}|undefined}
showdown.getFlavorOptions = function (name) {
if (flavor.hasOwnProperty(name)) {
* Get the default options
* @param {boolean} [simple=true]
showdown.getDefaultOptions = function (simple) {
return getDefaultOpts(simple);
* subParser(name) - Get a registered subParser
* subParser(name, func) - Register a subParser
* @param {function} [func]
showdown.subParser = function (name, func) {
if (showdown.helper.isString(name)) {
if (typeof func !== 'undefined') {
if (parsers.hasOwnProperty(name)) {
throw Error('SubParser named ' + name + ' not registered!');
* Gets or registers an extension
* @param {object|function=} ext
showdown.extension = function (name, ext) {
if (!showdown.helper.isString(name)) {
throw Error('Extension \'name\' must be a string');
name = showdown.helper.stdExtName(name);
if (showdown.helper.isUndefined(ext)) {
if (!extensions.hasOwnProperty(name)) {
throw Error('Extension named ' + name + ' is not registered!');
// Expand extension if it's wrapped in a function
if (typeof ext === 'function') {
// Ensure extension is an array
if (!showdown.helper.isArray(ext)) {
var validExtension = validate(ext, name);
if (validExtension.valid) {
throw Error(validExtension.error);
* Gets all extensions registered
showdown.getAllExtensions = function () {
showdown.removeExtension = function (name) {
showdown.resetExtensions = function () {
* @param {array} extension
* @returns {{valid: boolean, error: string}}
function validate (extension, name) {
var errMsg = (name) ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension',
if (!showdown.helper.isArray(extension)) {
for (var i = 0; i < extension.length; ++i) {
var baseMsg = errMsg + ' sub-extension ' + i + ': ',
if (typeof ext !== 'object') {
ret.error = baseMsg + 'must be an object, but ' + typeof ext + ' given';
if (!showdown.helper.isString(ext.type)) {
ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + ' given';
var type = ext.type = ext.type.toLowerCase();
// normalize extension type
if (type === 'language') {
type = ext.type = 'lang';
type = ext.type = 'output';
if (type !== 'lang' && type !== 'output' && type !== 'listener') {
ret.error = baseMsg + 'type ' + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"';
if (type === 'listener') {
if (showdown.helper.isUndefined(ext.listeners)) {
ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"';