Merge pull request #43 from ethereum/markdown-styling

Markdown styling
pull/26459/head^2
Corwin Smith 2 years ago committed by GitHub
commit bc030df0ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      package.json
  2. 106
      src/components/MDXComponents.tsx
  3. 85
      src/components/UI/docs/Code.tsx
  4. 2
      src/components/docs/Breadcrumbs.tsx
  5. 3
      src/constants.ts
  6. 22
      src/pages/[...slug].tsx
  7. 7
      src/theme/foundations/fonts.ts
  8. 1
      src/theme/foundations/index.ts
  9. 81
      src/theme/foundations/textStyles.ts
  10. 12
      src/theme/index.ts
  11. 30
      src/utils/getProgrammingLanguageName.ts
  12. 1
      src/utils/index.ts
  13. 6669
      yarn.lock

@ -19,6 +19,7 @@
"@mdx-js/loader": "^2.1.3",
"@mdx-js/react": "^2.1.3",
"@next/mdx": "^12.3.0",
"chakra-ui-markdown-renderer": "^4.1.0",
"focus-visible": "^5.2.0",
"framer-motion": "^7.3.2",
"gray-matter": "^4.0.3",
@ -27,7 +28,8 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"react-markdown": "^8.0.3",
"react-syntax-highlighter": "^15.5.0"
"react-syntax-highlighter": "^15.5.0",
"remark-gfm": "^3.0.1"
},
"devDependencies": {
"@types/js-yaml": "^4.0.5",

@ -1,37 +1,26 @@
import { Heading, Link, Stack, Text } from '@chakra-ui/react';
import {
Flex,
Heading,
Link,
ListItem,
OrderedList,
Stack,
Table,
Text,
UnorderedList
} from '@chakra-ui/react';
import NextLink from 'next/link';
import { PrismLight as SyntaxHighlighter } from 'react-syntax-highlighter';
import { Code } from './UI/docs'
import { Code } from './UI/docs';
import { textStyles } from '../theme/foundations';
import bash from 'react-syntax-highlighter/dist/cjs/languages/prism/bash';
import go from 'react-syntax-highlighter/dist/cjs/languages/prism/go';
import graphql from 'react-syntax-highlighter/dist/cjs/languages/prism/graphql';
import java from 'react-syntax-highlighter/dist/cjs/languages/prism/java';
import javascript from 'react-syntax-highlighter/dist/cjs/languages/prism/javascript';
import json from 'react-syntax-highlighter/dist/cjs/languages/prism/json';
import python from 'react-syntax-highlighter/dist/cjs/languages/prism/python';
import sh from 'react-syntax-highlighter/dist/cjs/languages/prism/shell-session';
import solidity from 'react-syntax-highlighter/dist/cjs/languages/prism/solidity';
import swift from 'react-syntax-highlighter/dist/cjs/languages/prism/swift';
// syntax highlighting languages supported
SyntaxHighlighter.registerLanguage('bash', bash);
SyntaxHighlighter.registerLanguage('go', go);
SyntaxHighlighter.registerLanguage('graphql', graphql);
SyntaxHighlighter.registerLanguage('java', java);
SyntaxHighlighter.registerLanguage('javascript', javascript);
SyntaxHighlighter.registerLanguage('json', json);
SyntaxHighlighter.registerLanguage('python', python);
SyntaxHighlighter.registerLanguage('sh', sh);
SyntaxHighlighter.registerLanguage('solidity', solidity);
SyntaxHighlighter.registerLanguage('swift', swift);
const { header1, header2, header3, header4 } = textStyles;
const MDXComponents = {
// paragraphs
p: ({ children }: any) => {
return (
<Text mb={7} _last={{ mb: 0 }} size='sm' lineHeight={1.5}>
<Text mb={7} lineHeight={1.5}>
{children}
</Text>
);
@ -42,7 +31,7 @@ const MDXComponents = {
<NextLink href={href} passHref>
<Link
isExternal={href.startsWith('http') && !href.includes('geth.ethereum.org')}
color='primary'
variant='light'
>
{children}
</Link>
@ -52,64 +41,65 @@ const MDXComponents = {
// headings
h1: ({ children }: any) => {
return (
<Heading as='h1' textAlign='start' fontSize='4xl' mb={5}>
<Heading as='h1' textAlign='start' mb={5} {...header1}>
{children}
</Heading>
);
},
h2: ({ children }: any) => {
return (
<Heading as='h2' textAlign='start' fontSize='3xl' mb={4}>
<Heading as='h2' textAlign='start' mt='16 !important' mb={4} {...header2}>
{children}
</Heading>
);
},
h3: ({ children }: any) => {
return (
<Heading as='h3' fontSize='2xl' mt={5} mb={2.5}>
<Heading as='h3' mt={5} mb={2.5} {...header3}>
{children}
</Heading>
);
},
h4: ({ children }: any) => {
return (
<Heading as='h4' fontSize='lg' mb={2.5}>
<Heading as='h4' mb={2.5} {...header4}>
{children}
</Heading>
);
},
// tables
table: ({ children }: any) => (
<Flex maxW='min(100%, 100vw)' overflowX='scroll'>
<Table
variant='striped'
colorScheme='greenAlpha'
border='1px'
borderColor='blackAlpha.50'
my={6}
size={{ base: 'sm', lg: 'md' }}
w='auto'
>
{children}
</Table>
</Flex>
),
// pre
pre: ({ children }: any) => {
return (
pre: ({ children }: any) => (
<Stack mb={5}>
<pre>{children}</pre>
</Stack>
);
},
),
// code
code: (code: any) => {
return (
<Code code={code} />
)
// return !!code.inline ? (
// <Text
// as={'span'}
// padding='0.125em 0.25em'
// color='red.300'
// background='code-bg-contrast'
// borderRadius='0.25em'
// fontFamily='code'
// fontSize='sm'
// overflowY='scroll'
// >
// {code.children[0]}
// </Text>
// ) : (
// <Stack style={nightOwl}>
// {code.children[0]}
// </Stack>
// );
code: ({ children, ...props }: any) => <Code {...props}>{children}</Code>,
// list
ul: ({children}: any) => {
return <UnorderedList mb={7} px={4}>{children}</UnorderedList>
},
ol: ({children}: any) => {
return <OrderedList mb={7} px={4}>{children}</OrderedList>
},
li: ({ children }: any) => {
return <ListItem color='primary'>{children}</ListItem>
}
};

@ -1,38 +1,77 @@
// Libraries
import { Code as ChakraCode, Stack, Text } from '@chakra-ui/react';
import { FC } from 'react';
import { Code as ChakraCode, Stack, Text, useColorMode } from '@chakra-ui/react';
import { nightOwl, prism } from 'react-syntax-highlighter/dist/cjs/styles/prism';
import { PrismLight as SyntaxHighlighter } from 'react-syntax-highlighter';
// Constants, utilities
import { CLASSNAME_PREFIX } from '../../../constants';
import { getProgrammingLanguageName } from '../../../utils';
// Programming lang syntax highlighters
import bash from 'react-syntax-highlighter/dist/cjs/languages/prism/bash';
import go from 'react-syntax-highlighter/dist/cjs/languages/prism/go';
import graphql from 'react-syntax-highlighter/dist/cjs/languages/prism/graphql';
import java from 'react-syntax-highlighter/dist/cjs/languages/prism/java';
import javascript from 'react-syntax-highlighter/dist/cjs/languages/prism/javascript';
import json from 'react-syntax-highlighter/dist/cjs/languages/prism/json';
import python from 'react-syntax-highlighter/dist/cjs/languages/prism/python';
import sh from 'react-syntax-highlighter/dist/cjs/languages/prism/shell-session';
import solidity from 'react-syntax-highlighter/dist/cjs/languages/prism/solidity';
import swift from 'react-syntax-highlighter/dist/cjs/languages/prism/swift';
// syntax highlighting languages supported
SyntaxHighlighter.registerLanguage('bash', bash);
SyntaxHighlighter.registerLanguage('terminal', bash);
SyntaxHighlighter.registerLanguage('go', go);
SyntaxHighlighter.registerLanguage('graphql', graphql);
SyntaxHighlighter.registerLanguage('java', java);
SyntaxHighlighter.registerLanguage('javascript', javascript);
SyntaxHighlighter.registerLanguage('json', json);
SyntaxHighlighter.registerLanguage('python', python);
SyntaxHighlighter.registerLanguage('sh', sh);
SyntaxHighlighter.registerLanguage('solidity', solidity);
SyntaxHighlighter.registerLanguage('swift', swift);
interface Props {
code: any;
className: string;
children: string[];
inline?: boolean;
}
export const Code: FC<Props> = ({ code }) => {
export const Code: React.FC<Props> = ({ className, children, inline }) => {
const { colorMode } = useColorMode();
const isDark = colorMode === 'dark';
const isTerminal = className?.includes('terminal');
const [content] = children;
if (inline)
return (
!!code.inline ?
(
<Text
as='span'
background='code-bg'
px={1}
color='primary'
bg='code-bg'
borderRadius='0.25em'
textStyle='inline-code-snippet'
pb={2}
mb={-2}
>
{code.children[0]}
{content}
</Text>
)
:
(
);
if (isTerminal)
return (
<Stack>
<ChakraCode
overflow='auto'
p={6}
background='code-bg-contrast'
textStyle='code-block'
color='code-text'
>
{code.children[0]}
<ChakraCode overflow='auto' p={6} background='terminal-bg' color='terminal-text'>
{content}
</ChakraCode>
</Stack>
)
);
if (className?.startsWith(CLASSNAME_PREFIX))
return (
<SyntaxHighlighter
language={getProgrammingLanguageName(className)}
style={isDark ? nightOwl : prism}
customStyle={{ borderRadius: '0.5rem', padding: '1rem' }}
>
{content}
</SyntaxHighlighter>
);
return <Stack>{content}</Stack>;
};

@ -10,7 +10,7 @@ export const Breadcrumbs: FC = () => {
pathSplit = pathSplit.splice(1, pathSplit.length);
return (
<Breadcrumb mb={10}>
<Breadcrumb>
{pathSplit.map((path: string, idx: number) => {
return (
<BreadcrumbItem key={path}>

@ -104,3 +104,6 @@ export const WINDOWS_BINARY_BASE_URL =
export const LATEST_SOURCES_BASE_URL = 'https://github.com/ethereum/go-ethereum/archive/';
export const RELEASE_NOTES_BASE_URL = 'https://github.com/ethereum/go-ethereum/releases/tag/';
// Code snippet class constants
export const CLASSNAME_PREFIX = 'language-';

@ -1,14 +1,17 @@
import fs from 'fs';
import matter from 'gray-matter';
import yaml from 'js-yaml';
import { Stack, Heading } from '@chakra-ui/react';
import ChakraUIRenderer from 'chakra-ui-markdown-renderer';
import ReactMarkdown from 'react-markdown';
import { Heading, Stack } from '@chakra-ui/react';
import MDXComponents from '../components/';
import gfm from 'remark-gfm';
import { ParsedUrlQuery } from 'querystring';
import type { GetStaticPaths, GetStaticProps, NextPage } from 'next';
import { Breadcrumbs } from '../components/docs';
import MDXComponents from '../components/';
import { Breadcrumbs } from '../components/docs';
import { PageMetadata } from '../components/UI';
import { textStyles } from '../theme/foundations';
const MATTER_OPTIONS = {
engines: {
@ -76,13 +79,16 @@ const DocPage: NextPage<Props> = ({ frontmatter, content }) => {
<PageMetadata title={frontmatter.title} description={frontmatter.description} />
<main>
<Stack py={8} px={4}>
<Stack mb={16}>
<Breadcrumbs />
<Heading as='h1'>{frontmatter.title}</Heading>
<ReactMarkdown components={MDXComponents}>{content}</ReactMarkdown>
<Heading as='h1' mt='4 !important' mb={0} {...textStyles.header1}>
{frontmatter.title}
</Heading>
{/* <Text as='span' mt='0 !important'>last edited {TODO: get last edited date}</Text> */}
</Stack>
<ReactMarkdown remarkPlugins={[gfm]} components={ChakraUIRenderer(MDXComponents)}>
{content}
</ReactMarkdown>
</main>
</>
);

@ -0,0 +1,7 @@
export const fonts = {
// set base fonts as fallback
heading: '"JetBrains Mono", monospace',
button: '"JetBrains Mono", monospace',
code: '"JetBrains Mono", monospace',
body: '"Inter", sans-serif'
};

@ -1,5 +1,6 @@
export * from './colors';
export * from './config';
export * from './fonts';
export * from './shadows';
export * from './sizes';
export * from './textStyles';

@ -1,51 +1,88 @@
export const textStyles = {
h1: {
fontFamily: '"JetBrains Mono", monospace',
fontFamily: 'heading',
fontWeight: 700,
fontSize: '2.75rem',
lineHeight: '3.375rem',
letterSpacing: '5%',
letterSpacing: '0.05em',
color: 'body'
},
h2: {
fontFamily: '"JetBrains Mono", monospace',
fontFamily: 'heading',
fontWeight: 400,
fontSize: '1.5rem',
lineHeight: 'auto',
letterSpacing: '4%',
lineHeight: 'normal',
letterSpacing: '0.04em',
color: 'body'
},
header1: {
fontFamily: 'heading',
fontWeight: 700,
fontSize: { base: '1.875rem', md: '2.125rem' },
letterSpacing: '0.04em',
lineHeight: 'normal'
},
header2: {
fontFamily: 'heading',
fontSize: { base: '1.5rem', md: '1.75rem' },
letterSpacing: '0.04em',
lineHeight: 'normal'
},
header3: {
fontFamily: 'heading',
fontSize: { base: '1.25rem', md: '1.375rem' },
letterSpacing: '0.04em',
lineHeight: 'normal'
},
header4: {
fontFamily: 'heading',
fontSize: '1.125rem',
letterSpacing: '0.04em',
lineHeight: 'normal'
},
header5: {
fontFamily: 'heading',
fontSize: '1rem',
letterSpacing: '0.02em',
lineHeight: 'normal'
},
header6: {
fontFamily: 'heading',
fontSize: '0.875rem',
letterSpacing: '0.02em',
lineHeight: 'normal'
},
'header-font': {
fontFamily: '"JetBrains Mono", monospace',
fontFamily: 'heading',
fontWeight: 700,
fontSize: { base: '0.86rem', sm: '1rem' }
},
'homepage-description': {
fontFamily: '"JetBrains Mono", monospace',
fontFamily: 'heading',
fontWeight: 700,
lineHeight: '21px',
letterSpacing: '0.05em',
textAlign: { base: 'center', md: 'left' }
},
'homepage-primary-label': {
fontFamily: '"JetBrains Mono", monospace',
fontFamily: 'heading',
color: 'bg',
fontWeight: 700,
textTransform: 'uppercase'
},
'home-section-link-label': {
fontFamily: '"JetBrains Mono", monospace',
fontFamily: 'heading',
fontWeight: 700,
textTransform: 'uppercase',
textAlign: 'center',
p: 4
},
'quick-link-text': {
fontFamily: '"Inter", sans-serif',
fontFamily: 'body',
lineHeight: '26px'
},
'quick-link-label': {
fontFamily: '"JetBrains Mono", monospace',
fontFamily: 'heading',
fontWeight: 700,
textTransform: 'uppercase',
textAlign: 'center',
@ -56,35 +93,35 @@ export const textStyles = {
},
'hero-text-small': {
fontSize: '13px',
fontFamily: '"Inter", sans-serif'
fontFamily: 'body'
},
'footer-link-label': {
fontFamily: '"JetBrains Mono", monospace',
fontWeight: 700,
textTransform: 'uppercase',
lineHeight: '21.12px',
letterSpacing: '2%'
letterSpacing: '0.02em'
},
'footer-text': {
fontFamily: '"Inter", sans-serif',
fontFamily: 'body',
lineHeight: '22px',
fontWeight: 400,
fontSize: '12px'
},
'downloads-button-label': {
fontFamily: '"JetBrains Mono", monospace',
fontFamily: 'heading',
color: 'bg',
fontSize: { base: 'md', lg: 'xl' },
textTransform: 'uppercase'
},
'downloads-button-sublabel': {
fontFamily: '"JetBrains Mono", monospace',
fontFamily: 'heading',
color: 'bg',
fontSize: { base: 'xs', lg: 'sm' },
textTransform: 'uppercase'
},
'download-tab-label': {
fontFamily: '"JetBrains Mono", monospace',
fontFamily: 'heading',
fontWeight: 700,
textTransform: 'uppercase',
textAlign: 'center',
@ -93,7 +130,7 @@ export const textStyles = {
'header-button': {
fontFamily: '"JetBrains Mono", monospace',
fontWeight: 700,
fontSize: { base: '0.86rem', sm: '1rem' },
fontSize: { base: '0.86rem', sm: '1rem' }
},
'header-mobile-button': {
fontFamily: '"JetBrains Mono", monospace',
@ -101,18 +138,18 @@ export const textStyles = {
fontSize: '2xl'
},
'inline-code-snippet': {
fontFamily: '"JetBrains Mono", monospace',
fontFamily: 'heading',
fontWeight: 400,
fontSize: 'md',
lineHeight: 4,
letterSpacing: '1%'
letterSpacing: '0.01em'
},
'code-block': {
fontFamily: '"JetBrains Mono", monospace',
fontFamily: 'heading',
fontWeight: 400,
fontSize: 'md',
lineHeight: '21.12px',
letterSpacing: '1%'
letterSpacing: '0.01em'
},
// TODO: refactor w/ semantic tokens for light/dark mode
'link-light': {},

@ -1,6 +1,6 @@
import { extendTheme } from '@chakra-ui/react';
import { config, colors, shadows, sizes, textStyles } from './foundations';
import { config, colors, fonts, shadows, sizes, textStyles } from './foundations';
import { Button, Link } from './components';
const overrides = {
@ -10,6 +10,7 @@ const overrides = {
Button,
Link
},
fonts,
shadows,
sizes,
styles: {
@ -17,6 +18,9 @@ const overrides = {
body: {
bg: 'bg',
transition: 'all 200ms linear !important'
},
code: {
fontFamily: 'code !important'
}
})
},
@ -28,9 +32,9 @@ const overrides = {
'button-bg': { _light: 'green.50', _dark: 'green.900' },
body: { _light: 'gray.800', _dark: 'yellow.50' },
'code-bg': { _light: 'gray.200', _dark: 'gray.700' },
'code-bg-contrast': { _light: 'gray.800', _dark: 'gray.900' },
'code-text': { _light: 'green.50', _dark: 'green.50' },
bg: { _light: 'yellow.50', _dark: 'gray.800' },
'terminal-bg': { _light: 'gray.800', _dark: 'gray.900' },
'terminal-text': { _light: 'green.50', _dark: 'green.200' },
bg: { _light: 'yellow.50', _dark: 'gray.800' }
}
}
};

@ -0,0 +1,30 @@
import { CLASSNAME_PREFIX } from '../constants';
const DEFAULT = 'bash';
const TERMINAL = 'terminal';
const JS = ['javascript', 'js', 'jsx', 'ts', 'tsx'];
const SH = ['sh', 'shell'];
const PY = ['python', 'py'];
const SOL = ['solidity', 'sol'];
const LANGS = [JS, SH, PY, SOL];
export const getProgrammingLanguageName = (code: string) => {
// If `code` argument matches any of the above, return the first value for the language
for (const lang of LANGS) {
if (lang.includes(code.toLowerCase())) return lang[0];
}
// Check if `code` argument starts with the CLASSNAME_PREFIX
const hasLanguageNameProperty = code.startsWith(CLASSNAME_PREFIX);
// If no matched so far, return default code formatting type
if (!hasLanguageNameProperty) return DEFAULT;
// `code` starts with the CLASSNAME_PREFIX, so we need to extract the language name
const newCode = code.replace(CLASSNAME_PREFIX, '').toLowerCase();
// If declared to be `terminal`, return the DEFAULT
if (newCode === TERMINAL) return DEFAULT;
// If `newCode` argument matches any of the above, return the first value for the language
for (const lang of LANGS) {
if (lang.includes(newCode.toLowerCase())) return lang[0];
}
// If no match from above, simply return the extracted language name
return newCode;
};

@ -0,0 +1 @@
export * from './getProgrammingLanguageName';

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save