Use Remark for Markdown Parsing (#12)

* Use remark for parsing markdown, enable local image embedding

* Support loading multiple markdown files

Closes #13
This commit is contained in:
Frank Murphy 2019-02-21 16:38:03 -05:00 committed by Fabian Schultz
parent c7027370ba
commit fd74d235f3
11 changed files with 3135 additions and 188 deletions

View File

@ -38,7 +38,12 @@ $ yarn build
## Writing
###### [src/slides.md](src/slides.md)
By default, use [src/slides/](src/slides/).
Markdown files are loaded in sorted path order. Slides are generated by
splitting each markdown file along `<hr/>` elements (`---` in Markdown lingo).
Examples:
```md
# This is the first slide
@ -53,3 +58,4 @@ $ yarn build
## Author
- Fabian Schultz ([@fschultz\_](https://twitter.com/fschultz_))
- Frank Murphy ([AnIrishDuck](https://github.com/AnIrishDuck))

View File

@ -12,8 +12,27 @@ module.exports = {
resolve: `gatsby-source-filesystem`,
options: {
name: `slides`,
path: `${__dirname}/src`,
path: `${__dirname}/src/slides`,
},
},
{
resolve: `gatsby-transformer-remark`,
options: {
plugins: [
`gatsby-remark-copy-images`,
{
resolve: `gatsby-remark-images`,
options: {
// It's important to specify the maxWidth (in pixels) of
// the content container as this plugin uses this as the
// base for generating different widths of each image.
maxWidth: 1920,
},
},
],
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
],
};

View File

@ -1,56 +1,10 @@
const path = require('path');
const { createFilePath } = require('gatsby-source-filesystem')
const remark = require('remark');
const recommended = require('remark-preset-lint-recommended');
const html = require('remark-html');
const crypto = require('crypto');
exports.onCreateNode = ({
node,
actions,
loadNodeContent,
createNodeId,
reporter,
}) => {
const { createNode } = actions;
if (
node.internal.mediaType !== `text/markdown` &&
node.internal.mediaType !== `text/x-markdown`
) {
return;
}
return new Promise(async (resolve, reject) => {
const content = await loadNodeContent(node);
const slides = content.split('---\n').map(body => body.trim());
slides.forEach((slide, index) => {
remark()
.use(recommended)
.use(html)
.process(slide, (err, file) => {
const digest = crypto
.createHash(`md5`)
.update(String(file))
.digest(`hex`);
createNode({
id: createNodeId(`${node.id}_${index + 1} >>> Slide`),
parent: node.id,
children: [],
internal: {
type: `Slide`,
contentDigest: digest,
},
html: String(file),
index: index + 1,
});
});
});
resolve();
});
};
const _ = require('lodash')
// Remove trailing slash
exports.onCreatePage = ({ page, actions }) => {
@ -74,15 +28,16 @@ exports.onCreatePage = ({ page, actions }) => {
};
// Create pages from markdown nodes
exports.createPages = ({ actions, graphql }) => {
const { createPage } = actions;
exports.createPages = ({ actions, createNodeId, graphql }) => {
const { createPage, createNode } = actions;
const blogPostTemplate = path.resolve(`src/templates/slide.js`);
return graphql(`
{
allSlide {
allMarkdownRemark {
edges {
node {
fileAbsolutePath,
html
}
}
@ -93,9 +48,32 @@ exports.createPages = ({ actions, graphql }) => {
return Promise.reject(result.errors);
}
const slides = result.data.allSlide.edges;
const slides = result.data.allMarkdownRemark.edges;
slides.sort((a, b) => a.node.fileAbsolutePath > b.node.fileAbsolutePath ? 1 : -1)
const nodes = slides.flatMap((s) => s.node.html.split('<hr>').map((html) => ({
node: s.node, html
})))
slides.forEach((slide, index) => {
nodes.forEach(({ node, html }, index) => {
const digest = crypto
.createHash(`md5`)
.update(html)
.digest(`hex`);
createNode({
id: createNodeId(`${node.id}_${index + 1} >>> Slide`),
parent: node.id,
children: [],
internal: {
type: `Slide`,
contentDigest: digest,
},
html: html,
index: index + 1,
});
})
nodes.forEach((slide, index) => {
createPage({
path: `/${index + 1}`,
component: blogPostTemplate,

View File

@ -4,11 +4,18 @@
"version": "2.0.0",
"author": "Fabian Schultz <desk@fabianschultz.com>",
"dependencies": {
"gatsby": "^2.0.4",
"gatsby": "^2.0.33",
"gatsby-plugin-layout": "^1.0.1",
"gatsby-plugin-offline": "^2.0.5",
"gatsby-plugin-react-helmet": "^3.0.0",
"gatsby-plugin-sharp": "^2.0.14",
"gatsby-remark-copy-images": "^0.2.1",
"gatsby-remark-copy-linked-files": "^2.0.7",
"gatsby-remark-images": "^3.0.1",
"gatsby-remark-relative-images": "^0.2.1",
"gatsby-source-filesystem": "^2.0.1",
"gatsby-transformer-remark": "^2.1.15",
"gatsby-transformer-sharp": "^2.1.9",
"react": "^16.5.1",
"react-dom": "^16.5.1",
"react-helmet": "^5.2.0",

View File

@ -50,6 +50,11 @@ html {
-webkit-overflow-scrolling: touch;
}
#slide ul {
text-align: left;
margin-left: 32px;
}
a {
color: var(--text);

View File

@ -71,7 +71,7 @@ class TemplateWrapper extends Component {
onSwipedRight={this.swipeRight}
>
<Transition location={location}>
<div id="slide">{children}</div>
<div id="slide" style={{'width': '100%'}}>{children}</div>
</Transition>
</Swipeable>
</div>

View File

@ -4,7 +4,7 @@ Create presentations using Gatsby & React.
---
> Inscrutable icons litter the face of the devices even though the research
> Inscrutable icons litter the face of the devices even though the research
> community has long demonstrated that people cannot remember the meaning of
> more than a small number of icons […] Who can remember what each icon
> means? Not me.
@ -23,12 +23,3 @@ Here's the source of the first slide:
# Gatsby Deck
Create presentations using Gatsby & React.
---
![Monkey](//i.imgur.com/PnbINJ6.gif)
🌟 Star it on [GitHub](//github.com/fabe/gatsby-deck),
or create your own with:
gatsby new my-slides https://github.com/fabe/gatsby-starter-deck

14
src/slides/02-outro.md Normal file
View File

@ -0,0 +1,14 @@
Images can be embedded from the local filesystem!
![xkcd on standards](./standards.png)
(attribution: xkcd.com)
---
![Monkey](//i.imgur.com/PnbINJ6.gif)
🌟 Star it on [GitHub](//github.com/fabe/gatsby-deck),
or create your own with:
gatsby new my-slides https://github.com/fabe/gatsby-starter-deck

BIN
src/slides/standards.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -2,7 +2,7 @@ import React from 'react';
import { graphql } from 'gatsby';
export default ({ data, transition }) => (
<div>
<div style={{'width': '100%'}}>
<div
style={transition && transition.style}
dangerouslySetInnerHTML={{ __html: data.slide.html }}

3167
yarn.lock

File diff suppressed because it is too large Load Diff