149 lines
3.6 KiB
JavaScript
149 lines
3.6 KiB
JavaScript
/*!
|
|
* WMD - Wanton Markdown
|
|
* Copyright (c) 2010 Caolan McMahon
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
* Main function for converting markdown to HTML.
|
|
*
|
|
* @param {String} content
|
|
* @param {Object} options
|
|
* @return {String}
|
|
* @api public
|
|
*/
|
|
|
|
var WMD = function (content, options) {
|
|
var doc = {raw: content, markdown: content};
|
|
var opt = WMD.readOptions(options);
|
|
WMD.preprocess(doc, opt);
|
|
doc.html = WMD.processor(doc.markdown);
|
|
WMD.postprocess(doc, opt);
|
|
doc.toString = function () {
|
|
return doc.html;
|
|
};
|
|
return doc;
|
|
};
|
|
|
|
|
|
function gsub(str, re, fn, /*optional*/newstr) {
|
|
newstr = newstr || '';
|
|
var match = re.exec(str);
|
|
if (match) {
|
|
newstr += str.slice(0, match.index);
|
|
newstr += fn.apply(null, match);
|
|
remaining = str.slice(match.index + match[0].length);
|
|
return gsub(remaining, re, fn, newstr);
|
|
}
|
|
return newstr + str;
|
|
}
|
|
|
|
WMD.processor = new Showdown.converter().makeHtml;
|
|
|
|
WMD.preprocessors = {
|
|
|
|
underscores: function (doc) {
|
|
// prevent foo_bar_baz from ending up with an italic word in the middle
|
|
doc.markdown = gsub(doc.markdown,
|
|
/(^(?! {4}|\t)\w+_\w+_\w[\w_]*)/, function (match) {
|
|
var count = 0;
|
|
for (var i = 0; i < match.length; i++) {
|
|
if (match[i] == '_') count++;
|
|
}
|
|
if (count === 2) {
|
|
return match.replace(/_/g, '\\_');
|
|
}
|
|
return match;
|
|
}
|
|
);
|
|
return doc;
|
|
},
|
|
|
|
metadata: function (doc) {
|
|
var key;
|
|
var lines = doc.markdown.split('\n');
|
|
doc.metadata = {};
|
|
|
|
while (lines.length) {
|
|
var match = /^(\S+):\s+(.*)$/.exec(lines[0]);
|
|
if (match) {
|
|
var key = match[1];
|
|
doc.metadata[key] = match[2];
|
|
lines.shift();
|
|
}
|
|
else {
|
|
var continued_value = /^\s+(.+)$/.exec(lines[0]);
|
|
// strip empty lines
|
|
if (/^\s*$/.exec(lines[0])) {
|
|
lines.shift();
|
|
}
|
|
else if (continued_value && key) {
|
|
doc.metadata[key] += '\n' + continued_value[1];
|
|
lines.shift();
|
|
}
|
|
else break;
|
|
}
|
|
}
|
|
doc.markdown = lines.join('\n');
|
|
return doc;
|
|
}
|
|
};
|
|
|
|
WMD.postprocessors = {};
|
|
|
|
/**
|
|
* Extends a default set of options with those passed to it.
|
|
*
|
|
* @param {Object} options
|
|
* @return {Object}
|
|
* @api public
|
|
*/
|
|
|
|
WMD.readOptions = function (options) {
|
|
var obj = {
|
|
preprocessors: [
|
|
WMD.preprocessors.metadata,
|
|
WMD.preprocessors.underscores
|
|
],
|
|
postprocessors: []
|
|
};
|
|
for (var k in options) {
|
|
obj[k] = options[k];
|
|
}
|
|
return obj;
|
|
};
|
|
|
|
/**
|
|
* Runs all the preprocessors defined in options on the doc object.
|
|
* This is executed before passing the doc's markdown property to the processor
|
|
* function to be turned into HTML.
|
|
*
|
|
* @param {Object} doc
|
|
* @param {Object} options
|
|
* @return {String}
|
|
* @api public
|
|
*/
|
|
|
|
WMD.preprocess = function (doc, options) {
|
|
return options.preprocessors.reduce(function (doc, fn) {
|
|
return fn(doc);
|
|
}, doc);
|
|
};
|
|
|
|
/**
|
|
* Runs all the postprocessors defined in options on the doc object.
|
|
* This is executed after passing the doc's markdown property to the processor
|
|
* function to be turned into HTML.
|
|
*
|
|
* @param {Object} doc
|
|
* @param {Object} options
|
|
* @return {String}
|
|
* @api public
|
|
*/
|
|
|
|
WMD.postprocess = function (doc, options) {
|
|
return options.postprocessors.reduce(function (doc, fn) {
|
|
return fn(doc);
|
|
}, doc);
|
|
}; |