diff --git a/index.js b/index.js index e707bbc5..950f0dad 100644 --- a/index.js +++ b/index.js @@ -14,6 +14,7 @@ */ var accepts = require('accepts'); +var bytes = require('bytes') var createError = require('http-errors'); var debug = require('debug')('serve-index'); var escapeHtml = require('escape-html'); @@ -144,6 +145,13 @@ function serveIndex(root, options) { if (!stat.isDirectory()) return next(); + // content-negotiation + var accept = accepts(req); + var type = accept.type(mediaTypes); + + // not acceptable + if (!type) return next(createError(406)); + // fetch files debug('readdir "%s"', path); fs.readdir(path, function(err, files){ @@ -154,13 +162,44 @@ function serveIndex(root, options) { }); files.sort(); - // content-negotiation - var accept = accepts(req); - var type = accept.type(mediaTypes); + // add parent directory as first + if (showUp) { + files.unshift('..'); + } - // not acceptable - if (!type) return next(createError(406)); - serveIndex[mediaType[type]](req, res, files, next, originalDir, showUp, icons, path, view, template, stylesheet); + // stat all files + fstat(path, files, function (err, stats) { + if (err) return next(err); + + // combine the stats into the file list + var fileList = files.map(function (file, i) { + return { name: file, stat: stats[i] }; + }); + + // sort file list + fileList.sort(fileSort); + + // make similar to W3 FileAPI Object + var directory = { + name: originalDir, + type: 'inode/directory', + size: stat.size, + lastModified: stat.mtime + } + + var nodes = fileList.map(function (file) { + var ext = extname(file.name) + var mimetype = mime.lookup(ext) + return { + name: file.name, + type: file.stat.isDirectory() ? 'inode/directory' : mimetype, + size: file.stat.size, + lastModified: file.stat.mtime + } + }) + + serveIndex[mediaType[type]](req, res, directory, nodes, next, showUp, icons, path, view, template, stylesheet); + }); }); }); }; @@ -170,46 +209,29 @@ 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, dir, files, next, showUp, icons, path, view, template, stylesheet) { var render = typeof template !== 'function' ? createHtmlRender(template) : template - if (showUp) { - files.unshift('..'); - } - - // stat all files - stat(path, files, function (err, stats) { + // read stylesheet + fs.readFile(stylesheet, 'utf8', function (err, style) { if (err) return next(err); - // combine the stats into the file list - var fileList = files.map(function (file, i) { - return { name: file, stat: stats[i] }; - }); - - // sort file list - fileList.sort(fileSort); + // create locals for rendering + var locals = { + directory: dir.name, + displayIcons: Boolean(icons), + fileList: files, + path: path, + style: style, + viewName: view + }; - // read stylesheet - fs.readFile(stylesheet, 'utf8', function (err, style) { + // render html + render(locals, function (err, body) { if (err) return next(err); - - // create locals for rendering - var locals = { - directory: dir, - displayIcons: Boolean(icons), - fileList: fileList, - path: path, - style: style, - viewName: view - }; - - // render html - render(locals, function (err, body) { - if (err) return next(err); - send(res, 'text/html', body) - }); + send(res, 'text/html', body) }); }); }; @@ -218,16 +240,31 @@ serveIndex.html = function _html(req, res, files, next, dir, showUp, icons, path * Respond with application/json. */ -serveIndex.json = function _json(req, res, files) { - send(res, 'application/json', JSON.stringify(files)) +serveIndex.json = function _json(req, res, directory, nodes) { + send(res, 'application/json', JSON.stringify({ directory: directory, nodes: nodes })) }; /** * Respond with text/plain. */ -serveIndex.plain = function _plain(req, res, files) { - send(res, 'text/plain', (files.join('\n') + '\n')) +serveIndex.plain = function _plain(req, res, dir, files) { + var directory = { + name: dir.name.replace(/\/?$/, '/') + }; + + // include size and date + var nodes = files.map(function (file) { + // human readable + var size = bytes(file.size) + + return [ + file.lastModified.toISOString(), + size, + file.name + ('inode/directory' === file.type ? '/' : '') + ].join('\t') + }) + send(res, 'text/plain', (directory.name + '\n' + nodes.join('\n') + '\n')) }; /** @@ -235,7 +272,7 @@ serveIndex.plain = function _plain(req, res, files) { * @private */ -function createHtmlFileList(files, dir, useIcons, view) { +function createHtmlFileList(files, dirname, useIcons, view) { var html = '