Markdown header margin fix [Fixes #83] (#120)

* expand parseHeadingId

Will produce a kebab-case heading ID from string if none explicitly declared in the markdown. Always returns an object with the children, title and headingId.

* remove redundant code from MDComponents.tsx

parseHeadingIds now always returns an object with an ID, removing need for conditionals here

* Use Box instead of flex Stack for MDX content

Allows stacked vertical margins to properly collapse into each other

* fix: h2 top margin to 3rem on mobile

* remove unneeded line

* extract and rename getKebabCaseFromName util fn

* Update src/pages/[...slug].tsx

* Update src/utils/parseHeadingId.ts

Co-authored-by: Corwin Smith <cssmittys@gmail.com>

* move constant inside function

make variable name all caps as a string constant

* clean up utils/index.ts to abc order

Co-authored-by: Corwin Smith <cssmittys@gmail.com>
This commit is contained in:
Paul Wackerow 2022-12-06 21:04:09 +01:00 committed by GitHub
parent 332e972397
commit 56b9963afd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 56 deletions

View File

@ -42,61 +42,37 @@ const MDComponents = {
},
// headings
h1: ({ children }: any) => {
const heading = parseHeadingId(children);
const { children: parsedChildren, headingId} = parseHeadingId(children);
return heading ? (
<Heading as='h1' textAlign='start' mb='5 !important' {...header1} id={heading.headingId}>
{heading.children}
</Heading>
) : (
<Heading as='h1' textAlign='start' mb='5 !important' {...header1}>
{children}
return (
<Heading as='h1' textAlign='start' mb='5 !important' {...header1} id={headingId}>
{parsedChildren}
</Heading>
);
},
h2: ({ children }: any) => {
const heading = parseHeadingId(children);
const { children: parsedChildren, headingId} = parseHeadingId(children);
return heading ? (
<Heading
as='h2'
textAlign='start'
mt='16 !important'
mb='4 !important'
{...header2}
id={heading.headingId}
>
{heading.children}
</Heading>
) : (
<Heading as='h2' textAlign='start' mt='16 !important' mb='4 !important' {...header2}>
{children}
return (
<Heading as='h2' textAlign='start' mt={{ base: '12 !important' , md: '16 !important'}} mb='4 !important' {...header2} id={headingId}>
{parsedChildren}
</Heading>
);
},
h3: ({ children }: any) => {
const heading = parseHeadingId(children);
return heading ? (
<Heading as='h3' mt='5 !important' mb='2.5 !important' {...header3} id={heading.headingId}>
{heading.children}
</Heading>
) : (
<Heading as='h3' mt='5 !important' mb='2.5 !important' {...header3}>
{children}
const { children: parsedChildren, headingId} = parseHeadingId(children);
return (
<Heading as='h3' mt='5 !important' mb='2.5 !important' {...header3} id={headingId}>
{parsedChildren}
</Heading>
);
},
h4: ({ children }: any) => {
const heading = parseHeadingId(children);
const { children: parsedChildren, headingId} = parseHeadingId(children);
return heading ? (
<Heading as='h4' mb='2.5 !important' {...header4} id={heading.headingId}>
{heading.children}
</Heading>
) : (
<Heading as='h4' mb='2.5 !important' {...header4}>
{children}
return (
<Heading as='h4' mb='2.5 !important' {...header4} id={headingId}>
{parsedChildren}
</Heading>
);
},

View File

@ -1,7 +1,7 @@
import fs from 'fs';
import matter from 'gray-matter';
import yaml from 'js-yaml';
import { Flex, Stack, Heading, Text } from '@chakra-ui/react';
import { Box, Flex, Stack, Heading, Text } from '@chakra-ui/react';
import ChakraUIRenderer from 'chakra-ui-markdown-renderer';
import ReactMarkdown from 'react-markdown';
import { useRouter } from 'next/router';
@ -116,7 +116,7 @@ const DocPage: NextPage<Props> = ({ frontmatter, content, navLinks, lastModified
</Stack>
<Flex width='100%' placeContent='space-between' gap={8}>
<Stack maxW='min(100%, 768px)' sx={{ "*:first-of-type": { marginTop: '0 !important' } }}>
<Box maxW='min(100%, 768px)' sx={{ '*:first-of-type': { marginTop: '0 !important' } }}>
<ReactMarkdown
remarkPlugins={[gfm]}
rehypePlugins={[rehypeRaw]}
@ -124,9 +124,12 @@ const DocPage: NextPage<Props> = ({ frontmatter, content, navLinks, lastModified
>
{content}
</ReactMarkdown>
</Stack>
</Box>
<Stack display={{ base: 'none', xl: 'block' }} w="clamp(var(--chakra-sizes-40), 12.5%, var(--chakra-sizes-56))">
<Stack
display={{ base: 'none', xl: 'block' }}
w='clamp(var(--chakra-sizes-40), 12.5%, var(--chakra-sizes-56))'
>
<DocumentNav content={content} />
</Stack>
</Flex>

View File

@ -0,0 +1,7 @@
export const getKebabCaseFromName = (name: string): string =>
name
.replace(/[#]/g, '')
.trim()
.toLowerCase()
.replace(/ /g, '-')
.replace(/[^a-z0-9-]/g, '');

View File

@ -2,8 +2,9 @@ export { compareReleasesFn } from './compareReleasesFn';
export { fetchLatestReleaseCommit } from './fetchLatestReleaseCommit';
export { fetchLatestReleaseVersionAndName } from './fetchLatestReleaseVersionAndName';
export { fetchXMLData } from './fetchXMLData';
export { getLatestBinaryURL } from './getLatestBinaryURL';
export { getChecksum } from './getChecksum';
export { getKebabCaseFromName } from './getKebabCaseFromName';
export { getLatestBinaryURL } from './getLatestBinaryURL';
export { getParsedDate } from './getParsedDate';
export { getProgrammingLanguageName } from './getProgrammingLanguageName';
export { getReleaseArch } from './getReleaseArch';

View File

@ -1,18 +1,22 @@
const check = '{#';
import { getKebabCaseFromName } from './';
export const parseHeadingId = (children: string[]) => {
if (children[children.length - 1].includes(check)) {
const temp = children[children.length - 1].split(check);
const headingId = temp[temp.length - 1].split('}')[0];
children[children.length - 1] = temp[0];
const CHECK = '{#';
const lastChild = children[children.length - 1];
const split = lastChild.split(CHECK);
if (lastChild.includes(CHECK)) {
const headingId = split[split.length - 1].split('}')[0];
const newChildren = [...children];
newChildren[newChildren.length - 1] = split[0];
return {
children,
title: temp[0].replaceAll('#', ''),
children: newChildren,
title: split[0].replaceAll('#', ''),
headingId
};
}
return null;
return {
children,
title: split[0].replaceAll('#', ''),
headingId: getKebabCaseFromName(split[0])
};
};