1 |
- {"version":3,"file":"markdownItAnchor.mjs","sources":["../permalink.js","../index.js"],"sourcesContent":["let emittedWarning = false\n\nconst position = {\n false: 'push',\n true: 'unshift',\n after: 'push',\n before: 'unshift'\n}\n\nconst permalinkSymbolMeta = {\n isPermalinkSymbol: true\n}\n\nexport function legacy (slug, opts, state, idx) {\n if (!emittedWarning) {\n const warningText = 'Using deprecated markdown-it-anchor permalink option, see https://github.com/valeriangalliat/markdown-it-anchor#todo-anchor-or-file'\n\n if (typeof process === 'object' && process && process.emitWarning) {\n process.emitWarning(warningText)\n } else {\n console.warn(warningText)\n }\n\n emittedWarning = true\n }\n\n const linkTokens = [\n Object.assign(new state.Token('link_open', 'a', 1), {\n attrs: [\n ...(opts.permalinkClass ? [['class', opts.permalinkClass]] : []),\n ['href', opts.permalinkHref(slug, state)],\n ...Object.entries(opts.permalinkAttrs(slug, state))\n ]\n }),\n Object.assign(new state.Token('html_block', '', 0), { content: opts.permalinkSymbol, meta: permalinkSymbolMeta }),\n new state.Token('link_close', 'a', -1)\n ]\n\n if (opts.permalinkSpace) {\n state.tokens[idx + 1].children[position[opts.permalinkBefore]](Object.assign(new state.Token('text', '', 0), { content: ' ' }))\n }\n\n state.tokens[idx + 1].children[position[opts.permalinkBefore]](...linkTokens)\n}\n\nexport function renderHref (slug) {\n return `#${slug}`\n}\n\nexport function renderAttrs (slug) {\n return {}\n}\n\nconst commonDefaults = {\n class: 'header-anchor',\n symbol: '#',\n renderHref,\n renderAttrs\n}\n\nexport function makePermalink (renderPermalinkImpl) {\n function renderPermalink (opts) {\n opts = Object.assign({}, renderPermalink.defaults, opts)\n\n return (slug, anchorOpts, state, idx) => {\n return renderPermalinkImpl(slug, opts, anchorOpts, state, idx)\n }\n }\n\n renderPermalink.defaults = Object.assign({}, commonDefaults)\n renderPermalink.renderPermalinkImpl = renderPermalinkImpl\n\n return renderPermalink\n}\n\nexport const linkInsideHeader = makePermalink((slug, opts, anchorOpts, state, idx) => {\n const linkTokens = [\n Object.assign(new state.Token('link_open', 'a', 1), {\n attrs: [\n ...(opts.class ? [['class', opts.class]] : []),\n ['href', opts.renderHref(slug, state)],\n ...(opts.ariaHidden ? [['aria-hidden', 'true']] : []),\n ...Object.entries(opts.renderAttrs(slug, state))\n ]\n }),\n Object.assign(new state.Token('html_inline', '', 0), { content: opts.symbol, meta: permalinkSymbolMeta }),\n new state.Token('link_close', 'a', -1)\n ]\n\n if (opts.space) {\n state.tokens[idx + 1].children[position[opts.placement]](Object.assign(new state.Token('text', '', 0), { content: ' ' }))\n }\n\n state.tokens[idx + 1].children[position[opts.placement]](...linkTokens)\n})\n\nObject.assign(linkInsideHeader.defaults, {\n space: true,\n placement: 'after',\n ariaHidden: false\n})\n\nexport const ariaHidden = makePermalink(linkInsideHeader.renderPermalinkImpl)\n\nariaHidden.defaults = Object.assign({}, linkInsideHeader.defaults, {\n ariaHidden: true\n})\n\nexport const headerLink = makePermalink((slug, opts, anchorOpts, state, idx) => {\n const linkTokens = [\n Object.assign(new state.Token('link_open', 'a', 1), {\n attrs: [\n ...(opts.class ? [['class', opts.class]] : []),\n ['href', opts.renderHref(slug, state)],\n ...Object.entries(opts.renderAttrs(slug, state))\n ]\n }),\n ...(opts.safariReaderFix ? [new state.Token('span_open', 'span', 1)] : []),\n ...state.tokens[idx + 1].children,\n ...(opts.safariReaderFix ? [new state.Token('span_close', 'span', -1)] : []),\n new state.Token('link_close', 'a', -1)\n ]\n\n state.tokens[idx + 1] = Object.assign(new state.Token('inline', '', 0), {\n children: linkTokens\n })\n})\n\nObject.assign(headerLink.defaults, {\n safariReaderFix: false\n})\n\nexport const linkAfterHeader = makePermalink((slug, opts, anchorOpts, state, idx) => {\n if (!['visually-hidden', 'aria-label', 'aria-describedby', 'aria-labelledby'].includes(opts.style)) {\n throw new Error(`\\`permalink.linkAfterHeader\\` called with unknown style option \\`${opts.style}\\``)\n }\n\n if (!['aria-describedby', 'aria-labelledby'].includes(opts.style) && !opts.assistiveText) {\n throw new Error(`\\`permalink.linkAfterHeader\\` called without the \\`assistiveText\\` option in \\`${opts.style}\\` style`)\n }\n\n if (opts.style === 'visually-hidden' && !opts.visuallyHiddenClass) {\n throw new Error('`permalink.linkAfterHeader` called without the `visuallyHiddenClass` option in `visually-hidden` style')\n }\n\n const title = state.tokens[idx + 1]\n .children\n .filter(token => token.type === 'text' || token.type === 'code_inline')\n .reduce((acc, t) => acc + t.content, '')\n\n const subLinkTokens = []\n const linkAttrs = []\n\n if (opts.class) {\n linkAttrs.push(['class', opts.class])\n }\n\n linkAttrs.push(['href', opts.renderHref(slug, state)])\n linkAttrs.push(...Object.entries(opts.renderAttrs(slug, state)))\n\n if (opts.style === 'visually-hidden') {\n subLinkTokens.push(\n Object.assign(new state.Token('span_open', 'span', 1), {\n attrs: [['class', opts.visuallyHiddenClass]],\n }),\n Object.assign(new state.Token('text', '', 0), {\n content: opts.assistiveText(title)\n }),\n new state.Token('span_close', 'span', -1)\n )\n\n if (opts.space) {\n subLinkTokens[position[opts.placement]](Object.assign(new state.Token('text', '', 0), { content: ' ' }))\n }\n\n subLinkTokens[position[opts.placement]](\n Object.assign(new state.Token('span_open', 'span', 1), {\n attrs: [['aria-hidden', 'true']],\n }),\n Object.assign(new state.Token('html_inline', '', 0), {\n content: opts.symbol,\n meta: permalinkSymbolMeta\n }),\n new state.Token('span_close', 'span', -1)\n )\n } else {\n subLinkTokens.push(\n Object.assign(new state.Token('html_inline', '', 0), {\n content: opts.symbol,\n meta: permalinkSymbolMeta\n })\n )\n }\n\n if (opts.style === 'aria-label') {\n linkAttrs.push(['aria-label', opts.assistiveText(title)])\n } else if (['aria-describedby', 'aria-labelledby'].includes(opts.style)) {\n linkAttrs.push([opts.style, slug])\n }\n\n const linkTokens = [\n Object.assign(new state.Token('link_open', 'a', 1), {\n attrs: linkAttrs\n }),\n ...subLinkTokens,\n new state.Token('link_close', 'a', -1),\n ]\n\n state.tokens.splice(idx + 3, 0, ...linkTokens)\n})\n\nObject.assign(linkAfterHeader.defaults, {\n style: 'visually-hidden',\n space: true,\n placement: 'after'\n})\n","import * as permalink from './permalink'\n\nconst slugify = (s) => encodeURIComponent(String(s).trim().toLowerCase().replace(/\\s+/g, '-'))\n\nfunction uniqueSlug (slug, slugs, failOnNonUnique, startIndex) {\n let uniq = slug\n let i = startIndex\n\n if (failOnNonUnique && Object.prototype.hasOwnProperty.call(slugs, uniq)) {\n throw new Error(`User defined \\`id\\` attribute \\`${slug}\\` is not unique. Please fix it in your Markdown to continue.`)\n } else {\n while (Object.prototype.hasOwnProperty.call(slugs, uniq)) {\n uniq = `${slug}-${i}`\n i += 1\n }\n }\n\n slugs[uniq] = true\n\n return uniq\n}\n\nconst isLevelSelectedNumber = selection => level => level >= selection\nconst isLevelSelectedArray = selection => level => selection.includes(level)\n\nfunction anchor (md, opts) {\n opts = Object.assign({}, anchor.defaults, opts)\n\n md.core.ruler.push('anchor', state => {\n const slugs = {}\n const tokens = state.tokens\n\n const isLevelSelected = Array.isArray(opts.level)\n ? isLevelSelectedArray(opts.level)\n : isLevelSelectedNumber(opts.level)\n\n for (let idx = 0; idx < tokens.length; idx++) {\n const token = tokens[idx]\n\n if (token.type !== 'heading_open') {\n continue\n }\n\n if (!isLevelSelected(Number(token.tag.substr(1)))) {\n continue\n }\n\n // Aggregate the next token children text.\n const title = tokens[idx + 1]\n .children\n .filter(token => token.type === 'text' || token.type === 'code_inline')\n .reduce((acc, t) => acc + t.content, '')\n\n let slug = token.attrGet('id')\n\n if (slug == null) {\n slug = uniqueSlug(opts.slugify(title), slugs, false, opts.uniqueSlugStartIndex)\n } else {\n slug = uniqueSlug(slug, slugs, true, opts.uniqueSlugStartIndex)\n }\n\n token.attrSet('id', slug)\n\n if (opts.tabIndex !== false) {\n token.attrSet('tabindex', `${opts.tabIndex}`)\n }\n\n if (typeof opts.permalink === 'function') {\n opts.permalink(slug, opts, state, idx)\n } else if (opts.permalink) {\n opts.renderPermalink(slug, opts, state, idx)\n } else if (opts.renderPermalink && opts.renderPermalink !== permalink.legacy) {\n opts.renderPermalink(slug, opts, state, idx)\n }\n\n
|