mirror of
https://github.com/c8r/x0.git
synced 2024-07-14 16:50:34 +03:00
commit
016f1b9928
3
cli.js
3
cli.js
@ -41,7 +41,8 @@ const cli = meow(`
|
||||
-d --out-dir Output directory (default dist)
|
||||
-s --static Output static HTML without JS bundle
|
||||
-t --template Path to custom HTML template
|
||||
|
||||
--basename Basename for URL paths
|
||||
--title Page title
|
||||
`, {
|
||||
flags: {
|
||||
// dev
|
||||
|
19
docs/JSX.md
Normal file
19
docs/JSX.md
Normal file
@ -0,0 +1,19 @@
|
||||
---
|
||||
---
|
||||
|
||||
# Using JSX
|
||||
|
||||
x0 supports Compositor JSX format, which allows writing files as pure JSX without any JavaScript syntax.
|
||||
|
||||
```jsx
|
||||
---
|
||||
title: JSX Example
|
||||
---
|
||||
import { Box, Heading } from 'rebass'
|
||||
|
||||
<Box p={3} bg='tomato'>
|
||||
<Heading>
|
||||
Hello
|
||||
</Heading>
|
||||
</Box>
|
||||
```
|
20
docs/MDX.md
Normal file
20
docs/MDX.md
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
# Using MDX
|
||||
|
||||
x0 also supports [MDX][mdx] format out of the box.
|
||||
MDX allows you to mix markdown syntax with JSX to render React components.
|
||||
|
||||
```mdx
|
||||
---
|
||||
title: MDX Example
|
||||
---
|
||||
import { Box } from 'rebass'
|
||||
|
||||
# Hello
|
||||
|
||||
<Box p={3} bg='tomato'>
|
||||
Beep
|
||||
</Box>
|
||||
```
|
||||
|
||||
[mdx]: https://github.com/mdx-js/mdx
|
46
docs/_app.js
46
docs/_app.js
@ -8,9 +8,47 @@ import {
|
||||
Box,
|
||||
Container,
|
||||
} from 'rebass'
|
||||
import sortBy from 'lodash.sortby'
|
||||
|
||||
import LandingLayout from './_layout'
|
||||
import theme from './_theme'
|
||||
import X0 from './_logo'
|
||||
|
||||
const navOrder = [
|
||||
'index',
|
||||
'getting-started',
|
||||
'markdown',
|
||||
'react',
|
||||
'MDX',
|
||||
'JSX',
|
||||
'routing',
|
||||
'custom-app',
|
||||
'components',
|
||||
'ScopeProvider',
|
||||
'SidebarLayout',
|
||||
'LivePreview',
|
||||
'LiveEditor',
|
||||
'cli-options',
|
||||
'exporting',
|
||||
'examples',
|
||||
]
|
||||
const pageNames = {
|
||||
index: 'Home',
|
||||
'cli-options': 'CLI Options'
|
||||
}
|
||||
|
||||
const sortRoutes = routes => [
|
||||
...sortBy([...routes], a => {
|
||||
const i = navOrder.indexOf(a.name)
|
||||
return i < 0 ? Infinity : i
|
||||
})
|
||||
].map(route => {
|
||||
if (!pageNames[route.name]) return route
|
||||
return {
|
||||
...route,
|
||||
name: pageNames[route.name]
|
||||
}
|
||||
})
|
||||
|
||||
export default class App extends React.Component {
|
||||
static defaultProps = {
|
||||
@ -29,10 +67,16 @@ export default class App extends React.Component {
|
||||
? LandingLayout
|
||||
: SidebarLayout
|
||||
|
||||
const nav = sortRoutes(routes)
|
||||
|
||||
return (
|
||||
<ScopeProvider scope={scope}>
|
||||
<RebassProvider theme={theme}>
|
||||
<Layout {...this.props} />
|
||||
<Layout
|
||||
{...this.props}
|
||||
routes={nav}
|
||||
logo={<X0 size={24} color='magenta' />}
|
||||
/>
|
||||
</RebassProvider>
|
||||
</ScopeProvider>
|
||||
)
|
||||
|
27
docs/_logo-rect.js
Normal file
27
docs/_logo-rect.js
Normal file
@ -0,0 +1,27 @@
|
||||
import React from 'react'
|
||||
import X0 from './_logo'
|
||||
|
||||
export default ({
|
||||
size = 1024
|
||||
}) =>
|
||||
<svg
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
viewBox='0 0 24 12'
|
||||
width={size}
|
||||
height={size / 2}
|
||||
fill='none'
|
||||
stroke='currentcolor'
|
||||
>
|
||||
<rect
|
||||
width={24}
|
||||
height={12}
|
||||
stroke='none'
|
||||
fill='black'
|
||||
/>
|
||||
<g transform='translate(8, 2)'>
|
||||
<X0
|
||||
size={8}
|
||||
color='white'
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
29
docs/_logo.js
Normal file
29
docs/_logo.js
Normal file
@ -0,0 +1,29 @@
|
||||
import React from 'react'
|
||||
|
||||
export default ({
|
||||
size = 128,
|
||||
color = 'currentcolor'
|
||||
}) =>
|
||||
<svg
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
viewBox='-12 -12 24 24'
|
||||
width={size}
|
||||
height={size}
|
||||
fill='none'
|
||||
stroke={color}
|
||||
>
|
||||
<circle
|
||||
strokeWidth={2}
|
||||
opacity={4/4}
|
||||
r={11}
|
||||
/>
|
||||
<circle
|
||||
strokeWidth={1/4}
|
||||
r={11.75}
|
||||
opacity={0/4}
|
||||
/>
|
||||
<g opacity={4/4} strokeWidth={2}>
|
||||
<path d='M-5 -5 L5 5' />
|
||||
<path d='M-5 5 L5 -5' />
|
||||
</g>
|
||||
</svg>
|
39
docs/cli-options.md
Normal file
39
docs/cli-options.md
Normal file
@ -0,0 +1,39 @@
|
||||
---
|
||||
name: CLI Options
|
||||
---
|
||||
|
||||
# CLI Options
|
||||
|
||||
```
|
||||
--webpack Path to webpack config file
|
||||
--match String to match routes against using minimatch
|
||||
```
|
||||
|
||||
The following options are used for the development server.
|
||||
|
||||
```
|
||||
-o --open Open dev server in default browser
|
||||
-p --port Port for dev server
|
||||
--analyze Runs with webpack-bundle-analyzer plugin
|
||||
```
|
||||
|
||||
The following options are used for static export.
|
||||
|
||||
```
|
||||
-d --out-dir Output directory (default dist)
|
||||
-s --static Output static HTML without JS bundle
|
||||
-t --template Path to custom HTML template
|
||||
--basename Basename for URL paths
|
||||
--title Page title
|
||||
```
|
||||
|
||||
## package.json
|
||||
|
||||
CLI options can also be specified in a `package.json` field named `x0`.
|
||||
|
||||
```json
|
||||
"x0": {
|
||||
"title": "Hello",
|
||||
"basename": "/my-site"
|
||||
}
|
||||
```
|
17
docs/components/LiveEditor.md
Normal file
17
docs/components/LiveEditor.md
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
# LiveEditor
|
||||
|
||||
The LiveEditor component can be used in React components outside of markdown code fences.
|
||||
When used within a [ScopeProvider](ScopeProvider) component, there's no need to pass a custom `scope` object.
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
import { LiveEditor } from '@compositor/x0/components'
|
||||
|
||||
const code = `<Button>Hello</Button>`
|
||||
|
||||
export default props =>
|
||||
<LiveEditor
|
||||
code={code}
|
||||
/>
|
||||
```
|
17
docs/components/LivePreview.md
Normal file
17
docs/components/LivePreview.md
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
# LivePreview
|
||||
|
||||
The LivePreview component can be used in React components outside of markdown code fences.
|
||||
When used within a [ScopeProvider](ScopeProvider) component, there's no need to pass a custom `scope` object.
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
import { LivePreview } from '@compositor/x0/components'
|
||||
|
||||
const code = `<Button>Hello</Button>`
|
||||
|
||||
export default props =>
|
||||
<LivePreview
|
||||
code={code}
|
||||
/>
|
||||
```
|
17
docs/components/ScopeProvider.md
Normal file
17
docs/components/ScopeProvider.md
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
# ScopeProvider
|
||||
|
||||
The ScopeProvider component allows you to customize the components that are used to render markdown elements
|
||||
and to provide components in scope for rendering code fences as live previews.
|
||||
It's best to use this component in a [Custom App](/custom-app) component.
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
import ScopeProvider from '@compositor/x0/components'
|
||||
import * as scope from '../src'
|
||||
|
||||
export default props =>
|
||||
<ScopeProvider scope={scope}>
|
||||
{props.children}
|
||||
</ScopeProvider>
|
||||
```
|
134
docs/components/SidebarLayout.md
Normal file
134
docs/components/SidebarLayout.md
Normal file
@ -0,0 +1,134 @@
|
||||
|
||||
# SidebarLayout
|
||||
|
||||
The SidebarLayout component can be used to quickly create a documentation site with navigation.
|
||||
This site uses the SidebarLayout component for navigation and pagination in the documentation section.
|
||||
|
||||
To use the component, import it in a [custom App](/custom-app).
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
import { SidebarLayout } from '@compositor/x0/components'
|
||||
|
||||
export default props =>
|
||||
<SidebarLayout {...props} />
|
||||
```
|
||||
|
||||
## Customizing navigation
|
||||
|
||||
The `props.routes` array can be altered to customize the order, names, and other aspects of the navigation.
|
||||
|
||||
### Sorting the routes
|
||||
|
||||
By default the `routes` array is in alphabetical order, with index pages occuring first.
|
||||
To sort the array for display in navigation, pass a new `routes` prop to the SidebarLayout component.
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
import { SidebarLayout } from '@compositor/x0/components'
|
||||
import sortBy from 'lodash.sortby'
|
||||
|
||||
const navOrder = [
|
||||
'index',
|
||||
'getting-started',
|
||||
'api'
|
||||
]
|
||||
|
||||
export default props => {
|
||||
const sortedRoutes = sortBy(props.routes, route => {
|
||||
const i = navOrder.indexOf(route.name)
|
||||
return i
|
||||
})
|
||||
|
||||
return (
|
||||
<SidebarLayout
|
||||
{...props}
|
||||
routes={sortedRoutes}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Customizing Route Names
|
||||
|
||||
By default the layout will format the filename by capitalizing each word and removing hyphens.
|
||||
To customize the name of the routes for navigation, pass a new `routes` prop to the SidebarLayout component.
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
import { SidebarLayout } from '@compositor/x0/components'
|
||||
import sortBy from 'lodash.sortby'
|
||||
|
||||
const routeNames = {
|
||||
index: 'Home',
|
||||
api: 'API'
|
||||
}
|
||||
|
||||
export default props => {
|
||||
const renamedRoutes = props.routes.map(route => {
|
||||
if (!routeNames[route.name]) return route
|
||||
return {
|
||||
...route,
|
||||
name: routeNames[route.name]
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<SidebarLayout
|
||||
{...props}
|
||||
routes={renamedRoutes}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Full Width Pages
|
||||
|
||||
The SidebarLayout component will center the contents of the page by default.
|
||||
To make a page span the full width of the main column, set the `fullWidth` option in default props or front-matter.
|
||||
|
||||
```md
|
||||
---
|
||||
fullWidth: true
|
||||
---
|
||||
|
||||
# Full-width markdown page
|
||||
```
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
|
||||
export default class extends React.Component {
|
||||
static defaultProps = {
|
||||
fullWidth: true
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<h1>Full-width component</h1>
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Page-Specific Layouts
|
||||
|
||||
Custom layouts can be specified as front-matter or default props, then handled in a custom App component to control the layout for specific pages.
|
||||
|
||||
```jsx
|
||||
// example with custom layouts
|
||||
import React from 'react'
|
||||
import { SidebarLayout } from '@compositor/x0/components'
|
||||
import HomeLayout from './_home-layout.js'
|
||||
|
||||
export default props => {
|
||||
const { route } = this.props
|
||||
const { layout } = route.props
|
||||
|
||||
const Layout = layout === 'home' ? HomeLayout : SidebarLayout
|
||||
|
||||
return <Layout {...this.props} />
|
||||
}
|
||||
```
|
||||
|
||||
|
9
docs/components/index.md
Normal file
9
docs/components/index.md
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
# Built-in Components
|
||||
|
||||
x0 includes several built-in components to make creating a custom site quicker.
|
||||
|
||||
- [ScopeProvider](ScopeProvider)
|
||||
- [SidebarLayout](SidebarLayout)
|
||||
- [LivePreview](LivePreview)
|
||||
- [LiveEditor](LiveEditor)
|
126
docs/custom-app.md
Normal file
126
docs/custom-app.md
Normal file
@ -0,0 +1,126 @@
|
||||
|
||||
# Custom App Component
|
||||
|
||||
Use a custom App component to completely customize the layout, add context providers, use global state, or set a custom scope.
|
||||
|
||||
## Layouts
|
||||
|
||||
Create a file named `_app.js` to provider a custom App component to x0.
|
||||
This file can be used for custom layouts, including headers, footers, and navigation.
|
||||
|
||||
```jsx
|
||||
// _app.js
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import {
|
||||
Container,
|
||||
Toolbar,
|
||||
NavLink
|
||||
} from 'rebass'
|
||||
|
||||
export default class extends React.Component {
|
||||
render () {
|
||||
const { children } = this.props
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Toolbar>
|
||||
<NavLink is={Link} to='/'>
|
||||
Home
|
||||
</NavLink>
|
||||
</Toolbar>
|
||||
<Container>
|
||||
{children}
|
||||
</Container>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Providers
|
||||
|
||||
Context providers, such as styled-component's `ThemeProvider` can be included in a custom app.
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
import { ThemeProvider } from 'styled-components'
|
||||
import theme from '../src/theme'
|
||||
|
||||
export default props =>
|
||||
<ThemeProvider theme={theme}>
|
||||
<React.Fragment>
|
||||
{props.children}
|
||||
</React.Fragment>
|
||||
</ThemeProvider>
|
||||
```
|
||||
|
||||
## Scope
|
||||
|
||||
Use the x0 `ScopeProvider` to customize the components used when rendering markdown elements in `.md` or `.mdx` files.
|
||||
The `ScopeProvider` also provides scope to [live code examples](markdown/#code-fences) in code fences.
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
import { ScopeProvider } from '@compositor/x0/components'
|
||||
import * as scope from '../src'
|
||||
|
||||
export default props =>
|
||||
<ScopeProvider scope={scope}>
|
||||
{props.children}
|
||||
</ScopeProvider>
|
||||
```
|
||||
|
||||
## App State
|
||||
|
||||
Global application state can also be provided in a custom App.
|
||||
Use `props.Component` instead of `props.children` to pass props to the rendered route.
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
|
||||
export default class extends React.Component {
|
||||
state = {
|
||||
count: 0
|
||||
}
|
||||
|
||||
update = fn => this.setState(fn)
|
||||
|
||||
render () {
|
||||
const { Component } = this.props
|
||||
|
||||
return (
|
||||
<Component
|
||||
{...this.state}
|
||||
update={this.update}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
Custom Apps receive the following props, which can expose greater control over the rendering.
|
||||
|
||||
- `children`: rendered content of the page
|
||||
- `Component`: a component to pass props to the current route and render content
|
||||
- `routes`: an array of route objects for the entire site – can be used for rendering navigation
|
||||
- `route`: the current route object
|
||||
- The [React Router][react-router] state is also passed to the App
|
||||
|
||||
### Route Object
|
||||
|
||||
Routes include the following properties:
|
||||
|
||||
- `key`: the filepath from webpack's `require.context`
|
||||
- `name`: the basename of the file
|
||||
- `path`: path used for routing
|
||||
- `extname`: file extension
|
||||
- `dirname`: file directory
|
||||
- `exact`: (boolean) added to index pages for React Router
|
||||
- `module`: the JS module for the file
|
||||
- `Component`: the default export from the file
|
||||
- `props`: default props or front-matter specified in the file
|
||||
|
||||
[react-router]: https://github.com/ReactTraining/react-router
|
||||
|
5
docs/examples.md
Normal file
5
docs/examples.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
ignore: true
|
||||
---
|
||||
|
||||
# Examples
|
49
docs/exporting.md
Normal file
49
docs/exporting.md
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
# Exporting
|
||||
|
||||
x0 sites can be exported as static sites using the `x0 build` command.
|
||||
|
||||
```sh
|
||||
x0 build docs
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
Options for static export can be passed as flags or specified in a `package.json` field named `x0`.
|
||||
|
||||
```
|
||||
-d --out-dir Output directory (default dist)
|
||||
-s --static Output static HTML without JS bundle
|
||||
-t --template Path to custom HTML template
|
||||
--basename Basename for URL paths
|
||||
--title Page title
|
||||
```
|
||||
|
||||
## Custom HTML Templates
|
||||
|
||||
A custom HTML template function can be used for greater control over the HTML output.
|
||||
|
||||
```js
|
||||
module.exports = ({
|
||||
html = '',
|
||||
css = '',
|
||||
scripts,
|
||||
title = 'x0',
|
||||
meta = [],
|
||||
links = [],
|
||||
}) =>
|
||||
`<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
||||
<title>${title}</title>
|
||||
${css}
|
||||
</head>
|
||||
<div id=root>${html}</div>
|
||||
${scripts}
|
||||
`
|
||||
```
|
||||
|
||||
See the [default template][template] for an example.
|
||||
|
||||
[template]: https://github.com/c8r/x0/blob/master/lib/template.js
|
92
docs/getting-started.md
Normal file
92
docs/getting-started.md
Normal file
@ -0,0 +1,92 @@
|
||||
---
|
||||
---
|
||||
|
||||
# Getting Started
|
||||
|
||||
Install x0 either globally or as a dev dependency in your project.
|
||||
|
||||
```sh
|
||||
npm install --global @compositor/x0
|
||||
```
|
||||
|
||||
```sh
|
||||
npm install --save-dev @compositor/x0
|
||||
```
|
||||
|
||||
Create a directory for your documentation or other site.
|
||||
|
||||
```sh
|
||||
mkdir docs
|
||||
```
|
||||
|
||||
Start the development server.
|
||||
|
||||
```sh
|
||||
x0 docs
|
||||
```
|
||||
|
||||
*Note: if you installed x0 as a dev dependency, add the command above to a run script in your `package.json`*
|
||||
|
||||
|
||||
Create an `index.md` file in the `docs/` directory.
|
||||
|
||||
```md
|
||||
# Hello World
|
||||
```
|
||||
|
||||
Open your browser to <http://localhost:8080> to see the file you just created.
|
||||
|
||||
To create another route, add another file to the `docs/` directory,
|
||||
for example `getting-started.md`
|
||||
|
||||
````md
|
||||
# Getting Started
|
||||
|
||||
```sh
|
||||
npm install @compositor/x0
|
||||
```
|
||||
````
|
||||
|
||||
The `getting-started.md` file should now be available at <http://localhost:8080/getting-started>.
|
||||
|
||||
Add a link to the *Getting Started* page from `index.md`.
|
||||
|
||||
```md
|
||||
# Hello World
|
||||
|
||||
- [Getting Started](getting-started)
|
||||
```
|
||||
|
||||
## Using React components
|
||||
|
||||
In addition to markdown, x0 can render any React component as a page.
|
||||
Create a `demo.js` file.
|
||||
|
||||
```jsx
|
||||
// demo.js
|
||||
import React from 'react'
|
||||
|
||||
export default class extends React.Component {
|
||||
render () {
|
||||
return (
|
||||
<h1>Demo</h1>
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Using MDX
|
||||
|
||||
x0 also supports [MDX][mdx] format, which allows you to mix JSX with markdown syntax.
|
||||
|
||||
```md
|
||||
import { Box } from 'rebass'
|
||||
|
||||
# Hello MDX
|
||||
|
||||
<Box p={3} bg='tomato'>
|
||||
This will render as a React component
|
||||
</Box>
|
||||
```
|
||||
|
||||
[mdx]: https://github.com/mdx-js/mdx
|
@ -20,8 +20,20 @@ const Video = styled.video([], {
|
||||
borderRadius: '16px',
|
||||
})
|
||||
|
||||
const features = [
|
||||
'Zero-config',
|
||||
'No plugins',
|
||||
'Components over configuration',
|
||||
'Use markdown, MDX, or React components',
|
||||
'Automatic file-system based routing',
|
||||
'Completely customizable',
|
||||
'Static-site generator',
|
||||
'Isolated development environment',
|
||||
]
|
||||
|
||||
export default class extends React.Component {
|
||||
static defaultProps = {
|
||||
name: 'Home',
|
||||
layout: 'landing'
|
||||
}
|
||||
|
||||
@ -29,15 +41,7 @@ export default class extends React.Component {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Container py={5}>
|
||||
<Heading
|
||||
is='h1'
|
||||
mb={4}
|
||||
lineHeight={1.125}
|
||||
fontWeight='bold'
|
||||
fontSize={[ 4, 5, 6 ]}>
|
||||
x0: Zero-config React development environment & static site generator
|
||||
</Heading>
|
||||
<Box mb={4}>
|
||||
<Box mb={3}>
|
||||
<Video
|
||||
autoPlay
|
||||
loop
|
||||
@ -47,6 +51,15 @@ export default class extends React.Component {
|
||||
src='hello-x0.mp4'
|
||||
/>
|
||||
</Box>
|
||||
<Heading
|
||||
is='h1'
|
||||
mb={4}
|
||||
lineHeight={1.125}
|
||||
fontWeight='bold'
|
||||
fontSize={[ 4, 5, 6 ]}>
|
||||
x0:
|
||||
Document & develop React components without breaking a sweat
|
||||
</Heading>
|
||||
<Pre>npm i -g @compositor/x0</Pre>
|
||||
<Flex py={4}>
|
||||
<Button
|
||||
@ -58,16 +71,25 @@ export default class extends React.Component {
|
||||
GitHub
|
||||
</Button>
|
||||
<Box mx={1} />
|
||||
{/*
|
||||
<Button
|
||||
is={Link}
|
||||
px={4}
|
||||
py={3}
|
||||
bg='black'
|
||||
to='/docs'>
|
||||
to='/getting-started'>
|
||||
Documentation
|
||||
</Button>
|
||||
*/}
|
||||
</Flex>
|
||||
</Container>
|
||||
<Container py={5}>
|
||||
<Flex flexWrap='wrap' mx={-3}>
|
||||
{features.map(feat => (
|
||||
<Box key={feat} width={[ 1, 1, 1/2 ]} p={3}>
|
||||
<Text fontWeight='bold'>
|
||||
{feat}
|
||||
</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Flex>
|
||||
</Container>
|
||||
</React.Fragment>
|
||||
|
107
docs/markdown.md
Normal file
107
docs/markdown.md
Normal file
@ -0,0 +1,107 @@
|
||||
---
|
||||
title: 'x0: Using Markdown'
|
||||
---
|
||||
|
||||
# Using Markdown
|
||||
|
||||
Using standard markdown syntax for documentation means that your docs will be easy to edit
|
||||
and render in many different markdown renderers, such as on [GitHub.com](https://github.com).
|
||||
|
||||
In addition to the standard markdown syntax, x0 supports front matter and special fenced code blocks
|
||||
that can render as live examples or previews of React components.
|
||||
|
||||
## Links
|
||||
|
||||
Standard markdown links work out of the box.
|
||||
Under the hood, x0 converts relative links to React Router [`Link`][rr-link] components,
|
||||
and absolute URLs are standard `<a>` tags.
|
||||
|
||||
```md
|
||||
- [Link to another page](about)
|
||||
- [Link to another site](http://example.com)
|
||||
```
|
||||
|
||||
## Images
|
||||
|
||||
Images in the same directory can be included with relative URLs,
|
||||
but we recommend using a CDN and absolute URLs for any images.
|
||||
|
||||
```md
|
||||
![Hubble telescope image of a nebula](https://images.unsplash.com/photo-1462331940025-496dfbfc7564?w=2048&q=20)
|
||||
```
|
||||
|
||||
Note: When using relative URLs, be sure to copy image assets to the dist folder when exporting a site with the `x0 build` command.
|
||||
|
||||
## Code Fences
|
||||
|
||||
To include a code snippet use a code fence.
|
||||
|
||||
````md
|
||||
```sh
|
||||
npm install @compositor/x0
|
||||
```
|
||||
````
|
||||
|
||||
### Live Editor
|
||||
|
||||
x0 includes support for special code fence language attributes for rendering live examples of React components.
|
||||
Use the `.jsx` (note the `.` prefix) to render a live preview with an editable code editor.
|
||||
|
||||
````md
|
||||
```.jsx
|
||||
<Button>Hello</Button>
|
||||
```
|
||||
````
|
||||
|
||||
The above code will render as the following (note this is only visible on the [documentation site][site]).
|
||||
Try editing the JSX code below the preview.
|
||||
|
||||
```.jsx
|
||||
<Button>Hello</Button>
|
||||
```
|
||||
|
||||
Using code fences means that your example code will render in any standard markdown renderer, including GitHub.
|
||||
|
||||
**Important Note**: To include custom components in scope for the live preview code fences,
|
||||
you must use the `ScopeProvider` in a [custom App component](custom-app).
|
||||
|
||||
|
||||
### Live Preview
|
||||
|
||||
To render a component preview without the code editor below, use the `!jsx` (note the `!` prefix) language attibute.
|
||||
|
||||
````md
|
||||
```!jsx
|
||||
<Button>Hello</Button>
|
||||
```
|
||||
````
|
||||
|
||||
The above code will render the following:
|
||||
|
||||
```!jsx
|
||||
<Button>Hello</Button>
|
||||
```
|
||||
|
||||
## Front Matter
|
||||
|
||||
All `.md`, `.mdx`, and `.jsx` files in x0 support the use of [front-matter][fm] for setting default props and page-level metadata.
|
||||
|
||||
```md
|
||||
---
|
||||
title: Getting Started
|
||||
---
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
Use the following front-matter options for controlling aspects of how a page renders.
|
||||
|
||||
- `ignore`: when set to true, x0 will not add the file as a route
|
||||
|
||||
#### HTML Template Options
|
||||
|
||||
Front matter will be passed to the [HTML template](customizing) to allow control over the page title, metatags and more.
|
||||
|
||||
[rr-link]: https://reacttraining.com/react-router/web/api/Link
|
||||
[site]: https://compositor.io/x0/markdown
|
||||
[fm]: https://github.com/jonschlinkert/gray-matter
|
110
docs/react.md
Normal file
110
docs/react.md
Normal file
@ -0,0 +1,110 @@
|
||||
|
||||
# Using React Components
|
||||
|
||||
In addition to markdown, x0 is optimized for rendering React components as pages.
|
||||
This makes it work great as a highly customizable documentation generator,
|
||||
or as a quick and minimal isolated development environment.
|
||||
|
||||
To use a React component as a page, ensure the component is the `default` export.
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
|
||||
export default class extends React.Component {
|
||||
render () {
|
||||
return <h1>Hello</h1>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Default Props
|
||||
|
||||
Default props on components work in a similar manner to front-matter,
|
||||
allowing you to supply page-level metadata to the [HTML template](customizing).
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
|
||||
export default class extends React.Component {
|
||||
static defaultProps = {
|
||||
title: 'Hello'
|
||||
}
|
||||
|
||||
render () {
|
||||
return <h1>Hello</h1>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Fetching Data
|
||||
|
||||
Use the async `getInitialProps` static method to fetch data for the component.
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
import fetch from 'isomorphic-fetch'
|
||||
|
||||
const endpoint = 'http://example.com/api'
|
||||
|
||||
export default class extends React.Component {
|
||||
static getInitialProps = async () => {
|
||||
const data = await fetch(endpoint)
|
||||
return {
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { data } = this.props
|
||||
|
||||
return <pre>{JSON.stringify(data, null, 2)}</pre>
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Local State
|
||||
|
||||
Just like any React component, a page can use React state.
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
|
||||
export default class extends React.Component {
|
||||
state = {
|
||||
count: 0
|
||||
}
|
||||
|
||||
increment = () => this.setState(state => ({ count: state.count + 1 }))
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
<samp>{count}</samp>
|
||||
<button
|
||||
onClick={e => {
|
||||
this.increment()
|
||||
}}>
|
||||
+
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
Import React Router's `Link` component to create links to other pages.
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
export default props =>
|
||||
<div>
|
||||
<Link to='/getting-started'>Getting Started</Link>
|
||||
<Link to='/api'>API</Link>
|
||||
</div>
|
||||
```
|
||||
|
57
docs/routing.md
Normal file
57
docs/routing.md
Normal file
@ -0,0 +1,57 @@
|
||||
|
||||
# Routing
|
||||
|
||||
x0 automatically creates routes based on files in the root directory.
|
||||
Any `.js`, `.md`, `.mdx`, or `.jsx` file will create a route based on the file name.
|
||||
|
||||
*Note that `.jsx` files are JSX format and **not** standard JavaScript*
|
||||
|
||||
Files that begin with an underscore (e.g. `_layout.js`) will be ignored.
|
||||
|
||||
To create a page with a React component, it must be the `default` export of a module.
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
|
||||
export default class extends React.Component {
|
||||
render () {
|
||||
return (
|
||||
<h1>Hello</h1>
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Index routes
|
||||
|
||||
Files with the `index` basename (e.g. `index.js` or `index.md`) will be used as an index page for the directory it's located in. Adding an `index.md` file at the root of the directory will make the page available at the `/` pathname in the URL.
|
||||
|
||||
## Nested routes
|
||||
|
||||
Adding files to subdirectories will create nested routes.
|
||||
For example, adding a file at `api/core.md` will create a route at `/api/core` and a file at `api/index.md` will create a route for `/api/`.
|
||||
|
||||
## Links
|
||||
|
||||
x0 uses [React Router][react-router] under the hood.
|
||||
In markdown, links will automatically use React Router's `<Link />` component for relative links.
|
||||
|
||||
To add links in a React component, import the `Link` component from `react-router-dom`
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
export default props =>
|
||||
<div>
|
||||
<Link to='/api'>API</Link>
|
||||
</div>
|
||||
```
|
||||
|
||||
## 404 page
|
||||
|
||||
A custom 404 page can be added with a file named `404.md`, `404.js`, `404.mdx`, or `404.jsx`.
|
||||
By default, x0 will show a link list of available routes for URLs that aren't valid routes.
|
||||
When exporting with `x0 build` the 404 page will be written to `404.html`, which works with GitHub pages.
|
||||
|
||||
[react-router]: https://github.com/ReactTraining/react-router
|
@ -7,7 +7,7 @@
|
||||
"x0": "cli.js"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "./cli.js docs -p 8989",
|
||||
"start": "./cli.js docs",
|
||||
"build": "./cli.js build docs",
|
||||
"test": "nyc ava --timeout=60s",
|
||||
"test:components": "nyc ava test/components.js",
|
||||
|
@ -267,7 +267,7 @@ export default class Layout extends React.Component {
|
||||
? React.Fragment
|
||||
: MaxWidth
|
||||
|
||||
const index = routes.findIndex(r => r === route)
|
||||
const index = routes.findIndex(r => r.path === route.path)
|
||||
const pagination = {
|
||||
previous: routes[index - 1],
|
||||
next: routes[index + 1]
|
||||
|
@ -98,7 +98,7 @@ export const getRoutes = async (components = initialComponents) => {
|
||||
|
||||
const RouterState = withRouter(({ render, ...props }) => {
|
||||
const { pathname } = props.location
|
||||
const route = props.routes.find(r => r.path === pathname || r.href === pathname)
|
||||
const route = props.routes.find(r => r.path === pathname || r.href === pathname) || { props: {} }
|
||||
return render({ ...props, route })
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user