UNPKG

@godaddy/dmd

Version:

Plugin for jsdoc2md with improved readability and GitHub compatibility

169 lines (152 loc) 4.19 kB
const slugs = new Map(); // captures multiple inline links const reInlineLinks = /(?<!\\)(\[([^(]+|[.+])\])(\(([^(]+)\))/g; // captures inline links with (parentheses) in title const reInlineSigLinks = /(?<!\\)(\[(.+)\])(\(([^)\s]+)\))/g; const reBrackets = /[^\\]\[|[^\\]]/g; const reLeftBrackets = /\[/g; const reRightBrackets = /]/g; const reSpaces = /\s+/g; const reNonSlugChars = /[^a-z0-9- _]/g; const reNewLines = /\n/g; // Finds first paragraph end or line break const reParagraphBreak = /(\n(\s+)?\n|\\\n|\s{2}\n)/; /** * Stores a slug for the element * * @param {string} parent - Parent * @param {string} name - Name * @param {string} slug - Generated slug * @private */ function setSlug(parent, name, slug) { if (parent !== 'event') { const sig = parent + '#' + name; slugs.set(sig, slug); } } /** * Gets a slug if defined for an element * * @param {string} parent - Parent * @param {string} name - Name * @returns {string|undefined} stored slug * @private */ function getSlug(parent, name) { if (parent === 'event') return name.toLowerCase(); const sig = parent + '#' + name; return slugs.get(sig); } /** * Builds a slug suitable for viewing on GitHub * * @param {string} parent - Parent * @param {string} prefix - Prefix * @param {string} accessSymbol - Access Symbol * @param {string} name - Name * @param {string} methodSign - Method Signature * @returns {string} slug */ function githubSlug(parent, prefix, accessSymbol, name, methodSign) { const slug = [ parent, prefix ? prefix + ' ' : '', accessSymbol, name, methodSign ].join('') .trim() .toLowerCase() .replace(reSpaces, '-') .replace(reNonSlugChars, ''); setSlug(parent, name, slug); return slug; } /* eslint-disable no-unused-vars */ /** * Adds code ticks to element name, and creates link if slug found * * @param {string} parent - Parent * @param {string} prefix - Prefix * @param {string} accessSymbol - Access Symbol * @param {string} name - Name * @param {string} methodSign - Method Signature * @returns {string} code name */ function codeLink(parent, prefix, accessSymbol, name, methodSign) { const slug = getSlug(parent, name); if (slug) { return '[`' + name + '`](#' + slug + ')'; } return '`' + name + '`'; } /* eslint-enable no-unused-vars */ /** * Returns only the first paragraph of a description with newlines removed * for use in tables. * * @param {string} description - Description * @returns {string} short description */ function shortDesc(description) { if (!description) return ''; let nextDesc = description.trim(); const match = reParagraphBreak.exec(nextDesc); if (match) { nextDesc = nextDesc.substring(0, match.index); } return nextDesc.replace(reNewLines, ' ').trim(); } /** * Block helper to transform all inline slugs to reference slugs. * * @param {object} options - Block details * @param {function} options.fn - Passed template * @returns {string} results */ function refLinks(options) { const refMap = new Map(); const slugMap = new Map(); let idx = 0; function safeRef(name, slug) { // if the name has non-escaped brackets, use numeric ref id if (reBrackets.test(name)) { const ref = slugMap.get(slug) || ++idx; refMap.set(ref, slug); slugMap.set(slug, ref); return ref; } refMap.set(name, slug); } function formatLink(match, brackets, title, parentheses, link) { const ref = safeRef(title, link); return brackets + (ref ? `[${ref}]` : ''); } const content = options.fn(this) .replace(reInlineLinks, formatLink) .replace(reInlineSigLinks, formatLink); let refContent = '<!-- LINKS -->\n\n'; for (const [name, slug] of refMap) { refContent += `[${name}]:${slug}\n`; } return content + refContent; } /** * Escapes brackets found in a string. * * @param {string} content - Text which may have brackets * @returns {string} content */ function escapeBrackets(content) { return content .replace(reLeftBrackets, '\\[') .replace(reRightBrackets, '\\]'); } module.exports = { githubSlug, codeLink, shortDesc, refLinks, escapeBrackets };