Comparing version 2.0.0 to 3.0.0
297
lib/fs.js
@@ -6,27 +6,20 @@ 'use strict'; | ||
const { dirname, join, extname, basename } = require('path'); | ||
const fsPromises = fs.promises; | ||
const chokidar = require('chokidar'); | ||
const escapeRegExp = require('escape-string-regexp'); | ||
const { escapeRegExp } = require('hexo-util'); | ||
const rEOL = /\r\n/g; | ||
const statAsync = Promise.promisify(fs.stat); | ||
const readdirAsync = Promise.promisify(fs.readdir); | ||
const unlinkAsync = Promise.promisify(fs.unlink); | ||
const mkdirAsync = Promise.promisify(fs.mkdir); | ||
const writeFileAsync = Promise.promisify(fs.writeFile); | ||
const appendFileAsync = Promise.promisify(fs.appendFile); | ||
const rmdirAsync = Promise.promisify(fs.rmdir); | ||
const readFileAsync = Promise.promisify(fs.readFile); | ||
const createReadStream = fs.createReadStream; | ||
const createWriteStream = fs.createWriteStream; | ||
const accessSync = fs.accessSync; | ||
const accessAsync = Promise.promisify(fs.access); | ||
function exists(path, callback) { | ||
if (!path) throw new TypeError('path is required!'); | ||
return accessAsync(path).then(() => true, () => false).then(exist => { | ||
const promise = fsPromises.access(path).then(() => true, err => { | ||
if (err.code !== 'ENOENT') throw err; | ||
return false; | ||
}).then(exist => { | ||
if (typeof callback === 'function') callback(exist); | ||
return exist; | ||
}); | ||
return Promise.resolve(promise); | ||
} | ||
@@ -40,2 +33,3 @@ | ||
} catch (err) { | ||
if (err.code !== 'ENOENT') throw err; | ||
return false; | ||
@@ -50,9 +44,3 @@ } | ||
const parent = dirname(path); | ||
return exists(parent).then(exist => { | ||
if (!exist) return mkdirs(parent); | ||
}).then(() => mkdirAsync(path)).catch(err => { | ||
if (err.cause.code !== 'EEXIST') throw err; | ||
}).asCallback(callback); | ||
return Promise.resolve(fsPromises.mkdir(path, { recursive: true })).asCallback(callback); | ||
} | ||
@@ -63,37 +51,14 @@ | ||
const parent = dirname(path); | ||
const exist = fs.existsSync(parent); | ||
if (!exist) mkdirsSync(parent); | ||
fs.mkdirSync(path); | ||
fs.mkdirSync(path, { recursive: true }); | ||
} | ||
function checkParent(path) { | ||
if (!path) throw new TypeError('path is required!'); | ||
const parent = dirname(path); | ||
return exists(parent).then(exist => { | ||
if (!exist) return mkdirs(parent); | ||
}); | ||
return Promise.resolve(fsPromises.mkdir(dirname(path), { recursive: true })); | ||
} | ||
function checkParentSync(path) { | ||
function writeFile(path, data, options, callback) { | ||
if (!path) throw new TypeError('path is required!'); | ||
const parent = dirname(path); | ||
const exist = fs.existsSync(parent); | ||
if (!data) data = ''; | ||
if (exist) return; | ||
try { | ||
mkdirsSync(parent); | ||
} catch (err) { | ||
if (err.code !== 'EEXIST') throw err; | ||
} | ||
} | ||
function writeFile(path, data, options, callback) { | ||
if (!path) throw new TypeError('path is required!'); | ||
if (!callback && typeof options === 'function') { | ||
@@ -104,3 +69,3 @@ callback = options; | ||
return checkParent(path).then(() => writeFileAsync(path, data, options)).asCallback(callback); | ||
return checkParent(path).then(() => fsPromises.writeFile(path, data, options)).asCallback(callback); | ||
} | ||
@@ -111,3 +76,3 @@ | ||
checkParentSync(path); | ||
fs.mkdirSync(dirname(path), { recursive: true }); | ||
fs.writeFileSync(path, data, options); | ||
@@ -124,3 +89,3 @@ } | ||
return checkParent(path).then(() => appendFileAsync(path, data, options)).asCallback(callback); | ||
return checkParent(path).then(() => fsPromises.appendFile(path, data, options)).asCallback(callback); | ||
} | ||
@@ -131,15 +96,6 @@ | ||
checkParentSync(path); | ||
fs.mkdirSync(dirname(path), { recursive: true }); | ||
fs.appendFileSync(path, data, options); | ||
} | ||
const _copyFile = fs.copyFile ? Promise.promisify(fs.copyFile) : (src, dest) => new Promise((resolve, reject) => { | ||
const rs = createReadStream(src); | ||
const ws = createWriteStream(dest); | ||
rs.pipe(ws).on('error', reject); | ||
ws.on('close', resolve).on('error', reject); | ||
}); | ||
function copyFile(src, dest, flags, callback) { | ||
@@ -150,5 +106,6 @@ if (!src) throw new TypeError('src is required!'); | ||
callback = flags; | ||
flags = undefined; | ||
} | ||
return checkParent(dest).then(() => _copyFile(src, dest, flags)).asCallback(callback); | ||
return checkParent(dest).then(() => fsPromises.copyFile(src, dest, flags)).asCallback(callback); | ||
} | ||
@@ -163,3 +120,3 @@ | ||
return item => item[0] !== '.'; | ||
return ({ name }) => !name.startsWith('.'); | ||
} | ||
@@ -170,3 +127,3 @@ | ||
return item => !regex.test(item); | ||
return ({ name }) => !regex.test(name); | ||
} | ||
@@ -177,13 +134,5 @@ | ||
// Build a map to make it faster. | ||
const map = {}; | ||
const set = new Set(arr); | ||
for (let i = 0, len = arr.length; i < len; i++) { | ||
map[arr[i]] = true; | ||
} | ||
return item => { | ||
const path = join(parent, item.path); | ||
return !map[path]; | ||
}; | ||
return ({ name }) => !set.has(join(parent, name)); | ||
} | ||
@@ -200,46 +149,29 @@ | ||
function _readAndFilterDir(path, options) { | ||
return readdirAsync(path) | ||
.filter(ignoreHiddenFiles(options.ignoreHidden == null ? true : options.ignoreHidden)) | ||
.filter(ignoreFilesRegex(options.ignorePattern)) | ||
.map(item => { | ||
const fullPath = join(path, item); | ||
return statAsync(fullPath).then(stats => ({ | ||
isDirectory: stats.isDirectory(), | ||
path: item, | ||
fullPath | ||
})); | ||
}); | ||
async function _readAndFilterDir(path, options) { | ||
const { ignoreHidden = true, ignorePattern } = options; | ||
return (await fsPromises.readdir(path, { ...options, withFileTypes: true })) | ||
.filter(ignoreHiddenFiles(ignoreHidden)) | ||
.filter(ignoreFilesRegex(ignorePattern)); | ||
} | ||
function _readAndFilterDirSync(path, options) { | ||
return fs.readdirSync(path) | ||
.filter(ignoreHiddenFiles(options.ignoreHidden == null ? true : options.ignoreHidden)) | ||
.filter(ignoreFilesRegex(options.ignorePattern)) | ||
.map(item => { | ||
const fullPath = join(path, item); | ||
const stats = fs.statSync(fullPath); | ||
return { | ||
isDirectory: stats.isDirectory(), | ||
path: item, | ||
fullPath | ||
}; | ||
}); | ||
const { ignoreHidden = true, ignorePattern } = options; | ||
return fs.readdirSync(path, { ...options, withFileTypes: true }) | ||
.filter(ignoreHiddenFiles(ignoreHidden)) | ||
.filter(ignoreFilesRegex(ignorePattern)); | ||
} | ||
function _copyDir(src, dest, options, parent) { | ||
return _readAndFilterDir(src, options) | ||
.map(item => { | ||
const childSrc = item.fullPath; | ||
const childDest = join(dest, item.path); | ||
const currentPath = join(parent, item.path); | ||
async function _copyDir(src, dest, options, parent) { | ||
const entrys = await _readAndFilterDir(src, options); | ||
return Promise.reduce(entrys.map(item => { | ||
const childSrc = join(src, item.name); | ||
const childDest = join(dest, item.name); | ||
const currentPath = join(parent, item.name); | ||
if (item.isDirectory) { | ||
return _copyDir(childSrc, childDest, options, currentPath); | ||
} | ||
if (item.isDirectory()) { | ||
return _copyDir(childSrc, childDest, options, currentPath); | ||
} | ||
return copyFile(childSrc, childDest, options).thenReturn(currentPath); | ||
}).reduce(reduceFiles, []); | ||
return copyFile(childSrc, childDest).thenReturn(currentPath); | ||
}), reduceFiles, []); | ||
} | ||
@@ -259,12 +191,13 @@ | ||
function _listDir(path, options, parent) { | ||
return _readAndFilterDir(path, options).map(item => { | ||
const currentPath = join(parent, item.path); | ||
async function _listDir(path, options, parent) { | ||
const entrys = await _readAndFilterDir(path, options); | ||
return Promise.reduce(entrys.map(item => { | ||
const currentPath = join(parent, item.name); | ||
if (item.isDirectory) { | ||
return _listDir(item.fullPath, options, currentPath); | ||
if (item.isDirectory()) { | ||
return _listDir(join(path, item.name), options, currentPath); | ||
} | ||
return currentPath; | ||
}).reduce(reduceFiles, []); | ||
}), reduceFiles, []); | ||
} | ||
@@ -280,3 +213,3 @@ | ||
return _listDir(path, options, '').asCallback(callback); | ||
return Promise.resolve(_listDir(path, options, '')).asCallback(callback); | ||
} | ||
@@ -286,6 +219,6 @@ | ||
return _readAndFilterDirSync(path, options).map(item => { | ||
const currentPath = join(parent, item.path); | ||
const currentPath = join(parent, item.name); | ||
if (item.isDirectory) { | ||
return _listDirSync(item.fullPath, options, currentPath); | ||
if (item.isDirectory()) { | ||
return _listDirSync(join(path, item.name), options, currentPath); | ||
} | ||
@@ -315,2 +248,14 @@ | ||
async function _readFile(path, options) { | ||
if (!Object.prototype.hasOwnProperty.call(options, 'encoding')) options.encoding = 'utf8'; | ||
const content = await fsPromises.readFile(path, options); | ||
if (options.escape == null || options.escape) { | ||
return escapeFileContent(content); | ||
} | ||
return content; | ||
} | ||
function readFile(path, options = {}, callback) { | ||
@@ -324,11 +269,3 @@ if (!path) throw new TypeError('path is required!'); | ||
if (!Object.prototype.hasOwnProperty.call(options, 'encoding')) options.encoding = 'utf8'; | ||
return readFileAsync(path, options).then(content => { | ||
if (options.escape == null || options.escape) { | ||
return escapeFileContent(content); | ||
} | ||
return content; | ||
}).asCallback(callback); | ||
return Promise.resolve(_readFile(path, options)).asCallback(callback); | ||
} | ||
@@ -350,17 +287,18 @@ | ||
function _emptyDir(path, options, parent) { | ||
return _readAndFilterDir(path, options) | ||
.filter(ignoreExcludeFiles(options.exclude, parent)) | ||
.map(item => { | ||
const fullPath = item.fullPath; | ||
const currentPath = join(parent, item.path); | ||
async function _emptyDir(path, options, parent) { | ||
const entrys = (await _readAndFilterDir(path, options)) | ||
.filter(ignoreExcludeFiles(options.exclude, parent)); | ||
return Promise.reduce(entrys.map(item => { | ||
const fullPath = join(path, item.name); | ||
const currentPath = join(parent, item.name); | ||
if (item.isDirectory) { | ||
return _emptyDir(fullPath, options, currentPath).tap(() => readdirAsync(fullPath).then(files => { | ||
if (!files.length) return rmdirAsync(fullPath); | ||
})); | ||
} | ||
if (item.isDirectory()) { | ||
return _emptyDir(fullPath, options, currentPath).then(files => { | ||
if (!files.length) return fsPromises.rmdir(fullPath).then(() => files); | ||
return files; | ||
}); | ||
} | ||
return unlinkAsync(fullPath).thenReturn(currentPath); | ||
}).reduce(reduceFiles, []); | ||
return fsPromises.unlink(fullPath).then(() => currentPath); | ||
}), reduceFiles, []); | ||
} | ||
@@ -376,3 +314,3 @@ | ||
return _emptyDir(path, options, '').asCallback(callback); | ||
return Promise.resolve(_emptyDir(path, options, '')).asCallback(callback); | ||
} | ||
@@ -384,6 +322,6 @@ | ||
.map(item => { | ||
const childPath = item.fullPath; | ||
const currentPath = join(parent, item.path); | ||
const childPath = join(path, item.name); | ||
const currentPath = join(parent, item.name); | ||
if (item.isDirectory) { | ||
if (item.isDirectory()) { | ||
const removed = _emptyDirSync(childPath, options, currentPath); | ||
@@ -409,14 +347,10 @@ | ||
function _rmdir(path) { | ||
return readdirAsync(path).map(item => { | ||
const childPath = join(path, item); | ||
async function _rmdir(path) { | ||
const files = await fsPromises.readdir(path, { withFileTypes: true }); | ||
await Promise.all(files.map(item => { | ||
const childPath = join(path, item.name); | ||
return statAsync(childPath).then(stats => { | ||
if (stats.isDirectory()) { | ||
return _rmdir(childPath); | ||
} | ||
return unlinkAsync(childPath); | ||
}); | ||
}).then(() => rmdirAsync(path)); | ||
return item.isDirectory() ? _rmdir(childPath) : fsPromises.unlink(childPath); | ||
})); | ||
return fsPromises.rmdir(path); | ||
} | ||
@@ -427,13 +361,13 @@ | ||
return _rmdir(path).asCallback(callback); | ||
return Promise.resolve(_rmdir(path)).asCallback(callback); | ||
} | ||
function _rmdirSync(path) { | ||
const files = fs.readdirSync(path); | ||
const files = fs.readdirSync(path, { withFileTypes: true }); | ||
for (let i = 0, len = files.length; i < len; i++) { | ||
const childPath = join(path, files[i]); | ||
const stats = fs.statSync(childPath); | ||
const item = files[i]; | ||
const childPath = join(path, item.name); | ||
if (stats.isDirectory()) { | ||
if (item.isDirectory()) { | ||
_rmdirSync(childPath); | ||
@@ -478,5 +412,5 @@ } else { | ||
const item = files[i]; | ||
if (!regex.test(item)) continue; | ||
const match = item.match(regex); | ||
const match = item.match(regex); | ||
if (match == null) continue; | ||
const matchNum = match[1] ? parseInt(match[1], 10) : 0; | ||
@@ -492,10 +426,13 @@ | ||
async function _ensurePath(path) { | ||
if (!await exists(path)) return path; | ||
const files = await fsPromises.readdir(dirname(path)); | ||
return _findUnusedPath(path, files); | ||
} | ||
function ensurePath(path, callback) { | ||
if (!path) throw new TypeError('path is required!'); | ||
return exists(path).then(exist => { | ||
if (!exist) return path; | ||
return readdirAsync(dirname(path)).then(files => _findUnusedPath(path, files)); | ||
}).asCallback(callback); | ||
return Promise.resolve(_ensurePath(path)).asCallback(callback); | ||
} | ||
@@ -526,3 +463,3 @@ | ||
checkParentSync(path); | ||
fs.mkdirSync(dirname(path), { recursive: true }); | ||
return fs.createWriteStream(path, options); | ||
@@ -540,4 +477,4 @@ } | ||
exports.access = accessAsync; | ||
exports.accessSync = accessSync; | ||
exports.access = Promise.promisify(fs.access); | ||
exports.accessSync = fs.accessSync; | ||
@@ -573,4 +510,4 @@ // appendFile | ||
// createStream | ||
exports.createReadStream = createReadStream; | ||
exports.createWriteStream = createWriteStream; | ||
exports.createReadStream = fs.createReadStream; | ||
exports.createWriteStream = fs.createWriteStream; | ||
@@ -606,3 +543,3 @@ // emptyDir | ||
// mkdir | ||
exports.mkdir = mkdirAsync; | ||
exports.mkdir = Promise.promisify(fs.mkdir); | ||
exports.mkdirSync = fs.mkdirSync; | ||
@@ -627,3 +564,3 @@ | ||
// readdir | ||
exports.readdir = readdirAsync; | ||
exports.readdir = Promise.promisify(fs.readdir); | ||
exports.readdirSync = fs.readdirSync; | ||
@@ -652,3 +589,3 @@ | ||
// stat | ||
exports.stat = statAsync; | ||
exports.stat = Promise.promisify(fs.stat); | ||
exports.statSync = fs.statSync; | ||
@@ -667,3 +604,3 @@ exports.fstat = Promise.promisify(fs.fstat); | ||
// unlink | ||
exports.unlink = unlinkAsync; | ||
exports.unlink = Promise.promisify(fs.unlink); | ||
exports.unlinkSync = fs.unlinkSync; | ||
@@ -670,0 +607,0 @@ |
{ | ||
"name": "hexo-fs", | ||
"version": "2.0.0", | ||
"description": "File system module for Hexo.", | ||
"main": "lib/fs.js", | ||
"scripts": { | ||
"eslint": "eslint .", | ||
"test": "mocha test/index.js", | ||
"test-cov": "nyc npm run test" | ||
}, | ||
"directories": { | ||
"lib": "./lib" | ||
}, | ||
"files": [ | ||
"lib/fs.js" | ||
], | ||
"repository": "hexojs/hexo-fs", | ||
"homepage": "https://hexo.io/", | ||
"keywords": [ | ||
"file", | ||
"file system", | ||
"fs", | ||
"hexo" | ||
], | ||
"author": "Tommy Chen <tommy351@gmail.com> (http://zespia.tw)", | ||
"maintainers": [ | ||
"Abner Chou <hi@abnerchou.me> (http://abnerchou.me)" | ||
], | ||
"license": "MIT", | ||
"dependencies": { | ||
"bluebird": "^3.5.1", | ||
"chokidar": "^3.0.0", | ||
"escape-string-regexp": "^2.0.0", | ||
"graceful-fs": "^4.1.11" | ||
}, | ||
"devDependencies": { | ||
"chai": "^4.1.2", | ||
"chai-as-promised": "^7.1.1", | ||
"eslint": "^6.0.1", | ||
"eslint-config-hexo": "^3.0.0", | ||
"iferr": "^1.0.2", | ||
"mocha": "^6.0.2", | ||
"nyc": "^14.1.1" | ||
}, | ||
"engines": { | ||
"node": ">=8" | ||
} | ||
"name": "hexo-fs", | ||
"version": "3.0.0", | ||
"description": "File system module for Hexo.", | ||
"main": "lib/fs.js", | ||
"scripts": { | ||
"eslint": "eslint .", | ||
"test": "mocha test/index.js", | ||
"test-cov": "nyc npm run test" | ||
}, | ||
"directories": { | ||
"lib": "./lib" | ||
}, | ||
"files": [ | ||
"lib/fs.js" | ||
], | ||
"repository": "hexojs/hexo-fs", | ||
"homepage": "https://hexo.io/", | ||
"keywords": [ | ||
"file", | ||
"file system", | ||
"fs", | ||
"hexo" | ||
], | ||
"author": "Tommy Chen <tommy351@gmail.com> (http://zespia.tw)", | ||
"maintainers": [ | ||
"Abner Chou <hi@abnerchou.me> (http://abnerchou.me)" | ||
], | ||
"license": "MIT", | ||
"dependencies": { | ||
"bluebird": "^3.5.1", | ||
"chokidar": "^3.0.0", | ||
"graceful-fs": "^4.1.11", | ||
"hexo-util": "^1.8.1" | ||
}, | ||
"devDependencies": { | ||
"chai": "^4.1.2", | ||
"chai-as-promised": "^7.1.1", | ||
"eslint": "^6.0.1", | ||
"eslint-config-hexo": "^4.1.0", | ||
"iferr": "^1.0.2", | ||
"mocha": "^7.0.0", | ||
"nyc": "^15.0.0" | ||
}, | ||
"engines": { | ||
"node": ">=10" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
0
21817
455
+ Addedhexo-util@^1.8.1
+ Addedcamel-case@4.1.2(transitive)
+ Addedcross-spawn@7.0.5(transitive)
+ Addeddeepmerge@4.3.1(transitive)
+ Addeddom-serializer@1.4.1(transitive)
+ Addeddomelementtype@2.3.0(transitive)
+ Addeddomhandler@3.3.04.3.1(transitive)
+ Addeddomutils@2.8.0(transitive)
+ Addedentities@2.2.0(transitive)
+ Addedhexo-util@1.9.1(transitive)
+ Addedhighlight.js@9.18.5(transitive)
+ Addedhtmlparser2@4.1.0(transitive)
+ Addedisexe@2.0.0(transitive)
+ Addedlower-case@2.0.2(transitive)
+ Addedmin-indent@1.0.1(transitive)
+ Addedno-case@3.0.4(transitive)
+ Addedpascal-case@3.1.2(transitive)
+ Addedpath-key@3.1.1(transitive)
+ Addedprismjs@1.29.0(transitive)
+ Addedpunycode.js@2.3.1(transitive)
+ Addedshebang-command@2.0.0(transitive)
+ Addedshebang-regex@3.0.0(transitive)
+ Addedstrip-indent@3.0.0(transitive)
+ Addedstriptags@3.2.0(transitive)
+ Addedtslib@2.8.1(transitive)
+ Addedwhich@2.0.2(transitive)
- Removedescape-string-regexp@^2.0.0
- Removedescape-string-regexp@2.0.0(transitive)