UNPKG

jsdoc-75lb

Version:

An API documentation generator for JavaScript.

179 lines (156 loc) 5.75 kB
/** * Provides access to Markdown-related functions. * @module jsdoc/util/markdown * @author Michael Mathews <micmath@gmail.com> * @author Ben Blank <ben.blank@gmail.com> */ 'use strict'; var env = require('jsdoc/env'); var util = require('util'); /** * Enumeration of Markdown parsers that are available. * @enum {String} */ var parserNames = { /** * The "[markdown-js](https://github.com/evilstreak/markdown-js)" (aka "evilstreak") parser. * * @deprecated Replaced by "marked," as markdown-js does not support inline HTML. */ evilstreak: 'marked', /** * The "GitHub-flavored Markdown" parser. * @deprecated Replaced by "marked." */ gfm: 'marked', /** * The "[Marked](https://github.com/chjj/marked)" parser. */ marked: 'marked' }; /** * Escape underscores that occur within {@ ... } in order to protect them * from the markdown parser(s). * @param {String} source the source text to sanitize. * @returns {String} `source` where underscores within {@ ... } have been * protected with a preceding backslash (i.e. \_) -- the markdown parsers * will strip the backslash and protect the underscore. */ function escapeUnderscores(source) { return source.replace(/\{@[^}\r\n]+\}/g, function (wholeMatch) { return wholeMatch.replace(/(^|[^\\])_/g, '$1\\_'); }); } /** * Escape HTTP/HTTPS URLs so that they are not automatically converted to HTML links. * * @param {string} source - The source text to escape. * @return {string} The source text with escape characters added to HTTP/HTTPS URLs. */ function escapeUrls(source) { return source.replace(/(https?)\:\/\//g, '$1:\\/\\/'); } /** * Unescape HTTP/HTTPS URLs after Markdown parsing is complete. * * @param {string} source - The source text to unescape. * @return {string} The source text with escape characters removed from HTTP/HTTPS URLs. */ function unescapeUrls(source) { return source.replace(/(https?)\:\\\/\\\//g, '$1://'); } /** * Escape characters in text within a code block. * * @param {string} source - The source text to escape. * @return {string} The escaped source text. */ function escapeCode(source) { return source.replace(/</g, '&lt;') .replace(/"/g, '&quot;') .replace(/'/g, '&#39;'); } /** * Unencode quotes that occur within {@ ... } after the markdown parser has turned them * into html entities (unfortunately it isn't possible to escape them before parsing) * * @param {string} source - The source text to unencode. * @return {string} The source text with html entity `&quot;` converted back to standard quotes */ function unencodeQuotes(source) { return source.replace(/\{@[^}\r\n]+\}/g, function (wholeMatch) { return wholeMatch.replace(/&quot;/g, '"'); }); } /** * Retrieve a function that accepts a single parameter containing Markdown source. The function uses * the specified parser to transform the Markdown source to HTML, then returns the HTML as a string. * * @private * @param {String} parserName The name of the selected parser. * @param {Object} [conf] Configuration for the selected parser, if any. * @returns {Function} A function that accepts Markdown source, feeds it to the selected parser, and * returns the resulting HTML. */ function getParseFunction(parserName, conf) { var logger = require('jsdoc/util/logger'); var marked = require('marked'); var markedRenderer; var parserFunction; conf = conf || {}; if (parserName === parserNames.marked) { if (conf.hardwrap) { marked.setOptions({breaks: true}); } // Marked generates an "id" attribute for headers; this custom renderer suppresses it markedRenderer = new marked.Renderer(); if (!conf.idInHeadings) { markedRenderer.heading = function(text, level) { return util.format('<h%s>%s</h%s>', level, text, level); }; } // Allow prettyprint to work on inline code samples markedRenderer.code = function(code, language) { var langClass = language ? ' lang-' + language : ''; return util.format( '<pre class="prettyprint source%s"><code>%s</code></pre>', langClass, escapeCode(code) ); }; parserFunction = function(source) { var result; source = escapeUnderscores(source); source = escapeUrls(source); result = marked(source, { renderer: markedRenderer }) .replace(/\s+$/, '') .replace(/&#39;/g, "'"); result = unescapeUrls(result); result = unencodeQuotes(result); return result; }; parserFunction._parser = parserNames.marked; return parserFunction; } else { logger.error('Unrecognized Markdown parser "%s". Markdown support is disabled.', parserName); return undefined; } } /** * Retrieve a Markdown parsing function based on the value of the `conf.json` file's * `env.conf.markdown` property. The parsing function accepts a single parameter containing Markdown * source. The function uses the parser specified in `conf.json` to transform the Markdown source to * HTML, then returns the HTML as a string. * * @returns {function} A function that accepts Markdown source, feeds it to the selected parser, and * returns the resulting HTML. */ exports.getParser = function() { var conf = env.conf.markdown; if (conf && conf.parser) { return getParseFunction(parserNames[conf.parser], conf); } else { // marked is the default parser return getParseFunction(parserNames.marked, conf); } };