From de4490bacdb4b07a27f66adbd29571a2585633f4 Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Tue, 19 Jun 2018 10:45:17 -0400 Subject: [PATCH 01/53] Adjust loader config and add fm loader --- docs/_app.js | 58 ------------------------------ docs/index.js | 70 ------------------------------------ docs/webpack.config.js | 23 ------------ lib/config.js | 27 +++++++++----- lib/entry.js | 2 +- lib/mdx-fm-loader.js | 13 +++++++ package.json | 35 +++++++++--------- src/LiveEditor.js | 73 ++++++++++++++++++++++++++++++++++++++ src/ScopeProvider.js | 20 +++++++++++ src/index.js | 3 ++ src/scope.js | 80 ++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 228 insertions(+), 176 deletions(-) delete mode 100644 docs/_app.js delete mode 100644 docs/index.js delete mode 100644 docs/webpack.config.js create mode 100644 lib/mdx-fm-loader.js create mode 100644 src/LiveEditor.js create mode 100644 src/ScopeProvider.js create mode 100644 src/index.js create mode 100644 src/scope.js diff --git a/docs/_app.js b/docs/_app.js deleted file mode 100644 index e6aca89..0000000 --- a/docs/_app.js +++ /dev/null @@ -1,58 +0,0 @@ -import React from 'react' -import { - Provider, - Flex, - Box, - Container, - Text, - Caps, - BlockLink, -} from 'rebass' -import { Link } from 'react-router-dom' -import { Logo } from '@compositor/logo' -import theme from './theme' - -export default ({ render }) => - - - - - - - Compositor - - - - - - - x0 - - - - - GitHub - - - - {render()} - - - - - GitHub - - - - - Compositor - - - - - © 2018 Compositor, Inc. All rights reserved - - - - diff --git a/docs/index.js b/docs/index.js deleted file mode 100644 index 52d8dc5..0000000 --- a/docs/index.js +++ /dev/null @@ -1,70 +0,0 @@ -import React from 'react' -import { Link } from 'react-router-dom' -import styled from 'styled-components' -import { - Container, - Box, - Flex, - Caps, - Heading, - Text, - Button, - Pre, -} from 'rebass' -import { Logo } from '@compositor/logo' - -const Video = styled.video([], { - display: 'block', - maxWidth: '100%', - height: 'auto', - borderRadius: '16px', -}) - -export default class extends React.Component { - render () { - return ( - - - - x0: Zero-config React development environment & static site generator - - - -
npm i -g @compositor/x0
- - - - - -
-
- ) - } -} diff --git a/docs/webpack.config.js b/docs/webpack.config.js deleted file mode 100644 index 9718488..0000000 --- a/docs/webpack.config.js +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = { - module: { - rules: [ - { - test: /\.md$/, - use: [ - // 'raw-loader' - { - loader: 'babel-loader', - options: { - presets: [ - 'env', - 'stage-0', - 'react' - ] - } - }, - '@compositor/md-loader' - ] - } - ] - } -} diff --git a/lib/config.js b/lib/config.js index 04dafb0..f642bd3 100644 --- a/lib/config.js +++ b/lib/config.js @@ -1,5 +1,12 @@ const path = require('path') +const remark = { + images: require('remark-images'), + emoji: require('remark-emoji'), + slug: require('remark-slug'), + autolinkHeadings: require('remark-autolink-headings'), +} + const babel = { presets: [ 'babel-preset-env', @@ -27,20 +34,24 @@ const rules = [ options: babel }, { - test: /\.jsx$/, - loader: require.resolve('@compositor/jsx-loader'), - options: {} - }, - { - test: /\.mdx$/, + test: /\.(md|mdx|jsx)$/, use: [ { loader: require.resolve('babel-loader'), options: babel }, { - loader: require.resolve('@mdx-js/loader') - } + loader: require.resolve('@mdx-js/loader'), + options: { + mdPlugins: [ + remark.slug, + remark.autolinkHeadings, + remark.images, + remark.emoji, + ] + } + }, + path.join(__dirname, './mdx-fm-loader'), ] } ] diff --git a/lib/entry.js b/lib/entry.js index 41eb723..8ab4f23 100644 --- a/lib/entry.js +++ b/lib/entry.js @@ -11,7 +11,7 @@ import { } from 'react-router-dom' const IS_CLIENT = typeof document !== 'undefined' -const req = require.context(DIRNAME, false, /\.(js|mdx|jsx)$/) +const req = require.context(DIRNAME, false, /\.(js|md|mdx|jsx)$/) const { filename, basename = '', disableScroll } = OPTIONS const index = filename ? path.basename(filename, path.extname(filename)) : 'index' diff --git a/lib/mdx-fm-loader.js b/lib/mdx-fm-loader.js new file mode 100644 index 0000000..28a04c6 --- /dev/null +++ b/lib/mdx-fm-loader.js @@ -0,0 +1,13 @@ +// front-matter loader for mdx +const matter = require('gray-matter') +const stringifyObject = require('stringify-object') + +module.exports = async function (src) { + const callback = this.async() + const { content, data } = matter(src) + + const code = `export const frontMatter = ${stringifyObject(data)} +${content} + ` + return callback(null, code) +} diff --git a/package.json b/package.json index e37f89e..d215d6c 100644 --- a/package.json +++ b/package.json @@ -27,13 +27,12 @@ "author": "Brent Jackson", "license": "MIT", "dependencies": { - "@compositor/jsx-loader": "^1.0.0-4", "@compositor/log": "^1.0.0-0", - "@mdx-js/loader": "^0.9.0", - "@mdx-js/mdx": "^0.9.0", + "@mdx-js/loader": "^0.11.0", + "@mdx-js/mdx": "^0.10.1", "babel-core": "^6.26.3", "babel-loader": "^7.1.4", - "babel-plugin-macros": "^2.2.1", + "babel-plugin-macros": "^2.2.2", "babel-plugin-transform-runtime": "^6.23.0", "babel-preset-env": "^1.7.0", "babel-preset-react": "^6.24.1", @@ -42,8 +41,8 @@ "chalk": "^2.4.1", "clipboardy": "^1.2.3", "connect-history-api-fallback": "^1.5.0", - "emotion": "^9.1.3", - "emotion-server": "^9.1.3", + "emotion": "^9.2.3", + "emotion-server": "^9.2.3", "find-up": "^2.1.0", "fs-extra": "^6.0.1", "glamor": "^2.20.40", @@ -52,31 +51,35 @@ "meow": "^5.0.0", "mini-html-webpack-plugin": "^0.2.3", "pkg-conf": "^2.1.0", - "react": "^16.4.0", + "react": "^16.4.1", "react-dev-utils": "^5.0.1", - "react-dom": "^16.4.0", - "react-router": "^4.2.0", - "react-router-dom": "^4.2.2", + "react-dom": "^16.4.1", + "react-router": "^4.3.1", + "react-router-dom": "^4.3.1", "read-pkg-up": "^3.0.0", + "remark-autolink-headings": "^5.0.0", + "remark-emoji": "^2.0.1", + "remark-images": "^0.8.1", + "remark-slug": "^5.0.0", "semver": "^5.5.0", "update-notifier": "^2.5.0", "webpack": "^4.10.2", - "webpack-merge": "^4.1.2", - "webpack-serve": "^1.0.2" + "webpack-merge": "^4.1.3", + "webpack-serve": "^1.0.4" }, "devDependencies": { - "@compositor/logo": "^1.3.5", + "@compositor/logo": "^1.4.0", "@compositor/md-loader": "^1.0.34", "ava": "^0.25.0", "isomorphic-fetch": "^2.2.1", "nano-style": "^1.0.0", "nyc": "^12.0.1", "raw-loader": "^0.5.1", - "rebass": "^2.0.0-2", + "rebass": "^2.0.0-7", "refunk": "^3.0.1", "rimraf": "^2.6.2", - "styled-components": "^3.3.0", - "styled-system": "^2.2.5" + "styled-components": "^3.3.2", + "styled-system": "^2.3.1" }, "x0": { "title": "Compositor x0", diff --git a/src/LiveEditor.js b/src/LiveEditor.js new file mode 100644 index 0000000..6ac3ac6 --- /dev/null +++ b/src/LiveEditor.js @@ -0,0 +1,73 @@ +import React from 'react' +import { + LiveProvider, + LivePreview, + LiveEditor, + LiveError +} from 'react-live' +import { ScopeConsumer } from 'react-scope-provider' +import { Box } from 'rebass' +import { color, borderColor } from 'styled-system' +import styled from 'styled-components' + +const transformCode = src => `${src}` + +const Preview = styled(LivePreview)([], { + padding: '16px', + border: '1px solid', + borderRadius: '2px 2px 0 0', +}, borderColor) +Preview.defaultProps = { + borderColor: 'gray' +} + +const Editor = styled(LiveEditor)([], { + fontFamily: 'Menlo, monospace', + fontSize: '13px', + margin: 0, + padding: '16px', + borderRadius: '0 0 2px 2px', + '&:focus': { + outline: 'none', + boxShadow: 'inset 0 0 0 1px #6cf', + } +}, color) +Editor.defaultProps = { + bg: 'gray' +} + +const Err = styled(LiveError)([], { + fontFamily: 'Menlo, monospace', + fontSize: '13px', + padding: '8px', + color: 'white', + backgroundColor: 'red' +}) + +export default ({ + code, + scope, + render +}) => ( + + + {scope => ( + + {typeof render === 'function' ? ( + render({ code, scope }) + ) : ( + + + + + + )} + + )} + + +) diff --git a/src/ScopeProvider.js b/src/ScopeProvider.js new file mode 100644 index 0000000..d302900 --- /dev/null +++ b/src/ScopeProvider.js @@ -0,0 +1,20 @@ +import React from 'react' +import { MDXProvider } from '@mdx-js/tag' +import { ScopeProvider } from 'react-scope-provider' +import defaultScope from './scope' + +export default props => { + const scope = { + ...defaultScope, + ...props.scope + } + return ( + + + + {props.children} + + + + ) +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..d59e3fc --- /dev/null +++ b/src/index.js @@ -0,0 +1,3 @@ +export { default as ScopeProvider } from './ScopeProvider' +export { default as LiveEditor } from './LiveEditor' +export { default as scope } from './scope' diff --git a/src/scope.js b/src/scope.js new file mode 100644 index 0000000..2257fb2 --- /dev/null +++ b/src/scope.js @@ -0,0 +1,80 @@ +import React from 'react' +import { withRouter, Link } from 'react-router-dom' +import rebassMarkdown from '@rebass/markdown' +import { Pre } from 'rebass' + +import LiveEditor from './LiveEditor' +import LivePreview from './LivePreview' + +const cleanHREF = href => href + .replace(/\.mdx?$/, '') + .replace(/\.jsx?$/, '') + +export const link = withRouter(({ + href, + match, + location, + children, + className, + ...props +}) => { + if (/^https?:\/\//.test(href) || /^#/.test(href)) { + return ( + + ) + } + const to = cleanHREF(href, location.pathname) + return ( + + ) +}) + +export const code = ({ + children, + className, + scope, + ...props +}) => { + const lang = className.replace(/^language\-/, '') + const type = lang.charAt(0) + const code = React.Children.toArray(children).join('\n') + + switch (type) { + case '.': + return + case '!': + return + default: + return ( +
+      )
+  }
+}
+
+const pre = props => props.children
+
+const scope = rebassMarkdown({
+  a: {
+    is: link
+  },
+  code: {
+    is: code
+  },
+  pre: {
+    is: pre,
+  }
+})
+
+export default scope

From cc49efa7e5f9bf1b5e39978c5d88c5de7904e915 Mon Sep 17 00:00:00 2001
From: Brent Jackson 
Date: Tue, 19 Jun 2018 10:54:44 -0400
Subject: [PATCH 02/53] Move docs around for development

---
 docs/__app.js      | 58 ++++++++++++++++++++++++++++++++++++++
 docs/beep.jsx      |  8 ++++++
 docs/components.md | 13 +++++++++
 docs/home.js       | 70 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 149 insertions(+)
 create mode 100644 docs/__app.js
 create mode 100644 docs/beep.jsx
 create mode 100644 docs/components.md
 create mode 100644 docs/home.js

diff --git a/docs/__app.js b/docs/__app.js
new file mode 100644
index 0000000..e6aca89
--- /dev/null
+++ b/docs/__app.js
@@ -0,0 +1,58 @@
+import React from 'react'
+import {
+  Provider,
+  Flex,
+  Box,
+  Container,
+  Text,
+  Caps,
+  BlockLink,
+} from 'rebass'
+import { Link } from 'react-router-dom'
+import { Logo } from '@compositor/logo'
+import theme from './theme'
+
+export default ({ render }) =>
+  
+    
+      
+        
+          
+          
+            Compositor
+          
+        
+      
+      
+      
+        
+          x0
+        
+      
+      
+        
+          GitHub
+        
+      
+    
+    {render()}
+    
+      
+        
+          
+            GitHub
+          
+        
+        
+          
+            Compositor
+          
+        
+        
+        
+          © 2018 Compositor, Inc. All rights reserved
+        
+      
+    
+  
diff --git a/docs/beep.jsx b/docs/beep.jsx
new file mode 100644
index 0000000..fde25c8
--- /dev/null
+++ b/docs/beep.jsx
@@ -0,0 +1,8 @@
+---
+title: Beep JSX
+---
+import { Box, Heading } from 'rebass'
+
+
+  Beep JSX
+
diff --git a/docs/components.md b/docs/components.md
new file mode 100644
index 0000000..07b9030
--- /dev/null
+++ b/docs/components.md
@@ -0,0 +1,13 @@
+---
+title: Components
+---
+
+# Components
+
+This is a standard markdown file.
+
+This is a live/editable code block:
+
+```.jsx
+

Hello

+``` diff --git a/docs/home.js b/docs/home.js new file mode 100644 index 0000000..52d8dc5 --- /dev/null +++ b/docs/home.js @@ -0,0 +1,70 @@ +import React from 'react' +import { Link } from 'react-router-dom' +import styled from 'styled-components' +import { + Container, + Box, + Flex, + Caps, + Heading, + Text, + Button, + Pre, +} from 'rebass' +import { Logo } from '@compositor/logo' + +const Video = styled.video([], { + display: 'block', + maxWidth: '100%', + height: 'auto', + borderRadius: '16px', +}) + +export default class extends React.Component { + render () { + return ( + + + + x0: Zero-config React development environment & static site generator + + + +
npm i -g @compositor/x0
+ + + + + +
+
+ ) + } +} From a1ddd164feeb777e21ce79e59676cb272df59cc8 Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Tue, 19 Jun 2018 11:00:22 -0400 Subject: [PATCH 03/53] Move files --- README.md | 13 +++++++++++++ lib/build.js | 4 ++-- lib/config.js | 2 +- lib/dev.js | 2 +- {lib => src}/entry.js | 1 + 5 files changed, 18 insertions(+), 4 deletions(-) rename {lib => src}/entry.js (99%) diff --git a/README.md b/README.md index b2922a6..6efa0c8 100644 --- a/README.md +++ b/README.md @@ -360,3 +360,16 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config) [react-loadable]: https://github.com/thejameskyle/react-loadable [webpack-merge]: https://github.com/survivejs/webpack-merge [webpack]: https://webpack.js.org + +--- + +## To Do + +**REMOVE BEFORE MERGING** + +- [ ] deep require context +- [ ] minimatch +- [ ] default route sorting +- [ ] markdown scope +- [ ] move client modules to src +- [ ] adjust resolve diff --git a/lib/build.js b/lib/build.js index e0e8665..4971fbf 100644 --- a/lib/build.js +++ b/lib/build.js @@ -18,7 +18,7 @@ const getApp = opts => { const config = merge(baseConfig, opts.webpack) config.mode = 'development' - config.entry = opts.entry || path.join(__dirname, './entry.js') + config.entry = opts.entry || path.join(__dirname, '../src/entry.js') config.output= { path: opts.tempdir, filename: 'App.js', @@ -191,7 +191,7 @@ module.exports = async (opts) => { if (opts.debug) { config.stats = 'verbose' } - config.entry = path.join(__dirname, './entry') + config.entry = path.join(__dirname, '../src/entry') config.output = { path: opts.outDir, filename: 'bundle.js', diff --git a/lib/config.js b/lib/config.js index f642bd3..7e062d5 100644 --- a/lib/config.js +++ b/lib/config.js @@ -29,7 +29,7 @@ const rules = [ { test: /\.js$/, exclude: path.resolve(__dirname, '../node_modules'), - include: path.resolve(__dirname), + include: path.resolve(__dirname, '..'), loader: require.resolve('babel-loader'), options: babel }, diff --git a/lib/dev.js b/lib/dev.js index c81c5ff..c454811 100644 --- a/lib/dev.js +++ b/lib/dev.js @@ -24,7 +24,7 @@ module.exports = async (opts) => { config.mode = 'development' config.context = opts.dirname - config.entry = opts.entry || path.join(__dirname, './entry') + config.entry = opts.entry || path.join(__dirname, '../src/entry') config.output = { path: path.join(process.cwd(), 'dev'), filename: 'dev.js', diff --git a/lib/entry.js b/src/entry.js similarity index 99% rename from lib/entry.js rename to src/entry.js index 8ab4f23..0606d3e 100644 --- a/lib/entry.js +++ b/src/entry.js @@ -1,3 +1,4 @@ +// Main application import path from 'path' import React from 'react' import { render, hydrate } from 'react-dom' From 74818b7066aab7926d972b7d960e8616d7f37b14 Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Tue, 19 Jun 2018 11:41:18 -0400 Subject: [PATCH 04/53] Add scope and matching --- README.md | 14 ++-- cli.js | 4 ++ docs/_app.js | 36 ++++++++++ docs/components.md | 2 +- docs/examples/Button.md | 6 ++ docs/examples/index.md | 2 + lib/build.js | 3 +- lib/dev.js | 1 + package.json | 7 +- src/Catch.js | 40 +++++++++++ src/FileList.js | 17 +++++ src/LivePreview.js | 30 ++++++++ src/ScrollTop.js | 22 ++++++ src/entry.js | 155 ++++++++++++++++------------------------ 14 files changed, 235 insertions(+), 104 deletions(-) create mode 100644 docs/_app.js create mode 100644 docs/examples/Button.md create mode 100644 docs/examples/index.md create mode 100644 src/Catch.js create mode 100644 src/FileList.js create mode 100644 src/LivePreview.js create mode 100644 src/ScrollTop.js diff --git a/README.md b/README.md index 6efa0c8..4d17554 100644 --- a/README.md +++ b/README.md @@ -367,9 +367,13 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config) **REMOVE BEFORE MERGING** -- [ ] deep require context -- [ ] minimatch -- [ ] default route sorting - [ ] markdown scope -- [ ] move client modules to src -- [ ] adjust resolve +- [ ] default route sorting +- [x] deep require context +- [ ] route dirname/full path +- [ ] minimatch +- [ ] pass front-matter as props +- [ ] props.Component in custom apps +- [x] move client modules to src +- [x] adjust resolve + diff --git a/cli.js b/cli.js index ed53b71..08a57de 100755 --- a/cli.js +++ b/cli.js @@ -28,6 +28,7 @@ const cli = meow(` ${chalk.gray('Options')} --webpack Path to webpack config file + --match String to match routes against using minimatch ${chalk.gray('Dev Server')} @@ -68,6 +69,9 @@ const cli = meow(` type: 'string', alias: 'c' }, + match: { + type: 'string' + }, scope: { type: 'string', }, diff --git a/docs/_app.js b/docs/_app.js new file mode 100644 index 0000000..bbe351d --- /dev/null +++ b/docs/_app.js @@ -0,0 +1,36 @@ +import React from 'react' +import * as scope from 'rebass' +import { ScopeProvider } from '../src' +import { + Flex, + Box, + Container, +} from 'rebass' + +export default class App extends React.Component { + static defaultProps = { + title: 'Hello' + } + + render () { + const { render } = this.props + console.log('custom app', this.props.routes) + + return ( + + + {false && ( + + custom app + + )} + + + {render()} + + + + + ) + } +} diff --git a/docs/components.md b/docs/components.md index 07b9030..0cbc221 100644 --- a/docs/components.md +++ b/docs/components.md @@ -9,5 +9,5 @@ This is a standard markdown file. This is a live/editable code block: ```.jsx -

Hello

+Hello ``` diff --git a/docs/examples/Button.md b/docs/examples/Button.md new file mode 100644 index 0000000..1a19a8f --- /dev/null +++ b/docs/examples/Button.md @@ -0,0 +1,6 @@ + +# Button + +```.jsx + +``` diff --git a/docs/examples/index.md b/docs/examples/index.md new file mode 100644 index 0000000..b0fe5b7 --- /dev/null +++ b/docs/examples/index.md @@ -0,0 +1,2 @@ + +# Examples diff --git a/lib/build.js b/lib/build.js index 4971fbf..c39a4e6 100644 --- a/lib/build.js +++ b/lib/build.js @@ -165,7 +165,8 @@ module.exports = async (opts) => { DEV: JSON.stringify(false), OPTIONS: JSON.stringify(opts), DIRNAME: JSON.stringify(opts.dirname), - APP: JSON.stringify(opts.app) + APP: JSON.stringify(opts.app), + MATCH: JSON.stringify(opts.match) }) ) diff --git a/lib/dev.js b/lib/dev.js index c454811..517a017 100644 --- a/lib/dev.js +++ b/lib/dev.js @@ -50,6 +50,7 @@ module.exports = async (opts) => { OPTIONS: JSON.stringify(opts), DIRNAME: JSON.stringify(opts.dirname), APP: JSON.stringify(opts.app), + MATCH: JSON.stringify(opts.match) }) ) diff --git a/package.json b/package.json index d215d6c..1249c85 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,8 @@ "@compositor/log": "^1.0.0-0", "@mdx-js/loader": "^0.11.0", "@mdx-js/mdx": "^0.10.1", + "@mdx-js/tag": "^0.11.0", + "@rebass/markdown": "^1.0.0-1", "babel-core": "^6.26.3", "babel-loader": "^7.1.4", "babel-plugin-macros": "^2.2.2", @@ -50,12 +52,14 @@ "koa-connect": "^2.0.1", "meow": "^5.0.0", "mini-html-webpack-plugin": "^0.2.3", + "minimatch": "^3.0.4", "pkg-conf": "^2.1.0", "react": "^16.4.1", "react-dev-utils": "^5.0.1", "react-dom": "^16.4.1", "react-router": "^4.3.1", "react-router-dom": "^4.3.1", + "react-scope-provider": "^1.0.0-1", "read-pkg-up": "^3.0.0", "remark-autolink-headings": "^5.0.0", "remark-emoji": "^2.0.1", @@ -69,13 +73,12 @@ }, "devDependencies": { "@compositor/logo": "^1.4.0", - "@compositor/md-loader": "^1.0.34", "ava": "^0.25.0", "isomorphic-fetch": "^2.2.1", "nano-style": "^1.0.0", "nyc": "^12.0.1", "raw-loader": "^0.5.1", - "rebass": "^2.0.0-7", + "rebass": "^2.0.0-6", "refunk": "^3.0.1", "rimraf": "^2.6.2", "styled-components": "^3.3.2", diff --git a/src/Catch.js b/src/Catch.js new file mode 100644 index 0000000..61091f0 --- /dev/null +++ b/src/Catch.js @@ -0,0 +1,40 @@ +import React from 'react' + +export default class Catch extends React.Component { + static getDerivedStateFromProps (props, state) { + if (!state.err) return null + return { err: null } + } + + state = { + err: null + } + + componentDidCatch (err) { + this.setState({ err }) + } + + render () { + const { err } = this.state + + if (err) { + return ( +
+      )
+    }
+
+    return this.props.children
+  }
+}
diff --git a/src/FileList.js b/src/FileList.js
new file mode 100644
index 0000000..5a58375
--- /dev/null
+++ b/src/FileList.js
@@ -0,0 +1,17 @@
+import React from 'react'
+import { Link } from 'react-router-dom'
+
+export default ({ routes = [] }) => (
+  
+    
{DIRNAME}
+
    + {routes.map(route => ( +
  • + + {route.name} + +
  • + ))} +
+
+) diff --git a/src/LivePreview.js b/src/LivePreview.js new file mode 100644 index 0000000..989b18f --- /dev/null +++ b/src/LivePreview.js @@ -0,0 +1,30 @@ +import React from 'react' +import { + LiveProvider, + LivePreview, + LiveError +} from 'react-live' +import { ScopeConsumer } from 'react-scope-provider' +import { Box } from 'rebass' + +const transformCode = str => `${str}` + +export default ({ + code, + scope +}) => ( + + + {scope => ( + + + + + )} + + +) diff --git a/src/ScrollTop.js b/src/ScrollTop.js new file mode 100644 index 0000000..72da1ff --- /dev/null +++ b/src/ScrollTop.js @@ -0,0 +1,22 @@ +import React from 'react' +import { withRouter } from 'react-router-dom' + +export default withRouter(class extends React.Component { + componentDidUpdate (prev) { + const { pathname, hash } = this.props.location + if (prev.location.pathname !== pathname) { + window.scrollTo(0, 0) + } + + // check performance of this + if (hash) { + const el = document.getElementById(hash.slice(1)) + if (!el) return + el.scrollIntoView() + } + } + + render () { + return false + } +}) diff --git a/src/entry.js b/src/entry.js index 0606d3e..9ecd4ae 100644 --- a/src/entry.js +++ b/src/entry.js @@ -10,44 +10,41 @@ import { Link, withRouter } from 'react-router-dom' +import minimatch from 'minimatch' + +import Catch from './Catch' +import ScopeProvider from './ScopeProvider' +import FileList from './FileList' +import ScrollTop from './ScrollTop' const IS_CLIENT = typeof document !== 'undefined' -const req = require.context(DIRNAME, false, /\.(js|md|mdx|jsx)$/) +const req = require.context(DIRNAME, true, /\.(js|md|mdx|jsx)$/) const { filename, basename = '', disableScroll } = OPTIONS const index = filename ? path.basename(filename, path.extname(filename)) : 'index' -const getComponents = req => req.keys().map(key => ({ - key, - name: path.basename(key, path.extname(key)), - module: req(key), - Component: req(key).default || req(key) -})) +req.keys().forEach(key => { + console.log(key, minimatch(key.replace(/^\.\//, ''), MATCH) ) +}) + +const getComponents = req => req.keys() + .filter(key => !MATCH || minimatch(key.replace(/^\.\//, ''), MATCH)) + .map(key => ({ + key, + name: path.basename(key, path.extname(key)), + module: req(key), + Component: req(key).default || req(key) + })) .filter(component => !/^(\.|_)/.test(component.name)) .filter(component => typeof component.Component === 'function') const initialComponents = getComponents(req) -const Index = ({ routes = [] }) => ( - -
{DIRNAME}
-
    - {routes.map(route => ( -
  • - - {route.name} - -
  • - ))} -
-
-) - const DefaultApp = ({ render, routes }) => ( {render()} ( - @@ -55,58 +52,8 @@ const DefaultApp = ({ render, routes }) => ( ) -class Catch extends React.Component { - static getDerivedStateFromProps (props, state) { - if (!state.err) return null - return { err: null } - } - - state = { - err: null - } - - componentDidCatch (err) { - this.setState({ err }) - } - - render () { - const { err } = this.state - - if (err) { - return ( -
-      )
-    }
-
-    return this.props.children
-  }
-}
-
-const ScrollTop = withRouter(class extends React.Component {
-  componentDidUpdate(prevProps) {
-    if (this.props.location.pathname !== prevProps.location.pathname) {
-      window.scrollTo(0, 0)
-    }
-  }
-  render () {
-    return false
-  }
-})
-
 const Router = IS_CLIENT ? BrowserRouter : StaticRouter
-const App = withRouter(APP ? (require(APP).default || require(APP)) : DefaultApp)
+const App = APP ? (require(APP).default || require(APP)) : DefaultApp
 
 export const getRoutes = async (components = initialComponents) => {
   const routes = await components.map(async ({ key, name, module, Component }) => {
@@ -129,19 +76,29 @@ export const getRoutes = async (components = initialComponents) => {
   return Promise.all(routes)
 }
 
+const RouterState = withRouter(({ render, ...props }) => {
+  const route = props.routes.find(r => r.path === props.location.pathname)
+  return render({ ...props, route })
+})
+
 export default class Root extends React.Component {
   static defaultProps = {
     path: '/',
     basename
   }
-  state = this.props
+  state = {
+    ...this.props,
+    ...App.defaultProps
+  }
 
   render () {
     const {
       routes,
       basename,
       path = '/'
-    } = this.state
+    } = this.props
+
+    console.log('App', App.defaultProps)
 
     return (
       
         
-          
-             (
-                routes.map(({ Component, ...route }) => (
-                   (
-                      
-                        
+            
+               (
+                   (
+                      routes.map(({ Component, ...route }) => (
+                         (
+                            
+                              
+                            
+                          )}
                         />
-                      
+                      ))
                     )}
                   />
-                ))
-              )}
-            />
-          
-          {!disableScroll && }
+                )}
+              />
+            
+            {!disableScroll && }
+          
         
       
     )

From 3f619382044d454bfe67a1be37498e2d1398a74c Mon Sep 17 00:00:00 2001
From: Brent Jackson 
Date: Tue, 19 Jun 2018 12:17:49 -0400
Subject: [PATCH 05/53] Support for nested routing

---
 README.md                    | 10 ++++----
 docs/_app.js                 | 18 ++++++++++----
 docs/_scope.js               | 46 ------------------------------------
 docs/components.md           |  6 +++++
 docs/dynamic.js              |  6 +++++
 docs/examples/index.md       |  2 ++
 docs/{docs.js => readme.js}  |  5 +---
 examples/jsx/pages/index.jsx |  3 ++-
 package.json                 |  2 +-
 src/entry.js                 | 24 +++++++++----------
 src/index.js                 |  4 ++++
 11 files changed, 53 insertions(+), 73 deletions(-)
 delete mode 100644 docs/_scope.js
 rename docs/{docs.js => readme.js} (84%)

diff --git a/README.md b/README.md
index 4d17554..525e3f4 100644
--- a/README.md
+++ b/README.md
@@ -367,13 +367,13 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config)
 
 **REMOVE BEFORE MERGING**
 
-- [ ] markdown scope
 - [ ] default route sorting
-- [x] deep require context
-- [ ] route dirname/full path
-- [ ] minimatch
-- [ ] pass front-matter as props
 - [ ] props.Component in custom apps
+- [x] route dirname/full path
+- [x] pass front-matter as props
+- [x] markdown scope
+- [x] deep require context
+- [x] minimatch
 - [x] move client modules to src
 - [x] adjust resolve
 
diff --git a/docs/_app.js b/docs/_app.js
index bbe351d..ed66031 100644
--- a/docs/_app.js
+++ b/docs/_app.js
@@ -1,5 +1,6 @@
 import React from 'react'
 import * as scope from 'rebass'
+import { Link } from 'react-router-dom'
 import { ScopeProvider } from '../src'
 import {
   Flex,
@@ -13,15 +14,24 @@ export default class App extends React.Component {
   }
 
   render () {
-    const { render } = this.props
-    console.log('custom app', this.props.routes)
+    const { routes, route, render } = this.props
+    console.log('custom app', routes)
+    console.log('route', route)
 
     return (
       
         
-          {false && (
+          {true && (
             
-              custom app
+              
    + {routes.map(route => ( +
  • + + {route.name} ({route.path}) + +
  • + ))} +
)} diff --git a/docs/_scope.js b/docs/_scope.js deleted file mode 100644 index dbf7edf..0000000 --- a/docs/_scope.js +++ /dev/null @@ -1,46 +0,0 @@ -import React from 'react' -import styled from 'styled-components' -import * as Rebass from 'rebass' -import { heading, link } from '@compositor/md' - -const Pre = styled(Rebass.Pre)({ - borderRadius: '8px' -}) - -export default { - ...Rebass, - h1: heading(props => - ), - h2: heading(props => - ), - h3: heading(props => - ), - a: link(props => - - ), - pre: props => -
-}
diff --git a/docs/components.md b/docs/components.md
index 0cbc221..9681060 100644
--- a/docs/components.md
+++ b/docs/components.md
@@ -1,6 +1,7 @@
 ---
 title: Components
 ---
+import { Box } from 'rebass'
 
 # Components
 
@@ -11,3 +12,8 @@ This is a live/editable code block:
 ```.jsx
 Hello
 ```
+
+---
+
+fm title: {frontMatter.title}
+
diff --git a/docs/dynamic.js b/docs/dynamic.js
index 3e76460..1d9e8a1 100644
--- a/docs/dynamic.js
+++ b/docs/dynamic.js
@@ -26,12 +26,18 @@ export default class extends React.Component {
   }
 
   render () {
+    const { match } = this.props
+
     return 
dynamic routing
Home Dynamic Routes Hello Hi + + {match.params.id && ( +

{match.params.id}

+ )}
} } diff --git a/docs/examples/index.md b/docs/examples/index.md index b0fe5b7..6ba417b 100644 --- a/docs/examples/index.md +++ b/docs/examples/index.md @@ -1,2 +1,4 @@ # Examples + +- [Button](Button.md) diff --git a/docs/docs.js b/docs/readme.js similarity index 84% rename from docs/docs.js rename to docs/readme.js index 4be4317..59157cc 100644 --- a/docs/docs.js +++ b/docs/readme.js @@ -4,7 +4,6 @@ import { } from 'rebass' import styled from 'styled-components' import Readme from '../README.md' -import scope from './_scope' const Prose = styled.div([], { '& img': { @@ -20,8 +19,6 @@ const Prose = styled.div([], { export default props => - + diff --git a/examples/jsx/pages/index.jsx b/examples/jsx/pages/index.jsx index 562ff3b..529f90e 100644 --- a/examples/jsx/pages/index.jsx +++ b/examples/jsx/pages/index.jsx @@ -1,7 +1,8 @@ --- title: Hello JSX -scope: import scope from './_scope' --- +import { Box, Heading, Text, Link } from 'rebass' + {props.title} diff --git a/package.json b/package.json index 1249c85..6a07c1d 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@compositor/x0", "version": "5.0.8", "description": "Zero-config React development environment and static site generator", - "main": "index.js", + "main": "src/index.js", "bin": { "x0": "cli.js" }, diff --git a/src/entry.js b/src/entry.js index 9ecd4ae..3bfc6c6 100644 --- a/src/entry.js +++ b/src/entry.js @@ -10,10 +10,10 @@ import { Link, withRouter } from 'react-router-dom' +import { Provider as RebassProvider } from 'rebass' import minimatch from 'minimatch' import Catch from './Catch' -import ScopeProvider from './ScopeProvider' import FileList from './FileList' import ScrollTop from './ScrollTop' @@ -23,17 +23,13 @@ const req = require.context(DIRNAME, true, /\.(js|md|mdx|jsx)$/) const { filename, basename = '', disableScroll } = OPTIONS const index = filename ? path.basename(filename, path.extname(filename)) : 'index' -req.keys().forEach(key => { - console.log(key, minimatch(key.replace(/^\.\//, ''), MATCH) ) -}) - const getComponents = req => req.keys() .filter(key => !MATCH || minimatch(key.replace(/^\.\//, ''), MATCH)) .map(key => ({ key, name: path.basename(key, path.extname(key)), module: req(key), - Component: req(key).default || req(key) + Component: req(key).default || req(key), })) .filter(component => !/^(\.|_)/.test(component.name)) .filter(component => typeof component.Component === 'function') @@ -58,14 +54,20 @@ const App = APP ? (require(APP).default || require(APP)) : DefaultApp export const getRoutes = async (components = initialComponents) => { const routes = await components.map(async ({ key, name, module, Component }) => { const exact = name === index - let pathname = exact ? '/' : '/' + name - const props = Component.getInitialProps + name = exact ? '/' : '/' + name + const dirname = path.dirname(key).replace(/^\./, '') + let pathname = dirname + (exact ? '/' : name) + const href = pathname + const initialProps = Component.getInitialProps ? await Component.getInitialProps({ path: pathname }) : {} + const meta = module.frontMatter || {} + const props = { ...meta, ...initialProps } pathname = props.path || pathname return { key: name, name, + href, path: pathname, exact, module, @@ -98,15 +100,13 @@ export default class Root extends React.Component { path = '/' } = this.props - console.log('App', App.defaultProps) - return ( - + {!disableScroll && } - + ) diff --git a/src/index.js b/src/index.js index d59e3fc..608ca9b 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,7 @@ export { default as ScopeProvider } from './ScopeProvider' export { default as LiveEditor } from './LiveEditor' +export { default as LivePreview } from './LivePreview' +export { default as FileList } from './FileList' +export { default as Catch } from './Catch' +export { default as ScrollTop } from './ScrollTop' export { default as scope } from './scope' From ee2895d746865f38d941e816c6f2c08a72b39c4b Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Tue, 19 Jun 2018 12:17:56 -0400 Subject: [PATCH 06/53] 5.0.9-0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6a07c1d..7767620 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@compositor/x0", - "version": "5.0.8", + "version": "5.0.9-0", "description": "Zero-config React development environment and static site generator", "main": "src/index.js", "bin": { From 6b3f50619d1797b453a8c524f0f4aa55750a63cc Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Tue, 19 Jun 2018 12:18:03 -0400 Subject: [PATCH 07/53] 5.1.0-0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7767620..b3dfcc9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@compositor/x0", - "version": "5.0.9-0", + "version": "5.1.0-0", "description": "Zero-config React development environment and static site generator", "main": "src/index.js", "bin": { From 59ec70de469a5fdf935411b052a574430c3384fe Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Tue, 19 Jun 2018 13:14:54 -0400 Subject: [PATCH 08/53] Adjust scope and fix deps --- README.md | 3 ++- cli.js | 4 +-- docs/_app.js | 4 +-- lib/config.js | 5 +++- package.json | 6 ++++- src/entry.js | 70 +++++++++++++++++++++++++++++---------------------- 6 files changed, 54 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 525e3f4..a1dae81 100644 --- a/README.md +++ b/README.md @@ -367,8 +367,9 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config) **REMOVE BEFORE MERGING** -- [ ] default route sorting - [ ] props.Component in custom apps +- [ ] peer deps +- [x] default route sorting - [x] route dirname/full path - [x] pass front-matter as props - [x] markdown scope diff --git a/cli.js b/cli.js index 08a57de..14b0e7c 100755 --- a/cli.js +++ b/cli.js @@ -131,7 +131,7 @@ log(chalk.cyan('@compositor/x0')) switch (cmd) { case 'build': log.start('building static site') - const { build } = require('.') + const build = require('./lib/build') build(opts) .then(res => { log.stop('site saved to ' + opts.outDir) @@ -141,7 +141,7 @@ switch (cmd) { case 'dev': default: log.start('starting dev server') - const { dev } = require('.') + const dev = require('./lib/dev') dev(opts) .then(({ server }) => { const { port } = server.options diff --git a/docs/_app.js b/docs/_app.js index ed66031..50423a9 100644 --- a/docs/_app.js +++ b/docs/_app.js @@ -1,7 +1,7 @@ import React from 'react' import * as scope from 'rebass' import { Link } from 'react-router-dom' -import { ScopeProvider } from '../src' +import { ScopeProvider } from '../components' import { Flex, Box, @@ -15,8 +15,6 @@ export default class App extends React.Component { render () { const { routes, route, render } = this.props - console.log('custom app', routes) - console.log('route', route) return ( diff --git a/lib/config.js b/lib/config.js index 7e062d5..df88d86 100644 --- a/lib/config.js +++ b/lib/config.js @@ -29,7 +29,10 @@ const rules = [ { test: /\.js$/, exclude: path.resolve(__dirname, '../node_modules'), - include: path.resolve(__dirname, '..'), + include: [ + path.resolve(__dirname, '..'), + path.resolve(__dirname, '../src') + ], loader: require.resolve('babel-loader'), options: babel }, diff --git a/package.json b/package.json index b3dfcc9..e670979 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@compositor/x0", "version": "5.1.0-0", "description": "Zero-config React development environment and static site generator", - "main": "src/index.js", + "main": "index.js", "bin": { "x0": "cli.js" }, @@ -48,8 +48,10 @@ "find-up": "^2.1.0", "fs-extra": "^6.0.1", "glamor": "^2.20.40", + "gray-matter": "^4.0.1", "html-minifier": "^3.5.16", "koa-connect": "^2.0.1", + "lodash.sortby": "^4.7.0", "meow": "^5.0.0", "mini-html-webpack-plugin": "^0.2.3", "minimatch": "^3.0.4", @@ -57,6 +59,7 @@ "react": "^16.4.1", "react-dev-utils": "^5.0.1", "react-dom": "^16.4.1", + "react-live": "^1.10.1", "react-router": "^4.3.1", "react-router-dom": "^4.3.1", "react-scope-provider": "^1.0.0-1", @@ -66,6 +69,7 @@ "remark-images": "^0.8.1", "remark-slug": "^5.0.0", "semver": "^5.5.0", + "stringify-object": "^3.2.2", "update-notifier": "^2.5.0", "webpack": "^4.10.2", "webpack-merge": "^4.1.3", diff --git a/src/entry.js b/src/entry.js index 3bfc6c6..399a803 100644 --- a/src/entry.js +++ b/src/entry.js @@ -12,7 +12,9 @@ import { } from 'react-router-dom' import { Provider as RebassProvider } from 'rebass' import minimatch from 'minimatch' +import sortBy from 'lodash.sortby' +import ScopeProvider from './ScopeProvider' import Catch from './Catch' import FileList from './FileList' import ScrollTop from './ScrollTop' @@ -52,7 +54,7 @@ const Router = IS_CLIENT ? BrowserRouter : StaticRouter const App = APP ? (require(APP).default || require(APP)) : DefaultApp export const getRoutes = async (components = initialComponents) => { - const routes = await components.map(async ({ key, name, module, Component }) => { + const promises = await components.map(async ({ key, name, module, Component }) => { const exact = name === index name = exact ? '/' : '/' + name const dirname = path.dirname(key).replace(/^\./, '') @@ -69,13 +71,19 @@ export const getRoutes = async (components = initialComponents) => { name, href, path: pathname, + dirname, exact, module, Component, props } }) - return Promise.all(routes) + const routes = await Promise.all(promises) + let sorted = [...routes] + sorted = sortBy([...sorted], a => a.name) + sorted = sortBy([...sorted], a => !a.exact) + sorted = sortBy([...sorted], a => a.dirname) + return sorted } const RouterState = withRouter(({ render, ...props }) => { @@ -107,35 +115,37 @@ export default class Root extends React.Component { location={path}> - - ( - ( - routes.map(({ Component, ...route }) => ( - ( - - - - )} - /> - )) - )} - /> - )} - /> - - {!disableScroll && } + + + ( + ( + routes.map(({ Component, ...route }) => ( + ( + + + + )} + /> + )) + )} + /> + )} + /> + + + {!disableScroll && } ) From 27833345e2dcd0053f99935748c5ca1cb0bd4280 Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Tue, 19 Jun 2018 13:43:01 -0400 Subject: [PATCH 09/53] Update snapshots --- components.js | 1 + package.json | 4 ++-- test/components/compositor.jsx | 5 ----- test/snapshots/build.js.md | 4 ++-- test/snapshots/build.js.snap | Bin 390 -> 411 bytes 5 files changed, 5 insertions(+), 9 deletions(-) create mode 100644 components.js delete mode 100644 test/components/compositor.jsx diff --git a/components.js b/components.js new file mode 100644 index 0000000..a2958b7 --- /dev/null +++ b/components.js @@ -0,0 +1 @@ +module.exports = require('./src') diff --git a/package.json b/package.json index e670979..8ec30a0 100644 --- a/package.json +++ b/package.json @@ -121,8 +121,8 @@ "ava": { "files": [ "test/*", - "!test/components", - "!test/output" + "!**/test/components", + "!**/test/output" ], "require": [ "babel-register" diff --git a/test/components/compositor.jsx b/test/components/compositor.jsx deleted file mode 100644 index 1d6afa0..0000000 --- a/test/components/compositor.jsx +++ /dev/null @@ -1,5 +0,0 @@ ---- -className: beep ---- - -

Hello

diff --git a/test/snapshots/build.js.md b/test/snapshots/build.js.md index 5bc7e2b..cc35734 100644 --- a/test/snapshots/build.js.md +++ b/test/snapshots/build.js.md @@ -8,10 +8,10 @@ Generated by [AVA](https://ava.li). > Snapshot 1 - 'x0

Hello

' + 'x0

Hello

' ## static uses getInitialProps method > Snapshot 1 - 'x0

Hello

' + 'x0

Hello

' diff --git a/test/snapshots/build.js.snap b/test/snapshots/build.js.snap index ff845ddbbb751f7220f08dbdc909b2c5a8d30e21..c2796041565a5848348b092c8ff3469f6785510b 100644 GIT binary patch literal 411 zcmV;M0c8F`RzV-=`{P9+QKihwJEIE^NY0K?e zYiYBY?=0RmZth>MuS!#Oes+>tn7T@H&hm^Y1*?t2dh_&X*G)~vqaX#!q96l9-6W+- zg9*K!X_GDQOBFPO(CZ@%x>6a>O{6d&tZRVGq#=VoCP1c583h`ooalsd2&=yl9T1?X zk?IGdF0-!GXhnBev37%oLo}=ee(?&l$!%F5#d1hAUZCjIVyPG?VwG_$Sw70B>Y%7q zw%e9U+B8F+*L1E8WTb~>O@$^J6t>5KU*H12_%*}6i!Ah%l*TLCgj20UPbVZEVn2;t z*23e)iJhj^Xb(7-He9s?YyQ4FfkP}~;Ly2A4ZfU6c3M@PU42*1u z4e= z<*i<|yL8vNxqrRBvghhkW7f4er|bo5rO~y+wa!tychcQ+a$Od2m;+^TSc0Zbnp3Gj zNA6H(WZV5#IV~Y_M+g@KA+_tIf@|Q0xRYIEWy;1R5o4n85_vyJgk&IzQKpGt)ug1dk34AY zWG0nlw8WwcRHZbOWQa{gxgrWAX4BBC<3g|gHN%mEEOMm~+6>SAcpr*F7~40Dan1Zx k;y^n}rjhFU;qFB From 99012faab7cda196e0bd79bc80509aafdba03338 Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Tue, 19 Jun 2018 13:48:28 -0400 Subject: [PATCH 10/53] Adjust docs layout --- README.md | 2 ++ docs/_app.js | 23 ++++++++++++++--------- docs/{__app.js => _layout.js} | 4 ++-- src/index.js | 1 + 4 files changed, 19 insertions(+), 11 deletions(-) rename docs/{__app.js => _layout.js} (96%) diff --git a/README.md b/README.md index a1dae81..a3b3e82 100644 --- a/README.md +++ b/README.md @@ -369,6 +369,8 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config) - [ ] props.Component in custom apps - [ ] peer deps +- [ ] Head component with react helmet +- [ ] changelog/docs - [x] default route sorting - [x] route dirname/full path - [x] pass front-matter as props diff --git a/docs/_app.js b/docs/_app.js index 50423a9..f07cf9a 100644 --- a/docs/_app.js +++ b/docs/_app.js @@ -7,6 +7,7 @@ import { Box, Container, } from 'rebass' +import Layout from './_layout' export default class App extends React.Component { static defaultProps = { @@ -18,8 +19,12 @@ export default class App extends React.Component { return ( - - {true && ( + {false ? ( + + {render()} + + ) : ( +
    {routes.map(route => ( @@ -31,13 +36,13 @@ export default class App extends React.Component { ))}
- )} - - - {render()} - - -
+ + + {render()} + + +
+ )}
) } diff --git a/docs/__app.js b/docs/_layout.js similarity index 96% rename from docs/__app.js rename to docs/_layout.js index e6aca89..0ea326f 100644 --- a/docs/__app.js +++ b/docs/_layout.js @@ -12,7 +12,7 @@ import { Link } from 'react-router-dom' import { Logo } from '@compositor/logo' import theme from './theme' -export default ({ render }) => +export default ({ children }) => - {render()} + {children} diff --git a/src/index.js b/src/index.js index 608ca9b..cc1fabf 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,4 @@ +export { Link, NavLink } from 'react-router-dom' export { default as ScopeProvider } from './ScopeProvider' export { default as LiveEditor } from './LiveEditor' export { default as LivePreview } from './LivePreview' From bef133c513f9ff61798167a96af03e310f61a17b Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Tue, 19 Jun 2018 14:23:28 -0400 Subject: [PATCH 11/53] Add default layout for markdown --- README.md | 14 +++++++++++--- docs/_app.js | 2 ++ src/CenteredLayout.js | 12 ++++++++++++ src/entry.js | 31 ++++++++++++++++++++++--------- 4 files changed, 47 insertions(+), 12 deletions(-) create mode 100644 src/CenteredLayout.js diff --git a/README.md b/README.md index a3b3e82..e4c1aab 100644 --- a/README.md +++ b/README.md @@ -280,16 +280,17 @@ export default () => ( ### JSX Format -x0 includes support for the [Compositor JSX][jsx-loader] file format. +x0 includes support for the Compositor JSX file format. ```jsx --- title: Hello -scope: import * as scope from 'rebass' --- +import { Box, Heading } from 'rebass' + - {props.title} + {frontMatter.title} ``` @@ -371,6 +372,8 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config) - [ ] peer deps - [ ] Head component with react helmet - [ ] changelog/docs +- [x] props.ignore +- [x] default layout for mdx/md - [x] default route sorting - [x] route dirname/full path - [x] pass front-matter as props @@ -380,3 +383,8 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config) - [x] move client modules to src - [x] adjust resolve +### Breaking + +- .jsx imports/scope +- .jsx props + diff --git a/docs/_app.js b/docs/_app.js index f07cf9a..8b36b57 100644 --- a/docs/_app.js +++ b/docs/_app.js @@ -17,6 +17,8 @@ export default class App extends React.Component { render () { const { routes, route, render } = this.props + return render() + return ( {false ? ( diff --git a/src/CenteredLayout.js b/src/CenteredLayout.js new file mode 100644 index 0000000..353c4bf --- /dev/null +++ b/src/CenteredLayout.js @@ -0,0 +1,12 @@ +import React from 'react' +import { + Container +} from 'rebass' + +export default props => props.active + ? + : props.children diff --git a/src/entry.js b/src/entry.js index 399a803..7d5d9ce 100644 --- a/src/entry.js +++ b/src/entry.js @@ -18,6 +18,7 @@ import ScopeProvider from './ScopeProvider' import Catch from './Catch' import FileList from './FileList' import ScrollTop from './ScrollTop' +import CenteredLayout from './CenteredLayout' const IS_CLIENT = typeof document !== 'undefined' const req = require.context(DIRNAME, true, /\.(js|md|mdx|jsx)$/) @@ -27,13 +28,13 @@ const index = filename ? path.basename(filename, path.extname(filename)) : 'inde const getComponents = req => req.keys() .filter(key => !MATCH || minimatch(key.replace(/^\.\//, ''), MATCH)) + .filter(key => !/^_/.test(path.basename(key))) .map(key => ({ key, name: path.basename(key, path.extname(key)), module: req(key), Component: req(key).default || req(key), })) - .filter(component => !/^(\.|_)/.test(component.name)) .filter(component => typeof component.Component === 'function') const initialComponents = getComponents(req) @@ -54,10 +55,16 @@ const Router = IS_CLIENT ? BrowserRouter : StaticRouter const App = APP ? (require(APP).default || require(APP)) : DefaultApp export const getRoutes = async (components = initialComponents) => { - const promises = await components.map(async ({ key, name, module, Component }) => { + const promises = await components.map(async ({ + key, + name, + module, + Component + }) => { const exact = name === index name = exact ? '/' : '/' + name const dirname = path.dirname(key).replace(/^\./, '') + const extname = path.extname(key) let pathname = dirname + (exact ? '/' : name) const href = pathname const initialProps = Component.getInitialProps @@ -67,8 +74,9 @@ export const getRoutes = async (components = initialComponents) => { const props = { ...meta, ...initialProps } pathname = props.path || pathname return { - key: name, + key, name, + extname, href, path: pathname, dirname, @@ -79,7 +87,8 @@ export const getRoutes = async (components = initialComponents) => { } }) const routes = await Promise.all(promises) - let sorted = [...routes] + const filtered = routes.filter(r => !r.props.ignore) + let sorted = [...filtered] sorted = sortBy([...sorted], a => a.name) sorted = sortBy([...sorted], a => !a.exact) sorted = sortBy([...sorted], a => a.dirname) @@ -107,6 +116,7 @@ export default class Root extends React.Component { basename, path = '/' } = this.props + console.log('routes', routes) return ( ( - + + + )} /> From b150d129720bf8f11baf58d50cfa6ad25be1585d Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Tue, 19 Jun 2018 14:23:33 -0400 Subject: [PATCH 12/53] 5.1.0-1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8ec30a0..3b37df4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@compositor/x0", - "version": "5.1.0-0", + "version": "5.1.0-1", "description": "Zero-config React development environment and static site generator", "main": "index.js", "bin": { From d23866f69e8249765f42f2353bc8f0ef47364e7a Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Tue, 19 Jun 2018 16:38:14 -0400 Subject: [PATCH 13/53] Filter node_modules --- README.md | 3 ++- src/entry.js | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e4c1aab..8d012e5 100644 --- a/README.md +++ b/README.md @@ -368,7 +368,8 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config) **REMOVE BEFORE MERGING** -- [ ] props.Component in custom apps +- [ ] require.context `_app` +- [ ] props.Component/children in custom apps - [ ] peer deps - [ ] Head component with react helmet - [ ] changelog/docs diff --git a/src/entry.js b/src/entry.js index 7d5d9ce..e92d0e2 100644 --- a/src/entry.js +++ b/src/entry.js @@ -27,6 +27,7 @@ const { filename, basename = '', disableScroll } = OPTIONS const index = filename ? path.basename(filename, path.extname(filename)) : 'index' const getComponents = req => req.keys() + .filter(minimatch.filter('!node_modules')) .filter(key => !MATCH || minimatch(key.replace(/^\.\//, ''), MATCH)) .filter(key => !/^_/.test(path.basename(key))) .map(key => ({ From 8fe228619b02eb0e0fcbbdc89af1a7721bf9ecb4 Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Tue, 19 Jun 2018 16:38:24 -0400 Subject: [PATCH 14/53] 5.1.0-2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3b37df4..a5c4661 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@compositor/x0", - "version": "5.1.0-1", + "version": "5.1.0-2", "description": "Zero-config React development environment and static site generator", "main": "index.js", "bin": { From 2dd8e2a25101099a5e9f253b810509c51d2b8e46 Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Tue, 19 Jun 2018 16:51:21 -0400 Subject: [PATCH 15/53] Edit deps --- README.md | 3 ++- package.json | 15 ++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 8d012e5..c0f5e41 100644 --- a/README.md +++ b/README.md @@ -369,10 +369,11 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config) **REMOVE BEFORE MERGING** - [ ] require.context `_app` +- [ ] pass RouterState props to view - [ ] props.Component/children in custom apps -- [ ] peer deps - [ ] Head component with react helmet - [ ] changelog/docs +- [x] peer deps - [x] props.ignore - [x] default layout for mdx/md - [x] default route sorting diff --git a/package.json b/package.json index a5c4661..c80ff2a 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "start": "./cli.js docs -op 8888", "build": "./cli.js build docs", - "test": "ava -T 20s", + "test": "nyc ava -T 20s", "cover": "nyc report --reporter=html --reporter=lcov" }, "keywords": [ @@ -64,6 +64,7 @@ "react-router-dom": "^4.3.1", "react-scope-provider": "^1.0.0-1", "read-pkg-up": "^3.0.0", + "rebass": "^2.0.0-6", "remark-autolink-headings": "^5.0.0", "remark-emoji": "^2.0.1", "remark-images": "^0.8.1", @@ -73,20 +74,20 @@ "update-notifier": "^2.5.0", "webpack": "^4.10.2", "webpack-merge": "^4.1.3", - "webpack-serve": "^1.0.4" + "webpack-serve": "^1.0.4", + "styled-system": "^2.3.1" }, "devDependencies": { "@compositor/logo": "^1.4.0", "ava": "^0.25.0", "isomorphic-fetch": "^2.2.1", - "nano-style": "^1.0.0", "nyc": "^12.0.1", - "raw-loader": "^0.5.1", - "rebass": "^2.0.0-6", "refunk": "^3.0.1", "rimraf": "^2.6.2", - "styled-components": "^3.3.2", - "styled-system": "^2.3.1" + "styled-components": "^3.3.2" + }, + "peerDependencies": { + "styled-components": "3.x" }, "x0": { "title": "Compositor x0", From 61294871909996efee30fb1e18ca48fdcdd27af3 Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Tue, 19 Jun 2018 17:04:15 -0400 Subject: [PATCH 16/53] Use require context for custom apps --- README.md | 3 ++- cli.js | 7 ------- docs/_app.js | 2 +- lib/build.js | 1 - lib/dev.js | 1 - src/entry.js | 6 +++--- 6 files changed, 6 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index c0f5e41..b661d01 100644 --- a/README.md +++ b/README.md @@ -368,11 +368,11 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config) **REMOVE BEFORE MERGING** -- [ ] require.context `_app` - [ ] pass RouterState props to view - [ ] props.Component/children in custom apps - [ ] Head component with react helmet - [ ] changelog/docs +- [x] require.context `_app` - [x] peer deps - [x] props.ignore - [x] default layout for mdx/md @@ -389,4 +389,5 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config) - .jsx imports/scope - .jsx props +- custom app path option (must be `_app.js`) diff --git a/cli.js b/cli.js index 14b0e7c..5585dfd 100755 --- a/cli.js +++ b/cli.js @@ -110,13 +110,6 @@ if (opts.webpack) { if (webpackConfig) opts.webpack = require(webpackConfig) } -if (opts.app) { - opts.app = path.resolve(opts.app) -} else { - const app = findup.sync('_app.js', { cwd: dirname }) - if (app) opts.app = app -} - if (opts.template) { opts.template = require(path.resolve(opts.template)) } diff --git a/docs/_app.js b/docs/_app.js index 8b36b57..d8e881b 100644 --- a/docs/_app.js +++ b/docs/_app.js @@ -17,7 +17,7 @@ export default class App extends React.Component { render () { const { routes, route, render } = this.props - return render() + // return render() return ( diff --git a/lib/build.js b/lib/build.js index c39a4e6..6b0feab 100644 --- a/lib/build.js +++ b/lib/build.js @@ -165,7 +165,6 @@ module.exports = async (opts) => { DEV: JSON.stringify(false), OPTIONS: JSON.stringify(opts), DIRNAME: JSON.stringify(opts.dirname), - APP: JSON.stringify(opts.app), MATCH: JSON.stringify(opts.match) }) ) diff --git a/lib/dev.js b/lib/dev.js index 517a017..c72a387 100644 --- a/lib/dev.js +++ b/lib/dev.js @@ -49,7 +49,6 @@ module.exports = async (opts) => { DEV: JSON.stringify(true), OPTIONS: JSON.stringify(opts), DIRNAME: JSON.stringify(opts.dirname), - APP: JSON.stringify(opts.app), MATCH: JSON.stringify(opts.match) }) ) diff --git a/src/entry.js b/src/entry.js index e92d0e2..386f0e5 100644 --- a/src/entry.js +++ b/src/entry.js @@ -53,7 +53,8 @@ const DefaultApp = ({ render, routes }) => ( ) const Router = IS_CLIENT ? BrowserRouter : StaticRouter -const App = APP ? (require(APP).default || require(APP)) : DefaultApp +const appPath = req.keys().find(key => key === './_app.js') +const App = appPath ? (req(appPath).default || req(appPath)) : DefaultApp export const getRoutes = async (components = initialComponents) => { const promises = await components.map(async ({ @@ -166,7 +167,6 @@ export default class Root extends React.Component { } } -let app if (IS_CLIENT) { const mount = DEV ? render : hydrate const div = window.root || document.body.appendChild( @@ -174,7 +174,7 @@ if (IS_CLIENT) { ) getRoutes() .then(routes => { - app = mount(, div) + mount(, div) }) } From fd207eb0a7ff4fd132e835a131c987370b1696ef Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Tue, 19 Jun 2018 17:27:02 -0400 Subject: [PATCH 17/53] Add Head component --- README.md | 2 +- docs/_app.js | 6 +++++- lib/build.js | 24 ++++++++++++++++++++---- package.json | 1 + src/Head.js | 7 +++++++ src/entry.js | 1 - src/index.js | 1 + 7 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 src/Head.js diff --git a/README.md b/README.md index b661d01..eff829c 100644 --- a/README.md +++ b/README.md @@ -389,5 +389,5 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config) - .jsx imports/scope - .jsx props -- custom app path option (must be `_app.js`) +- custom app path option (must be `_app.js`) (undocumented) diff --git a/docs/_app.js b/docs/_app.js index d8e881b..4b97f35 100644 --- a/docs/_app.js +++ b/docs/_app.js @@ -1,7 +1,7 @@ import React from 'react' import * as scope from 'rebass' import { Link } from 'react-router-dom' -import { ScopeProvider } from '../components' +import { ScopeProvider, Head } from '../components' import { Flex, Box, @@ -21,6 +21,10 @@ export default class App extends React.Component { return ( + + hello + + {false ? ( {render()} diff --git a/lib/build.js b/lib/build.js index 6b0feab..cf91087 100644 --- a/lib/build.js +++ b/lib/build.js @@ -7,6 +7,7 @@ const merge = require('webpack-merge') const React = require('react') const { renderToString, renderToStaticMarkup } = require('react-dom/server') const { StaticRouter } = require('react-router-dom') +const { Helmet } = require('react-helmet') const semver = require('semver') const util = require('util') @@ -93,13 +94,13 @@ const renderHTML = ({ ) ) css = sheet.getStyleTags() - return { path, html, css, props } + break case 'emotion': const { renderStylesToString } = require('emotion-server') html = renderStylesToString( render(app) ) - return { path, html, props } + break case 'glamor': // doesn't seem to be working... const glamor = require('glamor/server') @@ -108,13 +109,28 @@ const renderHTML = ({ )) html = res.html css = `` - return { path, html, css, props } + break default: html = render(app) - return { path, html, props } + break } + const helmet = Helmet.renderStatic() + const head = parseHelmet(helmet) + // doesn't seem to be working... + // console.log('head', head) + return { html, css, path, props } } +const parseHelmet = helmet => [ + helmet.title.toString(), + helmet.link.toString(), + helmet.meta.toString(), + helmet.script.toString(), + helmet.noscript.toString(), + helmet.style.toString(), + helmet.base.toString(), +].filter(n => !!n && n.length).join('\n') + const remove = filename => { fs.remove(filename, err => { if (err) console.log(err) diff --git a/package.json b/package.json index c80ff2a..9582f3d 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "react": "^16.4.1", "react-dev-utils": "^5.0.1", "react-dom": "^16.4.1", + "react-helmet": "^5.2.0", "react-live": "^1.10.1", "react-router": "^4.3.1", "react-router-dom": "^4.3.1", diff --git a/src/Head.js b/src/Head.js new file mode 100644 index 0000000..c3e3994 --- /dev/null +++ b/src/Head.js @@ -0,0 +1,7 @@ +export { Helmet as default } from 'react-helmet' + +// only needed if customizing api +// import React from 'react' +// import { Helmet } from 'react-helmet' +// export default props => +// diff --git a/src/entry.js b/src/entry.js index 386f0e5..6ce9f13 100644 --- a/src/entry.js +++ b/src/entry.js @@ -118,7 +118,6 @@ export default class Root extends React.Component { basename, path = '/' } = this.props - console.log('routes', routes) return ( Date: Tue, 19 Jun 2018 20:01:39 -0400 Subject: [PATCH 18/53] Remove helmet --- README.md | 2 +- docs/_app.js | 20 ++++++++++---------- lib/build.js | 18 ++---------------- package.json | 5 ++--- src/Head.js | 7 ------- src/entry.js | 41 ++++++++++++++++++++++------------------- src/index.js | 1 - 7 files changed, 37 insertions(+), 57 deletions(-) delete mode 100644 src/Head.js diff --git a/README.md b/README.md index eff829c..b8f7d67 100644 --- a/README.md +++ b/README.md @@ -370,7 +370,6 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config) - [ ] pass RouterState props to view - [ ] props.Component/children in custom apps -- [ ] Head component with react helmet - [ ] changelog/docs - [x] require.context `_app` - [x] peer deps @@ -384,6 +383,7 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config) - [x] minimatch - [x] move client modules to src - [x] adjust resolve +- [ ] ~~Head component with react helmet~~ doesn't work ### Breaking diff --git a/docs/_app.js b/docs/_app.js index 4b97f35..705f6f3 100644 --- a/docs/_app.js +++ b/docs/_app.js @@ -1,7 +1,7 @@ import React from 'react' import * as scope from 'rebass' import { Link } from 'react-router-dom' -import { ScopeProvider, Head } from '../components' +import { ScopeProvider } from '../components' import { Flex, Box, @@ -15,19 +15,19 @@ export default class App extends React.Component { } render () { - const { routes, route, render } = this.props - - // return render() + const { + routes, + route, + children, + // alternative to props.children + render, + } = this.props return ( - - hello - - {false ? ( - {render()} + {children} ) : ( @@ -44,7 +44,7 @@ export default class App extends React.Component {
- {render()} + {children} diff --git a/lib/build.js b/lib/build.js index cf91087..ad17376 100644 --- a/lib/build.js +++ b/lib/build.js @@ -7,7 +7,6 @@ const merge = require('webpack-merge') const React = require('react') const { renderToString, renderToStaticMarkup } = require('react-dom/server') const { StaticRouter } = require('react-router-dom') -const { Helmet } = require('react-helmet') const semver = require('semver') const util = require('util') @@ -90,7 +89,8 @@ const renderHTML = ({ const sheet = new ServerStyleSheet() html = render( sheet.collectStyles( - React.createElement(App.default, { routes, path }) + app + // React.createElement(App.default, { routes, path }) ) ) css = sheet.getStyleTags() @@ -114,23 +114,9 @@ const renderHTML = ({ html = render(app) break } - const helmet = Helmet.renderStatic() - const head = parseHelmet(helmet) - // doesn't seem to be working... - // console.log('head', head) return { html, css, path, props } } -const parseHelmet = helmet => [ - helmet.title.toString(), - helmet.link.toString(), - helmet.meta.toString(), - helmet.script.toString(), - helmet.noscript.toString(), - helmet.style.toString(), - helmet.base.toString(), -].filter(n => !!n && n.length).join('\n') - const remove = filename => { fs.remove(filename, err => { if (err) console.log(err) diff --git a/package.json b/package.json index 9582f3d..9d591b4 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,6 @@ "react": "^16.4.1", "react-dev-utils": "^5.0.1", "react-dom": "^16.4.1", - "react-helmet": "^5.2.0", "react-live": "^1.10.1", "react-router": "^4.3.1", "react-router-dom": "^4.3.1", @@ -72,11 +71,11 @@ "remark-slug": "^5.0.0", "semver": "^5.5.0", "stringify-object": "^3.2.2", + "styled-system": "^2.3.1", "update-notifier": "^2.5.0", "webpack": "^4.10.2", "webpack-merge": "^4.1.3", - "webpack-serve": "^1.0.4", - "styled-system": "^2.3.1" + "webpack-serve": "^1.0.4" }, "devDependencies": { "@compositor/logo": "^1.4.0", diff --git a/src/Head.js b/src/Head.js deleted file mode 100644 index c3e3994..0000000 --- a/src/Head.js +++ /dev/null @@ -1,7 +0,0 @@ -export { Helmet as default } from 'react-helmet' - -// only needed if customizing api -// import React from 'react' -// import { Helmet } from 'react-helmet' -// export default props => -// diff --git a/src/entry.js b/src/entry.js index 6ce9f13..60ed193 100644 --- a/src/entry.js +++ b/src/entry.js @@ -119,6 +119,26 @@ export default class Root extends React.Component { path = '/' } = this.props + const render = appProps => ( + routes.map(({ Component, ...route }) => ( + ( + + + + + + )} + /> + )) + ) + return ( ( - routes.map(({ Component, ...route }) => ( - ( - - - - - - )} - /> - )) - )} + render={render} + children={render()} /> )} /> diff --git a/src/index.js b/src/index.js index aab87b0..cc1fabf 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,5 @@ export { Link, NavLink } from 'react-router-dom' export { default as ScopeProvider } from './ScopeProvider' -export { default as Head } from './Head' export { default as LiveEditor } from './LiveEditor' export { default as LivePreview } from './LivePreview' export { default as FileList } from './FileList' From 4556918cbdea6e5631ed5fdaeaada8869c23fe28 Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Wed, 20 Jun 2018 13:53:12 -0400 Subject: [PATCH 19/53] Add basic layout component --- README.md | 10 +- docs/_app.js | 13 +- package.json | 3 +- src/SidebarLayout.js | 319 +++++++++++++++++++++++++++++++++++++++++++ src/entry.js | 10 +- src/index.js | 3 + 6 files changed, 350 insertions(+), 8 deletions(-) create mode 100644 src/SidebarLayout.js diff --git a/README.md b/README.md index b8f7d67..ef90f46 100644 --- a/README.md +++ b/README.md @@ -368,9 +368,13 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config) **REMOVE BEFORE MERGING** -- [ ] pass RouterState props to view -- [ ] props.Component/children in custom apps - [ ] changelog/docs + +- [x] SidebarLayout +- [x] test getInitialProps +- [x] double check dynamic routing +- [x] pass RouterState props to view +- [x] props.children in custom app - [x] require.context `_app` - [x] peer deps - [x] props.ignore @@ -383,7 +387,9 @@ See the [example](https://github.com/c8r/x0/tree/master/examples/webpack-config) - [x] minimatch - [x] move client modules to src - [x] adjust resolve +- [x] props.Component in custom app? - [ ] ~~Head component with react helmet~~ doesn't work +- [ ] ~~scope loader shim for jsx front matter~~ ### Breaking diff --git a/docs/_app.js b/docs/_app.js index 705f6f3..bb936a4 100644 --- a/docs/_app.js +++ b/docs/_app.js @@ -1,7 +1,7 @@ import React from 'react' import * as scope from 'rebass' import { Link } from 'react-router-dom' -import { ScopeProvider } from '../components' +import { ScopeProvider, SidebarLayout } from '../components' import { Flex, Box, @@ -20,9 +20,20 @@ export default class App extends React.Component { route, children, // alternative to props.children + Component, render, } = this.props + // built-in layout test + if (false) { + return ( + + + + ) + } + + return ( {false ? ( diff --git a/package.json b/package.json index 9d591b4..7019089 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "x0": "cli.js" }, "scripts": { - "start": "./cli.js docs -op 8888", + "start": "./cli.js docs -p 8888", "build": "./cli.js build docs", "test": "nyc ava -T 20s", "cover": "nyc report --reporter=html --reporter=lcov" @@ -56,6 +56,7 @@ "mini-html-webpack-plugin": "^0.2.3", "minimatch": "^3.0.4", "pkg-conf": "^2.1.0", + "prop-types": "^15.6.2", "react": "^16.4.1", "react-dev-utils": "^5.0.1", "react-dom": "^16.4.1", diff --git a/src/SidebarLayout.js b/src/SidebarLayout.js new file mode 100644 index 0000000..d76f27c --- /dev/null +++ b/src/SidebarLayout.js @@ -0,0 +1,319 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { + Link as RouterLink, + NavLink as RouterNavLink +} from 'react-router-dom' +import styled from 'styled-components' +import { + Provider as RebassProvider, + Flex, + Box, + Fixed, + Container, + Text, + Close, + Toolbar, + Divider, + Heading, + NavLink, + BlockLink, + Button, + ButtonTransparent, +} from 'rebass' +import { borderColor, themeGet } from 'styled-system' + +const breakpoint = `@media screen and (min-width: 48em)` + +export const Root = styled(Flex)([], { + minHeight: '100vh' +}) + +export const Sidebar = styled('div')([], { + width: '256px', + height: '100vh', + flex: 'none', + overflowY: 'auto', + transition: 'transform .2s ease-out', + backgroundColor: '#fff', + borderRight: '1px solid', + position: 'fixed', + top: 0, + left: 0, + bottom: 0, + [breakpoint]: { + // transition: 'none' + } +}, props => ({ + transform: props.open ? 'translateX(0)' : 'translateX(-100%)', + [breakpoint]: { + transform: 'none' + } +}), borderColor) +Sidebar.defaultProps = { + borderColor: 'gray' +} + +export const Overlay = styled('div')([], { + position: 'fixed', + top: 0, + right: 0, + bottom: 0, + left: 0, +}) + +export const MobileOnly = styled.div([], { + [breakpoint]: { + display: 'none' + }, +}) + +export const MenuIcon = ({ size = 24, ...props }) => + + + + +export const FocusButton = styled(Button)([], { + width: '2em', + height: '2em', +}) +FocusButton.defaultProps = { + fontSize: 0, + px: '0.25em', + py: '0.25em', + m: 2, + color: 'black', + bg: 'gray' +} + +export const Main = props => + + +export const MaxWidth = props => + + +export const UL = styled('ul')([], { + listStyle: 'none', + margin: 0, + paddingLeft: 0, + paddingBottom: '48px', +}) + +export const LI = styled('li')([], { +}) + +const depthPad = ({ to = '' }) => + (1 + to.split('/') + .filter(s => s.length) + .slice(1).length) * 16 + +const Link = styled(props => ( + +))([], props => ({ + borderLeft: '4px solid', + borderColor: 'transparent', + '&.active, &:focus': { + color: themeGet('colors.blue', '#07c')(props), + outline: 'none', + }, + '&:focus': { + borderColor: 'inherit', + } +})) + +Link.defaultProps = { + to: '' +} + +const unhyphenate = str => str.replace(/(\w)(-)(\w)/g, '$1 $3') +const upperFirst = str => str.charAt(0).toUpperCase() + str.slice(1) +const format = str => upperFirst(unhyphenate(str)) + +const NavBar = ({ + title, + focus, + update, +}) => + + + {title} + + + {DEV && ( + update(toggle('focus'))}> + F + + )} + + +export const Nav = ({ + routes = [], + ...props +}) => + + + +
    + {/* rename to route.type='section' */} + {routes.map(route => route.exact ? ( +
  • + + {format(route.name)} (index) + +
  • + ) : ( +
  • + {/^https?:\/\//.test(route.path) ? ( + + {route.name} + + ) : ( + + {format(route.name)} + + )} +
  • + ))} +
+
+ +export const Pagination = ({ previous, next }) => + + {previous && ( + + Previous: + + {format(previous.name)} + + + )} + + {next && ( + + Next: + + {format(next.name)} + + + )} + + +// move to app +const toggle = key => state => ({ [key]: !state[key] }) +const close = state => ({ menu: false }) + +export default class Layout extends React.Component { + static propTypes = { + // content: PropTypes.node.isRequired, + routes: PropTypes.array.isRequired + } + + state = { + menu: false, + update: fn => this.setState(fn) + } + + render () { + const { + routes = [], + children, + route, + location, + title = 'x0', + // theme, + // color, + } = this.props + const { menu, update } = this.state + + const Wrapper = route && route.props && route.props.fullWidth + ? React.Fragment + : MaxWidth + + const index = routes.findIndex(r => r === route) + const pagination = { + previous: routes[index - 1], + next: routes[index + 1] + } + + return ( + + + + update(toggle('menu'))}> + + + + {title} + + + + + + + + {menu && update(close)} />} + update(close)}> +