diff --git a/HISTORY.md b/HISTORY.md index 53389a8..ff29acc 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,7 @@ unreleased ========== * Send non-chunked response for `OPTIONS` + * Stat parent directory when necessary * Use `Date.prototype.toLocaleDateString` to format date * deps: accepts@~1.2.9 - deps: mime-types@~2.1.1 diff --git a/index.js b/index.js index a76c543..1c01f1f 100644 --- a/index.js +++ b/index.js @@ -171,21 +171,21 @@ function serveIndex(root, options) { */ serveIndex.html = function _html(req, res, files, next, dir, showUp, icons, path, view, template, stylesheet) { - fs.readFile(template, 'utf8', function(err, str){ + if (showUp) { + files.unshift('..'); + } + + stat(path, files, function (err, stats) { if (err) return next(err); - fs.readFile(stylesheet, 'utf8', function(err, style){ + fs.readFile(template, 'utf8', function(err, str){ if (err) return next(err); - stat(path, files, function(err, stats){ + fs.readFile(stylesheet, 'utf8', function(err, style){ if (err) return next(err); var fileData = files.map(function (file, i) { return { name: file, stat: stats[i] }; }).sort(fileSort); - if (showUp) { - fileData.unshift({ name: '..' }); - } - var body = str .replace(/\{style\}/g, style.concat(iconStyle(fileData, icons))) .replace(/\{files\}/g, createHtmlFileList(fileData, dir, icons, view)) @@ -243,7 +243,7 @@ function createHtmlFileList(files, dir, useIcons, view) { html += files.map(function (file) { var classes = []; - var isDir = '..' == file.name || (file.stat && file.stat.isDirectory()); + var isDir = file.stat && file.stat.isDirectory(); var path = dir.split('/').map(function (c) { return encodeURIComponent(c); }); if (useIcons) { @@ -293,6 +293,12 @@ function createHtmlFileList(files, dir, useIcons, view) { */ function fileSort(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()); } @@ -393,7 +399,7 @@ function iconStyle (files, useIcons) { for (i = 0; i < files.length; i++) { var file = files[i]; - var isDir = '..' == file.name || (file.stat && file.stat.isDirectory()); + var isDir = file.stat && file.stat.isDirectory(); var icon = isDir ? { className: 'icon-directory', fileName: icons.folder } : iconLookup(file.name); diff --git a/test/fixtures/users/#dir/tobi.txt b/test/fixtures/users/#dir/tobi.txt new file mode 100644 index 0000000..9d9529d --- /dev/null +++ b/test/fixtures/users/#dir/tobi.txt @@ -0,0 +1 @@ +ferret \ No newline at end of file diff --git a/test/test.js b/test/test.js index eec1d23..19697d9 100644 --- a/test/test.js +++ b/test/test.js @@ -270,7 +270,7 @@ describe('serveIndex(root)', function () { }); it('should filter directory paths', function (done) { - var cb = after(3, done) + var cb = after(4, done) var server = createServer(fixtures, {'filter': filter}) function filter(name, index, list, dir) { @@ -451,6 +451,25 @@ describe('serveIndex(root)', function () { .end(done); }); + it('should include link to parent directory', function (done) { + var server = createServer() + + request(server) + .get('/users') + .end(function (err, res) { + if (err) return done(err); + var body = res.text.split('')[1]; + var urls = body.split(/