1
1
mirror of https://github.com/primer/css.git synced 2025-01-03 11:41:59 +03:00

move outline (toc) logic out of _app.js

This commit is contained in:
Shawn Allen 2018-12-14 00:39:47 -05:00
parent 847726c593
commit 8907a7e95f
4 changed files with 62 additions and 52 deletions

View File

@ -4,6 +4,7 @@ import {MDXProvider} from '@mdx-js/tag'
import Head from 'next/head'
import {BaseStyles, Box, Flex, Link, theme} from '@primer/components'
import {Header, CodeExample, PackageHeader, SideNav, IndexHero} from '../src/components'
import getComponents from '../src/markdown'
import {rootPage} from '../src/utils'
import {CONTENT_MAX_WIDTH} from '../src/constants'
@ -27,23 +28,8 @@ export default class MyApp extends App {
const {Component, page} = this.props
const node = rootPage.first(node => node.path === pathname)
const {meta = {}, outline: getOutline = () => []} = node || {}
const components = {
// render links with our component
a: Link,
// render the outline for <p> tags with exactly the text "{:toc}"
p: ({children, ...rest}) => {
if (children === '{:toc}') {
return <TableOfContents outline={getOutline()} {...rest} />
} else {
return <p {...rest}>{children}</p>
}
},
// render code blocks with our wrapper around mdx-live
code: CodeExample,
pre: props => props.children
}
const {meta = {}} = node || {}
const components = getComponents(node)
return (
<BaseStyles style={{fontFamily: theme.fonts.normal}}>
@ -52,9 +38,7 @@ export default class MyApp extends App {
<title>Primer CSS{meta.title ? ` / ${meta.title}` : null}</title>
</Head>
<Header />
<Flex
flexDirection={['column', 'column', 'column', 'row-reverse']}
justifyContent="space-between">
<Flex flexDirection={['column', 'column', 'column', 'row-reverse']} justifyContent="space-between">
<Box width={['auto', 'auto', 'auto', '80%']}>
{meta.hero ? <IndexHero /> : null}
<Box color="gray.9" maxWidth={['auto', 'auto', 'auto', CONTENT_MAX_WIDTH]} px={6} mx="auto" my={6}>
@ -81,31 +65,3 @@ export default class MyApp extends App {
)
}
}
function TableOfContents({outline, ...rest}) {
if (outline && outline.length) {
return (
<Box is="details" mb={4}>
<summary>Table of contents</summary>
<List items={outline} {...rest} />
</Box>
)
}
return null
}
function List({items, ...rest}) {
if (items && items.length) {
return (
<ul {...rest}>
{items.map(item => (
<li key={item.id}>
<a href={`#${item.id}`}>{item.title}</a>
<List items={item.children} />
</li>
))}
</ul>
)
}
return null
}

View File

@ -1,3 +1,4 @@
import React from 'react'
import {withMDXLive} from 'mdx-live'
import HTMLtoJSX from 'html-2-jsx'
@ -10,7 +11,7 @@ const LiveEditor = withMDXLive('pre')
LiveEditor.defaultProps = {
// match ```html and ```jsx fenced code blocks, with or without "."
match: /\blanguage\-\.?(html|jsx)\b/
match: /\blanguage-\.?(html|jsx)\b/
}
export default function CodeExample(props) {
@ -18,9 +19,7 @@ export default function CodeExample(props) {
// get children; we need to handle both and convert them to a single string
// that we can sanitize
const {unsafeInnerHTML, children, ...rest} = props
const html = unsafeInnerHTML
? unsafeInnerHTML.__html
: React.Children.toArray(children).join('\n')
const html = unsafeInnerHTML ? unsafeInnerHTML.__html : React.Children.toArray(children).join('\n')
const jsx = converter.convert(html)
return <LiveEditor {...rest}>{jsx}</LiveEditor>
}

29
docs/src/Outline.js Normal file
View File

@ -0,0 +1,29 @@
import {Box} from '@primer/components'
export default function Outline({outline, ...rest}) {
if (outline && outline.length) {
return (
<Box is="details" mb={4}>
<summary>Table of contents</summary>
<TOCList items={outline} {...rest} />
</Box>
)
}
return null
}
export function OutlineList({items, ...rest}) {
if (items && items.length) {
return (
<ul {...rest}>
{items.map(item => (
<li key={item.id}>
<a href={`#${item.id}`}>{item.title}</a>
<OutlineList items={item.children} />
</li>
))}
</ul>
)
}
return null
}

26
docs/src/markdown.js Normal file
View File

@ -0,0 +1,26 @@
import {Heading, Link} from '@primer/components'
import CodeExample from './CodeExample'
import Outline from './Outline'
export const H1 = props => <Heading fontSize={6} fontWeight="light" {...props} />
export default function getComponents(page = {}) {
const {outline: getOutline = () => []} = page
return {
h1: H1,
// render links with our component
a: Link,
// render the outline for <p> tags with exactly the text "{:toc}"
p: ({children, ...rest}) => {
if (children === '{:toc}') {
return <Outline outline={getOutline()} {...rest} />
} else {
return <p {...rest}>{children}</p>
}
},
// render code blocks with our wrapper around mdx-live
code: CodeExample,
pre: props => props.children
}
}