From b67fc21a353ac660779468937bea1743271a526f Mon Sep 17 00:00:00 2001 From: Sana Javed Date: Fri, 21 Apr 2023 21:01:43 +0200 Subject: [PATCH] Adding anchor links --- package.json | 1 + source/helpers/components/anchors.ts | 38 ++++++++++++++++++++++++++++ source/helpers/engines.ts | 9 +++++-- yarn.lock | 11 ++++++++ 4 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 source/helpers/components/anchors.ts diff --git a/package.json b/package.json index 966faeb..7522fd0 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "kleur": "^4.1.5", "lorem-ipsum": "^2.0.8", "markdown-it": "^13.0.1", + "markdown-it-anchor": "^8.6.7", "markdown-it-attrs": "^4.1.6", "markdown-it-deflist": "^2.1.0", "netlify-plugin-11ty": "^1.3.0", diff --git a/source/helpers/components/anchors.ts b/source/helpers/components/anchors.ts new file mode 100644 index 0000000..c1cd3d2 --- /dev/null +++ b/source/helpers/components/anchors.ts @@ -0,0 +1,38 @@ +import Token from 'markdown-it/lib/token'; +import anchor from 'markdown-it-anchor/types'; + +// Custom permalink function, inspired by and modification of linkInsideHeader +// More context on custom permalink fns: https://github.com/valeriangalliat/markdown-it-anchor#custom-permalink +// linkInsideHeader function: https://github.com/valeriangalliat/markdown-it-anchor/blob/649582d58185b00cfb2ceee9b6b4cd6aafc645b7/permalink.js#L76 +export const renderPermalink: anchor.PermalinkGenerator = ( + slug, + opts: anchor.LinkInsideHeaderPermalinkOptions, + state, + idx, +) => { + opts.ariaHidden = false; + + const title = state?.tokens[idx + 1].children + ?.filter( + (token: Token) => token.type === 'text' || token.type === 'code_inline', + ) + .reduce((acc, t) => acc + t.content, ''); + + const linkTokens = [ + Object.assign(new state.Token('link_open', 'a', 1), { + attrs: [ + ['class', 'anchor'], + ['href', `#${slug}`], + ...(opts.ariaHidden ? [['aria-hidden', 'true']] : []), + ], + }), + Object.assign(new state.Token('html_inline', '', 0), { + content: `${ + title ? title : 'section' + } permalink'`, + }), + new state.Token('link_close', 'a', -1), + ]; + + state?.tokens[idx + 1]?.children?.push(...linkTokens); +}; diff --git a/source/helpers/engines.ts b/source/helpers/engines.ts index b6fc6a8..9257b0c 100644 --- a/source/helpers/engines.ts +++ b/source/helpers/engines.ts @@ -1,9 +1,11 @@ import { Liquid } from 'liquidjs'; -import markdown from 'markdown-it'; +import markdown, { PluginWithOptions } from 'markdown-it'; import markdownItAttrs from 'markdown-it-attrs'; import markdownDefList from 'markdown-it-deflist'; import path from 'path'; +import { renderPermalink } from './components/anchors'; + /** * Returns Markdown engine with custom configuration and plugins. * @@ -16,7 +18,10 @@ export const markdownEngine = markdown({ typographer: true, }) .use(markdownDefList) - .use(markdownItAttrs); + .use(markdownItAttrs) + .use(require('markdown-it-anchor') as PluginWithOptions, { + permalink: renderPermalink, + }); /** * Returns LiquidJS engine with custom configuration. diff --git a/yarn.lock b/yarn.lock index eff02b3..6c074d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5303,6 +5303,16 @@ __metadata: languageName: node linkType: hard +"markdown-it-anchor@npm:^8.6.7": + version: 8.6.7 + resolution: "markdown-it-anchor@npm:8.6.7" + peerDependencies: + "@types/markdown-it": "*" + markdown-it: "*" + checksum: 828236768ac7f61ed5591393c1b1bfc5dbf2b6d0c58a3deec606c61dddaa12658a34450cbef37ab50a04453e618ce1efd47d86e4e52595024334898fd306225b + languageName: node + linkType: hard + "markdown-it-attrs@npm:^4.1.6": version: 4.1.6 resolution: "markdown-it-attrs@npm:4.1.6" @@ -6758,6 +6768,7 @@ __metadata: kleur: ^4.1.5 lorem-ipsum: ^2.0.8 markdown-it: ^13.0.1 + markdown-it-anchor: ^8.6.7 markdown-it-attrs: ^4.1.6 markdown-it-deflist: ^2.1.0 netlify-plugin-11ty: ^1.3.0