Skip to content

Commit

Permalink
Fix watch issue, add watch() and unwatch()
Browse files Browse the repository at this point in the history
  • Loading branch information
xcatliu committed Mar 14, 2017
1 parent 31a5cb2 commit 243bd76
Show file tree
Hide file tree
Showing 8 changed files with 395 additions and 104 deletions.
12 changes: 12 additions & 0 deletions README.md
Expand Up @@ -232,13 +232,25 @@ It's also able to use it as a node module:
npm install pagic --save
```

### Common Usage

```js
const Pagic = require('pagic');

const pagic = new Pagic();
pagic.build();
```

### Watch File Change

```js
pagic.watch().build();

setTimeout(() => {
pagic.unwatch();
}, 10000);
```

## Development

```shell
Expand Down
10 changes: 3 additions & 7 deletions bin/pagic-build.js
@@ -1,6 +1,5 @@
#! /usr/bin/env node

const fs = require('fs');
const program = require('commander');
const Pagic = require('..');
const http = require('http');
Expand All @@ -16,13 +15,10 @@ program

const pagic = new Pagic();

pagic.build();

if (program.watch) {
console.log(`Watching ${pagic.config.src_dir}`);
fs.watch(pagic.config.src_dir, () => {
pagic.build();
});
pagic.watch().build();
} else {
pagic.build();
}

if (program.serve) {
Expand Down
2 changes: 1 addition & 1 deletion docs/front_matter/index.html
Expand Up @@ -10,7 +10,7 @@ <h1 id="pagic">Pagic</h1>

<footer>
Author: xcatliu,
Published: Thu Mar 02 2017 08:00:00 GMT+0800 (CST)
Published: Thu Mar 02 2017 08:00:00 GMT+0800 (China Standard Time)
</footer>
</body>
</html>
Expand Down
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -7,7 +7,7 @@
"pagic": "bin/pagic.js"
},
"scripts": {
"start": "node bin/pagic.js build",
"start": "node bin/pagic.js build -ws",
"lint": "eslint .",
"test": "npm run lint && _mocha",
"cover": "istanbul cover node_modules/mocha/bin/_mocha",
Expand All @@ -31,6 +31,7 @@
},
"homepage": "https://github.com/xcatliu/pagic#readme",
"dependencies": {
"chokidar": "^1.6.1",
"commander": "^2.9.0",
"ecstatic": "^2.1.0",
"find-parent-dir": "^0.3.0",
Expand Down
163 changes: 116 additions & 47 deletions src/Pagic.js
Expand Up @@ -3,9 +3,11 @@
const path = require('path');
const fse = require('fs-extra');
const glob = require('glob');
const chokidar = require('chokidar');

const getConfig = require('./util/getConfig');
const getLayout = require('./util/getLayout');
const fileType = require('./util/fileType');

class Pagic {
constructor() {
Expand All @@ -15,79 +17,146 @@ class Pagic {
require('./plugin/parseMarkdown'),
require('./plugin/injectRelativeToRoot'),
];

this.enabledWatch = false;
this.watcher = null;
}

build() {
this.clearPublicDir();
this.buildMD();
this.copyStaticFiles();
this.clean();
this.buildFilesInDir(this.config.src_dir);

if (this.enabledWatch) {
const watcher = chokidar.watch('**/*', {
cwd: this.config.src_dir,
});

watcher.on('ready', () => {
watcher
.on('add', this.handleFileChange.bind(this))
.on('change', this.handleFileChange.bind(this))
.on('unlink', this.handleFileRemove.bind(this))
.on('unlinkDir', this.handleDirRemove.bind(this))
.on('error', error => {
console.log(`Watcher error: ${error}`);
});
});

this.watcher = watcher;
console.log(`Watching ${this.config.src_dir}`);
}
return this;
}

watch() {
this.enabledWatch = true;
return this;
}

unwatch() {
this.enabledWatch = false;
if (this.watcher) {
this.watcher.close();
this.watcher = null;
console.log(`Unwatch ${this.config.src_dir}`);
}
return this;
}

clearPublicDir() {
console.log(`Clear ${this.config.public_dir}`);
clean() {
fse.emptyDirSync(this.config.public_dir);
console.log(`Cleaned ${this.config.public_dir}`);
return this;
}

buildMD() {
const mdFiles = glob.sync('**/*.md', {
cwd: this.config.src_dir,
});
handleFileChange(filePath) {
if (fileType.isLayout(filePath)) {
this.buildFilesInDir(path.dirname(path.join(this.config.src_dir, filePath)));
} else if (fileType.isMarkdown(filePath)) {
this.buildMarkdownFile(filePath);
} else if (fileType.isStaticFile(filePath)) {
this.buildStaticFile(filePath);
}
}

if (mdFiles.length === 0) {
console.log('No markdown files found');
return;
handleFileRemove(filePath) {
if (fileType.isLayout(filePath)) {
this.buildFilesInDir(path.dirname(path.join(this.config.src_dir, filePath)));
} else if (fileType.isMarkdown(filePath)) {
this.removeMarkdownFile(filePath);
} else if (fileType.isStaticFile(filePath)) {
this.removeStaticFile(filePath);
}
}

mdFiles.forEach(filePath => {
const resolvedFilePath = path.resolve(this.config.src_dir, filePath);
const resolvedDestinationFilePath = path.resolve(this.config.public_dir, filePath)
.replace(/\.md$/, '.html');
handleDirRemove(dirPath) {
this.removeStaticFile(dirPath);
}

const layout = getLayout(resolvedFilePath);
buildFilesInDir(dirPath) {
const relativeDirPath = path.relative(this.config.src_dir, dirPath) || '.';

if (!layout) {
console.error(`CANNOT find a layout for ${resolvedFilePath}, will skip this file`);
return;
const files = glob.sync(`${relativeDirPath}/**/*`, {
nodir: true,
cwd: this.config.src_dir,
});

files.forEach(filePath => {
if (fileType.isMarkdown(filePath)) {
this.buildMarkdownFile(filePath);
} else if (fileType.isStaticFile(filePath)) {
this.buildStaticFile(filePath);
}
});
}

const originalContent = fse.readFileSync(resolvedFilePath, 'utf-8');
buildMarkdownFile(filePath) {
const resolvedFilePath = path.resolve(this.config.src_dir, filePath);
const resolvedDestinationFilePath = path.resolve(this.config.public_dir, filePath)
.replace(/\.md$/, '.html');

const context = this.plugins.reduce((prevContext, plugin) => plugin(prevContext), {
path: filePath,
content: originalContent,
config: this.config,
});
const layout = getLayout(resolvedFilePath);

const html = layout(context);
if (typeof layout !== 'function') {
console.error(`CANNOT find a layout for ${resolvedFilePath}, will skip this file`);
return;
}

fse.outputFileSync(resolvedDestinationFilePath, html);
const originalContent = fse.readFileSync(resolvedFilePath, 'utf-8');

console.log(`Generated ${resolvedDestinationFilePath}`);
const context = this.plugins.reduce((prevContext, plugin) => plugin(prevContext), {
path: filePath,
content: originalContent,
config: this.config,
});

const html = layout(context);

fse.outputFileSync(resolvedDestinationFilePath, html);
console.log(`Generated ${resolvedDestinationFilePath}`);
}

copyStaticFiles() {
const staticFiles = glob.sync('**/*', {
ignore: [
'**/*.md',
'**/_*',
],
nodir: true,
cwd: this.config.src_dir,
});
buildStaticFile(filePath) {
const resolvedFilePath = path.resolve(this.config.src_dir, filePath);
const resolvedDestinationFilePath = path.resolve(this.config.public_dir, filePath);

if (staticFiles.length === 0) {
return;
}
fse.copySync(resolvedFilePath, resolvedDestinationFilePath);
console.log(`Copied ${resolvedDestinationFilePath}`);
}

removeMarkdownFile(filePath) {
const resolvedDestinationFilePath = path.resolve(this.config.public_dir, filePath)
.replace(/\.md$/, '.html');

staticFiles.forEach(filePath => {
const resolvedFilePath = path.resolve(this.config.src_dir, filePath);
const resolvedDistPath = path.resolve(this.config.public_dir, filePath);
fse.removeSync(resolvedDestinationFilePath);
console.log(`Removed ${resolvedDestinationFilePath}`);
}

fse.copySync(resolvedFilePath, resolvedDistPath);
removeStaticFile(filePath) {
const resolvedDestinationFilePath = path.resolve(this.config.public_dir, filePath);

console.log(`Copied ${resolvedDistPath}`);
});
fse.removeSync(resolvedDestinationFilePath);
console.log(`Removed ${resolvedDestinationFilePath}`);
}
}

Expand Down
16 changes: 16 additions & 0 deletions src/util/fileType.js
@@ -0,0 +1,16 @@
const path = require('path');

const fileType = {
isLayout: filePath => path.basename(filePath) === '_layout.js',
isMarkdown: filePath => path.extname(filePath) === '.md',
isStaticFile: filePath => {
if (fileType.isMarkdown(filePath)) {
return false;
} else if (path.basename(filePath).startsWith('_')) {
return false;
}
return true;
},
};

module.exports = fileType;

0 comments on commit 243bd76

Please sign in to comment.