From 6d7e9e8876f04da36869c541ec6f3e184442fec7 Mon Sep 17 00:00:00 2001 From: carvin Date: Sat, 26 Dec 2020 10:25:25 +0800 Subject: [PATCH 1/2] Add `headingLinksHref` option Support custom href. --- index.js | 72 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/index.js b/index.js index cdcca93..20311da 100644 --- a/index.js +++ b/index.js @@ -1,79 +1,81 @@ -module.exports = plugin +module.exports = plugin; -var GithubSlugger = require('github-slugger') -var innertext = require('innertext') +var GithubSlugger = require('github-slugger'); +var innertext = require('innertext'); var defaultOptions = { enableHeadingLinkIcons: true, prefixHeadingIds: true, prefix: 'user-content-', className: 'anchor', // shamelessly borrowed from GitHub, thanks y'all - linkIcon: '', - resetSlugger: true -} + linkIcon: + '', + resetSlugger: true, + headingLinksHref: slug => `#${slug}` +}; -function plugin (md, _opts) { - var options = Object.assign({}, defaultOptions, _opts) +function plugin(md, _opts) { + var options = Object.assign({}, defaultOptions, _opts); - if (!options.prefixHeadingIds) options.prefix = '' + if (!options.prefixHeadingIds) options.prefix = ''; - var slugger = new GithubSlugger() - var Token + var slugger = new GithubSlugger(); + var Token; md.core.ruler.push('headingLinks', function (state) { if (options.resetSlugger) { - slugger.reset() + slugger.reset(); } // save the Token constructor because we'll be building a few instances at render // time; that's sort of outside the intended markdown-it parsing sequence, but // since we have tight control over what we're creating (a link), we're safe if (!Token) { - Token = state.Token + Token = state.Token; } - }) + }); md.renderer.rules.heading_open = function (tokens, idx, opts, env, self) { - var children = tokens[idx + 1].children + var children = tokens[idx + 1].children; // make sure heading is not empty if (children && children.length) { // Generate an ID based on the heading's innerHTML; first, render without // converting gemoji strings to unicode emoji characters - var unemojiWithToken = unemoji.bind(null, Token) - var rendered = md.renderer.renderInline(children.map(unemojiWithToken), opts, env) + var unemojiWithToken = unemoji.bind(null, Token); + var rendered = md.renderer.renderInline(children.map(unemojiWithToken), opts, env); var postfix = slugger.slug( innertext(rendered) .replace(/[<>]/g, '') // In case the heading contains `` - .toLowerCase() // because `slug` doesn't lowercase - ) + .toLowerCase(), // because `slug` doesn't lowercase + ); // add 3 new token objects link_open, text, link_close - var linkOpen = new Token('link_open', 'a', 1) - var text = new Token('html_inline', '', 0) + var linkOpen = new Token('link_open', 'a', 1); + var text = new Token('html_inline', '', 0); if (options.enableHeadingLinkIcons) { - text.content = options.linkIcon + text.content = options.linkIcon; } - var linkClose = new Token('link_close', 'a', -1) + var linkClose = new Token('link_close', 'a', -1); // add some link attributes - linkOpen.attrSet('id', options.prefix + postfix) - linkOpen.attrSet('class', options.className) - linkOpen.attrSet('href', '#' + postfix) - linkOpen.attrSet('aria-hidden', 'true') + linkOpen.attrSet('id', options.prefix + postfix); + linkOpen.attrSet('class', options.className); + linkOpen.attrSet('href', options.headingLinksHref(postfix)); + linkOpen.attrSet('aria-hidden', 'true'); // add new token objects as children of heading - children.unshift(linkClose) - children.unshift(text) - children.unshift(linkOpen) + children.unshift(linkClose); + children.unshift(text); + children.unshift(linkOpen); } - return md.renderer.renderToken(tokens, idx, options, env, self) - } + return md.renderer.renderToken(tokens, idx, options, env, self); + }; } -function unemoji (TokenConstructor, token) { +function unemoji(TokenConstructor, token) { if (token.type === 'emoji') { - return Object.assign(new TokenConstructor(), token, {content: token.markup}) + return Object.assign(new TokenConstructor(), token, { content: token.markup }); } - return token + return token; } From 545855908927de0a82697242265ea5e895b24b9b Mon Sep 17 00:00:00 2001 From: carvin Date: Sat, 26 Dec 2020 10:28:34 +0800 Subject: [PATCH 2/2] Update index.js --- index.js | 69 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/index.js b/index.js index 20311da..c83c6e4 100644 --- a/index.js +++ b/index.js @@ -1,81 +1,80 @@ -module.exports = plugin; +module.exports = plugin -var GithubSlugger = require('github-slugger'); -var innertext = require('innertext'); +var GithubSlugger = require('github-slugger') +var innertext = require('innertext') var defaultOptions = { enableHeadingLinkIcons: true, prefixHeadingIds: true, prefix: 'user-content-', className: 'anchor', // shamelessly borrowed from GitHub, thanks y'all - linkIcon: - '', + linkIcon: '', resetSlugger: true, headingLinksHref: slug => `#${slug}` -}; +} -function plugin(md, _opts) { - var options = Object.assign({}, defaultOptions, _opts); +function plugin (md, _opts) { + var options = Object.assign({}, defaultOptions, _opts) - if (!options.prefixHeadingIds) options.prefix = ''; + if (!options.prefixHeadingIds) options.prefix = '' - var slugger = new GithubSlugger(); - var Token; + var slugger = new GithubSlugger() + var Token md.core.ruler.push('headingLinks', function (state) { if (options.resetSlugger) { - slugger.reset(); + slugger.reset() } // save the Token constructor because we'll be building a few instances at render // time; that's sort of outside the intended markdown-it parsing sequence, but // since we have tight control over what we're creating (a link), we're safe if (!Token) { - Token = state.Token; + Token = state.Token } - }); + }) md.renderer.rules.heading_open = function (tokens, idx, opts, env, self) { - var children = tokens[idx + 1].children; + var children = tokens[idx + 1].children // make sure heading is not empty if (children && children.length) { // Generate an ID based on the heading's innerHTML; first, render without // converting gemoji strings to unicode emoji characters - var unemojiWithToken = unemoji.bind(null, Token); - var rendered = md.renderer.renderInline(children.map(unemojiWithToken), opts, env); + var unemojiWithToken = unemoji.bind(null, Token) + var rendered = md.renderer.renderInline(children.map(unemojiWithToken), opts, env) var postfix = slugger.slug( innertext(rendered) .replace(/[<>]/g, '') // In case the heading contains `` - .toLowerCase(), // because `slug` doesn't lowercase - ); + .toLowerCase() // because `slug` doesn't lowercase + ) // add 3 new token objects link_open, text, link_close - var linkOpen = new Token('link_open', 'a', 1); - var text = new Token('html_inline', '', 0); + var linkOpen = new Token('link_open', 'a', 1) + var text = new Token('html_inline', '', 0) if (options.enableHeadingLinkIcons) { - text.content = options.linkIcon; + text.content = options.linkIcon } - var linkClose = new Token('link_close', 'a', -1); + var linkClose = new Token('link_close', 'a', -1) // add some link attributes - linkOpen.attrSet('id', options.prefix + postfix); - linkOpen.attrSet('class', options.className); - linkOpen.attrSet('href', options.headingLinksHref(postfix)); - linkOpen.attrSet('aria-hidden', 'true'); + linkOpen.attrSet('id', options.prefix + postfix) + linkOpen.attrSet('class', options.className) + linkOpen.attrSet('href', options.headingLinksHref(postfix)) + linkOpen.attrSet('aria-hidden', 'true') // add new token objects as children of heading - children.unshift(linkClose); - children.unshift(text); - children.unshift(linkOpen); + children.unshift(linkClose) + children.unshift(text) + children.unshift(linkOpen) } - return md.renderer.renderToken(tokens, idx, options, env, self); - }; + return md.renderer.renderToken(tokens, idx, options, env, self) + } } -function unemoji(TokenConstructor, token) { +function unemoji (TokenConstructor, token) { if (token.type === 'emoji') { - return Object.assign(new TokenConstructor(), token, { content: token.markup }); + return Object.assign(new TokenConstructor(), token, {content: token.markup}) } - return token; + return token }