diff --git a/css/lexiconga.css b/css/lexiconga.css
index 56a47b3..ca1f8ef 100644
--- a/css/lexiconga.css
+++ b/css/lexiconga.css
@@ -102,7 +102,7 @@ input, textarea, select, option, button {
}
#loginLink, #logoutLink,
-#descriptionToggle, #settingsButton,
+#descriptionToggle, #searchFilterToggle, #settingsButton,
.deleteCancelButton, .deleteConfirmButton,
#settingsScreenCloseButton, #infoScreenCloseButton,
.helperlink {
diff --git a/css/styles.css b/css/styles.css
index f9c3785..8e1a883 100644
--- a/css/styles.css
+++ b/css/styles.css
@@ -153,7 +153,9 @@ input[type=checkbox] {
cursor: pointer;
}
-#descriptionToggle {
+#descriptionToggle, #searchFilterToggle {
+ display: inline-block;
+ margin: 8px;
font-weight: bold;
font-size: 12px;
cursor: pointer;
diff --git a/index.php b/index.php
index cacb5a9..7a88e10 100644
--- a/index.php
+++ b/index.php
@@ -68,25 +68,31 @@ if ($_GET['adminoverride'] == 'dictionarytotext') {
Show Description
-
@@ -167,9 +173,11 @@ if ($_GET['adminoverride'] == 'dictionarytotext') {
-
+
-
+
+
+
diff --git a/js/defiant-js/defiant-latest.js b/js/defiant-js/defiant-latest.js
new file mode 100644
index 0000000..c739d6e
--- /dev/null
+++ b/js/defiant-js/defiant-latest.js
@@ -0,0 +1,687 @@
+/*
+ * Defiant.js v1.2.5
+ * Serch JSON structures plus smart templating with XSLT and XPath.
+ * http://defiantjs.com
+ *
+ * Copyright (c) 2013-2015, Hakan Bilgin
+ * Licensed under the MIT License
+ *
+ * NOTE:
+ * Robbie Antenesse edited line 165's RegExp to search global and case-insensitive in case of multiple contains() groups.
+ */
+
+if (typeof module === "undefined") {
+ var module = { exports: undefined };
+} else {
+ // Node env adaptation goes here...
+}
+
+module.exports = Defiant = (function(window, undefined) {
+ 'use strict';
+
+ var Defiant = {
+ is_ie : /msie/i.test(navigator.userAgent),
+ is_safari : /safari/i.test(navigator.userAgent),
+ env : 'production',
+ xml_decl : '',
+ namespace : 'xmlns:d="defiant-namespace"',
+ tabsize : 4,
+ render: function(template, data) {
+ var processor = new XSLTProcessor(),
+ span = document.createElement('span'),
+ opt = {match: '/'},
+ tmpltXpath,
+ scripts,
+ temp,
+ sorter;
+ // handle arguments
+ switch (typeof(template)) {
+ case 'object':
+ this.extend(opt, template);
+ if (!opt.data) opt.data = data;
+ break;
+ case 'string':
+ opt.template = template;
+ opt.data = data;
+ break;
+ default:
+ throw 'error';
+ }
+ opt.data = JSON.toXML(opt.data);
+ tmpltXpath = '//xsl:template[@name="'+ opt.template +'"]';
+
+ if (!this.xsl_template) this.gatherTemplates();
+
+ if (opt.sorter) {
+ sorter = this.node.selectSingleNode(this.xsl_template, tmpltXpath +'//xsl:for-each//xsl:sort');
+ if (sorter) {
+ if (opt.sorter.order) sorter.setAttribute('order', opt.sorter.order);
+ if (opt.sorter.select) sorter.setAttribute('select', opt.sorter.select);
+ sorter.setAttribute('data-type', opt.sorter.type || 'text');
+ }
+ }
+
+ temp = this.node.selectSingleNode(this.xsl_template, tmpltXpath);
+ temp.setAttribute('match', opt.match);
+ processor.importStylesheet(this.xsl_template);
+ span.appendChild(processor.transformToFragment(opt.data, document));
+ temp.removeAttribute('match');
+
+ if (this.is_safari) {
+ scripts = span.getElementsByTagName('script');
+ for (var i=0, il=scripts.length; i'+ str.replace(/defiant:(\w+)/g, '$1') +'');
+ },
+ getSnapshot: function(data) {
+ return JSON.toXML(data, true);
+ },
+ xmlFromString: function(str) {
+ var parser,
+ doc;
+ str = str.replace(/>\s{1,}<');
+ if (str.trim().match(/<\?xml/) === null) {
+ str = this.xml_decl + str;
+ }
+ if (this.is_ie) {
+ doc = new ActiveXObject('Msxml2.DOMDocument');
+ doc.loadXML(str);
+ if (str.indexOf('xsl:stylesheet') === -1) {
+ doc.setProperty('SelectionLanguage', 'XPath');
+ }
+ } else {
+ parser = new DOMParser();
+ doc = parser.parseFromString(str, 'text/xml');
+ }
+ return doc;
+ },
+ extend: function(src, dest) {
+ for (var content in dest) {
+ if (!src[content] || typeof(dest[content]) !== 'object') {
+ src[content] = dest[content];
+ } else {
+ this.extend(src[content], dest[content]);
+ }
+ }
+ return src;
+ },
+ node: {}
+ };
+
+ return Defiant;
+
+})(this);
+
+
+if (typeof(XSLTProcessor) === 'undefined') {
+
+ // emulating XSLT Processor (enough to be used in defiant)
+ var XSLTProcessor = function() {};
+ XSLTProcessor.prototype = {
+ importStylesheet: function(xsldoc) {
+ this.xsldoc = xsldoc;
+ },
+ transformToFragment: function(data, doc) {
+ var str = data.transformNode(this.xsldoc),
+ span = document.createElement('span');
+ span.innerHTML = str;
+ return span;
+ }
+ };
+
+}
+
+
+// extending STRING
+if (!String.prototype.fill) {
+ String.prototype.fill = function(i,c) {
+ var str = this;
+ c = c || ' ';
+ for (; str.length/,
+ rx_constructor : /<(.+?)( d:contr=".*?")>/,
+ rx_namespace : / xmlns\:d="defiant\-namespace"/,
+ rx_data : /(<.+?>)(.*?)(<\/d:data>)/i,
+ rx_function : /function (\w+)/i,
+ to_xml: function(tree) {
+ var str = this.hash_to_xml(null, tree);
+ return Defiant.xmlFromString(str);
+ },
+ hash_to_xml: function(name, tree, array_child) {
+ var is_array = tree.constructor === Array,
+ elem = [],
+ attr = [],
+ key,
+ val,
+ val_is_array,
+ type,
+ is_attr,
+ cname,
+ constr,
+ cnName,
+ i;
+
+ for (key in tree) {
+ val = tree[key];
+ if (val === null || val === undefined || val.toString() === 'NaN') val = null;
+
+ is_attr = key.slice(0,1) === '@';
+ cname = array_child ? name : key;
+ if (cname == +cname && tree.constructor !== Object) cname = 'd:item';
+ if (val === null) {
+ constr = null;
+ cnName = false;
+ } else {
+ constr = val.constructor;
+ cnName = constr.toString().match(this.rx_function)[1];
+ }
+
+ if (is_attr) {
+ attr.push( cname.slice(1) +'="'+ this.escape_xml(val) +'"' );
+ if (cnName !== 'String') attr.push( 'd:'+ cname.slice(1) +'="'+ cnName +'"' );
+ } else if (val === null) {
+ elem.push( this.scalar_to_xml( cname, val ) );
+ } else {
+ switch (constr) {
+ case Function:
+ // if constructor is function, then it's not a JSON structure
+ // throw ERROR ?
+ break;
+ case Object:
+ elem.push( this.hash_to_xml( cname, val ) );
+ break;
+ case Array:
+ if (key === cname) {
+ val_is_array = val.constructor === Array;
+ if (val_is_array) {
+ i = val.length;
+ while (i--) {
+ if (val[i].constructor === Array) val_is_array = true;
+ if (!val_is_array && val[i].constructor === Object) val_is_array = true;
+ }
+ }
+ elem.push( this.scalar_to_xml( cname, val, val_is_array ) );
+ break;
+ }
+ /* falls through */
+ case String:
+ if (typeof(val) === 'string') {
+ val = val.toString().replace(/\&/g, '&')
+ .replace(/\r|\n/g, '
');
+ }
+ if (cname === '#text') {
+ // prepare map
+ this.map.push(tree);
+ attr.push('d:mi="'+ this.map.length +'"');
+ attr.push('d:constr="'+ cnName +'"');
+ elem.push( this.escape_xml(val) );
+ break;
+ }
+ /* falls through */
+ case Number:
+ case Boolean:
+ if (cname === '#text' && cnName !== 'String') {
+ // prepare map
+ this.map.push(tree);
+ attr.push('d:mi="'+ this.map.length +'"');
+ attr.push('d:constr="'+ cnName +'"');
+ elem.push( this.escape_xml(val) );
+ break;
+ }
+ elem.push( this.scalar_to_xml( cname, val ) );
+ break;
+ }
+ }
+ }
+ if (!name) {
+ name = 'd:data';
+ attr.push(Defiant.namespace);
+ if (is_array) attr.push('d:constr="Array"');
+ }
+ if (name.match(this.rx_validate_name) === null) {
+ attr.push( 'd:name="'+ name +'"' );
+ name = 'd:name';
+ }
+ if (array_child) return elem.join('');
+ // prepare map
+ this.map.push(tree);
+ attr.push('d:mi="'+ this.map.length +'"');
+
+ return '<'+ name + (attr.length ? ' '+ attr.join(' ') : '') + (elem.length ? '>'+ elem.join('') +''+ name +'>' : '/>' );
+ },
+ scalar_to_xml: function(name, val, override) {
+ var attr = '',
+ text,
+ constr,
+ cnName;
+
+ // check whether the nodename is valid
+ if (name.match(this.rx_validate_name) === null) {
+ attr += ' d:name="'+ name +'"';
+ name = 'd:name';
+ override = false;
+ }
+ if (val === null || val.toString() === 'NaN') val = null;
+ if (val === null) return '<'+ name +' d:constr="null"/>';
+ if (val.length === 1 && val[0].constructor === Object) {
+
+ text = this.hash_to_xml(false, val[0]);
+
+ var a1 = text.match(this.rx_node),
+ a2 = text.match(this.rx_constructor);
+ a1 = (a1 !== null)? a1[2]
+ .replace(this.rx_namespace, '')
+ .replace(/>/, '')
+ .replace(/"\/$/, '"') : '';
+ a2 = (a2 !== null)? a2[2] : '';
+
+ text = text.match(this.rx_data);
+ text = (text !== null)? text[2] : '';
+
+ return '<'+ name + a1 +' '+ a2 +' d:type="ArrayItem">'+ text +''+ name +'>';
+ } else if (val.length === 0 && val.constructor === Array) {
+ return '<'+ name +' d:constr="Array"/>';
+ }
+ // else
+ if (override) {
+ return this.hash_to_xml( name, val, true );
+ }
+
+ constr = val.constructor;
+ cnName = constr.toString().match(this.rx_function)[1];
+ text = (constr === Array) ? this.hash_to_xml( 'd:item', val, true )
+ : this.escape_xml(val);
+
+ attr += ' d:constr="'+ cnName +'"';
+ // prepare map
+ this.map.push(val);
+ attr += ' d:mi="'+ this.map.length +'"';
+
+ return (name === '#text') ? this.escape_xml(val) : '<'+ name + attr +'>'+ text +''+ name +'>';
+ },
+ escape_xml: function(text) {
+ return String(text) .replace(//g, '>')
+ .replace(/"/g, '"')
+ .replace(/ /g, ' ');
+ }
+ },
+ doc = interpreter.to_xml.call(interpreter, tree);
+
+ // snapshot distinctly improves performance
+ if (snapshot) {
+ return {
+ doc: doc,
+ src: tree,
+ map: interpreter.map
+ };
+ }
+
+ this.search.map = interpreter.map;
+ return doc;
+ };
+}
+
+if (!JSON.search) {
+ JSON.search = function(tree, xpath, single) {
+ 'use strict';
+
+ var isSnapshot = tree.doc && tree.doc.nodeType,
+ doc = isSnapshot ? tree.doc : JSON.toXML(tree),
+ map = isSnapshot ? tree.map : this.search.map,
+ src = isSnapshot ? tree.src : tree,
+ xres = Defiant.node[ single ? 'selectSingleNode' : 'selectNodes' ](doc, xpath.xTransform()),
+ ret = [],
+ mapIndex,
+ i;
+
+ if (single) xres = [xres];
+ i = xres.length;
+
+ while (i--) {
+ switch(xres[i].nodeType) {
+ case 2:
+ case 3:
+ ret.unshift( xres[i].nodeValue );
+ break;
+ default:
+ mapIndex = +xres[i].getAttribute('d:mi');
+ if (map[mapIndex-1]) ret.unshift( map[mapIndex-1] );
+ }
+ }
+
+ // if environment = development, add search tracing
+ if (Defiant.env === 'development') {
+ this.trace = JSON.mtrace(src, ret, xres);
+ }
+
+ return ret;
+ };
+}
+
+if (!JSON.mtrace) {
+ JSON.mtrace = function(root, hits, xres) {
+ 'use strict';
+
+ var win = window,
+ stringify = JSON.stringify,
+ sroot = stringify( root, null, '\t' ).replace(/\t/g, ''),
+ trace = [],
+ i = 0,
+ il = xres.length,
+ od = il ? xres[i].ownerDocument.documentElement : false,
+ map = this.search.map,
+ hstr,
+ cConstr,
+ fIndex = 0,
+ mIndex,
+ lStart,
+ lEnd;
+
+ for (; i 0)? xI[0] : null;
+ } else {
+ return XNode.selectSingleNode(XPath);
+ }
+};
+
+
+Defiant.node.prettyPrint = function(node) {
+ var root = Defiant,
+ tabs = root.tabsize,
+ decl = root.xml_decl.toLowerCase(),
+ ser,
+ xstr;
+ if (root.is_ie) {
+ xstr = node.xml;
+ } else {
+ ser = new XMLSerializer();
+ xstr = ser.serializeToString(node);
+ }
+ if (root.env !== 'development') {
+ // if environment is not development, remove defiant related info
+ xstr = xstr.replace(/ \w+\:d=".*?"| d\:\w+=".*?"/g, '');
+ }
+ var str = xstr.trim().replace(/(>)\s*(<)(\/*)/g, '$1\n$2$3'),
+ lines = str.split('\n'),
+ indent = -1,
+ i = 0,
+ il = lines.length,
+ start,
+ end;
+ for (; i/g) !== null;
+ //start = lines[i].match(/<[^\/]+>/g) !== null;
+ end = lines[i].match(/<\/[\w\:]+>/g) !== null;
+ if (lines[i].match(/<.*?\/>/g) !== null) start = end = true;
+ if (start) indent++;
+ lines[i] = String().fill(indent, '\t') + lines[i];
+ if (start && end) indent--;
+ if (!start && end) indent--;
+ }
+ return lines.join('\n').replace(/\t/g, String().fill(tabs, ' '));
+};
+
+
+Defiant.node.toJSON = function(xnode, stringify) {
+ 'use strict';
+
+ var interpret = function(leaf) {
+ var obj = {},
+ win = window,
+ attr,
+ type,
+ item,
+ cname,
+ cConstr,
+ cval,
+ text,
+ i, il, a;
+
+ switch (leaf.nodeType) {
+ case 1:
+ cConstr = leaf.getAttribute('d:constr');
+ if (cConstr === 'Array') obj = [];
+ else if (cConstr === 'String' && leaf.textContent === '') obj = '';
+
+ attr = leaf.attributes;
+ i = 0;
+ il = attr.length;
+ for (; i 0) {
for (var i = 0; i < currentDictionary.words.length; i++) {
if (filter == "" || (filter != "" && currentDictionary.words[i].partOfSpeech == filter)) {
- if (search == "" || (search != "" && searchResults.indexOf(htmlEntities(currentDictionary.words[i].name)) >= 0)) {
+ if (search == "" || (search != "" && (searchByWord || searchBySimple || searchByLong) && searchResults.indexOf(currentDictionary.words[i].wordId) >= 0)) {
if (!currentDictionary.words[i].hasOwnProperty("pronunciation")) {
currentDictionary.words[i].pronunciation = ""; //Account for new property
}
@@ -246,32 +261,67 @@ function ShowDictionary() {
}
dictionaryArea.innerHTML = dictionaryText;
+ console.log("dictionary shown");
}
function DictionaryEntry(itemIndex) {
var entryText = "🔗";
- var searchTerm = htmlEntities(document.getElementById("searchBox").value);
- var searchRegEx = new RegExp(searchTerm, "gi");
+ var searchTerm = document.getElementById("searchBox").value;
+ var searchByWord = document.getElementById("searchOptionWord").checked;
+ var searchBySimple = document.getElementById("searchOptionSimple").checked;
+ var searchByLong = document.getElementById("searchOptionLong").checked;
+ var searchIgnoreCase = !document.getElementById("searchCaseSensitive").checked; //It's easier to negate case here instead of negating it every use since ignore case is default.
+ var searchIgnoreDiacritics = document.getElementById("searchIgnoreDiacritics").checked;
+
+ var searchRegEx = new RegExp("(" + ((searchIgnoreDiacritics) ? removeDiacritics(searchTerm) + "|" + searchTerm : searchTerm) + ")", "g" + ((searchIgnoreCase) ? "i" : ""));
- entryText += "" + ((searchTerm != "" && document.getElementById("searchOptionWord").checked) ? currentDictionary.words[itemIndex].name.replace(searchRegEx, "" + searchTerm + "") : currentDictionary.words[itemIndex].name) + "";
+ entryText += "";
+
+ if (searchTerm != "" && searchByWord) {
+ entryText += htmlEntitiesParse(currentDictionary.words[itemIndex].name).replace(searchRegEx, "$1");
+ } else {
+ entryText += currentDictionary.words[itemIndex].name;
+ }
+
+ entryText += "";
if (currentDictionary.words[itemIndex].pronunciation != "") {
- entryText += "" + markdown.toHTML(htmlEntitiesParse(currentDictionary.words[itemIndex].pronunciation)).replace("","").replace("
","") + "";
+ entryText += "";
+ entryText += marked(htmlEntitiesParse(currentDictionary.words[itemIndex].pronunciation)).replace("","").replace("
","");
+ entryText += "";
}
if (currentDictionary.words[itemIndex].partOfSpeech != "") {
- entryText += "" + currentDictionary.words[itemIndex].partOfSpeech + "";
+ entryText += "";
+ entryText += currentDictionary.words[itemIndex].partOfSpeech;
+ entryText += "";
}
entryText += "
";
if (currentDictionary.words[itemIndex].simpleDefinition != "") {
- entryText += "" + ((searchTerm != "" && document.getElementById("searchOptionSimple").checked) ? currentDictionary.words[itemIndex].simpleDefinition.replace(searchRegEx, "" + searchTerm + "") : currentDictionary.words[itemIndex].simpleDefinition) + "";
+ entryText += "";
+
+ if (searchTerm != "" && searchBySimple) {
+ entryText += htmlEntitiesParse(currentDictionary.words[itemIndex].simpleDefinition).replace(searchRegEx, "$1");
+ } else {
+ entryText += currentDictionary.words[itemIndex].simpleDefinition;
+ }
+
+ entryText += "";
}
if (currentDictionary.words[itemIndex].longDefinition != "") {
- entryText += "" + ((searchTerm != "" && document.getElementById("searchOptionLong").checked) ? markdown.toHTML(htmlEntitiesParse(currentDictionary.words[itemIndex].longDefinition)).replace(searchRegEx, "" + searchTerm + "") : markdown.toHTML(htmlEntitiesParse(currentDictionary.words[itemIndex].longDefinition))) + "";
+ entryText += "";
+
+ if (searchTerm != "" && searchByLong) {
+ entryText += marked(htmlEntitiesParse(currentDictionary.words[itemIndex].longDefinition).replace(searchRegEx, "$1"));
+ } else {
+ entryText += marked(htmlEntitiesParse(currentDictionary.words[itemIndex].longDefinition));
+ }
+
+ entryText += "";
}
if (!currentDictionary.settings.isComplete) {
@@ -371,7 +421,7 @@ function LoadDictionary() {
}
function ExportDictionary() {
- var downloadName = currentDictionary.name.replace(/\W/g, '');
+ var downloadName = removeDiacritics(stripHtmlEntities(currentDictionary.name)).replace(/\W/g, '');
if (downloadName == "") {
downloadName = "export";
}
@@ -444,6 +494,19 @@ function htmlEntitiesParse(string) {
return String(string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'").replace(/
/g, '\n');
}
+function stripHtmlEntities(string) {
+ // This is for the export name.
+ return String(string).replace(/&/g, '').replace(/</g, '').replace(/>/g, '').replace(/"/g, '').replace(/'/g, "").replace(/
/g, '');
+}
+
+function htmlEntitiesParseForSearchEntry(string) {
+ return String(string).replace(/"/g, '%%').replace(/'/g, "``");
+}
+
+function htmlEntitiesParseForSearch(string) {
+ return String(string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '%%').replace(/'/g, "``");
+}
+
function dynamicSort(property) {
/* Retrieved from http://stackoverflow.com/a/4760279
Usage: theArray.sort(dynamicSort("objectProperty"));*/
diff --git a/js/marked.js b/js/marked.js
new file mode 100644
index 0000000..bcea7a6
--- /dev/null
+++ b/js/marked.js
@@ -0,0 +1,1285 @@
+/**
+ * marked - a markdown parser
+ * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
+ * https://github.com/chjj/marked
+ */
+
+;(function() {
+
+/**
+ * Block-Level Grammar
+ */
+
+var block = {
+ newline: /^\n+/,
+ code: /^( {4}[^\n]+\n*)+/,
+ fences: noop,
+ hr: /^( *[-*_]){3,} *(?:\n+|$)/,
+ heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
+ nptable: noop,
+ lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
+ blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
+ list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
+ html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
+ def: /^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
+ table: noop,
+ paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
+ text: /^[^\n]+/
+};
+
+block.bullet = /(?:[*+-]|\d+\.)/;
+block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
+block.item = replace(block.item, 'gm')
+ (/bull/g, block.bullet)
+ ();
+
+block.list = replace(block.list)
+ (/bull/g, block.bullet)
+ ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
+ ('def', '\\n+(?=' + block.def.source + ')')
+ ();
+
+block.blockquote = replace(block.blockquote)
+ ('def', block.def)
+ ();
+
+block._tag = '(?!(?:'
+ + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
+ + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
+ + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
+
+block.html = replace(block.html)
+ ('comment', //)
+ ('closed', /<(tag)[\s\S]+?<\/\1>/)
+ ('closing', /])*?>/)
+ (/tag/g, block._tag)
+ ();
+
+block.paragraph = replace(block.paragraph)
+ ('hr', block.hr)
+ ('heading', block.heading)
+ ('lheading', block.lheading)
+ ('blockquote', block.blockquote)
+ ('tag', '<' + block._tag)
+ ('def', block.def)
+ ();
+
+/**
+ * Normal Block Grammar
+ */
+
+block.normal = merge({}, block);
+
+/**
+ * GFM Block Grammar
+ */
+
+block.gfm = merge({}, block.normal, {
+ fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
+ paragraph: /^/,
+ heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
+});
+
+block.gfm.paragraph = replace(block.paragraph)
+ ('(?!', '(?!'
+ + block.gfm.fences.source.replace('\\1', '\\2') + '|'
+ + block.list.source.replace('\\1', '\\3') + '|')
+ ();
+
+/**
+ * GFM + Tables Block Grammar
+ */
+
+block.tables = merge({}, block.gfm, {
+ nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
+ table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
+});
+
+/**
+ * Block Lexer
+ */
+
+function Lexer(options) {
+ this.tokens = [];
+ this.tokens.links = {};
+ this.options = options || marked.defaults;
+ this.rules = block.normal;
+
+ if (this.options.gfm) {
+ if (this.options.tables) {
+ this.rules = block.tables;
+ } else {
+ this.rules = block.gfm;
+ }
+ }
+}
+
+/**
+ * Expose Block Rules
+ */
+
+Lexer.rules = block;
+
+/**
+ * Static Lex Method
+ */
+
+Lexer.lex = function(src, options) {
+ var lexer = new Lexer(options);
+ return lexer.lex(src);
+};
+
+/**
+ * Preprocessing
+ */
+
+Lexer.prototype.lex = function(src) {
+ src = src
+ .replace(/\r\n|\r/g, '\n')
+ .replace(/\t/g, ' ')
+ .replace(/\u00a0/g, ' ')
+ .replace(/\u2424/g, '\n');
+
+ return this.token(src, true);
+};
+
+/**
+ * Lexing
+ */
+
+Lexer.prototype.token = function(src, top, bq) {
+ var src = src.replace(/^ +$/gm, '')
+ , next
+ , loose
+ , cap
+ , bull
+ , b
+ , item
+ , space
+ , i
+ , l;
+
+ while (src) {
+ // newline
+ if (cap = this.rules.newline.exec(src)) {
+ src = src.substring(cap[0].length);
+ if (cap[0].length > 1) {
+ this.tokens.push({
+ type: 'space'
+ });
+ }
+ }
+
+ // code
+ if (cap = this.rules.code.exec(src)) {
+ src = src.substring(cap[0].length);
+ cap = cap[0].replace(/^ {4}/gm, '');
+ this.tokens.push({
+ type: 'code',
+ text: !this.options.pedantic
+ ? cap.replace(/\n+$/, '')
+ : cap
+ });
+ continue;
+ }
+
+ // fences (gfm)
+ if (cap = this.rules.fences.exec(src)) {
+ src = src.substring(cap[0].length);
+ this.tokens.push({
+ type: 'code',
+ lang: cap[2],
+ text: cap[3] || ''
+ });
+ continue;
+ }
+
+ // heading
+ if (cap = this.rules.heading.exec(src)) {
+ src = src.substring(cap[0].length);
+ this.tokens.push({
+ type: 'heading',
+ depth: cap[1].length,
+ text: cap[2]
+ });
+ continue;
+ }
+
+ // table no leading pipe (gfm)
+ if (top && (cap = this.rules.nptable.exec(src))) {
+ src = src.substring(cap[0].length);
+
+ item = {
+ type: 'table',
+ header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
+ align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
+ cells: cap[3].replace(/\n$/, '').split('\n')
+ };
+
+ for (i = 0; i < item.align.length; i++) {
+ if (/^ *-+: *$/.test(item.align[i])) {
+ item.align[i] = 'right';
+ } else if (/^ *:-+: *$/.test(item.align[i])) {
+ item.align[i] = 'center';
+ } else if (/^ *:-+ *$/.test(item.align[i])) {
+ item.align[i] = 'left';
+ } else {
+ item.align[i] = null;
+ }
+ }
+
+ for (i = 0; i < item.cells.length; i++) {
+ item.cells[i] = item.cells[i].split(/ *\| */);
+ }
+
+ this.tokens.push(item);
+
+ continue;
+ }
+
+ // lheading
+ if (cap = this.rules.lheading.exec(src)) {
+ src = src.substring(cap[0].length);
+ this.tokens.push({
+ type: 'heading',
+ depth: cap[2] === '=' ? 1 : 2,
+ text: cap[1]
+ });
+ continue;
+ }
+
+ // hr
+ if (cap = this.rules.hr.exec(src)) {
+ src = src.substring(cap[0].length);
+ this.tokens.push({
+ type: 'hr'
+ });
+ continue;
+ }
+
+ // blockquote
+ if (cap = this.rules.blockquote.exec(src)) {
+ src = src.substring(cap[0].length);
+
+ this.tokens.push({
+ type: 'blockquote_start'
+ });
+
+ cap = cap[0].replace(/^ *> ?/gm, '');
+
+ // Pass `top` to keep the current
+ // "toplevel" state. This is exactly
+ // how markdown.pl works.
+ this.token(cap, top, true);
+
+ this.tokens.push({
+ type: 'blockquote_end'
+ });
+
+ continue;
+ }
+
+ // list
+ if (cap = this.rules.list.exec(src)) {
+ src = src.substring(cap[0].length);
+ bull = cap[2];
+
+ this.tokens.push({
+ type: 'list_start',
+ ordered: bull.length > 1
+ });
+
+ // Get each top-level item.
+ cap = cap[0].match(this.rules.item);
+
+ next = false;
+ l = cap.length;
+ i = 0;
+
+ for (; i < l; i++) {
+ item = cap[i];
+
+ // Remove the list item's bullet
+ // so it is seen as the next token.
+ space = item.length;
+ item = item.replace(/^ *([*+-]|\d+\.) +/, '');
+
+ // Outdent whatever the
+ // list item contains. Hacky.
+ if (~item.indexOf('\n ')) {
+ space -= item.length;
+ item = !this.options.pedantic
+ ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
+ : item.replace(/^ {1,4}/gm, '');
+ }
+
+ // Determine whether the next list item belongs here.
+ // Backpedal if it does not belong in this list.
+ if (this.options.smartLists && i !== l - 1) {
+ b = block.bullet.exec(cap[i + 1])[0];
+ if (bull !== b && !(bull.length > 1 && b.length > 1)) {
+ src = cap.slice(i + 1).join('\n') + src;
+ i = l - 1;
+ }
+ }
+
+ // Determine whether item is loose or not.
+ // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
+ // for discount behavior.
+ loose = next || /\n\n(?!\s*$)/.test(item);
+ if (i !== l - 1) {
+ next = item.charAt(item.length - 1) === '\n';
+ if (!loose) loose = next;
+ }
+
+ this.tokens.push({
+ type: loose
+ ? 'loose_item_start'
+ : 'list_item_start'
+ });
+
+ // Recurse.
+ this.token(item, false, bq);
+
+ this.tokens.push({
+ type: 'list_item_end'
+ });
+ }
+
+ this.tokens.push({
+ type: 'list_end'
+ });
+
+ continue;
+ }
+
+ // html
+ if (cap = this.rules.html.exec(src)) {
+ src = src.substring(cap[0].length);
+ this.tokens.push({
+ type: this.options.sanitize
+ ? 'paragraph'
+ : 'html',
+ pre: !this.options.sanitizer
+ && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
+ text: cap[0]
+ });
+ continue;
+ }
+
+ // def
+ if ((!bq && top) && (cap = this.rules.def.exec(src))) {
+ src = src.substring(cap[0].length);
+ this.tokens.links[cap[1].toLowerCase()] = {
+ href: cap[2],
+ title: cap[3]
+ };
+ continue;
+ }
+
+ // table (gfm)
+ if (top && (cap = this.rules.table.exec(src))) {
+ src = src.substring(cap[0].length);
+
+ item = {
+ type: 'table',
+ header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
+ align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
+ cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
+ };
+
+ for (i = 0; i < item.align.length; i++) {
+ if (/^ *-+: *$/.test(item.align[i])) {
+ item.align[i] = 'right';
+ } else if (/^ *:-+: *$/.test(item.align[i])) {
+ item.align[i] = 'center';
+ } else if (/^ *:-+ *$/.test(item.align[i])) {
+ item.align[i] = 'left';
+ } else {
+ item.align[i] = null;
+ }
+ }
+
+ for (i = 0; i < item.cells.length; i++) {
+ item.cells[i] = item.cells[i]
+ .replace(/^ *\| *| *\| *$/g, '')
+ .split(/ *\| */);
+ }
+
+ this.tokens.push(item);
+
+ continue;
+ }
+
+ // top-level paragraph
+ if (top && (cap = this.rules.paragraph.exec(src))) {
+ src = src.substring(cap[0].length);
+ this.tokens.push({
+ type: 'paragraph',
+ text: cap[1].charAt(cap[1].length - 1) === '\n'
+ ? cap[1].slice(0, -1)
+ : cap[1]
+ });
+ continue;
+ }
+
+ // text
+ if (cap = this.rules.text.exec(src)) {
+ // Top-level should never reach here.
+ src = src.substring(cap[0].length);
+ this.tokens.push({
+ type: 'text',
+ text: cap[0]
+ });
+ continue;
+ }
+
+ if (src) {
+ throw new
+ Error('Infinite loop on byte: ' + src.charCodeAt(0));
+ }
+ }
+
+ return this.tokens;
+};
+
+/**
+ * Inline-Level Grammar
+ */
+
+var inline = {
+ escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
+ autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
+ url: noop,
+ tag: /^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
+ link: /^!?\[(inside)\]\(href\)/,
+ reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
+ nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
+ strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
+ em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
+ code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
+ br: /^ {2,}\n(?!\s*$)/,
+ del: noop,
+ text: /^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/;
+
+inline.link = replace(inline.link)
+ ('inside', inline._inside)
+ ('href', inline._href)
+ ();
+
+inline.reflink = replace(inline.reflink)
+ ('inside', inline._inside)
+ ();
+
+/**
+ * Normal Inline Grammar
+ */
+
+inline.normal = merge({}, inline);
+
+/**
+ * Pedantic Inline Grammar
+ */
+
+inline.pedantic = merge({}, inline.normal, {
+ strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
+ em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
+});
+
+/**
+ * GFM Inline Grammar
+ */
+
+inline.gfm = merge({}, inline.normal, {
+ escape: replace(inline.escape)('])', '~|])')(),
+ url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
+ del: /^~~(?=\S)([\s\S]*?\S)~~/,
+ text: replace(inline.text)
+ (']|', '~]|')
+ ('|', '|https?://|')
+ ()
+});
+
+/**
+ * GFM + Line Breaks Inline Grammar
+ */
+
+inline.breaks = merge({}, inline.gfm, {
+ br: replace(inline.br)('{2,}', '*')(),
+ text: replace(inline.gfm.text)('{2,}', '*')()
+});
+
+/**
+ * Inline Lexer & Compiler
+ */
+
+function InlineLexer(links, options) {
+ this.options = options || marked.defaults;
+ this.links = links;
+ this.rules = inline.normal;
+ this.renderer = this.options.renderer || new Renderer;
+ this.renderer.options = this.options;
+
+ if (!this.links) {
+ throw new
+ Error('Tokens array requires a `links` property.');
+ }
+
+ if (this.options.gfm) {
+ if (this.options.breaks) {
+ this.rules = inline.breaks;
+ } else {
+ this.rules = inline.gfm;
+ }
+ } else if (this.options.pedantic) {
+ this.rules = inline.pedantic;
+ }
+}
+
+/**
+ * Expose Inline Rules
+ */
+
+InlineLexer.rules = inline;
+
+/**
+ * Static Lexing/Compiling Method
+ */
+
+InlineLexer.output = function(src, links, options) {
+ var inline = new InlineLexer(links, options);
+ return inline.output(src);
+};
+
+/**
+ * Lexing/Compiling
+ */
+
+InlineLexer.prototype.output = function(src) {
+ var out = ''
+ , link
+ , text
+ , href
+ , cap;
+
+ while (src) {
+ // escape
+ if (cap = this.rules.escape.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += cap[1];
+ continue;
+ }
+
+ // autolink
+ if (cap = this.rules.autolink.exec(src)) {
+ src = src.substring(cap[0].length);
+ if (cap[2] === '@') {
+ text = cap[1].charAt(6) === ':'
+ ? this.mangle(cap[1].substring(7))
+ : this.mangle(cap[1]);
+ href = this.mangle('mailto:') + text;
+ } else {
+ text = escape(cap[1]);
+ href = text;
+ }
+ out += this.renderer.link(href, null, text);
+ continue;
+ }
+
+ // url (gfm)
+ if (!this.inLink && (cap = this.rules.url.exec(src))) {
+ src = src.substring(cap[0].length);
+ text = escape(cap[1]);
+ href = text;
+ out += this.renderer.link(href, null, text);
+ continue;
+ }
+
+ // tag
+ if (cap = this.rules.tag.exec(src)) {
+ if (!this.inLink && /^/i.test(cap[0])) {
+ this.inLink = false;
+ }
+ src = src.substring(cap[0].length);
+ out += this.options.sanitize
+ ? this.options.sanitizer
+ ? this.options.sanitizer(cap[0])
+ : escape(cap[0])
+ : cap[0]
+ continue;
+ }
+
+ // link
+ if (cap = this.rules.link.exec(src)) {
+ src = src.substring(cap[0].length);
+ this.inLink = true;
+ out += this.outputLink(cap, {
+ href: cap[2],
+ title: cap[3]
+ });
+ this.inLink = false;
+ continue;
+ }
+
+ // reflink, nolink
+ if ((cap = this.rules.reflink.exec(src))
+ || (cap = this.rules.nolink.exec(src))) {
+ src = src.substring(cap[0].length);
+ link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
+ link = this.links[link.toLowerCase()];
+ if (!link || !link.href) {
+ out += cap[0].charAt(0);
+ src = cap[0].substring(1) + src;
+ continue;
+ }
+ this.inLink = true;
+ out += this.outputLink(cap, link);
+ this.inLink = false;
+ continue;
+ }
+
+ // strong
+ if (cap = this.rules.strong.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += this.renderer.strong(this.output(cap[2] || cap[1]));
+ continue;
+ }
+
+ // em
+ if (cap = this.rules.em.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += this.renderer.em(this.output(cap[2] || cap[1]));
+ continue;
+ }
+
+ // code
+ if (cap = this.rules.code.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += this.renderer.codespan(escape(cap[2], true));
+ continue;
+ }
+
+ // br
+ if (cap = this.rules.br.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += this.renderer.br();
+ continue;
+ }
+
+ // del (gfm)
+ if (cap = this.rules.del.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += this.renderer.del(this.output(cap[1]));
+ continue;
+ }
+
+ // text
+ if (cap = this.rules.text.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += this.renderer.text(escape(this.smartypants(cap[0])));
+ continue;
+ }
+
+ if (src) {
+ throw new
+ Error('Infinite loop on byte: ' + src.charCodeAt(0));
+ }
+ }
+
+ return out;
+};
+
+/**
+ * Compile Link
+ */
+
+InlineLexer.prototype.outputLink = function(cap, link) {
+ var href = escape(link.href)
+ , title = link.title ? escape(link.title) : null;
+
+ return cap[0].charAt(0) !== '!'
+ ? this.renderer.link(href, title, this.output(cap[1]))
+ : this.renderer.image(href, title, escape(cap[1]));
+};
+
+/**
+ * Smartypants Transformations
+ */
+
+InlineLexer.prototype.smartypants = function(text) {
+ if (!this.options.smartypants) return text;
+ return text
+ // em-dashes
+ .replace(/---/g, '\u2014')
+ // en-dashes
+ .replace(/--/g, '\u2013')
+ // opening singles
+ .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
+ // closing singles & apostrophes
+ .replace(/'/g, '\u2019')
+ // opening doubles
+ .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
+ // closing doubles
+ .replace(/"/g, '\u201d')
+ // ellipses
+ .replace(/\.{3}/g, '\u2026');
+};
+
+/**
+ * Mangle Links
+ */
+
+InlineLexer.prototype.mangle = function(text) {
+ if (!this.options.mangle) return text;
+ var out = ''
+ , l = text.length
+ , i = 0
+ , ch;
+
+ for (; i < l; i++) {
+ ch = text.charCodeAt(i);
+ if (Math.random() > 0.5) {
+ ch = 'x' + ch.toString(16);
+ }
+ out += '' + ch + ';';
+ }
+
+ return out;
+};
+
+/**
+ * Renderer
+ */
+
+function Renderer(options) {
+ this.options = options || {};
+}
+
+Renderer.prototype.code = function(code, lang, escaped) {
+ if (this.options.highlight) {
+ var out = this.options.highlight(code, lang);
+ if (out != null && out !== code) {
+ escaped = true;
+ code = out;
+ }
+ }
+
+ if (!lang) {
+ return ''
+ + (escaped ? code : escape(code, true))
+ + '\n
';
+ }
+
+ return ''
+ + (escaped ? code : escape(code, true))
+ + '\n
\n';
+};
+
+Renderer.prototype.blockquote = function(quote) {
+ return '\n' + quote + '
\n';
+};
+
+Renderer.prototype.html = function(html) {
+ return html;
+};
+
+Renderer.prototype.heading = function(text, level, raw) {
+ return '\n';
+};
+
+Renderer.prototype.hr = function() {
+ return this.options.xhtml ? '
\n' : '
\n';
+};
+
+Renderer.prototype.list = function(body, ordered) {
+ var type = ordered ? 'ol' : 'ul';
+ return '<' + type + '>\n' + body + '' + type + '>\n';
+};
+
+Renderer.prototype.listitem = function(text) {
+ return '' + text + '\n';
+};
+
+Renderer.prototype.paragraph = function(text) {
+ return '' + text + '
\n';
+};
+
+Renderer.prototype.table = function(header, body) {
+ return '\n'
+ + '\n'
+ + header
+ + '\n'
+ + '\n'
+ + body
+ + '\n'
+ + '
\n';
+};
+
+Renderer.prototype.tablerow = function(content) {
+ return '\n' + content + '
\n';
+};
+
+Renderer.prototype.tablecell = function(content, flags) {
+ var type = flags.header ? 'th' : 'td';
+ var tag = flags.align
+ ? '<' + type + ' style="text-align:' + flags.align + '">'
+ : '<' + type + '>';
+ return tag + content + '' + type + '>\n';
+};
+
+// span level renderer
+Renderer.prototype.strong = function(text) {
+ return '' + text + '';
+};
+
+Renderer.prototype.em = function(text) {
+ return '' + text + '';
+};
+
+Renderer.prototype.codespan = function(text) {
+ return '' + text + '
';
+};
+
+Renderer.prototype.br = function() {
+ return this.options.xhtml ? '
' : '
';
+};
+
+Renderer.prototype.del = function(text) {
+ return '' + text + '';
+};
+
+Renderer.prototype.link = function(href, title, text) {
+ if (this.options.sanitize) {
+ try {
+ var prot = decodeURIComponent(unescape(href))
+ .replace(/[^\w:]/g, '')
+ .toLowerCase();
+ } catch (e) {
+ return '';
+ }
+ if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
+ return '';
+ }
+ }
+ var out = '' + text + '';
+ return out;
+};
+
+Renderer.prototype.image = function(href, title, text) {
+ var out = '' : '>';
+ return out;
+};
+
+Renderer.prototype.text = function(text) {
+ return text;
+};
+
+/**
+ * Parsing & Compiling
+ */
+
+function Parser(options) {
+ this.tokens = [];
+ this.token = null;
+ this.options = options || marked.defaults;
+ this.options.renderer = this.options.renderer || new Renderer;
+ this.renderer = this.options.renderer;
+ this.renderer.options = this.options;
+}
+
+/**
+ * Static Parse Method
+ */
+
+Parser.parse = function(src, options, renderer) {
+ var parser = new Parser(options, renderer);
+ return parser.parse(src);
+};
+
+/**
+ * Parse Loop
+ */
+
+Parser.prototype.parse = function(src) {
+ this.inline = new InlineLexer(src.links, this.options, this.renderer);
+ this.tokens = src.reverse();
+
+ var out = '';
+ while (this.next()) {
+ out += this.tok();
+ }
+
+ return out;
+};
+
+/**
+ * Next Token
+ */
+
+Parser.prototype.next = function() {
+ return this.token = this.tokens.pop();
+};
+
+/**
+ * Preview Next Token
+ */
+
+Parser.prototype.peek = function() {
+ return this.tokens[this.tokens.length - 1] || 0;
+};
+
+/**
+ * Parse Text Tokens
+ */
+
+Parser.prototype.parseText = function() {
+ var body = this.token.text;
+
+ while (this.peek().type === 'text') {
+ body += '\n' + this.next().text;
+ }
+
+ return this.inline.output(body);
+};
+
+/**
+ * Parse Current Token
+ */
+
+Parser.prototype.tok = function() {
+ switch (this.token.type) {
+ case 'space': {
+ return '';
+ }
+ case 'hr': {
+ return this.renderer.hr();
+ }
+ case 'heading': {
+ return this.renderer.heading(
+ this.inline.output(this.token.text),
+ this.token.depth,
+ this.token.text);
+ }
+ case 'code': {
+ return this.renderer.code(this.token.text,
+ this.token.lang,
+ this.token.escaped);
+ }
+ case 'table': {
+ var header = ''
+ , body = ''
+ , i
+ , row
+ , cell
+ , flags
+ , j;
+
+ // header
+ cell = '';
+ for (i = 0; i < this.token.header.length; i++) {
+ flags = { header: true, align: this.token.align[i] };
+ cell += this.renderer.tablecell(
+ this.inline.output(this.token.header[i]),
+ { header: true, align: this.token.align[i] }
+ );
+ }
+ header += this.renderer.tablerow(cell);
+
+ for (i = 0; i < this.token.cells.length; i++) {
+ row = this.token.cells[i];
+
+ cell = '';
+ for (j = 0; j < row.length; j++) {
+ cell += this.renderer.tablecell(
+ this.inline.output(row[j]),
+ { header: false, align: this.token.align[j] }
+ );
+ }
+
+ body += this.renderer.tablerow(cell);
+ }
+ return this.renderer.table(header, body);
+ }
+ case 'blockquote_start': {
+ var body = '';
+
+ while (this.next().type !== 'blockquote_end') {
+ body += this.tok();
+ }
+
+ return this.renderer.blockquote(body);
+ }
+ case 'list_start': {
+ var body = ''
+ , ordered = this.token.ordered;
+
+ while (this.next().type !== 'list_end') {
+ body += this.tok();
+ }
+
+ return this.renderer.list(body, ordered);
+ }
+ case 'list_item_start': {
+ var body = '';
+
+ while (this.next().type !== 'list_item_end') {
+ body += this.token.type === 'text'
+ ? this.parseText()
+ : this.tok();
+ }
+
+ return this.renderer.listitem(body);
+ }
+ case 'loose_item_start': {
+ var body = '';
+
+ while (this.next().type !== 'list_item_end') {
+ body += this.tok();
+ }
+
+ return this.renderer.listitem(body);
+ }
+ case 'html': {
+ var html = !this.token.pre && !this.options.pedantic
+ ? this.inline.output(this.token.text)
+ : this.token.text;
+ return this.renderer.html(html);
+ }
+ case 'paragraph': {
+ return this.renderer.paragraph(this.inline.output(this.token.text));
+ }
+ case 'text': {
+ return this.renderer.paragraph(this.parseText());
+ }
+ }
+};
+
+/**
+ * Helpers
+ */
+
+function escape(html, encode) {
+ return html
+ .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
+ .replace(//g, '>')
+ .replace(/"/g, '"')
+ .replace(/'/g, ''');
+}
+
+function unescape(html) {
+ return html.replace(/&([#\w]+);/g, function(_, n) {
+ n = n.toLowerCase();
+ if (n === 'colon') return ':';
+ if (n.charAt(0) === '#') {
+ return n.charAt(1) === 'x'
+ ? String.fromCharCode(parseInt(n.substring(2), 16))
+ : String.fromCharCode(+n.substring(1));
+ }
+ return '';
+ });
+}
+
+function replace(regex, opt) {
+ regex = regex.source;
+ opt = opt || '';
+ return function self(name, val) {
+ if (!name) return new RegExp(regex, opt);
+ val = val.source || val;
+ val = val.replace(/(^|[^\[])\^/g, '$1');
+ regex = regex.replace(name, val);
+ return self;
+ };
+}
+
+function noop() {}
+noop.exec = noop;
+
+function merge(obj) {
+ var i = 1
+ , target
+ , key;
+
+ for (; i < arguments.length; i++) {
+ target = arguments[i];
+ for (key in target) {
+ if (Object.prototype.hasOwnProperty.call(target, key)) {
+ obj[key] = target[key];
+ }
+ }
+ }
+
+ return obj;
+}
+
+
+/**
+ * Marked
+ */
+
+function marked(src, opt, callback) {
+ if (callback || typeof opt === 'function') {
+ if (!callback) {
+ callback = opt;
+ opt = null;
+ }
+
+ opt = merge({}, marked.defaults, opt || {});
+
+ var highlight = opt.highlight
+ , tokens
+ , pending
+ , i = 0;
+
+ try {
+ tokens = Lexer.lex(src, opt)
+ } catch (e) {
+ return callback(e);
+ }
+
+ pending = tokens.length;
+
+ var done = function(err) {
+ if (err) {
+ opt.highlight = highlight;
+ return callback(err);
+ }
+
+ var out;
+
+ try {
+ out = Parser.parse(tokens, opt);
+ } catch (e) {
+ err = e;
+ }
+
+ opt.highlight = highlight;
+
+ return err
+ ? callback(err)
+ : callback(null, out);
+ };
+
+ if (!highlight || highlight.length < 3) {
+ return done();
+ }
+
+ delete opt.highlight;
+
+ if (!pending) return done();
+
+ for (; i < tokens.length; i++) {
+ (function(token) {
+ if (token.type !== 'code') {
+ return --pending || done();
+ }
+ return highlight(token.text, token.lang, function(err, code) {
+ if (err) return done(err);
+ if (code == null || code === token.text) {
+ return --pending || done();
+ }
+ token.text = code;
+ token.escaped = true;
+ --pending || done();
+ });
+ })(tokens[i]);
+ }
+
+ return;
+ }
+ try {
+ if (opt) opt = merge({}, marked.defaults, opt);
+ return Parser.parse(Lexer.lex(src, opt), opt);
+ } catch (e) {
+ e.message += '\nPlease report this to https://github.com/chjj/marked.';
+ if ((opt || marked.defaults).silent) {
+ return 'An error occured:
'
+ + escape(e.message + '', true)
+ + '
';
+ }
+ throw e;
+ }
+}
+
+/**
+ * Options
+ */
+
+marked.options =
+marked.setOptions = function(opt) {
+ merge(marked.defaults, opt);
+ return marked;
+};
+
+marked.defaults = {
+ gfm: true,
+ tables: true,
+ breaks: false,
+ pedantic: false,
+ sanitize: false,
+ sanitizer: null,
+ mangle: true,
+ smartLists: false,
+ silent: false,
+ highlight: null,
+ langPrefix: 'lang-',
+ smartypants: false,
+ headerPrefix: '',
+ renderer: new Renderer,
+ xhtml: false
+};
+
+/**
+ * Expose
+ */
+
+marked.Parser = Parser;
+marked.parser = Parser.parse;
+
+marked.Renderer = Renderer;
+
+marked.Lexer = Lexer;
+marked.lexer = Lexer.lex;
+
+marked.InlineLexer = InlineLexer;
+marked.inlineLexer = InlineLexer.output;
+
+marked.parse = marked;
+
+if (typeof module !== 'undefined' && typeof exports === 'object') {
+ module.exports = marked;
+} else if (typeof define === 'function' && define.amd) {
+ define(function() { return marked; });
+} else {
+ this.marked = marked;
+}
+
+}).call(function() {
+ return this || (typeof window !== 'undefined' ? window : global);
+}());
\ No newline at end of file
diff --git a/js/removeDiacritics.js b/js/removeDiacritics.js
new file mode 100644
index 0000000..60b1379
--- /dev/null
+++ b/js/removeDiacritics.js
@@ -0,0 +1,138 @@
+/*
+ Retrieved from http://stackoverflow.com/a/18391901/3508346
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+var defaultDiacriticsRemovalap = [
+ {'base':'A', 'letters':'\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F'},
+ {'base':'AA','letters':'\uA732'},
+ {'base':'AE','letters':'\u00C6\u01FC\u01E2'},
+ {'base':'AO','letters':'\uA734'},
+ {'base':'AU','letters':'\uA736'},
+ {'base':'AV','letters':'\uA738\uA73A'},
+ {'base':'AY','letters':'\uA73C'},
+ {'base':'B', 'letters':'\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181'},
+ {'base':'C', 'letters':'\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E'},
+ {'base':'D', 'letters':'\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779'},
+ {'base':'DZ','letters':'\u01F1\u01C4'},
+ {'base':'Dz','letters':'\u01F2\u01C5'},
+ {'base':'E', 'letters':'\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E'},
+ {'base':'F', 'letters':'\u0046\u24BB\uFF26\u1E1E\u0191\uA77B'},
+ {'base':'G', 'letters':'\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E'},
+ {'base':'H', 'letters':'\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D'},
+ {'base':'I', 'letters':'\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197'},
+ {'base':'J', 'letters':'\u004A\u24BF\uFF2A\u0134\u0248'},
+ {'base':'K', 'letters':'\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2'},
+ {'base':'L', 'letters':'\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780'},
+ {'base':'LJ','letters':'\u01C7'},
+ {'base':'Lj','letters':'\u01C8'},
+ {'base':'M', 'letters':'\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C'},
+ {'base':'N', 'letters':'\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4'},
+ {'base':'NJ','letters':'\u01CA'},
+ {'base':'Nj','letters':'\u01CB'},
+ {'base':'O', 'letters':'\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C'},
+ {'base':'OI','letters':'\u01A2'},
+ {'base':'OO','letters':'\uA74E'},
+ {'base':'OU','letters':'\u0222'},
+ {'base':'OE','letters':'\u008C\u0152'},
+ {'base':'oe','letters':'\u009C\u0153'},
+ {'base':'P', 'letters':'\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754'},
+ {'base':'Q', 'letters':'\u0051\u24C6\uFF31\uA756\uA758\u024A'},
+ {'base':'R', 'letters':'\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782'},
+ {'base':'S', 'letters':'\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784'},
+ {'base':'T', 'letters':'\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786'},
+ {'base':'TZ','letters':'\uA728'},
+ {'base':'U', 'letters':'\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244'},
+ {'base':'V', 'letters':'\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245'},
+ {'base':'VY','letters':'\uA760'},
+ {'base':'W', 'letters':'\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72'},
+ {'base':'X', 'letters':'\u0058\u24CD\uFF38\u1E8A\u1E8C'},
+ {'base':'Y', 'letters':'\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE'},
+ {'base':'Z', 'letters':'\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762'},
+ {'base':'a', 'letters':'\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250'},
+ {'base':'aa','letters':'\uA733'},
+ {'base':'ae','letters':'\u00E6\u01FD\u01E3'},
+ {'base':'ao','letters':'\uA735'},
+ {'base':'au','letters':'\uA737'},
+ {'base':'av','letters':'\uA739\uA73B'},
+ {'base':'ay','letters':'\uA73D'},
+ {'base':'b', 'letters':'\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253'},
+ {'base':'c', 'letters':'\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184'},
+ {'base':'d', 'letters':'\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A'},
+ {'base':'dz','letters':'\u01F3\u01C6'},
+ {'base':'e', 'letters':'\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD'},
+ {'base':'f', 'letters':'\u0066\u24D5\uFF46\u1E1F\u0192\uA77C'},
+ {'base':'g', 'letters':'\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F'},
+ {'base':'h', 'letters':'\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265'},
+ {'base':'hv','letters':'\u0195'},
+ {'base':'i', 'letters':'\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131'},
+ {'base':'j', 'letters':'\u006A\u24D9\uFF4A\u0135\u01F0\u0249'},
+ {'base':'k', 'letters':'\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3'},
+ {'base':'l', 'letters':'\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747'},
+ {'base':'lj','letters':'\u01C9'},
+ {'base':'m', 'letters':'\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F'},
+ {'base':'n', 'letters':'\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5'},
+ {'base':'nj','letters':'\u01CC'},
+ {'base':'o', 'letters':'\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275'},
+ {'base':'oi','letters':'\u01A3'},
+ {'base':'ou','letters':'\u0223'},
+ {'base':'oo','letters':'\uA74F'},
+ {'base':'p','letters':'\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755'},
+ {'base':'q','letters':'\u0071\u24E0\uFF51\u024B\uA757\uA759'},
+ {'base':'r','letters':'\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783'},
+ {'base':'s','letters':'\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B'},
+ {'base':'t','letters':'\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787'},
+ {'base':'tz','letters':'\uA729'},
+ {'base':'u','letters': '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289'},
+ {'base':'v','letters':'\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C'},
+ {'base':'vy','letters':'\uA761'},
+ {'base':'w','letters':'\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73'},
+ {'base':'x','letters':'\u0078\u24E7\uFF58\u1E8B\u1E8D'},
+ {'base':'y','letters':'\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF'},
+ {'base':'z','letters':'\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763'}
+];
+
+var diacriticsMap = {};
+for (var i=0; i < defaultDiacriticsRemovalap.length; i++){
+ var letters = defaultDiacriticsRemovalap[i].letters;
+ for (var j=0; j < letters.length ; j++){
+ diacriticsMap[letters[j]] = defaultDiacriticsRemovalap[i].base;
+ }
+}
+
+// "what?" version ... http://jsperf.com/diacritics/12
+function removeDiacritics(str) {
+ return str.replace(/[^\u0000-\u007E]/g, function(a){
+ return diacriticsMap[a] || a;
+ });
+}
+
+/*var allDiacritics = [];
+for (var i=0; i < defaultDiacriticsRemovalap.length; i++) {
+ var letters = defaultDiacriticsRemovalap[i].letters.split('');
+ for (var j=0; j < letters.length ; j++){
+ allDiacritics = allDiacritics.push(letters[j]);
+ }
+}
+
+function getDiacriticIndexes(searchString) {
+ // Finds starting and ending positions of quoted text
+ // in double or single quotes with escape char support like \" \'
+ var patt = new RegExp("[" + allDiacritics.join[''] + "]", "gim"); ///"((?:\\.|[^"])*)"/igm;
+ var ret = [];
+ while (match = patt.exec(searchString)) {
+ ret.push(match.index);
+ }
+
+ return ret;
+}*/
\ No newline at end of file
diff --git a/js/ui.js b/js/ui.js
index 9f0589e..0983213 100644
--- a/js/ui.js
+++ b/js/ui.js
@@ -29,6 +29,19 @@ function ToggleDescription() {
}
}
+function ToggleSearchFilter() {
+ var searchFilterToggle = document.getElementById("searchFilterToggle");
+ var searchFilterArea = document.getElementById("searchFilterArea");
+
+ if (searchFilterArea.style.display == "none") {
+ searchFilterArea.style.display = "block";
+ searchFilterToggle.innerHTML = "Hide Search/Filter Options";
+ } else {
+ searchFilterArea.style.display = "none";
+ searchFilterToggle.innerHTML = "Search/Filter Options";
+ }
+}
+
function ShowInfo(text) {
if (text == "terms") {
document.getElementById("infoText").innerHTML = termsText;