From 04ecb1d42f809169ceeeed6706a378c63d5a8491 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 5 May 2022 11:33:38 -0700 Subject: [PATCH] Normalize markdown links in notebooks (#148827) Fixes #146352 This ensures we pass links in markdown cells through the same normalization function we use to assign headers ids --- .../notebook/index.ts | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/extensions/markdown-language-features/notebook/index.ts b/extensions/markdown-language-features/notebook/index.ts index 7b4652a9795..3fdb86bd8d7 100644 --- a/extensions/markdown-language-features/notebook/index.ts +++ b/extensions/markdown-language-features/notebook/index.ts @@ -26,6 +26,7 @@ export const activate: ActivationFunction = (ctx) => { markdownIt.linkify.set({ fuzzyLink: false }); addNamedHeaderRendering(markdownIt); + addLinkRenderer(markdownIt); const style = document.createElement('style'); style.textContent = ` @@ -225,12 +226,12 @@ function addNamedHeaderRendering(md: InstanceType): void { const originalHeaderOpen = md.renderer.rules.heading_open; md.renderer.rules.heading_open = (tokens: MarkdownItToken[], idx: number, options, env, self) => { const title = tokens[idx + 1].children!.reduce((acc, t) => acc + t.content, ''); - let slug = slugFromHeading(title); + let slug = slugify(title); if (slugCounter.has(slug)) { const count = slugCounter.get(slug)!; slugCounter.set(slug, count + 1); - slug = slugFromHeading(slug + '-' + (count + 1)); + slug = slugify(slug + '-' + (count + 1)); } else { slugCounter.set(slug, 0); } @@ -251,9 +252,26 @@ function addNamedHeaderRendering(md: InstanceType): void { }; } -function slugFromHeading(heading: string): string { +function addLinkRenderer(md: MarkdownIt): void { + const original = md.renderer.rules.link_open; + + md.renderer.rules.link_open = (tokens: MarkdownItToken[], idx: number, options, env, self) => { + const token = tokens[idx]; + const href = token.attrGet('href'); + if (typeof href === 'string' && href.startsWith('#')) { + token.attrSet('href', '#' + slugify(href.slice(1))); + } + if (original) { + return original(tokens, idx, options, env, self); + } else { + return self.renderToken(tokens, idx, options); + } + }; +} + +function slugify(text: string): string { const slugifiedHeading = encodeURI( - heading.trim() + text.trim() .toLowerCase() .replace(/\s+/g, '-') // Replace whitespace with - // allow-any-unicode-next-line