mirror of
https://github.com/showdownjs/showdown.git
synced 2024-03-22 13:30:55 +08:00
Added new extension registering method
This commit is contained in:
parent
8ee87ead9f
commit
0fd10cb56a
BIN
dist/showdown.js
vendored
BIN
dist/showdown.js
vendored
Binary file not shown.
BIN
dist/showdown.js.map
vendored
BIN
dist/showdown.js.map
vendored
Binary file not shown.
BIN
dist/showdown.min.js
vendored
BIN
dist/showdown.min.js
vendored
Binary file not shown.
BIN
dist/showdown.min.js.map
vendored
BIN
dist/showdown.min.js.map
vendored
Binary file not shown.
|
@ -8,6 +8,7 @@ if (!showdown.hasOwnProperty('helper')) {
|
|||
|
||||
/**
|
||||
* Check if var is string
|
||||
* @static
|
||||
* @param {string} a
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
@ -18,6 +19,7 @@ showdown.helper.isString = function isString(a) {
|
|||
|
||||
/**
|
||||
* ForEach helper function
|
||||
* @static
|
||||
* @param {*} obj
|
||||
* @param {function} callback
|
||||
*/
|
||||
|
@ -26,8 +28,7 @@ showdown.helper.forEach = function forEach(obj, callback) {
|
|||
if (typeof obj.forEach === 'function') {
|
||||
obj.forEach(callback);
|
||||
} else {
|
||||
var i, len = obj.length;
|
||||
for (i = 0; i < len; i++) {
|
||||
for (var i = 0; i < obj.length; i++) {
|
||||
callback(obj[i], i, obj);
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +36,7 @@ showdown.helper.forEach = function forEach(obj, callback) {
|
|||
|
||||
/**
|
||||
* isArray helper function
|
||||
* @static
|
||||
* @param {*} a
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
@ -45,7 +47,6 @@ showdown.helper.isArray = function isArray(a) {
|
|||
|
||||
/**
|
||||
* Check if value is undefined
|
||||
*
|
||||
* @static
|
||||
* @param {*} value The value to check.
|
||||
* @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
|
||||
|
@ -55,6 +56,17 @@ showdown.helper.isUndefined = function isUndefined(value) {
|
|||
return typeof value === 'undefined';
|
||||
};
|
||||
|
||||
/**
|
||||
* Standardidize extension name
|
||||
* @static
|
||||
* @param {string} s extension name
|
||||
* @returns {string}
|
||||
*/
|
||||
showdown.helper.stdExtName = function (s) {
|
||||
'use strict';
|
||||
return s.replace(/[_-]||\s/g, '').toLowerCase();
|
||||
};
|
||||
|
||||
function escapeCharactersCallback(wholeMatch, m1) {
|
||||
'use strict';
|
||||
var charCodeToEscape = m1.charCodeAt(0);
|
||||
|
@ -63,6 +75,7 @@ function escapeCharactersCallback(wholeMatch, m1) {
|
|||
|
||||
/**
|
||||
* Callback used to escape characters when passing through String.replace
|
||||
* @static
|
||||
* @param {string} wholeMatch
|
||||
* @param {string} m1
|
||||
* @returns {string}
|
||||
|
@ -71,7 +84,7 @@ showdown.helper.escapeCharactersCallback = escapeCharactersCallback;
|
|||
|
||||
/**
|
||||
* Escape characters in a string
|
||||
*
|
||||
* @static
|
||||
* @param {string} text
|
||||
* @param {string} charsToEscape
|
||||
* @param {boolean} afterBackslash
|
||||
|
|
121
src/showdown.js
121
src/showdown.js
|
@ -5,32 +5,24 @@
|
|||
// Private properties
|
||||
var showdown = {},
|
||||
parsers = {},
|
||||
extensions = {},
|
||||
globalOptions = {
|
||||
omitExtraWLInCodeBlocks: false,
|
||||
prefixHeaderId: false
|
||||
prefixHeaderId: false
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Public API
|
||||
//
|
||||
/**
|
||||
* helper namespace
|
||||
* @type {{}}
|
||||
*/
|
||||
showdown.helper = {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
//
|
||||
|
||||
// Public properties
|
||||
showdown.extensions = {};
|
||||
|
||||
//Public methods
|
||||
|
||||
/**
|
||||
* Set a global option
|
||||
*
|
||||
* @static
|
||||
* @param {string} key
|
||||
* @param {string} value
|
||||
* @returns {showdown}
|
||||
|
@ -43,7 +35,7 @@ showdown.setOption = function (key, value) {
|
|||
|
||||
/**
|
||||
* Get a global option
|
||||
*
|
||||
* @static
|
||||
* @param {string} key
|
||||
* @returns {*}
|
||||
*/
|
||||
|
@ -54,6 +46,7 @@ showdown.getOption = function (key) {
|
|||
|
||||
/**
|
||||
* Get the global options
|
||||
* @static
|
||||
* @returns {{omitExtraWLInCodeBlocks: boolean, prefixHeaderId: boolean}}
|
||||
*/
|
||||
showdown.getOptions = function () {
|
||||
|
@ -66,6 +59,7 @@ showdown.getOptions = function () {
|
|||
*
|
||||
* subParser(name) - Get a registered subParser
|
||||
* subParser(name, func) - Register a subParser
|
||||
* @static
|
||||
* @param {string} name
|
||||
* @param {function} [func]
|
||||
* @returns {*}
|
||||
|
@ -85,6 +79,47 @@ showdown.subParser = function (name, func) {
|
|||
}
|
||||
};
|
||||
|
||||
showdown.extension = function (name, ext) {
|
||||
'use strict';
|
||||
|
||||
if (!showdown.helper.isString(name)) {
|
||||
throw Error('Extension \'name\' must be a string');
|
||||
}
|
||||
|
||||
name = showdown.helper.stdExtName(name);
|
||||
|
||||
if (showdown.helper.isUndefined(ext)) {
|
||||
return getExtension();
|
||||
} else {
|
||||
return setExtension();
|
||||
}
|
||||
};
|
||||
|
||||
function getExtension(name) {
|
||||
'use strict';
|
||||
|
||||
if (!extensions.hasOwnProperty(name)) {
|
||||
throw Error('Extension named ' + name + ' is not registered!');
|
||||
}
|
||||
return extensions[name];
|
||||
}
|
||||
|
||||
function setExtension(name, ext) {
|
||||
'use strict';
|
||||
|
||||
if (typeof ext !== 'object') {
|
||||
throw Error('A Showdown Extension must be an object, ' + typeof ext + ' given');
|
||||
}
|
||||
|
||||
if (!showdown.helper.isString(ext.type)) {
|
||||
throw Error('When registering a showdown extension, "type" must be a string, ' + typeof ext.type + ' given');
|
||||
}
|
||||
|
||||
ext.type = ext.type.toLowerCase();
|
||||
|
||||
extensions[name] = ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Showdown Converter class
|
||||
*
|
||||
|
@ -97,10 +132,9 @@ showdown.Converter = function (converterOptions) {
|
|||
converterOptions = converterOptions || {};
|
||||
|
||||
var options = globalOptions,
|
||||
langExtensions = [],
|
||||
outputModifiers = [],
|
||||
parserOrder = [
|
||||
'detab',
|
||||
'stripBlankLines',
|
||||
//runLanguageExtensions,
|
||||
'githubCodeBlocks',
|
||||
'hashHTMLBlocks',
|
||||
'stripLinkDefinitions',
|
||||
|
@ -117,6 +151,38 @@ showdown.Converter = function (converterOptions) {
|
|||
}
|
||||
}
|
||||
|
||||
// Parse options
|
||||
if (options.extensions) {
|
||||
|
||||
// Iterate over each plugin
|
||||
showdown.helper.forEach(options.extensions, function (plugin) {
|
||||
|
||||
// Assume it's a bundled plugin if a string is given
|
||||
if (typeof plugin === 'string') {
|
||||
plugin = extensions[showdown.helper.stdExtName(plugin)];
|
||||
}
|
||||
|
||||
if (typeof plugin === 'function') {
|
||||
// Iterate over each extension within that plugin
|
||||
showdown.helper.forEach(plugin(self), function (ext) {
|
||||
// Sort extensions by type
|
||||
if (ext.type) {
|
||||
if (ext.type === 'language' || ext.type === 'lang') {
|
||||
langExtensions.push(ext);
|
||||
} else if (ext.type === 'output' || ext.type === 'html') {
|
||||
outputModifiers.push(ext);
|
||||
}
|
||||
} else {
|
||||
// Assume language extension
|
||||
outputModifiers.push(ext);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
throw 'Extension "' + plugin + '" could not be loaded. It was either not found or is not a valid extension.';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a markdown string into HTML
|
||||
* @param {string} text
|
||||
|
@ -130,11 +196,13 @@ showdown.Converter = function (converterOptions) {
|
|||
}
|
||||
|
||||
var globals = {
|
||||
gHtmlBlocks: [],
|
||||
gUrls: {},
|
||||
gTitles: {},
|
||||
gListLevel: 0,
|
||||
hashLinkCounts: {}
|
||||
gHtmlBlocks: [],
|
||||
gUrls: {},
|
||||
gTitles: {},
|
||||
gListLevel: 0,
|
||||
hashLinkCounts: {},
|
||||
langExtensions: langExtensions,
|
||||
outputModifiers: outputModifiers
|
||||
};
|
||||
|
||||
// attacklab: Replace ~ with ~T
|
||||
|
@ -155,6 +223,15 @@ showdown.Converter = function (converterOptions) {
|
|||
// Make sure text begins and ends with a couple of newlines:
|
||||
text = '\n\n' + text + '\n\n';
|
||||
|
||||
// detab
|
||||
text = parsers.detab(text, options, globals);
|
||||
|
||||
// stripBlankLines
|
||||
text = parsers.stripBlankLines(text, options, globals);
|
||||
|
||||
//run languageExtensions
|
||||
text = parsers.languageExtensions(text, options, globals);
|
||||
|
||||
// Run all registered parsers
|
||||
for (var i = 0; i < parserOrder.length; ++i) {
|
||||
var name = parserOrder[i];
|
||||
|
@ -168,9 +245,7 @@ showdown.Converter = function (converterOptions) {
|
|||
text = text.replace(/~T/g, '~');
|
||||
|
||||
// Run output modifiers
|
||||
//showdown.forEach(g_output_modifiers, function (x) {
|
||||
// text = _ExecuteExtension(x, text);
|
||||
//});
|
||||
text = parsers.outputModifiers(text, options, globals);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
|
11
src/subParsers/languageExtensions.js
Normal file
11
src/subParsers/languageExtensions.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* Run language extensions
|
||||
*/
|
||||
showdown.subParser('languageExtensions', function (text, config, globals) {
|
||||
'use strict';
|
||||
|
||||
showdown.helper.forEach(globals.langExtensions, function (ext) {
|
||||
text = showdown.subParser('runExtension')(ext, text);
|
||||
});
|
||||
return text;
|
||||
});
|
11
src/subParsers/outputModifiers.js
Normal file
11
src/subParsers/outputModifiers.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* Run language extensions
|
||||
*/
|
||||
showdown.subParser('outputModifiers', function (text, config, globals) {
|
||||
'use strict';
|
||||
|
||||
showdown.helper.forEach(globals.outputModifiers, function (ext) {
|
||||
text = showdown.subParser('runExtension')(ext, text);
|
||||
});
|
||||
return text;
|
||||
});
|
13
src/subParsers/runExtension.js
Normal file
13
src/subParsers/runExtension.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* Run language extensions
|
||||
*/
|
||||
showdown.subParser('runExtension', function (ext, text) {
|
||||
'use strict';
|
||||
|
||||
if (ext.regex) {
|
||||
var re = new RegExp(ext.regex, 'g');
|
||||
return text.replace(re, ext.replace);
|
||||
} else if (ext.filter) {
|
||||
return ext.filter(text);
|
||||
}
|
||||
});
|
Loading…
Reference in New Issue
Block a user