text: 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
  };
  