Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sorting option #37

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,16 @@ provided locals:
* `path` is the full filesystem path to `directory`.
* `style` is the default stylesheet or the contents of the `stylesheet` option.
* `viewName` is the view name provided by the `view` option.
* `sorting` is the function to be used for custom sorting, provided by the `sorting` option

##### view

Display mode. `tiles` and `details` are available. Defaults to `tiles`.

##### sorting

Optional sorting of the files in the listing. To apply custom sorting pass a function for handling the sorting. If nothing is passed, files will be sortted on name.

## Examples

### Serve directory indexes with vanilla node.js http server
Expand Down
26 changes: 15 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ function serveIndex(root, options) {
var stylesheet = opts.stylesheet || defaultStylesheet;
var template = opts.template || defaultTemplate;
var view = opts.view || 'tiles';
var sorting = opts.sorting;

return function (req, res, next) {
if (req.method !== 'GET' && req.method !== 'HEAD') {
Expand Down Expand Up @@ -160,7 +161,7 @@ function serveIndex(root, options) {

// not acceptable
if (!type) return next(createError(406));
serveIndex[mediaType[type]](req, res, files, next, originalDir, showUp, icons, path, view, template, stylesheet);
serveIndex[mediaType[type]](req, res, files, next, originalDir, showUp, icons, path, view, template, stylesheet, sorting);
});
});
};
Expand All @@ -170,7 +171,7 @@ function serveIndex(root, options) {
* Respond with text/html.
*/

serveIndex.html = function _html(req, res, files, next, dir, showUp, icons, path, view, template, stylesheet) {
serveIndex.html = function _html(req, res, files, next, dir, showUp, icons, path, view, template, stylesheet, sorting) {
var render = typeof template !== 'function'
? createHtmlRender(template)
: template
Expand All @@ -189,7 +190,7 @@ serveIndex.html = function _html(req, res, files, next, dir, showUp, icons, path
});

// sort file list
fileList.sort(fileSort);
fileList.sort(fileSort(sorting));

// read stylesheet
fs.readFile(stylesheet, 'utf8', function (err, style) {
Expand Down Expand Up @@ -330,15 +331,18 @@ function createHtmlRender(template) {
* Sort function for with directories first.
*/

function fileSort(a, b) {
// sort ".." to the top
if (a.name === '..' || b.name === '..') {
return a.name === b.name ? 0
: a.name === '..' ? -1 : 1;
}
function fileSort(sortFn) {
return function (a, b) {
// sort ".." to the top
if (a.name === '..' || b.name === '..') {
return a.name === b.name ? 0
: a.name === '..' ? -1 : 1;
}

return Number(b.stat && b.stat.isDirectory()) - Number(a.stat && a.stat.isDirectory()) ||
String(a.name).toLocaleLowerCase().localeCompare(String(b.name).toLocaleLowerCase());
return sortFn ? sortFn(a, b)
: Number(b.stat && b.stat.isDirectory()) - Number(a.stat && a.stat.isDirectory()) ||
String(a).toLocaleLowerCase().localeCompare(String(b).toLocaleLowerCase())
}
}

/**
Expand Down
33 changes: 33 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,39 @@ describe('serveIndex(root)', function () {
});
});

describe('with "sorting" option', function () {
it('should sort files on name by default', function (done) {
var server = createServer(fixtures);

request(server)
.get('/')
.expect(function (res) {
if (res.text.indexOf('todo.txt') > res.text.indexOf('file #1.txt')){
return;
}
throw new Error('default sorting is not by name');
})
.expect(200, done);
});

it('should use options.sorting when being passed a function', function (done) {
var server = createServer(fixtures, {sorting: function sortByFilesize(a, b) {
return a.stat.size < b.stat.size ? 1 : -1;
}});

request(server)
.get('/')
.expect(function (res) {
if (res.text.indexOf('todo.txt') < res.text.indexOf('file #1.txt')){
return;
}
throw new Error('sorting function not applied');
})
.expect(200, done);
});

});

describe('with "icons" option', function () {
it('should include icons for html', function (done) {
var server = createServer(fixtures, {'icons': true})
Expand Down