commit c4213dc3e55af14173de323e29bccec7818bfb73 Author: Douglas Christopher Wilson Date: Wed Mar 5 18:28:02 2014 -0500 init from connect diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c4cdf95 --- /dev/null +++ b/.gitignore @@ -0,0 +1,65 @@ +# Compiled source # +################### +*.com +*.class +*.dll +*.exe +*.o +*.so + +# Packages # +############ +# it's better to unpack these files and commit the raw source +# git has its own built in compression methods +*.7z +*.dmg +*.gz +*.iso +*.jar +*.rar +*.tar +*.zip + +# Logs and databases # +###################### +*.log +*.sql +*.sqlite + +# OS generated files # +###################### +.DS_Store* +ehthumbs.db +Thumbs.db + +# Node.js # +########### +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz + +pids +logs +results + +node_modules +npm-debug.log + +# Git # +####### +*.orig +*.BASE.* +*.BACKUP.* +*.LOCAL.* +*.REMOTE.* + +# Components # +############## + +/build +/components diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/.npmignore @@ -0,0 +1 @@ +test diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..cc4dba2 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "0.8" + - "0.10" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b7bc085 --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ +(The MIT License) + +Copyright (c) 2010 Sencha Inc. +Copyright (c) 2011 LearnBoost +Copyright (c) 2011 TJ Holowaychuk +Copyright (c) 2014 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..b990866 --- /dev/null +++ b/Readme.md @@ -0,0 +1,39 @@ +# Serve Index + +Previously `connect.directory()`. + +Usage: + +```js +var connect = require('connect'); +var serveIndex = require('serve-index'); + +var app = connect(); + +app.use(serveIndex('public/ftp', {'icons': true})); +app.listen(); +``` + +## License + +The MIT License (MIT) + +Copyright (c) 2014 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/index.js b/index.js new file mode 100644 index 0000000..1c058a5 --- /dev/null +++ b/index.js @@ -0,0 +1,498 @@ + +/*! + * Connect - directory + * Copyright(c) 2011 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * Copyright(c) 2014 Douglas Christopher Wilson + * MIT Licensed + */ + +// TODO: arrow key navigation +// TODO: make icons extensible + +/** + * Module dependencies. + */ + +var http = require('http') + , fs = require('fs') + , parse = require('url').parse + , path = require('path') + , normalize = path.normalize + , sep = path.sep + , extname = path.extname + , join = path.join; +var Batch = require('batch'); +var Negotiator = require('negotiator'); + +/*! + * Icon cache. + */ + +var cache = {}; + +/*! + * Default template. + */ + +var defaultTemplate = join(__dirname, 'public', 'directory.html'); + +/*! + * Stylesheet. + */ + +var stylesheet = join(__dirname, 'public', 'style.css'); + +/** + * Media types and the map for content negotiation. + */ + +var mediaTypes = [ + 'text/html', + 'text/plain', + 'application/json' +]; + +var mediaType = { + 'text/html': 'html', + 'text/plain': 'plain', + 'application/json': 'json' +}; + +/** + * Directory: + * + * Serve directory listings with the given `root` path. + * + * Options: + * + * - `hidden` display hidden (dot) files. Defaults to false. + * - `icons` display icons. Defaults to false. + * - `filter` Apply this filter function to files. Defaults to false. + * - `template` Optional path to html template. Defaults to a built-in template. + * The following tokens are replaced: + * - `{directory}` with the name of the directory. + * - `{files}` with the HTML of an unordered list of file links. + * - `{linked-path}` with the HTML of a link to the directory. + * - `{style}` with the built-in CSS and embedded images. + * + * @param {String} root + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function directory(root, options){ + options = options || {}; + + // root required + if (!root) throw new Error('directory() root path required'); + var hidden = options.hidden + , icons = options.icons + , view = options.view || 'tiles' + , filter = options.filter + , root = normalize(root + sep) + , template = options.template || defaultTemplate; + + return function directory(req, res, next) { + if ('GET' != req.method && 'HEAD' != req.method) return next(); + + var url = parse(req.url) + , dir = decodeURIComponent(url.pathname) + , path = normalize(join(root, dir)) + , originalUrl = parse(req.originalUrl) + , originalDir = decodeURIComponent(originalUrl.pathname) + , showUp = path != root; + + // null byte(s), bad request + if (~path.indexOf('\0')) return next(createError(400)); + + // malicious path, forbidden + if (0 != path.indexOf(root)) return next(createError(403)); + + // check if we have a directory + fs.stat(path, function(err, stat){ + if (err) return 'ENOENT' == err.code + ? next() + : next(err); + + if (!stat.isDirectory()) return next(); + + // fetch files + fs.readdir(path, function(err, files){ + if (err) return next(err); + if (!hidden) files = removeHidden(files); + if (filter) files = files.filter(filter); + files.sort(); + + // content-negotiation + var type = new Negotiator(req).preferredMediaType(mediaTypes); + + // not acceptable + if (!type) return next(createError(406)); + exports[mediaType[type]](req, res, files, next, originalDir, showUp, icons, path, view, template); + }); + }); + }; +}; + +/** + * Respond with text/html. + */ + +exports.html = function(req, res, files, next, dir, showUp, icons, path, view, template){ + fs.readFile(template, 'utf8', function(err, str){ + if (err) return next(err); + fs.readFile(stylesheet, 'utf8', function(err, style){ + if (err) return next(err); + stat(path, files, function(err, stats){ + if (err) return next(err); + files = files.map(function(file, i){ return { name: file, stat: stats[i] }; }); + files.sort(fileSort); + if (showUp) files.unshift({ name: '..' }); + str = str + .replace('{style}', style.concat(iconStyle(files, icons))) + .replace('{files}', html(files, dir, icons, view)) + .replace('{directory}', dir) + .replace('{linked-path}', htmlPath(dir)); + res.setHeader('Content-Type', 'text/html'); + res.setHeader('Content-Length', str.length); + res.end(str); + }); + }); + }); +}; + +/** + * Respond with application/json. + */ + +exports.json = function(req, res, files){ + files = JSON.stringify(files); + res.setHeader('Content-Type', 'application/json'); + res.setHeader('Content-Length', files.length); + res.end(files); +}; + +/** + * Respond with text/plain. + */ + +exports.plain = function(req, res, files){ + files = files.join('\n') + '\n'; + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Content-Length', files.length); + res.end(files); +}; + +/** + * Generate an `Error` from the given status `code` + * and optional `msg`. + * + * @param {Number} code + * @param {String} msg + * @return {Error} + * @api private + */ + +function createError(code, msg) { + var err = new Error(msg || http.STATUS_CODES[code]); + err.status = code; + return err; +}; + +/** + * Sort function for with directories first. + */ + +function fileSort(a, b) { + return Number(b.stat && b.stat.isDirectory()) - Number(a.stat && a.stat.isDirectory()) || + String(a.name).toLocaleLowerCase().localeCompare(String(b.name).toLocaleLowerCase()); +} + +/** + * Map html `dir`, returning a linked path. + */ + +function htmlPath(dir) { + var curr = []; + return dir.split('/').map(function(part){ + curr.push(encodeURIComponent(part)); + return part ? '' + part + '' : ''; + }).join(' / '); +} + +/** + * Load icon images, return css string. + */ + +function iconStyle (files, useIcons) { + if (!useIcons) return ''; + var className; + var i; + var icon; + var list = []; + var rules = {}; + var selector; + var selectors = {}; + var style = ''; + + for (i = 0; i < files.length; i++) { + var file = files[i]; + + var isDir = '..' == file.name || (file.stat && file.stat.isDirectory()); + icon = isDir ? icons.folder : icons[extname(file.name)] || icons.default; + + var ext = extname(file.name); + className = 'icon-' + (isDir ? 'directory' : (icons[ext] ? ext.substring(1) : 'default')); + selector = '#files .' + className + ' .name'; + + if (!rules[icon]) { + rules[icon] = 'background-image: url(data:image/png;base64,' + load(icon) + ');' + selectors[icon] = []; + list.push(icon); + } + + if (!~selectors[icon].indexOf(selector)) { + selectors[icon].push(selector); + } + } + + for (i = 0; i < list.length; i++) { + icon = list[i]; + style += selectors[icon].join(',\n') + ' {\n ' + rules[icon] + '\n}\n'; + } + + return style; +} + +/** + * Map html `files`, returning an html unordered list. + */ + +function html(files, dir, useIcons, view) { + return ''; +} + +/** + * Load and cache the given `icon`. + * + * @param {String} icon + * @return {String} + * @api private + */ + +function load(icon) { + if (cache[icon]) return cache[icon]; + return cache[icon] = fs.readFileSync(__dirname + '/public/icons/' + icon, 'base64'); +} + +/** + * Normalizes the path separator from system separator + * to URL separator, aka `/`. + * + * @param {String} path + * @return {String} + * @api private + */ + +function normalizeSlashes(path) { + return path.split(sep).join('/'); +}; + +/** + * Filter "hidden" `files`, aka files + * beginning with a `.`. + * + * @param {Array} files + * @return {Array} + * @api private + */ + +function removeHidden(files) { + return files.filter(function(file){ + return '.' != file[0]; + }); +} + +/** + * Stat all files and return array of stat + * in same order. + */ + +function stat(dir, files, cb) { + var batch = new Batch(); + + batch.concurrency(10); + + files.forEach(function(file){ + batch.push(function(done){ + fs.stat(join(dir, file), done); + }); + }); + + batch.end(cb); +} + +/** + * Icon map. + */ + +var icons = { + '.js': 'page_white_code_red.png' + , '.json': 'page_white_code.png' + , '.c': 'page_white_c.png' + , '.h': 'page_white_h.png' + , '.cc': 'page_white_cplusplus.png' + , '.php': 'page_white_php.png' + , '.rb': 'page_white_ruby.png' + , '.erb': 'page_white_ruby.png' + , '.cpp': 'page_white_cplusplus.png' + , '.as': 'page_white_actionscript.png' + , '.cfm': 'page_white_coldfusion.png' + , '.cs': 'page_white_csharp.png' + , '.java': 'page_white_cup.png' + , '.jsp': 'page_white_cup.png' + , '.dll': 'page_white_gear.png' + , '.ini': 'page_white_gear.png' + , '.asp': 'page_white_code.png' + , '.aspx': 'page_white_code.png' + , '.clj': 'page_white_code.png' + , '.css': 'page_white_code.png' + , '.sass': 'page_white_code.png' + , '.scss': 'page_white_code.png' + , '.less': 'page_white_code.png' + , '.htm': 'page_white_code.png' + , '.html': 'page_white_code.png' + , '.xhtml': 'page_white_code.png' + , '.lua': 'page_white_code.png' + , '.m': 'page_white_code.png' + , '.pl': 'page_white_code.png' + , '.py': 'page_white_code.png' + , '.vb': 'page_white_code.png' + , '.vbs': 'page_white_code.png' + , '.xml': 'page_white_code.png' + , '.yaws': 'page_white_code.png' + , '.map': 'map.png' + + , '.app': 'application_xp.png' + , '.exe': 'application_xp.png' + , '.bat': 'application_xp_terminal.png' + , '.cgi': 'application_xp_terminal.png' + , '.sh': 'application_xp_terminal.png' + + , '.avi': 'film.png' + , '.flv': 'film.png' + , '.mv4': 'film.png' + , '.mov': 'film.png' + , '.mp4': 'film.png' + , '.mpeg': 'film.png' + , '.mpg': 'film.png' + , '.ogv': 'film.png' + , '.rm': 'film.png' + , '.webm': 'film.png' + , '.wmv': 'film.png' + , '.fnt': 'font.png' + , '.otf': 'font.png' + , '.ttf': 'font.png' + , '.woff': 'font.png' + , '.bmp': 'image.png' + , '.gif': 'image.png' + , '.ico': 'image.png' + , '.jpeg': 'image.png' + , '.jpg': 'image.png' + , '.png': 'image.png' + , '.psd': 'page_white_picture.png' + , '.xcf': 'page_white_picture.png' + , '.pdf': 'page_white_acrobat.png' + , '.swf': 'page_white_flash.png' + , '.ai': 'page_white_vector.png' + , '.eps': 'page_white_vector.png' + , '.ps': 'page_white_vector.png' + , '.svg': 'page_white_vector.png' + + , '.ods': 'page_white_excel.png' + , '.xls': 'page_white_excel.png' + , '.xlsx': 'page_white_excel.png' + , '.odp': 'page_white_powerpoint.png' + , '.ppt': 'page_white_powerpoint.png' + , '.pptx': 'page_white_powerpoint.png' + , '.md': 'page_white_text.png' + , '.srt': 'page_white_text.png' + , '.txt': 'page_white_text.png' + , '.doc': 'page_white_word.png' + , '.docx': 'page_white_word.png' + , '.odt': 'page_white_word.png' + , '.rtf': 'page_white_word.png' + + , '.dmg': 'drive.png' + , '.iso': 'cd.png' + , '.7z': 'box.png' + , '.apk': 'box.png' + , '.bz2': 'box.png' + , '.cab': 'box.png' + , '.deb': 'box.png' + , '.gz': 'box.png' + , '.jar': 'box.png' + , '.lz': 'box.png' + , '.lzma': 'box.png' + , '.msi': 'box.png' + , '.pkg': 'box.png' + , '.rar': 'box.png' + , '.rpm': 'box.png' + , '.tar': 'box.png' + , '.tbz2': 'box.png' + , '.tgz': 'box.png' + , '.tlz': 'box.png' + , '.xz': 'box.png' + , '.zip': 'box.png' + + , '.accdb': 'page_white_database.png' + , '.db': 'page_white_database.png' + , '.dbf': 'page_white_database.png' + , '.mdb': 'page_white_database.png' + , '.pdb': 'page_white_database.png' + , '.sql': 'page_white_database.png' + + , '.gam': 'controller.png' + , '.rom': 'controller.png' + , '.sav': 'controller.png' + + , 'folder': 'folder.png' + , 'default': 'page_white.png' +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..d3ac9bb --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "serve-index", + "description": "Serve directory listings", + "version": "1.0.0", + "author": "Douglas Christopher Wilson ", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/expressjs/serve-index.git" + }, + "bugs": { + "url": "https://github.com/expressjs/serve-index/issues" + }, + "dependencies": { + "batch": "0.5.0", + "negotiator": "0.3.0" + }, + "devDependencies": { + "connect": "^2.13.0", + "mocha": "^1.17.0", + "should": "^3.0.0", + "supertest": "~0.9.0" + }, + "engines": { + "node": ">= 0.8.0" + }, + "scripts": { + "test": "mocha --reporter spec --require should" + } +} diff --git a/public/directory.html b/public/directory.html new file mode 100644 index 0000000..8ed8b4a --- /dev/null +++ b/public/directory.html @@ -0,0 +1,82 @@ + + + + + + listing directory {directory} + + + + + +
+

{linked-path}

+ {files} +
+ + \ No newline at end of file diff --git a/public/icons/application_xp.png b/public/icons/application_xp.png new file mode 100644 index 0000000..d22860a Binary files /dev/null and b/public/icons/application_xp.png differ diff --git a/public/icons/application_xp_terminal.png b/public/icons/application_xp_terminal.png new file mode 100644 index 0000000..c28dd63 Binary files /dev/null and b/public/icons/application_xp_terminal.png differ diff --git a/public/icons/box.png b/public/icons/box.png new file mode 100644 index 0000000..8443c23 Binary files /dev/null and b/public/icons/box.png differ diff --git a/public/icons/cd.png b/public/icons/cd.png new file mode 100644 index 0000000..ef43223 Binary files /dev/null and b/public/icons/cd.png differ diff --git a/public/icons/controller.png b/public/icons/controller.png new file mode 100644 index 0000000..5cf76ed Binary files /dev/null and b/public/icons/controller.png differ diff --git a/public/icons/drive.png b/public/icons/drive.png new file mode 100644 index 0000000..37b7c9b Binary files /dev/null and b/public/icons/drive.png differ diff --git a/public/icons/film.png b/public/icons/film.png new file mode 100644 index 0000000..b0ce7bb Binary files /dev/null and b/public/icons/film.png differ diff --git a/public/icons/folder.png b/public/icons/folder.png new file mode 100644 index 0000000..698f3d3 Binary files /dev/null and b/public/icons/folder.png differ diff --git a/public/icons/font.png b/public/icons/font.png new file mode 100644 index 0000000..b7960db Binary files /dev/null and b/public/icons/font.png differ diff --git a/public/icons/image.png b/public/icons/image.png new file mode 100644 index 0000000..fc3c393 Binary files /dev/null and b/public/icons/image.png differ diff --git a/public/icons/map.png b/public/icons/map.png new file mode 100644 index 0000000..f90ef25 Binary files /dev/null and b/public/icons/map.png differ diff --git a/public/icons/page.png b/public/icons/page.png new file mode 100644 index 0000000..03ddd79 Binary files /dev/null and b/public/icons/page.png differ diff --git a/public/icons/page_add.png b/public/icons/page_add.png new file mode 100644 index 0000000..d5bfa07 Binary files /dev/null and b/public/icons/page_add.png differ diff --git a/public/icons/page_attach.png b/public/icons/page_attach.png new file mode 100644 index 0000000..89ee2da Binary files /dev/null and b/public/icons/page_attach.png differ diff --git a/public/icons/page_code.png b/public/icons/page_code.png new file mode 100644 index 0000000..f7ea904 Binary files /dev/null and b/public/icons/page_code.png differ diff --git a/public/icons/page_copy.png b/public/icons/page_copy.png new file mode 100644 index 0000000..195dc6d Binary files /dev/null and b/public/icons/page_copy.png differ diff --git a/public/icons/page_delete.png b/public/icons/page_delete.png new file mode 100644 index 0000000..3141467 Binary files /dev/null and b/public/icons/page_delete.png differ diff --git a/public/icons/page_edit.png b/public/icons/page_edit.png new file mode 100644 index 0000000..046811e Binary files /dev/null and b/public/icons/page_edit.png differ diff --git a/public/icons/page_error.png b/public/icons/page_error.png new file mode 100644 index 0000000..f07f449 Binary files /dev/null and b/public/icons/page_error.png differ diff --git a/public/icons/page_excel.png b/public/icons/page_excel.png new file mode 100644 index 0000000..eb6158e Binary files /dev/null and b/public/icons/page_excel.png differ diff --git a/public/icons/page_find.png b/public/icons/page_find.png new file mode 100644 index 0000000..2f19388 Binary files /dev/null and b/public/icons/page_find.png differ diff --git a/public/icons/page_gear.png b/public/icons/page_gear.png new file mode 100644 index 0000000..8e83281 Binary files /dev/null and b/public/icons/page_gear.png differ diff --git a/public/icons/page_go.png b/public/icons/page_go.png new file mode 100644 index 0000000..80fe1ed Binary files /dev/null and b/public/icons/page_go.png differ diff --git a/public/icons/page_green.png b/public/icons/page_green.png new file mode 100644 index 0000000..de8e003 Binary files /dev/null and b/public/icons/page_green.png differ diff --git a/public/icons/page_key.png b/public/icons/page_key.png new file mode 100644 index 0000000..d6626cb Binary files /dev/null and b/public/icons/page_key.png differ diff --git a/public/icons/page_lightning.png b/public/icons/page_lightning.png new file mode 100644 index 0000000..7e56870 Binary files /dev/null and b/public/icons/page_lightning.png differ diff --git a/public/icons/page_link.png b/public/icons/page_link.png new file mode 100644 index 0000000..312eab0 Binary files /dev/null and b/public/icons/page_link.png differ diff --git a/public/icons/page_paintbrush.png b/public/icons/page_paintbrush.png new file mode 100644 index 0000000..246a2f0 Binary files /dev/null and b/public/icons/page_paintbrush.png differ diff --git a/public/icons/page_paste.png b/public/icons/page_paste.png new file mode 100644 index 0000000..968f073 Binary files /dev/null and b/public/icons/page_paste.png differ diff --git a/public/icons/page_red.png b/public/icons/page_red.png new file mode 100644 index 0000000..0b18247 Binary files /dev/null and b/public/icons/page_red.png differ diff --git a/public/icons/page_refresh.png b/public/icons/page_refresh.png new file mode 100644 index 0000000..cf347c7 Binary files /dev/null and b/public/icons/page_refresh.png differ diff --git a/public/icons/page_save.png b/public/icons/page_save.png new file mode 100644 index 0000000..caea546 Binary files /dev/null and b/public/icons/page_save.png differ diff --git a/public/icons/page_white.png b/public/icons/page_white.png new file mode 100644 index 0000000..8b8b1ca Binary files /dev/null and b/public/icons/page_white.png differ diff --git a/public/icons/page_white_acrobat.png b/public/icons/page_white_acrobat.png new file mode 100644 index 0000000..8f8095e Binary files /dev/null and b/public/icons/page_white_acrobat.png differ diff --git a/public/icons/page_white_actionscript.png b/public/icons/page_white_actionscript.png new file mode 100644 index 0000000..159b240 Binary files /dev/null and b/public/icons/page_white_actionscript.png differ diff --git a/public/icons/page_white_add.png b/public/icons/page_white_add.png new file mode 100644 index 0000000..aa23dde Binary files /dev/null and b/public/icons/page_white_add.png differ diff --git a/public/icons/page_white_c.png b/public/icons/page_white_c.png new file mode 100644 index 0000000..34a05cc Binary files /dev/null and b/public/icons/page_white_c.png differ diff --git a/public/icons/page_white_camera.png b/public/icons/page_white_camera.png new file mode 100644 index 0000000..f501a59 Binary files /dev/null and b/public/icons/page_white_camera.png differ diff --git a/public/icons/page_white_cd.png b/public/icons/page_white_cd.png new file mode 100644 index 0000000..848bdaf Binary files /dev/null and b/public/icons/page_white_cd.png differ diff --git a/public/icons/page_white_code.png b/public/icons/page_white_code.png new file mode 100644 index 0000000..0c76bd1 Binary files /dev/null and b/public/icons/page_white_code.png differ diff --git a/public/icons/page_white_code_red.png b/public/icons/page_white_code_red.png new file mode 100644 index 0000000..87a6914 Binary files /dev/null and b/public/icons/page_white_code_red.png differ diff --git a/public/icons/page_white_coldfusion.png b/public/icons/page_white_coldfusion.png new file mode 100644 index 0000000..c66011f Binary files /dev/null and b/public/icons/page_white_coldfusion.png differ diff --git a/public/icons/page_white_compressed.png b/public/icons/page_white_compressed.png new file mode 100644 index 0000000..2b6b100 Binary files /dev/null and b/public/icons/page_white_compressed.png differ diff --git a/public/icons/page_white_copy.png b/public/icons/page_white_copy.png new file mode 100644 index 0000000..a9f31a2 Binary files /dev/null and b/public/icons/page_white_copy.png differ diff --git a/public/icons/page_white_cplusplus.png b/public/icons/page_white_cplusplus.png new file mode 100644 index 0000000..a87cf84 Binary files /dev/null and b/public/icons/page_white_cplusplus.png differ diff --git a/public/icons/page_white_csharp.png b/public/icons/page_white_csharp.png new file mode 100644 index 0000000..ffb8fc9 Binary files /dev/null and b/public/icons/page_white_csharp.png differ diff --git a/public/icons/page_white_cup.png b/public/icons/page_white_cup.png new file mode 100644 index 0000000..0a7d6f4 Binary files /dev/null and b/public/icons/page_white_cup.png differ diff --git a/public/icons/page_white_database.png b/public/icons/page_white_database.png new file mode 100644 index 0000000..bddba1f Binary files /dev/null and b/public/icons/page_white_database.png differ diff --git a/public/icons/page_white_delete.png b/public/icons/page_white_delete.png new file mode 100644 index 0000000..af1ecaf Binary files /dev/null and b/public/icons/page_white_delete.png differ diff --git a/public/icons/page_white_dvd.png b/public/icons/page_white_dvd.png new file mode 100644 index 0000000..4cc537a Binary files /dev/null and b/public/icons/page_white_dvd.png differ diff --git a/public/icons/page_white_edit.png b/public/icons/page_white_edit.png new file mode 100644 index 0000000..b93e776 Binary files /dev/null and b/public/icons/page_white_edit.png differ diff --git a/public/icons/page_white_error.png b/public/icons/page_white_error.png new file mode 100644 index 0000000..9fc5a0a Binary files /dev/null and b/public/icons/page_white_error.png differ diff --git a/public/icons/page_white_excel.png b/public/icons/page_white_excel.png new file mode 100644 index 0000000..b977d7e Binary files /dev/null and b/public/icons/page_white_excel.png differ diff --git a/public/icons/page_white_find.png b/public/icons/page_white_find.png new file mode 100644 index 0000000..5818436 Binary files /dev/null and b/public/icons/page_white_find.png differ diff --git a/public/icons/page_white_flash.png b/public/icons/page_white_flash.png new file mode 100644 index 0000000..5769120 Binary files /dev/null and b/public/icons/page_white_flash.png differ diff --git a/public/icons/page_white_freehand.png b/public/icons/page_white_freehand.png new file mode 100644 index 0000000..8d719df Binary files /dev/null and b/public/icons/page_white_freehand.png differ diff --git a/public/icons/page_white_gear.png b/public/icons/page_white_gear.png new file mode 100644 index 0000000..106f5aa Binary files /dev/null and b/public/icons/page_white_gear.png differ diff --git a/public/icons/page_white_get.png b/public/icons/page_white_get.png new file mode 100644 index 0000000..e4a1ecb Binary files /dev/null and b/public/icons/page_white_get.png differ diff --git a/public/icons/page_white_go.png b/public/icons/page_white_go.png new file mode 100644 index 0000000..7e62a92 Binary files /dev/null and b/public/icons/page_white_go.png differ diff --git a/public/icons/page_white_h.png b/public/icons/page_white_h.png new file mode 100644 index 0000000..e902abb Binary files /dev/null and b/public/icons/page_white_h.png differ diff --git a/public/icons/page_white_horizontal.png b/public/icons/page_white_horizontal.png new file mode 100644 index 0000000..1d2d0a4 Binary files /dev/null and b/public/icons/page_white_horizontal.png differ diff --git a/public/icons/page_white_key.png b/public/icons/page_white_key.png new file mode 100644 index 0000000..d616484 Binary files /dev/null and b/public/icons/page_white_key.png differ diff --git a/public/icons/page_white_lightning.png b/public/icons/page_white_lightning.png new file mode 100644 index 0000000..7215d1e Binary files /dev/null and b/public/icons/page_white_lightning.png differ diff --git a/public/icons/page_white_link.png b/public/icons/page_white_link.png new file mode 100644 index 0000000..bf7bd1c Binary files /dev/null and b/public/icons/page_white_link.png differ diff --git a/public/icons/page_white_magnify.png b/public/icons/page_white_magnify.png new file mode 100644 index 0000000..f6b74cc Binary files /dev/null and b/public/icons/page_white_magnify.png differ diff --git a/public/icons/page_white_medal.png b/public/icons/page_white_medal.png new file mode 100644 index 0000000..d3fffb6 Binary files /dev/null and b/public/icons/page_white_medal.png differ diff --git a/public/icons/page_white_office.png b/public/icons/page_white_office.png new file mode 100644 index 0000000..a65bcb3 Binary files /dev/null and b/public/icons/page_white_office.png differ diff --git a/public/icons/page_white_paint.png b/public/icons/page_white_paint.png new file mode 100644 index 0000000..23a37b8 Binary files /dev/null and b/public/icons/page_white_paint.png differ diff --git a/public/icons/page_white_paintbrush.png b/public/icons/page_white_paintbrush.png new file mode 100644 index 0000000..f907e44 Binary files /dev/null and b/public/icons/page_white_paintbrush.png differ diff --git a/public/icons/page_white_paste.png b/public/icons/page_white_paste.png new file mode 100644 index 0000000..5b2cbb3 Binary files /dev/null and b/public/icons/page_white_paste.png differ diff --git a/public/icons/page_white_php.png b/public/icons/page_white_php.png new file mode 100644 index 0000000..7868a25 Binary files /dev/null and b/public/icons/page_white_php.png differ diff --git a/public/icons/page_white_picture.png b/public/icons/page_white_picture.png new file mode 100644 index 0000000..134b669 Binary files /dev/null and b/public/icons/page_white_picture.png differ diff --git a/public/icons/page_white_powerpoint.png b/public/icons/page_white_powerpoint.png new file mode 100644 index 0000000..c4eff03 Binary files /dev/null and b/public/icons/page_white_powerpoint.png differ diff --git a/public/icons/page_white_put.png b/public/icons/page_white_put.png new file mode 100644 index 0000000..884ffd6 Binary files /dev/null and b/public/icons/page_white_put.png differ diff --git a/public/icons/page_white_ruby.png b/public/icons/page_white_ruby.png new file mode 100644 index 0000000..f59b7c4 Binary files /dev/null and b/public/icons/page_white_ruby.png differ diff --git a/public/icons/page_white_stack.png b/public/icons/page_white_stack.png new file mode 100644 index 0000000..44084ad Binary files /dev/null and b/public/icons/page_white_stack.png differ diff --git a/public/icons/page_white_star.png b/public/icons/page_white_star.png new file mode 100644 index 0000000..3a1441c Binary files /dev/null and b/public/icons/page_white_star.png differ diff --git a/public/icons/page_white_swoosh.png b/public/icons/page_white_swoosh.png new file mode 100644 index 0000000..e770829 Binary files /dev/null and b/public/icons/page_white_swoosh.png differ diff --git a/public/icons/page_white_text.png b/public/icons/page_white_text.png new file mode 100644 index 0000000..813f712 Binary files /dev/null and b/public/icons/page_white_text.png differ diff --git a/public/icons/page_white_text_width.png b/public/icons/page_white_text_width.png new file mode 100644 index 0000000..d9cf132 Binary files /dev/null and b/public/icons/page_white_text_width.png differ diff --git a/public/icons/page_white_tux.png b/public/icons/page_white_tux.png new file mode 100644 index 0000000..52699bf Binary files /dev/null and b/public/icons/page_white_tux.png differ diff --git a/public/icons/page_white_vector.png b/public/icons/page_white_vector.png new file mode 100644 index 0000000..4a05955 Binary files /dev/null and b/public/icons/page_white_vector.png differ diff --git a/public/icons/page_white_visualstudio.png b/public/icons/page_white_visualstudio.png new file mode 100644 index 0000000..a0a433d Binary files /dev/null and b/public/icons/page_white_visualstudio.png differ diff --git a/public/icons/page_white_width.png b/public/icons/page_white_width.png new file mode 100644 index 0000000..1eb8809 Binary files /dev/null and b/public/icons/page_white_width.png differ diff --git a/public/icons/page_white_word.png b/public/icons/page_white_word.png new file mode 100644 index 0000000..ae8ecbf Binary files /dev/null and b/public/icons/page_white_word.png differ diff --git a/public/icons/page_white_world.png b/public/icons/page_white_world.png new file mode 100644 index 0000000..6ed2490 Binary files /dev/null and b/public/icons/page_white_world.png differ diff --git a/public/icons/page_white_wrench.png b/public/icons/page_white_wrench.png new file mode 100644 index 0000000..fecadd0 Binary files /dev/null and b/public/icons/page_white_wrench.png differ diff --git a/public/icons/page_white_zip.png b/public/icons/page_white_zip.png new file mode 100644 index 0000000..fd4bbcc Binary files /dev/null and b/public/icons/page_white_zip.png differ diff --git a/public/icons/page_word.png b/public/icons/page_word.png new file mode 100644 index 0000000..834cdfa Binary files /dev/null and b/public/icons/page_word.png differ diff --git a/public/icons/page_world.png b/public/icons/page_world.png new file mode 100644 index 0000000..b8895dd Binary files /dev/null and b/public/icons/page_world.png differ diff --git a/public/style.css b/public/style.css new file mode 100644 index 0000000..0709908 --- /dev/null +++ b/public/style.css @@ -0,0 +1,257 @@ +* { + margin: 0; + padding: 0; + outline: 0; +} + +body { + padding: 80px 100px; + font: 13px "Helvetica Neue", "Lucida Grande", "Arial"; + background: #ECE9E9 -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ECE9E9)); + background: #ECE9E9 -moz-linear-gradient(top, #fff, #ECE9E9); + background-repeat: no-repeat; + color: #555; + -webkit-font-smoothing: antialiased; +} +h1, h2, h3 { + font-size: 22px; + color: #343434; +} +h1 em, h2 em { + padding: 0 5px; + font-weight: normal; +} +h1 { + font-size: 60px; +} +h2 { + margin-top: 10px; +} +h3 { + margin: 5px 0 10px 0; + padding-bottom: 5px; + border-bottom: 1px solid #eee; + font-size: 18px; +} +ul li { + list-style: none; +} +ul li:hover { + cursor: pointer; + color: #2e2e2e; +} +ul li .path { + padding-left: 5px; + font-weight: bold; +} +ul li .line { + padding-right: 5px; + font-style: italic; +} +ul li:first-child .path { + padding-left: 0; +} +p { + line-height: 1.5; +} +a { + color: #555; + text-decoration: none; +} +a:hover { + color: #303030; +} +#stacktrace { + margin-top: 15px; +} +.directory h1 { + margin-bottom: 15px; + font-size: 18px; +} +ul#files { + width: 100%; + height: 100%; + overflow: hidden; +} +ul#files li { + float: left; + width: 30%; + line-height: 25px; + margin: 1px; +} +ul#files li a { + display: block; + height: 25px; + border: 1px solid transparent; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + overflow: hidden; + white-space: nowrap; +} +ul#files li a:focus, +ul#files li a:hover { + background: rgba(255,255,255,0.65); + border: 1px solid #ececec; +} +ul#files li a.highlight { + -webkit-transition: background .4s ease-in-out; + background: #ffff4f; + border-color: #E9DC51; +} +#search { + display: block; + position: fixed; + top: 20px; + right: 20px; + width: 90px; + -webkit-transition: width ease 0.2s, opacity ease 0.4s; + -moz-transition: width ease 0.2s, opacity ease 0.4s; + -webkit-border-radius: 32px; + -moz-border-radius: 32px; + -webkit-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03); + -moz-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03); + -webkit-font-smoothing: antialiased; + text-align: left; + font: 13px "Helvetica Neue", Arial, sans-serif; + padding: 4px 10px; + border: none; + background: transparent; + margin-bottom: 0; + outline: none; + opacity: 0.7; + color: #888; +} +#search:focus { + width: 120px; + opacity: 1.0; +} + +/*views*/ +#files span { + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + text-indent: 10px; +} +#files .name { + background-repeat: no-repeat; +} +#files .icon .name { + text-indent: 28px; +} + +/*tiles*/ +.view-tiles .name { + width: 100%; + background-position: 8px 5px; +} +.view-tiles .size, +.view-tiles .date { + display: none; +} + +/*details*/ +ul#files.view-details li { + float: none; + display: block; + width: 90%; +} +ul#files.view-details li.header { + height: 25px; + background: #000; + color: #fff; + font-weight: bold; +} +.view-details .header { + border-radius: 5px; +} +.view-details .name { + width: 60%; + background-position: 8px 5px; +} +.view-details .size { + width: 10%; +} +.view-details .date { + width: 30%; +} +.view-details .size, +.view-details .date { + text-align: right; + direction: rtl; +} + +/*mobile*/ +@media (max-width: 768px) { + body { + font-size: 13px; + line-height: 16px; + padding: 0; + } + #search { + position: static; + width: 100%; + font-size: 2em; + line-height: 1.8em; + text-indent: 10px; + border: 0; + border-radius: 0; + padding: 10px 0; + margin: 0; + } + #search:focus { + width: 100%; + border: 0; + opacity: 1; + } + .directory h1 { + font-size: 2em; + line-height: 1.5em; + color: #fff; + background: #000; + padding: 15px 10px; + margin: 0; + } + ul#files { + border-top: 1px solid #cacaca; + } + ul#files li { + float: none; + width: auto !important; + display: block; + border-bottom: 1px solid #cacaca; + font-size: 2em; + line-height: 1.2em; + text-indent: 0; + margin: 0; + } + ul#files li:nth-child(odd) { + background: #e0e0e0; + } + ul#files li a { + height: auto; + border: 0; + border-radius: 0; + padding: 15px 10px; + } + ul#files li a:focus, + ul#files li a:hover { + border: 0; + } + #files .header, + #files .size, + #files .date { + display: none !important; + } + #files .name { + float: none; + display: inline-block; + width: 100%; + text-indent: 0; + background-position: 0 0; + } + #files .icon .name { + text-indent: 41px; + } +} diff --git a/test/fixtures/#directory/index.html b/test/fixtures/#directory/index.html new file mode 100644 index 0000000..00a2db4 --- /dev/null +++ b/test/fixtures/#directory/index.html @@ -0,0 +1 @@ +

tobi, loki, jane

\ No newline at end of file diff --git a/test/fixtures/.hidden b/test/fixtures/.hidden new file mode 100644 index 0000000..b885243 --- /dev/null +++ b/test/fixtures/.hidden @@ -0,0 +1 @@ +I am hidden \ No newline at end of file diff --git a/test/fixtures/file #1.txt b/test/fixtures/file #1.txt new file mode 100644 index 0000000..72c0718 --- /dev/null +++ b/test/fixtures/file #1.txt @@ -0,0 +1 @@ +#1 file! \ No newline at end of file diff --git a/test/fixtures/foo bar b/test/fixtures/foo bar new file mode 100644 index 0000000..3f95386 --- /dev/null +++ b/test/fixtures/foo bar @@ -0,0 +1 @@ +baz \ No newline at end of file diff --git a/test/fixtures/g# %3 o %2525 %37 dir/empty.txt b/test/fixtures/g# %3 o %2525 %37 dir/empty.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/nums b/test/fixtures/nums new file mode 100644 index 0000000..e2e107a --- /dev/null +++ b/test/fixtures/nums @@ -0,0 +1 @@ +123456789 \ No newline at end of file diff --git a/test/fixtures/todo.txt b/test/fixtures/todo.txt new file mode 100644 index 0000000..8c3539d --- /dev/null +++ b/test/fixtures/todo.txt @@ -0,0 +1 @@ +- groceries \ No newline at end of file diff --git a/test/fixtures/users/index.html b/test/fixtures/users/index.html new file mode 100644 index 0000000..00a2db4 --- /dev/null +++ b/test/fixtures/users/index.html @@ -0,0 +1 @@ +

tobi, loki, jane

\ No newline at end of file diff --git a/test/fixtures/users/tobi.txt b/test/fixtures/users/tobi.txt new file mode 100644 index 0000000..9d9529d --- /dev/null +++ b/test/fixtures/users/tobi.txt @@ -0,0 +1 @@ +ferret \ No newline at end of file diff --git a/test/shared/index.js b/test/shared/index.js new file mode 100644 index 0000000..3958366 --- /dev/null +++ b/test/shared/index.js @@ -0,0 +1,26 @@ + +var bytes = require('bytes'); + +exports['default request body'] = function(app){ + it('should default to {}', function(done){ + app.request() + .post('/') + .end(function(res){ + res.body.should.equal('{}'); + done(); + }) + }) +}; + +exports['limit body to'] = function(size, type, app){ + it('should accept a limit option', function(done){ + app.request() + .post('/') + .set('Content-Length', bytes(size) + 1) + .set('Content-Type', type) + .end(function(res){ + res.should.have.status(413); + done(); + }) + }) +} \ No newline at end of file diff --git a/test/shared/template.html b/test/shared/template.html new file mode 100644 index 0000000..86ddf0c --- /dev/null +++ b/test/shared/template.html @@ -0,0 +1,14 @@ + + + + listing directory {directory} + + + +

This is the test template

+
+

{linked-path}

+ {files} +
+ + diff --git a/test/test.js b/test/test.js new file mode 100644 index 0000000..81fbbc6 --- /dev/null +++ b/test/test.js @@ -0,0 +1,228 @@ + +process.env.NODE_ENV = 'test'; + +var connect = require('connect'); +var request = require('supertest'); +var serveIndex = require('..'); + +describe('directory()', function(){ + describe('when given Accept: header', function () { + var server; + before(function () { + server = createServer(); + }); + after(function (done) { + server.close(done); + }); + + describe('of application/json', function () { + it('should respond with json', function (done) { + request(server) + .get('/') + .set('Accept', 'application/json') + .expect(200) + .expect('Content-Type', /json/) + .end(function (err, res) { + if (err) throw err; + res.body.should.include('g# %3 o %2525 %37 dir'); + res.body.should.include('users'); + res.body.should.include('file #1.txt'); + res.body.should.include('nums'); + res.body.should.include('todo.txt'); + done(); + }); + }); + }); + + describe('when Accept: text/html is given', function () { + it('should respond with html', function (done) { + request(server) + .get('/') + .set('Accept', 'text/html') + .expect(200) + .expect('Content-Type', /html/) + .expect(/