mirror of
https://github.com/zhigang1992/docz.git
synced 2026-03-27 02:34:14 +08:00
feat(docz-core): add title and description on settings
This commit is contained in:
@@ -52,7 +52,7 @@ export class Bundler<C = any, S = any> {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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<any>): boolean =>
|
||||
filepath.isImportDeclaration() &&
|
||||
filepath.node &&
|
||||
filepath.node.source &&
|
||||
filepath.node.source.value === 'docz'
|
||||
|
||||
const hasDocFn = (filepath: NodePath<any>): boolean =>
|
||||
filepath.node.specifiers &&
|
||||
filepath.node.specifiers.some(
|
||||
(node: NodePath<any>) =>
|
||||
t.isImportSpecifier(node) && node.imported.name === 'doc'
|
||||
)
|
||||
|
||||
const checkImport = traverseAndAssign<NodePath<t.Node>, 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<ConfigArgs>): 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<string, string> {
|
||||
|
||||
@@ -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<any, string>({
|
||||
when: p => p.isCallExpression() && p.node.callee.name === 'doc',
|
||||
})
|
||||
|
||||
const hasImport = (filepath: NodePath<any>): boolean =>
|
||||
filepath.isImportDeclaration() &&
|
||||
filepath.node &&
|
||||
filepath.node.source &&
|
||||
filepath.node.source.value === 'docz'
|
||||
|
||||
const hasDocFn = (filepath: NodePath<any>): boolean =>
|
||||
filepath.node.specifiers &&
|
||||
filepath.node.specifiers.some(
|
||||
(node: NodePath<any>) =>
|
||||
t.isImportSpecifier(node) && node.imported.name === 'doc'
|
||||
)
|
||||
|
||||
const checkImport = traverseAndAssign<NodePath<t.Node>, 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
|
||||
|
||||
|
||||
@@ -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 = () =>
|
||||
|
||||
@@ -24,3 +24,7 @@ export function pick<R = object>(props: string[], obj: any): R {
|
||||
|
||||
return newObj as R
|
||||
}
|
||||
|
||||
export function propOf<T>(arr: any[] | undefined, method: keyof T): any {
|
||||
return arr && arr.map(p => p[method]).filter(m => m)
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="description" content="<%- DESCRIPTION %>">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>docz</title>
|
||||
<title><%- TITLE %></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user