fix(docz-core): config watch for directory operations

This commit is contained in:
Pedro Nauck
2018-05-07 02:49:05 -03:00
parent f75881ec8f
commit 43fa7aba6f
8 changed files with 86 additions and 69 deletions

View File

@@ -1,5 +0,0 @@
import { doc } from 'docz'
export const meta = doc('Test')
Just a test

View File

@@ -25,6 +25,7 @@
"@mdx-js/mdx": "^0.8.1",
"@mdx-js/mdxast": "^0.7.2",
"@sindresorhus/slugify": "^0.3.0",
"@types/shelljs": "^0.7.9",
"art-template": "^4.12.2",
"babel-loader": "^8.0.0-beta.1",
"babel-polyfill": "^7.0.0-beta.3",
@@ -44,11 +45,11 @@
"koa-static": "^4.0.2",
"load-cfg": "^0.0.1",
"lodash.get": "^4.4.2",
"mkdirp": "^0.5.1",
"prettier": "^1.12.0",
"react-hot-loader": "4.1.2",
"remark-parse": "^5.0.0",
"resolve": "^1.7.1",
"shelljs": "^0.8.1",
"thread-loader": "^1.1.5",
"ulid": "^2.3.0",
"unified": "^6.2.0",
@@ -66,7 +67,6 @@
"@types/del": "^3.0.1",
"@types/express": "^4.11.1",
"@types/html-webpack-plugin": "^2.30.3",
"@types/mkdirp": "^0.5.2",
"@types/node": "10.0.4",
"@types/prettier": "^1.12.1",
"@types/resolve": "^0.0.7",

View File

@@ -1,7 +1,7 @@
import * as glob from 'fast-glob'
import * as fs from 'fs'
import * as path from 'path'
import * as mkdir from 'mkdirp'
import { test, mkdir } from 'shelljs'
import { compile } from 'art-template'
import stringify from 'json-stringify-pretty-compact'
@@ -13,11 +13,7 @@ import { Entry } from './Entry'
import { Config } from './commands/args'
const mkd = (dir: string): void => {
try {
fs.lstatSync(dir)
} catch (err) {
mkdir.sync(dir)
}
!test('-d', dir) && mkdir('-p', dir)
}
const touch = (file: string, raw: string) => {
@@ -38,21 +34,12 @@ const html = compiled('index.tpl.html')
export type EntryMap = Record<string, Entry>
export class Entries {
public files: string[]
public config: Config
public entries: EntryMap
constructor(config: Config) {
const { files: pattern } = config
const ignoreGlob = '!node_modules'
const files: string[] = glob.sync(
Array.isArray(pattern) ? [...pattern, ignoreGlob] : [pattern, ignoreGlob]
)
this.files = files
this.config = config
this.entries = this.getEntries(files)
this.entries = this.getEntries(config)
}
public write(): void {
@@ -71,9 +58,26 @@ export class Entries {
public update(file: string): void {
const filepath = this.entryFilepath(file)
this.entries = {
...this.entries,
[filepath]: new Entry(file, this.config.src),
if (Entry.check(file)) {
this.entries = {
...this.entries,
[filepath]: new Entry(file, this.config.src),
}
}
}
public clean(dir: string): void {
if (test('-d', dir)) {
this.entries = this.getEntries(this.config)
return
}
const { paths } = this.config
const src = path.resolve(paths.root, this.config.src)
for (const file of Object.keys(this.entries)) {
const filepath = path.join(src, file)
if (!test('-f', filepath)) this.remove(filepath)
}
}
@@ -82,7 +86,14 @@ export class Entries {
return path.relative(srcPath, file)
}
private getEntries(files: string[]): EntryMap {
private getEntries(config: Config): EntryMap {
const { files: pattern } = config
const ignoreGlob = '!node_modules'
const files: string[] = glob.sync(
Array.isArray(pattern) ? [...pattern, ignoreGlob] : [pattern, ignoreGlob]
)
return files.filter(Entry.check).reduce((obj, file) => {
const entry = new Entry(file, this.config.src)
return { ...obj, [entry.filepath]: entry }

View File

@@ -52,21 +52,21 @@ export class Entry {
return checkImport(file) && Boolean(getNameFromDoc(file))
}
public static parseName(file: string): string | null {
return getNameFromDoc(file)
public static slug(file: string): string | null {
const name = getNameFromDoc(file)
return name ? slugify(name) : null
}
public id: string
public slug: string
public filepath: string
public slug: string | null
constructor(file: string, src: string) {
const srcPath = path.resolve(paths.root, src)
const filepath = path.relative(srcPath, file)
const name = Entry.parseName(file)
this.id = ulid()
this.slug = slugify(name)
this.slug = Entry.slug(file)
this.filepath = filepath
}
}

View File

@@ -14,16 +14,18 @@ export const devServerConfig = (
const nonExistentDir = path.resolve(__dirname, 'non-existent')
return {
content: [nonExistentDir],
compiler,
host,
dev: { logLevel: 'warn' },
port,
content: [nonExistentDir],
dev: {
logLevel: args.debug ? 'debug' : 'warn',
},
hot: {
logLevel: 'error',
reload: false,
},
logLevel: 'error',
port,
add: (app: any) => {
app.use(
convert(

View File

@@ -3,7 +3,6 @@ import chokidar from 'chokidar'
import del from 'del'
import * as paths from '../config/paths'
import { Entry } from '../Entry'
import { Entries } from '../Entries'
import { webpack } from '../bundlers'
import { Config } from './args'
@@ -11,6 +10,41 @@ import { Config } from './args'
process.env.BABEL_ENV = process.env.BABEL_ENV || 'development'
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
const handleUpdate = (entries: Entries) => (file: string) => {
entries.update(file)
entries.rewrite()
}
const handleRemove = (entries: Entries) => (file: string) => {
entries.remove(file)
entries.rewrite()
}
const handleRemoveDir = (entries: Entries) => (
event: string,
path: string,
details: any
) => {
if (details.event === 'moved' && details.type === 'directory') {
entries.clean(details.path)
entries.rewrite()
}
}
const writeEntriesAndWatch = (config: Config) => {
const entries = new Entries(config)
const watcher = chokidar.watch(config.files, {
ignored: /(^|[\/\\])\../,
})
watcher
.on('change', handleUpdate(entries))
.on('unlink', handleRemove(entries))
.on('raw', handleRemoveDir(entries))
entries.write()
}
const INITIAL_CONFIG = {
paths,
plugins: [],
@@ -18,33 +52,6 @@ const INITIAL_CONFIG = {
hastPlugins: [],
}
const writeEntriesAndWatch = (config: Config) => {
const watcher = chokidar.watch(config.files, {
ignored: /(^|[\/\\])\../,
})
const entries = new Entries(config)
const onUnlink = (file: string) => {
entries.remove(file)
entries.rewrite()
}
const onChange = (file: string) => {
const name = Entry.parseName(file)
if (name) {
entries.update(file)
entries.rewrite()
}
}
watcher.on('unlink', onUnlink)
watcher.on('change', onChange)
entries.write()
}
export const dev = async (args: Config) => {
const config = load('docz', { ...args, ...INITIAL_CONFIG })
const bundler = webpack(config)

View File

@@ -1,6 +1,7 @@
{
"extends": ["tslint:latest", "tslint-config-prettier"],
"rules": {
"curly": false,
"interface-name": [true, "never-prefix"],
"ordered-imports": false,
"object-literal-sort-keys": false,

View File

@@ -1418,12 +1418,6 @@
version "3.0.3"
resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
"@types/mkdirp@^0.5.2":
version "0.5.2"
resolved "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f"
dependencies:
"@types/node" "*"
"@types/node@*":
version "10.0.0"
resolved "https://registry.npmjs.org/@types/node/-/node-10.0.0.tgz#c40f8e07dce607d3ef25a626b93a6a7cdcf97881"
@@ -1481,6 +1475,13 @@
"@types/express-serve-static-core" "*"
"@types/mime" "*"
"@types/shelljs@^0.7.9":
version "0.7.9"
resolved "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.7.9.tgz#3abecb72d9cad9cd4b0e7cb86ed10a97d93ba602"
dependencies:
"@types/glob" "*"
"@types/node" "*"
"@types/tapable@*":
version "1.0.2"
resolved "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.2.tgz#e13182e1b69871a422d7863e11a4a6f5b814a4bd"