1
1
mirror of https://github.com/jxnblk/mdx-deck.git synced 2024-11-25 15:50:39 +03:00

Add base app

This commit is contained in:
Brent Jackson 2019-02-15 14:58:58 -05:00
parent 7123568fab
commit b7e3d1ec3f
13 changed files with 4172 additions and 4198 deletions

View File

@ -1,7 +0,0 @@
{
presets: [
'env',
'stage-0',
'react'
]
}

View File

@ -3,6 +3,8 @@
## Unreleased
- Simplified custom mdx loader, removing unused front-matter support
## v1.8.2 2018-12-04
- Bugfix for window check

View File

@ -1,3 +1,7 @@
module.exports = {
presets: ['env', 'react'],
presets: ['@babel/env', '@babel/react'],
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-export-namespace-from',
],
}

160
docs/__index.mdx Normal file
View File

@ -0,0 +1,160 @@
export { future as theme } from '../themes'
import { Head, Image, Notes, Appear } from '../dist'
import { Invert, Split, FullScreenCode, Horizontal} from '../layouts'
import Counter from './Counter'
import code from './code'
<Head>
<title>mdx-deck</title>
<meta name='twitter:card' content='summary_large_image' />
<meta name='twitter:site' content='@jxnblk' />
<meta name='twitter:title' content='mdx-deck' />
<meta name='twitter:description' content='MDX-based presentation decks' />
<meta name='twitter:image' content='https://jxnblk.com/mdx-deck/card.png' />
</Head>
# mdx-deck
MDX-based presention decks
---
# Presentation decks
---
# Built with [MDX][]
[MDX]: https://github.com/mdx-js/mdx
---
import Box from '@rebass/grid'
<Box
fontSize={3}
p={4}
bg='magenta'>
Import React components
</Box>
---
- Make bulleted lists
- To help make your point
---
## Getting Started
1. `npm i -D mdx-deck`
2. Write some markdown and JSX
3. Present
---
```jsx
<button>code example</button>
```
```notes
- These are speaker notes
- And they won't be rendered in your slide
```
---
```jsx
class extends React.Component {
render () {
return (
<React.Fragment>
<h1>Indented code</h1>
</React.Fragment>
)
}
}
```
---
> “Blockquotes are essential to any good presentation”
Anonymous
<Notes>
<ul>
<li>Speaker notes can also be</li>
<li>Written in JSX</li>
</ul>
</Notes>
---
### Appear
<ul>
<Appear>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
</Appear>
</ul>
---
<Image
src='https://source.unsplash.com/random/768x2048'
size='contain'
/>
```notes
Testing object fit
```
---
### Real React Components
<Counter />
---
<Image src='https://images.unsplash.com/photo-1462331940025-496dfbfc7564?w=2048&q=20' />
---
export default Split
![](https://images.unsplash.com/photo-1462331940025-496dfbfc7564?w=2048&q=20)
## Split Layout
---
export default Horizontal
![](https://source.unsplash.com/random/1024x768')
![](https://source.unsplash.com/random/1024x768')
### Horizontal Layout
---
export default Invert
# Invert Layout
---
export default FullScreenCode
```
<Button>
Beep
</Button>
```
---
![](https://images.unsplash.com/photo-1462331940025-496dfbfc7564?w=2048&h=1024&q=20&fit=crop)
Inline image
---
Prop | Type | Description
---|---|---
`width` | number, string, or array | sets element width
`color` | string | sets foreground color
`bg` | string | sets background color
---
export default Invert
# Get started :sunglasses:
[GitHub](https://github.com/jxnblk/mdx-deck)

View File

@ -1,160 +1,10 @@
export { future as theme } from '../themes'
import { Head, Image, Notes, Appear } from '../dist'
import { Invert, Split, FullScreenCode, Horizontal} from '../layouts'
import Counter from './Counter'
import code from './code'
<Head>
<title>mdx-deck</title>
<meta name='twitter:card' content='summary_large_image' />
<meta name='twitter:site' content='@jxnblk' />
<meta name='twitter:title' content='mdx-deck' />
<meta name='twitter:description' content='MDX-based presentation decks' />
<meta name='twitter:image' content='https://jxnblk.com/mdx-deck/card.png' />
</Head>
# mdx-deck
MDX-based presention decks
---
# Presentation decks
---
# Built with [MDX][]
[MDX]: https://github.com/mdx-js/mdx
---
import Box from 'superbox'
<Box
fontSize={3}
p={4}
bg='magenta'>
Import React components
</Box>
---
- Make bulleted lists
- To help make your point
# Hello MDX Deck
---
## Getting Started
1. `npm i -D mdx-deck`
2. Write some markdown and JSX
3. Present
## This is v2
---
```jsx
<button>code example</button>
```
```notes
- These are speaker notes
- And they won't be rendered in your slide
```
---
```jsx
class extends React.Component {
render () {
return (
<React.Fragment>
<h1>Indented code</h1>
</React.Fragment>
)
}
}
```
---
> “Blockquotes are essential to any good presentation”
Anonymous
<Notes>
<ul>
<li>Speaker notes can also be</li>
<li>Written in JSX</li>
</ul>
</Notes>
---
### Appear
<ul>
<Appear>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
</Appear>
</ul>
---
<Image
src='https://source.unsplash.com/random/768x2048'
size='contain'
/>
```notes
Testing object fit
```
---
### Real React Components
<Counter />
---
<Image src='https://images.unsplash.com/photo-1462331940025-496dfbfc7564?w=2048&q=20' />
---
export default Split
![](https://images.unsplash.com/photo-1462331940025-496dfbfc7564?w=2048&q=20)
## Split Layout
---
export default Horizontal
![](https://source.unsplash.com/random/1024x768')
![](https://source.unsplash.com/random/1024x768')
### Horizontal Layout
---
export default Invert
# Invert Layout
---
export default FullScreenCode
```
<Button>
Beep
</Button>
```
---
![](https://images.unsplash.com/photo-1462331940025-496dfbfc7564?w=2048&h=1024&q=20&fit=crop)
Inline image
---
Prop | Type | Description
---|---|---
`width` | number, string, or array | sets element width
`color` | string | sets foreground color
`bg` | string | sets background color
---
export default Invert
# Get started :sunglasses:
[GitHub](https://github.com/jxnblk/mdx-deck)
## What's New

View File

@ -7,18 +7,16 @@ const merge = require('webpack-merge')
const chalk = require('chalk')
const remark = {
emoji: require('remark-emoji'),
unwrapImages: require('remark-unwrap-images')
unwrapImages: require('remark-unwrap-images'),
}
const babel = {
presets: [
'babel-preset-env',
'babel-preset-stage-0',
'babel-preset-react',
].map(require.resolve),
presets: ['@babel/preset-env', '@babel/preset-react'].map(require.resolve),
plugins: [
'babel-plugin-styled-components'
].map(require.resolve)
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-export-namespace-from',
'babel-plugin-styled-components',
].map(require.resolve),
}
const rules = [
@ -26,16 +24,14 @@ const rules = [
test: /\.js$/,
exclude: /node_modules/,
loader: require.resolve('babel-loader'),
options: babel
options: babel,
},
{
test: /\.js$/,
exclude: path.resolve(__dirname, '../node_modules'),
include: [
path.resolve(__dirname, '..'),
],
include: [path.resolve(__dirname, '..')],
loader: require.resolve('babel-loader'),
options: babel
options: babel,
},
{
test: /\.mdx?$/,
@ -43,19 +39,16 @@ const rules = [
use: [
{
loader: require.resolve('babel-loader'),
options: babel
options: babel,
},
{
loader: require.resolve('./loader.js'),
options: {
mdPlugins: [
remark.emoji,
remark.unwrapImages
]
}
}
]
}
mdPlugins: [remark.emoji, remark.unwrapImages],
},
},
],
},
]
const template = ({
@ -63,7 +56,7 @@ const template = ({
css = '',
body = '',
js,
publicPath
publicPath,
}) => `<!DOCTYPE html>
<html>
<head>
@ -84,16 +77,16 @@ const baseConfig = {
stats: 'errors-only',
mode: 'development',
module: {
rules
rules,
},
resolve: {
alias: {
'mdx-deck': path.resolve(__dirname, '..')
'mdx-deck': path.resolve(__dirname, '..'),
},
modules: [
path.relative(process.cwd(), path.join(__dirname, '../node_modules')),
'node_modules'
]
'node_modules',
],
},
plugins: [
new ProgressBarPlugin({
@ -107,8 +100,8 @@ const baseConfig = {
].join(' '),
summary: false,
customSummary: () => {},
})
]
}),
],
}
const createConfig = (opts = {}) => {
@ -120,14 +113,12 @@ const createConfig = (opts = {}) => {
path.join(opts.dirname, 'node_modules')
)
config.entry = [
path.join(__dirname, '../dist/entry.js')
]
config.entry = [path.join(__dirname, '../dist/entry.js')]
const defs = Object.assign({}, opts.globals, {
OPTIONS: JSON.stringify(opts),
HOT_PORT: JSON.stringify(opts.hotPort),
HOT_HOST: JSON.stringify(opts.host)
HOT_HOST: JSON.stringify(opts.host),
})
config.plugins.push(

View File

@ -14,6 +14,7 @@ module.exports = async function(src) {
.split(SLIDEREG)
.map(str => {
const code = mdx.sync(str, options)
console.log('CODE', code)
const lines = code.split('\n')
const tagIndex = lines.findIndex(str => /^</.test(str))
modules.push(...lines.slice(0, tagIndex).filter(Boolean))

7580
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -7,13 +7,12 @@
"mdx-deck": "./cli.js"
},
"scripts": {
"prepare": "npm run babel",
"babel": "babel src -d dist",
"prepare": "babel src -d dist",
"watch": "babel src -d dist --watch",
"start": "./cli.js docs/index.mdx -p 8080",
"build": "./cli.js build docs/index.mdx -d site",
"pdf": "./cli.js pdf docs/index.mdx -d site",
"screenshot": "./cli.js screenshot docs/index.mdx -d docs",
"__pdf": "./cli.js pdf docs/index.mdx -d site",
"__screenshot": "./cli.js screenshot docs/index.mdx -d docs",
"help": "./cli.js",
"test": "jest"
},
@ -22,27 +21,26 @@
"license": "MIT",
"repository": "github:jxnblk/mdx-deck",
"dependencies": {
"@compositor/webfont": "^1.0.39",
"@babel/core": "^7.2.2",
"@babel/plugin-proposal-export-namespace-from": "^7.2.0",
"@babel/preset-env": "^7.3.1",
"@babel/preset-react": "^7.0.0",
"@mdx-js/mdx": "^0.15.7",
"@mdx-js/tag": "^0.15.6",
"@reach/router": "^1.2.1",
"ansi-html": "0.0.7",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-plugin-styled-components": "1.8.0",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"chalk": "^2.4.1",
"babel-loader": "^8.0.5",
"babel-plugin-styled-components": "^1.10.0",
"chalk": "^2.4.2",
"clipboardy": "^1.2.3",
"find-up": "^3.0.0",
"get-port": "^4.0.0",
"gray-matter": "^4.0.1",
"get-port": "^4.1.0",
"hhmmss": "^1.0.0",
"html-entities": "^1.2.1",
"koa": "^2.6.2",
"koa": "^2.7.0",
"koa-static": "^5.0.0",
"koa-webpack": "^5.1.1",
"loader-utils": "^1.1.0",
"koa-webpack": "^5.2.1",
"loader-utils": "^1.2.3",
"lodash.debounce": "^4.0.8",
"lodash.get": "^4.4.2",
"meow": "^5.0.0",
@ -50,37 +48,36 @@
"mkdirp": "^0.5.1",
"normalize-newline": "^3.0.0",
"pkg-conf": "^2.1.0",
"progress-bar-webpack-plugin": "^1.11.0",
"prop-types": "^15.6.2",
"puppeteer": "^1.10.0",
"progress-bar-webpack-plugin": "^1.12.1",
"prop-types": "^15.7.2",
"querystring": "^0.2.0",
"react": "^16.6.1",
"react-dev-utils": "^6.1.1",
"react-dom": "^16.6.1",
"react-swipeable": "^4.3.0",
"react-syntax-highlighter": "^8.1.0",
"react": "^16.8.2",
"react-dev-utils": "^7.0.3",
"react-dom": "^16.8.2",
"react-swipeable": "^5.0.1",
"react-syntax-highlighter": "^10.1.2",
"remark-emoji": "^2.0.2",
"remark-unwrap-images": "^0.1.0",
"rimraf": "^2.6.2",
"stringify-object": "^3.3.0",
"styled-components": "^3.4.10",
"styled-system": "^3.1.11",
"superbox": "^2.1.0",
"webpack": "^4.25.1",
"rimraf": "^2.6.3",
"styled-components": "^4.1.3",
"styled-system": "^3.2.1",
"webpack": "^4.29.4",
"webpack-hot-client": "^4.1.1",
"webpack-merge": "^4.1.4",
"webpack-merge": "^4.2.1",
"webpack-node-externals": "^1.7.2"
},
"peerDependencies": {},
"devDependencies": {
"babel-cli": "^6.26.0",
"husky": "^1.1.3",
"jest": "^23.6.0",
"jest-styled-components": "^5.0.1",
"lint-staged": "^7.3.0",
"mdx-deck-code-surfer": "^0.4.1",
"prettier": "^1.15.2",
"react-test-renderer": "^16.6.1"
"@babel/cli": "^7.2.3",
"@babel/plugin-proposal-class-properties": "^7.3.0",
"@rebass/grid": "^6.0.0-7",
"husky": "^1.3.1",
"jest": "^24.1.0",
"jest-styled-components": "^6.3.1",
"lint-staged": "^8.1.4",
"mdx-deck-code-surfer": "^0.5.5",
"prettier": "^1.16.4",
"react-test-renderer": "^16.8.2"
},
"jest": {
"roots": [

View File

@ -4,47 +4,50 @@ import { withDeck } from './context'
import { setSteps } from './updaters'
import { modes } from './constants'
export default withDeck(class Appear extends React.Component {
static propTypes = {
children: PropTypes.node.isRequired,
deck: PropTypes.object.isRequired
}
export default withDeck(
class Appear extends React.Component {
// static propTypes = {
// children: PropTypes.node.isRequired,
// deck: PropTypes.object.isRequired
// }
constructor (props) {
super(props)
const { update, index } = props.deck
const steps = React.Children.toArray(props.children).length
update(setSteps(index, steps))
}
constructor(props) {
super(props)
const { update, index } = props.deck
const steps = React.Children.toArray(props.children).length
update(setSteps(index, steps))
}
render() {
const children = React.Children.toArray(this.props.children)
.map(child => typeof child === 'string'
? <div>{child}</div>
: child
render() {
const children = React.Children.toArray(this.props.children).map(child =>
typeof child === 'string' ? <div>{child}</div> : child
)
const { step, mode } = this.props.deck
const { step, mode } = this.props.deck
if (mode === modes.grid) {
return children
if (mode === modes.grid) {
return children
}
if (
typeof window !== 'undefined' &&
window.navigator.userAgent.includes('Print/PDF')
) {
return children
}
return (
<React.Fragment>
{children.map((child, i) =>
React.cloneElement(child, {
key: i,
style: {
...((child.props || {}).style || {}),
visibility: step >= i + 1 ? 'visible' : 'hidden',
},
})
)}
</React.Fragment>
)
}
if (typeof window !== 'undefined' && window.navigator.userAgent.includes('Print/PDF')) {
return children;
}
return (
<React.Fragment>
{children.map((child, i) => (
React.cloneElement(child, {
key: i,
style: {
...((child.props || {}).style || {}),
visibility: (step >= i + 1) ? 'visible' : 'hidden'
}
})
))}
</React.Fragment>
)
}
})
)

View File

@ -1,44 +1,47 @@
import React from 'react'
import PropTypes from 'prop-types'
import { withTheme } from 'styled-components'
import SyntaxHighlighter, { registerLanguage } from 'react-syntax-highlighter/prism-light'
import SyntaxHighlighter, {
registerLanguage,
} from 'react-syntax-highlighter/prism-light'
import defaultTheme from 'react-syntax-highlighter/styles/prism/atom-dark'
import javascript from 'react-syntax-highlighter/languages/prism/javascript'
import jsx from 'react-syntax-highlighter/languages/prism/jsx'
export default withTheme(class Code extends React.Component {
static propTypes = {
children: PropTypes.string,
className: PropTypes.string,
theme: PropTypes.object
}
export default withTheme(
class Code extends React.Component {
// static propTypes = {
// children: PropTypes.string,
// className: PropTypes.string,
// theme: PropTypes.object
// }
constructor(props) {
super(props)
registerLanguage('javascript', javascript)
registerLanguage('jsx', jsx)
if (props.theme && props.theme.prism && props.theme.prism.languages) {
const languages = props.theme.prism.languages
Object.keys(languages).forEach(key => {
registerLanguage(key, languages[key])
})
constructor(props) {
super(props)
registerLanguage('javascript', javascript)
registerLanguage('jsx', jsx)
if (props.theme && props.theme.prism && props.theme.prism.languages) {
const languages = props.theme.prism.languages
Object.keys(languages).forEach(key => {
registerLanguage(key, languages[key])
})
}
}
getLangauge = lang => {
return lang ? lang.replace('language-', '') : 'javascripts'
}
render() {
const { className, children, theme } = this.props
const language = this.getLangauge(className)
const style =
theme.prism && theme.prism.style ? theme.prism.style : defaultTheme
return (
<SyntaxHighlighter language={language} style={style}>
{children}
</SyntaxHighlighter>
)
}
}
getLangauge = (lang) => {
return lang ? lang.replace('language-', '') : 'javascripts'
}
render() {
const { className, children, theme } = this.props
const language = this.getLangauge(className)
const style = (theme.prism && theme.prism.style)
? theme.prism.style
: defaultTheme
return (
<SyntaxHighlighter language={language} style={style}>
{children}
</SyntaxHighlighter>
)
}
})
)

View File

@ -1,17 +1,15 @@
import React from 'react'
import { render } from 'react-dom'
import PropTypes from 'prop-types'
import SlideDeck from './SlideDeck'
import { MDXDeck } from './index'
const mod = require(FILENAME)
const slides = mod.default
const { theme, components, Provider } = mod
export default class App extends React.Component {
render () {
render() {
return (
<SlideDeck
{...this.props}
<MDXDeck
slides={slides}
theme={theme}
components={components}
@ -22,10 +20,7 @@ export default class App extends React.Component {
}
if (typeof document !== 'undefined') {
render(
<App />,
document.getElementById('root')
)
render(<App />, document.getElementById('root'))
}
if (module.hot) module.hot.accept()

View File

@ -1,3 +1,4 @@
/* v1 API
export { withDeck, withSlide } from './context'
export { Head } from './Head'
export { default as SlideDeck } from './SlideDeck'
@ -14,3 +15,163 @@ export * as themes from './themes'
// internals for third-party components
export * as updaters from './updaters'
export * as constants from './constants'
*/
import React from 'react'
import PropTypes from 'prop-types'
import { Router, globalHistory, navigate } from '@reach/router'
import styled, { ThemeProvider } from 'styled-components'
export const Context = React.createContext(null)
export const withContext = Component => props => (
<Context.Consumer
children={context => <Component {...props} context={context} />}
/>
)
const themed = key => props => props.theme[key]
// TODO check against v1 styles
const SlideRoot = styled.div(
{
display: 'flex',
flexDirection: 'column',
width: '100vw',
height: '100vh',
alignItems: 'center',
justifyContent: 'center',
},
themed('Slide')
)
const Slide = ({ children, ...props }) => (
<Context.Provider value={props}>
<SlideRoot>{children}</SlideRoot>
</Context.Provider>
)
export class MDXDeck extends React.Component {
constructor(props) {
super(props)
console.log(props.slides)
this.state = {
slides: props.slides,
step: 0,
}
}
handleKeyDown = ({ key }) => {
switch (key) {
case 'ArrowLeft':
this.previous()
break
case 'ArrowRight':
this.next()
break
}
}
getIndex = () => {
const { pathname } = globalHistory.location
return Number(pathname.split('/')[1] || 0)
}
getMeta = i => {
const { slides } = this.state
const { meta = {} } = slides[i] || {}
return meta
}
goto = i => {
const current = this.getIndex()
const reverse = i < current
navigate('/' + i)
const meta = this.getMeta(i)
this.setState({
step: reverse ? meta.steps || 0 : 0,
})
}
previous = () => {
const { slides, step } = this.state
const index = this.getIndex()
const meta = this.getMeta(index)
if (meta.steps && step > 0) {
this.setState(state => ({
step: state.step - 1,
}))
} else {
const previous = index - 1
if (previous < 0) return
this.goto(previous)
}
}
next = () => {
const { slides, step } = this.state
const index = this.getIndex()
const meta = this.getMeta(index)
if (meta.steps && step < meta.steps) {
this.setState(state => ({
step: state.step + 1,
}))
} else {
const next = index + 1
if (next > slides.length - 1) return
this.goto(next)
}
}
register = (index, meta) => {
const { slides } = this.state
slides[index].meta = meta
this.setState({ slides })
}
componentDidMount() {
document.body.addEventListener('keydown', this.handleKeyDown)
}
componentWillUnmount() {
document.body.removeEventListener('keydown', this.handleKeyDown)
}
render() {
const { slides } = this.state
const context = {
...this.state,
register: this.register,
}
const [FirstSlide] = slides
return (
<Router>
<Slide path="/" index={0} {...context}>
<FirstSlide path="/" />
</Slide>
{slides.map((Component, i) => (
<Slide key={i} path={i + '/*'} index={i} {...context}>
<Component path={i + '/*'} />
</Slide>
))}
</Router>
)
}
}
MDXDeck.propTypes = {
slides: PropTypes.array.isRequired,
theme: PropTypes.object.isRequired,
components: PropTypes.object,
Provider: PropTypes.func,
}
MDXDeck.defaultProps = {
slides: [],
theme: {},
}
// Additional API
// export const Appear