diff --git a/packages/docz-core/src/DataServer.ts b/packages/docz-core/src/DataServer.ts index 633713a16..b70d0b02c 100644 --- a/packages/docz-core/src/DataServer.ts +++ b/packages/docz-core/src/DataServer.ts @@ -57,7 +57,7 @@ export class DataServer { this.server.on('connection', handleConnection) this.server.on('close', () => watcher.close()) - await Entries.writeGenerated(config) + await Entries.writeApp(config) await Entries.writeImports(await entries.getMap()) } diff --git a/packages/docz-core/src/Entries.ts b/packages/docz-core/src/Entries.ts index 6e1a370e2..634170a27 100644 --- a/packages/docz-core/src/Entries.ts +++ b/packages/docz-core/src/Entries.ts @@ -1,54 +1,27 @@ import * as glob from 'fast-glob' -import * as fs from 'fs' import * as path from 'path' -import { test, mkdir } from 'shelljs' -import template from 'lodash.template' import * as paths from './config/paths' import { propOf } from './utils/helpers' -import { format } from './utils/format' +import { mkd, touch, compiled } from './utils/fs' import { Entry, parseMdx } from './Entry' import { Config } from './commands/args' -const mkd = (dir: string): void => { - !test('-d', dir) && mkdir('-p', dir) -} - -const touch = (file: string, raw: string) => - new Promise(async (resolve, reject) => { - const content = /jsx?$/.test(path.extname(file)) ? await format(raw) : raw - const stream = fs.createWriteStream(file) - - stream.write(content, 'utf-8') - stream.on('finish', () => resolve()) - stream.on('error', err => reject(err)) - stream.end() - }) - -const compiled = (file: string) => - new Promise<(args: any) => string>((resolve, reject) => { - let data = '' - const filepath = path.join(paths.templates, file) - const stream = fs.createReadStream(filepath, { encoding: 'utf-8' }) - - stream.on('data', chunk => (data += chunk)) - stream.on('end', () => resolve(template(data))) - stream.on('error', err => reject(err)) - }) +const fromTemplates = (file: string) => path.join(paths.templates, file) -const writeGeneratedFiles = async (config: Config): Promise => { +const writeAppFiles = async (config: Config): Promise => { const { plugins, title, description, theme } = config const wrappers = propOf(plugins, 'wrapper') const afterRenders = propOf(plugins, 'afterRender') const beforeRenders = propOf(plugins, 'beforeRender') - const app = await compiled('app.tpl.js') - const js = await compiled('index.tpl.js') - const html = await compiled('index.tpl.html') + const root = await compiled(fromTemplates('root.tpl.js')) + const js = await compiled(fromTemplates('index.tpl.js')) + const html = await compiled(fromTemplates('index.tpl.html')) - const rawAppJs = app({ + const rawRootJs = root({ theme, wrappers, websocketUrl: `ws://${config.websocketHost}:${config.websocketPort}`, @@ -64,22 +37,22 @@ const writeGeneratedFiles = async (config: Config): Promise => { description, }) - await touch(paths.appJs, rawAppJs) + await touch(paths.rootJs, rawRootJs) await touch(paths.indexJs, rawIndexJs) await touch(paths.indexHtml, rawIndexHtml) } const writeImports = async (entries: EntryMap): Promise => { - const imports = await compiled('imports.tpl.js') + const imports = await compiled(fromTemplates('imports.tpl.js')) await touch(paths.importsJs, imports({ entries })) } export type EntryMap = Record export class Entries { - public static async writeGenerated(config: Config): Promise { - mkd(paths.docz) - await writeGeneratedFiles(config) + public static async writeApp(config: Config): Promise { + mkd(paths.app) + await writeAppFiles(config) } public static async writeImports(entries: EntryMap): Promise { diff --git a/packages/docz-core/src/config/paths.ts b/packages/docz-core/src/config/paths.ts index 716fa1691..f75a05a3d 100644 --- a/packages/docz-core/src/config/paths.ts +++ b/packages/docz-core/src/config/paths.ts @@ -32,26 +32,28 @@ const resolveApp = (to: string) => path.resolve(root, to) export interface Paths { root: string - docz: string + templates: string packageJson: string servedPath: string + docz: string + app: string dist: string - templates: string importsJs: string - appJs: string + rootJs: string indexJs: string indexHtml: string } export const templates = path.join(resolve.sync('docz-core'), '../templates') -export const docz = resolveApp('.docz') export const packageJson = resolveApp('package.json') export const servedPath = getServedPath(resolveApp('package.json')) +export const docz = resolveApp('.docz') +export const app = path.resolve(docz, 'app/') export const dist = path.resolve(docz, 'dist/') -export const importsJs = path.resolve(docz, 'imports.js') -export const appJs = path.resolve(docz, 'app.jsx') -export const indexJs = path.resolve(docz, 'index.jsx') -export const indexHtml = path.resolve(docz, 'index.html') +export const importsJs = path.resolve(app, 'imports.js') +export const rootJs = path.resolve(app, 'root.jsx') +export const indexJs = path.resolve(app, 'index.jsx') +export const indexHtml = path.resolve(app, 'index.html') diff --git a/packages/docz-core/src/utils/fs.ts b/packages/docz-core/src/utils/fs.ts new file mode 100644 index 000000000..c86c190b4 --- /dev/null +++ b/packages/docz-core/src/utils/fs.ts @@ -0,0 +1,36 @@ +import * as path from 'path' +import * as fs from 'fs' +import { test, mkdir } from 'shelljs' +import template from 'lodash.template' + +import { format } from './format' + +export const mkd = (dir: string): void => { + !test('-d', dir) && mkdir('-p', dir) +} + +export const touch = (file: string, raw: string) => + new Promise(async (resolve, reject) => { + const content = /jsx?$/.test(path.extname(file)) ? await format(raw) : raw + const stream = fs.createWriteStream(file) + + stream.write(content, 'utf-8') + stream.on('finish', () => resolve()) + stream.on('error', err => reject(err)) + stream.end() + }) + +export const read = (filepath: string): Promise => + new Promise((resolve, reject) => { + let data = '' + const stream = fs.createReadStream(filepath, { encoding: 'utf-8' }) + + stream.on('data', chunk => (data += chunk)) + stream.on('end', () => resolve(data)) + stream.on('error', err => reject(err)) + }) + +export const compiled = async (file: string): Promise<(args: any) => string> => + read(file) + .then(data => template(data)) + .catch(err => err) diff --git a/packages/docz-core/templates/index.tpl.js b/packages/docz-core/templates/index.tpl.js index a5264ddc6..5c8763685 100644 --- a/packages/docz-core/templates/index.tpl.js +++ b/packages/docz-core/templates/index.tpl.js @@ -2,7 +2,7 @@ import React from 'react' import ReactDOM from 'react-dom' import { imports } from './imports' -import App from './app' +import Root from './root' const _beforeRenders = [<% if (beforeRenders) {%><%- beforeRenders %><%}%>] const _afterRenders = [<% if (afterRenders) {%><%- afterRenders %><%}%>] @@ -11,13 +11,13 @@ const beforeRender = () => _beforeRenders.forEach(f => f && f()) const afterRender = () => _afterRenders.forEach(f => f && f()) const root = document.querySelector('#root') -const render = (Component = App) => { +const render = (Component = Root) => { beforeRender() - ReactDOM.render( , root, afterRender) + ReactDOM.render(, root, afterRender) } if (module.hot) { - module.hot.accept('./imports', () => render(App)) + module.hot.accept('./imports', () => render(Root)) } -render(App) +render(Root) diff --git a/packages/docz-core/templates/app.tpl.js b/packages/docz-core/templates/root.tpl.js similarity index 93% rename from packages/docz-core/templates/app.tpl.js rename to packages/docz-core/templates/root.tpl.js index bbb90810e..5b831dcbf 100644 --- a/packages/docz-core/templates/app.tpl.js +++ b/packages/docz-core/templates/root.tpl.js @@ -14,7 +14,7 @@ const recursiveWrappers = ([Wrapper, ...rest], props) => ( const Wrapper = props => _wrappers.length ? recursiveWrappers(_wrappers, props) : props.children -class App extends React.Component { +class Root extends React.Component { state = { config: {}, entries: {}, @@ -40,4 +40,4 @@ class App extends React.Component { } } -export default hot(module)(App) +export default hot(module)(Root) diff --git a/packages/docz-theme-default/.babelrc b/packages/docz-theme-default/.babelrc index 9bde24f37..616114cdc 100644 --- a/packages/docz-theme-default/.babelrc +++ b/packages/docz-theme-default/.babelrc @@ -1,6 +1,6 @@ { "presets": [ - ["@babel/preset-env", { "modules": false, }], + ["@babel/preset-env", { "modules": false }], "@babel/preset-react" ], "plugins": [ diff --git a/packages/docz/src/components/DocPreview.tsx b/packages/docz/src/components/DocPreview.tsx index 49a8f0d6a..8488fd4f5 100644 --- a/packages/docz/src/components/DocPreview.tsx +++ b/packages/docz/src/components/DocPreview.tsx @@ -3,28 +3,30 @@ import { SFC } from 'react' import loadable from 'loadable-components' import { Switch, Route, RouteComponentProps } from 'react-router-dom' -import { RenderComponent } from './Playground' import { dataContext, Entry } from '../theme' +import { RenderComponent } from './Playground' export type PageProps = RouteComponentProps & { doc?: Entry } +export interface ComponentsMap { + page?: React.ComponentType + render?: RenderComponent + h1?: React.ComponentType + h2?: React.ComponentType + h3?: React.ComponentType + h4?: React.ComponentType + h5?: React.ComponentType + h6?: React.ComponentType + ul?: React.ComponentType + table?: React.ComponentType + pre?: React.ComponentType + [key: string]: any +} + export interface DocPreviewProps { - components: { - page?: React.ComponentType - render?: RenderComponent - h1?: React.ComponentType - h2?: React.ComponentType - h3?: React.ComponentType - h4?: React.ComponentType - h5?: React.ComponentType - h6?: React.ComponentType - ul?: React.ComponentType - table?: React.ComponentType - pre?: React.ComponentType - [key: string]: any - } + components: ComponentsMap } export const DocPreview: SFC = ({ components }) => { diff --git a/packages/docz/src/theme.tsx b/packages/docz/src/theme.tsx index 5f6edd23d..088141854 100644 --- a/packages/docz/src/theme.tsx +++ b/packages/docz/src/theme.tsx @@ -3,8 +3,10 @@ import { ComponentType as CT } from 'react' import { BrowserRouter } from 'react-router-dom' import merge from 'deepmerge' +import { ComponentsMap } from './components/DocPreview' + export type MSXComponent = CT<{ - components: { [key: string]: any } + components: ComponentsMap }> export interface MSXImport {