UNPKG

apollo-nico

Version:

对 nico 及 apollo-theme 的封装,方便跨平台使用

207 lines (183 loc) 4.51 kB
var fs = require('fs'), path = require('path'), util = require('./util'); // Match "\". var PATTERN_BACKSLASH = /\\/g, // Extnames of text file. text = [ '.js', '.css', '.json', '.txt', '.tpl', '.xml' ], /** * Remove all contents in a directory. * @root {string} * @param [pathname] {string} */ emptyDir = exports.emptyDir = function (root, pathname) { // Remove contents. readDir(root, pathname || '.', true).data.forEach(function (pathname) { if (stat(root, pathname) === 'dir') { emptyDir(root, pathname); } else { fs.unlinkSync(path.join(root, pathname)); } }); // Remove self. fs.rmdirSync(path.join(root, pathname || '.')); }, /** * List directory and sub directories. * @param root {string} * @param [pathname] {string} * @return {Object} */ listDir = exports.listDir = function (root, pathname) { var result = {}; readDir(root, pathname || '.').data.forEach(function (pathname) { if (stat(root, pathname) === 'dir') { result[pathname] = true; // Is a directory. util.mix(result, listDir(root, pathname)); // List sub directory. } else { result[pathname] = false; // Not a directory. } }); return result; }, /** * Make directory and all parents. * @param pathname {string} */ makeDir = exports.makeDir = function (root, pathname) { (function next(pathname) { if (!fs.existsSync(pathname)) { // At first, make parent directory. next(path.resolve(pathname, '..')); // Then, make current directory. fs.mkdirSync(pathname); } }(path.join(root, pathname))); }, /** * Mix two directories. * @param target {string} * @param source {string} */ mixDir = exports.mixDir = function (target, source) { util.each(listDir(source), function (isDir, pathname) { if (isDir) { makeDir(target, pathname); } else { writeFile(target, readFile(source, pathname)); } }); }, /** * Read a directory. * @param root {string} * @param pathname {string} * @param [all] {boolean} * @return {Object} */ readDir = exports.readDir = function (root, pathname, all) { var file = { get data() { if (!this._data) { this._data = fs .readdirSync(path.join(root, pathname)) .filter(function (name) { // Ignore hidden items. return all || name[0] !== '.' }) .map(function (name) { return path.join(pathname, name) .replace(PATTERN_BACKSLASH, '/'); }); } return this._data; }, set data(data) { this._data = data; }, meta: {}, pathname: pathname, type: '/' }; return file; }, /** * Read a file. * @param root {string} * @param pathname {string} * @param [type] {string} * @return {Object} */ readFile = exports.readFile = function (root, pathname, type) { var file = { get data() { if (!this._data) { this._data = fs.readFileSync(path.join(root, pathname)); if (text.indexOf(this.type) !== -1) { decode(this); } } return this._data; }, set data(data) { this._data = data; }, meta: {}, pathname: pathname, type: type || path.extname(pathname) }; return file; }, /** * Determine file or directory. * @param root {string} * @param pathname {string} * @return {string|null} */ stat = exports.stat = function (root, pathname) { var fullPath = path.join(root, pathname); if (fs.existsSync(fullPath)) { if (fs.statSync(fullPath).isDirectory()) { return 'dir'; } else { return 'file'; } } else { return null; } }, /** * Write file or directory. * @param root {string} * @param file {Object} */ writeFile = exports.writeFile = function (root, file) { var fullPath = path.join(root, file.pathname); makeDir(root, path.dirname(file.pathname)); // Ensure container. if (text.indexOf(file.type) !== -1) { encode(file); } fs.writeFileSync(fullPath, file.data); }, /** * Decode text file. * @param file {Object} */ decode = function (file) { if (text.indexOf(file.type) !== -1) { var data = file.data; if (data.length > 2 && !(data[0] ^ 0xEF) && !(data[1] ^ 0xBB) && !(data[2] ^ 0xBF)) { // Remove UTF-8 BOM. data = data.slice(3); } file.data = data.toString('binary'); } }, /** * Encode text file. * @param file {Object} */ encode = function (file) { if (text.indexOf(file.type) !== -1) { file.data = new Buffer(file.data, 'binary'); } };