mirror of
https://github.com/c8r/x0.git
synced 2024-08-17 01:10:32 +03:00
Merge branch 'master' into v5-glob
This commit is contained in:
commit
04285687a0
@ -4,6 +4,7 @@ node_js:
|
||||
before_deploy:
|
||||
- npm install
|
||||
- npm run build
|
||||
- cp docs/hello-x0.gif docs/hello-x0.mp4 dist
|
||||
deploy:
|
||||
provider: pages
|
||||
skip_cleanup: true
|
||||
|
45
CHANGELOG.md
Normal file
45
CHANGELOG.md
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
## 5.0.0
|
||||
|
||||
- x0 now accepts a folder of components as the entry argument
|
||||
- Automatic routing based on filename
|
||||
- Dev server uses [webpack-serve](https://github.com/webpack-contrib/webpack-serve) under the hood
|
||||
- Uses [mini-html-webpack-plugin](https://github.com/styleguidist/mini-html-webpack-plugin)
|
||||
- Default HTML head contents for UTF-8 charset and viewport meta tag
|
||||
- Minimal base CSS styling
|
||||
- Rendering the `<head>` in the component is no longer supported
|
||||
- Webpack is used both for the client and static rendering, enabling webpack features in `getInitialProps`
|
||||
- Support for [babel-plugin-macros](https://github.com/kentcdodds/babel-plugin-macros)
|
||||
- Default props can no longer be passed through the `package.json` config
|
||||
- The `routes` array in `package.json` is no longer supported
|
||||
- Adding [react-router](https://github.com/ReactTraining/react-router) is no longer necessary
|
||||
- Removes [react-loadable](https://github.com/jamiebuilds/react-loadable) support
|
||||
- Proxy option is no longer supported, but can be configured with a custom webpack config
|
||||
- Automatically looks for a `webpack.config.js` file in the directory
|
||||
- The `--config` flag has been renamed to `--webpack`
|
||||
- Automatic support for [styled-components](https://github.com/styled-components/styled-components)
|
||||
- Automatic support for [emotion](https://github.com/emotion-js/emotion)
|
||||
- Custom HTML template option
|
||||
- Supports custom App component to wrap all routes
|
||||
- Support for [JSX](https://github.com/c8r/jsx-loader) file format
|
||||
- Support for [MDX](https://github.com/mdx-js/mdx) file format
|
||||
|
||||
### Migrating from v4
|
||||
|
||||
- A directory should be passed to the x0 command, instead of a single file
|
||||
- React router is not necessary for routing
|
||||
- The `routes` option is no longer supported
|
||||
- HTML head contents should be removed from components
|
||||
- Viewport and charset meta tags are included by default
|
||||
- Use the custom template option or head options to populate HTML head contents
|
||||
- Default props set in options should be added to the components
|
||||
- Custom usage of react-loadable will require additional setup
|
||||
- The `--config` flag should be renamed to `--webpack`
|
||||
- The `proxy` option is no longer supported
|
||||
- The `cssLibrary` option is no longer required
|
||||
- Support for automatic static rendering with `glamor`, `glamorous`, and `fela` is no longer supported
|
||||
- The `getInitialProps` method's `pathname` argument has be renamed to `path`
|
||||
- The `getInitialProps` method *only* receives the `path` argument, all other arguments are deprecated
|
||||
|
@ -26,6 +26,8 @@ npm install -g @compositor/x0
|
||||
- Works with CSS-in-JS libraries like [styled-components][sc] and [emotion][emotion]
|
||||
- Support for async data fetching
|
||||
|
||||
Read more about x0 in our [blog post](https://compositor.io/blog/x0-making-react-component-development-stupid-simple/).
|
||||
|
||||
\* Custom [webpack configuration](#webpack) is required for components that rely on webpack-based features
|
||||
|
||||
|
||||
|
16
cli.js
16
cli.js
@ -15,27 +15,27 @@ const pkg = readPkg().pkg
|
||||
log.name = 'x0'
|
||||
|
||||
const cli = meow(`
|
||||
Usage
|
||||
${chalk.gray('Usage')}
|
||||
|
||||
Dev Server
|
||||
${chalk.gray('Dev Server')}
|
||||
|
||||
x0 pages
|
||||
${chalk.cyan('x0 pages')}
|
||||
|
||||
Build
|
||||
${chalk.gray('Build')}
|
||||
|
||||
x0 build pages
|
||||
${chalk.cyan('x0 build pages')}
|
||||
|
||||
Options
|
||||
${chalk.gray('Options')}
|
||||
|
||||
--webpack Path to webpack config file
|
||||
--match Glob pattern to match files against
|
||||
|
||||
Dev Server
|
||||
${chalk.gray('Dev Server')}
|
||||
|
||||
-o --open Open dev server in default browser
|
||||
-p --port Port for dev server
|
||||
|
||||
Build
|
||||
${chalk.gray('Build')}
|
||||
|
||||
-d --out-dir Output directory (default dist)
|
||||
-s --static Output static HTML without JS bundle
|
||||
|
37
docs/dynamic.js
Normal file
37
docs/dynamic.js
Normal file
@ -0,0 +1,37 @@
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
const routes = [
|
||||
{ path: '/dynamic' },
|
||||
{ path: '/dynamic/hello' },
|
||||
{ path: '/dynamic/hi' },
|
||||
]
|
||||
|
||||
export default class extends React.Component {
|
||||
static getInitialProps = async ({ path }) => {
|
||||
let title = 'dynamic'
|
||||
switch (path) {
|
||||
case '/dynamic/hello':
|
||||
title = 'hello'
|
||||
break
|
||||
case '/dynamic/hi':
|
||||
title = 'hi'
|
||||
break
|
||||
}
|
||||
return {
|
||||
routes,
|
||||
path: '/dynamic/:id*',
|
||||
title,
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
return <div>
|
||||
<pre>dynamic routing</pre>
|
||||
<Link to='/'>Home</Link>
|
||||
<Link to='/dynamic'>Dynamic Routes</Link>
|
||||
<Link to='/dynamic/hello'>Hello</Link>
|
||||
<Link to='/dynamic/hi'>Hi</Link>
|
||||
</div>
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
Editing `App.js` will live update in the development server.
|
||||
Editing `index.js` will live update in the development server.
|
||||
|
||||
## Static Build
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
<!DOCTYPE html><html><head><title></title><meta charset="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><meta name="description"/></head><body><div id="app"><h1>Hello</h1></div></body></html>
|
@ -2,11 +2,10 @@
|
||||
"name": "x0-basic-example",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "x0 dev App.js -o",
|
||||
"build": "x0 build App.js > index.html",
|
||||
"test": "x0 build App.js"
|
||||
"start": "x0 . -o",
|
||||
"build": "x0 build ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@compositor/x0": "^3.2.0"
|
||||
"@compositor/x0": "^5.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
Editing `App.js` will live update in the development server.
|
||||
Editing `pages/index.js` will live update in the development server.
|
||||
|
||||
## Static Build
|
||||
|
||||
@ -19,6 +19,6 @@ Editing `App.js` will live update in the development server.
|
||||
npm run build
|
||||
```
|
||||
|
||||
This should save a `bundle.js` file which will rehydrate state in the `index.html`.
|
||||
This will save a `bundle.js` file which will rehydrate state in the `index.html`.
|
||||
|
||||
To view the output app, run a local server in the `site/` directory.
|
||||
To view the output app, run a local server in the `dist/` directory.
|
||||
|
@ -2,18 +2,15 @@
|
||||
"name": "x0-bundle-example",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "x0 dev App.js -o",
|
||||
"build": "x0 build App.js --out-dir ./site",
|
||||
"test": "x0 build App.js"
|
||||
"start": "x0 pages -o",
|
||||
"build": "x0 build pages"
|
||||
},
|
||||
"dependencies": {
|
||||
"@compositor/x0": "^3.2.0",
|
||||
"refunk": "^2.2.4"
|
||||
"@compositor/x0": "^5.0.0",
|
||||
"refunk": "^3.0.1"
|
||||
},
|
||||
"x0": {
|
||||
"title": "x0 Bundle Example",
|
||||
"description": "Just a simple example",
|
||||
"css": "*{box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,sans-serif;margin:0}",
|
||||
"count": 16
|
||||
"description": "Just a simple example"
|
||||
}
|
||||
}
|
||||
|
@ -16,4 +16,8 @@ const App = connect(props => (
|
||||
</div>
|
||||
))
|
||||
|
||||
App.defaultProps = {
|
||||
count: 16
|
||||
}
|
||||
|
||||
export default App
|
@ -11,7 +11,7 @@ npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
Editing `App.js` will live update in the development server.
|
||||
Editing `pages/index.js` will live update in the development server.
|
||||
|
||||
## Static Build
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
<!DOCTYPE html><html><head><title>x0 Configuration Example</title><meta charset="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><meta name="description" content="Just a simple example"/><style>*{box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,sans-serif;margin:0}</style></head><body><div id="app"><h1>Hello</h1></div></body></html>
|
@ -2,16 +2,14 @@
|
||||
"name": "x0-configuration-example",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "x0 dev App.js -o",
|
||||
"build": "x0 build App.js > index.html",
|
||||
"test": "x0 build App.js"
|
||||
"start": "x0 pages -o",
|
||||
"build": "x0 build pages"
|
||||
},
|
||||
"dependencies": {
|
||||
"@compositor/x0": "^3.2.0"
|
||||
"@compositor/x0": "^5.0.0"
|
||||
},
|
||||
"x0": {
|
||||
"title": "x0 Configuration Example",
|
||||
"description": "Just a simple example",
|
||||
"css": "*{box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,sans-serif;margin:0}"
|
||||
"description": "Just a simple example"
|
||||
}
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
import React from 'react'
|
||||
import cxs from 'cxs/component'
|
||||
|
||||
const Root = cxs('div')({
|
||||
padding: '48px'
|
||||
})
|
||||
|
||||
const Heading = cxs('h1')({
|
||||
fontSize: '48px',
|
||||
margin: 0
|
||||
})
|
||||
|
||||
const Button = cxs('button')(props => ({
|
||||
display: 'inline-block',
|
||||
fontFamily: 'inherit',
|
||||
fontSize: '14px',
|
||||
paddingTop: '6px',
|
||||
paddingBottom: '6px',
|
||||
paddingLeft: '12px',
|
||||
paddingRight: '12px',
|
||||
border: 0,
|
||||
borderRadius: '4px',
|
||||
color: 'white',
|
||||
backgroundColor: props.color,
|
||||
WebkitAppearance: 'none'
|
||||
}))
|
||||
|
||||
Button.defaultProps = {
|
||||
color: '#07c'
|
||||
}
|
||||
|
||||
const App = props => (
|
||||
<Root>
|
||||
<Heading>Hello CXS</Heading>
|
||||
<Button>
|
||||
Beep
|
||||
</Button>
|
||||
</Root>
|
||||
)
|
||||
|
||||
export default App
|
@ -1,20 +0,0 @@
|
||||
import React from 'react'
|
||||
import { Html } from '@compositor/x0'
|
||||
import cxs from 'cxs'
|
||||
|
||||
const basecss = `*{box-sizing:border-box}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,sans-serif;margin:0}`
|
||||
|
||||
const Root = props => {
|
||||
const css = basecss + cxs.css()
|
||||
|
||||
return (
|
||||
<Html
|
||||
{...props}
|
||||
title='x0 CXS'
|
||||
css={css}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default Root
|
@ -1,13 +0,0 @@
|
||||
{
|
||||
"name": "x0-cxs-example",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "x0 dev App.js -o",
|
||||
"build": "x0 build App.js --html Root.js --out-dir ./site",
|
||||
"test": "x0 build App.js --html Root.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"cxs": "^6.0.0",
|
||||
"@compositor/x0": "^1.0.9"
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
|
||||
# x0 CXS example
|
||||
# x0 emotion example
|
||||
|
||||
```sh
|
||||
npm install
|
||||
@ -16,5 +16,3 @@ npm start
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
When building static, CSS will be added to a `<style>` tag in the head.
|
10
examples/emotion/components/Container.js
Normal file
10
examples/emotion/components/Container.js
Normal file
@ -0,0 +1,10 @@
|
||||
import styled from 'react-emotion'
|
||||
|
||||
const Container = styled('div')({
|
||||
maxWidth: 768,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
padding: 32,
|
||||
})
|
||||
|
||||
export default Container
|
8
examples/emotion/components/Heading.js
Normal file
8
examples/emotion/components/Heading.js
Normal file
@ -0,0 +1,8 @@
|
||||
import styled from 'react-emotion'
|
||||
|
||||
const Heading = styled('h1')({
|
||||
margin: 0,
|
||||
fontSize: 32
|
||||
})
|
||||
|
||||
export default Heading
|
2
examples/emotion/components/index.js
Normal file
2
examples/emotion/components/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
export { default as Container } from './Container'
|
||||
export { default as Heading } from './Heading'
|
14
examples/emotion/package.json
Normal file
14
examples/emotion/package.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "x0-emotion-example",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"start": "x0 pages",
|
||||
"build": "x0 build pages"
|
||||
},
|
||||
"dependencies": {
|
||||
"@compositor/x0": "^5.0.0",
|
||||
"emotion": "^9.1.3",
|
||||
"react-emotion": "^9.1.3"
|
||||
}
|
||||
}
|
11
examples/emotion/pages/index.js
Normal file
11
examples/emotion/pages/index.js
Normal file
@ -0,0 +1,11 @@
|
||||
import React from 'react'
|
||||
import {
|
||||
Container,
|
||||
Heading
|
||||
} from '../components'
|
||||
|
||||
export default () => (
|
||||
<Container>
|
||||
<Heading>Hello emotion</Heading>
|
||||
</Container>
|
||||
)
|
@ -1,51 +0,0 @@
|
||||
import React from 'react'
|
||||
|
||||
const URL = 'https://api.graph.cool/simple/v1/cj90efsm60hka01721jcnbn53'
|
||||
|
||||
import { request } from 'graphql-request'
|
||||
|
||||
import { ThemeProvider } from 'glamorous'
|
||||
import theme from './theme'
|
||||
|
||||
import {
|
||||
H1,
|
||||
Flex,
|
||||
Font,
|
||||
Profile,
|
||||
Container
|
||||
} from './components'
|
||||
|
||||
const App = props =>
|
||||
<ThemeProvider theme={theme}>
|
||||
<Font>
|
||||
<Container>
|
||||
<H1 mb={5}>Compositor Team</H1>
|
||||
|
||||
<Flex
|
||||
children={props.team.map(t =>
|
||||
<Profile
|
||||
avatar={t.avatarUrl}
|
||||
name={t.name}
|
||||
location={t.location}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Container>
|
||||
</Font>
|
||||
</ThemeProvider>
|
||||
|
||||
App.getInitialProps = async () => {
|
||||
const query = `{
|
||||
allTeamMembers {
|
||||
avatarUrl
|
||||
location
|
||||
name
|
||||
}
|
||||
}`
|
||||
|
||||
const { allTeamMembers } = await request(URL, query)
|
||||
|
||||
return { team: allTeamMembers }
|
||||
}
|
||||
|
||||
export default App
|
@ -1,131 +0,0 @@
|
||||
{
|
||||
"name": "graphql-example",
|
||||
"library": "glamorous",
|
||||
"components": [
|
||||
{
|
||||
"name": "Avatar",
|
||||
"type": "img",
|
||||
"props": {
|
||||
"w": 100,
|
||||
"borderRadius": 9999,
|
||||
"borderWidth": 1,
|
||||
"borderColor": "lightgray"
|
||||
},
|
||||
"style": {
|
||||
"display": "block",
|
||||
"maxWidth": "100%",
|
||||
"height": "auto"
|
||||
},
|
||||
"examples": [
|
||||
"<Avatar src='https://compositor.io/images/jxnblk.png' />"
|
||||
],
|
||||
"system": [
|
||||
"borderRadius",
|
||||
"borderWidth",
|
||||
"borderColor"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "H3",
|
||||
"type": "h3",
|
||||
"props": {},
|
||||
"style": {},
|
||||
"examples": [
|
||||
"<H3>Hello</H3>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "H6",
|
||||
"type": "h6",
|
||||
"props": {
|
||||
"f": 2,
|
||||
"my": 0
|
||||
},
|
||||
"style": {
|
||||
"textTransform": "uppercase",
|
||||
"letterSpacing": "2px"
|
||||
},
|
||||
"examples": [
|
||||
"<H6>Hello</H6>"
|
||||
],
|
||||
"system": []
|
||||
},
|
||||
{
|
||||
"name": "Profile",
|
||||
"imports": [
|
||||
"Avatar",
|
||||
"H3",
|
||||
"H6",
|
||||
"Div"
|
||||
],
|
||||
"jsx": "<Div text='center'>\n <Avatar\n m='auto'\n src={props.avatar}\n />\n <H3\n mt={2}\n mb={0}\n children={props.name}\n />\n <H6\n children={props.location}\n />\n</Div>",
|
||||
"examples": [
|
||||
"<Profile\n avatar='https://compositor.io/images/jxnblk.png'\n name='Brent Jackson'\n location='nyc'\n/>"
|
||||
],
|
||||
"system": []
|
||||
},
|
||||
{
|
||||
"name": "Div",
|
||||
"type": "div",
|
||||
"props": {
|
||||
"text": "left"
|
||||
},
|
||||
"style": {
|
||||
"textAlign": "${props.text}"
|
||||
},
|
||||
"examples": [
|
||||
"<Div>Hello</Div>"
|
||||
],
|
||||
"system": []
|
||||
},
|
||||
{
|
||||
"name": "Font",
|
||||
"type": "div",
|
||||
"props": {},
|
||||
"style": {
|
||||
"fontFamily": "${props.theme.fonts[0]}"
|
||||
},
|
||||
"examples": [
|
||||
"<Font>Hello</Font>"
|
||||
],
|
||||
"system": []
|
||||
},
|
||||
{
|
||||
"name": "H1",
|
||||
"type": "h1",
|
||||
"props": {},
|
||||
"style": {},
|
||||
"examples": [
|
||||
"<H1>Hello</H1>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Flex",
|
||||
"type": "div",
|
||||
"props": {},
|
||||
"style": {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between"
|
||||
},
|
||||
"examples": [
|
||||
"<Flex>Hello</Flex>"
|
||||
],
|
||||
"system": []
|
||||
},
|
||||
{
|
||||
"name": "Container",
|
||||
"type": "div",
|
||||
"props": {
|
||||
"p": 3
|
||||
},
|
||||
"style": {
|
||||
"maxWidth": "64rem",
|
||||
"margin": "auto"
|
||||
},
|
||||
"examples": [
|
||||
"<Container>Hello</Container>"
|
||||
],
|
||||
"system": []
|
||||
}
|
||||
]
|
||||
}
|
@ -1,14 +1,11 @@
|
||||
{
|
||||
"name": "x0-graphql-example",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "lab --pkg -wd components | x0 dev App -s"
|
||||
"start": "x0 pages"
|
||||
},
|
||||
"dependencies": {
|
||||
"@compositor/lab": "^1.0.0-32",
|
||||
"@compositor/x0": "^2.0.0-8",
|
||||
"glamor": "^2.20.40",
|
||||
"glamorous": "^4.10.0",
|
||||
"graphql-request": "^1.4.0",
|
||||
"styled-system": "^1.0.8"
|
||||
"@compositor/x0": "^5.0.0",
|
||||
"graphql-request": "^1.4.0"
|
||||
}
|
||||
}
|
||||
|
38
examples/graphql/pages/index.js
Normal file
38
examples/graphql/pages/index.js
Normal file
@ -0,0 +1,38 @@
|
||||
import React from 'react'
|
||||
import { request } from 'graphql-request'
|
||||
|
||||
const URL = 'https://api.graph.cool/simple/v1/cj90efsm60hka01721jcnbn53'
|
||||
|
||||
const App = props =>
|
||||
<div>
|
||||
<h1>GraphQL Example</h1>
|
||||
<div>
|
||||
{props.team.map(({ name, avatarUrl, location }) =>
|
||||
<div key={name}>
|
||||
<img
|
||||
src={avatarUrl}
|
||||
width='48'
|
||||
height='48'
|
||||
/>
|
||||
<h2>{name}</h2>
|
||||
<div>{location}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
App.getInitialProps = async () => {
|
||||
const query = `{
|
||||
allTeamMembers {
|
||||
avatarUrl
|
||||
location
|
||||
name
|
||||
}
|
||||
}`
|
||||
|
||||
const { allTeamMembers } = await request(URL, query)
|
||||
|
||||
return { team: allTeamMembers }
|
||||
}
|
||||
|
||||
export default App
|
@ -11,7 +11,7 @@ npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
Editing `App.js` will live update in the development server.
|
||||
Editing `pages/index.js` will live update in the development server.
|
||||
|
||||
## Static Build
|
||||
|
||||
@ -19,4 +19,6 @@ Editing `App.js` will live update in the development server.
|
||||
npm run build
|
||||
```
|
||||
|
||||
Be sure to copy the image to the output folder or use an absolute URL.
|
||||
|
||||
Image credit: [Scott Webb](https://unsplash.com/photos/N1mAtFiMQzM)
|
||||
|
@ -2,11 +2,10 @@
|
||||
"name": "x0-images-example",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "x0 dev App.js -o",
|
||||
"build": "x0 build App.js > index.html",
|
||||
"test": "x0 build App.js"
|
||||
"start": "x0 pages -o",
|
||||
"build": "x0 build pages"
|
||||
},
|
||||
"dependencies": {
|
||||
"@compositor/x0": "^3.2.0"
|
||||
"@compositor/x0": "^5.0.0"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
22
examples/jsx/README.md
Normal file
22
examples/jsx/README.md
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
# x0 jsx example
|
||||
|
||||
Use [Compositor JSX format][jsx] for pages
|
||||
|
||||
[jsx]: https://github.com/c8r/jsx-loader
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
## Dev Server
|
||||
|
||||
```sh
|
||||
npm start
|
||||
```
|
||||
|
||||
## Build
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
12
examples/jsx/package.json
Normal file
12
examples/jsx/package.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "x0-jsx-example",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "x0 pages",
|
||||
"build": "x0 build pages"
|
||||
},
|
||||
"dependencies": {
|
||||
"@compositor/x0": "^5.0.0",
|
||||
"rebass": "^2.0.0-2"
|
||||
}
|
||||
}
|
3
examples/jsx/pages/_scope.js
Normal file
3
examples/jsx/pages/_scope.js
Normal file
@ -0,0 +1,3 @@
|
||||
import * as scope from 'rebass'
|
||||
|
||||
export default scope
|
12
examples/jsx/pages/index.jsx
Normal file
12
examples/jsx/pages/index.jsx
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
title: Hello JSX
|
||||
scope: import scope from './_scope'
|
||||
---
|
||||
<Box px={3} py={4}>
|
||||
<Heading is='h1' mb={2}>
|
||||
{props.title}
|
||||
</Heading>
|
||||
<Text>
|
||||
With <Link href='https://jxnblk.com/rebass'>Rebass</Link> in scope
|
||||
</Text>
|
||||
</Box>
|
22
examples/mdx/README.md
Normal file
22
examples/mdx/README.md
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
# x0 mdx example
|
||||
|
||||
Use [MDX format][mdx] for pages
|
||||
|
||||
[mdx]: https://github.com/mdx-js/mdx
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
## Dev Server
|
||||
|
||||
```sh
|
||||
npm start
|
||||
```
|
||||
|
||||
## Build
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
12
examples/mdx/package.json
Normal file
12
examples/mdx/package.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "x0-mdx-example",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "x0 pages",
|
||||
"build": "x0 build pages"
|
||||
},
|
||||
"dependencies": {
|
||||
"@compositor/x0": "^5.0.0",
|
||||
"rebass": "^2.0.0-2"
|
||||
}
|
||||
}
|
9
examples/mdx/pages/index.mdx
Normal file
9
examples/mdx/pages/index.mdx
Normal file
@ -0,0 +1,9 @@
|
||||
import { Provider, Box, Heading } from 'rebass'
|
||||
|
||||
# Hello MDX
|
||||
|
||||
<Provider>
|
||||
<Box px={2} py={3}>
|
||||
<Heading>Hello</Heading>
|
||||
</Box>
|
||||
</Provider>
|
50
examples/react-router/App.js
vendored
50
examples/react-router/App.js
vendored
@ -1,50 +0,0 @@
|
||||
import React from 'react'
|
||||
import {
|
||||
BrowserRouter,
|
||||
StaticRouter,
|
||||
Route,
|
||||
Link
|
||||
} from 'react-router-dom'
|
||||
import cxs from 'cxs/component'
|
||||
|
||||
const Root = cxs('div')({
|
||||
padding: '48px'
|
||||
})
|
||||
|
||||
const Heading = cxs('h1')({
|
||||
fontSize: '48px',
|
||||
margin: 0
|
||||
})
|
||||
|
||||
const App = props => {
|
||||
const Main = typeof document !== 'undefined'
|
||||
? BrowserRouter
|
||||
: StaticRouter
|
||||
|
||||
return (
|
||||
<Main
|
||||
context={{}}
|
||||
location={props.pathname}>
|
||||
<Root>
|
||||
<Heading>Hello react-router</Heading>
|
||||
<nav>
|
||||
<Link to='/'>Home</Link>
|
||||
<Link to='/about'>About</Link>
|
||||
</nav>
|
||||
<Route
|
||||
exact path='/'
|
||||
component={Home}
|
||||
/>
|
||||
<Route
|
||||
path='/about'
|
||||
component={About}
|
||||
/>
|
||||
</Root>
|
||||
</Main>
|
||||
)
|
||||
}
|
||||
|
||||
const Home = () => <Heading>Home</Heading>
|
||||
const About = () => <Heading>About</Heading>
|
||||
|
||||
export default App
|
18
examples/react-router/Root.js
vendored
18
examples/react-router/Root.js
vendored
@ -1,18 +0,0 @@
|
||||
import React from 'react'
|
||||
import { Html } from '@compositor/x0'
|
||||
|
||||
const css = `*{box-sizing:border-box}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,sans-serif;margin:0}`
|
||||
|
||||
const Root = props => {
|
||||
|
||||
return (
|
||||
<Html
|
||||
{...props}
|
||||
title='x0 react-router'
|
||||
css={css}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default Root
|
@ -2,20 +2,15 @@
|
||||
"name": "x0-react-router-example",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "x0 dev App.js -o",
|
||||
"build": "x0 build App.js --html Root.js --out-dir ./site",
|
||||
"test": "x0 build App.js --html Root.js"
|
||||
"start": "x0 pages -o",
|
||||
"build": "x0 build pages"
|
||||
},
|
||||
"dependencies": {
|
||||
"@compositor/x0": "^1.0.9",
|
||||
"cxs": "^6.2.0",
|
||||
"react-router-dom": "^4.2.2"
|
||||
"@compositor/x0": "^5.0.0",
|
||||
"react-router-dom": "^4.2.2",
|
||||
"styled-components": "^3.3.0"
|
||||
},
|
||||
"x0": {
|
||||
"title": "x0 react-router",
|
||||
"routes": [
|
||||
"/",
|
||||
"/about"
|
||||
]
|
||||
"title": "x0 routing"
|
||||
}
|
||||
}
|
||||
|
17
examples/react-router/pages/_app.js
vendored
Normal file
17
examples/react-router/pages/_app.js
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import styled from 'styled-components'
|
||||
|
||||
const Root = styled('div')({
|
||||
padding: '48px'
|
||||
})
|
||||
|
||||
export default ({ render }) => (
|
||||
<Root>
|
||||
<nav>
|
||||
<Link to='/'>Home</Link>
|
||||
<Link to='/about'>About</Link>
|
||||
</nav>
|
||||
{render()}
|
||||
</Root>
|
||||
)
|
5
examples/react-router/pages/about.js
vendored
Normal file
5
examples/react-router/pages/about.js
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
import React from 'react'
|
||||
|
||||
export default props => (
|
||||
<h1>About</h1>
|
||||
)
|
6
examples/react-router/pages/index.js
vendored
Normal file
6
examples/react-router/pages/index.js
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
export default props => (
|
||||
<h1>Home</h1>
|
||||
)
|
@ -2,12 +2,12 @@
|
||||
"name": "x0-styled-components-example",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "x0 dev App.js -o",
|
||||
"build": "x0 build App.js --out-dir ./site"
|
||||
"start": "x0 pages -o",
|
||||
"build": "x0 build pages"
|
||||
},
|
||||
"dependencies": {
|
||||
"@compositor/x0": "^3.2.0",
|
||||
"refunk": "^2.0.0-1",
|
||||
"styled-components": "^2.2.1"
|
||||
"@compositor/x0": "^5.0.0",
|
||||
"refunk": "^3.0.1",
|
||||
"styled-components": "^3.3.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
import React from 'react'
|
||||
import styled, { ServerStyleSheet } from 'styled-components'
|
||||
import styled from 'styled-components'
|
||||
import { connect } from 'refunk'
|
||||
|
||||
const css = `*{box-sizing:border-box}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,sans-serif;margin:0}`
|
||||
|
||||
const Root = styled('div')([], {
|
||||
padding: '48px'
|
||||
})
|
||||
@ -44,24 +41,13 @@ const dec = state => ({ count: state.count - 1 })
|
||||
const inc = state => ({ count: state.count + 1 })
|
||||
|
||||
const App = connect(props => [
|
||||
props.styles && (
|
||||
<head
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: props.styles || ''
|
||||
}}
|
||||
/>
|
||||
),
|
||||
<Root>
|
||||
<div id='app'>
|
||||
<title>x0 styled-components {props.count}</title>
|
||||
<style dangerouslySetInnerHTML={{ __html: css }} />
|
||||
<Heading>Hello x0 styled-components</Heading>
|
||||
<Button
|
||||
color={colors[props.count % colors.length]}
|
||||
onClick={e => props.update(inc)}>
|
||||
Beep {props.count}
|
||||
</Button>
|
||||
</div>
|
||||
<Heading>Hello x0 styled-components</Heading>
|
||||
<Button
|
||||
color={colors[props.count % colors.length]}
|
||||
onClick={e => props.update(inc)}>
|
||||
Beep {props.count}
|
||||
</Button>
|
||||
</Root>
|
||||
])
|
||||
|
||||
@ -70,11 +56,4 @@ App.defaultProps = {
|
||||
count: 0
|
||||
}
|
||||
|
||||
App.getInitialProps = ({ Component, props }) => {
|
||||
const sheet = new ServerStyleSheet()
|
||||
sheet.collectStyles(<Component {...props} />)
|
||||
const styles = sheet.getStyleTags()
|
||||
return { styles }
|
||||
}
|
||||
|
||||
export default App
|
@ -11,7 +11,7 @@ npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
Editing `App.js` will live update in the development server.
|
||||
Editing `pages/index.js` will live update in the development server.
|
||||
|
||||
## Static Build
|
||||
|
||||
|
@ -2,12 +2,11 @@
|
||||
"name": "x0-webpack-config-example",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "x0 dev App.js -oc webpack.config.js",
|
||||
"build": "x0 build App.js -c webpack.config.js -d ./site",
|
||||
"test": "x0 build App.js -c webpack.config.js"
|
||||
"start": "x0 pages -o",
|
||||
"build": "x0 build pages"
|
||||
},
|
||||
"dependencies": {
|
||||
"@compositor/x0": "^3.2.0-2",
|
||||
"@compositor/x0": "^5.0.0",
|
||||
"html-loader": "^0.5.5",
|
||||
"markdown-loader": "^2.0.2"
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react'
|
||||
import readme from './README.md'
|
||||
import readme from '../README.md'
|
||||
|
||||
const App = props => (
|
||||
<div>
|
33
lib/build.js
33
lib/build.js
@ -125,16 +125,29 @@ const getRoutes = async (App) => {
|
||||
const routes = await App.getRoutes()
|
||||
|
||||
const dynamicRoutes = []
|
||||
routes.forEach(route => {
|
||||
if (route.props.routes) {
|
||||
route.props.routes.forEach(subroute => dynamicRoutes.push(
|
||||
Object.assign({}, route, subroute)
|
||||
))
|
||||
}
|
||||
})
|
||||
await Promise.all(
|
||||
routes.map(async route => {
|
||||
if (!route.props.routes) return null
|
||||
await Promise.all(
|
||||
route.props.routes.map(async subroute => {
|
||||
const pageProps = typeof route.Component.getInitialProps === 'function'
|
||||
? await route.Component.getInitialProps(subroute)
|
||||
: {}
|
||||
dynamicRoutes.push(
|
||||
Object.assign({}, route, subroute, {
|
||||
props: Object.assign({}, route.props, subroute.props, pageProps)
|
||||
})
|
||||
)
|
||||
return
|
||||
})
|
||||
)
|
||||
return
|
||||
})
|
||||
)
|
||||
|
||||
const staticRoutes = [
|
||||
...routes.filter(route => !route.props.routes),
|
||||
...dynamicRoutes
|
||||
...dynamicRoutes.filter(route => !!route)
|
||||
]
|
||||
return { routes, staticRoutes }
|
||||
}
|
||||
@ -205,6 +218,10 @@ module.exports = async (opts) => {
|
||||
return
|
||||
}
|
||||
remove(opts.tempdir)
|
||||
if (opts.static) {
|
||||
const bundle = path.join(opts.outDir, 'bundle.js')
|
||||
remove(bundle)
|
||||
}
|
||||
resolve(stats)
|
||||
})
|
||||
})
|
||||
|
@ -52,6 +52,7 @@ module.exports = {
|
||||
modules: [
|
||||
__dirname,
|
||||
path.join(__dirname, '../node_modules'),
|
||||
path.relative(process.cwd(), path.join(__dirname, '../node_modules')),
|
||||
'node_modules'
|
||||
]
|
||||
},
|
||||
|
@ -17,6 +17,7 @@ const dev = {
|
||||
}
|
||||
|
||||
module.exports = async (opts) => {
|
||||
if (opts.basename) delete opts.basename
|
||||
const config = merge(baseConfig, opts.webpack)
|
||||
const template = createTemplate(opts)
|
||||
|
||||
@ -60,6 +61,7 @@ module.exports = async (opts) => {
|
||||
config,
|
||||
dev,
|
||||
logLevel: 'error',
|
||||
content: opts.dirname,
|
||||
port: opts.port,
|
||||
hot: { logLevel: 'error' },
|
||||
add: (app, middleware, options) => {
|
||||
|
55
package.json
55
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@compositor/x0",
|
||||
"version": "5.0.0-13",
|
||||
"version": "5.0.5",
|
||||
"description": "Zero-config React development environment and static site generator",
|
||||
"main": "index.js",
|
||||
"bin": {
|
||||
@ -9,14 +9,25 @@
|
||||
"scripts": {
|
||||
"start": "./cli.js docs -op 8888",
|
||||
"build": "./cli.js build docs",
|
||||
"test": "nyc ava",
|
||||
"test": "ava -T 20s",
|
||||
"cover": "nyc report --reporter=html --reporter=lcov"
|
||||
},
|
||||
"keywords": [],
|
||||
"keywords": [
|
||||
"react",
|
||||
"webpack",
|
||||
"zero-config",
|
||||
"jsx",
|
||||
"mdx",
|
||||
"ui",
|
||||
"prototyping",
|
||||
"static-site-generator",
|
||||
"isolated",
|
||||
"design-systems"
|
||||
],
|
||||
"author": "Brent Jackson",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@compositor/jsx-loader": "^1.0.0-3",
|
||||
"@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",
|
||||
@ -36,7 +47,7 @@
|
||||
"find-up": "^2.1.0",
|
||||
"fs-extra": "^6.0.1",
|
||||
"glamor": "^2.20.40",
|
||||
"html-minifier": "^3.5.15",
|
||||
"html-minifier": "^3.5.16",
|
||||
"koa-connect": "^2.0.1",
|
||||
"meow": "^5.0.0",
|
||||
"mini-html-webpack-plugin": "^0.2.3",
|
||||
@ -50,17 +61,17 @@
|
||||
"read-pkg-up": "^3.0.0",
|
||||
"semver": "^5.5.0",
|
||||
"update-notifier": "^2.5.0",
|
||||
"webpack": "^4.8.3",
|
||||
"webpack": "^4.10.2",
|
||||
"webpack-merge": "^4.1.2",
|
||||
"webpack-serve": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@compositor/logo": "^1.3.5",
|
||||
"@compositor/md-loader": "^1.0.27",
|
||||
"@compositor/md-loader": "^1.0.34",
|
||||
"ava": "^0.25.0",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
"nano-style": "^1.0.0",
|
||||
"nyc": "^11.8.0",
|
||||
"nyc": "^12.0.1",
|
||||
"raw-loader": "^0.5.1",
|
||||
"rebass": "^2.0.0-2",
|
||||
"refunk": "^3.0.1",
|
||||
@ -70,7 +81,33 @@
|
||||
},
|
||||
"x0": {
|
||||
"title": "Compositor x0",
|
||||
"_basename": "/x0"
|
||||
"basename": "/x0",
|
||||
"meta": [
|
||||
{
|
||||
"name": "description",
|
||||
"content": "Zero-config React development environment and static site generator"
|
||||
},
|
||||
{
|
||||
"name": "twitter:card",
|
||||
"content": "summary"
|
||||
},
|
||||
{
|
||||
"name": "twitter:site",
|
||||
"content": "@getcompositor"
|
||||
},
|
||||
{
|
||||
"name": "twitter:image",
|
||||
"content": "https://compositor.io/logo/dist/compositor.png"
|
||||
},
|
||||
{
|
||||
"name": "twitter:title",
|
||||
"content": "Compositor x0"
|
||||
},
|
||||
{
|
||||
"name": "twitter:description",
|
||||
"content": "Zero-config React development environment and static site generator"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ava": {
|
||||
"files": [
|
||||
|
5
test/components/compositor.jsx
Normal file
5
test/components/compositor.jsx
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
className: beep
|
||||
---
|
||||
|
||||
<h1 className={`${props.className} boop`}>Hello</h1>
|
Loading…
Reference in New Issue
Block a user