diff --git a/.gitignore b/.gitignore index 290b269..fbaa842 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,7 @@ node_modules legacy npm-debug.log coverage +*.swp +/.project +/.*.md.html diff --git a/README.md b/README.md index 14eab1b..81cf39f 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,8 @@ with help of [filer](https://github.com/filerjs/filer "Node-like file system for ```js const readify = require('readify'); -radify('/', (error, data) => { +// basic +readify('/', (error, data) => { console.log(data); // output { @@ -45,12 +46,13 @@ radify('/', (error, data) => { size: '4.22kb', date: '20.02.2016', owner: 'coderaiser', - mode: 'rw- rw- r--' + mode: 'rw- rw- r--', }] } }); -radify('/', 'raw', (error, data) => { +// raw output +readify('/', 'raw', (error, data) => { console.log(data); // output { @@ -64,6 +66,19 @@ radify('/', 'raw', (error, data) => { }] } }); + +// sort output +// available sort option: name, size, owner, date +// available order option: asc, desc +readify('/', {sort: 'size', order: 'desc'}, (error, data) => { + console.log(data); +}); + +// all together +readify('/', {sort: 'size', order: 'desc', type: 'raw'}, (error, data) => { + console.log(data); +}); + ``` `browser` example: diff --git a/lib/readify.js b/lib/readify.js index 9564f9a..0456620 100644 --- a/lib/readify.js +++ b/lib/readify.js @@ -30,25 +30,79 @@ const nicki = !WIN && !BROWSER && require('nicki/legacy'); const readdir = promisify(fs.readdir, fs); -// http://www.jstips.co/en/sorting-strings-with-accented-characters/ -const sortFiles = sort((a, b) => { - return a.name.localeCompare(b.name); +/* sorting on Win and node v0.8.0 */ +const sortFiles = currify((attr, order, array) => { + const cmpCallbacks = { + 'numeric': (a, b) => (+a - +b), + // http://www.jstips.co/en/sorting-strings-with-accented-characters/ + 'local_string': (a, b) => a.localeCompare(b), + 'default': (a, b) => (a > b ? 1 : -1), + }; + switch (order) { + case 'asc': + // nothing + break; + case 'desc': + // nothing + break; + default: + order = 'asc'; + } + var cmp; + switch (attr) { + case 'size': + cmp = cmpCallbacks.numeric; + break; + case 'date': + cmp = cmpCallbacks['default']; + break; + case 'owner': + cmp = cmpCallbacks['default']; + break; + case 'name': + cmp = cmpCallbacks.local_string; + break; + default: + attr = 'name'; + cmp = cmpCallbacks.local_string; + } + return sort((a, b) => { + var res = cmp(a[attr], b[attr]); + if (order === 'desc') { + res = -res; + } + return res; + }, array); }); const good = (f) => (...a) => f(null, ...a); module.exports = readify; -function readify(path, type, fn) { +function readify(path, options, fn) { if (!fn) { - fn = type; - type = ''; + fn = options; + options = ''; + } + if (typeof options !== 'object') { + options = { + type: options, + }; + } + if (typeof options.sort === 'undefined') { + options.sort = ''; + } + if (typeof options.order === 'undefined') { + options.order = ''; + } + if (typeof options.type === 'undefined') { + options.type = ''; } check(path, fn); readdir(path) - .then(getAllStats(path, type)) + .then(getAllStats(path, options)) .then(good(fn)) .catch(fn); } @@ -68,12 +122,12 @@ function check(path, callback) { * @param path * @param names */ -function _getAllStats(path, type, names, callback) { +function _getAllStats(path, options, names, callback) { const length = names.length; const dir = format.addSlashToEnd(path); if (!length) - return fillJSON(dir, [], type, callback); + return fillJSON(dir, [], options, callback); const funcs = names.map((name) => { return getStat(name, dir + name); @@ -81,7 +135,7 @@ function _getAllStats(path, type, names, callback) { exec.parallel(funcs, (...args) => { const files = args.slice(1); - fillJSON(dir, files, type, callback); + fillJSON(dir, files, options, callback); }); } @@ -144,8 +198,8 @@ function parseStat(type, stat) { * * @param params - { files, stats, path } */ -function fillJSON(path, stats, type, callback) { - const processFiles = squad(changeOrder, sortFiles, parseAllStats(type)); +function fillJSON(path, stats, options, callback) { + const processFiles = squad(changeOrder, parseAllStats(options.type), sortFiles(options.sort, options.order)); const json = { path: '', files: processFiles(stats) @@ -153,7 +207,7 @@ function fillJSON(path, stats, type, callback) { json.path = format.addSlashToEnd(path); - if (type === 'raw') + if (options.type === 'raw') return callback(null, json); changeUIDToName(json, (error, files) => { @@ -208,4 +262,3 @@ function replaceFromList(obj, prop, array) { }); }); } - diff --git a/test/dir/1.txt b/test/dir/1.txt new file mode 100644 index 0000000..9d07aa0 --- /dev/null +++ b/test/dir/1.txt @@ -0,0 +1 @@ +111 \ No newline at end of file diff --git a/test/dir/2.txt b/test/dir/2.txt new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/test/dir/2.txt @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/dir/3.txt b/test/dir/3.txt new file mode 100644 index 0000000..dc7b54a --- /dev/null +++ b/test/dir/3.txt @@ -0,0 +1 @@ +33 \ No newline at end of file diff --git a/test/readify.js b/test/readify.js index 89030ee..68595ef 100644 --- a/test/readify.js +++ b/test/readify.js @@ -129,7 +129,10 @@ test('readify: result: no owner', (t) => { update(); readify('.', (error, result) => { - delete result.files[0].owner; + result.files = result.files.map(function(file) { + delete file.owner; + return file; + }); t.deepEqual(result, expected, 'should get raw values'); fs.readdir = readdir; @@ -493,6 +496,89 @@ test('readify stat: error', (t) => { }); }); +test('readify sort: name asc', (t) => { + const files = [ + '1.txt', + '2.txt', + '3.txt' + ]; + + readify('./test/dir', {sort: 'name'}, (error, data) => { + t.notOk(error, 'no error'); + data.files = data.files.map(function(file) { + return file.name; + }); + t.deepEqual(data.files, files, 'correct order'); + t.end(); + }); +}); + +test('readify sort: name desc', (t) => { + const files = [ + '3.txt', + '2.txt', + '1.txt' + ]; + + readify('./test/dir', {sort: 'name', order: 'desc'}, (error, data) => { + t.notOk(error, 'no error'); + data.files = data.files.map(function(file) { + return file.name; + }); + t.deepEqual(data.files, files, 'correct order'); + t.end(); + }); +}); + +test('readify sort: size asc', (t) => { + const files = [ + '2.txt', + '3.txt', + '1.txt' + ]; + + readify('./test/dir', {sort: 'size', order: 'asc'}, (error, data) => { + t.notOk(error, 'no error'); + data.files = data.files.map(function(file) { + return file.name; + }); + t.deepEqual(data.files, files, 'correct order'); + t.end(); + }); +}); + +test('readify sort: size asc raw', (t) => { + const files = [ + '2.txt', + '3.txt', + '1.txt' + ]; + + readify('./test/dir', {sort: 'size', type: 'raw'}, (error, data) => { + t.notOk(error, 'no error'); + data.files = data.files.map(function(file) { + return file.name; + }); + t.deepEqual(data.files, files, 'correct order'); + t.end(); + }); +}); + +// no comment +test('readify sort: owner', (t) => { + readify('./test/dir', {sort: 'owner'}, (error) => { + t.notOk(error, 'no error'); + t.end(); + }); +}); + +test('readify sort: date', (t) => { + readify('./test/dir', {sort: 'date'}, (error) => { + t.notOk(error, 'no error'); + t.end(); + }); +}); + test('browser: filer', (t) => { const Filer = { FileSystem: sinon.stub()