From b29c44d8958b2414b1feb1cb8477fc61dadf805e Mon Sep 17 00:00:00 2001 From: John Philip Date: Wed, 17 Aug 2022 21:19:11 -0400 Subject: [PATCH 1/3] Autogenerate ids for headings in markdown content Signed-off-by: John Philip --- .changeset/lazy-snakes-film.md | 5 ++++ .../MarkdownContent/MarkdownContent.test.tsx | 30 +++++++++++++++++++ .../MarkdownContent/MarkdownContent.tsx | 19 ++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 .changeset/lazy-snakes-film.md diff --git a/.changeset/lazy-snakes-film.md b/.changeset/lazy-snakes-film.md new file mode 100644 index 0000000000..a21d197c51 --- /dev/null +++ b/.changeset/lazy-snakes-film.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': minor +--- + +Adds code to autogenerate ids for headers parsed through the MarkdownContent component. diff --git a/packages/core-components/src/components/MarkdownContent/MarkdownContent.test.tsx b/packages/core-components/src/components/MarkdownContent/MarkdownContent.test.tsx index 9c08b83c40..fa8cb35ca8 100644 --- a/packages/core-components/src/components/MarkdownContent/MarkdownContent.test.tsx +++ b/packages/core-components/src/components/MarkdownContent/MarkdownContent.test.tsx @@ -100,4 +100,34 @@ describe('', () => { 'https://example.com/blog/assets/6/header.png', ); }); + + it('render MarkdownContent component with headings given proper ids', async () => { + const rendered = await renderWithEffects( + wrapInTestApp( + , + ), + ); + + expect(rendered.getByText('Lorem ipsum').getAttribute('id')).toEqual( + 'lorem-ipsum', + ); + expect(rendered.getByText('bing bong').getAttribute('id')).toEqual( + 'bing-bong', + ); + expect( + rendered + .getByText( + 'The FitnessGram Pacer Test is a multistage aerobic capacity test', + ) + .getAttribute('id'), + ).toEqual( + 'the-fitnessgram-pacer-test-is-a-multistage-aerobic-capacity-test', + ); + }); }); diff --git a/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx b/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx index 013e81817a..e2ee460a1f 100644 --- a/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx +++ b/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx @@ -73,6 +73,19 @@ type Props = { className?: string; }; +const flatten = (text, child) => { + return typeof child === 'string' + ? text + child + : React.Children.toArray(child.props.children).reduce(flatten, text); +}; + +const headingRenderer = ({ level, children }) => { + const childrenArray = React.Children.toArray(children); + const text = childrenArray.reduce(flatten, ''); + const slug = text.toLocaleLowerCase('en-US').replace(/\W/g, '-'); + return React.createElement(`h${level}`, { id: slug }, children); +}; + const components: Options['components'] = { code: ({ inline, className, children, ...props }) => { const text = String(children).replace(/\n+$/, ''); @@ -85,6 +98,12 @@ const components: Options['components'] = { ); }, + h1: headingRenderer, + h2: headingRenderer, + h3: headingRenderer, + h4: headingRenderer, + h5: headingRenderer, + h6: headingRenderer, }; /** From e51cddd5fbba7df09203a19be7e391f0a5012012 Mon Sep 17 00:00:00 2001 From: John Philip Date: Wed, 17 Aug 2022 22:46:38 -0400 Subject: [PATCH 2/3] Changed types to be more specific Signed-off-by: John Philip --- .../src/components/MarkdownContent/MarkdownContent.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx b/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx index e2ee460a1f..d97172bf75 100644 --- a/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx +++ b/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx @@ -20,6 +20,7 @@ import gfm from 'remark-gfm'; import React from 'react'; import { BackstageTheme } from '@backstage/theme'; import { CodeSnippet } from '../CodeSnippet'; +import { HeadingProps } from 'react-markdown/lib/ast-to-react'; export type MarkdownContentClassKey = 'markdown'; @@ -73,13 +74,15 @@ type Props = { className?: string; }; -const flatten = (text, child) => { +const flatten = (text: string, child: any): string => { + if (!child) return text; + return typeof child === 'string' ? text + child : React.Children.toArray(child.props.children).reduce(flatten, text); }; -const headingRenderer = ({ level, children }) => { +const headingRenderer = ({ level, children }: HeadingProps) => { const childrenArray = React.Children.toArray(children); const text = childrenArray.reduce(flatten, ''); const slug = text.toLocaleLowerCase('en-US').replace(/\W/g, '-'); From bdf812508adea8ad39d7d854a5b20ae05d212c5c Mon Sep 17 00:00:00 2001 From: John Philip Date: Thu, 18 Aug 2022 10:11:00 -0400 Subject: [PATCH 3/3] fix spelling Signed-off-by: John Philip --- .changeset/lazy-snakes-film.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/lazy-snakes-film.md b/.changeset/lazy-snakes-film.md index a21d197c51..ff4097f78f 100644 --- a/.changeset/lazy-snakes-film.md +++ b/.changeset/lazy-snakes-film.md @@ -2,4 +2,4 @@ '@backstage/core-components': minor --- -Adds code to autogenerate ids for headers parsed through the MarkdownContent component. +Adds code to generate ids for headers parsed through the MarkdownContent component.