diff --git a/packages/docz-core/src/Bundler.ts b/packages/docz-core/src/Bundler.ts index c044cd948..d3577dcf1 100644 --- a/packages/docz-core/src/Bundler.ts +++ b/packages/docz-core/src/Bundler.ts @@ -52,7 +52,7 @@ export class Bundler { const dev = env === 'development' const initialConfig = this.config() - return Boolean(plugins) && plugins.length > 0 + return plugins && plugins.length > 0 ? plugins.reduce(this.reduceWithPlugins(dev), initialConfig) : initialConfig } diff --git a/packages/docz-core/src/Entries.ts b/packages/docz-core/src/Entries.ts index 7ace82cd4..5a0cc8295 100644 --- a/packages/docz-core/src/Entries.ts +++ b/packages/docz-core/src/Entries.ts @@ -1,37 +1,15 @@ import * as glob from 'fast-glob' -import * as t from 'babel-types' import * as fs from 'fs' import * as path from 'path' import * as mkdir from 'mkdirp' import * as prettier from 'prettier' -import { NodePath } from 'babel-traverse' import { compile } from 'art-template' import * as paths from './config/paths' +import { propOf } from './utils/helpers' -import { traverseAndAssign } from './utils/traverse' -import { Entry, convertToAst } from './Entry' -import { Plugin, PluginFactory } from './Plugin' - -const hasImport = (filepath: NodePath): boolean => - filepath.isImportDeclaration() && - filepath.node && - filepath.node.source && - filepath.node.source.value === 'docz' - -const hasDocFn = (filepath: NodePath): boolean => - filepath.node.specifiers && - filepath.node.specifiers.some( - (node: NodePath) => - t.isImportSpecifier(node) && node.imported.name === 'doc' - ) - -const checkImport = traverseAndAssign, boolean>({ - assign: () => true, - when: p => hasImport(p) && hasDocFn(p), -}) - -const isFile = (entry: string) => checkImport(convertToAst(entry)) +import { Entry } from './Entry' +import { ConfigArgs } from './Server' const mkd = (dir: string): void => { try { @@ -58,43 +36,11 @@ const touch = (file: string, raw: string) => { const compiled = (file: string) => compile(fs.readFileSync(path.join(paths.templates, file), 'utf-8')) -const propOf = (arr: any[], method: keyof PluginFactory) => - arr && arr.map(p => p[method]).filter(m => m) - const app = compiled('app.tpl.js') const js = compiled('index.tpl.js') const html = compiled('index.tpl.html') -export interface GenerateFilesParams { - entries: Entry[] - plugins: Plugin[] - theme: string -} - export class Entries { - public static generateFiles(args: GenerateFilesParams): void { - const { entries, theme, plugins } = args - - touch(paths.indexHtml, html({})) - - touch( - paths.appJs, - app({ - ENTRIES: entries, - THEME: theme, - WRAPPERS: propOf(plugins, 'wrapper'), - }) - ) - - touch( - paths.indexJs, - js({ - AFTER_RENDERS: propOf(plugins, 'afterRender'), - BEFORE_RENDERS: propOf(plugins, 'beforeRender'), - }) - ) - } - public files: string[] public all: Entry[] @@ -105,7 +51,31 @@ export class Entries { ) this.files = files - this.all = files.filter(isFile).map(file => new Entry({ file, src })) + this.all = files.filter(Entry.check).map(file => new Entry({ file, src })) + } + + public writeFiles(args: Partial): void { + const { theme, plugins, title, description } = args + + const rawIndexHtml = html({ + DESCRIPTION: description, + TITLE: title, + }) + + const rawAppJs = app({ + ENTRIES: this.all, + THEME: theme, + WRAPPERS: propOf(plugins, 'wrapper'), + }) + + const rawIndexJs = js({ + AFTER_RENDERS: propOf(plugins, 'afterRender'), + BEFORE_RENDERS: propOf(plugins, 'beforeRender'), + }) + + touch(paths.indexHtml, rawIndexHtml) + touch(paths.appJs, rawAppJs) + touch(paths.indexJs, rawIndexJs) } public map(): Record { diff --git a/packages/docz-core/src/Entry.ts b/packages/docz-core/src/Entry.ts index 74c15824f..00e706233 100644 --- a/packages/docz-core/src/Entry.ts +++ b/packages/docz-core/src/Entry.ts @@ -1,12 +1,14 @@ import * as fs from 'fs' import * as path from 'path' +import * as t from 'babel-types' +import { NodePath } from 'babel-traverse' import { File } from 'babel-types' import { parse } from 'babylon' import * as paths from './config/paths' import { traverseAndAssign } from './utils/traverse' -export const convertToAst = (entry: string): File => +const convertToAst = (entry: string): File => parse(fs.readFileSync(entry, 'utf-8'), { plugins: ['jsx'], sourceType: 'module', @@ -17,6 +19,24 @@ const getNameFromDoc = traverseAndAssign({ when: p => p.isCallExpression() && p.node.callee.name === 'doc', }) +const hasImport = (filepath: NodePath): boolean => + filepath.isImportDeclaration() && + filepath.node && + filepath.node.source && + filepath.node.source.value === 'docz' + +const hasDocFn = (filepath: NodePath): boolean => + filepath.node.specifiers && + filepath.node.specifiers.some( + (node: NodePath) => + t.isImportSpecifier(node) && node.imported.name === 'doc' + ) + +const checkImport = traverseAndAssign, boolean>({ + assign: () => true, + when: p => hasImport(p) && hasDocFn(p), +}) + export interface EntryConstructor { file: string src: string @@ -28,6 +48,10 @@ export class Entry { return getNameFromDoc(ast) } + public static check(entry: string): boolean | undefined { + return checkImport(convertToAst(entry)) + } + public name: string public filepath: string diff --git a/packages/docz-core/src/Server.ts b/packages/docz-core/src/Server.ts index 618d2a9f4..11e8d3a7a 100644 --- a/packages/docz-core/src/Server.ts +++ b/packages/docz-core/src/Server.ts @@ -12,21 +12,26 @@ import { Plugin } from './Plugin' process.env.BABEL_ENV = process.env.BABEL_ENV || 'development' process.env.NODE_ENV = process.env.NODE_ENV || 'development' -export interface ServerConstructor { - theme: string +export interface Argv { + /* io args */ + src: string files: string bundler: string - src: string - port: number + /* template args */ + title: string + description: string + theme: string + /* bundler args */ env: string - host: string - protocol: string debug: boolean + protocol: string + host: string + port: number } -export interface ConfigArgs extends ServerConstructor { - paths: paths.Paths - plugins: Plugin[] +export interface ConfigArgs extends Argv { + paths?: paths.Paths + plugins?: Plugin[] } export class Server { @@ -34,7 +39,7 @@ export class Server { private readonly watcher: FSWatcher private readonly bundler: Bundler - constructor(args: ServerConstructor) { + constructor(args: ConfigArgs) { const config = load('docz', { ...args, paths, plugins: [] }) const selectedBundler = this.getBundler(config.bundler) const ignoreWatch = { @@ -75,12 +80,12 @@ export class Server { } private processEntries(config: ConfigArgs): void { - const { files, src, theme, plugins } = config + const { files, src } = config const cache = new Map() const generateFilesAndUpdateCache = (entries: Entries) => { cache.set('map', entries.map()) - Entries.generateFiles({ entries: entries.all, plugins, theme }) + entries.writeFiles(config) } const updateEntries = () => diff --git a/packages/docz-core/src/utils/helpers.ts b/packages/docz-core/src/utils/helpers.ts index 1142045ed..b8e88a0b7 100644 --- a/packages/docz-core/src/utils/helpers.ts +++ b/packages/docz-core/src/utils/helpers.ts @@ -24,3 +24,7 @@ export function pick(props: string[], obj: any): R { return newObj as R } + +export function propOf(arr: any[] | undefined, method: keyof T): any { + return arr && arr.map(p => p[method]).filter(m => m) +} diff --git a/packages/docz-core/templates/index.tpl.html b/packages/docz-core/templates/index.tpl.html index 166b6710b..3c7a30578 100644 --- a/packages/docz-core/templates/index.tpl.html +++ b/packages/docz-core/templates/index.tpl.html @@ -2,9 +2,10 @@ + - docz + <%- TITLE %>
diff --git a/packages/docz/bin/index.js b/packages/docz/bin/index.js index 323350190..098026f1a 100755 --- a/packages/docz/bin/index.js +++ b/packages/docz/bin/index.js @@ -24,18 +24,21 @@ yargs type: 'string', default: DEFAULT_FILES_GLOB, }) - yargs.positional('theme', { - type: 'string', - default: 'docz-theme-default', - }) yargs.positional('bundler', { type: 'string', default: 'webpack', }) - yargs.positional('port', { - alias: 'p', - type: 'number', - default: process.env.PORT || 3000, + yargs.positional('title', { + type: 'string', + default: 'Docz', + }) + yargs.positional('description', { + type: 'string', + default: 'My awesome design system!', + }) + yargs.positional('theme', { + type: 'string', + default: 'docz-theme-default', }) yargs.positional('env', { type: 'boolean', @@ -53,6 +56,11 @@ yargs type: 'string', default: process.env.HOST || '0.0.0.0', }) + yargs.positional('port', { + alias: 'p', + type: 'number', + default: process.env.PORT || 3000, + }) }, argv => new Server(argv).start() )