Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support syntax highlighting and add additional CSS reset rules #15

Merged
merged 2 commits into from
Aug 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions app/components/CodeBlock/CodeBlock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react'
import Highlight, { defaultProps } from 'prism-react-renderer'

export default function CodeBlock({ children, className }) {
const language = className.replace(/language-/, '')

return (
<Highlight {...defaultProps} code={children.trim()} language={language}>
{({ className, style, tokens, getLineProps, getTokenProps }) => (
<pre className={className} style={{ ...style, padding: '20px' }}>
{tokens.map((line, i) => (
<div key={i} {...getLineProps({ line, key: i })}>
{line.map((token, key) => (
<span key={key} {...getTokenProps({ token, key })} />
))}
</div>
))}
</pre>
)}
</Highlight>
)
}
22 changes: 22 additions & 0 deletions app/components/CodeBlock/CodeBlock.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react'
import CodeBlock from './CodeBlock'

export default { title: 'CodeBlock' }

export const JS = () => (
<CodeBlock className='language-javascript'>
{`const a = doSomething()
const b = new Thing([
a, b, c
])`}
</CodeBlock>
)

export const CSS = () => (
<CodeBlock className='language-css'>
{`.foo {
color: red;
background: url('blah.jpg')
}`}
</CodeBlock>
)
9 changes: 9 additions & 0 deletions app/components/cssReset.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
export default function cssReset (felaRenderer) {
felaRenderer.renderStatic({
boxSizing: 'border-box',
fontSize: '16px',
fontFamily: 'sans-serif',
lineHeight: 1.5,
margin: 0
}, ':root')

felaRenderer.renderStatic({
boxSizing: 'inherit',
}, '*, *:before, *:after')

felaRenderer.renderStatic({
margin: 0
}, 'body')
}
8 changes: 8 additions & 0 deletions app/pages/example-post.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ import ExamplePostList from '../components/ExamplePostList/ExamplePostList'

---

```javascript
function example () {
console.log('Code syntax highlighting works too!')
}
```

---

Remember, components are only prerendered by default.

If you want to automatically [hydrate](https://reactjs.org/docs/react-dom.html#hydrate) a component on the client, you'll need to import a component wrapped with the `asIsland` higher order component.
Expand Down
59 changes: 29 additions & 30 deletions app/prerender.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,19 @@ import { createRenderer } from 'fela'
import { RendererProvider } from 'react-fela'
import { renderToMarkup } from 'fela-dom'
import { Helmet } from 'react-helmet'
import { MDXProvider } from '@mdx-js/react'
import cssReset from './components/cssReset'
import DefaultLayout from './layouts/DefaultLayout'
import CodeBlock from './components/CodeBlock/CodeBlock'

export default function prerender (manifest, mode) {
export default function prerender(manifest, mode) {
/*
1. Require every JS and MDX file in the `pages` directory and create a useful collection of 'page' objects.
(uses Webpack's context module API, see https://webpack.js.org/guides/dependency-management/)
*/
const pages = []
const req = require.context('./pages', true, /^(?!.*\/_).*(js|mdx)$/)
req.keys().forEach(sourceFilePath => {
req.keys().forEach((sourceFilePath) => {
const pageModule = req(sourceFilePath)
const sourceFile = path.parse(sourceFilePath)

Expand All @@ -52,7 +54,6 @@ export default function prerender (manifest, mode) {
const pageProps = { posts }
buildJSONFeedFile(pageProps)


/*
3. Build a HTML file for each page
*/
Expand All @@ -68,20 +69,13 @@ export default function prerender (manifest, mode) {
})
}

function collectPosts (pages) {
function collectPosts(pages) {
return pages
.filter((page) => page.meta && page.meta.collection === 'posts')
.sort((a, b) => new Date(b.meta.date) - new Date(a.meta.date))
}

function buildPageFile ({
PageComponent,
meta,
urlPath,
manifest,
mode,
pageProps = {}
}) {
function buildPageFile({ PageComponent, meta, urlPath, manifest, mode, pageProps = {} }) {
// 1. Create a Fela renderer to be provided for components in the page
const felaRenderer = createRenderer({
devMode: mode === 'development'
Expand All @@ -93,9 +87,16 @@ function buildPageFile ({
const Layout = meta.Layout || DefaultLayout
const bodyHTML = ReactDOMServer.renderToString(
<RendererProvider renderer={felaRenderer}>
<Layout meta={meta}>
<PageComponent {...pageProps} />
</Layout>
<MDXProvider
components={{
pre: (props) => <div {...props} />,
code: CodeBlock
}}
>
<Layout meta={meta}>
<PageComponent {...pageProps} />
</Layout>
</MDXProvider>
</RendererProvider>
)

Expand All @@ -114,23 +115,19 @@ function buildPageFile ({
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true })
const outputFilePath = `${outputDir}/index.html`

fs.writeFile(outputFilePath, renderedDocument, err => {
fs.writeFile(outputFilePath, renderedDocument, (err) => {
if (err) throw err
console.log(chalk.green(`🏝 Page built: ${outputFilePath}`))
})
}

// Get clean URLs by naming all HTML files `index.html` in a folder with the same name as the source file.
// (except source files called `index` - they can be output in place)
function cleanURLPathForPage (sourceFile) {
return path.join(
'/',
sourceFile.dir,
sourceFile.name === 'index' ? '' : sourceFile.name
)
function cleanURLPathForPage(sourceFile) {
return path.join('/', sourceFile.dir, sourceFile.name === 'index' ? '' : sourceFile.name)
}

function buildJSONFeedFile (pageProps) {
function buildJSONFeedFile(pageProps) {
const { siteURL, feedTitle } = packageJSON.tropical
const { posts } = pageProps

Expand All @@ -157,18 +154,13 @@ function buildJSONFeedFile (pageProps) {

const outputFilePath = path.resolve(__dirname, '../output/feed.json')

fs.writeFile(outputFilePath, JSON.stringify(feed), err => {
fs.writeFile(outputFilePath, JSON.stringify(feed), (err) => {
if (err) throw err
console.log(chalk.green(`🏝 JSON Feed built: ${outputFilePath}`))
})
}

function documentTemplate ({
stylesHTML,
bodyHTML,
helmet,
clientBundlePath
}) {
function documentTemplate({ stylesHTML, bodyHTML, helmet, clientBundlePath }) {
return `<!doctype html>
<html ${helmet.htmlAttributes.toString()}>
<head>
Expand All @@ -184,3 +176,10 @@ function documentTemplate ({
</html>
`
}

// By default prism-react-renderer only includes a subset of the languages Prism supports
// https://github.com/FormidableLabs/prism-react-renderer#faq
// Uncomment this to enable syntax highlighting for additional languages;
// import Prism from 'prism-react-renderer/prism'
// ;(typeof global !== 'undefined' ? global : window).Prism = Prism
// require('prismjs/components/prism-ruby')
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
"@babel/preset-env": "^7.8.4",
"@babel/preset-react": "^7.8.3",
"@mdx-js/loader": "^1.5.5",
"@mdx-js/react": "^1.6.16",
"@storybook/react": "^5.3.13",
"babel-loader": "^8.0.6",
"chalk": "^4.1.0",
"concurrently": "^5.1.0",
"fela": "^11.1.2",
"fela-dom": "^11.1.2",
"file-loader": "^6.0.0",
"prism-react-renderer": "^1.1.1",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-fela": "^11.1.2",
Expand Down
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,11 @@
resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.14.tgz#20c64d6691a894227cd04006b620e5fff85f79b1"
integrity sha512-WN4OWXiSTN5x1Ee0ZeYQ9bjjSSgH3Mfx/ezcSV3T691C/PcHTNWwJa5qhcuq8V/NrVAeMc26aXuSdOAq6sRb1g==

"@mdx-js/react@^1.6.16":
version "1.6.16"
resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.16.tgz#538eb14473194d0b3c54020cb230e426174315cd"
integrity sha512-+FhuSVOPo7+4fZaRwWuCSRUcZkJOkZu0rfAbBKvoCg1LWb1Td8Vzi0DTLORdSvgWNbU6+EL40HIgwTOs00x2Jw==

"@mdx-js/[email protected]":
version "1.6.14"
resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.14.tgz#e3c14aef1c721b79ca7afa4d54ed7b5817a973c7"
Expand Down Expand Up @@ -7233,6 +7238,11 @@ pretty-hrtime@^1.0.3:
resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=

prism-react-renderer@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.1.1.tgz#1c1be61b1eb9446a146ca7a50b7bcf36f2a70a44"
integrity sha512-MgMhSdHuHymNRqD6KM3eGS0PNqgK9q4QF5P0yoQQvpB6jNjeSAi3jcSAz0Sua/t9fa4xDOMar9HJbLa08gl9ug==

prismjs@^1.8.4:
version "1.20.0"
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.20.0.tgz#9b685fc480a3514ee7198eac6a3bf5024319ff03"
Expand Down