mirror of
https://github.com/primer/css.git
synced 2025-01-05 12:57:32 +03:00
move outline (toc) logic out of _app.js
This commit is contained in:
parent
847726c593
commit
8907a7e95f
@ -4,6 +4,7 @@ import {MDXProvider} from '@mdx-js/tag'
|
|||||||
import Head from 'next/head'
|
import Head from 'next/head'
|
||||||
import {BaseStyles, Box, Flex, Link, theme} from '@primer/components'
|
import {BaseStyles, Box, Flex, Link, theme} from '@primer/components'
|
||||||
import {Header, CodeExample, PackageHeader, SideNav, IndexHero} from '../src/components'
|
import {Header, CodeExample, PackageHeader, SideNav, IndexHero} from '../src/components'
|
||||||
|
import getComponents from '../src/markdown'
|
||||||
import {rootPage} from '../src/utils'
|
import {rootPage} from '../src/utils'
|
||||||
import {CONTENT_MAX_WIDTH} from '../src/constants'
|
import {CONTENT_MAX_WIDTH} from '../src/constants'
|
||||||
|
|
||||||
@ -27,23 +28,8 @@ export default class MyApp extends App {
|
|||||||
const {Component, page} = this.props
|
const {Component, page} = this.props
|
||||||
|
|
||||||
const node = rootPage.first(node => node.path === pathname)
|
const node = rootPage.first(node => node.path === pathname)
|
||||||
const {meta = {}, outline: getOutline = () => []} = node || {}
|
const {meta = {}} = node || {}
|
||||||
|
const components = getComponents(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
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseStyles style={{fontFamily: theme.fonts.normal}}>
|
<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>
|
<title>Primer CSS{meta.title ? ` / ${meta.title}` : null}</title>
|
||||||
</Head>
|
</Head>
|
||||||
<Header />
|
<Header />
|
||||||
<Flex
|
<Flex flexDirection={['column', 'column', 'column', 'row-reverse']} justifyContent="space-between">
|
||||||
flexDirection={['column', 'column', 'column', 'row-reverse']}
|
|
||||||
justifyContent="space-between">
|
|
||||||
<Box width={['auto', 'auto', 'auto', '80%']}>
|
<Box width={['auto', 'auto', 'auto', '80%']}>
|
||||||
{meta.hero ? <IndexHero /> : null}
|
{meta.hero ? <IndexHero /> : null}
|
||||||
<Box color="gray.9" maxWidth={['auto', 'auto', 'auto', CONTENT_MAX_WIDTH]} px={6} mx="auto" my={6}>
|
<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
|
|
||||||
}
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import React from 'react'
|
||||||
import {withMDXLive} from 'mdx-live'
|
import {withMDXLive} from 'mdx-live'
|
||||||
import HTMLtoJSX from 'html-2-jsx'
|
import HTMLtoJSX from 'html-2-jsx'
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ const LiveEditor = withMDXLive('pre')
|
|||||||
|
|
||||||
LiveEditor.defaultProps = {
|
LiveEditor.defaultProps = {
|
||||||
// match ```html and ```jsx fenced code blocks, with or without "."
|
// 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) {
|
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
|
// get children; we need to handle both and convert them to a single string
|
||||||
// that we can sanitize
|
// that we can sanitize
|
||||||
const {unsafeInnerHTML, children, ...rest} = props
|
const {unsafeInnerHTML, children, ...rest} = props
|
||||||
const html = unsafeInnerHTML
|
const html = unsafeInnerHTML ? unsafeInnerHTML.__html : React.Children.toArray(children).join('\n')
|
||||||
? unsafeInnerHTML.__html
|
|
||||||
: React.Children.toArray(children).join('\n')
|
|
||||||
const jsx = converter.convert(html)
|
const jsx = converter.convert(html)
|
||||||
return <LiveEditor {...rest}>{jsx}</LiveEditor>
|
return <LiveEditor {...rest}>{jsx}</LiveEditor>
|
||||||
}
|
}
|
||||||
|
29
docs/src/Outline.js
Normal file
29
docs/src/Outline.js
Normal 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
26
docs/src/markdown.js
Normal 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
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user