diff --git a/.gitignore b/.gitignore index 92b2c45..422e2c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ -node_modules/ -tmp/ +/node_modules +/coverage +/doc +/tmp +*.log +*.tgz diff --git a/.jshintignore b/.jshintignore new file mode 100644 index 0000000..c64162c --- /dev/null +++ b/.jshintignore @@ -0,0 +1 @@ +/coverage/* diff --git a/.jshintrc b/.jshintrc index df6e7cc..8e279ec 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,3 +1,4 @@ { - "node": true + "node": true, + "-W030": true } diff --git a/.npmignore b/.npmignore index 12a26d3..a0cdcd0 100644 --- a/.npmignore +++ b/.npmignore @@ -1,5 +1,12 @@ -**/.* -test/ -tmp/ -markedpp-*.tgz +/node_modules +/coverage +/doc +/test +/tmp +.* +*.log +*.tgz Makefile +bower.json +component.json +markedpp.min.js \ No newline at end of file diff --git a/Makefile b/Makefile index 2b5c7ee..ba2d7b4 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,30 @@ -all: jshint runtest minify gitadd +all: readme jshint 0.8 0.12 markedpp.min.js -minify: - @uglifyjs -m --comments '/\*[^\0]+?\@copyright[^\0]+?\*/' -o markedpp.min.js lib/markedpp.js +markedpp.min.js: lib/markedpp.js + @uglifyjs -m --comments '/\*[^\0]+?\@copyright[^\0]+?\*/' -o $@ $< jshint: - @jshint lib/*.js test/*.js + @npm run lint -gitadd: - @git ls -m | xargs git add - -runtest: +test: @npm test +cover: + @npm run cover + clean: @rm markedpp.min.js + @rm -rf doc coverage + +readme: README.md + ./bin/markedpp.js --githubid $< > tmp.md + mv tmp.md $< + +browser: + x-www-browser "http://localhost:3000" ;\ + node test/server.js + +%: + n $@ && npm test -.PHONY: clean all +.PHONY: readme jshint test clean browser all diff --git a/README.md b/README.md index 75254c7..6784119 100644 --- a/README.md +++ b/README.md @@ -36,45 +36,47 @@ Albeight the markdown syntax of this project here is slightly different, [markdo * [skip](#numberedheadings-skip) * [start](#numberedheadings-start) * [omit](#numberedheadings-omit) +* [Specials](#specials) + * [Using custom anchors](#using-custom-anchors) + * [Changing type of autoId generation](#changing-type-of-autoid-generation) * [Installation](#installation) * [Usage](#usage) * [CLI](#cli) -* [Running Tests & Contributing](#running-tests-contributing) +* [Running Tests & Contributing](#running-tests--contributing) * [Contribution and License Agreement](#contribution-and-license-agreement) * [License](#license) * [References](#references) - ## Extended Markdown Syntax The extended markdown syntax for the preprocessor borrows from the already existing image tag. All commands start using a `!` followed by the command. Options for the specific command are specified in normal brackets. ! () - + ### toc - !toc [([level=1-6] [minlevel=1-6] [numbered] [omit="...;..."])] + !toc [([level=1-6] [minlevel=1-6] [numbered] [omit="...;..."])] Inserts a "Table of Contents" section: -* level: \[optional\] level of headings to show (default is 3) -* minlevel: \[optional\] min-level of headings to show (default is 1) +* level: \[optional\] level of headings to show (default is 3) +* minlevel: \[optional\] min-level of headings to show (default is 1) * numbered: \[optional\] show numbered -* omit: \[optional\] remove headings from ToC. Headings need to be given in `"` and separated by `;` +* omit: \[optional\] remove headings from ToC. Headings need to be given in `"` and separated by `;` E.g. * [One](#one) * [One One](#one-one) - * [One One One](#one-one-one) + * [One One One](#one-one-one) * [Two](#two) * [Two One](#two-one) - -This includes a "Table of Contents" section. All headings up to level=3 will be linked with their references as a unnumbered bullet list. + + This includes a "Table of Contents" section. All headings up to level=3 will be linked with their references as a unnumbered bullet list. #### level @@ -112,12 +114,12 @@ The Preprocessor inserts a html comment tag which allows regenerating the TOC on E.g. - + - * [One](#one) - * [Two](#two) + * [One](#one) + * [Two](#two) - + #### omit @@ -125,33 +127,33 @@ To omit headings in the ToC define those with `omit`. E.g. to remove "Table of Contents" and the branch of "Heading 1": - # Table of Contents - - !toc (omit="Table of Contents;Heading 1") + # Table of Contents - # Heading 1 - ## Heading 1.1 - # Heading 2 + !toc (omit="Table of Contents;Heading 1") + + # Heading 1 + ## Heading 1.1 + # Heading 2 will result in: - # Table of Contents + # Table of Contents - + - * [Heading 2](#heading-2) + * [Heading 2](#heading-2) - + - # Heading 1 + # Heading 1 - ## Heading 1.1 + ## Heading 1.1 - # Heading 2 + # Heading 2 ### ref - !ref + !ref This command includes a references section displaying all references using the alternate link syntax
`[]: ""` given in the document being preprocessed. @@ -160,26 +162,26 @@ Local references which start with a "#" are ignored. E.g. - !ref + !ref - [markdown]: http://daringfireball.net/projects/markdown/syntax - [GFM]: https://help.github.com/articles/github-flavored-markdown "Github-Flavored-Markdown" + [markdown]: http://daringfireball.net/projects/markdown/syntax + [GFM]: https://help.github.com/articles/github-flavored-markdown "Github-Flavored-Markdown" renders as: - <!-- !ref --> + <!-- !ref --> - * [Github-Flavored-Markdown][GFM] - * [markdown][markdown] + * [Github-Flavored-Markdown][GFM] + * [markdown][markdown] - <!-- ref! --> + <!-- ref! --> - [markdown]: http://daringfireball.net/projects/markdown/syntax - [GFM]: https://help.github.com/articles/github-flavored-markdown "Github-Flavored-Markdown" + [markdown]: http://daringfireball.net/projects/markdown/syntax + [GFM]: https://help.github.com/articles/github-flavored-markdown "Github-Flavored-Markdown" ### include - !include (filename [lang=...]) + !include (filename [lang=...]) This inserts the the file specified with `filename` at the given position in the document being preprocessed. The preprocessor inserts any type of files. @@ -195,7 +197,7 @@ E.g. !include (test.js lang=javascript) -renders as +renders as ```javascript /* contents of test.js */ @@ -205,26 +207,26 @@ Files to insert which cannot be found or recursive inset of the same file leaves ### numberedheadings - !numberedheadings [([level=1-6] [minlevel=1-6] [skip=1..] [start=1..] [omit="...;..."])] + !numberedheadings [([level=1-6] [minlevel=1-6] [skip=1..] [start=1..] [omit="...;..."])] Add numbers on headings -* level: {Number} \[optional\] level of Headings to show (default is 3) +* level: {Number} \[optional\] level of Headings to show (default is 3) * minlevel: {Number} \[optional\] min-level of Headings to show (default is 1) * skip: {Number} \[optional\] skip number of Headings on min-level * start: {Number} \[optional\] start numbering of Headings with given number -* omit: {String} \[optional\] omit numbering of Headings. Headings need to be given in `"` and separated by `;` +* omit: {String} \[optional\] omit numbering of Headings. Headings need to be given in `"` and separated by `;` All Headings up to level 3 will get numbered. If used, this command shall be given at the very top of a document. -<a name="numberedheadings-level"> +<a name="numberedheadings-level"/> #### level With the option `level`, the Headings level where the numbering shall be applied, can be specified. E.g. - !numberedheadings (level=2) + !numberedheadings (level=2) will number all Headings of level 1 and 2. @@ -240,36 +242,80 @@ E.g. 1\. [One](#1-one) <br> 1.1\. [One One](#1-1-one-one) -<a name="numberedheadings-minlevel"> +<a name="numberedheadings-minlevel"/> #### minlevel The option `minlevel` omits numbering all Headings below `minlevel`. -<a name="numberedheadings-skip"> +<a name="numberedheadings-skip"/> #### skip The option `skip` skips numbering for the first Headings on `minlevel`. -<a name="numberedheadings-start"> +<a name="numberedheadings-start"/> #### start The option `start` starts the numbering with the given number. -<a name="numberedheadings-omit"> +<a name="numberedheadings-omit"/> #### omit The option `omit` omits numbering all Headings matching. +## Specials + +### Using custom anchors + +Custom anchors can be added to headings by putting a `<a name="..."/>` in a separate line right in front of the heading. + +```html +<a name="custom-heading"/> +# Heading with custom id +``` + +Instead of using the auto generated id `#heading-with-custom-id`, `#custom-heading` will be used as anchor in the ToC. + +### Changing type of autoId generation + +Unfortunately there is no unique format which defines the composition of an auto identifier in markdown. +[marked][] uses a different format then github. + +On the CLI + +```bash +markedpp --githubid file.md +``` + +Or use in your options + +```javascript +var markedpp = require('markedpp'), + md = '!toc\n# hello\n## hello & again', + options = { githubid: true }; + +markedpp(md, options, function(err, result){ + console.log(result); +}); +``` + ## Installation +For use from commandline consider global install + npm install -g markedpp + +For your project + + npm install markedpp ## Usage ```javascript -var markedpp = require('markedpp'); -markedpp('!numberedheadings\n!toc(level=1)\n# hello\n## hello again', function(err, data){ - console.log(data); +var markedpp = require('markedpp'), + md = '!numberedheadings\n!toc(level=1)\n# hello\n## hello again'; + +markedpp(md, function(err, result){ + console.log(result); /* Outputs <!-- !numberedheadings --> @@ -289,9 +335,12 @@ markedpp('!numberedheadings\n!toc(level=1)\n# hello\n## hello again', function(e To include files the dirname need to be defined via `options`, otherwise it is assumed that the file to include is relative to the current working directory: ```javascript -var markedpp = require('markedpp'); -markedpp('!include(hello.md)', { dirname: __dirname }, function(err, data){ - console.log(data); +var markedpp = require('markedpp'), + md = '!include(hello.md)', + options = { dirname: __dirname }; + +markedpp(md, options, function(err, result){ + console.log(result); }); ``` @@ -299,15 +348,15 @@ markedpp('!include(hello.md)', { dirname: __dirname }, function(err, data){ Standalone -``` bash +```bash $ (cat<<EOF !numberedheadings !toc(level=1) # hello ## hello again EOF -) > hello.md -$ markedpp hello.md +) > hello.md +$ markedpp hello.md <!-- !numberedheadings --> <!-- !toc (level=1) --> @@ -323,7 +372,7 @@ $ markedpp hello.md Together with [marked][marked] -``` bash +```bash $ markedpp --no-tags hello.md | marked <ul> <li><a href="#1-hello">1. hello</a></li> @@ -338,7 +387,7 @@ If you want to submit a pull request, make sure your changes pass the tests. If To run the tests: -``` bash +```bash npm test ``` @@ -359,7 +408,7 @@ See [LICENSE][] for more info. <!-- !ref --> * [Github-Flavored-Markdown][GFM] -* [license][license] +* [LICENSE][LICENSE] * [markdown][markdown] * [markdown-pp][markdown-pp] * [marked][marked] @@ -371,3 +420,8 @@ See [LICENSE][] for more info. [markdown-pp]: https://github.com/jreese/markdown-pp [GFM]: https://help.github.com/articles/github-flavored-markdown "Github-Flavored-Markdown" [LICENSE]: ./LICENSE + + + + + diff --git a/bower.json b/bower.json index 875e52c..3f3c21e 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "markedpp", - "version": "0.3.6", + "version": "0.3.7", "description": "Preprocessor for markdown files", "main": "lib/markedpp.js", "authors": [ @@ -33,6 +33,6 @@ "test", "tmp", "*.tgz", - "Makefile" + "Makefile" ] -} +} \ No newline at end of file diff --git a/component.json b/component.json index e20556d..7829bb5 100644 --- a/component.json +++ b/component.json @@ -1,6 +1,6 @@ { "name": "markedpp", - "version": "0.3.6", + "version": "0.3.7", "repo": "commenthol/markedpp", "description": "Preprocessor for markdown files", "keywords": [ @@ -17,4 +17,4 @@ ], "main": "lib/markedpp.js", "license": "MIT" -} +} \ No newline at end of file diff --git a/lib/markedpp.js b/lib/markedpp.js index 2dd6067..9ebe9fd 100644 --- a/lib/markedpp.js +++ b/lib/markedpp.js @@ -10,6 +10,8 @@ * @credits Christopher Jeffrey <https://github.com/chjj/marked> */ +/*globals XMLHttpRequest,location,define */ + (function (ctx) { 'use strict'; @@ -17,19 +19,20 @@ * default values */ var defaults = { - gfm: true, // consider gfm fences - include: true, // enable !includes - toc: true, // enable !toc + gfm: true, // consider gfm fences + include: true, // enable !includes + toc: true, // enable !toc numberedheadings: true, // enable !numberedheadings - ref: true, // enable !ref + ref: true, // enable !ref - breaks: true, // render <br> tags for Table of Contents with numbered style - tags: true, // render pre-proc tags <!-- !command --> - level: 3, // default level for !toc and !numberheadings - minlevel: 1, // default minlevel for !toc and !numberheadings + breaks: true, // render <br> tags for Table of Contents with numbered style + tags: true, // render pre-proc tags <!-- !command --> + level: 3, // default level for !toc and !numberheadings + minlevel: 1, // default minlevel for !toc and !numberheadings - autonumber: true, // renumber lists - autoid: true // update identifiers on headings automatically + autonumber: true, // renumber lists + autoid: true, // update identifiers on headings automatically + githubid: false, // use github convention for heading auto identifiers }; /* @@ -227,13 +230,11 @@ function xhr (url, options, callback) { var o = options ? options : {}; var req = new XMLHttpRequest(), method = o.method || 'get', - async = (typeof o.async !== 'undefined' ? o.async : true), params = o.data || null, key; req.queryString = params; - req.open(method, url, async); - // Set "X-Requested-With" header + req.open(method, url, true); req.setRequestHeader('X-Requested-With','XMLHttpRequest'); if (method.toLowerCase() == 'post') { @@ -257,11 +258,14 @@ function xhr (url, options, callback) { } } - if (async) { - req.onreadystatechange = stateChange; + req.onreadystatechange = stateChange; + + try { + req.send(params); + } catch(e) { + console.log('Error: Resolving URL ' + url); + callback(e); } - req.send(params); - if (!async) stateChange(); } var ppInclude; @@ -278,7 +282,7 @@ else { * @param {Function} callback - `function(err, tokens)` */ ppInclude = function (tokens, options, callback) { - var dirname = options.dirname || '/', + var dirname = options.dirname || path.dirname(location.pathname), lexed = {}, _options = merge({}, options); @@ -290,18 +294,22 @@ else { typeof token.text === 'string' && ! _options.ppInclude[token.text] ) { - var path_ = path.resolve(path.join(path.dirname(location.pathname), dirname, token.text)); - var url = location.origin + path_; + var path_ = path.resolve(path.join(dirname, token.text)); + var url = location.protocol +'//' + location.host + path_; + xhr(url, function (err, src) { _options.ppInclude[token.text] = 1; _options.dirname = path.dirname(path_); if (err) { - console.error('Error: ' + err.message); + console.log('Error: ' + err.message); return done(); } var lexer = new Lexer(_options); src = token.indent + src.split('\n').join('\n' + token.indent); ppInclude( lexer.lex(src), _options, function (err, ntokens){ + if (err) { + // TODO + } lexed[token.text] = ntokens; done(); }); @@ -311,11 +319,11 @@ else { done(); } }, - function (err) { + function () { var _tokens = []; // compose the new tokens array - tokens.forEach(function(token, idx){ + tokens.forEach(function(token){ if (token.type === 'ppinclude' && typeof token.text === 'string' && lexed[token.text] !== undefined) @@ -344,15 +352,16 @@ else { } /* - * preprocessor regex rules + * block lexer rules */ var block = { newline: /^\n+/, code: /^( {4}[^\n]+\n*)+/, fences: noop, hr: /^( *[-*_]){3,} *(?:\n+|$)/, - heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n|$)/, - lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n|$)/, + heading: /^headingid *(#{1,6}) *([^\n]+?) *#* *(?:\n|$)/, + lheading: /^headingid([^\n]+)\n *(=|-){2,} *(?:\n|$)/, + headingid: /(?: *<a name="([^\"]+)" *(?:\/>|> *<\/a>|>) *\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*$))/, @@ -385,6 +394,13 @@ block.blockquote = replace(block.blockquote) ('def', block.def) (); +block.heading = replace(block.heading) + ('headingid', block.headingid) + (); +block.lheading = replace(block.lheading) + ('headingid', block.headingid) + (); + // list of allowed tags - TODO //~ block._tag = '(?!(?:' + //~ 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' + @@ -417,7 +433,9 @@ block.opts.gfm = { fences: /^( *)(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\2 *(?:\n|$)/ }; -// preprocessor rules +/* + * preprocessor rules + */ var preproc = { _ppopts_: / ?(?:\(([^\)]+)\))?/, @@ -534,15 +552,14 @@ Lexer.prototype.token = function(src, top) { bull, next, l, + b, i, item, space, loose, bq, tmp, - spaces, - opts, - self = this; + opts; while (src) { // newline @@ -588,30 +605,43 @@ Lexer.prototype.token = function(src, top) { }); continue; } - // heading + /* + * heading + * cap[1] - headingid from <a name=""> + * cap[2] - heading char + * cap[3] - heading text + */ if ((cap = this.rules.heading.exec(src))) { src = src.substring(cap[0].length); tmp = new InlineLexer(this.options); this.tokens.push({ type: 'heading', - depth: cap[1].length, - text: cap[2], - raw: cap[2], + depth: cap[2].length, + text: cap[3], + raw: cap[3], autoid: null, - inline: tmp.lex(cap[2]) + anchor: cap[1], + inline: tmp.lex(cap[3]) }); continue; } - // lheading + /* + * lheading + * cap[1] - headingid from <a name=""> + * cap[2] - heading char + * cap[3] - heading text + */ if ((cap = this.rules.lheading.exec(src))) { src = src.substring(cap[0].length); tmp = new InlineLexer(this.options); this.tokens.push({ type: 'heading', - depth: cap[2] === '=' ? 1 : 2, - text: cap[1], - raw: cap[1], - inline: tmp.lex(cap[1]) + depth: cap[3] === '=' ? 1 : 2, + text: cap[2], + raw: cap[2], + autoid: null, + anchor: cap[1], + inline: tmp.lex(cap[2]) }); continue; } @@ -929,7 +959,8 @@ Lexer.range = function (val, min, max, def) { } }; -/** +/* + * inline lexer rules */ var inline = { escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, @@ -1142,7 +1173,7 @@ InlineLexer.prototype.lex = function(src) { /** * Number headings * @constructor - * @private + * @api private */ function Numbering (init) { this._ = [0,0,0,0,0,0,0]; @@ -1211,14 +1242,18 @@ function Renderer(options) { * @param {String} raw - Raw heading text (without numbers) * @return {String} rendered output */ -Renderer.prototype.heading = function(text, level, raw, number, autoid) { - var atx = '########'.substring(0, level); +Renderer.prototype.heading = function(text, level, raw, number, autoid, anchor) { + var atx = ''; + if (anchor) { + atx += '<a name="'+anchor+'"/>\n'; + } + atx += '########'.substring(0, level); return atx + ' ' + text + '\n'; }; /** * Render text - * @param {String} text + * @param {String} text - text * @return {String} rendered output */ Renderer.prototype.paragraph = function(text) { @@ -1226,13 +1261,18 @@ Renderer.prototype.paragraph = function(text) { }; /** + * Render newline `<br>` + * @param {String} text - text + * @return {String} rendered output */ Renderer.prototype.newline = function(text) { return text; }; /** - * TODO + * Renders a blockquote + * @param {String} body - body of blockquote + * @return {String} rendered output */ Renderer.prototype.blockquote = function(body) { //~ return body.replace(/\n/gm, '\n> '); @@ -1240,14 +1280,19 @@ Renderer.prototype.blockquote = function(body) { }; /** - * TODO + * Renders a list + * @param {String} body - body of list + * @return {String} rendered output */ -Renderer.prototype.list = function(body, ordered) { +Renderer.prototype.list = function(body/*, ordered*/) { return body.replace(/\n$/, ''); }; /** - * TODO + * Renders a listitem + * @param {String} bullet - bullet char + * @param {String} text - text of listitem + * @return {String} rendered output */ Renderer.prototype.listitem = function(bullet, text) { var i, indent = ''; @@ -1281,7 +1326,9 @@ Renderer.prototype.reference = function(ref, href, title) { /** * Render a ppinclude which could not be resolved - * @param {String} text + * @param {String} text - text + * @param {String} indent - indent as whitespaces string + * @param {String} lang - language of included file * @return {String} rendered output */ Renderer.prototype.include = function(text, indent, lang) { @@ -1299,12 +1346,27 @@ Renderer.prototype.fence = function(lang, indent, fences) { return indent + fences + (lang ? lang : '') + '\n'; }; +/** + * Render codeblock + * @param {String} text - text + * @return rendered output + */ Renderer.prototype.codeblock = function(text) { return text; }; +/** + * Render html + * @param {String} text - text + * @return rendered output + */ Renderer.prototype.html = function(text) { return text; }; +/** + * Render horizontal ruler + * @param {String} text - text + * @return rendered output + */ Renderer.prototype.hr = function(text) { return text; }; @@ -1359,7 +1421,7 @@ Renderer.prototype.code = function(text) { /** * Sorter to sort reference by title - * @private + * @api private */ Renderer.sortByTitle = function (a, b) { var _a = a.title.toLowerCase(), @@ -1416,7 +1478,6 @@ Renderer.prototype.references = function (refs) { */ Renderer.prototype.tableOfContents = function (toc, options) { var self = this, - i, omitlevel, out = [], opts = this.joinOpts({ @@ -1644,20 +1705,26 @@ Parser.prototype.tableOfContents = function () { /** * Generate a internal reference id (method used by marked) - * @private - * @param {String} raw - * @return {String} + * + * @api private + * @param {Object} token - parsed token + * @param {Object} opts - options + * @param {Boolean} opts.raw - if true use `token.raw` for id generation othewise `token.text` is used + * @return {String} id */ Parser.prototype.headingAutoId = function (token, opts) { opts = opts || { raw: false }; var id = ( !opts.raw ? token.text : token.raw || '').replace(/^#/, ''); - - if (false /*github*/) { - // TODO - - //https://github.com/thlorenz/anchor-markdown-header - id = token.text.replace(/ /g,'-') + + if (token.anchor) { + return '#' + token.anchor; + } + + if (this.options.githubid) { + // from https://github.com/thlorenz/anchor-markdown-header + id = id.replace(/ /g,'-') .replace(/%([abcdef]|\d){2,2}/ig, '') // escape codes - .replace(/[\/?:\[\]`.,()*"';{}+<>]/g,'') // single chars that are removed + .replace(/[\/?:\[\]`.,()*"';{}+<>&]/g,'') // single chars that are removed .toLowerCase(); } else { @@ -1676,6 +1743,7 @@ Parser.prototype.updateAutoIdentifier = function () { var self = this, headings = {}; + // sanitize the id before lookup function prep (id) { id = id.replace(/(?:%20|\+)/g, ' '); id = self.headingAutoId({text: id}); @@ -1684,10 +1752,9 @@ Parser.prototype.updateAutoIdentifier = function () { // obtain headings ids this.tokens = this.tokens.map(function(token){ - var i, - id, + var id, raw; - + if (token.type === 'heading') { id = self.headingAutoId(token); raw = self.headingAutoId(token, { raw: true }); @@ -1718,11 +1785,13 @@ Parser.prototype.updateAutoIdentifier = function () { else { switch(token.type) { case 'def': { - id = prep(token.href); - if (headings[id]) { - token.href = headings[id]; + if (token.href && token.href.indexOf('#') === 0) { + id = prep(token.href); + if (headings[id]) { + token.href = headings[id]; + } + break; } - break; } } } @@ -1820,7 +1889,8 @@ Parser.prototype.tok = function(options) { this.token.depth, this.token.raw, this.token.number, - this.token.autoid); + this.token.autoid, + this.token.anchor); } case 'fences': { return this.renderer.fences( @@ -2027,6 +2097,9 @@ function markedpp(src, options, callback) { options = merge({}, defaults, options || {}); Lexer.lex(src, options, function(err, tokens){ + if (err) { + // TODO + } var out = Parser.parse(tokens, options); callback(null, out); }); @@ -2037,6 +2110,9 @@ function markedpp(src, options, callback) { */ markedpp.defaults = defaults; markedpp.Lexer = Lexer; +markedpp.InlineLexer = InlineLexer; +markedpp.Renderer = Renderer; +markedpp.Parser = Parser; markedpp.merge = merge; markedpp.setOptions = function(opt) { diff --git a/lib/ppinclude.js b/lib/ppinclude.js index 578495e..8a02153 100644 --- a/lib/ppinclude.js +++ b/lib/ppinclude.js @@ -18,8 +18,8 @@ var fs = require('fs'), /** * Wrapper to hand over Lexer and other required functions - * @param {Lexer} Lexer - * @param {Function} merge + * @param {Lexer} Lexer - lexer + * @param {Function} merge - merge function * @return {Function} ppInclude */ function ppIncludeWrap (Lexer, merge) { @@ -45,7 +45,7 @@ function ppIncludeWrap (Lexer, merge) { ! _options.ppInclude[token.text] ) { var file = path.resolve(path.join(dirname, token.text)); - fs.readFile(file, { encoding: 'utf8' }, function (err, src) { + fs.readFile(file, 'utf8', function (err, src) { _options.ppInclude[token.text] = 1; _options.dirname = path.dirname(file); if (err) { diff --git a/markedpp.min.js b/markedpp.min.js index 2529beb..79eb2d3 100644 --- a/markedpp.min.js +++ b/markedpp.min.js @@ -9,4 +9,4 @@ * @note Code inspired by `marked` project * @credits Christopher Jeffrey <https://github.com/chjj/marked> */ -(function(e){"use strict";var t={gfm:true,include:true,toc:true,numberedheadings:true,ref:true,breaks:true,tags:true,level:3,minlevel:1,autonumber:true,autoid:true};function n(){return typeof process!=="undefined"&&typeof module!=="undefined"&&module.exports}function r(e,t){e=e.source;t=t||"";return function n(r,i){if(!r)return new RegExp(e,t);i=i.source||i;i=i.replace(/(^|[^\[])\^/g,"$1");e=e.replace(r,i);return n}}function i(){}i.exec=i;function s(e){var t=1,n,r;for(;t<arguments.length;t++){n=arguments[t];for(r in n){if(Object.prototype.hasOwnProperty.call(n,r)){e[r]=n[r]}}}return e}function o(e,t){var n=parseInt(e,10);if(isNaN(n)){if(t===true)return;else return e}return n}var p={normalizeArray:function(e,t){var n=0;for(var r=e.length-1;r>=0;r--){var i=e[r];if(i==="."){e.splice(r,1)}else if(i===".."){e.splice(r,1);n++}else if(n){e.splice(r,1);n--}}if(t){for(;n--;n){e.unshift("..")}}return e},resolve:function(){var e="",t=false;for(var n=arguments.length-1;n>=-1&&!t;n--){var r=n>=0?arguments[n]:"/";if(!r){continue}e=r+"/"+e;t=r.charAt(0)==="/"}e=this.normalizeArray(e.split("/").filter(function(e){return!!e}),!t).join("/");return(t?"/":"")+e||"."},splitPathRe:/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,splitPath:function(e){return this.splitPathRe.exec(e).slice(1)},dirname:function(e){var t=this.splitPath(e),n=t[0],r=t[1];if(!n&&!r){return"."}if(r){r=r.substr(0,r.length-1)}return n+r},join:function(){return Array.prototype.slice.call(arguments).join("/")}};var u={_eachLimit:function(e){return function(t,n,r){r=r||function(){};if(!t.length||e<=0){return r()}var i=0;var s=0;var o=0;(function p(){if(i>=t.length){return r()}while(o<e&&s<t.length){s+=1;o+=1;n(t[s-1],function(e){if(e){r(e);r=function(){}}else{i+=1;o-=1;if(i>=t.length){r()}else{p()}}})}})()}},eachLimit:function(e,t,n,r){var i=this._eachLimit(t);i.apply(null,[e,n,r])}};function l(e,t,n){if(typeof t==="function"){n=t;t=null}var r=t?t:{};var i=new XMLHttpRequest,s=r.method||"get",o=typeof r.async!=="undefined"?r.async:true,p=r.data||null,u;i.queryString=p;i.open(s,e,o);i.setRequestHeader("X-Requested-With","XMLHttpRequest");if(s.toLowerCase()=="post"){i.setRequestHeader("Content-Type","application/x-www-form-urlencoded")}for(u in r.headers){if(r.headers.hasOwnProperty(u)){i.setRequestHeader(u,r.headers[u])}}function l(){if(i.readyState===4){if(/^[20]/.test(i.status)){n(null,i.responseText)}else if(/^[45]/.test(i.status)){n(new Error(i.status))}}}if(o){i.onreadystatechange=l}i.send(p);if(!o)l()}var a;if(n()){a=require("./ppinclude")(c,s)}else{a=function(e,t,n){var r=t.dirname||"/",i={},o=s({},t);if(!o.ppInclude){o.ppInclude={}}u.eachLimit(e,5,function(e,t){if(e.type==="ppinclude"&&typeof e.text==="string"&&!o.ppInclude[e.text]){var n=p.resolve(p.join(p.dirname(location.pathname),r,e.text));var s=location.origin+n;l(s,function(r,s){o.ppInclude[e.text]=1;o.dirname=p.dirname(n);if(r){console.error("Error: "+r.message);return t()}var u=new c(o);s=e.indent+s.split("\n").join("\n"+e.indent);a(u.lex(s),o,function(n,r){i[e.text]=r;t()})})}else{t()}},function(t){var r=[];e.forEach(function(e,t){if(e.type==="ppinclude"&&typeof e.text==="string"&&i[e.text]!==undefined){r.push({type:"ppinclude_start",text:e.text,indent:e.indent,lang:e.lang});i[e.text].forEach(function(e){r.push(s({},e))});r.push({type:"ppinclude_end",lang:e.lang})}else{r.push(e)}});n(null,r)})}}var h={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:i,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n|$)/,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:i,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/,ppinclude:i,ppnumberedheadings:i,pptoc:i,ppref:i};h.bullet=/(?:[*+-]|\d+\.)/;h.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;h.item=r(h.item,"gm")(/bull/g,h.bullet)();h.list=r(h.list)(/bull/g,h.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+h.def.source+")")();h.blockquote=r(h.blockquote)("def",h.def)();h._tag="(?!(?:[A-Za-z][A-Za-z-]*)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";h.html=r(h.html)("comment",/<!--[\s\S]*?-->/)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,h._tag)();h.paragraph=r(h.paragraph)("hr",h.hr)("heading",h.heading)("lheading",h.lheading)("blockquote",h.blockquote)("tag","<"+h._tag)("def",h.def)();h.opts={};h.opts.gfm={fences:/^( *)(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\2 *(?:\n|$)/};var f={_ppopts_:/ ?(?:\(([^\)]+)\))?/,ppinclude:/^( *)(?:\!(?:include)_ppopts_|_ppinclude_|_ppincludeCompat_) *(?:\n|$)/,_ppinclude_:/<!-- *include_ppopts_ *-->(?:(?!<!-- *\/include * -->)[^])*<!-- *\/include * -->/,_ppincludeCompat_:/\!INCLUDE "([^"]+)"/,ppnumberedheadings:/^ *(?:\!(?:numberedheadings)_ppopts_|_ppnumberedheadings_) *(?:\n+|$)/,_ppnumberedheadings_:/<!-- \!*numberedheadings_ppopts_ *-->/,pptoc:/^(?:\!(?:toc)_ppopts_|_pptoc_|_pptocCompat1_|_pptocCompat2_|_pptocCompat3_) *(?:\n+|$)/,_pptoc_:/<!-- *\!toc_ppopts_ *-->(?:(?!<!-- *toc\! * -->)[^])*<!-- *toc\! * -->/,_pptocCompat1_:/\!TOC/,_pptocCompat2_:/<!-- *toc *-->(?:(?!<!-- *(?:\/toc|toc stop) * -->)[^])*<!-- *(?:\/toc|toc stop) * -->/,_pptocCompat3_:/<!-- *toc *-->/,ppref:/^(?:\!(?:ref)|_ppref_|_pprefCompat1_|_pprefCompat2_) *(?:\n|$)/,_ppref_:/<!-- *\!ref *-->(?:(?!<!-- *ref\! * -->)[^])*<!-- *ref\! * -->/,_pprefCompat1_:/\!REF/,_pprefCompat2_:/<!-- *ref *-->(?:(?!<!-- *\/ref * -->)[^])*<!-- \/ref * -->/};f.ppinclude=r(f.ppinclude)("_ppinclude_",f._ppinclude_)("_ppincludeCompat_",f._ppincludeCompat_)("_ppopts_",f._ppopts_)("_ppopts_",f._ppopts_)();f.ppnumberedheadings=r(f.ppnumberedheadings)("_ppnumberedheadings_",f._ppnumberedheadings_)("_ppopts_",f._ppopts_)("_ppopts_",f._ppopts_)();f.pptoc=r(f.pptoc)("_pptoc_",f._pptoc_)("_ppopts_",f._ppopts_)("_ppopts_",f._ppopts_)("_pptocCompat1_",f._pptocCompat1_)("_pptocCompat2_",f._pptocCompat2_)("_pptocCompat3_",f._pptocCompat3_)();f.ppref=r(f.ppref)("_ppref_",f._ppref_)("_pprefCompat1_",f._pprefCompat1_)("_pprefCompat2_",f._pprefCompat2_)();h.opts.include={ppinclude:f.ppinclude};h.opts.numberedheadings={ppnumberedheadings:f.ppnumberedheadings};h.opts.toc={pptoc:f.pptoc};h.opts.ref={ppref:f.ppref};function c(e){this.tokens=[];this.options=e||t;this.rules=h;if(this.options.gfm){s(this.rules,h.opts.gfm)}if(this.options.include){s(this.rules,h.opts.include)}if(this.options.numberedheadings){s(this.rules,h.opts.numberedheadings)}if(this.options.toc){s(this.rules,h.opts.toc)}if(this.options.ref){s(this.rules,h.opts.ref)}}c.prototype.lex=function(e){e=e.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(e,true)};c.prototype.token=function(e,n){var r,i,s,p,u,l,a,h,f,d,m,_,k=this;while(e){if(r=this.rules.newline.exec(e)){e=e.substring(r[0].length);this.tokens.push({type:"space",text:r[0]})}if(r=this.rules.ppinclude.exec(e)){e=e.substring(r[0].length);d=r[2]||r[3]||r[4];_=c.splitOpts(d);d=d.replace(/ *(?:[a-z]+=[a-z0-9\-]+)/,"").replace(/\\ /g," ");this.tokens.push({type:"ppinclude",text:d,indent:r[1],lang:_.lang});continue}if(r=this.rules.code.exec(e)){e=e.substring(r[0].length);this.tokens.push({type:"code",text:r[0]});continue}if(r=this.rules.fences.exec(e)){e=e.substring(r[0].length);this.tokens.push({type:"fences",indent:r[1],fences:r[2],lang:r[3],text:r[4]});continue}if(r=this.rules.heading.exec(e)){e=e.substring(r[0].length);d=new g(this.options);this.tokens.push({type:"heading",depth:r[1].length,text:r[2],raw:r[2],autoid:null,inline:d.lex(r[2])});continue}if(r=this.rules.lheading.exec(e)){e=e.substring(r[0].length);d=new g(this.options);this.tokens.push({type:"heading",depth:r[2]==="="?1:2,text:r[1],raw:r[1],inline:d.lex(r[1])});continue}if(r=this.rules.hr.exec(e)){e=e.substring(r[0].length);this.tokens.push({type:"hr",text:r[0]});continue}if(r=this.rules.blockquote.exec(e)){e=e.substring(r[0].length);this.tokens.push({type:"blockquote_start"});r=r[0].replace(/^ *> ?/gm,"");this.token(r,n);this.tokens.push({type:"blockquote_end"});continue}if(r=this.rules.list.exec(e)){e=e.substring(r[0].length);i=r[2];this.tokens.push({type:"list_start",ordered:i.length>1,start:o(i,true)});r=r[0].match(this.rules.item);s=false;p=r.length;u=0;for(;u<p;u++){l=r[u];i=this.rules.bullet.exec(l)[0];a=l.length;l=l.replace(/^ *([*+-]|\d+\.) +/,"");if(~l.indexOf("\n ")){a-=l.length;l=!this.options.pedantic?l.replace(new RegExp("^ {1,"+a+"}","gm"),""):l.replace(/^ {1,4}/gm,"")}if(this.options.smartLists&&u!==p-1){b=this.rules.bullet.exec(r[u+1])[0];if(i!==b&&!(i.length>1&&b.length>1)){e=r.slice(u+1).join("\n")+e;u=p-1}}h=s||/\n\n(?!\s*$)/.test(l);if(u!==p-1){s=l.charAt(l.length-1)==="\n";if(!h)h=s}this.tokens.push({type:h?"loose_item_start":"list_item_start",text:i});this.token(l,false,f);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(r=this.rules.ppnumberedheadings.exec(e)){e=e.substring(r[0].length);_=c.splitOpts(r[1]||r[2]);if(typeof _.omit==="string"){_.omit=[_.omit]}this.options.numberedHeadings=true;this.tokens.push({type:"ppnumberedheadings",level:c.range(_.level,t.minlevel,6,t.level),minlevel:c.range(_.minlevel,t.minlevel,6),skip:_.skip,start:_.start,omit:_.omit});continue}if(r=this.rules.pptoc.exec(e)){e=e.substring(r[0].length);_=c.splitOpts(r[1]||r[2]);if(typeof _.omit==="string"){_.omit=[_.omit]}this.tokens.push({type:"pptoc",level:c.range(_.level,t.minlevel,6,t.level),minlevel:c.range(_.minlevel,t.minlevel,6),numbered:_.numbered,omit:_.omit});continue}if(r=this.rules.ppref.exec(e)){e=e.substring(r[0].length);this.tokens.push({type:"ppref"});continue}if(r=this.rules.html.exec(e)){e=e.substring(r[0].length);this.tokens.push({type:"html",pre:r[1]==="pre"||r[1]==="script"||r[1]==="style",text:r[0]});continue}if(n&&(r=this.rules.def.exec(e))){e=e.substring(r[0].length);this.tokens.push({type:"def",ref:r[1],href:r[2],title:r[3]});continue}if(n&&(r=this.rules.paragraph.exec(e))){e=e.substring(r[1].length);d=new g(this.options);this.tokens.push({type:"paragraph",text:r[1],inline:d.lex(r[1])});continue}if(r=this.rules.text.exec(e)){e=e.substring(r[0].length);d=new g(this.options);this.tokens.push({type:"text",text:r[0],inline:d.lex(r[0])});continue}if(e){throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}}return this.tokens};c.rules=h;c.lex=function(e,t,n){var r=new c(t);var i=r.lex(e);a(i,t,function(e,r){n(e,r,t)})};c.splitOpts=function(e){var t={},n,r="",i=/^(.+)$/,s=/^([a-z0-9]+)=(.*)$/,o=/^([a-z0-9]+)=(["'])(.*?)\2$/;(e||"").split(" ").forEach(function(e){if(/\\$|^["'].*[^"']$/.test(e)||n&&!n.test(e)){r+=e+" ";return}if(/\=(["']).*[^"']$/.test(e)){n=e.replace(/^.*\=(["']).*[^"']$/,"$1");n=new RegExp(n+"$");r+=e+" ";return}if(r){e=r+e;r="";n=undefined}if(o.test(e)){e.replace(o,function(e,n,r,i){t[n]=i.split(";");t[n]=t[n].map(function(e){if(/^\d+$/.test(e)){var t=parseInt(e,10);if(!isNaN(t)){e=t}}return e});if(t[n].length===1){t[n]=t[n][0]}})}else if(s.test(e)){e.replace(s,function(e,n,r){var i=parseInt(r,10);if(!isNaN(i)){r=i}t[n]=r})}else if(i.test(e)){e=e.replace(/\\ /g," ").replace(/^(["'])([^\1]+)\1$/,"$2");if(/^\!(.*)$/.test(e)){e=e.replace(/^\!(.*)$/,"$1");t[e]=false}else{t[e]=true}}});return t};c.range=function(e,t,n,r){if(e<t){return t}else if(e>n){return n}else{if(r&&e===r){return undefined}return e}};var d={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:i,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^(!)?\[(inside)\]\(href\)/,reflink:/^(!)?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^(!)?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:i,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/,_inside:/(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/,_href:/\s*<?([\s\S]*?)>?(?:\s+(['"][\s\S]*?['"]))?\s*/};d.link=r(d.link)("inside",d._inside)("href",d._href)();d.reflink=r(d.reflink)("inside",d._inside)();d.opts={};d.opts.gfm={escape:r(d.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:r(d.text)("]|","~]|")("|","|https?://|")()};d.opts.breaks={br:r(d.br)("{2,}","*")(),text:r(d.opts.gfm.text)("{2,}","*")()};function g(e){this.tokens=[];this.options=e||t;this.rules=d;if(this.options.gfm){s(this.rules,d.opts.gfm)}if(this.options.breaks){s(this.rules,d.opts.gfm,d.opts.breaks)}}g.rules=d;g.lex=function(e,t){var n=new g(t);return n.lex(e)};g.prototype.lex=function(e){var t;while(e){if(t=this.rules.escape.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"escape",text:t[1]});continue}if(!this.inLink&&(t=this.rules.url.exec(e))){e=e.substring(t[0].length);this.tokens.push({type:"url",text:t[1]});continue}if(t=this.rules.tag.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"tag",text:t[0]});continue}if(t=this.rules.link.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:t[1]?"image":"link",raw:t[0],text:t[2],href:t[3],title:t[4]});continue}if(t=this.rules.reflink.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:t[1]?"refimage":"reflink",raw:t[0],text:t[2],ref:t[3]});continue}if(t=this.rules.nolink.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:t[1]?"noimage":"nolink",raw:t[0],text:t[2]});continue}if(t=this.rules.strong.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"strong",text:t[2]||t[1],"char":/^(..)/.exec(t[0])[0]});continue}if(t=this.rules.em.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"em",text:t[2]||t[1],"char":/^(.)/.exec(t[0])[0]});continue}if(t=this.rules.code.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"code",text:t[0]});continue}if(t=this.rules.br.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"br",text:t[0]});continue}if(t=this.rules.del.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"del",text:t[1]});continue}if(t=this.rules.text.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"text",text:t[0]});continue}if(e){throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}}return this.tokens};function m(e){this._=[0,0,0,0,0,0,0];this.last=1;this._[1]=e?e-1:0}m.prototype.reset=function(e){for(var t=e+1;t<this._.length;t++){this._[t]=0}};m.prototype.val=function(e){var t,n=this._[1];for(t=2;t<=e;t++){n+="."+this._[t]}return n+"\\."};m.prototype.count=function(e){if(e<=6){if(this.last>e){this.reset(e)}this._[e]+=1;this.last=e;return this.val(e)}return};function _(e){this.options=e||{}}_.prototype.heading=function(e,t,n,r,i){var s="########".substring(0,t);return s+" "+e+"\n"};_.prototype.paragraph=function(e){return e};_.prototype.newline=function(e){return e};_.prototype.blockquote=function(e){return e.replace(/\n$/,"").replace(/^/gm,"> ")+"\n"};_.prototype.list=function(e,t){return e.replace(/\n$/,"")};_.prototype.listitem=function(e,t){var n,r="";e+=" ";for(n=0;n<e.length;n++){r+=" "}return e+t.replace(/\n(?!\n|$)/gm,"\n"+r)+"\n"};_.prototype.fences=function(e,t,n,r){return this.fence(t,n,r)+e+"\n"+this.fence("",n,r)};_.prototype.reference=function(e,t,n){return"["+e+"]: "+t+(n?' "'+n+'"':"")+"\n"};_.prototype.include=function(e,t,n){return t+"!include ("+e+(n?" lang="+n:"")+")\n"};_.prototype.fence=function(e,t,n){n=n||"```";t=t||"";return t+n+(e?e:"")+"\n"};_.prototype.codeblock=function(e){return e};_.prototype.html=function(e){return e};_.prototype.hr=function(e){return e};_.prototype.escape=function(e){return"\\"+e};_.prototype.url=function(e){return e};_.prototype.tag=function(e){return e};_.prototype.link=function(e,t,n,r){return"["+t+"]("+n+(r?" "+r:"")+")"};_.prototype.reflink=function(e,t,n){return"["+t+"]["+n+"]"};_.prototype.nolink=function(e,t){return"["+t+"]"};_.prototype.image=function(e,t,n,r){return"!"+this.link(e,t,n,r)};_.prototype.refimage=function(e,t,n){return"!"+this.reflink(e,t,n)};_.prototype.noimage=function(e,t){return"!"+this.nolink(e,t)};_.prototype.strong=function(e,t){return t+e+t};_.prototype.em=function(e,t){return t+e+t};_.prototype.del=function(e){return"~~"+e+"~~"};_.prototype.text=function(e){return e};_.prototype.br=function(e){return e};_.prototype.code=function(e){return e};_.sortByTitle=function(e,t){var n=e.title.toLowerCase(),r=t.title.toLowerCase();if(n>r){return 1}else if(n<r){return-1}else{return 0}};_.prototype.references=function(e){var t=[];e.map(function(e){if(!e.title){e.title=e.ref}return e}).sort(_.sortByTitle).forEach(function(e){t.push("* ["+e.title+"]["+e.ref+"]")});if(this.options.tags){return"<!-- !ref -->\n\n"+t.join("\n")+"\n\n<!-- ref! -->\n"}else{return t.join("\n")+"\n"}};_.prototype.tableOfContents=function(e,n){var r=this,i,s,o=[],p=this.joinOpts({level:n.level,minlevel:n.minlevel,numbered:n.numbered,omit:n.omit}),u=new m,l=this.options.breaks?" <br>":"",a=n.level||t.level,h=n.minlevel||t.minlevel;o=e.filter(function(e){if(e.depth<=a&&e.depth>=h){return true}return false}).map(function(e){if(!r.options.numberedHeadings&&n.numbered){e.number=u.count(e.depth-h+1)}return e}).filter(function(e){if(n.omit){if(s){if(e.depth>s){return false}else{s=undefined}}return!n.omit.some(function(t){if(t===e.raw){s=e.depth;return true}return false})}return true}).map(function(e){if(n.numbered){if(r.options.numberedHeadings){return(e.number?e.number+" ":"")+"["+r.sanitizeHeadings(e.raw)+"]("+e.autoid+")"+l}else{return e.number+" ["+r.sanitizeHeadings(e.text)+"]("+e.autoid+")"+l}}else{var t="";for(var i=1;i<(e.depth-h+1||1);i++){t+=" "}return t+"* ["+r.sanitizeHeadings(e.text)+"]("+e.autoid+")"}});if(this.options.tags){return"<!-- !toc "+p+"-->\n\n"+o.join("\n")+"\n\n<!-- toc! -->\n\n"}else{return o.join("\n")+"\n\n"}};_.prototype.numberedHeadings=function(e,t,n,r,i){var s=this.joinOpts({level:e,minlevel:t,skip:n,start:r,omit:i});if(this.options.tags){return"<!-- !numberedheadings "+s+"-->\n\n"}return""};_.prototype.joinOpts=function(e){var t,n,r=[];for(t in e){n=e[t];if(n===true){r.push(t)}else if(n!==undefined){if(Array.isArray(n)){n='"'+n.join(";")+'"'}r.push(t+"="+n)}}if(r.length>0){return"("+r.join(" ")+") "}else{return""}};_.prototype.sanitizeHeadings=function(e){return e.replace(/\[([^\]]*)\]\s*(?:\[[^\]]*\]|\([^\)]*\))/g,"$1")};function k(e){this.tokens=[];this.token=null;this.count=-1;this.indent=[];this.options=e||t;this.options.renderer=this.options.renderer||new _;this.renderer=this.options.renderer;this.renderer.options=this.options}k.prototype.parse=function(e){this.tokens=e;this.updateAutoIdentifier();var t="";while(this.next()){t+=this.tok()}return t};k.prototype.next=function(){this.token=this.tokens[this.count+=1];return this.token};k.prototype.peek=function(){return this.tokens[this.count+1]||0};k.prototype.references=function(){var e,t=[],n={title:{},ref:{}};this.tokens.forEach(function(e){if(e.type==="def"&&!/^#/.test(e.href)){if(e.title){n.title[e.ref]=e.title}else{n.ref[e.ref]=e.ref}}});for(e in n.title){t.push({ref:e,title:n.title[e]})}for(e in n.ref){if(!n.title[e]){t.push({ref:e,title:e})}}return t};k.prototype.tableOfContents=function(){return this.tokens.filter(function(e){if(e.type==="heading"){return true}return false})};k.prototype.headingAutoId=function(e,t){t=t||{raw:false};var n=(!t.raw?e.text:e.raw||"").replace(/^#/,"");if(false){n=e.text.replace(/ /g,"-").replace(/%([abcdef]|\d){2,2}/gi,"").replace(/[\/?:\[\]`.,()*"';{}+<>]/g,"").toLowerCase()}else{n=n.replace(/[^\w]+/g,"-").toLowerCase()}return"#"+n};k.prototype.updateAutoIdentifier=function(){var e=this,t={};function n(t){t=t.replace(/(?:%20|\+)/g," ");t=e.headingAutoId({text:t});return t}this.tokens=this.tokens.map(function(n){var r,i,s;if(n.type==="heading"){i=e.headingAutoId(n);s=e.headingAutoId(n,{raw:true});t[s]=i;t[i]=i;n.autoid=i}return n});this.tokens=this.tokens.map(function(e){var r;if(e.inline){e.inline=e.inline.map(function(e){switch(e.type){case"link":case"image":{r=n(e.href);if(t[r]){e.href=t[r]}break}}return e})}else{switch(e.type){case"def":{r=n(e.href);if(t[r]){e.href=t[r]}break}}}return e})};k.prototype.numberedHeadings=function(e,n,r,i,s){var o=/^([0-9]+\\?\.)+ +/,p={},u=false,l=new m(i);r=r||0;(s||[]).forEach(function(e){p[e]=true});e=e||t.level;n=n||t.minlevel;this.tokens=this.tokens.map(function(t){if(t.type==="heading"){t.text=t.text.replace(o,"");t.raw=t.raw.replace(o,"");if(t.depth===n){if(r>0){r-=1;u=true}else if(r===0){u=false}}if(!u&&!p[t.raw]&&t.depth<=e&&t.depth>=n){t.number=l.count(t.depth-n+1);t.text=t.number+" "+t.text}}return t})};k.prototype.tok=function(e){var t,n,r,i,s,o=this;e=e||{};switch(this.token.type){case"space":{return this.renderer.newline(this.token.text)}case"code":{return this.renderer.codeblock(this.token.text)}case"hr":{return this.renderer.hr(this.token.text)}case"html":{return this.renderer.html(this.token.text)}case"paragraph":{n="";(this.token.inline||[]).forEach(function(e){n+=o.inlinetok(e)});return this.renderer.paragraph(n)}case"text":{n="";(this.token.inline||[]).forEach(function(e){n+=o.inlinetok(e)});return this.renderer.text(n)}case"heading":{return this.renderer.heading(this.token.text,this.token.depth,this.token.raw,this.token.number,this.token.autoid)}case"fences":{return this.renderer.fences(this.token.text,this.token.lang,this.token.indent,this.token.fences)}case"def":{return this.renderer.reference(this.token.ref,this.token.href,this.token.title)}case"blockquote_start":{n="";while(this.next().type!=="blockquote_end"){n+=this.tok()}return this.renderer.blockquote(n)}case"list_start":{n="";s=this.token.ordered;i=this.token.start;while(this.next().type!=="list_end"){if(this.options.autonumber&&s){t={start:i++}}n+=this.tok(t)}return this.renderer.list(n,s)}case"list_item_start":{n="";r=this.token.text;if(e.start){r=e.start+"."}while(this.next().type!=="list_item_end"){n+=this.tok()}return this.renderer.listitem(r,n)}case"loose_item_start":{n="";r=this.token.text;if(e.start){r=e.start+"."}while(this.next().type!=="list_item_end"){n+=this.tok()}return this.renderer.listitem(r,n)}case"ppnumberedheadings":{this.options.numberedHeadings=true;this.numberedHeadings(this.token.level,this.token.minlevel,this.token.skip,this.token.start,this.token.omit);this.updateAutoIdentifier();return this.renderer.numberedHeadings(this.token.level,this.token.minlevel,this.token.skip,this.token.start,this.token.omit)}case"ppref":{return this.renderer.references(this.references())}case"ppinclude_start":{n="";if(typeof this.token.lang==="string"){n=this.renderer.fence(this.token.lang)}return n}case"ppinclude_end":{n="";if(typeof this.token.lang==="string"){n=this.renderer.fence()}return n}case"ppinclude":{return this.renderer.include(this.token.text,this.token.indent,this.token.lang)}case"pptoc":{return this.renderer.tableOfContents(this.tableOfContents(),this.token)}default:{return"<!-- "+JSON.stringify(this.token)+" -->\n"}}};k.prototype.inlinetok=function(e){switch(e.type){case"escape":{return this.renderer.escape(e.text)}case"url":{return this.renderer.url(e.text)}case"tag":{return this.renderer.tag(e.text)}case"link":{return this.renderer.link(e.raw,e.text,e.href,e.title)}case"reflink":{return this.renderer.reflink(e.raw,e.text,e.ref)}case"nolink":{return this.renderer.nolink(e.raw,e.text)}case"image":{return this.renderer.image(e.raw,e.text,e.href,e.title)}case"refimage":{return this.renderer.refimage(e.raw,e.text,e.ref)}case"noimage":{return this.renderer.noimage(e.raw,e.text)}case"strong":{return this.renderer.strong(e.text,e.char)}case"em":{return this.renderer.em(e.text,e.char)}case"text":{return this.renderer.text(e.text)}case"code":{return this.renderer.code(e.text)}case"br":{return this.renderer.br(e.text)}case"del":{return this.renderer.del(e.text)}default:{return"<!-- "+JSON.stringify(this.token)+" -->\n"}}};k.parse=function(e,t){var n=new k(t);return n.parse(e)};function x(e,n,r){if(typeof n==="function"){r=n;n=null}n=s({},t,n||{});c.lex(e,n,function(e,t){var i=k.parse(t,n);r(null,i)})}x.defaults=t;x.Lexer=c;x.merge=s;x.setOptions=function(e){s(t,e);return x};if(n()){module.exports=x}else if(typeof define!=="undefined"&&define.amd){define([],function(){return x})}else if(typeof e.Window!=="undefined"&&!e[x]){e.markedpp=x}})(this); \ No newline at end of file +(function(e){"use strict";var t={gfm:true,include:true,toc:true,numberedheadings:true,ref:true,breaks:true,tags:true,level:3,minlevel:1,autonumber:true,autoid:true,githubid:false};function n(){return typeof process!=="undefined"&&typeof module!=="undefined"&&module.exports}function i(e,t){e=e.source;t=t||"";return function n(i,r){if(!i)return new RegExp(e,t);r=r.source||r;r=r.replace(/(^|[^\[])\^/g,"$1");e=e.replace(i,r);return n}}function r(){}r.exec=r;function s(e){var t=1,n,i;for(;t<arguments.length;t++){n=arguments[t];for(i in n){if(Object.prototype.hasOwnProperty.call(n,i)){e[i]=n[i]}}}return e}function o(e,t){var n=parseInt(e,10);if(isNaN(n)){if(t===true)return;else return e}return n}var p={normalizeArray:function(e,t){var n=0;for(var i=e.length-1;i>=0;i--){var r=e[i];if(r==="."){e.splice(i,1)}else if(r===".."){e.splice(i,1);n++}else if(n){e.splice(i,1);n--}}if(t){for(;n--;n){e.unshift("..")}}return e},resolve:function(){var e="",t=false;for(var n=arguments.length-1;n>=-1&&!t;n--){var i=n>=0?arguments[n]:"/";if(!i){continue}e=i+"/"+e;t=i.charAt(0)==="/"}e=this.normalizeArray(e.split("/").filter(function(e){return!!e}),!t).join("/");return(t?"/":"")+e||"."},splitPathRe:/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,splitPath:function(e){return this.splitPathRe.exec(e).slice(1)},dirname:function(e){var t=this.splitPath(e),n=t[0],i=t[1];if(!n&&!i){return"."}if(i){i=i.substr(0,i.length-1)}return n+i},join:function(){return Array.prototype.slice.call(arguments).join("/")}};var u={_eachLimit:function(e){return function(t,n,i){i=i||function(){};if(!t.length||e<=0){return i()}var r=0;var s=0;var o=0;(function p(){if(r>=t.length){return i()}while(o<e&&s<t.length){s+=1;o+=1;n(t[s-1],function(e){if(e){i(e);i=function(){}}else{r+=1;o-=1;if(r>=t.length){i()}else{p()}}})}})()}},eachLimit:function(e,t,n,i){var r=this._eachLimit(t);r.apply(null,[e,n,i])}};function l(e,t,n){if(typeof t==="function"){n=t;t=null}var i=t?t:{};var r=new XMLHttpRequest,s=i.method||"get",o=i.data||null,p;r.queryString=o;r.open(s,e,true);r.setRequestHeader("X-Requested-With","XMLHttpRequest");if(s.toLowerCase()=="post"){r.setRequestHeader("Content-Type","application/x-www-form-urlencoded")}for(p in i.headers){if(i.headers.hasOwnProperty(p)){r.setRequestHeader(p,i.headers[p])}}function u(){if(r.readyState===4){if(/^[20]/.test(r.status)){n(null,r.responseText)}else if(/^[45]/.test(r.status)){n(new Error(r.status))}}}r.onreadystatechange=u;try{r.send(o)}catch(l){console.log("Error: Resolving URL "+e);n(l)}}var a;if(n()){a=require("./ppinclude")(f,s)}else{a=function(e,t,n){var i=t.dirname||p.dirname(location.pathname),r={},o=s({},t);if(!o.ppInclude){o.ppInclude={}}u.eachLimit(e,5,function(e,t){if(e.type==="ppinclude"&&typeof e.text==="string"&&!o.ppInclude[e.text]){var n=p.resolve(p.join(i,e.text));var s=location.protocol+"//"+location.host+n;l(s,function(i,s){o.ppInclude[e.text]=1;o.dirname=p.dirname(n);if(i){console.log("Error: "+i.message);return t()}var u=new f(o);s=e.indent+s.split("\n").join("\n"+e.indent);a(u.lex(s),o,function(n,i){if(n){}r[e.text]=i;t()})})}else{t()}},function(){var t=[];e.forEach(function(e){if(e.type==="ppinclude"&&typeof e.text==="string"&&r[e.text]!==undefined){t.push({type:"ppinclude_start",text:e.text,indent:e.indent,lang:e.lang});r[e.text].forEach(function(e){t.push(s({},e))});t.push({type:"ppinclude_end",lang:e.lang})}else{t.push(e)}});n(null,t)})}}var h={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:r,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^headingid *(#{1,6}) *([^\n]+?) *#* *(?:\n|$)/,lheading:/^headingid([^\n]+)\n *(=|-){2,} *(?:\n|$)/,headingid:/(?: *<a name="([^\"]+)" *(?:\/>|> *<\/a>|>) *\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:r,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/,ppinclude:r,ppnumberedheadings:r,pptoc:r,ppref:r};h.bullet=/(?:[*+-]|\d+\.)/;h.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;h.item=i(h.item,"gm")(/bull/g,h.bullet)();h.list=i(h.list)(/bull/g,h.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+h.def.source+")")();h.blockquote=i(h.blockquote)("def",h.def)();h.heading=i(h.heading)("headingid",h.headingid)();h.lheading=i(h.lheading)("headingid",h.headingid)();h._tag="(?!(?:[A-Za-z][A-Za-z-]*)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";h.html=i(h.html)("comment",/<!--[\s\S]*?-->/)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,h._tag)();h.paragraph=i(h.paragraph)("hr",h.hr)("heading",h.heading)("lheading",h.lheading)("blockquote",h.blockquote)("tag","<"+h._tag)("def",h.def)();h.opts={};h.opts.gfm={fences:/^( *)(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\2 *(?:\n|$)/};var c={_ppopts_:/ ?(?:\(([^\)]+)\))?/,ppinclude:/^( *)(?:\!(?:include)_ppopts_|_ppinclude_|_ppincludeCompat_) *(?:\n|$)/,_ppinclude_:/<!-- *include_ppopts_ *-->(?:(?!<!-- *\/include * -->)[^])*<!-- *\/include * -->/,_ppincludeCompat_:/\!INCLUDE "([^"]+)"/,ppnumberedheadings:/^ *(?:\!(?:numberedheadings)_ppopts_|_ppnumberedheadings_) *(?:\n+|$)/,_ppnumberedheadings_:/<!-- \!*numberedheadings_ppopts_ *-->/,pptoc:/^(?:\!(?:toc)_ppopts_|_pptoc_|_pptocCompat1_|_pptocCompat2_|_pptocCompat3_) *(?:\n+|$)/,_pptoc_:/<!-- *\!toc_ppopts_ *-->(?:(?!<!-- *toc\! * -->)[^])*<!-- *toc\! * -->/,_pptocCompat1_:/\!TOC/,_pptocCompat2_:/<!-- *toc *-->(?:(?!<!-- *(?:\/toc|toc stop) * -->)[^])*<!-- *(?:\/toc|toc stop) * -->/,_pptocCompat3_:/<!-- *toc *-->/,ppref:/^(?:\!(?:ref)|_ppref_|_pprefCompat1_|_pprefCompat2_) *(?:\n|$)/,_ppref_:/<!-- *\!ref *-->(?:(?!<!-- *ref\! * -->)[^])*<!-- *ref\! * -->/,_pprefCompat1_:/\!REF/,_pprefCompat2_:/<!-- *ref *-->(?:(?!<!-- *\/ref * -->)[^])*<!-- \/ref * -->/};c.ppinclude=i(c.ppinclude)("_ppinclude_",c._ppinclude_)("_ppincludeCompat_",c._ppincludeCompat_)("_ppopts_",c._ppopts_)("_ppopts_",c._ppopts_)();c.ppnumberedheadings=i(c.ppnumberedheadings)("_ppnumberedheadings_",c._ppnumberedheadings_)("_ppopts_",c._ppopts_)("_ppopts_",c._ppopts_)();c.pptoc=i(c.pptoc)("_pptoc_",c._pptoc_)("_ppopts_",c._ppopts_)("_ppopts_",c._ppopts_)("_pptocCompat1_",c._pptocCompat1_)("_pptocCompat2_",c._pptocCompat2_)("_pptocCompat3_",c._pptocCompat3_)();c.ppref=i(c.ppref)("_ppref_",c._ppref_)("_pprefCompat1_",c._pprefCompat1_)("_pprefCompat2_",c._pprefCompat2_)();h.opts.include={ppinclude:c.ppinclude};h.opts.numberedheadings={ppnumberedheadings:c.ppnumberedheadings};h.opts.toc={pptoc:c.pptoc};h.opts.ref={ppref:c.ppref};function f(e){this.tokens=[];this.options=e||t;this.rules=h;if(this.options.gfm){s(this.rules,h.opts.gfm)}if(this.options.include){s(this.rules,h.opts.include)}if(this.options.numberedheadings){s(this.rules,h.opts.numberedheadings)}if(this.options.toc){s(this.rules,h.opts.toc)}if(this.options.ref){s(this.rules,h.opts.ref)}}f.prototype.lex=function(e){e=e.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(e,true)};f.prototype.token=function(e,n){var i,r,s,p,u,l,a,h,c,d,m,_;while(e){if(i=this.rules.newline.exec(e)){e=e.substring(i[0].length);this.tokens.push({type:"space",text:i[0]})}if(i=this.rules.ppinclude.exec(e)){e=e.substring(i[0].length);m=i[2]||i[3]||i[4];_=f.splitOpts(m);m=m.replace(/ *(?:[a-z]+=[a-z0-9\-]+)/,"").replace(/\\ /g," ");this.tokens.push({type:"ppinclude",text:m,indent:i[1],lang:_.lang});continue}if(i=this.rules.code.exec(e)){e=e.substring(i[0].length);this.tokens.push({type:"code",text:i[0]});continue}if(i=this.rules.fences.exec(e)){e=e.substring(i[0].length);this.tokens.push({type:"fences",indent:i[1],fences:i[2],lang:i[3],text:i[4]});continue}if(i=this.rules.heading.exec(e)){e=e.substring(i[0].length);m=new g(this.options);this.tokens.push({type:"heading",depth:i[2].length,text:i[3],raw:i[3],autoid:null,anchor:i[1],inline:m.lex(i[3])});continue}if(i=this.rules.lheading.exec(e)){e=e.substring(i[0].length);m=new g(this.options);this.tokens.push({type:"heading",depth:i[3]==="="?1:2,text:i[2],raw:i[2],autoid:null,anchor:i[1],inline:m.lex(i[2])});continue}if(i=this.rules.hr.exec(e)){e=e.substring(i[0].length);this.tokens.push({type:"hr",text:i[0]});continue}if(i=this.rules.blockquote.exec(e)){e=e.substring(i[0].length);this.tokens.push({type:"blockquote_start"});i=i[0].replace(/^ *> ?/gm,"");this.token(i,n);this.tokens.push({type:"blockquote_end"});continue}if(i=this.rules.list.exec(e)){e=e.substring(i[0].length);r=i[2];this.tokens.push({type:"list_start",ordered:r.length>1,start:o(r,true)});i=i[0].match(this.rules.item);s=false;p=i.length;l=0;for(;l<p;l++){a=i[l];r=this.rules.bullet.exec(a)[0];h=a.length;a=a.replace(/^ *([*+-]|\d+\.) +/,"");if(~a.indexOf("\n ")){h-=a.length;a=!this.options.pedantic?a.replace(new RegExp("^ {1,"+h+"}","gm"),""):a.replace(/^ {1,4}/gm,"")}if(this.options.smartLists&&l!==p-1){u=this.rules.bullet.exec(i[l+1])[0];if(r!==u&&!(r.length>1&&u.length>1)){e=i.slice(l+1).join("\n")+e;l=p-1}}c=s||/\n\n(?!\s*$)/.test(a);if(l!==p-1){s=a.charAt(a.length-1)==="\n";if(!c)c=s}this.tokens.push({type:c?"loose_item_start":"list_item_start",text:r});this.token(a,false,d);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(i=this.rules.ppnumberedheadings.exec(e)){e=e.substring(i[0].length);_=f.splitOpts(i[1]||i[2]);if(typeof _.omit==="string"){_.omit=[_.omit]}this.options.numberedHeadings=true;this.tokens.push({type:"ppnumberedheadings",level:f.range(_.level,t.minlevel,6,t.level),minlevel:f.range(_.minlevel,t.minlevel,6),skip:_.skip,start:_.start,omit:_.omit});continue}if(i=this.rules.pptoc.exec(e)){e=e.substring(i[0].length);_=f.splitOpts(i[1]||i[2]);if(typeof _.omit==="string"){_.omit=[_.omit]}this.tokens.push({type:"pptoc",level:f.range(_.level,t.minlevel,6,t.level),minlevel:f.range(_.minlevel,t.minlevel,6),numbered:_.numbered,omit:_.omit});continue}if(i=this.rules.ppref.exec(e)){e=e.substring(i[0].length);this.tokens.push({type:"ppref"});continue}if(i=this.rules.html.exec(e)){e=e.substring(i[0].length);this.tokens.push({type:"html",pre:i[1]==="pre"||i[1]==="script"||i[1]==="style",text:i[0]});continue}if(n&&(i=this.rules.def.exec(e))){e=e.substring(i[0].length);this.tokens.push({type:"def",ref:i[1],href:i[2],title:i[3]});continue}if(n&&(i=this.rules.paragraph.exec(e))){e=e.substring(i[1].length);m=new g(this.options);this.tokens.push({type:"paragraph",text:i[1],inline:m.lex(i[1])});continue}if(i=this.rules.text.exec(e)){e=e.substring(i[0].length);m=new g(this.options);this.tokens.push({type:"text",text:i[0],inline:m.lex(i[0])});continue}if(e){throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}}return this.tokens};f.rules=h;f.lex=function(e,t,n){var i=new f(t);var r=i.lex(e);a(r,t,function(e,i){n(e,i,t)})};f.splitOpts=function(e){var t={},n,i="",r=/^(.+)$/,s=/^([a-z0-9]+)=(.*)$/,o=/^([a-z0-9]+)=(["'])(.*?)\2$/;(e||"").split(" ").forEach(function(e){if(/\\$|^["'].*[^"']$/.test(e)||n&&!n.test(e)){i+=e+" ";return}if(/\=(["']).*[^"']$/.test(e)){n=e.replace(/^.*\=(["']).*[^"']$/,"$1");n=new RegExp(n+"$");i+=e+" ";return}if(i){e=i+e;i="";n=undefined}if(o.test(e)){e.replace(o,function(e,n,i,r){t[n]=r.split(";");t[n]=t[n].map(function(e){if(/^\d+$/.test(e)){var t=parseInt(e,10);if(!isNaN(t)){e=t}}return e});if(t[n].length===1){t[n]=t[n][0]}})}else if(s.test(e)){e.replace(s,function(e,n,i){var r=parseInt(i,10);if(!isNaN(r)){i=r}t[n]=i})}else if(r.test(e)){e=e.replace(/\\ /g," ").replace(/^(["'])([^\1]+)\1$/,"$2");if(/^\!(.*)$/.test(e)){e=e.replace(/^\!(.*)$/,"$1");t[e]=false}else{t[e]=true}}});return t};f.range=function(e,t,n,i){if(e<t){return t}else if(e>n){return n}else{if(i&&e===i){return undefined}return e}};var d={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:r,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^(!)?\[(inside)\]\(href\)/,reflink:/^(!)?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^(!)?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:r,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/,_inside:/(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/,_href:/\s*<?([\s\S]*?)>?(?:\s+(['"][\s\S]*?['"]))?\s*/};d.link=i(d.link)("inside",d._inside)("href",d._href)();d.reflink=i(d.reflink)("inside",d._inside)();d.opts={};d.opts.gfm={escape:i(d.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:i(d.text)("]|","~]|")("|","|https?://|")()};d.opts.breaks={br:i(d.br)("{2,}","*")(),text:i(d.opts.gfm.text)("{2,}","*")()};function g(e){this.tokens=[];this.options=e||t;this.rules=d;if(this.options.gfm){s(this.rules,d.opts.gfm)}if(this.options.breaks){s(this.rules,d.opts.gfm,d.opts.breaks)}}g.rules=d;g.lex=function(e,t){var n=new g(t);return n.lex(e)};g.prototype.lex=function(e){var t;while(e){if(t=this.rules.escape.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"escape",text:t[1]});continue}if(!this.inLink&&(t=this.rules.url.exec(e))){e=e.substring(t[0].length);this.tokens.push({type:"url",text:t[1]});continue}if(t=this.rules.tag.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"tag",text:t[0]});continue}if(t=this.rules.link.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:t[1]?"image":"link",raw:t[0],text:t[2],href:t[3],title:t[4]});continue}if(t=this.rules.reflink.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:t[1]?"refimage":"reflink",raw:t[0],text:t[2],ref:t[3]});continue}if(t=this.rules.nolink.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:t[1]?"noimage":"nolink",raw:t[0],text:t[2]});continue}if(t=this.rules.strong.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"strong",text:t[2]||t[1],"char":/^(..)/.exec(t[0])[0]});continue}if(t=this.rules.em.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"em",text:t[2]||t[1],"char":/^(.)/.exec(t[0])[0]});continue}if(t=this.rules.code.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"code",text:t[0]});continue}if(t=this.rules.br.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"br",text:t[0]});continue}if(t=this.rules.del.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"del",text:t[1]});continue}if(t=this.rules.text.exec(e)){e=e.substring(t[0].length);this.tokens.push({type:"text",text:t[0]});continue}if(e){throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}}return this.tokens};function m(e){this._=[0,0,0,0,0,0,0];this.last=1;this._[1]=e?e-1:0}m.prototype.reset=function(e){for(var t=e+1;t<this._.length;t++){this._[t]=0}};m.prototype.val=function(e){var t,n=this._[1];for(t=2;t<=e;t++){n+="."+this._[t]}return n+"\\."};m.prototype.count=function(e){if(e<=6){if(this.last>e){this.reset(e)}this._[e]+=1;this.last=e;return this.val(e)}return};function _(e){this.options=e||{}}_.prototype.heading=function(e,t,n,i,r,s){var o="";if(s){o+='<a name="'+s+'"/>\n'}o+="########".substring(0,t);return o+" "+e+"\n"};_.prototype.paragraph=function(e){return e};_.prototype.newline=function(e){return e};_.prototype.blockquote=function(e){return e.replace(/\n$/,"").replace(/^/gm,"> ")+"\n"};_.prototype.list=function(e){return e.replace(/\n$/,"")};_.prototype.listitem=function(e,t){var n,i="";e+=" ";for(n=0;n<e.length;n++){i+=" "}return e+t.replace(/\n(?!\n|$)/gm,"\n"+i)+"\n"};_.prototype.fences=function(e,t,n,i){return this.fence(t,n,i)+e+"\n"+this.fence("",n,i)};_.prototype.reference=function(e,t,n){return"["+e+"]: "+t+(n?' "'+n+'"':"")+"\n"};_.prototype.include=function(e,t,n){return t+"!include ("+e+(n?" lang="+n:"")+")\n"};_.prototype.fence=function(e,t,n){n=n||"```";t=t||"";return t+n+(e?e:"")+"\n"};_.prototype.codeblock=function(e){return e};_.prototype.html=function(e){return e};_.prototype.hr=function(e){return e};_.prototype.escape=function(e){return"\\"+e};_.prototype.url=function(e){return e};_.prototype.tag=function(e){return e};_.prototype.link=function(e,t,n,i){return"["+t+"]("+n+(i?" "+i:"")+")"};_.prototype.reflink=function(e,t,n){return"["+t+"]["+n+"]"};_.prototype.nolink=function(e,t){return"["+t+"]"};_.prototype.image=function(e,t,n,i){return"!"+this.link(e,t,n,i)};_.prototype.refimage=function(e,t,n){return"!"+this.reflink(e,t,n)};_.prototype.noimage=function(e,t){return"!"+this.nolink(e,t)};_.prototype.strong=function(e,t){return t+e+t};_.prototype.em=function(e,t){return t+e+t};_.prototype.del=function(e){return"~~"+e+"~~"};_.prototype.text=function(e){return e};_.prototype.br=function(e){return e};_.prototype.code=function(e){return e};_.sortByTitle=function(e,t){var n=e.title.toLowerCase(),i=t.title.toLowerCase();if(n>i){return 1}else if(n<i){return-1}else{return 0}};_.prototype.references=function(e){var t=[];e.map(function(e){if(!e.title){e.title=e.ref}return e}).sort(_.sortByTitle).forEach(function(e){t.push("* ["+e.title+"]["+e.ref+"]")});if(this.options.tags){return"<!-- !ref -->\n\n"+t.join("\n")+"\n\n<!-- ref! -->\n"}else{return t.join("\n")+"\n"}};_.prototype.tableOfContents=function(e,n){var i=this,r,s=[],o=this.joinOpts({level:n.level,minlevel:n.minlevel,numbered:n.numbered,omit:n.omit}),p=new m,u=this.options.breaks?" <br>":"",l=n.level||t.level,a=n.minlevel||t.minlevel;s=e.filter(function(e){if(e.depth<=l&&e.depth>=a){return true}return false}).map(function(e){if(!i.options.numberedHeadings&&n.numbered){e.number=p.count(e.depth-a+1)}return e}).filter(function(e){if(n.omit){if(r){if(e.depth>r){return false}else{r=undefined}}return!n.omit.some(function(t){if(t===e.raw){r=e.depth;return true}return false})}return true}).map(function(e){if(n.numbered){if(i.options.numberedHeadings){return(e.number?e.number+" ":"")+"["+i.sanitizeHeadings(e.raw)+"]("+e.autoid+")"+u}else{return e.number+" ["+i.sanitizeHeadings(e.text)+"]("+e.autoid+")"+u}}else{var t="";for(var r=1;r<(e.depth-a+1||1);r++){t+=" "}return t+"* ["+i.sanitizeHeadings(e.text)+"]("+e.autoid+")"}});if(this.options.tags){return"<!-- !toc "+o+"-->\n\n"+s.join("\n")+"\n\n<!-- toc! -->\n\n"}else{return s.join("\n")+"\n\n"}};_.prototype.numberedHeadings=function(e,t,n,i,r){var s=this.joinOpts({level:e,minlevel:t,skip:n,start:i,omit:r});if(this.options.tags){return"<!-- !numberedheadings "+s+"-->\n\n"}return""};_.prototype.joinOpts=function(e){var t,n,i=[];for(t in e){n=e[t];if(n===true){i.push(t)}else if(n!==undefined){if(Array.isArray(n)){n='"'+n.join(";")+'"'}i.push(t+"="+n)}}if(i.length>0){return"("+i.join(" ")+") "}else{return""}};_.prototype.sanitizeHeadings=function(e){return e.replace(/\[([^\]]*)\]\s*(?:\[[^\]]*\]|\([^\)]*\))/g,"$1")};function k(e){this.tokens=[];this.token=null;this.count=-1;this.indent=[];this.options=e||t;this.options.renderer=this.options.renderer||new _;this.renderer=this.options.renderer;this.renderer.options=this.options}k.prototype.parse=function(e){this.tokens=e;this.updateAutoIdentifier();var t="";while(this.next()){t+=this.tok()}return t};k.prototype.next=function(){this.token=this.tokens[this.count+=1];return this.token};k.prototype.peek=function(){return this.tokens[this.count+1]||0};k.prototype.references=function(){var e,t=[],n={title:{},ref:{}};this.tokens.forEach(function(e){if(e.type==="def"&&!/^#/.test(e.href)){if(e.title){n.title[e.ref]=e.title}else{n.ref[e.ref]=e.ref}}});for(e in n.title){t.push({ref:e,title:n.title[e]})}for(e in n.ref){if(!n.title[e]){t.push({ref:e,title:e})}}return t};k.prototype.tableOfContents=function(){return this.tokens.filter(function(e){if(e.type==="heading"){return true}return false})};k.prototype.headingAutoId=function(e,t){t=t||{raw:false};var n=(!t.raw?e.text:e.raw||"").replace(/^#/,"");if(e.anchor){return"#"+e.anchor}if(this.options.githubid){n=n.replace(/ /g,"-").replace(/%([abcdef]|\d){2,2}/gi,"").replace(/[\/?:\[\]`.,()*"';{}+<>&]/g,"").toLowerCase()}else{n=n.replace(/[^\w]+/g,"-").toLowerCase()}return"#"+n};k.prototype.updateAutoIdentifier=function(){var e=this,t={};function n(t){t=t.replace(/(?:%20|\+)/g," ");t=e.headingAutoId({text:t});return t}this.tokens=this.tokens.map(function(n){var i,r;if(n.type==="heading"){i=e.headingAutoId(n);r=e.headingAutoId(n,{raw:true});t[r]=i;t[i]=i;n.autoid=i}return n});this.tokens=this.tokens.map(function(e){var i;if(e.inline){e.inline=e.inline.map(function(e){switch(e.type){case"link":case"image":{i=n(e.href);if(t[i]){e.href=t[i]}break}}return e})}else{switch(e.type){case"def":{if(e.href&&e.href.indexOf("#")===0){i=n(e.href);if(t[i]){e.href=t[i]}break}}}}return e})};k.prototype.numberedHeadings=function(e,n,i,r,s){var o=/^([0-9]+\\?\.)+ +/,p={},u=false,l=new m(r);i=i||0;(s||[]).forEach(function(e){p[e]=true});e=e||t.level;n=n||t.minlevel;this.tokens=this.tokens.map(function(t){if(t.type==="heading"){t.text=t.text.replace(o,"");t.raw=t.raw.replace(o,"");if(t.depth===n){if(i>0){i-=1;u=true}else if(i===0){u=false}}if(!u&&!p[t.raw]&&t.depth<=e&&t.depth>=n){t.number=l.count(t.depth-n+1);t.text=t.number+" "+t.text}}return t})};k.prototype.tok=function(e){var t,n,i,r,s,o=this;e=e||{};switch(this.token.type){case"space":{return this.renderer.newline(this.token.text)}case"code":{return this.renderer.codeblock(this.token.text)}case"hr":{return this.renderer.hr(this.token.text)}case"html":{return this.renderer.html(this.token.text)}case"paragraph":{n="";(this.token.inline||[]).forEach(function(e){n+=o.inlinetok(e)});return this.renderer.paragraph(n)}case"text":{n="";(this.token.inline||[]).forEach(function(e){n+=o.inlinetok(e)});return this.renderer.text(n)}case"heading":{return this.renderer.heading(this.token.text,this.token.depth,this.token.raw,this.token.number,this.token.autoid,this.token.anchor)}case"fences":{return this.renderer.fences(this.token.text,this.token.lang,this.token.indent,this.token.fences)}case"def":{return this.renderer.reference(this.token.ref,this.token.href,this.token.title)}case"blockquote_start":{n="";while(this.next().type!=="blockquote_end"){n+=this.tok()}return this.renderer.blockquote(n)}case"list_start":{n="";s=this.token.ordered;r=this.token.start;while(this.next().type!=="list_end"){if(this.options.autonumber&&s){t={start:r++}}n+=this.tok(t)}return this.renderer.list(n,s)}case"list_item_start":{n="";i=this.token.text;if(e.start){i=e.start+"."}while(this.next().type!=="list_item_end"){n+=this.tok()}return this.renderer.listitem(i,n)}case"loose_item_start":{n="";i=this.token.text;if(e.start){i=e.start+"."}while(this.next().type!=="list_item_end"){n+=this.tok()}return this.renderer.listitem(i,n)}case"ppnumberedheadings":{this.options.numberedHeadings=true;this.numberedHeadings(this.token.level,this.token.minlevel,this.token.skip,this.token.start,this.token.omit);this.updateAutoIdentifier();return this.renderer.numberedHeadings(this.token.level,this.token.minlevel,this.token.skip,this.token.start,this.token.omit)}case"ppref":{return this.renderer.references(this.references())}case"ppinclude_start":{n="";if(typeof this.token.lang==="string"){n=this.renderer.fence(this.token.lang)}return n}case"ppinclude_end":{n="";if(typeof this.token.lang==="string"){n=this.renderer.fence()}return n}case"ppinclude":{return this.renderer.include(this.token.text,this.token.indent,this.token.lang)}case"pptoc":{return this.renderer.tableOfContents(this.tableOfContents(),this.token)}default:{return"<!-- "+JSON.stringify(this.token)+" -->\n"}}};k.prototype.inlinetok=function(e){switch(e.type){case"escape":{return this.renderer.escape(e.text)}case"url":{return this.renderer.url(e.text)}case"tag":{return this.renderer.tag(e.text)}case"link":{return this.renderer.link(e.raw,e.text,e.href,e.title)}case"reflink":{return this.renderer.reflink(e.raw,e.text,e.ref)}case"nolink":{return this.renderer.nolink(e.raw,e.text)}case"image":{return this.renderer.image(e.raw,e.text,e.href,e.title)}case"refimage":{return this.renderer.refimage(e.raw,e.text,e.ref)}case"noimage":{return this.renderer.noimage(e.raw,e.text)}case"strong":{return this.renderer.strong(e.text,e.char)}case"em":{return this.renderer.em(e.text,e.char)}case"text":{return this.renderer.text(e.text)}case"code":{return this.renderer.code(e.text)}case"br":{return this.renderer.br(e.text)}case"del":{return this.renderer.del(e.text)}default:{return"<!-- "+JSON.stringify(this.token)+" -->\n"}}};k.parse=function(e,t){var n=new k(t);return n.parse(e)};function x(e,n,i){if(typeof n==="function"){i=n;n=null}n=s({},t,n||{});f.lex(e,n,function(e,t){if(e){}var r=k.parse(t,n);i(null,r)})}x.defaults=t;x.Lexer=f;x.InlineLexer=g;x.Renderer=_;x.Parser=k;x.merge=s;x.setOptions=function(e){s(t,e);return x};if(n()){module.exports=x}else if(typeof define!=="undefined"&&define.amd){define([],function(){return x})}else if(typeof e.Window!=="undefined"&&!e[x]){e.markedpp=x}})(this); \ No newline at end of file diff --git a/package.json b/package.json index fc82777..0d166e4 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,31 @@ { "name": "markedpp", - "version": "0.3.6", + "version": "0.3.7", "description": "Preprocessor for markdown files", "main": "lib/markedpp.js", "bin": { "markedpp": "./bin/markedpp.js" }, - "author": "commenthol", - "license": "MIT", + "directories": { + "test": "test" + }, + "dependencies": { + "async": "^0.9.0" + }, + "devDependencies": { + "express": "^4.8.7", + "mocha": "^1.21.4" + }, + "scripts": { + "test": "mocha test/*.mocha.js", + "cover": "istanbul cover _mocha --report lcov --report text -- -R dot --check-leaks test/*.mocha.js", + "lint": "jshint --show-non-errors lib/*.js", + "doc": "mkdir -p doc && jsdox -o doc lib/*.js", + "clean": "rm -rf doc coverage" + }, "repository": { "type": "git", - "url": "git://github.com/commenthol/markedpp.git" - }, - "homepage": "https://github.com/commenthol/markedpp", - "bugs": { - "url": "http://github.com/commenthol/markedpp/issues" + "url": "https://github.com/commenthol/markedpp.git" }, "keywords": [ "markdown", @@ -25,17 +36,11 @@ "number headings", "autonumber ordered lists" ], - "directories": { - "test": "test" - }, - "dependencies": { - "async": "^0.9.0" - }, - "devDependencies": { - "express": "^4.8.7", - "mocha": "^1.21.4" + "author": "commenthol <commenthol@gmail.com>", + "maintainers": "commenthol <commenthol@gmail.com>", + "license": "MIT", + "bugs": { + "url": "https://github.com/commenthol/markedpp/issues" }, - "scripts": { - "test": "mocha test/*.mocha.js" - } -} + "homepage": "https://github.com/commenthol/markedpp" +} \ No newline at end of file diff --git a/test/assets/toc_id.exp.md b/test/assets/toc_id.exp.md new file mode 100644 index 0000000..8523025 --- /dev/null +++ b/test/assets/toc_id.exp.md @@ -0,0 +1,23 @@ +<!-- !toc --> + +* [Heading 1](#anchor-headingid1) + * [Heading 1.1](#heading-1-1) +* [Heading 2](#anchor-headingid2) +* [Heading 3](#anchor-headingid3) + * [Heading 4](#anchor-headingid4) + +<!-- toc! --> + +<a name="anchor-headingid1"/> +# Heading 1 + +## Heading 1.1 + +<a name="anchor-headingid2"/> +# Heading 2 + +<a name="anchor-headingid3"/> +# Heading 3 + +<a name="anchor-headingid4"/> +## Heading 4 diff --git a/test/assets/toc_id.md b/test/assets/toc_id.md new file mode 100644 index 0000000..5623192 --- /dev/null +++ b/test/assets/toc_id.md @@ -0,0 +1,17 @@ +!toc + +<a name="anchor-headingid1" /> +# Heading 1 + +## Heading 1.1 + +<a name="anchor-headingid2"></a> +# Heading 2 + +<a name="anchor-headingid3"> +Heading 3 +========= + +<a name="anchor-headingid4" ></a> +Heading 4 +--------- diff --git a/test/lexer.mocha.js b/test/lexer.mocha.js index b9cc91c..55ea0e2 100644 --- a/test/lexer.mocha.js +++ b/test/lexer.mocha.js @@ -5,17 +5,19 @@ var assert = require('assert'), Lexer = require('../lib/markedpp').Lexer; +//~ console.log(Lexer); return; + describe ('#Lexer.splitOpts', function() { var splitOpts = Lexer.splitOpts; - - it ('empty', function(){ + + it ('empty', function(){ var str = '', res = splitOpts(str), exp = {}; assert.deepEqual(res, exp); }); - + it ('single key', function(){ var str = 'key', res = splitOpts(str), diff --git a/test/markedpp.mocha.js b/test/markedpp.mocha.js index 26f29a8..dd92cf7 100644 --- a/test/markedpp.mocha.js +++ b/test/markedpp.mocha.js @@ -29,6 +29,7 @@ var u = { opt.dirname = u.dir; markedpp(src, opt, function (err, res) { + //~ console.log(res); assert.equal(res, exp); done(); }); @@ -115,6 +116,11 @@ describe ('toc', function() { it ('update autoid on references using numberedheadings', function(done){ u.run('toc_autoid.md', done); }); + + it ('toc change id', function(done){ + u.run('toc_id.md', done); + }); + }); describe ('references', function() { @@ -221,6 +227,38 @@ describe ('parser', function() { it ('no autonumber lists', function(done){ u.run('parser_lists_noautonumber.md', done, { autonumber: false }); }); +}); + +describe('headingAutoId', function(){ + it('marked', function(){ + var token = { + text: 'mergeExt(opts, opts.ignoreNull, opts.ignoreCircular, target, source)' + }; + var parser = new markedpp.Parser(); + var exp = '#mergeext-opts-opts-ignorenull-opts-ignorecircular-target-source-'; + var res = parser.headingAutoId(token); + assert.equal(res, exp); + }); + + it('github', function(){ + var token = { + text: 'mergeExt(opts, opts.ignoreNull, opts.ignoreCircular, target, source)' + }; + var parser = new markedpp.Parser({ githubid: true }); + var exp = '#mergeextopts-optsignorenull-optsignorecircular-target-source'; + var res = parser.headingAutoId(token); + assert.equal(res, exp); + }); + + it('github &ersand', function(){ + var token = { + text: 'Running Tests & Contributing' + }; + var parser = new markedpp.Parser({ githubid: true }); + var exp = '#running-tests--contributing'; + var res = parser.headingAutoId(token); + assert.equal(res, exp); + }); }); diff --git a/test/server.js b/test/server.js index 65619a0..68158d5 100644 --- a/test/server.js +++ b/test/server.js @@ -4,12 +4,12 @@ if (typeof describe === 'function') { return; } -var express = require('express'), +var express = require('express'), app = express(); app.set('port', process.env.PORT || 3000); app.use(express.static(__dirname + '/assets')); var server = app.listen(app.get('port'), function() { - console.log('Server listening on port ' + server.address().port); + console.log('Server listening on port ' + server.address().port); });