Skip to content

Instantly share code, notes, and snippets.

@pachacamac
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pachacamac/e3a8dbb2100ee5d16dae to your computer and use it in GitHub Desktop.
Save pachacamac/e3a8dbb2100ee5d16dae to your computer and use it in GitHub Desktop.
tiny javascript markdown parser
/*tinyMd based on https://github.com/SimonWaldherr/micromarkdown.js*/
var tinyMd = {
regexobject: {
headline: /^(\#{1,6})([^\#\n]+)$/m,
code: /\s\`\`\`\n?([^`]+)\`\`\`/g,
hr: /^(?:([\*\-_] ?)+)\1\1$/gm,
lists: /^((\s*((\*|\-)|\d(\.|\))) [^\n]+)\n)+/gm,
bolditalic: /(?:([\*_~]{1,3}))([^\*_~\n]+[^\*_~\s])\1/g,
links: /!?\[([^\]<>]+)\]\(([^ \)<>]+)( "[^\(\)\"]+")?\)/g,
reflinks: /\[([^\]]+)\]\[([^\]]+)\]/g,
mail: /<(([a-z0-9_\-\.])+\@([a-z0-9_\-\.])+\.([a-z]{2,7}))>/gmi,
/*url: /\w+:\/\/([-\w\.]+)+(:\d+)?(\/([\w/_\.]*(\?\S+)?)?)?/gmi*/
},
parse: function (str, strict) {
'use strict';
var line, nstatus = 0,
status, cel, calign, indent, helper, helper1, helper2, count, repstr, stra, trashgc = [],
casca = 0,
i = 0,
j = 0;
str = '\n' + str + '\n';
if (strict !== true) {
tinyMd.regexobject.lists = /^((\s*(\*|\d\.) [^\n]+)\n)+/gm;
}
/* code */
while ((stra = tinyMd.regexobject.code.exec(str)) !== null) {
str = str.replace(stra[0], '<code>\n' + tinyMd.htmlEncode(stra[1]).replace(/\n/gm, '<br/>').replace(/\ /gm, '&nbsp;') + '</code>\n');
}
/* headlines */
while ((stra = tinyMd.regexobject.headline.exec(str)) !== null) {
count = stra[1].length;
str = str.replace(stra[0], '<h' + count + '>' + stra[2] + '</h' + count + '>' + '\n');
}
/* lists */
while ((stra = tinyMd.regexobject.lists.exec(str)) !== null) {
casca = 0;
if ((stra[0].trim().substr(0, 1) === '*') || (stra[0].trim().substr(0, 1) === '-')) {
repstr = '<ul>';
} else {
repstr = '<ol>';
}
helper = stra[0].split('\n');
helper1 = [];
status = 0;
indent = false;
for (i = 0; i < helper.length; i++) {
if ((line = /^((\s*)((\*|\-)|\d(\.|\))) ([^\n]+))/.exec(helper[i])) !== null) {
if ((line[2] === undefined) || (line[2].length === 0)) {
nstatus = 0;
} else {
if (indent === false) {
indent = line[2].replace(/\t/, ' ').length;
}
nstatus = Math.round(line[2].replace(/\t/, ' ').length / indent);
}
while (status > nstatus) {
repstr += helper1.pop();
status--;
casca--;
}
while (status < nstatus) {
if ((line[0].trim().substr(0, 1) === '*') || (line[0].trim().substr(0, 1) === '-')) {
repstr += '<ul>';
helper1.push('</ul>');
} else {
repstr += '<ol>';
helper1.push('</ol>');
}
status++;
casca++;
}
repstr += '<li>' + line[6] + '</li>' + '\n';
}
}
while (casca > 0) {
repstr += '</ul>';
casca--;
}
if ((stra[0].trim().substr(0, 1) === '*') || (stra[0].trim().substr(0, 1) === '-')) {
repstr += '</ul>';
} else {
repstr += '</ol>';
}
str = str.replace(stra[0], repstr + '\n');
}
/* bold and italic */
for (i = 0; i < 3; i++) {
while ((stra = tinyMd.regexobject.bolditalic.exec(str)) !== null) {
repstr = [];
if (stra[1] === '~~') {
str = str.replace(stra[0], '<del>' + stra[2] + '</del>');
} else {
switch (stra[1].length) {
case 1:
repstr = ['<i>', '</i>'];
break;
case 2:
repstr = ['<b>', '</b>'];
break;
case 3:
repstr = ['<i><b>', '</b></i>'];
break;
}
str = str.replace(stra[0], repstr[0] + stra[2] + repstr[1]);
}
}
}
/* links */
while ((stra = tinyMd.regexobject.links.exec(str)) !== null) {
if (stra[0].substr(0, 1) === '!') {
str = str.replace(stra[0], '<img src="' + stra[2] + '" alt="' + stra[1] + '" title="' + stra[1] + '" />\n');
} else {
str = str.replace(stra[0], '<a href="' + stra[2] + '">' + stra[1] + '</a>\n');
}
}
while ((stra = tinyMd.regexobject.mail.exec(str)) !== null) {
str = str.replace(stra[0], '<a href="mailto:' + stra[1] + '">' + stra[1] + '</a>');
}
/*
while ((stra = tinyMd.regexobject.url.exec(str)) !== null) {
str = str.replace(stra[0], '<a href="' + stra[1] + '">' + stra[1] + '</a>');
}
*/
while ((stra = tinyMd.regexobject.reflinks.exec(str)) !== null) {
helper1 = new RegExp('\\[' + stra[2] + '\\]: ?([^ \n]+)', "gi");
if ((helper = helper1.exec(str)) !== null) {
str = str.replace(stra[0], '<a href="' + helper[1] + '">' + stra[1] + '</a>');
trashgc.push(helper[0]);
}
}
for (i = 0; i < trashgc.length; i++) {
str = str.replace(trashgc[i], '');
}
/* horizontal line */
while ((stra = tinyMd.regexobject.hr.exec(str)) !== null) {
str = str.replace(stra[0], '<hr/>');
}
str = str.replace(/ {2,}[\n]{1,}/gmi, '<br/>');
return str;
},
countingChars: function (str, split) {
'use strict';
str = str.split(split);
if (typeof str === 'object') {return str.length - 1;}
return 0;
},
htmlEncode: function (str) {
'use strict';
var div = document.createElement('div');
div.appendChild(document.createTextNode(str));
str = div.innerHTML;
div = undefined;
return str;
}
};
(function (root, factory) {
"use strict";
if (typeof define === 'function' && define.amd) {
define([], factory);
} else if (typeof exports === 'object') {
module.exports = factory();
} else {
root.returnExports = factory();
}
}(this, function () {
'use strict';
return tinyMd;
}));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment