Skip to content

Instantly share code, notes, and snippets.

@Teino1978-Corp
Created November 3, 2015 23:36
Show Gist options
  • Save Teino1978-Corp/4387efcf37ed81ea10e6 to your computer and use it in GitHub Desktop.
Save Teino1978-Corp/4387efcf37ed81ea10e6 to your computer and use it in GitHub Desktop.
test
This gist exceeds the recommended number of files (~10). To access all files, please clone this gist.
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<file url="file://$PROJECT_DIR$" libraries="{nodejs_event node_modules}" />
<file url="PROJECT" libraries="{Node.js v0.10.26 Core Modules}" />
<includedPredefinedLibrary name="Node.js Globals" />
</component>
</project>
<component name="libraryTable">
<library name="nodejs_event node_modules" type="javaScript">
<properties>
<option name="frameworkName" value="node_modules" />
<sourceFilesUrls>
<item url="file://$PROJECT_DIR$/node_modules" />
</sourceFilesUrls>
</properties>
<CLASSES>
<root url="file://$PROJECT_DIR$/node_modules" />
</CLASSES>
<SOURCES />
</library>
</component>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" />
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/nodejs_event.iml" filepath="$PROJECT_DIR$/.idea/nodejs_event.iml" />
</modules>
</component>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Node.js v0.10.26 Core Modules" level="application" />
<orderEntry type="library" name="nodejs_event node_modules" level="project" />
</component>
</module>
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="bin\www" type="NodeJSConfigurationType" factoryName="Node.js" path-to-node="C:/Program Files/nodejs/node" path-to-js-file="bin/www" working-dir="$PROJECT_DIR$">
<envs>
<env name="DEBUG" value="nodejs_event" />
</envs>
<browser url="http://localhost:3000/" />
<method />
</configuration>
</component>
<component name="DependencyValidationManager">
<state>
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</state>
</component>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
</component>
</project>
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
/// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
/// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
#!/usr/bin/env node
var debug = require('debug')('nodejs_event');
var app = require('../app');
app.set('port', process.env.PORT || 3000);
var server = app.listen(app.get('port'), function () {
debug('Express server listening on port ' + server.address().port);
});
#!/bin/sh
basedir=`dirname "$0"`
case `uname` in
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac
if [ -x "$basedir/node" ]; then
"$basedir/node" "$basedir/../jade/bin/jade.js" "$@"
ret=$?
else
node "$basedir/../jade/bin/jade.js" "$@"
ret=$?
fi
exit $ret
@IF EXIST "%~dp0\node.exe" (
"%~dp0\node.exe" "%~dp0\..\jade\bin\jade.js" %*
) ELSE (
node "%~dp0\..\jade\bin\jade.js" %*
)

1.0.1 / 2014-04-14

  • use type-is module

1.0.1 / 2014-03-20

  • lower default limits to 100kb
var getBody = require('raw-body');
var typeis = require('type-is');
var http = require('http');
var qs = require('qs');
exports = module.exports = bodyParser;
exports.json = json;
exports.urlencoded = urlencoded;
function bodyParser(options) {
var _urlencoded = urlencoded(options);
var _json = json(options);
return function bodyParser(req, res, next) {
_json(req, res, function (err) {
if (err) return next(err);
_urlencoded(req, res, next);
});
}
}
function json(options) {
options = options || {};
var strict = options.strict !== false;
return function jsonParser(req, res, next) {
if (req._body) return next();
req.body = req.body || {};
if (!typeis(req, 'json')) return next();
// flag as parsed
req._body = true;
// parse
getBody(req, {
limit: options.limit || '100kb',
length: req.headers['content-length'],
encoding: 'utf8'
}, function (err, buf) {
if (err) return next(err);
var first = buf.trim()[0];
if (0 == buf.length) {
return next(error(400, 'invalid json, empty body'));
}
if (strict && '{' != first && '[' != first) return next(error(400, 'invalid json'));
try {
req.body = JSON.parse(buf, options.reviver);
} catch (err) {
err.body = buf;
err.status = 400;
return next(err);
}
next();
})
};
}
function urlencoded(options) {
options = options || {};
return function urlencodedParser(req, res, next) {
if (req._body) return next();
req.body = req.body || {};
if (!typeis(req, 'urlencoded')) return next();
// flag as parsed
req._body = true;
// parse
getBody(req, {
limit: options.limit || '100kb',
length: req.headers['content-length'],
encoding: 'utf8'
}, function (err, buf) {
if (err) return next(err);
try {
req.body = buf.length
? qs.parse(buf)
: {};
} catch (err) {
err.body = buf;
return next(err);
}
next();
})
}
}
function error(code, msg) {
var err = new Error(msg || http.STATUS_CODES[code]);
err.status = code;
return err;
}
BIN = ./node_modules/.bin/
test:
@$(BIN)mocha \
--require should \
--reporter spec \
--bail
.PHONY: test
[submodule "support/expresso"]
path = support/expresso
url = git://github.com/visionmedia/expresso.git
[submodule "support/should"]
path = support/should
url = git://github.com/visionmedia/should.js.git
test
.travis.yml
benchmark.js
component.json
examples.js
History.md
Makefile
/**
* Object#toString() ref for stringify().
*/
var toString = Object.prototype.toString;
/**
* Object#hasOwnProperty ref
*/
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* Array#indexOf shim.
*/
var indexOf = typeof Array.prototype.indexOf === 'function'
? function (arr, el) {
return arr.indexOf(el);
}
: function (arr, el) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] === el) return i;
}
return -1;
};
/**
* Array.isArray shim.
*/
var isArray = Array.isArray || function (arr) {
return toString.call(arr) == '[object Array]';
};
/**
* Object.keys shim.
*/
var objectKeys = Object.keys || function (obj) {
var ret = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
ret.push(key);
}
}
return ret;
};
/**
* Array#forEach shim.
*/
var forEach = typeof Array.prototype.forEach === 'function'
? function (arr, fn) {
return arr.forEach(fn);
}
: function (arr, fn) {
for (var i = 0; i < arr.length; i++) fn(arr[i]);
};
/**
* Array#reduce shim.
*/
var reduce = function (arr, fn, initial) {
if (typeof arr.reduce === 'function') return arr.reduce(fn, initial);
var res = initial;
for (var i = 0; i < arr.length; i++) res = fn(res, arr[i]);
return res;
};
/**
* Cache non-integer test regexp.
*/
var isint = /^[0-9]+$/;
function promote(parent, key) {
if (parent[key].length == 0) return parent[key] = {}
var t = {};
for (var i in parent[key]) {
if (hasOwnProperty.call(parent[key], i)) {
t[i] = parent[key][i];
}
}
parent[key] = t;
return t;
}
function parse(parts, parent, key, val) {
var part = parts.shift();
// illegal
if (Object.getOwnPropertyDescriptor(Object.prototype, key)) return;
// end
if (!part) {
if (isArray(parent[key])) {
parent[key].push(val);
} else if ('object' == typeof parent[key]) {
parent[key] = val;
} else if ('undefined' == typeof parent[key]) {
parent[key] = val;
} else {
parent[key] = [parent[key], val];
}
// array
} else {
var obj = parent[key] = parent[key] || [];
if (']' == part) {
if (isArray(obj)) {
if ('' != val) obj.push(val);
} else if ('object' == typeof obj) {
obj[objectKeys(obj).length] = val;
} else {
obj = parent[key] = [parent[key], val];
}
// prop
} else if (~indexOf(part, ']')) {
part = part.substr(0, part.length - 1);
if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
parse(parts, obj, part, val);
// key
} else {
if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
parse(parts, obj, part, val);
}
}
}
/**
* Merge parent key/val pair.
*/
function merge(parent, key, val) {
if (~indexOf(key, ']')) {
var parts = key.split('[')
, len = parts.length
, last = len - 1;
parse(parts, parent, 'base', val);
// optimize
} else {
if (!isint.test(key) && isArray(parent.base)) {
var t = {};
for (var k in parent.base) t[k] = parent.base[k];
parent.base = t;
}
set(parent.base, key, val);
}
return parent;
}
/**
* Compact sparse arrays.
*/
function compact(obj) {
if ('object' != typeof obj) return obj;
if (isArray(obj)) {
var ret = [];
for (var i in obj) {
if (hasOwnProperty.call(obj, i)) {
ret.push(obj[i]);
}
}
return ret;
}
for (var key in obj) {
obj[key] = compact(obj[key]);
}
return obj;
}
/**
* Parse the given obj.
*/
function parseObject(obj) {
var ret = { base: {} };
forEach(objectKeys(obj), function (name) {
merge(ret, name, obj[name]);
});
return compact(ret.base);
}
/**
* Parse the given str.
*/
function parseString(str) {
var ret = reduce(String(str).split('&'), function (ret, pair) {
var eql = indexOf(pair, '=')
, brace = lastBraceInKey(pair)
, key = pair.substr(0, brace || eql)
, val = pair.substr(brace || eql, pair.length)
, val = val.substr(indexOf(val, '=') + 1, val.length);
// ?foo
if ('' == key) key = pair, val = '';
if ('' == key) return ret;
return merge(ret, decode(key), decode(val));
}, { base: {} }).base;
return compact(ret);
}
/**
* Parse the given query `str` or `obj`, returning an object.
*
* @param {String} str | {Object} obj
* @return {Object}
* @api public
*/
exports.parse = function (str) {
if (null == str || '' == str) return {};
return 'object' == typeof str
? parseObject(str)
: parseString(str);
};
/**
* Turn the given `obj` into a query string
*
* @param {Object} obj
* @return {String}
* @api public
*/
var stringify = exports.stringify = function (obj, prefix) {
if (isArray(obj)) {
return stringifyArray(obj, prefix);
} else if ('[object Object]' == toString.call(obj)) {
return stringifyObject(obj, prefix);
} else if ('string' == typeof obj) {
return stringifyString(obj, prefix);
} else {
return prefix + '=' + encodeURIComponent(String(obj));
}
};
/**
* Stringify the given `str`.
*
* @param {String} str
* @param {String} prefix
* @return {String}
* @api private
*/
function stringifyString(str, prefix) {
if (!prefix) throw new TypeError('stringify expects an object');
return prefix + '=' + encodeURIComponent(str);
}
/**
* Stringify the given `arr`.
*
* @param {Array} arr
* @param {String} prefix
* @return {String}
* @api private
*/
function stringifyArray(arr, prefix) {
var ret = [];
if (!prefix) throw new TypeError('stringify expects an object');
for (var i = 0; i < arr.length; i++) {
ret.push(stringify(arr[i], prefix + '[' + i + ']'));
}
return ret.join('&');
}
/**
* Stringify the given `obj`.
*
* @param {Object} obj
* @param {String} prefix
* @return {String}
* @api private
*/
function stringifyObject(obj, prefix) {
var ret = []
, keys = objectKeys(obj)
, key;
for (var i = 0, len = keys.length; i < len; ++i) {
key = keys[i];
if ('' == key) continue;
if (null == obj[key]) {
ret.push(encodeURIComponent(key) + '=');
} else {
ret.push(stringify(obj[key], prefix
? prefix + '[' + encodeURIComponent(key) + ']'
: encodeURIComponent(key)));
}
}
return ret.join('&');
}
/**
* Set `obj`'s `key` to `val` respecting
* the weird and wonderful syntax of a qs,
* where "foo=bar&foo=baz" becomes an array.
*
* @param {Object} obj
* @param {String} key
* @param {String} val
* @api private
*/
function set(obj, key, val) {
var v = obj[key];
if (Object.getOwnPropertyDescriptor(Object.prototype, key)) return;
if (undefined === v) {
obj[key] = val;
} else if (isArray(v)) {
v.push(val);
} else {
obj[key] = [v, val];
}
}
/**
* Locate last brace in `str` within the key.
*
* @param {String} str
* @return {Number}
* @api private
*/
function lastBraceInKey(str) {
var len = str.length
, brace
, c;
for (var i = 0; i < len; ++i) {
c = str[i];
if (']' == c) brace = false;
if ('[' == c) brace = true;
if ('=' == c && !brace) return i;
}
}
/**
* Decode `str`.
*
* @param {String} str
* @return {String}
* @api private
*/
function decode(str) {
try {
return decodeURIComponent(str.replace(/\+/g, ' '));
} catch (err) {
return str;
}
}
{
"name": "qs",
"description": "querystring parser",
"version": "0.6.6",
"keywords": [
"query string",
"parser",
"component"
],
"repository": {
"type": "git",
"url": "git://github.com/visionmedia/node-querystring.git"
},
"devDependencies": {
"mocha": "*",
"expect.js": "*"
},
"scripts": {
"test": "make test"
},
"author": {
"name": "TJ Holowaychuk",
"email": "[email protected]",
"url": "http://tjholowaychuk.com"
},
"main": "index",
"engines": {
"node": "*"
},
"readme": "# node-querystring\n\n query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.\n\n## Installation\n\n $ npm install qs\n\n## Examples\n\n```js\nvar qs = require('qs');\n\nqs.parse('user[name][first]=Tobi&user[email][email protected]');\n// => { user: { name: { first: 'Tobi' }, email: '[email protected]' } }\n\nqs.stringify({ user: { name: 'Tobi', email: '[email protected]' }})\n// => user[name]=Tobi&user[email]=tobi%40learnboost.com\n```\n\n## Testing\n\nInstall dev dependencies:\n\n $ npm install -d\n\nand execute:\n\n $ make test\n\nbrowser:\n\n $ open test/browser/index.html\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2010 TJ Holowaychuk &lt;[email protected]&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
"readmeFilename": "Readme.md",
"bugs": {
"url": "https://github.com/visionmedia/node-querystring/issues"
},
"homepage": "https://github.com/visionmedia/node-querystring",
"_id": "[email protected]",
"dist": {
"shasum": "971541a143106eea48b882de809e3d433d1c52b1"
},
"_from": "qs@~0.6.6",
"_resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz"
}

node-querystring

query string parser for node and the browser supporting nesting, as it was removed from 0.3.x, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by express, connect and others.

Installation

$ npm install qs

Examples

var qs = require('qs');

qs.parse('user[name][first]=Tobi&user[email][email protected]');
// => { user: { name: { first: 'Tobi' }, email: '[email protected]' } }

qs.stringify({ user: { name: 'Tobi', email: '[email protected]' }})
// => user[name]=Tobi&user[email]=tobi%40learnboost.com

Testing

Install dev dependencies:

$ npm install -d

and execute:

$ make test

browser:

$ open test/browser/index.html

License

(The MIT License)

Copyright (c) 2010 TJ Holowaychuk <[email protected]>

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.

var StringDecoder = require('string_decoder').StringDecoder
var bytes = require('bytes')
module.exports = function (stream, options, done) {
if (typeof options === 'function') {
done = options
options = {}
} else if (!options) {
options = {}
} else if (options === true) {
options = {
encoding: 'utf8'
}
}
// convert the limit to an integer
var limit = null
if (typeof options.limit === 'number')
limit = options.limit
if (typeof options.limit === 'string')
limit = bytes(options.limit)
// convert the expected length to an integer
var length = null
if (options.length != null && !isNaN(options.length))
length = parseInt(options.length, 10)
// check the length and limit options.
// note: we intentionally leave the stream paused,
// so users should handle the stream themselves.
if (limit !== null && length !== null && length > limit) {
if (typeof stream.pause === 'function')
stream.pause()
process.nextTick(function () {
var err = makeError('request entity too large', 'entity.too.large')
err.status = err.statusCode = 413
err.length = err.expected = length
err.limit = limit
done(err)
})
return defer
}
// streams1: assert request encoding is buffer.
// streams2+: assert the stream encoding is buffer.
// stream._decoder: streams1
// state.encoding: streams2
// state.decoder: streams2, specifically < 0.10.6
var state = stream._readableState
if (stream._decoder || (state && (state.encoding || state.decoder))) {
if (typeof stream.pause === 'function')
stream.pause()
process.nextTick(function () {
var err = makeError('stream encoding should not be set',
'stream.encoding.set')
// developer error
err.status = err.statusCode = 500
done(err)
})
return defer
}
var received = 0
// note: we delegate any invalid encodings to the constructor
var decoder = options.encoding
? new StringDecoder(options.encoding === true ? 'utf8' : options.encoding)
: null
var buffer = decoder
? ''
: []
stream.on('data', onData)
stream.once('end', onEnd)
stream.once('error', onEnd)
stream.once('close', cleanup)
return defer
// yieldable support
function defer(fn) {
done = fn
}
function onData(chunk) {
received += chunk.length
decoder
? buffer += decoder.write(chunk)
: buffer.push(chunk)
if (limit !== null && received > limit) {
if (typeof stream.pause === 'function')
stream.pause()
var err = makeError('request entity too large', 'entity.too.large')
err.status = err.statusCode = 413
err.received = received
err.limit = limit
done(err)
cleanup()
}
}
function onEnd(err) {
if (err) {
if (typeof stream.pause === 'function')
stream.pause()
done(err)
} else if (length !== null && received !== length) {
err = makeError('request size did not match content length',
'request.size.invalid')
err.status = err.statusCode = 400
err.received = received
err.length = err.expected = length
done(err)
} else {
done(null, decoder
? buffer + endStringDecoder(decoder)
: Buffer.concat(buffer)
)
}
cleanup()
}
function cleanup() {
received = buffer = null
stream.removeListener('data', onData)
stream.removeListener('end', onEnd)
stream.removeListener('error', onEnd)
stream.removeListener('close', cleanup)
}
}
// to create serializable errors you must re-set message so
// that it is enumerable and you must re configure the type
// property so that is writable and enumerable
function makeError(message, type) {
var error = new Error()
error.message = message
Object.defineProperty(error, 'type', {
value: type,
enumerable: true,
writable: true,
configurable: true
})
return error
}
// https://github.com/Raynos/body/blob/2512ced39e31776e5a2f7492b907330badac3a40/index.js#L72
// bug fix for missing `StringDecoder.end` in v0.8.x
function endStringDecoder(decoder) {
if (decoder.end) {
return decoder.end()
}
var res = ""
if (decoder.charReceived) {
var cr = decoder.charReceived
var buf = decoder.charBuffer
var enc = decoder.encoding
res += buf.slice(0, cr).toString(enc)
}
return res
}
NODE ?= node
BIN = ./node_modules/.bin/
test:
@${NODE} ${BIN}mocha \
--harmony-generators \
--reporter spec \
--bail \
./test/index.js
clean:
@rm -rf node_modules
.PHONY: test clean
{
"name": "bytes",
"description": "byte size string parser / serializer",
"keywords": ["bytes", "utility"],
"version": "0.2.1",
"scripts": ["index.js"]
}

1.0.0 / 2014-05-05

  • add negative support. fixes #6

0.3.0 / 2014-03-19

  • added terabyte support

0.2.1 / 2013-04-01

  • add .component

0.2.0 / 2012-10-28

  • bytes(200).should.eql('200b')

0.1.0 / 2012-07-04

  • add bytes to string conversion [yields]
/**
* Parse byte `size` string.
*
* @param {String} size
* @return {Number}
* @api public
*/
module.exports = function (size) {
if ('number' == typeof size) return convert(size);
var parts = size.match(/^(\d+(?:\.\d+)?) *(kb|mb|gb|tb)$/)
, n = parseFloat(parts[1])
, type = parts[2];
var map = {
kb: 1 << 10, mb: 1 << 20, gb: 1 << 30, tb: ((1 << 30) * 1024)
};
return map[type] * n;
};
/**
* convert bytes into string.
*
* @param {Number} b - bytes to convert
* @return {String}
* @api public
*/
function convert(b) {
var tb = ((1 << 30) * 1024), gb = 1 << 30, mb = 1 << 20, kb = 1 << 10, abs = Math.abs(b);
if (abs >= tb) return (Math.round(b / tb * 100) / 100) + 'tb';
if (abs >= gb) return (Math.round(b / gb * 100) / 100) + 'gb';
if (abs >= mb) return (Math.round(b / mb * 100) / 100) + 'mb';
if (abs >= kb) return (Math.round(b / kb * 100) / 100) + 'kb';
return b + 'b';
}
test:
@./node_modules/.bin/mocha \
--reporter spec \
--require should
.PHONY: test
{
"name": "bytes",
"author": {
"name": "TJ Holowaychuk",
"email": "[email protected]",
"url": "http://tjholowaychuk.com"
},
"description": "byte size string parser / serializer",
"repository": {
"type": "git",
"url": "https://github.com/visionmedia/bytes.js.git"
},
"version": "1.0.0",
"main": "index.js",
"dependencies": {},
"devDependencies": {
"mocha": "*",
"should": "*"
},
"component": {
"scripts": {
"bytes/index.js": "index.js"
}
},
"readme": "# node-bytes\n\n Byte string parser / formatter.\n\n## Example:\n\n```js\nbytes('1kb')\n// => 1024\n\nbytes('2mb')\n// => 2097152\n\nbytes('1gb')\n// => 1073741824\n\nbytes(1073741824)\n// => 1gb\n\nbytes(1099511627776)\n// => 1tb\n```\n\n## Installation\n\n```\n$ npm install bytes\n$ component install visionmedia/bytes.js\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk &lt;[email protected]&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
"readmeFilename": "Readme.md",
"bugs": {
"url": "https://github.com/visionmedia/bytes.js/issues"
},
"homepage": "https://github.com/visionmedia/bytes.js",
"_id": "[email protected]",
"dist": {
"shasum": "ff1191a12ac9ef761ff1dbb639fa168f3aefd21b"
},
"_from": "bytes@1",
"_resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz"
}

node-bytes

Byte string parser / formatter.

Example:

bytes('1kb')
// => 1024

bytes('2mb')
// => 2097152

bytes('1gb')
// => 1073741824

bytes(1073741824)
// => 1gb

bytes(1099511627776)
// => 1tb

Installation

$ npm install bytes
$ component install visionmedia/bytes.js

License

(The MIT License)

Copyright (c) 2012 TJ Holowaychuk <[email protected]>

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.

{
"name": "raw-body",
"description": "Get and validate the raw body of a readable stream.",
"version": "1.1.6",
"author": {
"name": "Jonathan Ong",
"email": "[email protected]",
"url": "http://jongleberry.com"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/stream-utils/raw-body.git"
},
"bugs": {
"url": "https://github.com/stream-utils/raw-body/issues"
},
"dependencies": {
"bytes": "1"
},
"devDependencies": {
"readable-stream": "~1.0.17",
"co": "3",
"gnode": "~0.0.4",
"mocha": "^1.14.0",
"through2": "~0.4.1",
"request": "^2.27.0",
"assert-tap": "~0.1.4"
},
"scripts": {
"test": "NODE=gnode make test && node ./test/acceptance.js"
},
"engines": {
"node": ">= 0.8.0"
},
"readme": "# Raw Body [![Build Status](https://travis-ci.org/stream-utils/raw-body.svg?branch=master)](https://travis-ci.org/stream-utils/raw-body)\n\nGets the entire buffer of a stream either as a `Buffer` or a string.\nValidates the stream's length against an expected length and maximum limit.\nIdeal for parsing request bodies.\n\n## API\n\n```js\nvar getRawBody = require('raw-body')\n\napp.use(function (req, res, next) {\n getRawBody(req, {\n length: req.headers['content-length'],\n limit: '1mb',\n encoding: 'utf8'\n }, function (err, string) {\n if (err)\n return next(err)\n\n req.text = string\n next()\n })\n})\n```\n\nor in a Koa generator:\n\n```js\napp.use(function* (next) {\n var string = yield getRawBody(this.req, {\n length: this.length,\n limit: '1mb',\n encoding: 'utf8'\n })\n})\n```\n\n### getRawBody(stream, [options], [callback])\n\nReturns a thunk for yielding with generators.\n\nOptions:\n\n- `length` - The length length of the stream.\n If the contents of the stream do not add up to this length,\n an `400` error code is returned.\n- `limit` - The byte limit of the body.\n If the body ends up being larger than this limit,\n a `413` error code is returned.\n- `encoding` - The requested encoding.\n By default, a `Buffer` instance will be returned.\n Most likely, you want `utf8`.\n You can use any type of encoding supported by [StringDecoder](http://nodejs.org/api/string_decoder.html).\n You can also pass `true` which sets it to the default `utf8`\n\n`callback(err, res)`:\n\n- `err` - the following attributes will be defined if applicable:\n\n - `limit` - the limit in bytes\n - `length` and `expected` - the expected length of the stream\n - `received` - the received bytes\n - `status` and `statusCode` - the corresponding status code for the error\n - `type` - either `entity.too.large`, `request.size.invalid`, or `stream.encoding.set`\n\n- `res` - the result, either as a `String` if an encoding was set or a `Buffer` otherwise.\n\nIf an error occurs, the stream will be paused,\nand you are responsible for correctly disposing the stream.\nFor HTTP requests, no handling is required if you send a response.\nFor streams that use file descriptors, you should `stream.destroy()` or `stream.close()` to prevent leaks.\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 Jonathan Ong [email protected]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n",
"readmeFilename": "README.md",
"homepage": "https://github.com/stream-utils/raw-body",
"_id": "[email protected]",
"dist": {
"shasum": "088ff85b697d3edcf6355deeb7a3702148a7d74b"
},
"_from": "raw-body@~1.1.2",
"_resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.6.tgz"
}

Raw Body Build Status

Gets the entire buffer of a stream either as a Buffer or a string. Validates the stream's length against an expected length and maximum limit. Ideal for parsing request bodies.

API

var getRawBody = require('raw-body')

app.use(function (req, res, next) {
  getRawBody(req, {
    length: req.headers['content-length'],
    limit: '1mb',
    encoding: 'utf8'
  }, function (err, string) {
    if (err)
      return next(err)

    req.text = string
    next()
  })
})

or in a Koa generator:

app.use(function* (next) {
  var string = yield getRawBody(this.req, {
    length: this.length,
    limit: '1mb',
    encoding: 'utf8'
  })
})

getRawBody(stream, [options], [callback])

Returns a thunk for yielding with generators.

Options:

  • length - The length length of the stream. If the contents of the stream do not add up to this length, an 400 error code is returned.
  • limit - The byte limit of the body. If the body ends up being larger than this limit, a 413 error code is returned.
  • encoding - The requested encoding. By default, a Buffer instance will be returned. Most likely, you want utf8. You can use any type of encoding supported by StringDecoder. You can also pass true which sets it to the default utf8

callback(err, res):

  • err - the following attributes will be defined if applicable:

    • limit - the limit in bytes
    • length and expected - the expected length of the stream
    • received - the received bytes
    • status and statusCode - the corresponding status code for the error
    • type - either entity.too.large, request.size.invalid, or stream.encoding.set
  • res - the result, either as a String if an encoding was set or a Buffer otherwise.

If an error occurs, the stream will be paused, and you are responsible for correctly disposing the stream. For HTTP requests, no handling is required if you send a response. For streams that use file descriptors, you should stream.destroy() or stream.close() to prevent leaks.

License

The MIT License (MIT)

Copyright (c) 2013 Jonathan Ong [email protected]

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.

1.1.0 / 2014-04-12

  • add non-array values support

  • expose internal utilities:

    • .is()
    • .hasBody()
    • .normalize()
    • .match()

1.0.1 / 2014-03-30

  • add multipart as a shorthand
var mime = require('mime');
var slice = [].slice;
module.exports = typeofrequest;
typeofrequest.is = typeis;
typeofrequest.hasBody = hasbody;
typeofrequest.normalize = normalize;
typeofrequest.match = mimeMatch;
/**
* Compare a `value` content-type with `types`.
* Each `type` can be an extension like `html`,
* a special shortcut like `multipart` or `urlencoded`,
* or a mime type.
*
* If no types match, `false` is returned.
* Otherwise, the first `type` that matches is returned.
*
* @param {String} value
* @param {Array} types
* @return String
*/
function typeis(value, types) {
if (!value) return false;
if (types && !Array.isArray(types)) types = slice.call(arguments, 1);
// remove stuff like charsets
var index = value.indexOf(';')
value = ~index ? value.slice(0, index) : value
// no types, return the content type
if (!types || !types.length) return value;
var type;
for (var i = 0; i < types.length; i++)
if (mimeMatch(normalize(type = types[i]), value))
return ~type.indexOf('*') ? value : type;
// no matches
return false;
}
/**
* Check if a request has a request body.
* A request with a body __must__ either have `transfer-encoding`
* or `content-length` headers set.
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
*
* @param {Object} request
* @return {Boolean}
* @api public
*/
function hasbody(req) {
var headers = req.headers;
if ('transfer-encoding' in headers) return true;
var length = headers['content-length'];
if (!length) return false;
// no idea when this would happen, but `isNaN(null) === false`
if (isNaN(length)) return false;
return !!parseInt(length, 10);
}
/**
* Check if the incoming request contains the "Content-Type"
* header field, and it contains any of the give mime `type`s.
* If there is no request body, `null` is returned.
* If there is no content type, `false` is returned.
* Otherwise, it returns the first `type` that matches.
*
* Examples:
*
* // With Content-Type: text/html; charset=utf-8
* this.is('html'); // => 'html'
* this.is('text/html'); // => 'text/html'
* this.is('text/*', 'application/json'); // => 'text/html'
*
* // When Content-Type is application/json
* this.is('json', 'urlencoded'); // => 'json'
* this.is('application/json'); // => 'application/json'
* this.is('html', 'application/*'); // => 'application/json'
*
* this.is('html'); // => false
*
* @param {String|Array} types...
* @return {String|false|null}
* @api public
*/
function typeofrequest(req, types) {
if (!hasbody(req)) return null;
if (types && !Array.isArray(types)) types = slice.call(arguments, 1);
return typeis(req.headers['content-type'], types);
}
/**
* Normalize a mime type.
* If it's a shorthand, expand it to a valid mime type.
*
* In general, you probably want:
*
* var type = is(req, ['urlencoded', 'json', 'multipart']);
*
* Then use the appropriate body parsers.
* These three are the most common request body types
* and are thus ensured to work.
*
* @param {String} type
* @api private
*/
function normalize(type) {
switch (type) {
case 'urlencoded':
return 'application/x-www-form-urlencoded';
case 'multipart':
type = 'multipart/*';
break;
}
return ~type.indexOf('/') ? type : mime.lookup(type);
}
/**
* Check if `exected` mime type
* matches `actual` mime type with
* wildcard support.
*
* @param {String} expected
* @param {String} actual
* @return {Boolean}
* @api private
*/
function mimeMatch(expected, actual) {
if (expected === actual) return true;
if (!~expected.indexOf('*')) return false;
actual = actual.split('/');
expected = expected.split('/');
if ('*' === expected[0] && expected[1] === actual[1]) return true;
if ('*' === expected[1] && expected[0] === actual[0]) return true;
return false;
}
Copyright (c) 2010 Benjamin Thomas, Robert Kieffer
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.
var path = require('path');
var fs = require('fs');
function Mime() {
// Map of extension -> mime type
this.types = Object.create(null);
// Map of mime type -> extension
this.extensions = Object.create(null);
}
/**
* Define mimetype -> extension mappings. Each key is a mime-type that maps
* to an array of extensions associated with the type. The first extension is
* used as the default extension for the type.
*
* e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']});
*
* @param map (Object) type definitions
*/
Mime.prototype.define = function (map) {
for (var type in map) {
var exts = map[type];
for (var i = 0; i < exts.length; i++) {
if (process.env.DEBUG_MIME && this.types[exts]) {
console.warn(this._loading.replace(/.*\//, ''), 'changes "' + exts[i] + '" extension type from ' +
this.types[exts] + ' to ' + type);
}
this.types[exts[i]] = type;
}
// Default extension is the first one we encounter
if (!this.extensions[type]) {
this.extensions[type] = exts[0];
}
}
};
/**
* Load an Apache2-style ".types" file
*
* This may be called multiple times (it's expected). Where files declare
* overlapping types/extensions, the last file wins.
*
* @param file (String) path of file to load.
*/
Mime.prototype.load = function (file) {
this._loading = file;
// Read file and split into lines
var map = {},
content = fs.readFileSync(file, 'ascii'),
lines = content.split(/[\r\n]+/);
lines.forEach(function (line) {
// Clean up whitespace/comments, and split into fields
var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/);
map[fields.shift()] = fields;
});
this.define(map);
this._loading = null;
};
/**
* Lookup a mime type based on extension
*/
Mime.prototype.lookup = function (path, fallback) {
var ext = path.replace(/.*[\.\/\\]/, '').toLowerCase();
return this.types[ext] || fallback || this.default_type;
};
/**
* Return file extension associated with a mime type
*/
Mime.prototype.extension = function (mimeType) {
var type = mimeType.match(/^\s*([^;\s]*)(?:;|\s|$)/)[1].toLowerCase();
return this.extensions[type];
};
// Default instance
var mime = new Mime();
// Load local copy of
// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
mime.load(path.join(__dirname, 'types/mime.types'));
// Load additional types from node.js community
mime.load(path.join(__dirname, 'types/node.types'));
// Default type
mime.default_type = mime.lookup('bin');
//
// Additional API specific to the default instance
//
mime.Mime = Mime;
/**
* Lookup a charset based on mime type.
*/
mime.charsets = {
lookup: function (mimeType, fallback) {
// Assume text types are utf8
return (/^text\//).test(mimeType) ? 'UTF-8' : fallback;
}
};
module.exports = mime;
{
"author": {
"name": "Robert Kieffer",
"email": "[email protected]",
"url": "http://github.com/broofa"
},
"contributors": [
{
"name": "Benjamin Thomas",
"email": "[email protected]",
"url": "http://github.com/bentomas"
}
],
"dependencies": {},
"description": "A comprehensive library for mime-type mapping",
"devDependencies": {},
"keywords": [
"util",
"mime"
],
"main": "mime.js",
"name": "mime",
"repository": {
"url": "https://github.com/broofa/node-mime",
"type": "git"
},
"version": "1.2.11",
"readme": "# mime\n\nComprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.\n\n## Install\n\nInstall with [npm](http://github.com/isaacs/npm):\n\n npm install mime\n\n## API - Queries\n\n### mime.lookup(path)\nGet the mime type associated with a file, if no mime type is found `application/octet-stream` is returned. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.'). E.g.\n\n var mime = require('mime');\n\n mime.lookup('/path/to/file.txt'); // => 'text/plain'\n mime.lookup('file.txt'); // => 'text/plain'\n mime.lookup('.TXT'); // => 'text/plain'\n mime.lookup('htm'); // => 'text/html'\n\n### mime.default_type\nSets the mime type returned when `mime.lookup` fails to find the extension searched for. (Default is `application/octet-stream`.)\n\n### mime.extension(type)\nGet the default extension for `type`\n\n mime.extension('text/html'); // => 'html'\n mime.extension('application/octet-stream'); // => 'bin'\n\n### mime.charsets.lookup()\n\nMap mime-type to charset\n\n mime.charsets.lookup('text/plain'); // => 'UTF-8'\n\n(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.)\n\n## API - Defining Custom Types\n\nThe following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types).\n\n### mime.define()\n\nAdd custom mime/extension mappings\n\n mime.define({\n 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],\n 'application/x-my-type': ['x-mt', 'x-mtt'],\n // etc ...\n });\n\n mime.lookup('x-sft'); // => 'text/x-some-format'\n\nThe first entry in the extensions array is returned by `mime.extension()`. E.g.\n\n mime.extension('text/x-some-format'); // => 'x-sf'\n\n### mime.load(filepath)\n\nLoad mappings from an Apache \".types\" format file\n\n mime.load('./my_project.types');\n\nThe .types file format is simple - See the `types` dir for examples.\n",
"readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/broofa/node-mime/issues"
},
"homepage": "https://github.com/broofa/node-mime",
"_id": "[email protected]",
"dist": {
"shasum": "8401d4ab4f06fcf4bc53e86d918c0443ccaa7274"
},
"_from": "mime@~1.2.11",
"_resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz"
}

mime

Comprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.

Install

Install with npm:

npm install mime

API - Queries

mime.lookup(path)

Get the mime type associated with a file, if no mime type is found application/octet-stream is returned. Performs a case-insensitive lookup using the extension in path (the substring after the last '/' or '.'). E.g.

var mime = require('mime');

mime.lookup('/path/to/file.txt');         // => 'text/plain'
mime.lookup('file.txt');                  // => 'text/plain'
mime.lookup('.TXT');                      // => 'text/plain'
mime.lookup('htm');                       // => 'text/html'

mime.default_type

Sets the mime type returned when mime.lookup fails to find the extension searched for. (Default is application/octet-stream.)

mime.extension(type)

Get the default extension for type

mime.extension('text/html');                 // => 'html'
mime.extension('application/octet-stream');  // => 'bin'

mime.charsets.lookup()

Map mime-type to charset

mime.charsets.lookup('text/plain');        // => 'UTF-8'

(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.)

API - Defining Custom Types

The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see requesting new types.

mime.define()

Add custom mime/extension mappings

mime.define({
    'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],
    'application/x-my-type': ['x-mt', 'x-mtt'],
    // etc ...
});

mime.lookup('x-sft');                 // => 'text/x-some-format'

The first entry in the extensions array is returned by mime.extension(). E.g.

mime.extension('text/x-some-format'); // => 'x-sf'

mime.load(filepath)

Load mappings from an Apache ".types" format file

mime.load('./my_project.types');

The .types file format is simple - See the types dir for examples.

/**
* Usage: node test.js
*/
var mime = require('./mime');
var assert = require('assert');
var path = require('path');
function eq(a, b) {
console.log('Test: ' + a + ' === ' + b);
assert.strictEqual.apply(null, arguments);
}
console.log(Object.keys(mime.extensions).length + ' types');
console.log(Object.keys(mime.types).length + ' extensions\n');
//
// Test mime lookups
//
eq('text/plain', mime.lookup('text.txt')); // normal file
eq('text/plain', mime.lookup('TEXT.TXT')); // uppercase
eq('text/plain', mime.lookup('dir/text.txt')); // dir + file
eq('text/plain', mime.lookup('.text.txt')); // hidden file
eq('text/plain', mime.lookup('.txt')); // nameless
eq('text/plain', mime.lookup('txt')); // extension-only
eq('text/plain', mime.lookup('/txt')); // extension-less ()
eq('text/plain', mime.lookup('\\txt')); // Windows, extension-less
eq('application/octet-stream', mime.lookup('text.nope')); // unrecognized
eq('fallback', mime.lookup('text.fallback', 'fallback')); // alternate default
//
// Test extensions
//
eq('txt', mime.extension(mime.types.text));
eq('html', mime.extension(mime.types.htm));
eq('bin', mime.extension('application/octet-stream'));
eq('bin', mime.extension('application/octet-stream '));
eq('html', mime.extension(' text/html; charset=UTF-8'));
eq('html', mime.extension('text/html; charset=UTF-8 '));
eq('html', mime.extension('text/html; charset=UTF-8'));
eq('html', mime.extension('text/html ; charset=UTF-8'));
eq('html', mime.extension('text/html;charset=UTF-8'));
eq('html', mime.extension('text/Html;charset=UTF-8'));
eq(undefined, mime.extension('unrecognized'));
//
// Test node.types lookups
//
eq('application/font-woff', mime.lookup('file.woff'));
eq('application/octet-stream', mime.lookup('file.buffer'));
eq('audio/mp4', mime.lookup('file.m4a'));
eq('font/opentype', mime.lookup('file.otf'));
//
// Test charsets
//
eq('UTF-8', mime.charsets.lookup('text/plain'));
eq(undefined, mime.charsets.lookup(mime.types.js));
eq('fallback', mime.charsets.lookup('application/octet-stream', 'fallback'));
//
// Test for overlaps between mime.types and node.types
//
var apacheTypes = new mime.Mime(), nodeTypes = new mime.Mime();
apacheTypes.load(path.join(__dirname, 'types/mime.types'));
nodeTypes.load(path.join(__dirname, 'types/node.types'));
var keys = [].concat(Object.keys(apacheTypes.types))
.concat(Object.keys(nodeTypes.types));
keys.sort();
for (var i = 1; i < keys.length; i++) {
if (keys[i] == keys[i - 1]) {
console.warn('Warning: ' +
'node.types defines ' + keys[i] + '->' + nodeTypes.types[keys[i]] +
', mime.types defines ' + keys[i] + '->' + apacheTypes.types[keys[i]]);
}
}
console.log('\nOK');
# This file maps Internet media types to unique file extension(s).
# Although created for httpd, this file is used by many software systems
# and has been placed in the public domain for unlimited redisribution.
#
# The table below contains both registered and (common) unregistered types.
# A type that has no unique extension can be ignored -- they are listed
# here to guide configurations toward known types and to make it easier to
# identify "new" types. File extensions are also commonly used to indicate
# content languages and encodings, so choose them carefully.
#
# Internet media types should be registered as described in RFC 4288.
# The registry is at <http://www.iana.org/assignments/media-types/>.
#
# MIME type (lowercased) Extensions
# ============================================ ==========
# application/1d-interleaved-parityfec
# application/3gpp-ims+xml
# application/activemessage
application/andrew-inset ez
# application/applefile
application/applixware aw
application/atom+xml atom
application/atomcat+xml atomcat
# application/atomicmail
application/atomsvc+xml atomsvc
# application/auth-policy+xml
# application/batch-smtp
# application/beep+xml
# application/calendar+xml
# application/cals-1840
# application/ccmp+xml
application/ccxml+xml ccxml
application/cdmi-capability cdmia
application/cdmi-container cdmic
application/cdmi-domain cdmid
application/cdmi-object cdmio
application/cdmi-queue cdmiq
# application/cea-2018+xml
# application/cellml+xml
# application/cfw
# application/cnrp+xml
# application/commonground
# application/conference-info+xml
# application/cpl+xml
# application/csta+xml
# application/cstadata+xml
application/cu-seeme cu
# application/cybercash
application/davmount+xml davmount
# application/dca-rft
# application/dec-dx
# application/dialog-info+xml
# application/dicom
# application/dns
application/docbook+xml dbk
# application/dskpp+xml
application/dssc+der dssc
application/dssc+xml xdssc
# application/dvcs
application/ecmascript ecma
# application/edi-consent
# application/edi-x12
# application/edifact
application/emma+xml emma
# application/epp+xml
application/epub+zip epub
# application/eshop
# application/example
application/exi exi
# application/fastinfoset
# application/fastsoap
# application/fits
application/font-tdpfr pfr
# application/framework-attributes+xml
application/gml+xml gml
application/gpx+xml gpx
application/gxf gxf
# application/h224
# application/held+xml
# application/http
application/hyperstudio stk
# application/ibe-key-request+xml
# application/ibe-pkg-reply+xml
# application/ibe-pp-data
# application/iges
# application/im-iscomposing+xml
# application/index
# application/index.cmd
# application/index.obj
# application/index.response
# application/index.vnd
application/inkml+xml ink inkml
# application/iotp
application/ipfix ipfix
# application/ipp
# application/isup
application/java-archive jar
application/java-serialized-object ser
application/java-vm class
application/javascript js
application/json json
application/jsonml+json jsonml
# application/kpml-request+xml
# application/kpml-response+xml
application/lost+xml lostxml
application/mac-binhex40 hqx
application/mac-compactpro cpt
# application/macwriteii
application/mads+xml mads
application/marc mrc
application/marcxml+xml mrcx
application/mathematica ma nb mb
# application/mathml-content+xml
# application/mathml-presentation+xml
application/mathml+xml mathml
# application/mbms-associated-procedure-description+xml
# application/mbms-deregister+xml
# application/mbms-envelope+xml
# application/mbms-msk+xml
# application/mbms-msk-response+xml
# application/mbms-protection-description+xml
# application/mbms-reception-report+xml
# application/mbms-register+xml
# application/mbms-register-response+xml
# application/mbms-user-service-description+xml
application/mbox mbox
# application/media_control+xml
application/mediaservercontrol+xml mscml
application/metalink+xml metalink
application/metalink4+xml meta4
application/mets+xml mets
# application/mikey
application/mods+xml mods
# application/moss-keys
# application/moss-signature
# application/mosskey-data
# application/mosskey-request
application/mp21 m21 mp21
application/mp4 mp4s
# application/mpeg4-generic
# application/mpeg4-iod
# application/mpeg4-iod-xmt
# application/msc-ivr+xml
# application/msc-mixer+xml
application/msword doc dot
application/mxf mxf
# application/nasdata
# application/news-checkgroups
# application/news-groupinfo
# application/news-transmission
# application/nss
# application/ocsp-request
# application/ocsp-response
application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy
application/oda oda
application/oebps-package+xml opf
application/ogg ogx
application/omdoc+xml omdoc
application/onenote onetoc onetoc2 onetmp onepkg
application/oxps oxps
# application/parityfec
application/patch-ops-error+xml xer
application/pdf pdf
application/pgp-encrypted pgp
# application/pgp-keys
application/pgp-signature asc sig
application/pics-rules prf
# application/pidf+xml
# application/pidf-diff+xml
application/pkcs10 p10
application/pkcs7-mime p7m p7c
application/pkcs7-signature p7s
application/pkcs8 p8
application/pkix-attr-cert ac
application/pkix-cert cer
application/pkix-crl crl
application/pkix-pkipath pkipath
application/pkixcmp pki
application/pls+xml pls
# application/poc-settings+xml
application/postscript ai eps ps
# application/prs.alvestrand.titrax-sheet
application/prs.cww cww
# application/prs.nprend
# application/prs.plucker
# application/prs.rdf-xml-crypt
# application/prs.xsf+xml
application/pskc+xml pskcxml
# application/qsig
application/rdf+xml rdf
application/reginfo+xml rif
application/relax-ng-compact-syntax rnc
# application/remote-printing
application/resource-lists+xml rl
application/resource-lists-diff+xml rld
# application/riscos
# application/rlmi+xml
application/rls-services+xml rs
application/rpki-ghostbusters gbr
application/rpki-manifest mft
application/rpki-roa roa
# application/rpki-updown
application/rsd+xml rsd
application/rss+xml rss
application/rtf rtf
# application/rtx
# application/samlassertion+xml
# application/samlmetadata+xml
application/sbml+xml sbml
application/scvp-cv-request scq
application/scvp-cv-response scs
application/scvp-vp-request spq
application/scvp-vp-response spp
application/sdp sdp
# application/set-payment
application/set-payment-initiation setpay
# application/set-registration
application/set-registration-initiation setreg
# application/sgml
# application/sgml-open-catalog
application/shf+xml shf
# application/sieve
# application/simple-filter+xml
# application/simple-message-summary
# application/simplesymbolcontainer
# application/slate
# application/smil
application/smil+xml smi smil
# application/soap+fastinfoset
# application/soap+xml
application/sparql-query rq
application/sparql-results+xml srx
# application/spirits-event+xml
application/srgs gram
application/srgs+xml grxml
application/sru+xml sru
application/ssdl+xml ssdl
application/ssml+xml ssml
# application/tamp-apex-update
# application/tamp-apex-update-confirm
# application/tamp-community-update
# application/tamp-community-update-confirm
# application/tamp-error
# application/tamp-sequence-adjust
# application/tamp-sequence-adjust-confirm
# application/tamp-status-query
# application/tamp-status-response
# application/tamp-update
# application/tamp-update-confirm
application/tei+xml tei teicorpus
application/thraud+xml tfi
# application/timestamp-query
# application/timestamp-reply
application/timestamped-data tsd
# application/tve-trigger
# application/ulpfec
# application/vcard+xml
# application/vemmi
# application/vividence.scriptfile
# application/vnd.3gpp.bsf+xml
application/vnd.3gpp.pic-bw-large plb
application/vnd.3gpp.pic-bw-small psb
application/vnd.3gpp.pic-bw-var pvb
# application/vnd.3gpp.sms
# application/vnd.3gpp2.bcmcsinfo+xml
# application/vnd.3gpp2.sms
application/vnd.3gpp2.tcap tcap
application/vnd.3m.post-it-notes pwn
application/vnd.accpac.simply.aso aso
application/vnd.accpac.simply.imp imp
application/vnd.acucobol acu
application/vnd.acucorp atc acutc
application/vnd.adobe.air-application-installer-package+zip air
application/vnd.adobe.formscentral.fcdt fcdt
application/vnd.adobe.fxp fxp fxpl
# application/vnd.adobe.partial-upload
application/vnd.adobe.xdp+xml xdp
application/vnd.adobe.xfdf xfdf
# application/vnd.aether.imp
# application/vnd.ah-barcode
application/vnd.ahead.space ahead
application/vnd.airzip.filesecure.azf azf
application/vnd.airzip.filesecure.azs azs
application/vnd.amazon.ebook azw
application/vnd.americandynamics.acc acc
application/vnd.amiga.ami ami
# application/vnd.amundsen.maze+xml
application/vnd.android.package-archive apk
application/vnd.anser-web-certificate-issue-initiation cii
application/vnd.anser-web-funds-transfer-initiation fti
application/vnd.antix.game-component atx
application/vnd.apple.installer+xml mpkg
application/vnd.apple.mpegurl m3u8
# application/vnd.arastra.swi
application/vnd.aristanetworks.swi swi
application/vnd.astraea-software.iota iota
application/vnd.audiograph aep
# application/vnd.autopackage
# application/vnd.avistar+xml
application/vnd.blueice.multipass mpm
# application/vnd.bluetooth.ep.oob
application/vnd.bmi bmi
application/vnd.businessobjects rep
# application/vnd.cab-jscript
# application/vnd.canon-cpdl
# application/vnd.canon-lips
# application/vnd.cendio.thinlinc.clientconf
application/vnd.chemdraw+xml cdxml
application/vnd.chipnuts.karaoke-mmd mmd
application/vnd.cinderella cdy
# application/vnd.cirpack.isdn-ext
application/vnd.claymore cla
application/vnd.cloanto.rp9 rp9
application/vnd.clonk.c4group c4g c4d c4f c4p c4u
application/vnd.cluetrust.cartomobile-config c11amc
application/vnd.cluetrust.cartomobile-config-pkg c11amz
# application/vnd.collection+json
# application/vnd.commerce-battelle
application/vnd.commonspace csp
application/vnd.contact.cmsg cdbcmsg
application/vnd.cosmocaller cmc
application/vnd.crick.clicker clkx
application/vnd.crick.clicker.keyboard clkk
application/vnd.crick.clicker.palette clkp
application/vnd.crick.clicker.template clkt
application/vnd.crick.clicker.wordbank clkw
application/vnd.criticaltools.wbs+xml wbs
application/vnd.ctc-posml pml
# application/vnd.ctct.ws+xml
# application/vnd.cups-pdf
# application/vnd.cups-postscript
application/vnd.cups-ppd ppd
# application/vnd.cups-raster
# application/vnd.cups-raw
# application/vnd.curl
application/vnd.curl.car car
application/vnd.curl.pcurl pcurl
# application/vnd.cybank
application/vnd.dart dart
application/vnd.data-vision.rdz rdz
application/vnd.dece.data uvf uvvf uvd uvvd
application/vnd.dece.ttml+xml uvt uvvt
application/vnd.dece.unspecified uvx uvvx
application/vnd.dece.zip uvz uvvz
application/vnd.denovo.fcselayout-link fe_launch
# application/vnd.dir-bi.plate-dl-nosuffix
application/vnd.dna dna
application/vnd.dolby.mlp mlp
# application/vnd.dolby.mobile.1
# application/vnd.dolby.mobile.2
application/vnd.dpgraph dpg
application/vnd.dreamfactory dfac
application/vnd.ds-keypoint kpxx
application/vnd.dvb.ait ait
# application/vnd.dvb.dvbj
# application/vnd.dvb.esgcontainer
# application/vnd.dvb.ipdcdftnotifaccess
# application/vnd.dvb.ipdcesgaccess
# application/vnd.dvb.ipdcesgaccess2
# application/vnd.dvb.ipdcesgpdd
# application/vnd.dvb.ipdcroaming
# application/vnd.dvb.iptv.alfec-base
# application/vnd.dvb.iptv.alfec-enhancement
# application/vnd.dvb.notif-aggregate-root+xml
# application/vnd.dvb.notif-container+xml
# application/vnd.dvb.notif-generic+xml
# application/vnd.dvb.notif-ia-msglist+xml
# application/vnd.dvb.notif-ia-registration-request+xml
# application/vnd.dvb.notif-ia-registration-response+xml
# application/vnd.dvb.notif-init+xml
# application/vnd.dvb.pfr
application/vnd.dvb.service svc
# application/vnd.dxr
application/vnd.dynageo geo
# application/vnd.easykaraoke.cdgdownload
# application/vnd.ecdis-update
application/vnd.ecowin.chart mag
# application/vnd.ecowin.filerequest
# application/vnd.ecowin.fileupdate
# application/vnd.ecowin.series
# application/vnd.ecowin.seriesrequest
# application/vnd.ecowin.seriesupdate
# application/vnd.emclient.accessrequest+xml
application/vnd.enliven nml
# application/vnd.eprints.data+xml
application/vnd.epson.esf esf
application/vnd.epson.msf msf
application/vnd.epson.quickanime qam
application/vnd.epson.salt slt
application/vnd.epson.ssf ssf
# application/vnd.ericsson.quickcall
application/vnd.eszigno3+xml es3 et3
# application/vnd.etsi.aoc+xml
# application/vnd.etsi.cug+xml
# application/vnd.etsi.iptvcommand+xml
# application/vnd.etsi.iptvdiscovery+xml
# application/vnd.etsi.iptvprofile+xml
# application/vnd.etsi.iptvsad-bc+xml
# application/vnd.etsi.iptvsad-cod+xml
# application/vnd.etsi.iptvsad-npvr+xml
# application/vnd.etsi.iptvservice+xml
# application/vnd.etsi.iptvsync+xml
# application/vnd.etsi.iptvueprofile+xml
# application/vnd.etsi.mcid+xml
# application/vnd.etsi.overload-control-policy-dataset+xml
# application/vnd.etsi.sci+xml
# application/vnd.etsi.simservs+xml
# application/vnd.etsi.tsl+xml
# application/vnd.etsi.tsl.der
# application/vnd.eudora.data
application/vnd.ezpix-album ez2
application/vnd.ezpix-package ez3
# application/vnd.f-secure.mobile
application/vnd.fdf fdf
application/vnd.fdsn.mseed mseed
application/vnd.fdsn.seed seed dataless
# application/vnd.ffsns
# application/vnd.fints
application/vnd.flographit gph
application/vnd.fluxtime.clip ftc
# application/vnd.font-fontforge-sfd
application/vnd.framemaker fm frame maker book
application/vnd.frogans.fnc fnc
application/vnd.frogans.ltf ltf
application/vnd.fsc.weblaunch fsc
application/vnd.fujitsu.oasys oas
application/vnd.fujitsu.oasys2 oa2
application/vnd.fujitsu.oasys3 oa3
application/vnd.fujitsu.oasysgp fg5
application/vnd.fujitsu.oasysprs bh2
# application/vnd.fujixerox.art-ex
# application/vnd.fujixerox.art4
# application/vnd.fujixerox.hbpl
application/vnd.fujixerox.ddd ddd
application/vnd.fujixerox.docuworks xdw
application/vnd.fujixerox.docuworks.binder xbd
# application/vnd.fut-misnet
application/vnd.fuzzysheet fzs
application/vnd.genomatix.tuxedo txd
# application/vnd.geocube+xml
application/vnd.geogebra.file ggb
application/vnd.geogebra.tool ggt
application/vnd.geometry-explorer gex gre
application/vnd.geonext gxt
application/vnd.geoplan g2w
application/vnd.geospace g3w
# application/vnd.globalplatform.card-content-mgt
# application/vnd.globalplatform.card-content-mgt-response
application/vnd.gmx gmx
application/vnd.google-earth.kml+xml kml
application/vnd.google-earth.kmz kmz
application/vnd.grafeq gqf gqs
# application/vnd.gridmp
application/vnd.groove-account gac
application/vnd.groove-help ghf
application/vnd.groove-identity-message gim
application/vnd.groove-injector grv
application/vnd.groove-tool-message gtm
application/vnd.groove-tool-template tpl
application/vnd.groove-vcard vcg
# application/vnd.hal+json
application/vnd.hal+xml hal
application/vnd.handheld-entertainment+xml zmm
application/vnd.hbci hbci
# application/vnd.hcl-bireports
application/vnd.hhe.lesson-player les
application/vnd.hp-hpgl hpgl
application/vnd.hp-hpid hpid
application/vnd.hp-hps hps
application/vnd.hp-jlyt jlt
application/vnd.hp-pcl pcl
application/vnd.hp-pclxl pclxl
# application/vnd.httphone
application/vnd.hydrostatix.sof-data sfd-hdstx
# application/vnd.hzn-3d-crossword
# application/vnd.ibm.afplinedata
# application/vnd.ibm.electronic-media
application/vnd.ibm.minipay mpy
application/vnd.ibm.modcap afp listafp list3820
application/vnd.ibm.rights-management irm
application/vnd.ibm.secure-container sc
application/vnd.iccprofile icc icm
application/vnd.igloader igl
application/vnd.immervision-ivp ivp
application/vnd.immervision-ivu ivu
# application/vnd.informedcontrol.rms+xml
# application/vnd.informix-visionary
# application/vnd.infotech.project
# application/vnd.infotech.project+xml
# application/vnd.innopath.wamp.notification
application/vnd.insors.igm igm
application/vnd.intercon.formnet xpw xpx
application/vnd.intergeo i2g
# application/vnd.intertrust.digibox
# application/vnd.intertrust.nncp
application/vnd.intu.qbo qbo
application/vnd.intu.qfx qfx
# application/vnd.iptc.g2.conceptitem+xml
# application/vnd.iptc.g2.knowledgeitem+xml
# application/vnd.iptc.g2.newsitem+xml
# application/vnd.iptc.g2.newsmessage+xml
# application/vnd.iptc.g2.packageitem+xml
# application/vnd.iptc.g2.planningitem+xml
application/vnd.ipunplugged.rcprofile rcprofile
application/vnd.irepository.package+xml irp
application/vnd.is-xpr xpr
application/vnd.isac.fcs fcs
application/vnd.jam jam
# application/vnd.japannet-directory-service
# application/vnd.japannet-jpnstore-wakeup
# application/vnd.japannet-payment-wakeup
# application/vnd.japannet-registration
# application/vnd.japannet-registration-wakeup
# application/vnd.japannet-setstore-wakeup
# application/vnd.japannet-verification
# application/vnd.japannet-verification-wakeup
application/vnd.jcp.javame.midlet-rms rms
application/vnd.jisp jisp
application/vnd.joost.joda-archive joda
application/vnd.kahootz ktz ktr
application/vnd.kde.karbon karbon
application/vnd.kde.kchart chrt
application/vnd.kde.kformula kfo
application/vnd.kde.kivio flw
application/vnd.kde.kontour kon
application/vnd.kde.kpresenter kpr kpt
application/vnd.kde.kspread ksp
application/vnd.kde.kword kwd kwt
application/vnd.kenameaapp htke
application/vnd.kidspiration kia
application/vnd.kinar kne knp
application/vnd.koan skp skd skt skm
application/vnd.kodak-descriptor sse
application/vnd.las.las+xml lasxml
# application/vnd.liberty-request+xml
application/vnd.llamagraphics.life-balance.desktop lbd
application/vnd.llamagraphics.life-balance.exchange+xml lbe
application/vnd.lotus-1-2-3 123
application/vnd.lotus-approach apr
application/vnd.lotus-freelance pre
application/vnd.lotus-notes nsf
application/vnd.lotus-organizer org
application/vnd.lotus-screencam scm
application/vnd.lotus-wordpro lwp
application/vnd.macports.portpkg portpkg
# application/vnd.marlin.drm.actiontoken+xml
# application/vnd.marlin.drm.conftoken+xml
# application/vnd.marlin.drm.license+xml
# application/vnd.marlin.drm.mdcf
application/vnd.mcd mcd
application/vnd.medcalcdata mc1
application/vnd.mediastation.cdkey cdkey
# application/vnd.meridian-slingshot
application/vnd.mfer mwf
application/vnd.mfmp mfm
application/vnd.micrografx.flo flo
application/vnd.micrografx.igx igx
application/vnd.mif mif
# application/vnd.minisoft-hp3000-save
# application/vnd.mitsubishi.misty-guard.trustweb
application/vnd.mobius.daf daf
application/vnd.mobius.dis dis
application/vnd.mobius.mbk mbk
application/vnd.mobius.mqy mqy
application/vnd.mobius.msl msl
application/vnd.mobius.plc plc
application/vnd.mobius.txf txf
application/vnd.mophun.application mpn
application/vnd.mophun.certificate mpc
# application/vnd.motorola.flexsuite
# application/vnd.motorola.flexsuite.adsi
# application/vnd.motorola.flexsuite.fis
# application/vnd.motorola.flexsuite.gotap
# application/vnd.motorola.flexsuite.kmr
# application/vnd.motorola.flexsuite.ttc
# application/vnd.motorola.flexsuite.wem
# application/vnd.motorola.iprm
application/vnd.mozilla.xul+xml xul
application/vnd.ms-artgalry cil
# application/vnd.ms-asf
application/vnd.ms-cab-compressed cab
# application/vnd.ms-color.iccprofile
application/vnd.ms-excel xls xlm xla xlc xlt xlw
application/vnd.ms-excel.addin.macroenabled.12 xlam
application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb
application/vnd.ms-excel.sheet.macroenabled.12 xlsm
application/vnd.ms-excel.template.macroenabled.12 xltm
application/vnd.ms-fontobject eot
application/vnd.ms-htmlhelp chm
application/vnd.ms-ims ims
application/vnd.ms-lrm lrm
# application/vnd.ms-office.activex+xml
application/vnd.ms-officetheme thmx
# application/vnd.ms-opentype
# application/vnd.ms-package.obfuscated-opentype
application/vnd.ms-pki.seccat cat
application/vnd.ms-pki.stl stl
# application/vnd.ms-playready.initiator+xml
application/vnd.ms-powerpoint ppt pps pot
application/vnd.ms-powerpoint.addin.macroenabled.12 ppam
application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm
application/vnd.ms-powerpoint.slide.macroenabled.12 sldm
application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm
application/vnd.ms-powerpoint.template.macroenabled.12 potm
# application/vnd.ms-printing.printticket+xml
application/vnd.ms-project mpp mpt
# application/vnd.ms-tnef
# application/vnd.ms-wmdrm.lic-chlg-req
# application/vnd.ms-wmdrm.lic-resp
# application/vnd.ms-wmdrm.meter-chlg-req
# application/vnd.ms-wmdrm.meter-resp
application/vnd.ms-word.document.macroenabled.12 docm
application/vnd.ms-word.template.macroenabled.12 dotm
application/vnd.ms-works wps wks wcm wdb
application/vnd.ms-wpl wpl
application/vnd.ms-xpsdocument xps
application/vnd.mseq mseq
# application/vnd.msign
# application/vnd.multiad.creator
# application/vnd.multiad.creator.cif
# application/vnd.music-niff
application/vnd.musician mus
application/vnd.muvee.style msty
application/vnd.mynfc taglet
# application/vnd.ncd.control
# application/vnd.ncd.reference
# application/vnd.nervana
# application/vnd.netfpx
application/vnd.neurolanguage.nlu nlu
application/vnd.nitf ntf nitf
application/vnd.noblenet-directory nnd
application/vnd.noblenet-sealer nns
application/vnd.noblenet-web nnw
# application/vnd.nokia.catalogs
# application/vnd.nokia.conml+wbxml
# application/vnd.nokia.conml+xml
# application/vnd.nokia.isds-radio-presets
# application/vnd.nokia.iptv.config+xml
# application/vnd.nokia.landmark+wbxml
# application/vnd.nokia.landmark+xml
# application/vnd.nokia.landmarkcollection+xml
# application/vnd.nokia.n-gage.ac+xml
application/vnd.nokia.n-gage.data ngdat
application/vnd.nokia.n-gage.symbian.install n-gage
# application/vnd.nokia.ncd
# application/vnd.nokia.pcd+wbxml
# application/vnd.nokia.pcd+xml
application/vnd.nokia.radio-preset rpst
application/vnd.nokia.radio-presets rpss
application/vnd.novadigm.edm edm
application/vnd.novadigm.edx edx
application/vnd.novadigm.ext ext
# application/vnd.ntt-local.file-transfer
# application/vnd.ntt-local.sip-ta_remote
# application/vnd.ntt-local.sip-ta_tcp_stream
application/vnd.oasis.opendocument.chart odc
application/vnd.oasis.opendocument.chart-template otc
application/vnd.oasis.opendocument.database odb
application/vnd.oasis.opendocument.formula odf
application/vnd.oasis.opendocument.formula-template odft
application/vnd.oasis.opendocument.graphics odg
application/vnd.oasis.opendocument.graphics-template otg
application/vnd.oasis.opendocument.image odi
application/vnd.oasis.opendocument.image-template oti
application/vnd.oasis.opendocument.presentation odp
application/vnd.oasis.opendocument.presentation-template otp
application/vnd.oasis.opendocument.spreadsheet ods
application/vnd.oasis.opendocument.spreadsheet-template ots
application/vnd.oasis.opendocument.text odt
application/vnd.oasis.opendocument.text-master odm
application/vnd.oasis.opendocument.text-template ott
application/vnd.oasis.opendocument.text-web oth
# application/vnd.obn
# application/vnd.oftn.l10n+json
# application/vnd.oipf.contentaccessdownload+xml
# application/vnd.oipf.contentaccessstreaming+xml
# application/vnd.oipf.cspg-hexbinary
# application/vnd.oipf.dae.svg+xml
# application/vnd.oipf.dae.xhtml+xml
# application/vnd.oipf.mippvcontrolmessage+xml
# application/vnd.oipf.pae.gem
# application/vnd.oipf.spdiscovery+xml
# application/vnd.oipf.spdlist+xml
# application/vnd.oipf.ueprofile+xml
# application/vnd.oipf.userprofile+xml
application/vnd.olpc-sugar xo
# application/vnd.oma-scws-config
# application/vnd.oma-scws-http-request
# application/vnd.oma-scws-http-response
# application/vnd.oma.bcast.associated-procedure-parameter+xml
# application/vnd.oma.bcast.drm-trigger+xml
# application/vnd.oma.bcast.imd+xml
# application/vnd.oma.bcast.ltkm
# application/vnd.oma.bcast.notification+xml
# application/vnd.oma.bcast.provisioningtrigger
# application/vnd.oma.bcast.sgboot
# application/vnd.oma.bcast.sgdd+xml
# application/vnd.oma.bcast.sgdu
# application/vnd.oma.bcast.simple-symbol-container
# application/vnd.oma.bcast.smartcard-trigger+xml
# application/vnd.oma.bcast.sprov+xml
# application/vnd.oma.bcast.stkm
# application/vnd.oma.cab-address-book+xml
# application/vnd.oma.cab-feature-handler+xml
# application/vnd.oma.cab-pcc+xml
# application/vnd.oma.cab-user-prefs+xml
# application/vnd.oma.dcd
# application/vnd.oma.dcdc
application/vnd.oma.dd2+xml dd2
# application/vnd.oma.drm.risd+xml
# application/vnd.oma.group-usage-list+xml
# application/vnd.oma.pal+xml
# application/vnd.oma.poc.detailed-progress-report+xml
# application/vnd.oma.poc.final-report+xml
# application/vnd.oma.poc.groups+xml
# application/vnd.oma.poc.invocation-descriptor+xml
# application/vnd.oma.poc.optimized-progress-report+xml
# application/vnd.oma.push
# application/vnd.oma.scidm.messages+xml
# application/vnd.oma.xcap-directory+xml
# application/vnd.omads-email+xml
# application/vnd.omads-file+xml
# application/vnd.omads-folder+xml
# application/vnd.omaloc-supl-init
application/vnd.openofficeorg.extension oxt
# application/vnd.openxmlformats-officedocument.custom-properties+xml
# application/vnd.openxmlformats-officedocument.customxmlproperties+xml
# application/vnd.openxmlformats-officedocument.drawing+xml
# application/vnd.openxmlformats-officedocument.drawingml.chart+xml
# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml
# application/vnd.openxmlformats-officedocument.extended-properties+xml
# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml
# application/vnd.openxmlformats-officedocument.presentationml.comments+xml
# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml
# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml
# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml
application/vnd.openxmlformats-officedocument.presentationml.presentation pptx
# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml
# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml
application/vnd.openxmlformats-officedocument.presentationml.slide sldx
# application/vnd.openxmlformats-officedocument.presentationml.slide+xml
# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml
# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml
application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx
# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml
# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml
# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml
# application/vnd.openxmlformats-officedocument.presentationml.tags+xml
application/vnd.openxmlformats-officedocument.presentationml.template potx
# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml
# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx
# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml
application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx
# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml
# application/vnd.openxmlformats-officedocument.theme+xml
# application/vnd.openxmlformats-officedocument.themeoverride+xml
# application/vnd.openxmlformats-officedocument.vmldrawing
# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml
application/vnd.openxmlformats-officedocument.wordprocessingml.document docx
# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml
application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx
# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml
# application/vnd.openxmlformats-package.core-properties+xml
# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml
# application/vnd.openxmlformats-package.relationships+xml
# application/vnd.quobject-quoxdocument
# application/vnd.osa.netdeploy
application/vnd.osgeo.mapguide.package mgp
# application/vnd.osgi.bundle
application/vnd.osgi.dp dp
application/vnd.osgi.subsystem esa
# application/vnd.otps.ct-kip+xml
application/vnd.palm pdb pqa oprc
# application/vnd.paos.xml
application/vnd.pawaafile paw
application/vnd.pg.format str
application/vnd.pg.osasli ei6
# application/vnd.piaccess.application-licence
application/vnd.picsel efif
application/vnd.pmi.widget wg
# application/vnd.poc.group-advertisement+xml
application/vnd.pocketlearn plf
application/vnd.powerbuilder6 pbd
# application/vnd.powerbuilder6-s
# application/vnd.powerbuilder7
# application/vnd.powerbuilder7-s
# application/vnd.powerbuilder75
# application/vnd.powerbuilder75-s
# application/vnd.preminet
application/vnd.previewsystems.box box
application/vnd.proteus.magazine mgz
application/vnd.publishare-delta-tree qps
application/vnd.pvi.ptid1 ptid
# application/vnd.pwg-multiplexed
# application/vnd.pwg-xhtml-print+xml
# application/vnd.qualcomm.brew-app-res
application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb
# application/vnd.radisys.moml+xml
# application/vnd.radisys.msml+xml
# application/vnd.radisys.msml-audit+xml
# application/vnd.radisys.msml-audit-conf+xml
# application/vnd.radisys.msml-audit-conn+xml
# application/vnd.radisys.msml-audit-dialog+xml
# application/vnd.radisys.msml-audit-stream+xml
# application/vnd.radisys.msml-conf+xml
# application/vnd.radisys.msml-dialog+xml
# application/vnd.radisys.msml-dialog-base+xml
# application/vnd.radisys.msml-dialog-fax-detect+xml
# application/vnd.radisys.msml-dialog-fax-sendrecv+xml
# application/vnd.radisys.msml-dialog-group+xml
# application/vnd.radisys.msml-dialog-speech+xml
# application/vnd.radisys.msml-dialog-transform+xml
# application/vnd.rainstor.data
# application/vnd.rapid
application/vnd.realvnc.bed bed
application/vnd.recordare.musicxml mxl
application/vnd.recordare.musicxml+xml musicxml
# application/vnd.renlearn.rlprint
application/vnd.rig.cryptonote cryptonote
application/vnd.rim.cod cod
application/vnd.rn-realmedia rm
application/vnd.rn-realmedia-vbr rmvb
application/vnd.route66.link66+xml link66
# application/vnd.rs-274x
# application/vnd.ruckus.download
# application/vnd.s3sms
application/vnd.sailingtracker.track st
# application/vnd.sbm.cid
# application/vnd.sbm.mid2
# application/vnd.scribus
# application/vnd.sealed.3df
# application/vnd.sealed.csf
# application/vnd.sealed.doc
# application/vnd.sealed.eml
# application/vnd.sealed.mht
# application/vnd.sealed.net
# application/vnd.sealed.ppt
# application/vnd.sealed.tiff
# application/vnd.sealed.xls
# application/vnd.sealedmedia.softseal.html
# application/vnd.sealedmedia.softseal.pdf
application/vnd.seemail see
application/vnd.sema sema
application/vnd.semd semd
application/vnd.semf semf
application/vnd.shana.informed.formdata ifm
application/vnd.shana.informed.formtemplate itp
application/vnd.shana.informed.interchange iif
application/vnd.shana.informed.package ipk
application/vnd.simtech-mindmapper twd twds
application/vnd.smaf mmf
# application/vnd.smart.notebook
application/vnd.smart.teacher teacher
# application/vnd.software602.filler.form+xml
# application/vnd.software602.filler.form-xml-zip
application/vnd.solent.sdkm+xml sdkm sdkd
application/vnd.spotfire.dxp dxp
application/vnd.spotfire.sfs sfs
# application/vnd.sss-cod
# application/vnd.sss-dtf
# application/vnd.sss-ntf
application/vnd.stardivision.calc sdc
application/vnd.stardivision.draw sda
application/vnd.stardivision.impress sdd
application/vnd.stardivision.math smf
application/vnd.stardivision.writer sdw vor
application/vnd.stardivision.writer-global sgl
application/vnd.stepmania.package smzip
application/vnd.stepmania.stepchart sm
# application/vnd.street-stream
application/vnd.sun.xml.calc sxc
application/vnd.sun.xml.calc.template stc
application/vnd.sun.xml.draw sxd
application/vnd.sun.xml.draw.template std
application/vnd.sun.xml.impress sxi
application/vnd.sun.xml.impress.template sti
application/vnd.sun.xml.math sxm
application/vnd.sun.xml.writer sxw
application/vnd.sun.xml.writer.global sxg
application/vnd.sun.xml.writer.template stw
# application/vnd.sun.wadl+xml
application/vnd.sus-calendar sus susp
application/vnd.svd svd
# application/vnd.swiftview-ics
application/vnd.symbian.install sis sisx
application/vnd.syncml+xml xsm
application/vnd.syncml.dm+wbxml bdm
application/vnd.syncml.dm+xml xdm
# application/vnd.syncml.dm.notification
# application/vnd.syncml.ds.notification
application/vnd.tao.intent-module-archive tao
application/vnd.tcpdump.pcap pcap cap dmp
application/vnd.tmobile-livetv tmo
application/vnd.trid.tpt tpt
application/vnd.triscape.mxs mxs
application/vnd.trueapp tra
# application/vnd.truedoc
# application/vnd.ubisoft.webplayer
application/vnd.ufdl ufd ufdl
application/vnd.uiq.theme utz
application/vnd.umajin umj
application/vnd.unity unityweb
application/vnd.uoml+xml uoml
# application/vnd.uplanet.alert
# application/vnd.uplanet.alert-wbxml
# application/vnd.uplanet.bearer-choice
# application/vnd.uplanet.bearer-choice-wbxml
# application/vnd.uplanet.cacheop
# application/vnd.uplanet.cacheop-wbxml
# application/vnd.uplanet.channel
# application/vnd.uplanet.channel-wbxml
# application/vnd.uplanet.list
# application/vnd.uplanet.list-wbxml
# application/vnd.uplanet.listcmd
# application/vnd.uplanet.listcmd-wbxml
# application/vnd.uplanet.signal
application/vnd.vcx vcx
# application/vnd.vd-study
# application/vnd.vectorworks
# application/vnd.verimatrix.vcas
# application/vnd.vidsoft.vidconference
application/vnd.visio vsd vst vss vsw
application/vnd.visionary vis
# application/vnd.vividence.scriptfile
application/vnd.vsf vsf
# application/vnd.wap.sic
# application/vnd.wap.slc
application/vnd.wap.wbxml wbxml
application/vnd.wap.wmlc wmlc
application/vnd.wap.wmlscriptc wmlsc
application/vnd.webturbo wtb
# application/vnd.wfa.wsc
# application/vnd.wmc
# application/vnd.wmf.bootstrap
# application/vnd.wolfram.mathematica
# application/vnd.wolfram.mathematica.package
application/vnd.wolfram.player nbp
application/vnd.wordperfect wpd
application/vnd.wqd wqd
# application/vnd.wrq-hp3000-labelled
application/vnd.wt.stf stf
# application/vnd.wv.csp+wbxml
# application/vnd.wv.csp+xml
# application/vnd.wv.ssp+xml
application/vnd.xara xar
application/vnd.xfdl xfdl
# application/vnd.xfdl.webform
# application/vnd.xmi+xml
# application/vnd.xmpie.cpkg
# application/vnd.xmpie.dpkg
# application/vnd.xmpie.plan
# application/vnd.xmpie.ppkg
# application/vnd.xmpie.xlim
application/vnd.yamaha.hv-dic hvd
application/vnd.yamaha.hv-script hvs
application/vnd.yamaha.hv-voice hvp
application/vnd.yamaha.openscoreformat osf
application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg
# application/vnd.yamaha.remote-setup
application/vnd.yamaha.smaf-audio saf
application/vnd.yamaha.smaf-phrase spf
# application/vnd.yamaha.through-ngn
# application/vnd.yamaha.tunnel-udpencap
application/vnd.yellowriver-custom-menu cmp
application/vnd.zul zir zirz
application/vnd.zzazz.deck+xml zaz
application/voicexml+xml vxml
# application/vq-rtcpxr
# application/watcherinfo+xml
# application/whoispp-query
# application/whoispp-response
application/widget wgt
application/winhlp hlp
# application/wita
# application/wordperfect5.1
application/wsdl+xml wsdl
application/wspolicy+xml wspolicy
application/x-7z-compressed 7z
application/x-abiword abw
application/x-ace-compressed ace
# application/x-amf
application/x-apple-diskimage dmg
application/x-authorware-bin aab x32 u32 vox
application/x-authorware-map aam
application/x-authorware-seg aas
application/x-bcpio bcpio
application/x-bittorrent torrent
application/x-blorb blb blorb
application/x-bzip bz
application/x-bzip2 bz2 boz
application/x-cbr cbr cba cbt cbz cb7
application/x-cdlink vcd
application/x-cfs-compressed cfs
application/x-chat chat
application/x-chess-pgn pgn
application/x-conference nsc
# application/x-compress
application/x-cpio cpio
application/x-csh csh
application/x-debian-package deb udeb
application/x-dgc-compressed dgc
application/x-director dir dcr dxr cst cct cxt w3d fgd swa
application/x-doom wad
application/x-dtbncx+xml ncx
application/x-dtbook+xml dtb
application/x-dtbresource+xml res
application/x-dvi dvi
application/x-envoy evy
application/x-eva eva
application/x-font-bdf bdf
# application/x-font-dos
# application/x-font-framemaker
application/x-font-ghostscript gsf
# application/x-font-libgrx
application/x-font-linux-psf psf
application/x-font-otf otf
application/x-font-pcf pcf
application/x-font-snf snf
# application/x-font-speedo
# application/x-font-sunos-news
application/x-font-ttf ttf ttc
application/x-font-type1 pfa pfb pfm afm
application/font-woff woff
# application/x-font-vfont
application/x-freearc arc
application/x-futuresplash spl
application/x-gca-compressed gca
application/x-glulx ulx
application/x-gnumeric gnumeric
application/x-gramps-xml gramps
application/x-gtar gtar
# application/x-gzip
application/x-hdf hdf
application/x-install-instructions install
application/x-iso9660-image iso
application/x-java-jnlp-file jnlp
application/x-latex latex
application/x-lzh-compressed lzh lha
application/x-mie mie
application/x-mobipocket-ebook prc mobi
application/x-ms-application application
application/x-ms-shortcut lnk
application/x-ms-wmd wmd
application/x-ms-wmz wmz
application/x-ms-xbap xbap
application/x-msaccess mdb
application/x-msbinder obd
application/x-mscardfile crd
application/x-msclip clp
application/x-msdownload exe dll com bat msi
application/x-msmediaview mvb m13 m14
application/x-msmetafile wmf wmz emf emz
application/x-msmoney mny
application/x-mspublisher pub
application/x-msschedule scd
application/x-msterminal trm
application/x-mswrite wri
application/x-netcdf nc cdf
application/x-nzb nzb
application/x-pkcs12 p12 pfx
application/x-pkcs7-certificates p7b spc
application/x-pkcs7-certreqresp p7r
application/x-rar-compressed rar
application/x-research-info-systems ris
application/x-sh sh
application/x-shar shar
application/x-shockwave-flash swf
application/x-silverlight-app xap
application/x-sql sql
application/x-stuffit sit
application/x-stuffitx sitx
application/x-subrip srt
application/x-sv4cpio sv4cpio
application/x-sv4crc sv4crc
application/x-t3vm-image t3
application/x-tads gam
application/x-tar tar
application/x-tcl tcl
application/x-tex tex
application/x-tex-tfm tfm
application/x-texinfo texinfo texi
application/x-tgif obj
application/x-ustar ustar
application/x-wais-source src
application/x-x509-ca-cert der crt
application/x-xfig fig
application/x-xliff+xml xlf
application/x-xpinstall xpi
application/x-xz xz
application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8
# application/x400-bp
application/xaml+xml xaml
# application/xcap-att+xml
# application/xcap-caps+xml
application/xcap-diff+xml xdf
# application/xcap-el+xml
# application/xcap-error+xml
# application/xcap-ns+xml
# application/xcon-conference-info-diff+xml
# application/xcon-conference-info+xml
application/xenc+xml xenc
application/xhtml+xml xhtml xht
# application/xhtml-voice+xml
application/xml xml xsl
application/xml-dtd dtd
# application/xml-external-parsed-entity
# application/xmpp+xml
application/xop+xml xop
application/xproc+xml xpl
application/xslt+xml xslt
application/xspf+xml xspf
application/xv+xml mxml xhvml xvml xvm
application/yang yang
application/yin+xml yin
application/zip zip
# audio/1d-interleaved-parityfec
# audio/32kadpcm
# audio/3gpp
# audio/3gpp2
# audio/ac3
audio/adpcm adp
# audio/amr
# audio/amr-wb
# audio/amr-wb+
# audio/asc
# audio/atrac-advanced-lossless
# audio/atrac-x
# audio/atrac3
audio/basic au snd
# audio/bv16
# audio/bv32
# audio/clearmode
# audio/cn
# audio/dat12
# audio/dls
# audio/dsr-es201108
# audio/dsr-es202050
# audio/dsr-es202211
# audio/dsr-es202212
# audio/dv
# audio/dvi4
# audio/eac3
# audio/evrc
# audio/evrc-qcp
# audio/evrc0
# audio/evrc1
# audio/evrcb
# audio/evrcb0
# audio/evrcb1
# audio/evrcwb
# audio/evrcwb0
# audio/evrcwb1
# audio/example
# audio/fwdred
# audio/g719
# audio/g722
# audio/g7221
# audio/g723
# audio/g726-16
# audio/g726-24
# audio/g726-32
# audio/g726-40
# audio/g728
# audio/g729
# audio/g7291
# audio/g729d
# audio/g729e
# audio/gsm
# audio/gsm-efr
# audio/gsm-hr-08
# audio/ilbc
# audio/ip-mr_v2.5
# audio/isac
# audio/l16
# audio/l20
# audio/l24
# audio/l8
# audio/lpc
audio/midi mid midi kar rmi
# audio/mobile-xmf
audio/mp4 mp4a
# audio/mp4a-latm
# audio/mpa
# audio/mpa-robust
audio/mpeg mpga mp2 mp2a mp3 m2a m3a
# audio/mpeg4-generic
# audio/musepack
audio/ogg oga ogg spx
# audio/opus
# audio/parityfec
# audio/pcma
# audio/pcma-wb
# audio/pcmu-wb
# audio/pcmu
# audio/prs.sid
# audio/qcelp
# audio/red
# audio/rtp-enc-aescm128
# audio/rtp-midi
# audio/rtx
audio/s3m s3m
audio/silk sil
# audio/smv
# audio/smv0
# audio/smv-qcp
# audio/sp-midi
# audio/speex
# audio/t140c
# audio/t38
# audio/telephone-event
# audio/tone
# audio/uemclip
# audio/ulpfec
# audio/vdvi
# audio/vmr-wb
# audio/vnd.3gpp.iufp
# audio/vnd.4sb
# audio/vnd.audiokoz
# audio/vnd.celp
# audio/vnd.cisco.nse
# audio/vnd.cmles.radio-events
# audio/vnd.cns.anp1
# audio/vnd.cns.inf1
audio/vnd.dece.audio uva uvva
audio/vnd.digital-winds eol
# audio/vnd.dlna.adts
# audio/vnd.dolby.heaac.1
# audio/vnd.dolby.heaac.2
# audio/vnd.dolby.mlp
# audio/vnd.dolby.mps
# audio/vnd.dolby.pl2
# audio/vnd.dolby.pl2x
# audio/vnd.dolby.pl2z
# audio/vnd.dolby.pulse.1
audio/vnd.dra dra
audio/vnd.dts dts
audio/vnd.dts.hd dtshd
# audio/vnd.dvb.file
# audio/vnd.everad.plj
# audio/vnd.hns.audio
audio/vnd.lucent.voice lvp
audio/vnd.ms-playready.media.pya pya
# audio/vnd.nokia.mobile-xmf
# audio/vnd.nortel.vbk
audio/vnd.nuera.ecelp4800 ecelp4800
audio/vnd.nuera.ecelp7470 ecelp7470
audio/vnd.nuera.ecelp9600 ecelp9600
# audio/vnd.octel.sbc
# audio/vnd.qcelp
# audio/vnd.rhetorex.32kadpcm
audio/vnd.rip rip
# audio/vnd.sealedmedia.softseal.mpeg
# audio/vnd.vmx.cvsd
# audio/vorbis
# audio/vorbis-config
audio/webm weba
audio/x-aac aac
audio/x-aiff aif aiff aifc
audio/x-caf caf
audio/x-flac flac
audio/x-matroska mka
audio/x-mpegurl m3u
audio/x-ms-wax wax
audio/x-ms-wma wma
audio/x-pn-realaudio ram ra
audio/x-pn-realaudio-plugin rmp
# audio/x-tta
audio/x-wav wav
audio/xm xm
chemical/x-cdx cdx
chemical/x-cif cif
chemical/x-cmdf cmdf
chemical/x-cml cml
chemical/x-csml csml
# chemical/x-pdb
chemical/x-xyz xyz
image/bmp bmp
image/cgm cgm
# image/example
# image/fits
image/g3fax g3
image/gif gif
image/ief ief
# image/jp2
image/jpeg jpeg jpg jpe
# image/jpm
# image/jpx
image/ktx ktx
# image/naplps
image/png png
image/prs.btif btif
# image/prs.pti
image/sgi sgi
image/svg+xml svg svgz
# image/t38
image/tiff tiff tif
# image/tiff-fx
image/vnd.adobe.photoshop psd
# image/vnd.cns.inf2
image/vnd.dece.graphic uvi uvvi uvg uvvg
image/vnd.dvb.subtitle sub
image/vnd.djvu djvu djv
image/vnd.dwg dwg
image/vnd.dxf dxf
image/vnd.fastbidsheet fbs
image/vnd.fpx fpx
image/vnd.fst fst
image/vnd.fujixerox.edmics-mmr mmr
image/vnd.fujixerox.edmics-rlc rlc
# image/vnd.globalgraphics.pgb
# image/vnd.microsoft.icon
# image/vnd.mix
image/vnd.ms-modi mdi
image/vnd.ms-photo wdp
image/vnd.net-fpx npx
# image/vnd.radiance
# image/vnd.sealed.png
# image/vnd.sealedmedia.softseal.gif
# image/vnd.sealedmedia.softseal.jpg
# image/vnd.svf
image/vnd.wap.wbmp wbmp
image/vnd.xiff xif
image/webp webp
image/x-3ds 3ds
image/x-cmu-raster ras
image/x-cmx cmx
image/x-freehand fh fhc fh4 fh5 fh7
image/x-icon ico
image/x-mrsid-image sid
image/x-pcx pcx
image/x-pict pic pct
image/x-portable-anymap pnm
image/x-portable-bitmap pbm
image/x-portable-graymap pgm
image/x-portable-pixmap ppm
image/x-rgb rgb
image/x-tga tga
image/x-xbitmap xbm
image/x-xpixmap xpm
image/x-xwindowdump xwd
# message/cpim
# message/delivery-status
# message/disposition-notification
# message/example
# message/external-body
# message/feedback-report
# message/global
# message/global-delivery-status
# message/global-disposition-notification
# message/global-headers
# message/http
# message/imdn+xml
# message/news
# message/partial
message/rfc822 eml mime
# message/s-http
# message/sip
# message/sipfrag
# message/tracking-status
# message/vnd.si.simp
# model/example
model/iges igs iges
model/mesh msh mesh silo
model/vnd.collada+xml dae
model/vnd.dwf dwf
# model/vnd.flatland.3dml
model/vnd.gdl gdl
# model/vnd.gs-gdl
# model/vnd.gs.gdl
model/vnd.gtw gtw
# model/vnd.moml+xml
model/vnd.mts mts
# model/vnd.parasolid.transmit.binary
# model/vnd.parasolid.transmit.text
model/vnd.vtu vtu
model/vrml wrl vrml
model/x3d+binary x3db x3dbz
model/x3d+vrml x3dv x3dvz
model/x3d+xml x3d x3dz
# multipart/alternative
# multipart/appledouble
# multipart/byteranges
# multipart/digest
# multipart/encrypted
# multipart/example
# multipart/form-data
# multipart/header-set
# multipart/mixed
# multipart/parallel
# multipart/related
# multipart/report
# multipart/signed
# multipart/voice-message
# text/1d-interleaved-parityfec
text/cache-manifest appcache
text/calendar ics ifb
text/css css
text/csv csv
# text/directory
# text/dns
# text/ecmascript
# text/enriched
# text/example
# text/fwdred
text/html html htm
# text/javascript
text/n3 n3
# text/parityfec
text/plain txt text conf def list log in
# text/prs.fallenstein.rst
text/prs.lines.tag dsc
# text/vnd.radisys.msml-basic-layout
# text/red
# text/rfc822-headers
text/richtext rtx
# text/rtf
# text/rtp-enc-aescm128
# text/rtx
text/sgml sgml sgm
# text/t140
text/tab-separated-values tsv
text/troff t tr roff man me ms
text/turtle ttl
# text/ulpfec
text/uri-list uri uris urls
text/vcard vcard
# text/vnd.abc
text/vnd.curl curl
text/vnd.curl.dcurl dcurl
text/vnd.curl.scurl scurl
text/vnd.curl.mcurl mcurl
# text/vnd.dmclientscript
text/vnd.dvb.subtitle sub
# text/vnd.esmertec.theme-descriptor
text/vnd.fly fly
text/vnd.fmi.flexstor flx
text/vnd.graphviz gv
text/vnd.in3d.3dml 3dml
text/vnd.in3d.spot spot
# text/vnd.iptc.newsml
# text/vnd.iptc.nitf
# text/vnd.latex-z
# text/vnd.motorola.reflex
# text/vnd.ms-mediapackage
# text/vnd.net2phone.commcenter.command
# text/vnd.si.uricatalogue
text/vnd.sun.j2me.app-descriptor jad
# text/vnd.trolltech.linguist
# text/vnd.wap.si
# text/vnd.wap.sl
text/vnd.wap.wml wml
text/vnd.wap.wmlscript wmls
text/x-asm s asm
text/x-c c cc cxx cpp h hh dic
text/x-fortran f for f77 f90
text/x-java-source java
text/x-opml opml
text/x-pascal p pas
text/x-nfo nfo
text/x-setext etx
text/x-sfv sfv
text/x-uuencode uu
text/x-vcalendar vcs
text/x-vcard vcf
# text/xml
# text/xml-external-parsed-entity
# video/1d-interleaved-parityfec
video/3gpp 3gp
# video/3gpp-tt
video/3gpp2 3g2
# video/bmpeg
# video/bt656
# video/celb
# video/dv
# video/example
video/h261 h261
video/h263 h263
# video/h263-1998
# video/h263-2000
video/h264 h264
# video/h264-rcdo
# video/h264-svc
video/jpeg jpgv
# video/jpeg2000
video/jpm jpm jpgm
video/mj2 mj2 mjp2
# video/mp1s
# video/mp2p
# video/mp2t
video/mp4 mp4 mp4v mpg4
# video/mp4v-es
video/mpeg mpeg mpg mpe m1v m2v
# video/mpeg4-generic
# video/mpv
# video/nv
video/ogg ogv
# video/parityfec
# video/pointer
video/quicktime qt mov
# video/raw
# video/rtp-enc-aescm128
# video/rtx
# video/smpte292m
# video/ulpfec
# video/vc1
# video/vnd.cctv
video/vnd.dece.hd uvh uvvh
video/vnd.dece.mobile uvm uvvm
# video/vnd.dece.mp4
video/vnd.dece.pd uvp uvvp
video/vnd.dece.sd uvs uvvs
video/vnd.dece.video uvv uvvv
# video/vnd.directv.mpeg
# video/vnd.directv.mpeg-tts
# video/vnd.dlna.mpeg-tts
video/vnd.dvb.file dvb
video/vnd.fvt fvt
# video/vnd.hns.video
# video/vnd.iptvforum.1dparityfec-1010
# video/vnd.iptvforum.1dparityfec-2005
# video/vnd.iptvforum.2dparityfec-1010
# video/vnd.iptvforum.2dparityfec-2005
# video/vnd.iptvforum.ttsavc
# video/vnd.iptvforum.ttsmpeg2
# video/vnd.motorola.video
# video/vnd.motorola.videop
video/vnd.mpegurl mxu m4u
video/vnd.ms-playready.media.pyv pyv
# video/vnd.nokia.interleaved-multimedia
# video/vnd.nokia.videovoip
# video/vnd.objectvideo
# video/vnd.sealed.mpeg1
# video/vnd.sealed.mpeg4
# video/vnd.sealed.swf
# video/vnd.sealedmedia.softseal.mov
video/vnd.uvvu.mp4 uvu uvvu
video/vnd.vivo viv
video/webm webm
video/x-f4v f4v
video/x-fli fli
video/x-flv flv
video/x-m4v m4v
video/x-matroska mkv mk3d mks
video/x-mng mng
video/x-ms-asf asf asx
video/x-ms-vob vob
video/x-ms-wm wm
video/x-ms-wmv wmv
video/x-ms-wmx wmx
video/x-ms-wvx wvx
video/x-msvideo avi
video/x-sgi-movie movie
video/x-smv smv
x-conference/x-cooltalk ice
# What: WebVTT
# Why: To allow formats intended for marking up external text track resources.
# http://dev.w3.org/html5/webvtt/
# Added by: niftylettuce
text/vtt vtt
# What: Google Chrome Extension
# Why: To allow apps to (work) be served with the right content type header.
# http://codereview.chromium.org/2830017
# Added by: niftylettuce
application/x-chrome-extension crx
# What: HTC support
# Why: To properly render .htc files such as CSS3PIE
# Added by: niftylettuce
text/x-component htc
# What: HTML5 application cache manifes ('.manifest' extension)
# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps
# per https://developer.mozilla.org/en/offline_resources_in_firefox
# Added by: louisremi
text/cache-manifest manifest
# What: node binary buffer format
# Why: semi-standard extension w/in the node community
# Added by: tootallnate
application/octet-stream buffer
# What: The "protected" MP-4 formats used by iTunes.
# Why: Required for streaming music to browsers (?)
# Added by: broofa
application/mp4 m4p
audio/mp4 m4a
# What: Video format, Part of RFC1890
# Why: See https://github.com/bentomas/node-mime/pull/6
# Added by: mjrusso
video/MP2T ts
# What: EventSource mime type
# Why: mime type of Server-Sent Events stream
# http://www.w3.org/TR/eventsource/#text-event-stream
# Added by: francois2metz
text/event-stream event-stream
# What: Mozilla App manifest mime type
# Why: https://developer.mozilla.org/en/Apps/Manifest#Serving_manifests
# Added by: ednapiranha
application/x-web-app-manifest+json webapp
# What: Lua file types
# Why: Googling around shows de-facto consensus on these
# Added by: creationix (Issue #45)
text/x-lua lua
application/x-lua-bytecode luac
# What: Markdown files, as per http://daringfireball.net/projects/markdown/syntax
# Why: http://stackoverflow.com/questions/10701983/what-is-the-mime-type-for-markdown
# Added by: avoidwork
text/x-markdown markdown md mkd
# What: ini files
# Why: because they're just text files
# Added by: Matthew Kastor
text/plain ini
# What: DASH Adaptive Streaming manifest
# Why: https://developer.mozilla.org/en-US/docs/DASH_Adaptive_Streaming_for_HTML_5_Video
# Added by: eelcocramer
application/dash+xml mdp
# What: OpenType font files - http://www.microsoft.com/typography/otspec/
# Why: Browsers usually ignore the font MIME types and sniff the content,
# but Chrome, shows a warning if OpenType fonts aren't served with
# the `font/opentype` MIME type: http://i.imgur.com/8c5RN8M.png.
# Added by: alrra
font/opentype otf
{
"name": "type-is",
"description": "Infer the content type if a request",
"version": "1.1.0",
"author": {
"name": "Jonathan Ong",
"email": "[email protected]",
"url": "http://jongleberry.com"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/expressjs/type-is"
},
"dependencies": {
"mime": "~1.2.11"
},
"devDependencies": {
"mocha": "*",
"should": "*"
},
"scripts": {
"test": "mocha --require should --reporter spec --bail"
},
"readme": "# Type Is [![Build Status](https://travis-ci.org/expressjs/type-is.png)](https://travis-ci.org/expressjs/type-is)\n\nInfer the content type of a request. \nExtracted from [koa](https://github.com/koajs/koa) for general use.\n\nHere's an example body parser:\n\n```js\nvar is = require('type-is');\nvar parse = require('body');\nvar busboy = require('busboy');\n\nfunction bodyParser(req, res, next) {\n var hasRequestBody = 'content-type' in req.headers\n || 'transfer-encoding' in req.headers;\n if (!hasRequestBody) return next();\n \n switch (is(req, ['urlencoded', 'json', 'multipart'])) {\n case 'urlencoded':\n // parse urlencoded body\n break\n case 'json':\n // parse json body\n break\n case 'multipart':\n // parse multipart body\n break\n default:\n // 415 error code\n }\n}\n```\n\n## API\n\n### var type = is(request, types)\n\n```js\nvar is = require('type-is')\n\nhttp.createServer(function (req, res) {\n is(req, ['text/*'])\n})\n```\n\n`request` is the node HTTP request. `types` is an array of types. Each type can be:\n\n- An extension name such as `json`. This name will be returned if matched.\n- A mime type such as `application/json`.\n- A mime type with a wildcard such as `*/json` or `application/*`. The full mime type will be returned if matched\n\n`false` will be returned if no type matches.\n\nExamples:\n\n```js\n// req.headers.content-type = 'application/json'\nis(req, ['json']) // -> 'json'\nis(req, ['html', 'json']) // -> 'json'\nis(req, ['application/*']) // -> 'application/json'\nis(req, ['application/json']) // -> 'application/json'\nis(req, ['html']) // -> false\n```\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 Jonathan Ong [email protected]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n",
"readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/expressjs/type-is/issues"
},
"homepage": "https://github.com/expressjs/type-is",
"_id": "[email protected]",
"dist": {
"shasum": "a595b3f01c7851e8c33dcb39f5233c9a0378272b"
},
"_from": "type-is@~1.1.0",
"_resolved": "https://registry.npmjs.org/type-is/-/type-is-1.1.0.tgz"
}

Type Is Build Status

Infer the content type of a request. Extracted from koa for general use.

Here's an example body parser:

var is = require('type-is');
var parse = require('body');
var busboy = require('busboy');

function bodyParser(req, res, next) {
  var hasRequestBody = 'content-type' in req.headers
    || 'transfer-encoding' in req.headers;
  if (!hasRequestBody) return next();
  
  switch (is(req, ['urlencoded', 'json', 'multipart'])) {
    case 'urlencoded':
      // parse urlencoded body
      break
    case 'json':
      // parse json body
      break
    case 'multipart':
      // parse multipart body
      break
    default:
      // 415 error code
  }
}

API

var type = is(request, types)

var is = require('type-is')

http.createServer(function (req, res) {
  is(req, ['text/*'])
})

request is the node HTTP request. types is an array of types. Each type can be:

  • An extension name such as json. This name will be returned if matched.
  • A mime type such as application/json.
  • A mime type with a wildcard such as */json or application/*. The full mime type will be returned if matched

false will be returned if no type matches.

Examples:

// req.headers.content-type = 'application/json'
is(req, ['json']) // -> 'json'
is(req, ['html', 'json']) // -> 'json'
is(req, ['application/*']) // -> 'application/json'
is(req, ['application/json']) // -> 'application/json'
is(req, ['html']) // -> false

License

The MIT License (MIT)

Copyright (c) 2013 Jonathan Ong [email protected]

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.

{
"name": "body-parser",
"description": "Connect's body parsing middleware",
"version": "1.0.2",
"author": {
"name": "Jonathan Ong",
"email": "[email protected]",
"url": "http://jongleberry.com"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/expressjs/body-parser"
},
"dependencies": {
"type-is": "~1.1.0",
"raw-body": "~1.1.2",
"qs": "~0.6.6"
},
"devDependencies": {
"connect": "*",
"mocha": "*",
"should": "*",
"supertest": "*"
},
"scripts": {
"test": "make test"
},
"readme": "# Body Parser [![Build Status](https://travis-ci.org/expressjs/body-parser.png)](https://travis-ci.org/expressjs/body-parser)\n\nConnect's body parsing middleware.\n\n## API\n\n```js\nvar bodyParser = require('body-parser');\n\nvar app = connect();\n\napp.use(bodyParser());\n\napp.use(function (req, res, next) {\n console.log(req.body) // populated!\n next();\n})\n```\n\n### bodyParser([options])\n\nReturns middleware that parses both `json` and `urlencoded`. The `options` are passed to both middleware.\n\n### bodyParser.json([options])\n\nReturns middleware that only parses `json`. The options are:\n\n- `strict` <true> - only parse objects and arrays\n- `limit` <1mb> - maximum request body size\n- `reviver` - passed to `JSON.parse()`\n\n### bodyParser.urlencoded([options])\n\nReturns middleware that only parses `urlencoded` with the [qs](https://github.com/visionmedia/node-querystring) module. The options are:\n\n- `limit` <1mb> - maximum request body size\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Jonathan Ong [email protected]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n",
"readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/expressjs/body-parser/issues"
},
"homepage": "https://github.com/expressjs/body-parser",
"_id": "[email protected]",
"_from": "body-parser@~1.0.0"
}

Body Parser Build Status

Connect's body parsing middleware.

API

var bodyParser = require('body-parser');

var app = connect();

app.use(bodyParser());

app.use(function (req, res, next) {
  console.log(req.body) // populated!
  next();
})

bodyParser([options])

Returns middleware that parses both json and urlencoded. The options are passed to both middleware.

bodyParser.json([options])

Returns middleware that only parses json. The options are:

  • strict - only parse objects and arrays
  • limit <1mb> - maximum request body size
  • reviver - passed to JSON.parse()

bodyParser.urlencoded([options])

Returns middleware that only parses urlencoded with the qs module. The options are:

  • limit <1mb> - maximum request body size

License

The MIT License (MIT)

Copyright (c) 2014 Jonathan Ong [email protected]

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.

/**
* Expose `debug()` as the module.
*/
module.exports = debug;
/**
* Create a debugger with the given `name`.
*
* @param {String} name
* @return {Type}
* @api public
*/
function debug(name) {
if (!debug.enabled(name)) return function () {
};
return function (fmt) {
fmt = coerce(fmt);
var curr = new Date;
var ms = curr - (debug[name] || curr);
debug[name] = curr;
fmt = name
+ ' '
+ fmt
+ ' +' + debug.humanize(ms);
// This hackery is required for IE8
// where `console.log` doesn't have 'apply'
window.console
&& console.log
&& Function.prototype.apply.call(console.log, console, arguments);
}
}
/**
* The currently active debug mode names.
*/
debug.names = [];
debug.skips = [];
/**
* Enables a debug mode by name. This can include modes
* separated by a colon and wildcards.
*
* @param {String} name
* @api public
*/
debug.enable = function (name) {
try {
localStorage.debug = name;
} catch (e) {
}
var split = (name || '').split(/[\s,]+/)
, len = split.length;
for (var i = 0; i < len; i++) {
name = split[i].replace('*', '.*?');
if (name[0] === '-') {
debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
}
else {
debug.names.push(new RegExp('^' + name + '$'));
}
}
};
/**
* Disable debug output.
*
* @api public
*/
debug.disable = function () {
debug.enable('');
};
/**
* Humanize the given `ms`.
*
* @param {Number} m
* @return {String}
* @api private
*/
debug.humanize = function (ms) {
var sec = 1000
, min = 60 * 1000
, hour = 60 * min;
if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
if (ms >= min) return (ms / min).toFixed(1) + 'm';
if (ms >= sec) return (ms / sec | 0) + 's';
return ms + 'ms';
};
/**
* Returns true if the given mode name is enabled, false otherwise.
*
* @param {String} name
* @return {Boolean}
* @api public
*/
debug.enabled = function (name) {
for (var i = 0, len = debug.skips.length; i < len; i++) {
if (debug.skips[i].test(name)) {
return false;
}
}
for (var i = 0, len = debug.names.length; i < len; i++) {
if (debug.names[i].test(name)) {
return true;
}
}
return false;
};
/**
* Coerce `val`.
*/
function coerce(val) {
if (val instanceof Error) return val.stack || val.message;
return val;
}
// persist
try {
if (window.localStorage) debug.enable(localStorage.debug);
} catch (e) {
}
if ('undefined' == typeof window) {
module.exports = require('./lib/debug');
} else {
module.exports = require('./debug');
}
/**
* Module dependencies.
*/
var tty = require('tty');
/**
* Expose `debug()` as the module.
*/
module.exports = debug;
/**
* Enabled debuggers.
*/
var names = []
, skips = [];
(process.env.DEBUG || '')
.split(/[\s,]+/)
.forEach(function (name) {
name = name.replace('*', '.*?');
if (name[0] === '-') {
skips.push(new RegExp('^' + name.substr(1) + '$'));
} else {
names.push(new RegExp('^' + name + '$'));
}
});
/**
* Colors.
*/
var colors = [6, 2, 3, 4, 5, 1];
/**
* Previous debug() call.
*/
var prev = {};
/**
* Previously assigned color.
*/
var prevColor = 0;
/**
* Is stdout a TTY? Colored output is disabled when `true`.
*/
var isatty = tty.isatty(2);
/**
* Select a color.
*
* @return {Number}
* @api private
*/
function color() {
return colors[prevColor++ % colors.length];
}
/**
* Humanize the given `ms`.
*
* @param {Number} m
* @return {String}
* @api private
*/
function humanize(ms) {
var sec = 1000
, min = 60 * 1000
, hour = 60 * min;
if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
if (ms >= min) return (ms / min).toFixed(1) + 'm';
if (ms >= sec) return (ms / sec | 0) + 's';
return ms + 'ms';
}
/**
* Create a debugger with the given `name`.
*
* @param {String} name
* @return {Type}
* @api public
*/
function debug(name) {
function disabled() {
}
disabled.enabled = false;
var match = skips.some(function (re) {
return re.test(name);
});
if (match) return disabled;
match = names.some(function (re) {
return re.test(name);
});
if (!match) return disabled;
var c = color();
function colored(fmt) {
fmt = coerce(fmt);
var curr = new Date;
var ms = curr - (prev[name] || curr);
prev[name] = curr;
fmt = ' \u001b[9' + c + 'm' + name + ' '
+ '\u001b[3' + c + 'm\u001b[90m'
+ fmt + '\u001b[3' + c + 'm'
+ ' +' + humanize(ms) + '\u001b[0m';
console.error.apply(this, arguments);
}
function plain(fmt) {
fmt = coerce(fmt);
fmt = new Date().toUTCString()
+ ' ' + name + ' ' + fmt;
console.error.apply(this, arguments);
}
colored.enabled = plain.enabled = true;
return isatty || process.env.DEBUG_COLORS
? colored
: plain;
}
/**
* Coerce `val`.
*/
function coerce(val) {
if (val instanceof Error) return val.stack || val.message;
return val;
}
{
"name": "debug",
"version": "0.7.4",
"repository": {
"type": "git",
"url": "git://github.com/visionmedia/debug.git"
},
"description": "small debugging utility",
"keywords": [
"debug",
"log",
"debugger"
],
"author": {
"name": "TJ Holowaychuk",
"email": "[email protected]"
},
"dependencies": {},
"devDependencies": {
"mocha": "*"
},
"main": "lib/debug.js",
"browser": "./debug.js",
"engines": {
"node": "*"
},
"files": [
"lib/debug.js",
"debug.js",
"index.js"
],
"component": {
"scripts": {
"debug/index.js": "index.js",
"debug/debug.js": "debug.js"
}
},
"readme": "# debug\n\n tiny node.js debugging utility modelled after node core's debugging technique.\n\n## Installation\n\n```\n$ npm install debug\n```\n\n## Usage\n\n With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.\n \nExample _app.js_:\n\n```js\nvar debug = require('debug')('http')\n , http = require('http')\n , name = 'My App';\n\n// fake app\n\ndebug('booting %s', name);\n\nhttp.createServer(function(req, res){\n debug(req.method + ' ' + req.url);\n res.end('hello\\n');\n}).listen(3000, function(){\n debug('listening');\n});\n\n// fake worker of some kind\n\nrequire('./worker');\n```\n\nExample _worker.js_:\n\n```js\nvar debug = require('debug')('worker');\n\nsetInterval(function(){\n debug('doing some work');\n}, 1000);\n```\n\n The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:\n\n ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)\n\n ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)\n\n## Millisecond diff\n\n When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the \"+NNNms\" will show you how much time was spent between calls.\n\n ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)\n\n When stderr is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:\n _(NOTE: Debug now uses stderr instead of stdout, so the correct shell command for this example is actually `DEBUG=* node example/worker 2> out &`)_\n \n ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)\n \n## Conventions\n\n If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use \":\" to separate features. For example \"bodyParser\" from Connect would then be \"connect:bodyParser\". \n\n## Wildcards\n\n The \"*\" character may be used as a wildcard. Suppose for example your library has debuggers named \"connect:bodyParser\", \"connect:compress\", \"connect:session\", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.\n\n You can also exclude specific debuggers by prefixing them with a \"-\" character. For example, `DEBUG=* -connect:*` would include all debuggers except those starting with \"connect:\".\n\n## Browser support\n\n Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. \n\n```js\na = debug('worker:a');\nb = debug('worker:b');\n\nsetInterval(function(){\n a('doing some work');\n}, 1000);\n\nsetInterval(function(){\n a('doing some work');\n}, 1200);\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk &lt;[email protected]&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
"readmeFilename": "Readme.md",
"bugs": {
"url": "https://github.com/visionmedia/debug/issues"
},
"homepage": "https://github.com/visionmedia/debug",
"_id": "[email protected]",
"_from": "debug@~0.7.4"
}

debug

tiny node.js debugging utility modelled after node core's debugging technique.

Installation

$ npm install debug

Usage

With debug you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated console.error, so all of the console format string goodies you're used to work fine. A unique color is selected per-function for visibility.

Example app.js:

var debug = require('debug')('http')
  , http = require('http')
  , name = 'My App';

// fake app

debug('booting %s', name);

http.createServer(function(req, res){
  debug(req.method + ' ' + req.url);
  res.end('hello\n');
}).listen(3000, function(){
  debug('listening');
});

// fake worker of some kind

require('./worker');

Example worker.js:

var debug = require('debug')('worker');

setInterval(function(){
  debug('doing some work');
}, 1000);

The DEBUG environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:

debug http and worker

debug worker

Millisecond diff

When actively developing an application it can be useful to see when the time spent between one debug() call and the next. Suppose for example you invoke debug() before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.

When stderr is not a TTY, Date#toUTCString() is used, making it more useful for logging the debug information as shown below: (NOTE: Debug now uses stderr instead of stdout, so the correct shell command for this example is actually DEBUG=* node example/worker 2> out &)

Conventions

If you're using this in one or more of your libraries, you should use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you should prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".

Wildcards

The "*" character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with DEBUG=connect:bodyParser,connect.compress,connect:session, you may simply do DEBUG=connect:*, or to run everything using this module simply use DEBUG=*.

You can also exclude specific debuggers by prefixing them with a "-" character. For example, DEBUG=* -connect:* would include all debuggers except those starting with "connect:".

Browser support

Debug works in the browser as well, currently persisted by localStorage. For example if you have worker:a and worker:b as shown below, and wish to debug both type debug.enable('worker:*') in the console and refresh the page, this will remain until you disable with debug.disable().

a = debug('worker:a');
b = debug('worker:b');

setInterval(function(){
  a('doing some work');
}, 1000);

setInterval(function(){
  a('doing some work');
}, 1200);

License

(The MIT License)

Copyright (c) 2011 TJ Holowaychuk <[email protected]>

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.

.git*
benchmarks/
docs/
examples/
support/
test/
testing.js
.DS_Store
.travis.yml
coverage.html
lib-cov

4.2.0 / 2014-05-11

  • deprecate app.del() -- use app.delete() instead
  • deprecate res.json(obj, status) -- use res.json(status, obj) instead
    • the edge-case res.json(status, num) requires res.status(status).json(num)
  • deprecate res.jsonp(obj, status) -- use res.jsonp(status, obj) instead
    • the edge-case res.jsonp(status, num) requires res.status(status).jsonp(num)
  • fix req.next when inside router instance
  • include ETag header in HEAD requests
  • keep previous Content-Type for res.jsonp
  • support PURGE method
    • add app.purge
    • add router.purge
    • include PURGE in app.all
  • update debug to 0.8.0
    • add enable() method
    • change from stderr to stdout
  • update methods to 1.0.0
    • add PURGE

4.1.2 / 2014-05-08

  • fix req.host for IPv6 literals
  • fix res.jsonp error if callback param is object

4.1.1 / 2014-04-27

  • fix package.json to reflect supported node version

4.1.0 / 2014-04-24

  • pass options from res.sendfile to send
  • preserve casing of headers in res.header and res.set
  • support unicode file names in res.attachment and res.download
  • update accepts to 1.0.1
  • update cookie to 0.1.2
    • Fix for maxAge == 0
    • made compat with expires field
  • update send to 0.3.0
    • Accept API options in options object
    • Coerce option types
    • Control whether to generate etags
    • Default directory access to 403 when index disabled
    • Fix sending files with dots without root set
    • Include file path in etag
    • Make "Can't set headers after they are sent." catchable
    • Send full entity-body for multi range requests
    • Set etags to "weak"
    • Support "If-Range" header
    • Support multiple index paths
    • deps: [email protected]
  • update serve-static to 1.1.0
    • Accept options directly to send module
    • Resolve relative paths at middleware setup
    • Use parseurl to parse the URL from request
    • deps: [email protected]
  • update type-is to 1.1.0
    • add non-array values support
    • add multipart as a shorthand

4.0.0 / 2014-04-09

  • remove:
    • node 0.8 support
    • connect and connect's patches except for charset handling
    • express(1) - moved to express-generator
    • express.createServer() - it has been deprecated for a long time. Use express()
    • app.configure - use logic in your own app code
    • app.router - is removed
    • req.auth - use basic-auth instead
    • req.accepted* - use req.accepts*() instead
    • res.location - relative URL resolution is removed
    • res.charset - include the charset in the content type when using res.set()
    • all bundled middleware except static
  • change:
    • app.route -> app.mountpath when mounting an express app in another express app
    • json spaces no longer enabled by default in development
    • req.accepts* -> req.accepts*s - i.e. req.acceptsEncoding -> req.acceptsEncodings
    • req.params is now an object instead of an array
    • res.locals is no longer a function. It is a plain js object. Treat it as such.
    • res.headerSent -> res.headersSent to match node.js ServerResponse object
  • refactor:
  • add:
    • app.router() - returns the app Router instance
    • app.route() - Proxy to the app's Router#route() method to create a new route
    • Router & Route - public API

3.6.0 / 2014-05-09

  • deprecate app.del() -- use app.delete() instead
  • deprecate res.json(obj, status) -- use res.json(status, obj) instead
    • the edge-case res.json(status, num) requires res.status(status).json(num)
  • deprecate res.jsonp(obj, status) -- use res.jsonp(status, obj) instead
    • the edge-case res.jsonp(status, num) requires res.status(status).jsonp(num)
  • support PURGE method
    • add app.purge
    • add router.purge
    • include PURGE in app.all
  • update connect to 2.15.0
  • update debug to 0.8.0
    • add enable() method
    • change from stderr to stdout
  • update methods to 1.0.0
    • add PURGE
  • update mkdirp to 0.5.0

3.5.3 / 2014-05-08

  • fix req.host for IPv6 literals
  • fix res.jsonp error if callback param is object

3.5.2 / 2014-04-24

  • update connect to 2.14.5
  • update cookie to 0.1.2
  • update mkdirp to 0.4.0
  • update send to 0.3.0

3.5.1 / 2014-03-25

  • pin less-middleware in generated app

3.5.0 / 2014-03-06

  • bump deps

3.4.8 / 2014-01-13

  • prevent incorrect automatic OPTIONS responses #1868 @dpatti
  • update binary and examples for jade 1.0 #1876 @yossi, #1877 @reqshark, #1892 @matheusazzi
  • throw 400 in case of malformed paths @rlidwka

3.4.7 / 2013-12-10

  • update connect

3.4.6 / 2013-12-01

  • update connect (raw-body)

3.4.5 / 2013-11-27

  • update connect
  • res.location: remove leading ./ #1802 @kapouer
  • res.redirect: fix `res.redirect('toString') #1829 @michaelficarra
  • res.send: always send ETag when content-length > 0
  • router: add Router.all() method

3.4.4 / 2013-10-29

  • update connect
  • update supertest
  • update methods
  • express(1): replace bodyParser() with urlencoded() and json() #1795 @chirag04

3.4.3 / 2013-10-23

  • update connect

3.4.2 / 2013-10-18

  • update connect
  • downgrade commander

3.4.1 / 2013-10-15

  • update connect
  • update commander
  • jsonp: check if callback is a function
  • router: wrap encodeURIComponent in a try/catch #1735 (@lxe)
  • res.format: now includes chraset @1747 (@sorribas)
  • res.links: allow multiple calls @1746 (@sorribas)

3.4.0 / 2013-09-07

  • add res.vary(). Closes #1682
  • update connect

3.3.8 / 2013-09-02

  • update connect

3.3.7 / 2013-08-28

  • update connect

3.3.6 / 2013-08-27

  • Revert "remove charset from json responses. Closes #1631" (causes issues in some clients)
  • add: req.accepts take an argument list

3.3.4 / 2013-07-08

  • update send and connect

3.3.3 / 2013-07-04

  • update connect

3.3.2 / 2013-07-03

  • update connect
  • update send
  • remove .version export

3.3.1 / 2013-06-27

  • update connect

3.3.0 / 2013-06-26

  • update connect
  • add support for multiple X-Forwarded-Proto values. Closes #1646
  • change: remove charset from json responses. Closes #1631
  • change: return actual booleans from req.accept* functions
  • fix jsonp callback array throw

3.2.6 / 2013-06-02

  • update connect

3.2.5 / 2013-05-21

  • update connect
  • update node-cookie
  • add: throw a meaningful error when there is no default engine
  • change generation of ETags with res.send() to GET requests only. Closes #1619

3.2.4 / 2013-05-09

  • fix req.subdomains when no Host is present
  • fix req.host when no Host is present, return undefined

3.2.3 / 2013-05-07

  • update connect / qs

3.2.2 / 2013-05-03

  • update qs

3.2.1 / 2013-04-29

  • add app.VERB() paths array deprecation warning
  • update connect
  • update qs and remove all ~ semver crap
  • fix: accept number as value of Signed Cookie

3.2.0 / 2013-04-15

  • add "view" constructor setting to override view behaviour
  • add req.acceptsEncoding(name)
  • add req.acceptedEncodings
  • revert cookie signature change causing session race conditions
  • fix sorting of Accept values of the same quality

3.1.2 / 2013-04-12

  • add support for custom Accept parameters
  • update cookie-signature

3.1.1 / 2013-04-01

  • add X-Forwarded-Host support to req.host
  • fix relative redirects
  • update mkdirp
  • update buffer-crc32
  • remove legacy app.configure() method from app template.

3.1.0 / 2013-01-25

  • add support for leading "." in "view engine" setting
  • add array support to res.set()
  • add node 0.8.x to travis.yml
  • add "subdomain offset" setting for tweaking req.subdomains
  • add res.location(url) implementing res.redirect()-like setting of Location
  • use app.get() for x-powered-by setting for inheritance
  • fix colons in passwords for req.auth

3.0.6 / 2013-01-04

  • add http verb methods to Router
  • update connect
  • fix mangling of the res.cookie() options object
  • fix jsonp whitespace escape. Closes #1132

3.0.5 / 2012-12-19

  • add throwing when a non-function is passed to a route
  • fix: explicitly remove Transfer-Encoding header from 204 and 304 responses
  • revert "add 'etag' option"

3.0.4 / 2012-12-05

  • add 'etag' option to disable res.send() Etags
  • add escaping of urls in text/plain in res.redirect() for old browsers interpreting as html
  • change crc32 module for a more liberal license
  • update connect

3.0.3 / 2012-11-13

  • update connect
  • update cookie module
  • fix cookie max-age

3.0.2 / 2012-11-08

  • add OPTIONS to cors example. Closes #1398
  • fix route chaining regression. Closes #1397

3.0.1 / 2012-11-01

  • update connect

3.0.0 / 2012-10-23

  • add make clean
  • add "Basic" check to req.auth
  • add req.auth test coverage
  • add cb && cb(payload) to res.jsonp(). Closes #1374
  • add backwards compat for res.redirect() status. Closes #1336
  • add support for res.json() to retain previously defined Content-Types. Closes #1349
  • update connect
  • change res.redirect() to utilize a pathname-relative Location again. Closes #1382
  • remove non-primitive string support for res.send()
  • fix view-locals example. Closes #1370
  • fix route-separation example

3.0.0rc5 / 2012-09-18

  • update connect
  • add redis search example
  • add static-files example
  • add "x-powered-by" setting (app.disable('x-powered-by'))
  • add "application/octet-stream" redirect Accept test case. Closes #1317

3.0.0rc4 / 2012-08-30

  • add res.jsonp(). Closes #1307
  • add "verbose errors" option to error-pages example
  • add another route example to express(1) so people are not so confused
  • add redis online user activity tracking example
  • update connect dep
  • fix etag quoting. Closes #1310
  • fix error-pages 404 status
  • fix jsonp callback char restrictions
  • remove old OPTIONS default response

3.0.0rc3 / 2012-08-13

  • update connect dep
  • fix signed cookies to work with connect.cookieParser() ("s:" prefix was missing) [tnydwrds]
  • fix res.render() clobbering of "locals"

3.0.0rc2 / 2012-08-03

  • add CORS example
  • update connect dep
  • deprecate .createServer() & remove old stale examples
  • fix: escape res.redirect() link
  • fix vhost example

3.0.0rc1 / 2012-07-24

  • add more examples to view-locals
  • add scheme-relative redirects (res.redirect("//foo.com")) support
  • update cookie dep
  • update connect dep
  • update send dep
  • fix express(1) -h flag, use -H for hogan. Closes #1245
  • fix res.sendfile() socket error handling regression

3.0.0beta7 / 2012-07-16

  • update connect dep for send() root normalization regression

3.0.0beta6 / 2012-07-13

  • add err.view property for view errors. Closes #1226
  • add "jsonp callback name" setting
  • add support for "/foo/:bar*" non-greedy matches
  • change res.sendfile() to use send() module
  • change res.send to use "response-send" module
  • remove app.locals.use and res.locals.use, use regular middleware

3.0.0beta5 / 2012-07-03

  • add "make check" support
  • add route-map example
  • add res.json(obj, status) support back for BC
  • add "methods" dep, remove internal methods module
  • update connect dep
  • update auth example to utilize cores pbkdf2
  • updated tests to use "supertest"

3.0.0beta4 / 2012-06-25

  • Added req.auth
  • Added req.range(size)
  • Added res.links(obj)
  • Added res.send(body, status) support back for backwards compat
  • Added .default() support to res.format()
  • Added 2xx / 304 check to req.fresh
  • Revert "Added + support to the router"
  • Fixed res.send() freshness check, respect res.statusCode

3.0.0beta3 / 2012-06-15

  • Added hogan --hjs to express(1) [nullfirm]
  • Added another example to content-negotiation
  • Added fresh dep
  • Changed: res.send() always checks freshness
  • Fixed: expose connects mime module. Cloases #1165

3.0.0beta2 / 2012-06-06

  • Added + support to the router
  • Added req.host
  • Changed req.param() to check route first
  • Update connect dep

3.0.0beta1 / 2012-06-01

  • Added res.format() callback to override default 406 behaviour
  • Fixed res.redirect() 406. Closes #1154

3.0.0alpha5 / 2012-05-30

  • Added req.ip
  • Added { signed: true } option to res.cookie()
  • Removed res.signedCookie()
  • Changed: dont reverse req.ips
  • Fixed "trust proxy" setting check for req.ips

3.0.0alpha4 / 2012-05-09

  • Added: allow [] in jsonp callback. Closes #1128
  • Added PORT env var support in generated template. Closes #1118 [benatkin]
  • Updated: connect 2.2.2

3.0.0alpha3 / 2012-05-04

  • Added public app.routes. Closes #887
  • Added view-locals example
  • Added mvc example
  • Added res.locals.use(). Closes #1120
  • Added conditional-GET support to res.send()
  • Added: coerce res.set() values to strings
  • Changed: moved static() in generated apps below router
  • Changed: res.send() only set ETag when not previously set
  • Changed connect 2.2.1 dep
  • Changed: make test now runs unit / acceptance tests
  • Fixed req/res proto inheritance

3.0.0alpha2 / 2012-04-26

  • Added make benchmark back
  • Added res.send() support for String objects
  • Added client-side data exposing example
  • Added res.header() and req.header() aliases for BC
  • Added express.createServer() for BC
  • Perf: memoize parsed urls
  • Perf: connect 2.2.0 dep
  • Changed: make expressInit() middleware self-aware
  • Fixed: use app.get() for all core settings
  • Fixed redis session example
  • Fixed session example. Closes #1105
  • Fixed generated express dep. Closes #1078

3.0.0alpha1 / 2012-04-15

  • Added app.locals.use(callback)
  • Added app.locals object
  • Added app.locals(obj)
  • Added res.locals object
  • Added res.locals(obj)
  • Added res.format() for content-negotiation
  • Added app.engine()
  • Added res.cookie() JSON cookie support
  • Added "trust proxy" setting
  • Added req.subdomains
  • Added req.protocol
  • Added req.secure
  • Added req.path
  • Added req.ips
  • Added req.fresh
  • Added req.stale
  • Added comma-delmited / array support for req.accepts()
  • Added debug instrumentation
  • Added res.set(obj)
  • Added res.set(field, value)
  • Added res.get(field)
  • Added app.get(setting). Closes #842
  • Added req.acceptsLanguage()
  • Added req.acceptsCharset()
  • Added req.accepted
  • Added req.acceptedLanguages
  • Added req.acceptedCharsets
  • Added "json replacer" setting
  • Added "json spaces" setting
  • Added X-Forwarded-Proto support to res.redirect(). Closes #92
  • Added --less support to express(1)
  • Added express.response prototype
  • Added express.request prototype
  • Added express.application prototype
  • Added app.path()
  • Added app.render()
  • Added res.type() to replace res.contentType()
  • Changed: res.redirect() to add relative support
  • Changed: enable "jsonp callback" by default
  • Changed: renamed "case sensitive routes" to "case sensitive routing"
  • Rewrite of all tests with mocha
  • Removed "root" setting
  • Removed res.redirect('home') support
  • Removed req.notify()
  • Removed app.register()
  • Removed app.redirect()
  • Removed app.is()
  • Removed app.helpers()
  • Removed app.dynamicHelpers()
  • Fixed res.sendfile() with non-GET. Closes #723
  • Fixed express(1) public dir for windows. Closes #866

2.5.9/ 2012-04-02

  • Added support for PURGE request method [pbuyle]
  • Fixed express(1) generated app app.address() before listening [mmalecki]

2.5.8 / 2012-02-08

  • Update mkdirp dep. Closes #991

2.5.7 / 2012-02-06

  • Fixed app.all duplicate DELETE requests [mscdex]

2.5.6 / 2012-01-13

  • Updated hamljs dev dep. Closes #953

2.5.5 / 2012-01-08

  • Fixed: set filename on cached templates [matthewleon]

2.5.4 / 2012-01-02

  • Fixed express(1) eol on 0.4.x. Closes #947

2.5.3 / 2011-12-30

  • Fixed req.is() when a charset is present

2.5.2 / 2011-12-10

  • Fixed: express(1) LF -> CRLF for windows

2.5.1 / 2011-11-17

  • Changed: updated connect to 1.8.x
  • Removed sass.js support from express(1)

2.5.0 / 2011-10-24

  • Added ./routes dir for generated app by default
  • Added npm install reminder to express(1) app gen
  • Added 0.5.x support
  • Removed make test-cov since it wont work with node 0.5.x
  • Fixed express(1) public dir for windows. Closes #866

2.4.7 / 2011-10-05

  • Added mkdirp to express(1). Closes #795
  • Added simple json-config example
  • Added shorthand for the parsed request's pathname via req.path
  • Changed connect dep to 1.7.x to fix npm issue...
  • Fixed res.redirect() HEAD support. [reported by xerox]
  • Fixed req.flash(), only escape args
  • Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie]

2.4.6 / 2011-08-22

  • Fixed multiple param callback regression. Closes #824 [reported by TroyGoode]

2.4.5 / 2011-08-19

  • Added support for routes to handle errors. Closes #809
  • Added app.routes.all(). Closes #803
  • Added "basepath" setting to work in conjunction with reverse proxies etc.
  • Refactored Route to use a single array of callbacks
  • Added support for multiple callbacks for app.param(). Closes #801 Closes #805
  • Changed: removed .call(self) for route callbacks
  • Dependency: qs >= 0.3.1
  • Fixed res.redirect() on windows due to join() usage. Closes #808

2.4.4 / 2011-08-05

  • Fixed res.header() intention of a set, even when undefined
  • Fixed *, value no longer required
  • Fixed res.send(204) support. Closes #771

2.4.3 / 2011-07-14

  • Added docs for status option special-case. Closes #739
  • Fixed options.filename, exposing the view path to template engines

2.4.2. / 2011-07-06

  • Revert "removed jsonp stripping" for XSS

2.4.1 / 2011-07-06

  • Added res.json() JSONP support. Closes #737
  • Added extending-templates example. Closes #730
  • Added "strict routing" setting for trailing slashes
  • Added support for multiple envs in app.configure() calls. Closes #735
  • Changed: res.send() using res.json()
  • Changed: when cookie path === null don't default it
  • Changed; default cookie path to "home" setting. Closes #731
  • Removed pids/logs creation from express(1)

2.4.0 / 2011-06-28

  • Added chainable res.status(code)
  • Added res.json(), an explicit version of res.send(obj)
  • Added simple web-service example

2.3.12 / 2011-06-22

  • #express is now on freenode! come join!
  • Added req.get(field, param)
  • Added links to Japanese documentation, thanks @hideyukisaito!
  • Added; the express(1) generated app outputs the env
  • Added content-negotiation example
  • Dependency: connect >= 1.5.1 < 2.0.0
  • Fixed view layout bug. Closes #720
  • Fixed; ignore body on 304. Closes #701

2.3.11 / 2011-06-04

  • Added npm test
  • Removed generation of dummy test file from express(1)
  • Fixed; express(1) adds express as a dep
  • Fixed; prune on prepublish

2.3.10 / 2011-05-27

  • Added req.route, exposing the current route
  • Added package.json generation support to express(1)
  • Fixed call to app.param() function for optional params. Closes #682

2.3.9 / 2011-05-25

  • Fixed bug-ish with ../' in res.partial()` calls

2.3.8 / 2011-05-24

  • Fixed app.options()

2.3.7 / 2011-05-23

  • Added route Collection, ex: app.get('/user/:id').remove();
  • Added support for app.param(fn) to define param logic
  • Removed app.param() support for callback with return value
  • Removed module.parent check from express(1) generated app. Closes #670
  • Refactored router. Closes #639

2.3.6 / 2011-05-20

  • Changed; using devDependencies instead of git submodules
  • Fixed redis session example
  • Fixed markdown example
  • Fixed view caching, should not be enabled in development

2.3.5 / 2011-05-20

  • Added export .view as alias for .View

2.3.4 / 2011-05-08

  • Added ./examples/say
  • Fixed res.sendfile() bug preventing the transfer of files with spaces

2.3.3 / 2011-05-03

  • Added "case sensitive routes" option.
  • Changed; split methods supported per rfc [slaskis]
  • Fixed route-specific middleware when using the same callback function several times

2.3.2 / 2011-04-27

  • Fixed view hints

2.3.1 / 2011-04-26

  • Added app.match() as app.match.all()
  • Added app.lookup() as app.lookup.all()
  • Added app.remove() for app.remove.all()
  • Added app.remove.VERB()
  • Fixed template caching collision issue. Closes #644
  • Moved router over from connect and started refactor

2.3.0 / 2011-04-25

  • Added options support to res.clearCookie()
  • Added res.helpers() as alias of res.locals()
  • Added; json defaults to UTF-8 with res.send(). Closes #632. [Daniel * Dependency connect >= 1.4.0
  • Changed; auto set Content-Type in res.attachement [Aaron Heckmann]
  • Renamed "cache views" to "view cache". Closes #628
  • Fixed caching of views when using several apps. Closes #637
  • Fixed gotcha invoking app.param() callbacks once per route middleware. Closes #638
  • Fixed partial lookup precedence. Closes #631 Shaw]

2.2.2 / 2011-04-12

  • Added second callback support for res.download() connection errors
  • Fixed filename option passing to template engine

2.2.1 / 2011-04-04

  • Added layout(path) helper to change the layout within a view. Closes #610

  • Fixed partial() collection object support. Previously only anything with .length would work. When .length is present one must still be aware of holes, however now { collection: {foo: 'bar'}} is valid, exposes keyInCollection and keysInCollection.

  • Performance improved with better view caching

  • Removed request and response locals

  • Changed; errorHandler page title is now Express instead of Connect

2.2.0 / 2011-03-30

  • Added app.lookup.VERB(), ex app.lookup.put('/user/:id'). Closes #606
  • Added app.match.VERB(), ex app.match.put('/user/12'). Closes #606
  • Added app.VERB(path) as alias of app.lookup.VERB().
  • Dependency connect >= 1.2.0

2.1.1 / 2011-03-29

  • Added; expose err.view object when failing to locate a view
  • Fixed res.partial() call next(err) when no callback is given [reported by aheckmann]
  • Fixed; res.send(undefined) responds with 204 [aheckmann]

2.1.0 / 2011-03-24

  • Added <root>/_?<name> partial lookup support. Closes #447
  • Added request, response, and app local variables
  • Added settings local variable, containing the app's settings
  • Added req.flash() exception if req.session is not available
  • Added res.send(bool) support (json response)
  • Fixed stylus example for latest version
  • Fixed; wrap try/catch around res.render()

2.0.0 / 2011-03-17

  • Fixed up index view path alternative.
  • Changed; res.locals() without object returns the locals

2.0.0rc3 / 2011-03-17

  • Added res.locals(obj) to compliment res.local(key, val)
  • Added res.partial() callback support
  • Fixed recursive error reporting issue in res.render()

2.0.0rc2 / 2011-03-17

  • Changed; partial() "locals" are now optional
  • Fixed SlowBuffer support. Closes #584 [reported by tyrda01]
  • Fixed .filename view engine option [reported by drudge]
  • Fixed blog example
  • Fixed {req,res}.app reference when mounting [Ben Weaver]

2.0.0rc / 2011-03-14

  • Fixed; expose HTTPSServer constructor
  • Fixed express(1) default test charset. Closes #579 [reported by secoif]
  • Fixed; default charset to utf-8 instead of utf8 for lame IE [reported by NickP]

2.0.0beta3 / 2011-03-09

  • Added support for res.contentType() literal The original res.contentType('.json'), res.contentType('application/json'), and res.contentType('json') will work now.
  • Added res.render() status option support back
  • Added charset option for res.render()
  • Added .charset support (via connect 1.0.4)
  • Added view resolution hints when in development and a lookup fails
  • Added layout lookup support relative to the page view. For example while rendering ./views/user/index.jade if you create ./views/user/layout.jade it will be used in favour of the root layout.
  • Fixed res.redirect(). RFC states absolute url [reported by unlink]
  • Fixed; default res.send() string charset to utf8
  • Removed Partial constructor (not currently used)

2.0.0beta2 / 2011-03-07

  • Added res.render() .locals support back to aid in migration process
  • Fixed flash example

2.0.0beta / 2011-03-03

  • Added HTTPS support
  • Added res.cookie() maxAge support
  • Added req.header() Referrer / Referer special-case, either works
  • Added mount support for res.redirect(), now respects the mount-point
  • Added union() util, taking place of merge(clone()) combo
  • Added stylus support to express(1) generated app
  • Added secret to session middleware used in examples and generated app
  • Added res.local(name, val) for progressive view locals
  • Added default param support to req.param(name, default)
  • Added app.disabled() and app.enabled()
  • Added app.register() support for omitting leading ".", either works
  • Added res.partial(), using the same interface as partial() within a view. Closes #539
  • Added app.param() to map route params to async/sync logic
  • Added; aliased app.helpers() as app.locals(). Closes #481
  • Added extname with no leading "." support to res.contentType()
  • Added cache views setting, defaulting to enabled in "production" env
  • Added index file partial resolution, eg: partial('user') may try views/user/index.jade.
  • Added req.accepts() support for extensions
  • Changed; res.download() and res.sendfile() now utilize Connect's static file server connect.static.send().
  • Changed; replaced connect.utils.mime() with npm mime module
  • Changed; allow req.query to be pre-defined (via middleware or other parent
  • Changed view partial resolution, now relative to parent view
  • Changed view engine signature. no longer engine.render(str, options, callback), now engine.compile(str, options) -> Function, the returned function accepts fn(locals).
  • Fixed req.param() bug returning Array.prototype methods. Closes #552
  • Fixed; using Stream#pipe() instead of sys.pump() in res.sendfile()
  • Fixed; using qs module instead of querystring
  • Fixed; strip unsafe chars from jsonp callbacks
  • Removed "stream threshold" setting

1.0.8 / 2011-03-01

  • Allow req.query to be pre-defined (via middleware or other parent app)
  • "connect": ">= 0.5.0 < 1.0.0". Closes #547
  • Removed the long deprecated EXPRESS_ENV support

1.0.7 / 2011-02-07

  • Fixed render() setting inheritance. Mounted apps would not inherit "view engine"

1.0.6 / 2011-02-07

  • Fixed view engine setting bug when period is in dirname

1.0.5 / 2011-02-05

  • Added secret to generated app session() call

1.0.4 / 2011-02-05

  • Added qs dependency to package.json
  • Fixed namespaced require()s for latest connect support

1.0.3 / 2011-01-13

  • Remove unsafe characters from JSONP callback names [Ryan Grove]

1.0.2 / 2011-01-10

  • Removed nested require, using connect.router

1.0.1 / 2010-12-29

  • Fixed for middleware stacked via createServer() previously the foo middleware passed to createServer(foo) would not have access to Express methods such as res.send() or props like req.query etc.

1.0.0 / 2010-11-16

  • Added; deduce partial object names from the last segment. For example by default partial('forum/post', postObject) will give you the post object, providing a meaningful default.
  • Added http status code string representation to res.redirect() body
  • Added; res.redirect() supporting text/plain and text/html via Accept.
  • Added req.is() to aid in content negotiation
  • Added partial local inheritance [suggested by masylum]. Closes #102 providing access to parent template locals.
  • Added -s, --session[s] flag to express(1) to add session related middleware
  • Added --template flag to express(1) to specify the template engine to use.
  • Added --css flag to express(1) to specify the stylesheet engine to use (or just plain css by default).
  • Added app.all() support [thanks aheckmann]
  • Added partial direct object support. You may now partial('user', user) providing the "user" local, vs previously partial('user', { object: user }).
  • Added route-separation example since many people question ways to do this with CommonJS modules. Also view the blog example for an alternative.
  • Performance; caching view path derived partial object names
  • Fixed partial local inheritance precedence. [reported by Nick Poulden] Closes #454
  • Fixed jsonp support; text/javascript as per mailinglist discussion

1.0.0rc4 / 2010-10-14

  • Added NODE_ENV support, EXPRESS_ENV is deprecated and will be removed in 1.0.0
  • Added route-middleware support (very helpful, see the docs)
  • Added jsonp callback setting to enable/disable jsonp autowrapping [Dav Glass]
  • Added callback query check on response.send to autowrap JSON objects for simple webservice implementations [Dav Glass]
  • Added partial() support for array-like collections. Closes #434
  • Added support for swappable querystring parsers
  • Added session usage docs. Closes #443
  • Added dynamic helper caching. Closes #439 [suggested by maritz]
  • Added authentication example
  • Added basic Range support to res.sendfile() (and res.download() etc)
  • Changed; express(1) generated app using 2 spaces instead of 4
  • Default env to "development" again [aheckmann]
  • Removed context option is no more, use "scope"
  • Fixed; exposing ./support libs to examples so they can run without installs
  • Fixed mvc example

1.0.0rc3 / 2010-09-20

  • Added confirmation for express(1) app generation. Closes #391
  • Added extending of flash formatters via app.flashFormatters
  • Added flash formatter support. Closes #411
  • Added streaming support to res.sendfile() using sys.pump() when >= "stream threshold"
  • Added stream threshold setting for res.sendfile()
  • Added res.send() HEAD support
  • Added res.clearCookie()
  • Added res.cookie()
  • Added res.render() headers option
  • Added res.redirect() response bodies
  • Added res.render() status option support. Closes #425 [thanks aheckmann]
  • Fixed res.sendfile() responding with 403 on malicious path
  • Fixed res.download() bug; when an error occurs remove Content-Disposition
  • Fixed; mounted apps settings now inherit from parent app [aheckmann]
  • Fixed; stripping Content-Length / Content-Type when 204
  • Fixed res.send() 204. Closes #419
  • Fixed multiple Set-Cookie headers via res.header(). Closes #402
  • Fixed bug messing with error handlers when listenFD() is called instead of listen(). [thanks guillermo]

1.0.0rc2 / 2010-08-17

  • Added app.register() for template engine mapping. Closes #390
  • Added res.render() callback support as second argument (no options)
  • Added callback support to res.download()
  • Added callback support for res.sendfile()
  • Added support for middleware access via express.middlewareName() vs connect.middlewareName()
  • Added "partials" setting to docs
  • Added default expresso tests to express(1) generated app. Closes #384
  • Fixed res.sendfile() error handling, defer via next()
  • Fixed res.render() callback when a layout is used [thanks guillermo]
  • Fixed; make install creating ~/.node_libraries when not present
  • Fixed issue preventing error handlers from being defined anywhere. Closes #387

1.0.0rc / 2010-07-28

  • Added mounted hook. Closes #369

  • Added connect dependency to package.json

  • Removed "reload views" setting and support code development env never caches, production always caches.

  • Removed param in route callbacks, signature is now simply (req, res, next), previously (req, res, params, next). Use req.params for path captures, req.query for GET params.

  • Fixed "home" setting

  • Fixed middleware/router precedence issue. Closes #366

  • Fixed; configure() callbacks called immediately. Closes #368

1.0.0beta2 / 2010-07-23

  • Added more examples
  • Added; exporting Server constructor
  • Added Server#helpers() for view locals
  • Added Server#dynamicHelpers() for dynamic view locals. Closes #349
  • Added support for absolute view paths
  • Added; home setting defaults to Server#route for mounted apps. Closes #363
  • Added Guillermo Rauch to the contributor list
  • Added support for "as" for non-collection partials. Closes #341
  • Fixed install.sh, ensuring ~/.node_libraries exists. Closes #362 [thanks jf]
  • Fixed res.render() exceptions, now passed to next() when no callback is given [thanks guillermo]
  • Fixed instanceof Array checks, now Array.isArray()
  • Fixed express(1) expansion of public dirs. Closes #348
  • Fixed middleware precedence. Closes #345
  • Fixed view watcher, now async [thanks aheckmann]

1.0.0beta / 2010-07-15

  • Re-write
    • much faster
    • much lighter
    • Check ExpressJS.com for migration guide and updated docs

0.14.0 / 2010-06-15

  • Utilize relative requires
  • Added Static bufferSize option [aheckmann]
  • Fixed caching of view and partial subdirectories [aheckmann]
  • Fixed mime.type() comments now that ".ext" is not supported
  • Updated haml submodule
  • Updated class submodule
  • Removed bin/express

0.13.0 / 2010-06-01

  • Added node v0.1.97 compatibility
  • Added support for deleting cookies via Request#cookie('key', null)
  • Updated haml submodule
  • Fixed not-found page, now using using charset utf-8
  • Fixed show-exceptions page, now using using charset utf-8
  • Fixed view support due to fs.readFile Buffers
  • Changed; mime.type() no longer accepts ".type" due to node extname() changes

0.12.0 / 2010-05-22

  • Added node v0.1.96 compatibility
  • Added view helpers export which act as additional local variables
  • Updated haml submodule
  • Changed ETag; removed inode, modified time only
  • Fixed LF to CRLF for setting multiple cookies
  • Fixed cookie complation; values are now urlencoded
  • Fixed cookies parsing; accepts quoted values and url escaped cookies

0.11.0 / 2010-05-06

  • Added support for layouts using different engines
    • this.render('page.html.haml', { layout: 'super-cool-layout.html.ejs' })
    • this.render('page.html.haml', { layout: 'foo' }) // assumes 'foo.html.haml'
    • this.render('page.html.haml', { layout: false }) // no layout
  • Updated ext submodule
  • Updated haml submodule
  • Fixed EJS partial support by passing along the context. Issue #307

0.10.1 / 2010-05-03

  • Fixed binary uploads.

0.10.0 / 2010-04-30

  • Added charset support via Request#charset (automatically assigned to 'UTF-8' when respond()'s encoding is set to 'utf8' or 'utf-8'.
  • Added "encoding" option to Request#render(). Closes #299
  • Added "dump exceptions" setting, which is enabled by default.
  • Added simple ejs template engine support
  • Added error reponse support for text/plain, application/json. Closes #297
  • Added callback function param to Request#error()
  • Added Request#sendHead()
  • Added Request#stream()
  • Added support for Request#respond(304, null) for empty response bodies
  • Added ETag support to Request#sendfile()
  • Added options to Request#sendfile(), passed to fs.createReadStream()
  • Added filename arg to Request#download()
  • Performance enhanced due to pre-reversing plugins so that plugins.reverse() is not called on each request
  • Performance enhanced by preventing several calls to toLowerCase() in Router#match()
  • Changed; Request#sendfile() now streams
  • Changed; Renamed Request#halt() to Request#respond(). Closes #289
  • Changed; Using sys.inspect() instead of JSON.encode() for error output
  • Changed; run() returns the http.Server instance. Closes #298
  • Changed; Defaulting Server#host to null (INADDR_ANY)
  • Changed; Logger "common" format scale of 0.4f
  • Removed Logger "request" format
  • Fixed; Catching ENOENT in view caching, preventing error when "views/partials" is not found
  • Fixed several issues with http client
  • Fixed Logger Content-Length output
  • Fixed bug preventing Opera from retaining the generated session id. Closes #292

0.9.0 / 2010-04-14

  • Added DSL level error() route support
  • Added DSL level notFound() route support
  • Added Request#error()
  • Added Request#notFound()
  • Added Request#render() callback function. Closes #258
  • Added "max upload size" setting
  • Added "magic" variables to collection partials (__index__, __length__, __isFirst__, __isLast__). Closes #254
  • Added haml.js submodule; removed haml-js
  • Added callback function support to Request#halt() as 3rd/4th arg
  • Added preprocessing of route param wildcards using param(). Closes #251
  • Added view partial support (with collections etc)
  • Fixed bug preventing falsey params (such as ?page=0). Closes #286
  • Fixed setting of multiple cookies. Closes #199
  • Changed; view naming convention is now NAME.TYPE.ENGINE (for example page.html.haml)
  • Changed; session cookie is now httpOnly
  • Changed; Request is no longer global
  • Changed; Event is no longer global
  • Changed; "sys" module is no longer global
  • Changed; moved Request#download to Static plugin where it belongs
  • Changed; Request instance created before body parsing. Closes #262
  • Changed; Pre-caching views in memory when "cache view contents" is enabled. Closes #253
  • Changed; Pre-caching view partials in memory when "cache view partials" is enabled
  • Updated support to node --version 0.1.90
  • Updated dependencies
  • Removed set("session cookie") in favour of use(Session, { cookie: { ... }})
  • Removed utils.mixin(); use Object#mergeDeep()

0.8.0 / 2010-03-19

  • Added coffeescript example app. Closes #242
  • Changed; cache api now async friendly. Closes #240
  • Removed deprecated 'express/static' support. Use 'express/plugins/static'

0.7.6 / 2010-03-19

  • Added Request#isXHR. Closes #229
  • Added make install (for the executable)
  • Added express executable for setting up simple app templates
  • Added "GET /public/*" to Static plugin, defaulting to /public
  • Added Static plugin
  • Fixed; Request#render() only calls cache.get() once
  • Fixed; Namespacing View caches with "view:"
  • Fixed; Namespacing Static caches with "static:"
  • Fixed; Both example apps now use the Static plugin
  • Fixed set("views"). Closes #239
  • Fixed missing space for combined log format
  • Deprecated Request#sendfile() and 'express/static'
  • Removed Server#running

0.7.5 / 2010-03-16

  • Added Request#flash() support without args, now returns all flashes
  • Updated ext submodule

0.7.4 / 2010-03-16

  • Fixed session reaper
  • Changed; class.js replacing js-oo Class implementation (quite a bit faster, no browser cruft)

0.7.3 / 2010-03-16

  • Added package.json
  • Fixed requiring of haml / sass due to kiwi removal

0.7.2 / 2010-03-16

  • Fixed GIT submodules (HAH!)

0.7.1 / 2010-03-16

  • Changed; Express now using submodules again until a PM is adopted
  • Changed; chat example using millisecond conversions from ext

0.7.0 / 2010-03-15

  • Added Request#pass() support (finds the next matching route, or the given path)
  • Added Logger plugin (default "common" format replaces CommonLogger)
  • Removed Profiler plugin
  • Removed CommonLogger plugin

0.6.0 / 2010-03-11

  • Added seed.yml for kiwi package management support

  • Added HTTP client query string support when method is GET. Closes #205

  • Added support for arbitrary view engines. For example "foo.engine.html" will now require('engine'), the exports from this module are cached after the first require().

  • Added async plugin support

  • Removed usage of RESTful route funcs as http client get() etc, use http.get() and friends

  • Removed custom exceptions

0.5.0 / 2010-03-10

  • Added ext dependency (library of js extensions)
  • Removed extname() / basename() utils. Use path module
  • Removed toArray() util. Use arguments.values
  • Removed escapeRegexp() util. Use RegExp.escape()
  • Removed process.mixin() dependency. Use utils.mixin()
  • Removed Collection
  • Removed ElementCollection
  • Shameless self promotion of ebook "Advanced JavaScript" (http://dev-mag.com) ;)

0.4.0 / 2010-02-11

  • Added flash() example to sample upload app
  • Added high level restful http client module (express/http)
  • Changed; RESTful route functions double as HTTP clients. Closes #69
  • Changed; throwing error when routes are added at runtime
  • Changed; defaulting render() context to the current Request. Closes #197
  • Updated haml submodule

0.3.0 / 2010-02-11

  • Updated haml / sass submodules. Closes #200
  • Added flash message support. Closes #64
  • Added accepts() now allows multiple args. fixes #117
  • Added support for plugins to halt. Closes #189
  • Added alternate layout support. Closes #119
  • Removed Route#run(). Closes #188
  • Fixed broken specs due to use(Cookie) missing

0.2.1 / 2010-02-05

  • Added "plot" format option for Profiler (for gnuplot processing)
  • Added request number to Profiler plugin
  • Fixed binary encoding for multi-part file uploads, was previously defaulting to UTF8
  • Fixed issue with routes not firing when not files are present. Closes #184
  • Fixed process.Promise -> events.Promise

0.2.0 / 2010-02-03

  • Added parseParam() support for name[] etc. (allows for file inputs with "multiple" attr) Closes #180
  • Added Both Cache and Session option "reapInterval" may be "reapEvery". Closes #174
  • Added expiration support to cache api with reaper. Closes #133
  • Added cache Store.Memory#reap()
  • Added Cache; cache api now uses first class Cache instances
  • Added abstract session Store. Closes #172
  • Changed; cache Memory.Store#get() utilizing Collection
  • Renamed MemoryStore -> Store.Memory
  • Fixed use() of the same plugin several time will always use latest options. Closes #176

0.1.0 / 2010-02-03

  • Changed; Hooks (before / after) pass request as arg as well as evaluated in their context
  • Updated node support to 0.1.27 Closes #169
  • Updated dirname(__filename) -> __dirname
  • Updated libxmljs support to v0.2.0
  • Added session support with memory store / reaping
  • Added quick uid() helper
  • Added multi-part upload support
  • Added Sass.js support / submodule
  • Added production env caching view contents and static files
  • Added static file caching. Closes #136
  • Added cache plugin with memory stores
  • Added support to StaticFile so that it works with non-textual files.
  • Removed dirname() helper
  • Removed several globals (now their modules must be required)

0.0.2 / 2010-01-10

  • Added view benchmarks; currently haml vs ejs
  • Added Request#attachment() specs. Closes #116
  • Added use of node's parseQuery() util. Closes #123
  • Added make init for submodules
  • Updated Haml
  • Updated sample chat app to show messages on load
  • Updated libxmljs parseString -> parseHtmlString
  • Fixed make init to work with older versions of git
  • Fixed specs can now run independant specs for those who cant build deps. Closes #127
  • Fixed issues introduced by the node url module changes. Closes 126.
  • Fixed two assertions failing due to Collection#keys() returning strings
  • Fixed faulty Collection#toArray() spec due to keys() returning strings
  • Fixed make test now builds libxmljs.node before testing

0.0.1 / 2010-01-03

  • Initial release
module.exports = process.env.EXPRESS_COV
? require('./lib-cov/express')
: require('./lib/express');
/**
* Module dependencies.
*/
var mixin = require('utils-merge');
var escapeHtml = require('escape-html');
var Router = require('./router');
var methods = require('methods');
var middleware = require('./middleware/init');
var query = require('./middleware/query');
var debug = require('debug')('express:application');
var View = require('./view');
var http = require('http');
var deprecate = require('./utils').deprecate;
/**
* Application prototype.
*/
var app = exports = module.exports = {};
/**
* Initialize the server.
*
* - setup default configuration
* - setup default middleware
* - setup route reflection methods
*
* @api private
*/
app.init = function () {
this.cache = {};
this.settings = {};
this.engines = {};
this.defaultConfiguration();
};
/**
* Initialize application configuration.
*
* @api private
*/
app.defaultConfiguration = function () {
// default settings
this.enable('x-powered-by');
this.enable('etag');
var env = process.env.NODE_ENV || 'development';
this.set('env', env);
this.set('subdomain offset', 2);
debug('booting in %s mode', env);
// inherit protos
this.on('mount', function (parent) {
this.request.__proto__ = parent.request;
this.response.__proto__ = parent.response;
this.engines.__proto__ = parent.engines;
this.settings.__proto__ = parent.settings;
});
// setup locals
this.locals = Object.create(null);
// top-most app is mounted at /
this.mountpath = '/';
// default locals
this.locals.settings = this.settings;
// default configuration
this.set('view', View);
this.set('views', process.cwd() + '/views');
this.set('jsonp callback name', 'callback');
if (env === 'production') {
this.enable('view cache');
}
Object.defineProperty(this, 'router', {
get: function () {
throw new Error('\'app.router\' is deprecated!\nPlease see the 3.x to 4.x migration guide for details on how to update your app.');
}
});
};
/**
* lazily adds the base router if it has not yet been added.
*
* We cannot add the base router in the defaultConfiguration because
* it reads app settings which might be set after that has run.
*
* @api private
*/
app.lazyrouter = function () {
if (!this._router) {
this._router = new Router({
caseSensitive: this.enabled('case sensitive routing'),
strict: this.enabled('strict routing')
});
this._router.use(query());
this._router.use(middleware.init(this));
}
};
/**
* Dispatch a req, res pair into the application. Starts pipeline processing.
*
* If no _done_ callback is provided, then default error handlers will respond
* in the event of an error bubbling through the stack.
*
* @api private
*/
app.handle = function (req, res, done) {
var env = this.get('env');
this._router.handle(req, res, function (err) {
if (done) {
return done(err);
}
// unhandled error
if (err) {
// default to 500
if (res.statusCode < 400) res.statusCode = 500;
debug('default %s', res.statusCode);
// respect err.status
if (err.status) res.statusCode = err.status;
// production gets a basic error message
var msg = 'production' == env
? http.STATUS_CODES[res.statusCode]
: err.stack || err.toString();
msg = escapeHtml(msg);
// log to stderr in a non-test env
if ('test' != env) console.error(err.stack || err.toString());
if (res.headersSent) return req.socket.destroy();
res.setHeader('Content-Type', 'text/html');
res.setHeader('Content-Length', Buffer.byteLength(msg));
if ('HEAD' == req.method) return res.end();
res.end(msg);
return;
}
// 404
debug('default 404');
res.statusCode = 404;
res.setHeader('Content-Type', 'text/html');
if ('HEAD' == req.method) return res.end();
res.end('Cannot ' + escapeHtml(req.method) + ' ' + escapeHtml(req.originalUrl) + '\n');
});
};
/**
* Proxy `Router#use()` to add middleware to the app router.
* See Router#use() documentation for details.
*
* If the _fn_ parameter is an express app, then it will be
* mounted at the _route_ specified.
*
* @param {String|Function|Server} route
* @param {Function|Server} fn
* @return {app} for chaining
* @api public
*/
app.use = function (route, fn) {
var mount_app;
// default route to '/'
if ('string' != typeof route) fn = route, route = '/';
// express app
if (fn.handle && fn.set) mount_app = fn;
// restore .app property on req and res
if (mount_app) {
debug('.use app under %s', route);
mount_app.mountpath = route;
fn = function (req, res, next) {
var orig = req.app;
mount_app.handle(req, res, function (err) {
req.__proto__ = orig.request;
res.__proto__ = orig.response;
next(err);
});
};
}
this.lazyrouter();
this._router.use(route, fn);
// mounted an app
if (mount_app) {
mount_app.parent = this;
mount_app.emit('mount', this);
}
return this;
};
/**
* Proxy to the app `Router#route()`
* Returns a new `Route` instance for the _path_.
*
* Routes are isolated middleware stacks for specific paths.
* See the Route api docs for details.
*
* @api public
*/
app.route = function (path) {
this.lazyrouter();
return this._router.route(path);
};
/**
* Register the given template engine callback `fn`
* as `ext`.
*
* By default will `require()` the engine based on the
* file extension. For example if you try to render
* a "foo.jade" file Express will invoke the following internally:
*
* app.engine('jade', require('jade').__express);
*
* For engines that do not provide `.__express` out of the box,
* or if you wish to "map" a different extension to the template engine
* you may use this method. For example mapping the EJS template engine to
* ".html" files:
*
* app.engine('html', require('ejs').renderFile);
*
* In this case EJS provides a `.renderFile()` method with
* the same signature that Express expects: `(path, options, callback)`,
* though note that it aliases this method as `ejs.__express` internally
* so if you're using ".ejs" extensions you dont need to do anything.
*
* Some template engines do not follow this convention, the
* [Consolidate.js](https://github.com/visionmedia/consolidate.js)
* library was created to map all of node's popular template
* engines to follow this convention, thus allowing them to
* work seamlessly within Express.
*
* @param {String} ext
* @param {Function} fn
* @return {app} for chaining
* @api public
*/
app.engine = function (ext, fn) {
if ('function' != typeof fn) throw new Error('callback function required');
if ('.' != ext[0]) ext = '.' + ext;
this.engines[ext] = fn;
return this;
};
/**
* Proxy to `Router#param()` with one added api feature. The _name_ parameter
* can be an array of names.
*
* See the Router#param() docs for more details.
*
* @param {String|Array} name
* @param {Function} fn
* @return {app} for chaining
* @api public
*/
app.param = function (name, fn) {
var self = this;
self.lazyrouter();
if (Array.isArray(name)) {
name.forEach(function (key) {
self.param(key, fn);
});
return this;
}
self._router.param(name, fn);
return this;
};
/**
* Assign `setting` to `val`, or return `setting`'s value.
*
* app.set('foo', 'bar');
* app.get('foo');
* // => "bar"
*
* Mounted servers inherit their parent server's settings.
*
* @param {String} setting
* @param {*} [val]
* @return {Server} for chaining
* @api public
*/
app.set = function (setting, val) {
if (1 == arguments.length) {
return this.settings[setting];
} else {
this.settings[setting] = val;
return this;
}
};
/**
* Return the app's absolute pathname
* based on the parent(s) that have
* mounted it.
*
* For example if the application was
* mounted as "/admin", which itself
* was mounted as "/blog" then the
* return value would be "/blog/admin".
*
* @return {String}
* @api private
*/
app.path = function () {
return this.parent
? this.parent.path() + this.mountpath
: '';
};
/**
* Check if `setting` is enabled (truthy).
*
* app.enabled('foo')
* // => false
*
* app.enable('foo')
* app.enabled('foo')
* // => true
*
* @param {String} setting
* @return {Boolean}
* @api public
*/
app.enabled = function (setting) {
return !!this.set(setting);
};
/**
* Check if `setting` is disabled.
*
* app.disabled('foo')
* // => true
*
* app.enable('foo')
* app.disabled('foo')
* // => false
*
* @param {String} setting
* @return {Boolean}
* @api public
*/
app.disabled = function (setting) {
return !this.set(setting);
};
/**
* Enable `setting`.
*
* @param {String} setting
* @return {app} for chaining
* @api public
*/
app.enable = function (setting) {
return this.set(setting, true);
};
/**
* Disable `setting`.
*
* @param {String} setting
* @return {app} for chaining
* @api public
*/
app.disable = function (setting) {
return this.set(setting, false);
};
/**
* Delegate `.VERB(...)` calls to `router.VERB(...)`.
*/
methods.forEach(function (method) {
app[method] = function (path) {
if ('get' == method && 1 == arguments.length) return this.set(path);
this.lazyrouter();
var route = this._router.route(path);
route[method].apply(route, [].slice.call(arguments, 1));
return this;
};
});
/**
* Special-cased "all" method, applying the given route `path`,
* middleware, and callback to _every_ HTTP method.
*
* @param {String} path
* @param {Function} ...
* @return {app} for chaining
* @api public
*/
app.all = function (path) {
this.lazyrouter();
var route = this._router.route(path);
var args = [].slice.call(arguments, 1);
methods.forEach(function (method) {
route[method].apply(route, args);
});
return this;
};
// del -> delete alias
app.del = deprecate(app.delete, 'app.del: Use app.delete instead');
/**
* Render the given view `name` name with `options`
* and a callback accepting an error and the
* rendered template string.
*
* Example:
*
* app.render('email', { name: 'Tobi' }, function(err, html){
* // ...
* })
*
* @param {String} name
* @param {String|Function} options or fn
* @param {Function} fn
* @api public
*/
app.render = function (name, options, fn) {
var opts = {};
var cache = this.cache;
var engines = this.engines;
var view;
// support callback function as second arg
if ('function' == typeof options) {
fn = options, options = {};
}
// merge app.locals
mixin(opts, this.locals);
// merge options._locals
if (options._locals) mixin(opts, options._locals);
// merge options
mixin(opts, options);
// set .cache unless explicitly provided
opts.cache = null == opts.cache
? this.enabled('view cache')
: opts.cache;
// primed cache
if (opts.cache) view = cache[name];
// view
if (!view) {
view = new (this.get('view'))(name, {
defaultEngine: this.get('view engine'),
root: this.get('views'),
engines: engines
});
if (!view.path) {
var err = new Error('Failed to lookup view "' + name + '" in views directory "' + view.root + '"');
err.view = view;
return fn(err);
}
// prime the cache
if (opts.cache) cache[name] = view;
}
// render
try {
view.render(opts, fn);
} catch (err) {
fn(err);
}
};
/**
* Listen for connections.
*
* A node `http.Server` is returned, with this
* application (which is a `Function`) as its
* callback. If you wish to create both an HTTP
* and HTTPS server you may do so with the "http"
* and "https" modules as shown here:
*
* var http = require('http')
* , https = require('https')
* , express = require('express')
* , app = express();
*
* http.createServer(app).listen(80);
* https.createServer({ ... }, app).listen(443);
*
* @return {http.Server}
* @api public
*/
app.listen = function () {
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
/**
* Module dependencies.
*/
var EventEmitter = require('events').EventEmitter;
var mixin = require('utils-merge');
var proto = require('./application');
var Route = require('./router/route');
var Router = require('./router');
var req = require('./request');
var res = require('./response');
/**
* Expose `createApplication()`.
*/
exports = module.exports = createApplication;
/**
* Create an express application.
*
* @return {Function}
* @api public
*/
function createApplication() {
var app = function (req, res, next) {
app.handle(req, res, next);
};
mixin(app, proto);
mixin(app, EventEmitter.prototype);
app.request = { __proto__: req, app: app };
app.response = { __proto__: res, app: app };
app.init();
return app;
}
/**
* Expose the prototypes.
*/
exports.application = proto;
exports.request = req;
exports.response = res;
/**
* Expose constructors.
*/
exports.Route = Route;
exports.Router = Router;
/**
* Expose middleware
*/
exports.query = require('./middleware/query');
exports.static = require('serve-static');
/**
* Replace removed middleware with an appropriate error message.
*/
[
'json',
'urlencoded',
'bodyParser',
'compress',
'cookieSession',
'session',
'logger',
'cookieParser',
'favicon',
'responseTime',
'errorHandler',
'timeout',
'methodOverride',
'vhost',
'csrf',
'directory',
'limit',
'multipart',
'staticCache',
].forEach(function (name) {
Object.defineProperty(exports, name, {
get: function () {
throw new Error('Most middleware (like ' + name + ') is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.');
},
configurable: true
});
});
/**
* Initialization middleware, exposing the
* request and response to eachother, as well
* as defaulting the X-Powered-By header field.
*
* @param {Function} app
* @return {Function}
* @api private
*/
exports.init = function (app) {
return function expressInit(req, res, next) {
if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express');
req.res = res;
res.req = req;
req.next = next;
req.__proto__ = app.request;
res.__proto__ = app.response;
res.locals = res.locals || Object.create(null);
next();
};
};
/**
* Module dependencies.
*/
var qs = require('qs');
var parseUrl = require('parseurl');
/**
* Query:
*
* Automatically parse the query-string when available,
* populating the `req.query` object using
* [qs](https://github.com/visionmedia/node-querystring).
*
* Examples:
*
* .use(connect.query())
* .use(function(req, res){
* res.end(JSON.stringify(req.query));
* });
*
* The `options` passed are provided to qs.parse function.
*
* @param {Object} options
* @return {Function}
* @api public
*/
module.exports = function query(options) {
return function query(req, res, next) {
if (!req.query) {
req.query = ~req.url.indexOf('?')
? qs.parse(parseUrl(req).query, options)
: {};
}
next();
};
};
/**
* Module dependencies.
*/
var accepts = require('accepts');
var typeis = require('type-is');
var http = require('http');
var fresh = require('fresh');
var parseRange = require('range-parser');
var parse = require('parseurl');
/**
* Request prototype.
*/
var req = exports = module.exports = {
__proto__: http.IncomingMessage.prototype
};
/**
* Return request header.
*
* The `Referrer` header field is special-cased,
* both `Referrer` and `Referer` are interchangeable.
*
* Examples:
*
* req.get('Content-Type');
* // => "text/plain"
*
* req.get('content-type');
* // => "text/plain"
*
* req.get('Something');
* // => undefined
*
* Aliased as `req.header()`.
*
* @param {String} name
* @return {String}
* @api public
*/
req.get =
req.header = function (name) {
switch (name = name.toLowerCase()) {
case 'referer':
case 'referrer':
return this.headers.referrer
|| this.headers.referer;
default:
return this.headers[name];
}
};
/**
* To do: update docs.
*
* Check if the given `type(s)` is acceptable, returning
* the best match when true, otherwise `undefined`, in which
* case you should respond with 406 "Not Acceptable".
*
* The `type` value may be a single mime type string
* such as "application/json", the extension name
* such as "json", a comma-delimted list such as "json, html, text/plain",
* an argument list such as `"json", "html", "text/plain"`,
* or an array `["json", "html", "text/plain"]`. When a list
* or array is given the _best_ match, if any is returned.
*
* Examples:
*
* // Accept: text/html
* req.accepts('html');
* // => "html"
*
* // Accept: text/*, application/json
* req.accepts('html');
* // => "html"
* req.accepts('text/html');
* // => "text/html"
* req.accepts('json, text');
* // => "json"
* req.accepts('application/json');
* // => "application/json"
*
* // Accept: text/*, application/json
* req.accepts('image/png');
* req.accepts('png');
* // => undefined
*
* // Accept: text/*;q=.5, application/json
* req.accepts(['html', 'json']);
* req.accepts('html', 'json');
* req.accepts('html, json');
* // => "json"
*
* @param {String|Array} type(s)
* @return {String}
* @api public
*/
req.accepts = function () {
var accept = accepts(this);
return accept.types.apply(accept, arguments);
};
/**
* Check if the given `encoding` is accepted.
*
* @param {String} encoding
* @return {Boolean}
* @api public
*/
req.acceptsEncoding = // backwards compatibility
req.acceptsEncodings = function () {
var accept = accepts(this);
return accept.encodings.apply(accept, arguments);
};
/**
* To do: update docs.
*
* Check if the given `charset` is acceptable,
* otherwise you should respond with 406 "Not Acceptable".
*
* @param {String} charset
* @return {Boolean}
* @api public
*/
req.acceptsCharset = // backwards compatibility
req.acceptsCharsets = function () {
var accept = accepts(this);
return accept.charsets.apply(accept, arguments);
};
/**
* To do: update docs.
*
* Check if the given `lang` is acceptable,
* otherwise you should respond with 406 "Not Acceptable".
*
* @param {String} lang
* @return {Boolean}
* @api public
*/
req.acceptsLanguage = // backwards compatibility
req.acceptsLanguages = function () {
var accept = accepts(this);
return accept.languages.apply(accept, arguments);
};
/**
* Parse Range header field,
* capping to the given `size`.
*
* Unspecified ranges such as "0-" require
* knowledge of your resource length. In
* the case of a byte range this is of course
* the total number of bytes. If the Range
* header field is not given `null` is returned,
* `-1` when unsatisfiable, `-2` when syntactically invalid.
*
* NOTE: remember that ranges are inclusive, so
* for example "Range: users=0-3" should respond
* with 4 users when available, not 3.
*
* @param {Number} size
* @return {Array}
* @api public
*/
req.range = function (size) {
var range = this.get('Range');
if (!range) return;
return parseRange(size, range);
};
/**
* Return the value of param `name` when present or `defaultValue`.
*
* - Checks route placeholders, ex: _/user/:id_
* - Checks body params, ex: id=12, {"id":12}
* - Checks query string params, ex: ?id=12
*
* To utilize request bodies, `req.body`
* should be an object. This can be done by using
* the `bodyParser()` middleware.
*
* @param {String} name
* @param {Mixed} [defaultValue]
* @return {String}
* @api public
*/
req.param = function (name, defaultValue) {
var params = this.params || {};
var body = this.body || {};
var query = this.query || {};
if (null != params[name] && params.hasOwnProperty(name)) return params[name];
if (null != body[name]) return body[name];
if (null != query[name]) return query[name];
return defaultValue;
};
/**
* Check if the incoming request contains the "Content-Type"
* header field, and it contains the give mime `type`.
*
* Examples:
*
* // With Content-Type: text/html; charset=utf-8
* req.is('html');
* req.is('text/html');
* req.is('text/*');
* // => true
*
* // When Content-Type is application/json
* req.is('json');
* req.is('application/json');
* req.is('application/*');
* // => true
*
* req.is('html');
* // => false
*
* @param {String} type
* @return {Boolean}
* @api public
*/
req.is = function (types) {
if (!Array.isArray(types)) types = [].slice.call(arguments);
return typeis(this, types);
};
/**
* Return the protocol string "http" or "https"
* when requested with TLS. When the "trust proxy"
* setting is enabled the "X-Forwarded-Proto" header
* field will be trusted. If you're running behind
* a reverse proxy that supplies https for you this
* may be enabled.
*
* @return {String}
* @api public
*/
req.__defineGetter__('protocol', function () {
var trustProxy = this.app.get('trust proxy');
if (this.connection.encrypted) return 'https';
if (!trustProxy) return 'http';
var proto = this.get('X-Forwarded-Proto') || 'http';
return proto.split(/\s*,\s*/)[0];
});
/**
* Short-hand for:
*
* req.protocol == 'https'
*
* @return {Boolean}
* @api public
*/
req.__defineGetter__('secure', function () {
return 'https' == this.protocol;
});
/**
* Return the remote address, or when
* "trust proxy" is `true` return
* the upstream addr.
*
* @return {String}
* @api public
*/
req.__defineGetter__('ip', function () {
return this.ips[0] || this.connection.remoteAddress;
});
/**
* When "trust proxy" is `true`, parse
* the "X-Forwarded-For" ip address list.
*
* For example if the value were "client, proxy1, proxy2"
* you would receive the array `["client", "proxy1", "proxy2"]`
* where "proxy2" is the furthest down-stream.
*
* @return {Array}
* @api public
*/
req.__defineGetter__('ips', function () {
var trustProxy = this.app.get('trust proxy');
var val = this.get('X-Forwarded-For');
return trustProxy && val
? val.split(/ *, */)
: [];
});
/**
* Return subdomains as an array.
*
* Subdomains are the dot-separated parts of the host before the main domain of
* the app. By default, the domain of the app is assumed to be the last two
* parts of the host. This can be changed by setting "subdomain offset".
*
* For example, if the domain is "tobi.ferrets.example.com":
* If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`.
* If "subdomain offset" is 3, req.subdomains is `["tobi"]`.
*
* @return {Array}
* @api public
*/
req.__defineGetter__('subdomains', function () {
var offset = this.app.get('subdomain offset');
return (this.host || '')
.split('.')
.reverse()
.slice(offset);
});
/**
* Short-hand for `url.parse(req.url).pathname`.
*
* @return {String}
* @api public
*/
req.__defineGetter__('path', function () {
return parse(this).pathname;
});
/**
* Parse the "Host" header field hostname.
*
* @return {String}
* @api public
*/
req.__defineGetter__('host', function () {
var trustProxy = this.app.get('trust proxy');
var host = trustProxy && this.get('X-Forwarded-Host');
host = host || this.get('Host');
if (!host) return;
var offset = host[0] === '['
? host.indexOf(']') + 1
: 0;
var index = host.indexOf(':', offset);
return ~index
? host.substring(0, index)
: host;
});
/**
* Check if the request is fresh, aka
* Last-Modified and/or the ETag
* still match.
*
* @return {Boolean}
* @api public
*/
req.__defineGetter__('fresh', function () {
var method = this.method;
var s = this.res.statusCode;
// GET or HEAD for weak freshness validation only
if ('GET' != method && 'HEAD' != method) return false;
// 2xx or 304 as per rfc2616 14.26
if ((s >= 200 && s < 300) || 304 == s) {
return fresh(this.headers, this.res._headers);
}
return false;
});
/**
* Check if the request is stale, aka
* "Last-Modified" and / or the "ETag" for the
* resource has changed.
*
* @return {Boolean}
* @api public
*/
req.__defineGetter__('stale', function () {
return !this.fresh;
});
/**
* Check if the request was an _XMLHttpRequest_.
*
* @return {Boolean}
* @api public
*/
req.__defineGetter__('xhr', function () {
var val = this.get('X-Requested-With') || '';
return 'xmlhttprequest' == val.toLowerCase();
});
/**
* Module dependencies.
*/
var http = require('http');
var path = require('path');
var mixin = require('utils-merge');
var escapeHtml = require('escape-html');
var sign = require('cookie-signature').sign;
var normalizeType = require('./utils').normalizeType;
var normalizeTypes = require('./utils').normalizeTypes;
var contentDisposition = require('./utils').contentDisposition;
var deprecate = require('./utils').deprecate;
var etag = require('./utils').etag;
var statusCodes = http.STATUS_CODES;
var cookie = require('cookie');
var send = require('send');
var basename = path.basename;
var extname = path.extname;
var mime = send.mime;
/**
* Response prototype.
*/
var res = module.exports = {
__proto__: http.ServerResponse.prototype
};
/**
* Set status `code`.
*
* @param {Number} code
* @return {ServerResponse}
* @api public
*/
res.status = function (code) {
this.statusCode = code;
return this;
};
/**
* Set Link header field with the given `links`.
*
* Examples:
*
* res.links({
* next: 'http://api.example.com/users?page=2',
* last: 'http://api.example.com/users?page=5'
* });
*
* @param {Object} links
* @return {ServerResponse}
* @api public
*/
res.links = function (links) {
var link = this.get('Link') || '';
if (link) link += ', ';
return this.set('Link', link + Object.keys(links).map(function (rel) {
return '<' + links[rel] + '>; rel="' + rel + '"';
}).join(', '));
};
/**
* Send a response.
*
* Examples:
*
* res.send(new Buffer('wahoo'));
* res.send({ some: 'json' });
* res.send('<p>some html</p>');
* res.send(404, 'Sorry, cant find that');
* res.send(404);
*
* @param {Mixed} body or status
* @param {Mixed} body
* @return {ServerResponse}
* @api public
*/
res.send = function (body) {
var req = this.req;
var head = 'HEAD' == req.method;
var len;
// settings
var app = this.app;
// allow status / body
if (2 == arguments.length) {
// res.send(body, status) backwards compat
if ('number' != typeof body && 'number' == typeof arguments[1]) {
this.statusCode = arguments[1];
} else {
this.statusCode = body;
body = arguments[1];
}
}
switch (typeof body) {
// response status
case 'number':
this.get('Content-Type') || this.type('txt');
this.statusCode = body;
body = http.STATUS_CODES[body];
break;
// string defaulting to html
case 'string':
if (!this.get('Content-Type')) this.type('html');
break;
case 'boolean':
case 'object':
if (null == body) {
body = '';
} else if (Buffer.isBuffer(body)) {
this.get('Content-Type') || this.type('bin');
} else {
return this.json(body);
}
break;
}
// populate Content-Length
if (undefined !== body && !this.get('Content-Length')) {
this.set('Content-Length', len = Buffer.isBuffer(body)
? body.length
: Buffer.byteLength(body));
}
// ETag support
// TODO: W/ support
if (app.settings.etag && len && ('GET' == req.method || 'HEAD' == req.method)) {
if (!this.get('ETag')) {
this.set('ETag', etag(body));
}
}
// freshness
if (req.fresh) this.statusCode = 304;
// strip irrelevant headers
if (204 == this.statusCode || 304 == this.statusCode) {
this.removeHeader('Content-Type');
this.removeHeader('Content-Length');
this.removeHeader('Transfer-Encoding');
body = '';
}
// respond
this.end(head ? null : body);
return this;
};
/**
* Send JSON response.
*
* Examples:
*
* res.json(null);
* res.json({ user: 'tj' });
* res.json(500, 'oh noes!');
* res.json(404, 'I dont have that');
*
* @param {Mixed} obj or status
* @param {Mixed} obj
* @return {ServerResponse}
* @api public
*/
res.json = function (obj) {
// allow status / body
if (2 == arguments.length) {
// res.json(body, status) backwards compat
if ('number' == typeof arguments[1]) {
this.statusCode = arguments[1];
return 'number' === typeof obj
? jsonNumDeprecated.call(this, obj)
: jsonDeprecated.call(this, obj);
} else {
this.statusCode = obj;
obj = arguments[1];
}
}
// settings
var app = this.app;
var replacer = app.get('json replacer');
var spaces = app.get('json spaces');
var body = JSON.stringify(obj, replacer, spaces);
// content-type
this.get('Content-Type') || this.set('Content-Type', 'application/json');
return this.send(body);
};
var jsonDeprecated = deprecate(res.json,
'res.json(obj, status): Use res.json(status, obj) instead');
var jsonNumDeprecated = deprecate(res.json,
'res.json(num, status): Use res.status(status).json(num) instead');
/**
* Send JSON response with JSONP callback support.
*
* Examples:
*
* res.jsonp(null);
* res.jsonp({ user: 'tj' });
* res.jsonp(500, 'oh noes!');
* res.jsonp(404, 'I dont have that');
*
* @param {Mixed} obj or status
* @param {Mixed} obj
* @return {ServerResponse}
* @api public
*/
res.jsonp = function (obj) {
// allow status / body
if (2 == arguments.length) {
// res.json(body, status) backwards compat
if ('number' == typeof arguments[1]) {
this.statusCode = arguments[1];
return 'number' === typeof obj
? jsonpNumDeprecated.call(this, obj)
: jsonpDeprecated.call(this, obj);
} else {
this.statusCode = obj;
obj = arguments[1];
}
}
// settings
var app = this.app;
var replacer = app.get('json replacer');
var spaces = app.get('json spaces');
var body = JSON.stringify(obj, replacer, spaces)
.replace(/\u2028/g, '\\u2028')
.replace(/\u2029/g, '\\u2029');
var callback = this.req.query[app.get('jsonp callback name')];
// content-type
this.get('Content-Type') || this.set('Content-Type', 'application/json');
// fixup callback
if (Array.isArray(callback)) {
callback = callback[0];
}
// jsonp
if (callback && 'string' === typeof callback) {
this.set('Content-Type', 'text/javascript');
var cb = callback.replace(/[^\[\]\w$.]/g, '');
body = 'typeof ' + cb + ' === \'function\' && ' + cb + '(' + body + ');';
}
return this.send(body);
};
var jsonpDeprecated = deprecate(res.json,
'res.jsonp(obj, status): Use res.jsonp(status, obj) instead');
var jsonpNumDeprecated = deprecate(res.json,
'res.jsonp(num, status): Use res.status(status).jsonp(num) instead');
/**
* Transfer the file at the given `path`.
*
* Automatically sets the _Content-Type_ response header field.
* The callback `fn(err)` is invoked when the transfer is complete
* or when an error occurs. Be sure to check `res.sentHeader`
* if you wish to attempt responding, as the header and some data
* may have already been transferred.
*
* Options:
*
* - `maxAge` defaulting to 0
* - `root` root directory for relative filenames
* - `hidden` serve hidden files, defaulting to false
*
* Other options are passed along to `send`.
*
* Examples:
*
* The following example illustrates how `res.sendfile()` may
* be used as an alternative for the `static()` middleware for
* dynamic situations. The code backing `res.sendfile()` is actually
* the same code, so HTTP cache support etc is identical.
*
* app.get('/user/:uid/photos/:file', function(req, res){
* var uid = req.params.uid
* , file = req.params.file;
*
* req.user.mayViewFilesFrom(uid, function(yes){
* if (yes) {
* res.sendfile('/uploads/' + uid + '/' + file);
* } else {
* res.send(403, 'Sorry! you cant see that.');
* }
* });
* });
*
* @param {String} path
* @param {Object|Function} options or fn
* @param {Function} fn
* @api public
*/
res.sendfile = function (path, options, fn) {
options = options || {};
var self = this;
var req = self.req;
var next = this.req.next;
var done;
// support function as second arg
if ('function' == typeof options) {
fn = options;
options = {};
}
// socket errors
req.socket.on('error', error);
// errors
function error(err) {
if (done) return;
done = true;
// clean up
cleanup();
if (!self.headersSent) self.removeHeader('Content-Disposition');
// callback available
if (fn) return fn(err);
// list in limbo if there's no callback
if (self.headersSent) return;
// delegate
next(err);
}
// streaming
function stream(stream) {
if (done) return;
cleanup();
if (fn) stream.on('end', fn);
}
// cleanup
function cleanup() {
req.socket.removeListener('error', error);
}
// Back-compat
options.maxage = options.maxage || options.maxAge || 0;
// transfer
var file = send(req, path, options);
file.on('error', error);
file.on('directory', next);
file.on('stream', stream);
file.pipe(this);
this.on('finish', cleanup);
};
/**
* Transfer the file at the given `path` as an attachment.
*
* Optionally providing an alternate attachment `filename`,
* and optional callback `fn(err)`. The callback is invoked
* when the data transfer is complete, or when an error has
* ocurred. Be sure to check `res.headersSent` if you plan to respond.
*
* This method uses `res.sendfile()`.
*
* @param {String} path
* @param {String|Function} filename or fn
* @param {Function} fn
* @api public
*/
res.download = function (path, filename, fn) {
// support function as second arg
if ('function' == typeof filename) {
fn = filename;
filename = null;
}
filename = filename || path;
this.set('Content-Disposition', contentDisposition(filename));
return this.sendfile(path, fn);
};
/**
* Set _Content-Type_ response header with `type` through `mime.lookup()`
* when it does not contain "/", or set the Content-Type to `type` otherwise.
*
* Examples:
*
* res.type('.html');
* res.type('html');
* res.type('json');
* res.type('application/json');
* res.type('png');
*
* @param {String} type
* @return {ServerResponse} for chaining
* @api public
*/
res.contentType =
res.type = function (type) {
return this.set('Content-Type', ~type.indexOf('/')
? type
: mime.lookup(type));
};
/**
* Respond to the Acceptable formats using an `obj`
* of mime-type callbacks.
*
* This method uses `req.accepted`, an array of
* acceptable types ordered by their quality values.
* When "Accept" is not present the _first_ callback
* is invoked, otherwise the first match is used. When
* no match is performed the server responds with
* 406 "Not Acceptable".
*
* Content-Type is set for you, however if you choose
* you may alter this within the callback using `res.type()`
* or `res.set('Content-Type', ...)`.
*
* res.format({
* 'text/plain': function(){
* res.send('hey');
* },
*
* 'text/html': function(){
* res.send('<p>hey</p>');
* },
*
* 'appliation/json': function(){
* res.send({ message: 'hey' });
* }
* });
*
* In addition to canonicalized MIME types you may
* also use extnames mapped to these types:
*
* res.format({
* text: function(){
* res.send('hey');
* },
*
* html: function(){
* res.send('<p>hey</p>');
* },
*
* json: function(){
* res.send({ message: 'hey' });
* }
* });
*
* By default Express passes an `Error`
* with a `.status` of 406 to `next(err)`
* if a match is not made. If you provide
* a `.default` callback it will be invoked
* instead.
*
* @param {Object} obj
* @return {ServerResponse} for chaining
* @api public
*/
res.format = function (obj) {
var req = this.req;
var next = req.next;
var fn = obj.default;
if (fn) delete obj.default;
var keys = Object.keys(obj);
var key = req.accepts(keys);
this.vary("Accept");
if (key) {
this.set('Content-Type', normalizeType(key).value);
obj[key](req, this, next);
} else if (fn) {
fn();
} else {
var err = new Error('Not Acceptable');
err.status = 406;
err.types = normalizeTypes(keys).map(function (o) {
return o.value
});
next(err);
}
return this;
};
/**
* Set _Content-Disposition_ header to _attachment_ with optional `filename`.
*
* @param {String} filename
* @return {ServerResponse}
* @api public
*/
res.attachment = function (filename) {
if (filename) this.type(extname(filename));
this.set('Content-Disposition', contentDisposition(filename));
return this;
};
/**
* Set header `field` to `val`, or pass
* an object of header fields.
*
* Examples:
*
* res.set('Foo', ['bar', 'baz']);
* res.set('Accept', 'application/json');
* res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });
*
* Aliased as `res.header()`.
*
* @param {String|Object|Array} field
* @param {String} val
* @return {ServerResponse} for chaining
* @api public
*/
res.set =
res.header = function (field, val) {
if (2 == arguments.length) {
if (Array.isArray(val)) val = val.map(String);
else val = String(val);
if ('content-type' == field.toLowerCase() && !/;\s*charset\s*=/.test(val)) {
var charset = mime.charsets.lookup(val.split(';')[0]);
if (charset) val += '; charset=' + charset.toLowerCase();
}
this.setHeader(field, val);
} else {
for (var key in field) {
this.set(key, field[key]);
}
}
return this;
};
/**
* Get value for header `field`.
*
* @param {String} field
* @return {String}
* @api public
*/
res.get = function (field) {
return this.getHeader(field);
};
/**
* Clear cookie `name`.
*
* @param {String} name
* @param {Object} options
* @param {ServerResponse} for chaining
* @api public
*/
res.clearCookie = function (name, options) {
var opts = { expires: new Date(1), path: '/' };
return this.cookie(name, '', options
? mixin(opts, options)
: opts);
};
/**
* Set cookie `name` to `val`, with the given `options`.
*
* Options:
*
* - `maxAge` max-age in milliseconds, converted to `expires`
* - `signed` sign the cookie
* - `path` defaults to "/"
*
* Examples:
*
* // "Remember Me" for 15 minutes
* res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
*
* // save as above
* res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })
*
* @param {String} name
* @param {String|Object} val
* @param {Options} options
* @api public
*/
res.cookie = function (name, val, options) {
options = mixin({}, options);
var secret = this.req.secret;
var signed = options.signed;
if (signed && !secret) throw new Error('cookieParser("secret") required for signed cookies');
if ('number' == typeof val) val = val.toString();
if ('object' == typeof val) val = 'j:' + JSON.stringify(val);
if (signed) val = 's:' + sign(val, secret);
if ('maxAge' in options) {
options.expires = new Date(Date.now() + options.maxAge);
options.maxAge /= 1000;
}
if (null == options.path) options.path = '/';
var headerVal = cookie.serialize(name, String(val), options);
// supports multiple 'res.cookie' calls by getting previous value
var prev = this.get('Set-Cookie');
if (prev) {
if (Array.isArray(prev)) {
headerVal = prev.concat(headerVal);
} else {
headerVal = [prev, headerVal];
}
}
this.set('Set-Cookie', headerVal);
return this;
};
/**
* Set the location header to `url`.
*
* The given `url` can also be "back", which redirects
* to the _Referrer_ or _Referer_ headers or "/".
*
* Examples:
*
* res.location('/foo/bar').;
* res.location('http://example.com');
* res.location('../login');
*
* @param {String} url
* @api public
*/
res.location = function (url) {
var req = this.req;
// "back" is an alias for the referrer
if ('back' == url) url = req.get('Referrer') || '/';
// Respond
this.set('Location', url);
return this;
};
/**
* Redirect to the given `url` with optional response `status`
* defaulting to 302.
*
* The resulting `url` is determined by `res.location()`, so
* it will play nicely with mounted apps, relative paths,
* `"back"` etc.
*
* Examples:
*
* res.redirect('/foo/bar');
* res.redirect('http://example.com');
* res.redirect(301, 'http://example.com');
* res.redirect('http://example.com', 301);
* res.redirect('../login'); // /blog/post/1 -> /blog/login
*
* @param {String} url
* @param {Number} code
* @api public
*/
res.redirect = function (url) {
var head = 'HEAD' == this.req.method;
var status = 302;
var body;
// allow status / url
if (2 == arguments.length) {
if ('number' == typeof url) {
status = url;
url = arguments[1];
} else {
status = arguments[1];
}
}
// Set location header
this.location(url);
url = this.get('Location');
// Support text/{plain,html} by default
this.format({
text: function () {
body = statusCodes[status] + '. Redirecting to ' + encodeURI(url);
},
html: function () {
var u = escapeHtml(url);
body = '<p>' + statusCodes[status] + '. Redirecting to <a href="' + u + '">' + u + '</a></p>';
},
default: function () {
body = '';
}
});
// Respond
this.statusCode = status;
this.set('Content-Length', Buffer.byteLength(body));
this.end(head ? null : body);
};
/**
* Add `field` to Vary. If already present in the Vary set, then
* this call is simply ignored.
*
* @param {Array|String} field
* @param {ServerResponse} for chaining
* @api public
*/
res.vary = function (field) {
var self = this;
// nothing
if (!field) return this;
// array
if (Array.isArray(field)) {
field.forEach(function (field) {
self.vary(field);
});
return;
}
var vary = this.get('Vary');
// append
if (vary) {
vary = vary.split(/ *, */);
if (!~vary.indexOf(field)) vary.push(field);
this.set('Vary', vary.join(', '));
return this;
}
// set
this.set('Vary', field);
return this;
};
/**
* Render `view` with the given `options` and optional callback `fn`.
* When a callback function is given a response will _not_ be made
* automatically, otherwise a response of _200_ and _text/html_ is given.
*
* Options:
*
* - `cache` boolean hinting to the engine it should cache
* - `filename` filename of the view being rendered
*
* @param {String} view
* @param {Object|Function} options or callback function
* @param {Function} fn
* @api public
*/
res.render = function (view, options, fn) {
options = options || {};
var self = this;
var req = this.req;
var app = req.app;
// support callback function as second arg
if ('function' == typeof options) {
fn = options, options = {};
}
// merge res.locals
options._locals = self.locals;
// default callback to respond
fn = fn || function (err, str) {
if (err) return req.next(err);
self.send(str);
};
// render
app.render(view, options, fn);
};
/**
* Module dependencies.
*/
var Route = require('./route');
var Layer = require('./layer');
var methods = require('methods');
var debug = require('debug')('express:router');
var parseUrl = require('parseurl');
var slice = Array.prototype.slice;
/**
* Initialize a new `Router` with the given `options`.
*
* @param {Object} options
* @return {Router} which is an callable function
* @api public
*/
var proto = module.exports = function (options) {
options = options || {};
function router(req, res, next) {
router.handle(req, res, next);
}
// mixin Router class functions
router.__proto__ = proto;
router.params = {};
router._params = [];
router.caseSensitive = options.caseSensitive;
router.strict = options.strict;
router.stack = [];
return router;
};
/**
* Map the given param placeholder `name`(s) to the given callback.
*
* Parameter mapping is used to provide pre-conditions to routes
* which use normalized placeholders. For example a _:user_id_ parameter
* could automatically load a user's information from the database without
* any additional code,
*
* The callback uses the same signature as middleware, the only difference
* being that the value of the placeholder is passed, in this case the _id_
* of the user. Once the `next()` function is invoked, just like middleware
* it will continue on to execute the route, or subsequent parameter functions.
*
* Just like in middleware, you must either respond to the request or call next
* to avoid stalling the request.
*
* app.param('user_id', function(req, res, next, id){
* User.find(id, function(err, user){
* if (err) {
* return next(err);
* } else if (!user) {
* return next(new Error('failed to load user'));
* }
* req.user = user;
* next();
* });
* });
*
* @param {String} name
* @param {Function} fn
* @return {app} for chaining
* @api public
*/
proto.param = function (name, fn) {
// param logic
if ('function' == typeof name) {
this._params.push(name);
return;
}
// apply param functions
var params = this._params;
var len = params.length;
var ret;
if (name[0] === ':') {
name = name.substr(1);
}
for (var i = 0; i < len; ++i) {
if (ret = params[i](name, fn)) {
fn = ret;
}
}
// ensure we end up with a
// middleware function
if ('function' != typeof fn) {
throw new Error('invalid param() call for ' + name + ', got ' + fn);
}
(this.params[name] = this.params[name] || []).push(fn);
return this;
};
/**
* Dispatch a req, res into the router.
*
* @api private
*/
proto.handle = function (req, res, done) {
var self = this;
debug('dispatching %s %s', req.method, req.url);
var method = req.method.toLowerCase();
var search = 1 + req.url.indexOf('?');
var pathlength = search ? search - 1 : req.url.length;
var fqdn = 1 + req.url.substr(0, pathlength).indexOf('://');
var protohost = fqdn ? req.url.substr(0, req.url.indexOf('/', 2 + fqdn)) : '';
var idx = 0;
var removed = '';
var slashAdded = false;
// store options for OPTIONS request
// only used if OPTIONS request
var options = [];
// middleware and routes
var stack = self.stack;
// request-level next
var parent = req.next;
done = wrap(done, function (old, err) {
req.next = parent;
old(err);
});
req.next = next;
// for options requests, respond with a default if nothing else responds
if (method === 'options') {
done = wrap(done, function (old, err) {
if (err || options.length === 0) return old(err);
var body = options.join(',');
return res.set('Allow', body).send(body);
});
}
next();
function next(err) {
if (err === 'route') {
err = undefined;
}
var layer = stack[idx++];
if (!layer) {
return done(err);
}
if (slashAdded) {
req.url = req.url.substr(1);
slashAdded = false;
}
req.url = protohost + removed + req.url.substr(protohost.length);
req.originalUrl = req.originalUrl || req.url;
removed = '';
try {
var path = parseUrl(req).pathname;
if (undefined == path) path = '/';
if (!layer.match(path)) return next(err);
// route object and not middleware
var route = layer.route;
// if final route, then we support options
if (route) {
// we don't run any routes with error first
if (err) {
return next(err);
}
req.route = route;
// we can now dispatch to the route
if (method === 'options' && !route.methods['options']) {
options.push.apply(options, route._options());
}
}
req.params = layer.params;
// this should be done for the layer
return self.process_params(layer, req, res, function (err) {
if (err) {
return next(err);
}
if (route) {
return layer.handle(req, res, next);
}
trim_prefix();
});
} catch (err) {
next(err);
}
function trim_prefix() {
var c = path[layer.path.length];
if (c && '/' != c && '.' != c) return next(err);
// Trim off the part of the url that matches the route
// middleware (.use stuff) needs to have the path stripped
debug('trim prefix (%s) from url %s', removed, req.url);
removed = layer.path;
req.url = protohost + req.url.substr(protohost.length + removed.length);
// Ensure leading slash
if (!fqdn && '/' != req.url[0]) {
req.url = '/' + req.url;
slashAdded = true;
}
debug('%s %s : %s', layer.handle.name || 'anonymous', layer.path, req.originalUrl);
var arity = layer.handle.length;
if (err) {
if (arity === 4) {
layer.handle(err, req, res, next);
} else {
next(err);
}
} else if (arity < 4) {
layer.handle(req, res, next);
} else {
next(err);
}
}
}
function wrap(old, fn) {
return function () {
var args = [old].concat(slice.call(arguments));
fn.apply(this, args);
};
}
};
/**
* Process any parameters for the route.
*
* @api private
*/
proto.process_params = function (route, req, res, done) {
var params = this.params;
// captured parameters from the route, keys and values
var keys = route.keys;
// fast track
if (!keys || keys.length === 0) {
return done();
}
var i = 0;
var paramIndex = 0;
var key;
var paramVal;
var paramCallbacks;
// process params in order
// param callbacks can be async
function param(err) {
if (err) {
return done(err);
}
if (i >= keys.length) {
return done();
}
paramIndex = 0;
key = keys[i++];
paramVal = key && req.params[key.name];
paramCallbacks = key && params[key.name];
try {
if (paramCallbacks && undefined !== paramVal) {
return paramCallback();
} else if (key) {
return param();
}
} catch (err) {
return done(err);
}
done();
}
// single param callbacks
function paramCallback(err) {
var fn = paramCallbacks[paramIndex++];
if (err || !fn) return param(err);
fn(req, res, paramCallback, paramVal, key.name);
}
param();
};
/**
* Use the given middleware function, with optional path, defaulting to "/".
*
* Use (like `.all`) will run for any http METHOD, but it will not add
* handlers for those methods so OPTIONS requests will not consider `.use`
* functions even if they could respond.
*
* The other difference is that _route_ path is stripped and not visible
* to the handler function. The main effect of this feature is that mounted
* handlers can operate without any code changes regardless of the "prefix"
* pathname.
*
* @param {String|Function} route
* @param {Function} fn
* @return {app} for chaining
* @api public
*/
proto.use = function (route, fn) {
// default route to '/'
if ('string' != typeof route) {
fn = route;
route = '/';
}
if (typeof fn !== 'function') {
var type = {}.toString.call(fn);
var msg = 'Router.use() requires callback functions but got a ' + type;
throw new Error(msg);
}
// strip trailing slash
if ('/' == route[route.length - 1]) {
route = route.slice(0, -1);
}
var layer = new Layer(route, {
sensitive: this.caseSensitive,
strict: this.strict,
end: false
}, fn);
// add the middleware
debug('use %s %s', route || '/', fn.name || 'anonymous');
this.stack.push(layer);
return this;
};
/**
* Create a new Route for the given path.
*
* Each route contains a separate middleware stack and VERB handlers.
*
* See the Route api documentation for details on adding handlers
* and middleware to routes.
*
* @param {String} path
* @return {Route}
* @api public
*/
proto.route = function (path) {
var route = new Route(path);
var layer = new Layer(path, {
sensitive: this.caseSensitive,
strict: this.strict,
end: true
}, route.dispatch.bind(route));
layer.route = route;
this.stack.push(layer);
return route;
};
// create Router#VERB functions
methods.concat('all').forEach(function (method) {
proto[method] = function (path) {
var route = this.route(path)
route[method].apply(route, [].slice.call(arguments, 1));
return this;
};
});
/**
* Module dependencies.
*/
var pathRegexp = require('path-to-regexp');
var debug = require('debug')('express:router:layer');
/**
* Expose `Layer`.
*/
module.exports = Layer;
function Layer(path, options, fn) {
if (!(this instanceof Layer)) {
return new Layer(path, options, fn);
}
debug('new %s', path);
options = options || {};
this.regexp = pathRegexp(path, this.keys = [], options);
this.handle = fn;
}
/**
* Check if this route matches `path`, if so
* populate `.params`.
*
* @param {String} path
* @return {Boolean}
* @api private
*/
Layer.prototype.match = function (path) {
var keys = this.keys;
var params = this.params = {};
var m = this.regexp.exec(path);
var n = 0;
var key;
var val;
if (!m) return false;
this.path = m[0];
for (var i = 1, len = m.length; i < len; ++i) {
key = keys[i - 1];
try {
val = 'string' == typeof m[i]
? decodeURIComponent(m[i])
: m[i];
} catch (e) {
var err = new Error("Failed to decode param '" + m[i] + "'");
err.status = 400;
throw err;
}
if (key) {
params[key.name] = val;
} else {
params[n++] = val;
}
}
return true;
};
/**
* Module dependencies.
*/
var debug = require('debug')('express:router:route');
var methods = require('methods');
var utils = require('../utils');
/**
* Expose `Route`.
*/
module.exports = Route;
/**
* Initialize `Route` with the given `path`,
*
* @param {String} path
* @api private
*/
function Route(path) {
debug('new %s', path);
this.path = path;
this.stack = undefined;
// route handlers for various http methods
this.methods = {};
}
/**
* @return {Array} supported HTTP methods
* @api private
*/
Route.prototype._options = function () {
return Object.keys(this.methods).map(function (method) {
return method.toUpperCase();
});
};
/**
* dispatch req, res into this route
*
* @api private
*/
Route.prototype.dispatch = function (req, res, done) {
var self = this;
var method = req.method.toLowerCase();
if (method === 'head' && !this.methods['head']) {
method = 'get';
}
req.route = self;
// single middleware route case
if (typeof this.stack === 'function') {
this.stack(req, res, done);
return;
}
var stack = self.stack;
if (!stack) {
return done();
}
var idx = 0;
(function next_layer(err) {
if (err && err === 'route') {
return done();
}
var layer = stack[idx++];
if (!layer) {
return done(err);
}
if (layer.method && layer.method !== method) {
return next_layer(err);
}
var arity = layer.handle.length;
if (err) {
if (arity < 4) {
return next_layer(err);
}
try {
layer.handle(err, req, res, next_layer);
} catch (err) {
next_layer(err);
}
return;
}
if (arity > 3) {
return next_layer();
}
try {
layer.handle(req, res, next_layer);
} catch (err) {
next_layer(err);
}
})();
};
/**
* Add a handler for all HTTP verbs to this route.
*
* Behaves just like middleware and can respond or call `next`
* to continue processing.
*
* You can use multiple `.all` call to add multiple handlers.
*
* function check_something(req, res, next){
* next();
* };
*
* function validate_user(req, res, next){
* next();
* };
*
* route
* .all(validate_user)
* .all(check_something)
* .get(function(req, res, next){
* res.send('hello world');
* });
*
* @param {function} handler
* @return {Route} for chaining
* @api public
*/
Route.prototype.all = function () {
var self = this;
var callbacks = utils.flatten([].slice.call(arguments));
callbacks.forEach(function (fn) {
if (typeof fn !== 'function') {
var type = {}.toString.call(fn);
var msg = 'Route.all() requires callback functions but got a ' + type;
throw new Error(msg);
}
if (!self.stack) {
self.stack = fn;
}
else if (typeof self.stack === 'function') {
self.stack = [
{ handle: self.stack },
{ handle: fn }
];
}
else {
self.stack.push({ handle: fn });
}
});
return self;
};
methods.forEach(function (method) {
Route.prototype[method] = function () {
var self = this;
var callbacks = utils.flatten([].slice.call(arguments));
callbacks.forEach(function (fn) {
if (typeof fn !== 'function') {
var type = {}.toString.call(fn);
var msg = 'Route.' + method + '() requires callback functions but got a ' + type;
throw new Error(msg);
}
debug('%s %s', method, self.path);
if (!self.methods[method]) {
self.methods[method] = true;
}
if (!self.stack) {
self.stack = [];
}
else if (typeof self.stack === 'function') {
self.stack = [
{ handle: self.stack }
];
}
self.stack.push({ method: method, handle: fn });
});
return self;
};
});
/**
* Module dependencies.
*/
var mime = require('send').mime;
var crc32 = require('buffer-crc32');
var basename = require('path').basename;
var deprecate = require('util').deprecate;
/**
* Deprecate function, like core `util.deprecate`
*
* @param {Function} fn
* @param {String} msg
* @return {Function}
* @api private
*/
exports.deprecate = function (fn, msg) {
return 'test' !== process.env.NODE_ENV
? deprecate(fn, 'express: ' + msg)
: fn;
};
/**
* Return ETag for `body`.
*
* @param {String|Buffer} body
* @return {String}
* @api private
*/
exports.etag = function (body) {
return '"' + crc32.signed(body) + '"';
};
/**
* Check if `path` looks absolute.
*
* @param {String} path
* @return {Boolean}
* @api private
*/
exports.isAbsolute = function (path) {
if ('/' == path[0]) return true;
if (':' == path[1] && '\\' == path[2]) return true;
if ('\\\\' == path.substring(0, 2)) return true; // Microsoft Azure absolute path
};
/**
* Flatten the given `arr`.
*
* @param {Array} arr
* @return {Array}
* @api private
*/
exports.flatten = function (arr, ret) {
ret = ret || [];
var len = arr.length;
for (var i = 0; i < len; ++i) {
if (Array.isArray(arr[i])) {
exports.flatten(arr[i], ret);
} else {
ret.push(arr[i]);
}
}
return ret;
};
/**
* Normalize the given `type`, for example "html" becomes "text/html".
*
* @param {String} type
* @return {Object}
* @api private
*/
exports.normalizeType = function (type) {
return ~type.indexOf('/')
? acceptParams(type)
: { value: mime.lookup(type), params: {} };
};
/**
* Normalize `types`, for example "html" becomes "text/html".
*
* @param {Array} types
* @return {Array}
* @api private
*/
exports.normalizeTypes = function (types) {
var ret = [];
for (var i = 0; i < types.length; ++i) {
ret.push(exports.normalizeType(types[i]));
}
return ret;
};
/**
* Generate Content-Disposition header appropriate for the filename.
* non-ascii filenames are urlencoded and a filename* parameter is added
*
* @param {String} filename
* @return {String}
* @api private
*/
exports.contentDisposition = function (filename) {
var ret = 'attachment';
if (filename) {
filename = basename(filename);
// if filename contains non-ascii characters, add a utf-8 version ala RFC 5987
ret = /[^\040-\176]/.test(filename)
? 'attachment; filename=' + encodeURI(filename) + '; filename*=UTF-8\'\'' + encodeURI(filename)
: 'attachment; filename="' + filename + '"';
}
return ret;
};
/**
* Parse accept params `str` returning an
* object with `.value`, `.quality` and `.params`.
* also includes `.originalIndex` for stable sorting
*
* @param {String} str
* @return {Object}
* @api private
*/
function acceptParams(str, index) {
var parts = str.split(/ *; */);
var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index };
for (var i = 1; i < parts.length; ++i) {
var pms = parts[i].split(/ *= */);
if ('q' == pms[0]) {
ret.quality = parseFloat(pms[1]);
} else {
ret.params[pms[0]] = pms[1];
}
}
return ret;
}
/**
* Module dependencies.
*/
var path = require('path');
var fs = require('fs');
var utils = require('./utils');
var dirname = path.dirname;
var basename = path.basename;
var extname = path.extname;
var exists = fs.existsSync || path.existsSync;
var join = path.join;
/**
* Expose `View`.
*/
module.exports = View;
/**
* Initialize a new `View` with the given `name`.
*
* Options:
*
* - `defaultEngine` the default template engine name
* - `engines` template engine require() cache
* - `root` root path for view lookup
*
* @param {String} name
* @param {Object} options
* @api private
*/
function View(name, options) {
options = options || {};
this.name = name;
this.root = options.root;
var engines = options.engines;
this.defaultEngine = options.defaultEngine;
var ext = this.ext = extname(name);
if (!ext && !this.defaultEngine) throw new Error('No default engine was specified and no extension was provided.');
if (!ext) name += (ext = this.ext = ('.' != this.defaultEngine[0] ? '.' : '') + this.defaultEngine);
this.engine = engines[ext] || (engines[ext] = require(ext.slice(1)).__express);
this.path = this.lookup(name);
}
/**
* Lookup view by the given `path`
*
* @param {String} path
* @return {String}
* @api private
*/
View.prototype.lookup = function (path) {
var ext = this.ext;
// <path>.<engine>
if (!utils.isAbsolute(path)) path = join(this.root, path);
if (exists(path)) return path;
// <path>/index.<engine>
path = join(dirname(path), basename(path, ext), 'index' + ext);
if (exists(path)) return path;
};
/**
* Render with the given `options` and callback `fn(err, str)`.
*
* @param {Object} options
* @param {Function} fn
* @api private
*/
View.prototype.render = function (options, fn) {
this.engine(this.path, options, fn);
};
(The MIT License)
Copyright (c) 2009-2014 TJ Holowaychuk <[email protected]>
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.
MOCHA_OPTS= --check-leaks
REPORTER = dot
check: test
test: test-unit test-acceptance
test-unit:
@NODE_ENV=test ./node_modules/.bin/mocha \
--reporter $(REPORTER) \
--globals setImmediate,clearImmediate \
$(MOCHA_OPTS)
test-acceptance:
@NODE_ENV=test ./node_modules/.bin/mocha \
--reporter $(REPORTER) \
--bail \
test/acceptance/*.js
test-cov: lib-cov
@EXPRESS_COV=1 $(MAKE) test REPORTER=html-cov > coverage.html
lib-cov:
@jscoverage lib lib-cov
bench:
@$(MAKE) -C benchmarks
clean:
rm -f coverage.html
rm -fr lib-cov
.PHONY: test test-unit test-acceptance bench clean
var Negotiator = require('negotiator')
var mime = require('mime')
var slice = [].slice
module.exports = Accepts
function Accepts(req) {
if (!(this instanceof Accepts))
return new Accepts(req)
this.headers = req.headers
this.negotiator = Negotiator(req)
}
/**
* Check if the given `type(s)` is acceptable, returning
* the best match when true, otherwise `undefined`, in which
* case you should respond with 406 "Not Acceptable".
*
* The `type` value may be a single mime type string
* such as "application/json", the extension name
* such as "json" or an array `["json", "html", "text/plain"]`. When a list
* or array is given the _best_ match, if any is returned.
*
* Examples:
*
* // Accept: text/html
* this.accepts('html');
* // => "html"
*
* // Accept: text/*, application/json
* this.accepts('html');
* // => "html"
* this.accepts('text/html');
* // => "text/html"
* this.accepts('json', 'text');
* // => "json"
* this.accepts('application/json');
* // => "application/json"
*
* // Accept: text/*, application/json
* this.accepts('image/png');
* this.accepts('png');
* // => undefined
*
* // Accept: text/*;q=.5, application/json
* this.accepts(['html', 'json']);
* this.accepts('html', 'json');
* // => "json"
*
* @param {String|Array} type(s)...
* @return {String|Array|Boolean}
* @api public
*/
Accepts.prototype.type =
Accepts.prototype.types = function (types) {
if (!Array.isArray(types)) types = slice.call(arguments);
var n = this.negotiator;
if (!types.length) return n.mediaTypes();
if (!this.headers.accept) return types[0];
var mimes = types.map(extToMime);
var accepts = n.mediaTypes(mimes);
var first = accepts[0];
if (!first) return false;
return types[mimes.indexOf(first)];
}
/**
* Return accepted encodings or best fit based on `encodings`.
*
* Given `Accept-Encoding: gzip, deflate`
* an array sorted by quality is returned:
*
* ['gzip', 'deflate']
*
* @param {String|Array} encoding(s)...
* @return {String|Array}
* @api public
*/
Accepts.prototype.encoding =
Accepts.prototype.encodings = function (encodings) {
if (!Array.isArray(encodings)) encodings = slice.call(arguments);
var n = this.negotiator;
if (!encodings.length) return n.encodings();
return n.encodings(encodings)[0] || false;
}
/**
* Return accepted charsets or best fit based on `charsets`.
*
* Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5`
* an array sorted by quality is returned:
*
* ['utf-8', 'utf-7', 'iso-8859-1']
*
* @param {String|Array} charset(s)...
* @return {String|Array}
* @api public
*/
Accepts.prototype.charset =
Accepts.prototype.charsets = function (charsets) {
if (!Array.isArray(charsets)) charsets = [].slice.call(arguments);
var n = this.negotiator;
if (!charsets.length) return n.charsets();
if (!this.headers['accept-charset']) return charsets[0];
return n.charsets(charsets)[0] || false;
}
/**
* Return accepted languages or best fit based on `langs`.
*
* Given `Accept-Language: en;q=0.8, es, pt`
* an array sorted by quality is returned:
*
* ['es', 'pt', 'en']
*
* @param {String|Array} lang(s)...
* @return {Array|String}
* @api public
*/
Accepts.prototype.lang =
Accepts.prototype.langs =
Accepts.prototype.language =
Accepts.prototype.languages = function (langs) {
if (!Array.isArray(langs)) langs = slice.call(arguments);
var n = this.negotiator;
if (!langs.length) return n.languages();
if (!this.headers['accept-language']) return langs[0];
return n.languages(langs)[0] || false;
}
/**
* Convert extnames to mime.
*
* @param {String} type
* @return {String}
* @api private
*/
function extToMime(type) {
if (~type.indexOf('/')) return type;
return mime.lookup(type);
}
BIN = ./node_modules/.bin/
test:
@${BIN}mocha \
--require should \
--reporter spec
.PHONY: test
Copyright (c) 2010 Benjamin Thomas, Robert Kieffer
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.
var path = require('path');
var fs = require('fs');
function Mime() {
// Map of extension -> mime type
this.types = Object.create(null);
// Map of mime type -> extension
this.extensions = Object.create(null);
}
/**
* Define mimetype -> extension mappings. Each key is a mime-type that maps
* to an array of extensions associated with the type. The first extension is
* used as the default extension for the type.
*
* e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']});
*
* @param map (Object) type definitions
*/
Mime.prototype.define = function (map) {
for (var type in map) {
var exts = map[type];
for (var i = 0; i < exts.length; i++) {
if (process.env.DEBUG_MIME && this.types[exts]) {
console.warn(this._loading.replace(/.*\//, ''), 'changes "' + exts[i] + '" extension type from ' +
this.types[exts] + ' to ' + type);
}
this.types[exts[i]] = type;
}
// Default extension is the first one we encounter
if (!this.extensions[type]) {
this.extensions[type] = exts[0];
}
}
};
/**
* Load an Apache2-style ".types" file
*
* This may be called multiple times (it's expected). Where files declare
* overlapping types/extensions, the last file wins.
*
* @param file (String) path of file to load.
*/
Mime.prototype.load = function (file) {
this._loading = file;
// Read file and split into lines
var map = {},
content = fs.readFileSync(file, 'ascii'),
lines = content.split(/[\r\n]+/);
lines.forEach(function (line) {
// Clean up whitespace/comments, and split into fields
var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/);
map[fields.shift()] = fields;
});
this.define(map);
this._loading = null;
};
/**
* Lookup a mime type based on extension
*/
Mime.prototype.lookup = function (path, fallback) {
var ext = path.replace(/.*[\.\/\\]/, '').toLowerCase();
return this.types[ext] || fallback || this.default_type;
};
/**
* Return file extension associated with a mime type
*/
Mime.prototype.extension = function (mimeType) {
var type = mimeType.match(/^\s*([^;\s]*)(?:;|\s|$)/)[1].toLowerCase();
return this.extensions[type];
};
// Default instance
var mime = new Mime();
// Load local copy of
// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
mime.load(path.join(__dirname, 'types/mime.types'));
// Load additional types from node.js community
mime.load(path.join(__dirname, 'types/node.types'));
// Default type
mime.default_type = mime.lookup('bin');
//
// Additional API specific to the default instance
//
mime.Mime = Mime;
/**
* Lookup a charset based on mime type.
*/
mime.charsets = {
lookup: function (mimeType, fallback) {
// Assume text types are utf8
return (/^text\//).test(mimeType) ? 'UTF-8' : fallback;
}
};
module.exports = mime;
{
"author": {
"name": "Robert Kieffer",
"email": "[email protected]",
"url": "http://github.com/broofa"
},
"contributors": [
{
"name": "Benjamin Thomas",
"email": "[email protected]",
"url": "http://github.com/bentomas"
}
],
"dependencies": {},
"description": "A comprehensive library for mime-type mapping",
"devDependencies": {},
"keywords": [
"util",
"mime"
],
"main": "mime.js",
"name": "mime",
"repository": {
"url": "https://github.com/broofa/node-mime",
"type": "git"
},
"version": "1.2.11",
"readme": "# mime\n\nComprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.\n\n## Install\n\nInstall with [npm](http://github.com/isaacs/npm):\n\n npm install mime\n\n## API - Queries\n\n### mime.lookup(path)\nGet the mime type associated with a file, if no mime type is found `application/octet-stream` is returned. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.'). E.g.\n\n var mime = require('mime');\n\n mime.lookup('/path/to/file.txt'); // => 'text/plain'\n mime.lookup('file.txt'); // => 'text/plain'\n mime.lookup('.TXT'); // => 'text/plain'\n mime.lookup('htm'); // => 'text/html'\n\n### mime.default_type\nSets the mime type returned when `mime.lookup` fails to find the extension searched for. (Default is `application/octet-stream`.)\n\n### mime.extension(type)\nGet the default extension for `type`\n\n mime.extension('text/html'); // => 'html'\n mime.extension('application/octet-stream'); // => 'bin'\n\n### mime.charsets.lookup()\n\nMap mime-type to charset\n\n mime.charsets.lookup('text/plain'); // => 'UTF-8'\n\n(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.)\n\n## API - Defining Custom Types\n\nThe following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types).\n\n### mime.define()\n\nAdd custom mime/extension mappings\n\n mime.define({\n 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],\n 'application/x-my-type': ['x-mt', 'x-mtt'],\n // etc ...\n });\n\n mime.lookup('x-sft'); // => 'text/x-some-format'\n\nThe first entry in the extensions array is returned by `mime.extension()`. E.g.\n\n mime.extension('text/x-some-format'); // => 'x-sf'\n\n### mime.load(filepath)\n\nLoad mappings from an Apache \".types\" format file\n\n mime.load('./my_project.types');\n\nThe .types file format is simple - See the `types` dir for examples.\n",
"readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/broofa/node-mime/issues"
},
"homepage": "https://github.com/broofa/node-mime",
"_id": "[email protected]",
"dist": {
"shasum": "8401d4ab4f06fcf4bc53e86d918c0443ccaa7274"
},
"_from": "mime@~1.2.11",
"_resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz"
}

mime

Comprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.

Install

Install with npm:

npm install mime

API - Queries

mime.lookup(path)

Get the mime type associated with a file, if no mime type is found application/octet-stream is returned. Performs a case-insensitive lookup using the extension in path (the substring after the last '/' or '.'). E.g.

var mime = require('mime');

mime.lookup('/path/to/file.txt');         // => 'text/plain'
mime.lookup('file.txt');                  // => 'text/plain'
mime.lookup('.TXT');                      // => 'text/plain'
mime.lookup('htm');                       // => 'text/html'

mime.default_type

Sets the mime type returned when mime.lookup fails to find the extension searched for. (Default is application/octet-stream.)

mime.extension(type)

Get the default extension for type

mime.extension('text/html');                 // => 'html'
mime.extension('application/octet-stream');  // => 'bin'

mime.charsets.lookup()

Map mime-type to charset

mime.charsets.lookup('text/plain');        // => 'UTF-8'

(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.)

API - Defining Custom Types

The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see requesting new types.

mime.define()

Add custom mime/extension mappings

mime.define({
    'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],
    'application/x-my-type': ['x-mt', 'x-mtt'],
    // etc ...
});

mime.lookup('x-sft');                 // => 'text/x-some-format'

The first entry in the extensions array is returned by mime.extension(). E.g.

mime.extension('text/x-some-format'); // => 'x-sf'

mime.load(filepath)

Load mappings from an Apache ".types" format file

mime.load('./my_project.types');

The .types file format is simple - See the types dir for examples.

/**
* Usage: node test.js
*/
var mime = require('./mime');
var assert = require('assert');
var path = require('path');
function eq(a, b) {
console.log('Test: ' + a + ' === ' + b);
assert.strictEqual.apply(null, arguments);
}
console.log(Object.keys(mime.extensions).length + ' types');
console.log(Object.keys(mime.types).length + ' extensions\n');
//
// Test mime lookups
//
eq('text/plain', mime.lookup('text.txt')); // normal file
eq('text/plain', mime.lookup('TEXT.TXT')); // uppercase
eq('text/plain', mime.lookup('dir/text.txt')); // dir + file
eq('text/plain', mime.lookup('.text.txt')); // hidden file
eq('text/plain', mime.lookup('.txt')); // nameless
eq('text/plain', mime.lookup('txt')); // extension-only
eq('text/plain', mime.lookup('/txt')); // extension-less ()
eq('text/plain', mime.lookup('\\txt')); // Windows, extension-less
eq('application/octet-stream', mime.lookup('text.nope')); // unrecognized
eq('fallback', mime.lookup('text.fallback', 'fallback')); // alternate default
//
// Test extensions
//
eq('txt', mime.extension(mime.types.text));
eq('html', mime.extension(mime.types.htm));
eq('bin', mime.extension('application/octet-stream'));
eq('bin', mime.extension('application/octet-stream '));
eq('html', mime.extension(' text/html; charset=UTF-8'));
eq('html', mime.extension('text/html; charset=UTF-8 '));
eq('html', mime.extension('text/html; charset=UTF-8'));
eq('html', mime.extension('text/html ; charset=UTF-8'));
eq('html', mime.extension('text/html;charset=UTF-8'));
eq('html', mime.extension('text/Html;charset=UTF-8'));
eq(undefined, mime.extension('unrecognized'));
//
// Test node.types lookups
//
eq('application/font-woff', mime.lookup('file.woff'));
eq('application/octet-stream', mime.lookup('file.buffer'));
eq('audio/mp4', mime.lookup('file.m4a'));
eq('font/opentype', mime.lookup('file.otf'));
//
// Test charsets
//
eq('UTF-8', mime.charsets.lookup('text/plain'));
eq(undefined, mime.charsets.lookup(mime.types.js));
eq('fallback', mime.charsets.lookup('application/octet-stream', 'fallback'));
//
// Test for overlaps between mime.types and node.types
//
var apacheTypes = new mime.Mime(), nodeTypes = new mime.Mime();
apacheTypes.load(path.join(__dirname, 'types/mime.types'));
nodeTypes.load(path.join(__dirname, 'types/node.types'));
var keys = [].concat(Object.keys(apacheTypes.types))
.concat(Object.keys(nodeTypes.types));
keys.sort();
for (var i = 1; i < keys.length; i++) {
if (keys[i] == keys[i - 1]) {
console.warn('Warning: ' +
'node.types defines ' + keys[i] + '->' + nodeTypes.types[keys[i]] +
', mime.types defines ' + keys[i] + '->' + apacheTypes.types[keys[i]]);
}
}
console.log('\nOK');
# This file maps Internet media types to unique file extension(s).
# Although created for httpd, this file is used by many software systems
# and has been placed in the public domain for unlimited redisribution.
#
# The table below contains both registered and (common) unregistered types.
# A type that has no unique extension can be ignored -- they are listed
# here to guide configurations toward known types and to make it easier to
# identify "new" types. File extensions are also commonly used to indicate
# content languages and encodings, so choose them carefully.
#
# Internet media types should be registered as described in RFC 4288.
# The registry is at <http://www.iana.org/assignments/media-types/>.
#
# MIME type (lowercased) Extensions
# ============================================ ==========
# application/1d-interleaved-parityfec
# application/3gpp-ims+xml
# application/activemessage
application/andrew-inset ez
# application/applefile
application/applixware aw
application/atom+xml atom
application/atomcat+xml atomcat
# application/atomicmail
application/atomsvc+xml atomsvc
# application/auth-policy+xml
# application/batch-smtp
# application/beep+xml
# application/calendar+xml
# application/cals-1840
# application/ccmp+xml
application/ccxml+xml ccxml
application/cdmi-capability cdmia
application/cdmi-container cdmic
application/cdmi-domain cdmid
application/cdmi-object cdmio
application/cdmi-queue cdmiq
# application/cea-2018+xml
# application/cellml+xml
# application/cfw
# application/cnrp+xml
# application/commonground
# application/conference-info+xml
# application/cpl+xml
# application/csta+xml
# application/cstadata+xml
application/cu-seeme cu
# application/cybercash
application/davmount+xml davmount
# application/dca-rft
# application/dec-dx
# application/dialog-info+xml
# application/dicom
# application/dns
application/docbook+xml dbk
# application/dskpp+xml
application/dssc+der dssc
application/dssc+xml xdssc
# application/dvcs
application/ecmascript ecma
# application/edi-consent
# application/edi-x12
# application/edifact
application/emma+xml emma
# application/epp+xml
application/epub+zip epub
# application/eshop
# application/example
application/exi exi
# application/fastinfoset
# application/fastsoap
# application/fits
application/font-tdpfr pfr
# application/framework-attributes+xml
application/gml+xml gml
application/gpx+xml gpx
application/gxf gxf
# application/h224
# application/held+xml
# application/http
application/hyperstudio stk
# application/ibe-key-request+xml
# application/ibe-pkg-reply+xml
# application/ibe-pp-data
# application/iges
# application/im-iscomposing+xml
# application/index
# application/index.cmd
# application/index.obj
# application/index.response
# application/index.vnd
application/inkml+xml ink inkml
# application/iotp
application/ipfix ipfix
# application/ipp
# application/isup
application/java-archive jar
application/java-serialized-object ser
application/java-vm class
application/javascript js
application/json json
application/jsonml+json jsonml
# application/kpml-request+xml
# application/kpml-response+xml
application/lost+xml lostxml
application/mac-binhex40 hqx
application/mac-compactpro cpt
# application/macwriteii
application/mads+xml mads
application/marc mrc
application/marcxml+xml mrcx
application/mathematica ma nb mb
# application/mathml-content+xml
# application/mathml-presentation+xml
application/mathml+xml mathml
# application/mbms-associated-procedure-description+xml
# application/mbms-deregister+xml
# application/mbms-envelope+xml
# application/mbms-msk+xml
# application/mbms-msk-response+xml
# application/mbms-protection-description+xml
# application/mbms-reception-report+xml
# application/mbms-register+xml
# application/mbms-register-response+xml
# application/mbms-user-service-description+xml
application/mbox mbox
# application/media_control+xml
application/mediaservercontrol+xml mscml
application/metalink+xml metalink
application/metalink4+xml meta4
application/mets+xml mets
# application/mikey
application/mods+xml mods
# application/moss-keys
# application/moss-signature
# application/mosskey-data
# application/mosskey-request
application/mp21 m21 mp21
application/mp4 mp4s
# application/mpeg4-generic
# application/mpeg4-iod
# application/mpeg4-iod-xmt
# application/msc-ivr+xml
# application/msc-mixer+xml
application/msword doc dot
application/mxf mxf
# application/nasdata
# application/news-checkgroups
# application/news-groupinfo
# application/news-transmission
# application/nss
# application/ocsp-request
# application/ocsp-response
application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy
application/oda oda
application/oebps-package+xml opf
application/ogg ogx
application/omdoc+xml omdoc
application/onenote onetoc onetoc2 onetmp onepkg
application/oxps oxps
# application/parityfec
application/patch-ops-error+xml xer
application/pdf pdf
application/pgp-encrypted pgp
# application/pgp-keys
application/pgp-signature asc sig
application/pics-rules prf
# application/pidf+xml
# application/pidf-diff+xml
application/pkcs10 p10
application/pkcs7-mime p7m p7c
application/pkcs7-signature p7s
application/pkcs8 p8
application/pkix-attr-cert ac
application/pkix-cert cer
application/pkix-crl crl
application/pkix-pkipath pkipath
application/pkixcmp pki
application/pls+xml pls
# application/poc-settings+xml
application/postscript ai eps ps
# application/prs.alvestrand.titrax-sheet
application/prs.cww cww
# application/prs.nprend
# application/prs.plucker
# application/prs.rdf-xml-crypt
# application/prs.xsf+xml
application/pskc+xml pskcxml
# application/qsig
application/rdf+xml rdf
application/reginfo+xml rif
application/relax-ng-compact-syntax rnc
# application/remote-printing
application/resource-lists+xml rl
application/resource-lists-diff+xml rld
# application/riscos
# application/rlmi+xml
application/rls-services+xml rs
application/rpki-ghostbusters gbr
application/rpki-manifest mft
application/rpki-roa roa
# application/rpki-updown
application/rsd+xml rsd
application/rss+xml rss
application/rtf rtf
# application/rtx
# application/samlassertion+xml
# application/samlmetadata+xml
application/sbml+xml sbml
application/scvp-cv-request scq
application/scvp-cv-response scs
application/scvp-vp-request spq
application/scvp-vp-response spp
application/sdp sdp
# application/set-payment
application/set-payment-initiation setpay
# application/set-registration
application/set-registration-initiation setreg
# application/sgml
# application/sgml-open-catalog
application/shf+xml shf
# application/sieve
# application/simple-filter+xml
# application/simple-message-summary
# application/simplesymbolcontainer
# application/slate
# application/smil
application/smil+xml smi smil
# application/soap+fastinfoset
# application/soap+xml
application/sparql-query rq
application/sparql-results+xml srx
# application/spirits-event+xml
application/srgs gram
application/srgs+xml grxml
application/sru+xml sru
application/ssdl+xml ssdl
application/ssml+xml ssml
# application/tamp-apex-update
# application/tamp-apex-update-confirm
# application/tamp-community-update
# application/tamp-community-update-confirm
# application/tamp-error
# application/tamp-sequence-adjust
# application/tamp-sequence-adjust-confirm
# application/tamp-status-query
# application/tamp-status-response
# application/tamp-update
# application/tamp-update-confirm
application/tei+xml tei teicorpus
application/thraud+xml tfi
# application/timestamp-query
# application/timestamp-reply
application/timestamped-data tsd
# application/tve-trigger
# application/ulpfec
# application/vcard+xml
# application/vemmi
# application/vividence.scriptfile
# application/vnd.3gpp.bsf+xml
application/vnd.3gpp.pic-bw-large plb
application/vnd.3gpp.pic-bw-small psb
application/vnd.3gpp.pic-bw-var pvb
# application/vnd.3gpp.sms
# application/vnd.3gpp2.bcmcsinfo+xml
# application/vnd.3gpp2.sms
application/vnd.3gpp2.tcap tcap
application/vnd.3m.post-it-notes pwn
application/vnd.accpac.simply.aso aso
application/vnd.accpac.simply.imp imp
application/vnd.acucobol acu
application/vnd.acucorp atc acutc
application/vnd.adobe.air-application-installer-package+zip air
application/vnd.adobe.formscentral.fcdt fcdt
application/vnd.adobe.fxp fxp fxpl
# application/vnd.adobe.partial-upload
application/vnd.adobe.xdp+xml xdp
application/vnd.adobe.xfdf xfdf
# application/vnd.aether.imp
# application/vnd.ah-barcode
application/vnd.ahead.space ahead
application/vnd.airzip.filesecure.azf azf
application/vnd.airzip.filesecure.azs azs
application/vnd.amazon.ebook azw
application/vnd.americandynamics.acc acc
application/vnd.amiga.ami ami
# application/vnd.amundsen.maze+xml
application/vnd.android.package-archive apk
application/vnd.anser-web-certificate-issue-initiation cii
application/vnd.anser-web-funds-transfer-initiation fti
application/vnd.antix.game-component atx
application/vnd.apple.installer+xml mpkg
application/vnd.apple.mpegurl m3u8
# application/vnd.arastra.swi
application/vnd.aristanetworks.swi swi
application/vnd.astraea-software.iota iota
application/vnd.audiograph aep
# application/vnd.autopackage
# application/vnd.avistar+xml
application/vnd.blueice.multipass mpm
# application/vnd.bluetooth.ep.oob
application/vnd.bmi bmi
application/vnd.businessobjects rep
# application/vnd.cab-jscript
# application/vnd.canon-cpdl
# application/vnd.canon-lips
# application/vnd.cendio.thinlinc.clientconf
application/vnd.chemdraw+xml cdxml
application/vnd.chipnuts.karaoke-mmd mmd
application/vnd.cinderella cdy
# application/vnd.cirpack.isdn-ext
application/vnd.claymore cla
application/vnd.cloanto.rp9 rp9
application/vnd.clonk.c4group c4g c4d c4f c4p c4u
application/vnd.cluetrust.cartomobile-config c11amc
application/vnd.cluetrust.cartomobile-config-pkg c11amz
# application/vnd.collection+json
# application/vnd.commerce-battelle
application/vnd.commonspace csp
application/vnd.contact.cmsg cdbcmsg
application/vnd.cosmocaller cmc
application/vnd.crick.clicker clkx
application/vnd.crick.clicker.keyboard clkk
application/vnd.crick.clicker.palette clkp
application/vnd.crick.clicker.template clkt
application/vnd.crick.clicker.wordbank clkw
application/vnd.criticaltools.wbs+xml wbs
application/vnd.ctc-posml pml
# application/vnd.ctct.ws+xml
# application/vnd.cups-pdf
# application/vnd.cups-postscript
application/vnd.cups-ppd ppd
# application/vnd.cups-raster
# application/vnd.cups-raw
# application/vnd.curl
application/vnd.curl.car car
application/vnd.curl.pcurl pcurl
# application/vnd.cybank
application/vnd.dart dart
application/vnd.data-vision.rdz rdz
application/vnd.dece.data uvf uvvf uvd uvvd
application/vnd.dece.ttml+xml uvt uvvt
application/vnd.dece.unspecified uvx uvvx
application/vnd.dece.zip uvz uvvz
application/vnd.denovo.fcselayout-link fe_launch
# application/vnd.dir-bi.plate-dl-nosuffix
application/vnd.dna dna
application/vnd.dolby.mlp mlp
# application/vnd.dolby.mobile.1
# application/vnd.dolby.mobile.2
application/vnd.dpgraph dpg
application/vnd.dreamfactory dfac
application/vnd.ds-keypoint kpxx
application/vnd.dvb.ait ait
# application/vnd.dvb.dvbj
# application/vnd.dvb.esgcontainer
# application/vnd.dvb.ipdcdftnotifaccess
# application/vnd.dvb.ipdcesgaccess
# application/vnd.dvb.ipdcesgaccess2
# application/vnd.dvb.ipdcesgpdd
# application/vnd.dvb.ipdcroaming
# application/vnd.dvb.iptv.alfec-base
# application/vnd.dvb.iptv.alfec-enhancement
# application/vnd.dvb.notif-aggregate-root+xml
# application/vnd.dvb.notif-container+xml
# application/vnd.dvb.notif-generic+xml
# application/vnd.dvb.notif-ia-msglist+xml
# application/vnd.dvb.notif-ia-registration-request+xml
# application/vnd.dvb.notif-ia-registration-response+xml
# application/vnd.dvb.notif-init+xml
# application/vnd.dvb.pfr
application/vnd.dvb.service svc
# application/vnd.dxr
application/vnd.dynageo geo
# application/vnd.easykaraoke.cdgdownload
# application/vnd.ecdis-update
application/vnd.ecowin.chart mag
# application/vnd.ecowin.filerequest
# application/vnd.ecowin.fileupdate
# application/vnd.ecowin.series
# application/vnd.ecowin.seriesrequest
# application/vnd.ecowin.seriesupdate
# application/vnd.emclient.accessrequest+xml
application/vnd.enliven nml
# application/vnd.eprints.data+xml
application/vnd.epson.esf esf
application/vnd.epson.msf msf
application/vnd.epson.quickanime qam
application/vnd.epson.salt slt
application/vnd.epson.ssf ssf
# application/vnd.ericsson.quickcall
application/vnd.eszigno3+xml es3 et3
# application/vnd.etsi.aoc+xml
# application/vnd.etsi.cug+xml
# application/vnd.etsi.iptvcommand+xml
# application/vnd.etsi.iptvdiscovery+xml
# application/vnd.etsi.iptvprofile+xml
# application/vnd.etsi.iptvsad-bc+xml
# application/vnd.etsi.iptvsad-cod+xml
# application/vnd.etsi.iptvsad-npvr+xml
# application/vnd.etsi.iptvservice+xml
# application/vnd.etsi.iptvsync+xml
# application/vnd.etsi.iptvueprofile+xml
# application/vnd.etsi.mcid+xml
# application/vnd.etsi.overload-control-policy-dataset+xml
# application/vnd.etsi.sci+xml
# application/vnd.etsi.simservs+xml
# application/vnd.etsi.tsl+xml
# application/vnd.etsi.tsl.der
# application/vnd.eudora.data
application/vnd.ezpix-album ez2
application/vnd.ezpix-package ez3
# application/vnd.f-secure.mobile
application/vnd.fdf fdf
application/vnd.fdsn.mseed mseed
application/vnd.fdsn.seed seed dataless
# application/vnd.ffsns
# application/vnd.fints
application/vnd.flographit gph
application/vnd.fluxtime.clip ftc
# application/vnd.font-fontforge-sfd
application/vnd.framemaker fm frame maker book
application/vnd.frogans.fnc fnc
application/vnd.frogans.ltf ltf
application/vnd.fsc.weblaunch fsc
application/vnd.fujitsu.oasys oas
application/vnd.fujitsu.oasys2 oa2
application/vnd.fujitsu.oasys3 oa3
application/vnd.fujitsu.oasysgp fg5
application/vnd.fujitsu.oasysprs bh2
# application/vnd.fujixerox.art-ex
# application/vnd.fujixerox.art4
# application/vnd.fujixerox.hbpl
application/vnd.fujixerox.ddd ddd
application/vnd.fujixerox.docuworks xdw
application/vnd.fujixerox.docuworks.binder xbd
# application/vnd.fut-misnet
application/vnd.fuzzysheet fzs
application/vnd.genomatix.tuxedo txd
# application/vnd.geocube+xml
application/vnd.geogebra.file ggb
application/vnd.geogebra.tool ggt
application/vnd.geometry-explorer gex gre
application/vnd.geonext gxt
application/vnd.geoplan g2w
application/vnd.geospace g3w
# application/vnd.globalplatform.card-content-mgt
# application/vnd.globalplatform.card-content-mgt-response
application/vnd.gmx gmx
application/vnd.google-earth.kml+xml kml
application/vnd.google-earth.kmz kmz
application/vnd.grafeq gqf gqs
# application/vnd.gridmp
application/vnd.groove-account gac
application/vnd.groove-help ghf
application/vnd.groove-identity-message gim
application/vnd.groove-injector grv
application/vnd.groove-tool-message gtm
application/vnd.groove-tool-template tpl
application/vnd.groove-vcard vcg
# application/vnd.hal+json
application/vnd.hal+xml hal
application/vnd.handheld-entertainment+xml zmm
application/vnd.hbci hbci
# application/vnd.hcl-bireports
application/vnd.hhe.lesson-player les
application/vnd.hp-hpgl hpgl
application/vnd.hp-hpid hpid
application/vnd.hp-hps hps
application/vnd.hp-jlyt jlt
application/vnd.hp-pcl pcl
application/vnd.hp-pclxl pclxl
# application/vnd.httphone
application/vnd.hydrostatix.sof-data sfd-hdstx
# application/vnd.hzn-3d-crossword
# application/vnd.ibm.afplinedata
# application/vnd.ibm.electronic-media
application/vnd.ibm.minipay mpy
application/vnd.ibm.modcap afp listafp list3820
application/vnd.ibm.rights-management irm
application/vnd.ibm.secure-container sc
application/vnd.iccprofile icc icm
application/vnd.igloader igl
application/vnd.immervision-ivp ivp
application/vnd.immervision-ivu ivu
# application/vnd.informedcontrol.rms+xml
# application/vnd.informix-visionary
# application/vnd.infotech.project
# application/vnd.infotech.project+xml
# application/vnd.innopath.wamp.notification
application/vnd.insors.igm igm
application/vnd.intercon.formnet xpw xpx
application/vnd.intergeo i2g
# application/vnd.intertrust.digibox
# application/vnd.intertrust.nncp
application/vnd.intu.qbo qbo
application/vnd.intu.qfx qfx
# application/vnd.iptc.g2.conceptitem+xml
# application/vnd.iptc.g2.knowledgeitem+xml
# application/vnd.iptc.g2.newsitem+xml
# application/vnd.iptc.g2.newsmessage+xml
# application/vnd.iptc.g2.packageitem+xml
# application/vnd.iptc.g2.planningitem+xml
application/vnd.ipunplugged.rcprofile rcprofile
application/vnd.irepository.package+xml irp
application/vnd.is-xpr xpr
application/vnd.isac.fcs fcs
application/vnd.jam jam
# application/vnd.japannet-directory-service
# application/vnd.japannet-jpnstore-wakeup
# application/vnd.japannet-payment-wakeup
# application/vnd.japannet-registration
# application/vnd.japannet-registration-wakeup
# application/vnd.japannet-setstore-wakeup
# application/vnd.japannet-verification
# application/vnd.japannet-verification-wakeup
application/vnd.jcp.javame.midlet-rms rms
application/vnd.jisp jisp
application/vnd.joost.joda-archive joda
application/vnd.kahootz ktz ktr
application/vnd.kde.karbon karbon
application/vnd.kde.kchart chrt
application/vnd.kde.kformula kfo
application/vnd.kde.kivio flw
application/vnd.kde.kontour kon
application/vnd.kde.kpresenter kpr kpt
application/vnd.kde.kspread ksp
application/vnd.kde.kword kwd kwt
application/vnd.kenameaapp htke
application/vnd.kidspiration kia
application/vnd.kinar kne knp
application/vnd.koan skp skd skt skm
application/vnd.kodak-descriptor sse
application/vnd.las.las+xml lasxml
# application/vnd.liberty-request+xml
application/vnd.llamagraphics.life-balance.desktop lbd
application/vnd.llamagraphics.life-balance.exchange+xml lbe
application/vnd.lotus-1-2-3 123
application/vnd.lotus-approach apr
application/vnd.lotus-freelance pre
application/vnd.lotus-notes nsf
application/vnd.lotus-organizer org
application/vnd.lotus-screencam scm
application/vnd.lotus-wordpro lwp
application/vnd.macports.portpkg portpkg
# application/vnd.marlin.drm.actiontoken+xml
# application/vnd.marlin.drm.conftoken+xml
# application/vnd.marlin.drm.license+xml
# application/vnd.marlin.drm.mdcf
application/vnd.mcd mcd
application/vnd.medcalcdata mc1
application/vnd.mediastation.cdkey cdkey
# application/vnd.meridian-slingshot
application/vnd.mfer mwf
application/vnd.mfmp mfm
application/vnd.micrografx.flo flo
application/vnd.micrografx.igx igx
application/vnd.mif mif
# application/vnd.minisoft-hp3000-save
# application/vnd.mitsubishi.misty-guard.trustweb
application/vnd.mobius.daf daf
application/vnd.mobius.dis dis
application/vnd.mobius.mbk mbk
application/vnd.mobius.mqy mqy
application/vnd.mobius.msl msl
application/vnd.mobius.plc plc
application/vnd.mobius.txf txf
application/vnd.mophun.application mpn
application/vnd.mophun.certificate mpc
# application/vnd.motorola.flexsuite
# application/vnd.motorola.flexsuite.adsi
# application/vnd.motorola.flexsuite.fis
# application/vnd.motorola.flexsuite.gotap
# application/vnd.motorola.flexsuite.kmr
# application/vnd.motorola.flexsuite.ttc
# application/vnd.motorola.flexsuite.wem
# application/vnd.motorola.iprm
application/vnd.mozilla.xul+xml xul
application/vnd.ms-artgalry cil
# application/vnd.ms-asf
application/vnd.ms-cab-compressed cab
# application/vnd.ms-color.iccprofile
application/vnd.ms-excel xls xlm xla xlc xlt xlw
application/vnd.ms-excel.addin.macroenabled.12 xlam
application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb
application/vnd.ms-excel.sheet.macroenabled.12 xlsm
application/vnd.ms-excel.template.macroenabled.12 xltm
application/vnd.ms-fontobject eot
application/vnd.ms-htmlhelp chm
application/vnd.ms-ims ims
application/vnd.ms-lrm lrm
# application/vnd.ms-office.activex+xml
application/vnd.ms-officetheme thmx
# application/vnd.ms-opentype
# application/vnd.ms-package.obfuscated-opentype
application/vnd.ms-pki.seccat cat
application/vnd.ms-pki.stl stl
# application/vnd.ms-playready.initiator+xml
application/vnd.ms-powerpoint ppt pps pot
application/vnd.ms-powerpoint.addin.macroenabled.12 ppam
application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm
application/vnd.ms-powerpoint.slide.macroenabled.12 sldm
application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm
application/vnd.ms-powerpoint.template.macroenabled.12 potm
# application/vnd.ms-printing.printticket+xml
application/vnd.ms-project mpp mpt
# application/vnd.ms-tnef
# application/vnd.ms-wmdrm.lic-chlg-req
# application/vnd.ms-wmdrm.lic-resp
# application/vnd.ms-wmdrm.meter-chlg-req
# application/vnd.ms-wmdrm.meter-resp
application/vnd.ms-word.document.macroenabled.12 docm
application/vnd.ms-word.template.macroenabled.12 dotm
application/vnd.ms-works wps wks wcm wdb
application/vnd.ms-wpl wpl
application/vnd.ms-xpsdocument xps
application/vnd.mseq mseq
# application/vnd.msign
# application/vnd.multiad.creator
# application/vnd.multiad.creator.cif
# application/vnd.music-niff
application/vnd.musician mus
application/vnd.muvee.style msty
application/vnd.mynfc taglet
# application/vnd.ncd.control
# application/vnd.ncd.reference
# application/vnd.nervana
# application/vnd.netfpx
application/vnd.neurolanguage.nlu nlu
application/vnd.nitf ntf nitf
application/vnd.noblenet-directory nnd
application/vnd.noblenet-sealer nns
application/vnd.noblenet-web nnw
# application/vnd.nokia.catalogs
# application/vnd.nokia.conml+wbxml
# application/vnd.nokia.conml+xml
# application/vnd.nokia.isds-radio-presets
# application/vnd.nokia.iptv.config+xml
# application/vnd.nokia.landmark+wbxml
# application/vnd.nokia.landmark+xml
# application/vnd.nokia.landmarkcollection+xml
# application/vnd.nokia.n-gage.ac+xml
application/vnd.nokia.n-gage.data ngdat
application/vnd.nokia.n-gage.symbian.install n-gage
# application/vnd.nokia.ncd
# application/vnd.nokia.pcd+wbxml
# application/vnd.nokia.pcd+xml
application/vnd.nokia.radio-preset rpst
application/vnd.nokia.radio-presets rpss
application/vnd.novadigm.edm edm
application/vnd.novadigm.edx edx
application/vnd.novadigm.ext ext
# application/vnd.ntt-local.file-transfer
# application/vnd.ntt-local.sip-ta_remote
# application/vnd.ntt-local.sip-ta_tcp_stream
application/vnd.oasis.opendocument.chart odc
application/vnd.oasis.opendocument.chart-template otc
application/vnd.oasis.opendocument.database odb
application/vnd.oasis.opendocument.formula odf
application/vnd.oasis.opendocument.formula-template odft
application/vnd.oasis.opendocument.graphics odg
application/vnd.oasis.opendocument.graphics-template otg
application/vnd.oasis.opendocument.image odi
application/vnd.oasis.opendocument.image-template oti
application/vnd.oasis.opendocument.presentation odp
application/vnd.oasis.opendocument.presentation-template otp
application/vnd.oasis.opendocument.spreadsheet ods
application/vnd.oasis.opendocument.spreadsheet-template ots
application/vnd.oasis.opendocument.text odt
application/vnd.oasis.opendocument.text-master odm
application/vnd.oasis.opendocument.text-template ott
application/vnd.oasis.opendocument.text-web oth
# application/vnd.obn
# application/vnd.oftn.l10n+json
# application/vnd.oipf.contentaccessdownload+xml
# application/vnd.oipf.contentaccessstreaming+xml
# application/vnd.oipf.cspg-hexbinary
# application/vnd.oipf.dae.svg+xml
# application/vnd.oipf.dae.xhtml+xml
# application/vnd.oipf.mippvcontrolmessage+xml
# application/vnd.oipf.pae.gem
# application/vnd.oipf.spdiscovery+xml
# application/vnd.oipf.spdlist+xml
# application/vnd.oipf.ueprofile+xml
# application/vnd.oipf.userprofile+xml
application/vnd.olpc-sugar xo
# application/vnd.oma-scws-config
# application/vnd.oma-scws-http-request
# application/vnd.oma-scws-http-response
# application/vnd.oma.bcast.associated-procedure-parameter+xml
# application/vnd.oma.bcast.drm-trigger+xml
# application/vnd.oma.bcast.imd+xml
# application/vnd.oma.bcast.ltkm
# application/vnd.oma.bcast.notification+xml
# application/vnd.oma.bcast.provisioningtrigger
# application/vnd.oma.bcast.sgboot
# application/vnd.oma.bcast.sgdd+xml
# application/vnd.oma.bcast.sgdu
# application/vnd.oma.bcast.simple-symbol-container
# application/vnd.oma.bcast.smartcard-trigger+xml
# application/vnd.oma.bcast.sprov+xml
# application/vnd.oma.bcast.stkm
# application/vnd.oma.cab-address-book+xml
# application/vnd.oma.cab-feature-handler+xml
# application/vnd.oma.cab-pcc+xml
# application/vnd.oma.cab-user-prefs+xml
# application/vnd.oma.dcd
# application/vnd.oma.dcdc
application/vnd.oma.dd2+xml dd2
# application/vnd.oma.drm.risd+xml
# application/vnd.oma.group-usage-list+xml
# application/vnd.oma.pal+xml
# application/vnd.oma.poc.detailed-progress-report+xml
# application/vnd.oma.poc.final-report+xml
# application/vnd.oma.poc.groups+xml
# application/vnd.oma.poc.invocation-descriptor+xml
# application/vnd.oma.poc.optimized-progress-report+xml
# application/vnd.oma.push
# application/vnd.oma.scidm.messages+xml
# application/vnd.oma.xcap-directory+xml
# application/vnd.omads-email+xml
# application/vnd.omads-file+xml
# application/vnd.omads-folder+xml
# application/vnd.omaloc-supl-init
application/vnd.openofficeorg.extension oxt
# application/vnd.openxmlformats-officedocument.custom-properties+xml
# application/vnd.openxmlformats-officedocument.customxmlproperties+xml
# application/vnd.openxmlformats-officedocument.drawing+xml
# application/vnd.openxmlformats-officedocument.drawingml.chart+xml
# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml
# application/vnd.openxmlformats-officedocument.extended-properties+xml
# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml
# application/vnd.openxmlformats-officedocument.presentationml.comments+xml
# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml
# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml
# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml
application/vnd.openxmlformats-officedocument.presentationml.presentation pptx
# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml
# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml
application/vnd.openxmlformats-officedocument.presentationml.slide sldx
# application/vnd.openxmlformats-officedocument.presentationml.slide+xml
# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml
# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml
application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx
# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml
# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml
# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml
# application/vnd.openxmlformats-officedocument.presentationml.tags+xml
application/vnd.openxmlformats-officedocument.presentationml.template potx
# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml
# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx
# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml
application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx
# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml
# application/vnd.openxmlformats-officedocument.theme+xml
# application/vnd.openxmlformats-officedocument.themeoverride+xml
# application/vnd.openxmlformats-officedocument.vmldrawing
# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml
application/vnd.openxmlformats-officedocument.wordprocessingml.document docx
# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml
application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx
# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml
# application/vnd.openxmlformats-package.core-properties+xml
# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml
# application/vnd.openxmlformats-package.relationships+xml
# application/vnd.quobject-quoxdocument
# application/vnd.osa.netdeploy
application/vnd.osgeo.mapguide.package mgp
# application/vnd.osgi.bundle
application/vnd.osgi.dp dp
application/vnd.osgi.subsystem esa
# application/vnd.otps.ct-kip+xml
application/vnd.palm pdb pqa oprc
# application/vnd.paos.xml
application/vnd.pawaafile paw
application/vnd.pg.format str
application/vnd.pg.osasli ei6
# application/vnd.piaccess.application-licence
application/vnd.picsel efif
application/vnd.pmi.widget wg
# application/vnd.poc.group-advertisement+xml
application/vnd.pocketlearn plf
application/vnd.powerbuilder6 pbd
# application/vnd.powerbuilder6-s
# application/vnd.powerbuilder7
# application/vnd.powerbuilder7-s
# application/vnd.powerbuilder75
# application/vnd.powerbuilder75-s
# application/vnd.preminet
application/vnd.previewsystems.box box
application/vnd.proteus.magazine mgz
application/vnd.publishare-delta-tree qps
application/vnd.pvi.ptid1 ptid
# application/vnd.pwg-multiplexed
# application/vnd.pwg-xhtml-print+xml
# application/vnd.qualcomm.brew-app-res
application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb
# application/vnd.radisys.moml+xml
# application/vnd.radisys.msml+xml
# application/vnd.radisys.msml-audit+xml
# application/vnd.radisys.msml-audit-conf+xml
# application/vnd.radisys.msml-audit-conn+xml
# application/vnd.radisys.msml-audit-dialog+xml
# application/vnd.radisys.msml-audit-stream+xml
# application/vnd.radisys.msml-conf+xml
# application/vnd.radisys.msml-dialog+xml
# application/vnd.radisys.msml-dialog-base+xml
# application/vnd.radisys.msml-dialog-fax-detect+xml
# application/vnd.radisys.msml-dialog-fax-sendrecv+xml
# application/vnd.radisys.msml-dialog-group+xml
# application/vnd.radisys.msml-dialog-speech+xml
# application/vnd.radisys.msml-dialog-transform+xml
# application/vnd.rainstor.data
# application/vnd.rapid
application/vnd.realvnc.bed bed
application/vnd.recordare.musicxml mxl
application/vnd.recordare.musicxml+xml musicxml
# application/vnd.renlearn.rlprint
application/vnd.rig.cryptonote cryptonote
application/vnd.rim.cod cod
application/vnd.rn-realmedia rm
application/vnd.rn-realmedia-vbr rmvb
application/vnd.route66.link66+xml link66
# application/vnd.rs-274x
# application/vnd.ruckus.download
# application/vnd.s3sms
application/vnd.sailingtracker.track st
# application/vnd.sbm.cid
# application/vnd.sbm.mid2
# application/vnd.scribus
# application/vnd.sealed.3df
# application/vnd.sealed.csf
# application/vnd.sealed.doc
# application/vnd.sealed.eml
# application/vnd.sealed.mht
# application/vnd.sealed.net
# application/vnd.sealed.ppt
# application/vnd.sealed.tiff
# application/vnd.sealed.xls
# application/vnd.sealedmedia.softseal.html
# application/vnd.sealedmedia.softseal.pdf
application/vnd.seemail see
application/vnd.sema sema
application/vnd.semd semd
application/vnd.semf semf
application/vnd.shana.informed.formdata ifm
application/vnd.shana.informed.formtemplate itp
application/vnd.shana.informed.interchange iif
application/vnd.shana.informed.package ipk
application/vnd.simtech-mindmapper twd twds
application/vnd.smaf mmf
# application/vnd.smart.notebook
application/vnd.smart.teacher teacher
# application/vnd.software602.filler.form+xml
# application/vnd.software602.filler.form-xml-zip
application/vnd.solent.sdkm+xml sdkm sdkd
application/vnd.spotfire.dxp dxp
application/vnd.spotfire.sfs sfs
# application/vnd.sss-cod
# application/vnd.sss-dtf
# application/vnd.sss-ntf
application/vnd.stardivision.calc sdc
application/vnd.stardivision.draw sda
application/vnd.stardivision.impress sdd
application/vnd.stardivision.math smf
application/vnd.stardivision.writer sdw vor
application/vnd.stardivision.writer-global sgl
application/vnd.stepmania.package smzip
application/vnd.stepmania.stepchart sm
# application/vnd.street-stream
application/vnd.sun.xml.calc sxc
application/vnd.sun.xml.calc.template stc
application/vnd.sun.xml.draw sxd
application/vnd.sun.xml.draw.template std
application/vnd.sun.xml.impress sxi
application/vnd.sun.xml.impress.template sti
application/vnd.sun.xml.math sxm
application/vnd.sun.xml.writer sxw
application/vnd.sun.xml.writer.global sxg
application/vnd.sun.xml.writer.template stw
# application/vnd.sun.wadl+xml
application/vnd.sus-calendar sus susp
application/vnd.svd svd
# application/vnd.swiftview-ics
application/vnd.symbian.install sis sisx
application/vnd.syncml+xml xsm
application/vnd.syncml.dm+wbxml bdm
application/vnd.syncml.dm+xml xdm
# application/vnd.syncml.dm.notification
# application/vnd.syncml.ds.notification
application/vnd.tao.intent-module-archive tao
application/vnd.tcpdump.pcap pcap cap dmp
application/vnd.tmobile-livetv tmo
application/vnd.trid.tpt tpt
application/vnd.triscape.mxs mxs
application/vnd.trueapp tra
# application/vnd.truedoc
# application/vnd.ubisoft.webplayer
application/vnd.ufdl ufd ufdl
application/vnd.uiq.theme utz
application/vnd.umajin umj
application/vnd.unity unityweb
application/vnd.uoml+xml uoml
# application/vnd.uplanet.alert
# application/vnd.uplanet.alert-wbxml
# application/vnd.uplanet.bearer-choice
# application/vnd.uplanet.bearer-choice-wbxml
# application/vnd.uplanet.cacheop
# application/vnd.uplanet.cacheop-wbxml
# application/vnd.uplanet.channel
# application/vnd.uplanet.channel-wbxml
# application/vnd.uplanet.list
# application/vnd.uplanet.list-wbxml
# application/vnd.uplanet.listcmd
# application/vnd.uplanet.listcmd-wbxml
# application/vnd.uplanet.signal
application/vnd.vcx vcx
# application/vnd.vd-study
# application/vnd.vectorworks
# application/vnd.verimatrix.vcas
# application/vnd.vidsoft.vidconference
application/vnd.visio vsd vst vss vsw
application/vnd.visionary vis
# application/vnd.vividence.scriptfile
application/vnd.vsf vsf
# application/vnd.wap.sic
# application/vnd.wap.slc
application/vnd.wap.wbxml wbxml
application/vnd.wap.wmlc wmlc
application/vnd.wap.wmlscriptc wmlsc
application/vnd.webturbo wtb
# application/vnd.wfa.wsc
# application/vnd.wmc
# application/vnd.wmf.bootstrap
# application/vnd.wolfram.mathematica
# application/vnd.wolfram.mathematica.package
application/vnd.wolfram.player nbp
application/vnd.wordperfect wpd
application/vnd.wqd wqd
# application/vnd.wrq-hp3000-labelled
application/vnd.wt.stf stf
# application/vnd.wv.csp+wbxml
# application/vnd.wv.csp+xml
# application/vnd.wv.ssp+xml
application/vnd.xara xar
application/vnd.xfdl xfdl
# application/vnd.xfdl.webform
# application/vnd.xmi+xml
# application/vnd.xmpie.cpkg
# application/vnd.xmpie.dpkg
# application/vnd.xmpie.plan
# application/vnd.xmpie.ppkg
# application/vnd.xmpie.xlim
application/vnd.yamaha.hv-dic hvd
application/vnd.yamaha.hv-script hvs
application/vnd.yamaha.hv-voice hvp
application/vnd.yamaha.openscoreformat osf
application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg
# application/vnd.yamaha.remote-setup
application/vnd.yamaha.smaf-audio saf
application/vnd.yamaha.smaf-phrase spf
# application/vnd.yamaha.through-ngn
# application/vnd.yamaha.tunnel-udpencap
application/vnd.yellowriver-custom-menu cmp
application/vnd.zul zir zirz
application/vnd.zzazz.deck+xml zaz
application/voicexml+xml vxml
# application/vq-rtcpxr
# application/watcherinfo+xml
# application/whoispp-query
# application/whoispp-response
application/widget wgt
application/winhlp hlp
# application/wita
# application/wordperfect5.1
application/wsdl+xml wsdl
application/wspolicy+xml wspolicy
application/x-7z-compressed 7z
application/x-abiword abw
application/x-ace-compressed ace
# application/x-amf
application/x-apple-diskimage dmg
application/x-authorware-bin aab x32 u32 vox
application/x-authorware-map aam
application/x-authorware-seg aas
application/x-bcpio bcpio
application/x-bittorrent torrent
application/x-blorb blb blorb
application/x-bzip bz
application/x-bzip2 bz2 boz
application/x-cbr cbr cba cbt cbz cb7
application/x-cdlink vcd
application/x-cfs-compressed cfs
application/x-chat chat
application/x-chess-pgn pgn
application/x-conference nsc
# application/x-compress
application/x-cpio cpio
application/x-csh csh
application/x-debian-package deb udeb
application/x-dgc-compressed dgc
application/x-director dir dcr dxr cst cct cxt w3d fgd swa
application/x-doom wad
application/x-dtbncx+xml ncx
application/x-dtbook+xml dtb
application/x-dtbresource+xml res
application/x-dvi dvi
application/x-envoy evy
application/x-eva eva
application/x-font-bdf bdf
# application/x-font-dos
# application/x-font-framemaker
application/x-font-ghostscript gsf
# application/x-font-libgrx
application/x-font-linux-psf psf
application/x-font-otf otf
application/x-font-pcf pcf
application/x-font-snf snf
# application/x-font-speedo
# application/x-font-sunos-news
application/x-font-ttf ttf ttc
application/x-font-type1 pfa pfb pfm afm
application/font-woff woff
# application/x-font-vfont
application/x-freearc arc
application/x-futuresplash spl
application/x-gca-compressed gca
application/x-glulx ulx
application/x-gnumeric gnumeric
application/x-gramps-xml gramps
application/x-gtar gtar
# application/x-gzip
application/x-hdf hdf
application/x-install-instructions install
application/x-iso9660-image iso
application/x-java-jnlp-file jnlp
application/x-latex latex
application/x-lzh-compressed lzh lha
application/x-mie mie
application/x-mobipocket-ebook prc mobi
application/x-ms-application application
application/x-ms-shortcut lnk
application/x-ms-wmd wmd
application/x-ms-wmz wmz
application/x-ms-xbap xbap
application/x-msaccess mdb
application/x-msbinder obd
application/x-mscardfile crd
application/x-msclip clp
application/x-msdownload exe dll com bat msi
application/x-msmediaview mvb m13 m14
application/x-msmetafile wmf wmz emf emz
application/x-msmoney mny
application/x-mspublisher pub
application/x-msschedule scd
application/x-msterminal trm
application/x-mswrite wri
application/x-netcdf nc cdf
application/x-nzb nzb
application/x-pkcs12 p12 pfx
application/x-pkcs7-certificates p7b spc
application/x-pkcs7-certreqresp p7r
application/x-rar-compressed rar
application/x-research-info-systems ris
application/x-sh sh
application/x-shar shar
application/x-shockwave-flash swf
application/x-silverlight-app xap
application/x-sql sql
application/x-stuffit sit
application/x-stuffitx sitx
application/x-subrip srt
application/x-sv4cpio sv4cpio
application/x-sv4crc sv4crc
application/x-t3vm-image t3
application/x-tads gam
application/x-tar tar
application/x-tcl tcl
application/x-tex tex
application/x-tex-tfm tfm
application/x-texinfo texinfo texi
application/x-tgif obj
application/x-ustar ustar
application/x-wais-source src
application/x-x509-ca-cert der crt
application/x-xfig fig
application/x-xliff+xml xlf
application/x-xpinstall xpi
application/x-xz xz
application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8
# application/x400-bp
application/xaml+xml xaml
# application/xcap-att+xml
# application/xcap-caps+xml
application/xcap-diff+xml xdf
# application/xcap-el+xml
# application/xcap-error+xml
# application/xcap-ns+xml
# application/xcon-conference-info-diff+xml
# application/xcon-conference-info+xml
application/xenc+xml xenc
application/xhtml+xml xhtml xht
# application/xhtml-voice+xml
application/xml xml xsl
application/xml-dtd dtd
# application/xml-external-parsed-entity
# application/xmpp+xml
application/xop+xml xop
application/xproc+xml xpl
application/xslt+xml xslt
application/xspf+xml xspf
application/xv+xml mxml xhvml xvml xvm
application/yang yang
application/yin+xml yin
application/zip zip
# audio/1d-interleaved-parityfec
# audio/32kadpcm
# audio/3gpp
# audio/3gpp2
# audio/ac3
audio/adpcm adp
# audio/amr
# audio/amr-wb
# audio/amr-wb+
# audio/asc
# audio/atrac-advanced-lossless
# audio/atrac-x
# audio/atrac3
audio/basic au snd
# audio/bv16
# audio/bv32
# audio/clearmode
# audio/cn
# audio/dat12
# audio/dls
# audio/dsr-es201108
# audio/dsr-es202050
# audio/dsr-es202211
# audio/dsr-es202212
# audio/dv
# audio/dvi4
# audio/eac3
# audio/evrc
# audio/evrc-qcp
# audio/evrc0
# audio/evrc1
# audio/evrcb
# audio/evrcb0
# audio/evrcb1
# audio/evrcwb
# audio/evrcwb0
# audio/evrcwb1
# audio/example
# audio/fwdred
# audio/g719
# audio/g722
# audio/g7221
# audio/g723
# audio/g726-16
# audio/g726-24
# audio/g726-32
# audio/g726-40
# audio/g728
# audio/g729
# audio/g7291
# audio/g729d
# audio/g729e
# audio/gsm
# audio/gsm-efr
# audio/gsm-hr-08
# audio/ilbc
# audio/ip-mr_v2.5
# audio/isac
# audio/l16
# audio/l20
# audio/l24
# audio/l8
# audio/lpc
audio/midi mid midi kar rmi
# audio/mobile-xmf
audio/mp4 mp4a
# audio/mp4a-latm
# audio/mpa
# audio/mpa-robust
audio/mpeg mpga mp2 mp2a mp3 m2a m3a
# audio/mpeg4-generic
# audio/musepack
audio/ogg oga ogg spx
# audio/opus
# audio/parityfec
# audio/pcma
# audio/pcma-wb
# audio/pcmu-wb
# audio/pcmu
# audio/prs.sid
# audio/qcelp
# audio/red
# audio/rtp-enc-aescm128
# audio/rtp-midi
# audio/rtx
audio/s3m s3m
audio/silk sil
# audio/smv
# audio/smv0
# audio/smv-qcp
# audio/sp-midi
# audio/speex
# audio/t140c
# audio/t38
# audio/telephone-event
# audio/tone
# audio/uemclip
# audio/ulpfec
# audio/vdvi
# audio/vmr-wb
# audio/vnd.3gpp.iufp
# audio/vnd.4sb
# audio/vnd.audiokoz
# audio/vnd.celp
# audio/vnd.cisco.nse
# audio/vnd.cmles.radio-events
# audio/vnd.cns.anp1
# audio/vnd.cns.inf1
audio/vnd.dece.audio uva uvva
audio/vnd.digital-winds eol
# audio/vnd.dlna.adts
# audio/vnd.dolby.heaac.1
# audio/vnd.dolby.heaac.2
# audio/vnd.dolby.mlp
# audio/vnd.dolby.mps
# audio/vnd.dolby.pl2
# audio/vnd.dolby.pl2x
# audio/vnd.dolby.pl2z
# audio/vnd.dolby.pulse.1
audio/vnd.dra dra
audio/vnd.dts dts
audio/vnd.dts.hd dtshd
# audio/vnd.dvb.file
# audio/vnd.everad.plj
# audio/vnd.hns.audio
audio/vnd.lucent.voice lvp
audio/vnd.ms-playready.media.pya pya
# audio/vnd.nokia.mobile-xmf
# audio/vnd.nortel.vbk
audio/vnd.nuera.ecelp4800 ecelp4800
audio/vnd.nuera.ecelp7470 ecelp7470
audio/vnd.nuera.ecelp9600 ecelp9600
# audio/vnd.octel.sbc
# audio/vnd.qcelp
# audio/vnd.rhetorex.32kadpcm
audio/vnd.rip rip
# audio/vnd.sealedmedia.softseal.mpeg
# audio/vnd.vmx.cvsd
# audio/vorbis
# audio/vorbis-config
audio/webm weba
audio/x-aac aac
audio/x-aiff aif aiff aifc
audio/x-caf caf
audio/x-flac flac
audio/x-matroska mka
audio/x-mpegurl m3u
audio/x-ms-wax wax
audio/x-ms-wma wma
audio/x-pn-realaudio ram ra
audio/x-pn-realaudio-plugin rmp
# audio/x-tta
audio/x-wav wav
audio/xm xm
chemical/x-cdx cdx
chemical/x-cif cif
chemical/x-cmdf cmdf
chemical/x-cml cml
chemical/x-csml csml
# chemical/x-pdb
chemical/x-xyz xyz
image/bmp bmp
image/cgm cgm
# image/example
# image/fits
image/g3fax g3
image/gif gif
image/ief ief
# image/jp2
image/jpeg jpeg jpg jpe
# image/jpm
# image/jpx
image/ktx ktx
# image/naplps
image/png png
image/prs.btif btif
# image/prs.pti
image/sgi sgi
image/svg+xml svg svgz
# image/t38
image/tiff tiff tif
# image/tiff-fx
image/vnd.adobe.photoshop psd
# image/vnd.cns.inf2
image/vnd.dece.graphic uvi uvvi uvg uvvg
image/vnd.dvb.subtitle sub
image/vnd.djvu djvu djv
image/vnd.dwg dwg
image/vnd.dxf dxf
image/vnd.fastbidsheet fbs
image/vnd.fpx fpx
image/vnd.fst fst
image/vnd.fujixerox.edmics-mmr mmr
image/vnd.fujixerox.edmics-rlc rlc
# image/vnd.globalgraphics.pgb
# image/vnd.microsoft.icon
# image/vnd.mix
image/vnd.ms-modi mdi
image/vnd.ms-photo wdp
image/vnd.net-fpx npx
# image/vnd.radiance
# image/vnd.sealed.png
# image/vnd.sealedmedia.softseal.gif
# image/vnd.sealedmedia.softseal.jpg
# image/vnd.svf
image/vnd.wap.wbmp wbmp
image/vnd.xiff xif
image/webp webp
image/x-3ds 3ds
image/x-cmu-raster ras
image/x-cmx cmx
image/x-freehand fh fhc fh4 fh5 fh7
image/x-icon ico
image/x-mrsid-image sid
image/x-pcx pcx
image/x-pict pic pct
image/x-portable-anymap pnm
image/x-portable-bitmap pbm
image/x-portable-graymap pgm
image/x-portable-pixmap ppm
image/x-rgb rgb
image/x-tga tga
image/x-xbitmap xbm
image/x-xpixmap xpm
image/x-xwindowdump xwd
# message/cpim
# message/delivery-status
# message/disposition-notification
# message/example
# message/external-body
# message/feedback-report
# message/global
# message/global-delivery-status
# message/global-disposition-notification
# message/global-headers
# message/http
# message/imdn+xml
# message/news
# message/partial
message/rfc822 eml mime
# message/s-http
# message/sip
# message/sipfrag
# message/tracking-status
# message/vnd.si.simp
# model/example
model/iges igs iges
model/mesh msh mesh silo
model/vnd.collada+xml dae
model/vnd.dwf dwf
# model/vnd.flatland.3dml
model/vnd.gdl gdl
# model/vnd.gs-gdl
# model/vnd.gs.gdl
model/vnd.gtw gtw
# model/vnd.moml+xml
model/vnd.mts mts
# model/vnd.parasolid.transmit.binary
# model/vnd.parasolid.transmit.text
model/vnd.vtu vtu
model/vrml wrl vrml
model/x3d+binary x3db x3dbz
model/x3d+vrml x3dv x3dvz
model/x3d+xml x3d x3dz
# multipart/alternative
# multipart/appledouble
# multipart/byteranges
# multipart/digest
# multipart/encrypted
# multipart/example
# multipart/form-data
# multipart/header-set
# multipart/mixed
# multipart/parallel
# multipart/related
# multipart/report
# multipart/signed
# multipart/voice-message
# text/1d-interleaved-parityfec
text/cache-manifest appcache
text/calendar ics ifb
text/css css
text/csv csv
# text/directory
# text/dns
# text/ecmascript
# text/enriched
# text/example
# text/fwdred
text/html html htm
# text/javascript
text/n3 n3
# text/parityfec
text/plain txt text conf def list log in
# text/prs.fallenstein.rst
text/prs.lines.tag dsc
# text/vnd.radisys.msml-basic-layout
# text/red
# text/rfc822-headers
text/richtext rtx
# text/rtf
# text/rtp-enc-aescm128
# text/rtx
text/sgml sgml sgm
# text/t140
text/tab-separated-values tsv
text/troff t tr roff man me ms
text/turtle ttl
# text/ulpfec
text/uri-list uri uris urls
text/vcard vcard
# text/vnd.abc
text/vnd.curl curl
text/vnd.curl.dcurl dcurl
text/vnd.curl.scurl scurl
text/vnd.curl.mcurl mcurl
# text/vnd.dmclientscript
text/vnd.dvb.subtitle sub
# text/vnd.esmertec.theme-descriptor
text/vnd.fly fly
text/vnd.fmi.flexstor flx
text/vnd.graphviz gv
text/vnd.in3d.3dml 3dml
text/vnd.in3d.spot spot
# text/vnd.iptc.newsml
# text/vnd.iptc.nitf
# text/vnd.latex-z
# text/vnd.motorola.reflex
# text/vnd.ms-mediapackage
# text/vnd.net2phone.commcenter.command
# text/vnd.si.uricatalogue
text/vnd.sun.j2me.app-descriptor jad
# text/vnd.trolltech.linguist
# text/vnd.wap.si
# text/vnd.wap.sl
text/vnd.wap.wml wml
text/vnd.wap.wmlscript wmls
text/x-asm s asm
text/x-c c cc cxx cpp h hh dic
text/x-fortran f for f77 f90
text/x-java-source java
text/x-opml opml
text/x-pascal p pas
text/x-nfo nfo
text/x-setext etx
text/x-sfv sfv
text/x-uuencode uu
text/x-vcalendar vcs
text/x-vcard vcf
# text/xml
# text/xml-external-parsed-entity
# video/1d-interleaved-parityfec
video/3gpp 3gp
# video/3gpp-tt
video/3gpp2 3g2
# video/bmpeg
# video/bt656
# video/celb
# video/dv
# video/example
video/h261 h261
video/h263 h263
# video/h263-1998
# video/h263-2000
video/h264 h264
# video/h264-rcdo
# video/h264-svc
video/jpeg jpgv
# video/jpeg2000
video/jpm jpm jpgm
video/mj2 mj2 mjp2
# video/mp1s
# video/mp2p
# video/mp2t
video/mp4 mp4 mp4v mpg4
# video/mp4v-es
video/mpeg mpeg mpg mpe m1v m2v
# video/mpeg4-generic
# video/mpv
# video/nv
video/ogg ogv
# video/parityfec
# video/pointer
video/quicktime qt mov
# video/raw
# video/rtp-enc-aescm128
# video/rtx
# video/smpte292m
# video/ulpfec
# video/vc1
# video/vnd.cctv
video/vnd.dece.hd uvh uvvh
video/vnd.dece.mobile uvm uvvm
# video/vnd.dece.mp4
video/vnd.dece.pd uvp uvvp
video/vnd.dece.sd uvs uvvs
video/vnd.dece.video uvv uvvv
# video/vnd.directv.mpeg
# video/vnd.directv.mpeg-tts
# video/vnd.dlna.mpeg-tts
video/vnd.dvb.file dvb
video/vnd.fvt fvt
# video/vnd.hns.video
# video/vnd.iptvforum.1dparityfec-1010
# video/vnd.iptvforum.1dparityfec-2005
# video/vnd.iptvforum.2dparityfec-1010
# video/vnd.iptvforum.2dparityfec-2005
# video/vnd.iptvforum.ttsavc
# video/vnd.iptvforum.ttsmpeg2
# video/vnd.motorola.video
# video/vnd.motorola.videop
video/vnd.mpegurl mxu m4u
video/vnd.ms-playready.media.pyv pyv
# video/vnd.nokia.interleaved-multimedia
# video/vnd.nokia.videovoip
# video/vnd.objectvideo
# video/vnd.sealed.mpeg1
# video/vnd.sealed.mpeg4
# video/vnd.sealed.swf
# video/vnd.sealedmedia.softseal.mov
video/vnd.uvvu.mp4 uvu uvvu
video/vnd.vivo viv
video/webm webm
video/x-f4v f4v
video/x-fli fli
video/x-flv flv
video/x-m4v m4v
video/x-matroska mkv mk3d mks
video/x-mng mng
video/x-ms-asf asf asx
video/x-ms-vob vob
video/x-ms-wm wm
video/x-ms-wmv wmv
video/x-ms-wmx wmx
video/x-ms-wvx wvx
video/x-msvideo avi
video/x-sgi-movie movie
video/x-smv smv
x-conference/x-cooltalk ice
# What: WebVTT
# Why: To allow formats intended for marking up external text track resources.
# http://dev.w3.org/html5/webvtt/
# Added by: niftylettuce
text/vtt vtt
# What: Google Chrome Extension
# Why: To allow apps to (work) be served with the right content type header.
# http://codereview.chromium.org/2830017
# Added by: niftylettuce
application/x-chrome-extension crx
# What: HTC support
# Why: To properly render .htc files such as CSS3PIE
# Added by: niftylettuce
text/x-component htc
# What: HTML5 application cache manifes ('.manifest' extension)
# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps
# per https://developer.mozilla.org/en/offline_resources_in_firefox
# Added by: louisremi
text/cache-manifest manifest
# What: node binary buffer format
# Why: semi-standard extension w/in the node community
# Added by: tootallnate
application/octet-stream buffer
# What: The "protected" MP-4 formats used by iTunes.
# Why: Required for streaming music to browsers (?)
# Added by: broofa
application/mp4 m4p
audio/mp4 m4a
# What: Video format, Part of RFC1890
# Why: See https://github.com/bentomas/node-mime/pull/6
# Added by: mjrusso
video/MP2T ts
# What: EventSource mime type
# Why: mime type of Server-Sent Events stream
# http://www.w3.org/TR/eventsource/#text-event-stream
# Added by: francois2metz
text/event-stream event-stream
# What: Mozilla App manifest mime type
# Why: https://developer.mozilla.org/en/Apps/Manifest#Serving_manifests
# Added by: ednapiranha
application/x-web-app-manifest+json webapp
# What: Lua file types
# Why: Googling around shows de-facto consensus on these
# Added by: creationix (Issue #45)
text/x-lua lua
application/x-lua-bytecode luac
# What: Markdown files, as per http://daringfireball.net/projects/markdown/syntax
# Why: http://stackoverflow.com/questions/10701983/what-is-the-mime-type-for-markdown
# Added by: avoidwork
text/x-markdown markdown md mkd
# What: ini files
# Why: because they're just text files
# Added by: Matthew Kastor
text/plain ini
# What: DASH Adaptive Streaming manifest
# Why: https://developer.mozilla.org/en-US/docs/DASH_Adaptive_Streaming_for_HTML_5_Video
# Added by: eelcocramer
application/dash+xml mdp
# What: OpenType font files - http://www.microsoft.com/typography/otspec/
# Why: Browsers usually ignore the font MIME types and sniff the content,
# but Chrome, shows a warning if OpenType fonts aren't served with
# the `font/opentype` MIME type: http://i.imgur.com/8c5RN8M.png.
# Added by: alrra
font/opentype otf
module.exports = preferredCharsets;
preferredCharsets.preferredCharsets = preferredCharsets;
function parseAcceptCharset(accept) {
return accept.split(',').map(function (e) {
return parseCharset(e.trim());
}).filter(function (e) {
return e;
});
}
function parseCharset(s) {
var match = s.match(/^\s*(\S+?)\s*(?:;(.*))?$/);
if (!match) return null;
var charset = match[1];
var q = 1;
if (match[2]) {
var params = match[2].split(';')
for (var i = 0; i < params.length; i++) {
var p = params[i].trim().split('=');
if (p[0] === 'q') {
q = parseFloat(p[1]);
break;
}
}
}
return {
charset: charset,
q: q
};
}
function getCharsetPriority(charset, accepted) {
return (accepted.filter(function (a) {
return specify(charset, a);
}).sort(function (a, b) {
// revsort
return a.s > b.s ? -1 : 1;
})[0] || {q: 0}).q;
}
function specify(charset, spec) {
var s = 0;
if (spec.charset === charset) {
s |= 1;
} else if (spec.charset !== '*') {
return null
}
return {
s: s,
q: spec.q,
}
}
function preferredCharsets(accept, provided) {
// RFC 2616 sec 14.2: no header = *
accept = parseAcceptCharset(accept === undefined ? '*' : accept || '');
if (provided) {
return provided.map(function (type) {
return [type, getCharsetPriority(type, accept)];
}).filter(function (pair) {
return pair[1] > 0;
}).sort(function (a, b) {
// revsort
return a[1] > b[1] ? -1 : 1;
}).map(function (pair) {
return pair[0];
});
} else {
return accept.sort(function (a, b) {
// revsort
return a.q < b.q ? 1 : -1;
}).filter(function (type) {
return type.q > 0;
}).map(function (type) {
return type.charset;
});
}
}
module.exports = preferredEncodings;
preferredEncodings.preferredEncodings = preferredEncodings;
function parseAcceptEncoding(accept) {
var acceptableEncodings;
if (accept) {
acceptableEncodings = accept.split(',').map(function (e) {
return parseEncoding(e.trim());
});
} else {
acceptableEncodings = [];
}
if (!acceptableEncodings.some(function (e) {
return e && specify('identity', e);
})) {
/*
* If identity doesn't explicitly appear in the accept-encoding header,
* it's added to the list of acceptable encoding with the lowest q
*
*/
var lowestQ = 1;
for (var i = 0; i < acceptableEncodings.length; i++) {
var e = acceptableEncodings[i];
if (e && e.q < lowestQ) {
lowestQ = e.q;
}
}
acceptableEncodings.push({
encoding: 'identity',
q: lowestQ / 2,
});
}
return acceptableEncodings.filter(function (e) {
return e;
});
}
function parseEncoding(s) {
var match = s.match(/^\s*(\S+?)\s*(?:;(.*))?$/);
if (!match) return null;
var encoding = match[1];
var q = 1;
if (match[2]) {
var params = match[2].split(';');
for (var i = 0; i < params.length; i++) {
var p = params[i].trim().split('=');
if (p[0] === 'q') {
q = parseFloat(p[1]);
break;
}
}
}
return {
encoding: encoding,
q: q
};
}
function getEncodingPriority(encoding, accepted) {
return (accepted.map(function (a) {
return specify(encoding, a);
}).filter(function (a) {
return a;
}).sort(function (a, b) {
// revsort
return a.s > b.s ? -1 : 1;
})[0] || {q: 0}).q;
}
function specify(encoding, spec) {
var s = 0;
if (spec.encoding === encoding) {
s |= 1;
} else if (spec.encoding !== '*') {
return null
}
return {
s: s,
q: spec.q,
}
};
function preferredEncodings(accept, provided) {
accept = parseAcceptEncoding(accept || '');
if (provided) {
return provided.map(function (type) {
return [type, getEncodingPriority(type, accept)];
}).filter(function (pair) {
return pair[1] > 0;
}).sort(function (a, b) {
// revsort
return a[1] === b[1] ? 0 : a[1] > b[1] ? -1 : 1;
}).map(function (pair) {
return pair[0];
});
} else {
return accept.sort(function (a, b) {
// revsort
return a.q < b.q ? 1 : -1;
}).filter(function (type) {
return type.q > 0;
}).map(function (type) {
return type.encoding;
});
}
}
module.exports = preferredLanguages;
preferredLanguages.preferredLanguages = preferredLanguages;
function parseAcceptLanguage(accept) {
return accept.split(',').map(function (e) {
return parseLanguage(e.trim());
}).filter(function (e) {
return e;
});
}
function parseLanguage(s) {
var match = s.match(/^\s*(\S+?)(?:-(\S+?))?\s*(?:;(.*))?$/);
if (!match) return null;
var prefix = match[1],
suffix = match[2],
full = prefix;
if (suffix) full += "-" + suffix;
var q = 1;
if (match[3]) {
var params = match[3].split(';')
for (var i = 0; i < params.length; i++) {
var p = params[i].split('=');
if (p[0] === 'q') q = parseFloat(p[1]);
}
}
return {
prefix: prefix,
suffix: suffix,
q: q,
full: full
};
}
function getLanguagePriority(language, accepted) {
return (accepted.map(function (a) {
return specify(language, a);
}).filter(function (a) {
return a;
}).sort(function (a, b) {
// revsort
return a.s > b.s ? -1 : 1;
})[0] || {q: 0}).q;
}
function specify(language, spec) {
var p = parseLanguage(language)
var s = 0;
if (spec.full === p.full) {
s |= 4;
} else if (spec.prefix === p.full) {
s |= 2;
} else if (spec.full === p.prefix) {
s |= 1;
} else if (spec.full !== '*') {
return null
}
return {
s: s,
q: spec.q,
}
};
function preferredLanguages(accept, provided) {
// RFC 2616 sec 14.4: no header = *
accept = parseAcceptLanguage(accept === undefined ? '*' : accept || '');
if (provided) {
var ret = provided.map(function (type) {
return [type, getLanguagePriority(type, accept)];
}).filter(function (pair) {
return pair[1] > 0;
}).sort(function (a, b) {
// revsort
return a[1] === b[1] ? 0 : a[1] > b[1] ? -1 : 1;
}).map(function (pair) {
return pair[0];
});
return ret;
} else {
return accept.sort(function (a, b) {
// revsort
return a.q < b.q ? 1 : -1;
}).filter(function (type) {
return type.q > 0;
}).map(function (type) {
return type.full;
});
}
}
module.exports = preferredMediaTypes;
preferredMediaTypes.preferredMediaTypes = preferredMediaTypes;
function parseAccept(accept) {
return accept.split(',').map(function (e) {
return parseMediaType(e.trim());
}).filter(function (e) {
return e;
});
};
function parseMediaType(s) {
var match = s.match(/\s*(\S+?)\/([^;\s]+)\s*(?:;(.*))?/);
if (!match) return null;
var type = match[1],
subtype = match[2],
full = "" + type + "/" + subtype,
params = {},
q = 1;
if (match[3]) {
params = match[3].split(';').map(function (s) {
return s.trim().split('=');
}).reduce(function (set, p) {
set[p[0]] = p[1];
return set
}, params);
if (params.q != null) {
q = parseFloat(params.q);
delete params.q;
}
}
return {
type: type,
subtype: subtype,
params: params,
q: q,
full: full
};
}
function getMediaTypePriority(type, accepted) {
return (accepted.map(function (a) {
return specify(type, a);
}).filter(Boolean).sort(function (a, b) {
// revsort
return a.s > b.s ? -1 : 1;
})[0] || {q: 0}).q;
}
function specify(type, spec) {
var p = parseMediaType(type);
var s = 0;
if (spec.type == p.type) {
s |= 4
} else if (spec.type != '*') {
return null;
}
if (spec.subtype == p.subtype) {
s |= 2
} else if (spec.subtype != '*') {
return null;
}
var keys = Object.keys(spec.params);
if (keys.length > 0) {
if (keys.every(function (k) {
return spec.params[k] == '*' || spec.params[k] == p.params[k];
})) {
s |= 1
} else {
return null
}
}
return {
q: spec.q,
s: s,
}
}
function preferredMediaTypes(accept, provided) {
// RFC 2616 sec 14.2: no header = */*
accept = parseAccept(accept === undefined ? '*/*' : accept || '');
if (provided) {
return provided.map(function (type) {
return [type, getMediaTypePriority(type, accept)];
}).filter(function (pair) {
return pair[1] > 0;
}).sort(function (a, b) {
// revsort
return a[1] === b[1] ? 0 : a[1] > b[1] ? -1 : 1;
}).map(function (pair) {
return pair[0];
});
} else {
return accept.sort(function (a, b) {
// revsort
return a.q < b.q ? 1 : -1;
}).filter(function (type) {
return type.q > 0;
}).map(function (type) {
return type.full;
});
}
}
module.exports = Negotiator;
Negotiator.Negotiator = Negotiator;
function Negotiator(request) {
if (!(this instanceof Negotiator)) return new Negotiator(request);
this.request = request;
}
var set = { charset: 'accept-charset',
encoding: 'accept-encoding',
language: 'accept-language',
mediaType: 'accept' };
function capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
Object.keys(set).forEach(function (k) {
var header = set[k],
method = require('./' + k + '.js'),
singular = k,
plural = k + 's';
Negotiator.prototype[plural] = function (available) {
return method(this.request.headers[header], available);
};
Negotiator.prototype[singular] = function (available) {
var set = this[plural](available);
if (set) return set[0];
};
// Keep preferred* methods for legacy compatibility
Negotiator.prototype['preferred' + capitalize(plural)] = Negotiator.prototype[plural];
Negotiator.prototype['preferred' + capitalize(singular)] = Negotiator.prototype[singular];
})
Original "Negotiator" program Copyright Federico Romero
Port to JavaScript Copyright Isaac Z. Schlueter
All rights reserved.
MIT License
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.
{
"name": "negotiator",
"description": "HTTP content negotiation",
"version": "0.4.5",
"author": {
"name": "Federico Romero",
"email": "[email protected]"
},
"contributors": [
{
"name": "Isaac Z. Schlueter",
"email": "[email protected]",
"url": "http://blog.izs.me/"
}
],
"repository": {
"type": "git",
"url": "git://github.com/federomero/negotiator.git"
},
"keywords": [
"http",
"content negotiation",
"accept",
"accept-language",
"accept-encoding",
"accept-charset"
],
"engine": "node >= 0.6",
"license": "MIT",
"devDependencies": {
"nodeunit": "0.8.x"
},
"scripts": {
"test": "nodeunit test"
},
"optionalDependencies": {},
"engines": {
"node": "*"
},
"main": "lib/negotiator.js",
"readme": "# Negotiator [![Build Status](https://travis-ci.org/federomero/negotiator.png)](https://travis-ci.org/federomero/negotiator)\n\nAn HTTP content negotiator for node.js written in javascript.\n\n# Accept Negotiation\n\n Negotiator = require('negotiator')\n\n availableMediaTypes = ['text/html', 'text/plain', 'application/json']\n\n // The negotiator constructor receives a request object\n negotiator = new Negotiator(request)\n\n // Let's say Accept header is 'text/html, application/*;q=0.2, image/jpeg;q=0.8'\n\n negotiator.mediaTypes()\n // -> ['text/html', 'image/jpeg', 'application/*']\n\n negotiator.mediaTypes(availableMediaTypes)\n // -> ['text/html', 'application/json']\n\n negotiator.mediaType(availableMediaTypes)\n // -> 'text/html'\n\nYou can check a working example at `examples/accept.js`.\n\n## Methods\n\n`mediaTypes(availableMediaTypes)`:\n\nReturns an array of preferred media types ordered by priority from a list of available media types.\n\n`mediaType(availableMediaType)`:\n\nReturns the top preferred media type from a list of available media types.\n\n# Accept-Language Negotiation\n\n Negotiator = require('negotiator')\n\n negotiator = new Negotiator(request)\n\n availableLanguages = 'en', 'es', 'fr'\n\n // Let's say Accept-Language header is 'en;q=0.8, es, pt'\n\n negotiator.languages()\n // -> ['es', 'pt', 'en']\n\n negotiator.languages(availableLanguages)\n // -> ['es', 'en']\n\n language = negotiator.language(availableLanguages)\n // -> 'es'\n\nYou can check a working example at `examples/language.js`.\n\n## Methods\n\n`languages(availableLanguages)`:\n\nReturns an array of preferred languages ordered by priority from a list of available languages.\n\n`language(availableLanguages)`:\n\nReturns the top preferred language from a list of available languages.\n\n# Accept-Charset Negotiation\n\n Negotiator = require('negotiator')\n\n availableCharsets = ['utf-8', 'iso-8859-1', 'iso-8859-5']\n\n negotiator = new Negotiator(request)\n\n // Let's say Accept-Charset header is 'utf-8, iso-8859-1;q=0.8, utf-7;q=0.2'\n\n negotiator.charsets()\n // -> ['utf-8', 'iso-8859-1', 'utf-7']\n\n negotiator.charsets(availableCharsets)\n // -> ['utf-8', 'iso-8859-1']\n\n negotiator.charset(availableCharsets)\n // -> 'utf-8'\n\nYou can check a working example at `examples/charset.js`.\n\n## Methods\n\n`charsets(availableCharsets)`:\n\nReturns an array of preferred charsets ordered by priority from a list of available charsets.\n\n`charset(availableCharsets)`:\n\nReturns the top preferred charset from a list of available charsets.\n\n# Accept-Encoding Negotiation\n\n Negotiator = require('negotiator').Negotiator\n\n availableEncodings = ['identity', 'gzip']\n\n negotiator = new Negotiator(request)\n\n // Let's say Accept-Encoding header is 'gzip, compress;q=0.2, identity;q=0.5'\n\n negotiator.encodings()\n // -> ['gzip', 'identity', 'compress']\n\n negotiator.encodings(availableEncodings)\n // -> ['gzip', 'identity']\n\n negotiator.encoding(availableEncodings)\n // -> 'gzip'\n\nYou can check a working example at `examples/encoding.js`.\n\n## Methods\n\n`encodings(availableEncodings)`:\n\nReturns an array of preferred encodings ordered by priority from a list of available encodings.\n\n`encoding(availableEncodings)`:\n\nReturns the top preferred encoding from a list of available encodings.\n\n# License\n\nMIT\n",
"readmeFilename": "readme.md",
"bugs": {
"url": "https://github.com/federomero/negotiator/issues"
},
"homepage": "https://github.com/federomero/negotiator",
"dependencies": {},
"_id": "[email protected]",
"dist": {
"shasum": "fbd3aa072063bc4fa42c24419e27e91795a0018e"
},
"_from": "negotiator@~0.4.0",
"_resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.5.tgz"
}

Negotiator Build Status

An HTTP content negotiator for node.js written in javascript.

Accept Negotiation

Negotiator = require('negotiator')

availableMediaTypes = ['text/html', 'text/plain', 'application/json']

// The negotiator constructor receives a request object
negotiator = new Negotiator(request)

// Let's say Accept header is 'text/html, application/*;q=0.2, image/jpeg;q=0.8'

negotiator.mediaTypes()
// -> ['text/html', 'image/jpeg', 'application/*']

negotiator.mediaTypes(availableMediaTypes)
// -> ['text/html', 'application/json']

negotiator.mediaType(availableMediaTypes)
// -> 'text/html'

You can check a working example at examples/accept.js.

Methods

mediaTypes(availableMediaTypes):

Returns an array of preferred media types ordered by priority from a list of available media types.

mediaType(availableMediaType):

Returns the top preferred media type from a list of available media types.

Accept-Language Negotiation

Negotiator = require('negotiator')

negotiator = new Negotiator(request)

availableLanguages = 'en', 'es', 'fr'

// Let's say Accept-Language header is 'en;q=0.8, es, pt'

negotiator.languages()
// -> ['es', 'pt', 'en']

negotiator.languages(availableLanguages)
// -> ['es', 'en']

language = negotiator.language(availableLanguages)
// -> 'es'

You can check a working example at examples/language.js.

Methods

languages(availableLanguages):

Returns an array of preferred languages ordered by priority from a list of available languages.

language(availableLanguages):

Returns the top preferred language from a list of available languages.

Accept-Charset Negotiation

Negotiator = require('negotiator')

availableCharsets = ['utf-8', 'iso-8859-1', 'iso-8859-5']

negotiator = new Negotiator(request)

// Let's say Accept-Charset header is 'utf-8, iso-8859-1;q=0.8, utf-7;q=0.2'

negotiator.charsets()
// -> ['utf-8', 'iso-8859-1', 'utf-7']

negotiator.charsets(availableCharsets)
// -> ['utf-8', 'iso-8859-1']

negotiator.charset(availableCharsets)
// -> 'utf-8'

You can check a working example at examples/charset.js.

Methods

charsets(availableCharsets):

Returns an array of preferred charsets ordered by priority from a list of available charsets.

charset(availableCharsets):

Returns the top preferred charset from a list of available charsets.

Accept-Encoding Negotiation

Negotiator = require('negotiator').Negotiator

availableEncodings = ['identity', 'gzip']

negotiator = new Negotiator(request)

// Let's say Accept-Encoding header is 'gzip, compress;q=0.2, identity;q=0.5'

negotiator.encodings()
// -> ['gzip', 'identity', 'compress']

negotiator.encodings(availableEncodings)
// -> ['gzip', 'identity']

negotiator.encoding(availableEncodings)
// -> 'gzip'

You can check a working example at examples/encoding.js.

Methods

encodings(availableEncodings):

Returns an array of preferred encodings ordered by priority from a list of available encodings.

encoding(availableEncodings):

Returns the top preferred encoding from a list of available encodings.

License

MIT

{
"name": "accepts",
"description": "Higher-level content negotiation",
"version": "1.0.1",
"author": {
"name": "Jonathan Ong",
"email": "[email protected]",
"url": "http://jongleberry.com"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/expressjs/accepts.git"
},
"bugs": {
"url": "https://github.com/expressjs/accepts/issues"
},
"dependencies": {
"mime": "~1.2.11",
"negotiator": "~0.4.0"
},
"devDependencies": {
"mocha": "*",
"should": "*"
},
"scripts": {
"test": "make test"
},
"readme": "# Accepts [![Build Status](https://travis-ci.org/expressjs/accepts.png)](https://travis-ci.org/expressjs/accepts)\n\nHigher level content negotation based on [negotiator](https://github.com/federomero/negotiator). Extracted from [koa](https://github.com/koajs/koa) for general use.\n\nIn addition to negotatior, it allows:\n\n- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])` as well as `('text/html', 'application/json')`.\n- Allows type shorthands such as `json`.\n- Returns `false` when no types match\n- Treats non-existent headers as `*`\n\n## API\n\n### var accept = new Accepts(req)\n\n```js\nvar accepts = require('accepts')\n\nhttp.createServer(function (req, res) {\n var accept = accepts(req)\n})\n```\n\n### accept\\[property\\]\\(\\)\n\nReturns all the explicitly accepted content property as an array in descending priority.\n\n- `accept.types()`\n- `accept.encodings()`\n- `accept.charsets()`\n- `accept.languages()`\n\nThey are also aliased in singular form such as `accept.type()`. `accept.languages()` is also aliased as `accept.langs()`, etc.\n\nNote: you should almost never do this in a real app as it defeats the purpose of content negotiation.\n\nExample:\n\n```js\n// in Google Chrome\nvar encodings = accept.encodings() // -> ['sdch', 'gzip', 'deflate']\n```\n\nSince you probably don't support `sdch`, you should just supply the encodings you support:\n\n```js\nvar encoding = accept.encodings('gzip', 'deflate') // -> 'gzip', probably\n```\n\n### accept\\[property\\]\\(values, ...\\)\n\nYou can either have `values` be an array or have an argument list of values.\n\nIf the client does not accept any `values`, `false` will be returned.\nIf the client accepts any `values`, the preferred `value` will be return.\n\nFor `accept.types()`, shorthand mime types are allowed.\n\nExample:\n\n```js\n// req.headers.accept = 'application/json'\n\naccept.types('json') // -> 'json'\naccept.types('html', 'json') // -> 'json'\naccept.types('html') // -> false\n\n// req.headers.accept = ''\n// which is equivalent to `*`\n\naccept.types() // -> [], no explicit types\naccept.types('text/html', 'text/json') // -> 'text/html', since it was first\n```\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 Jonathan Ong [email protected]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.",
"readmeFilename": "README.md",
"homepage": "https://github.com/expressjs/accepts",
"_id": "[email protected]",
"dist": {
"shasum": "96d6d85d3462e6dcb01293192e144c7f5e012a8a"
},
"_from": "[email protected]",
"_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.0.1.tgz"
}

Accepts Build Status

Higher level content negotation based on negotiator. Extracted from koa for general use.

In addition to negotatior, it allows:

  • Allows types as an array or arguments list, ie (['text/html', 'application/json']) as well as ('text/html', 'application/json').
  • Allows type shorthands such as json.
  • Returns false when no types match
  • Treats non-existent headers as *

API

var accept = new Accepts(req)

var accepts = require('accepts')

http.createServer(function (req, res) {
  var accept = accepts(req)
})

accept[property]()

Returns all the explicitly accepted content property as an array in descending priority.

  • accept.types()
  • accept.encodings()
  • accept.charsets()
  • accept.languages()

They are also aliased in singular form such as accept.type(). accept.languages() is also aliased as accept.langs(), etc.

Note: you should almost never do this in a real app as it defeats the purpose of content negotiation.

Example:

// in Google Chrome
var encodings = accept.encodings() // -> ['sdch', 'gzip', 'deflate']

Since you probably don't support sdch, you should just supply the encodings you support:

var encoding = accept.encodings('gzip', 'deflate') // -> 'gzip', probably

accept[property](values, ...)

You can either have values be an array or have an argument list of values.

If the client does not accept any values, false will be returned. If the client accepts any values, the preferred value will be return.

For accept.types(), shorthand mime types are allowed.

Example:

// req.headers.accept = 'application/json'

accept.types('json') // -> 'json'
accept.types('html', 'json') // -> 'json'
accept.types('html') // -> false

// req.headers.accept = ''
// which is equivalent to `*`

accept.types() // -> [], no explicit types
accept.types('text/html', 'text/json') // -> 'text/html', since it was first

License

The MIT License (MIT)

Copyright (c) 2013 Jonathan Ong [email protected]

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.

language: node_js
node_js:
- 0.6
- 0.8
notifications:
email:
recipients:
- [email protected]
var Buffer = require('buffer').Buffer;
var CRC_TABLE = [
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
0x2d02ef8d
];
function bufferizeInt(num) {
var tmp = Buffer(4);
tmp.writeInt32BE(num, 0);
return tmp;
}
function _crc32(buf, previous) {
if (!Buffer.isBuffer(buf)) {
buf = Buffer(buf);
}
if (Buffer.isBuffer(previous)) {
previous = previous.readUInt32BE(0);
}
var crc = ~~previous ^ -1;
for (var n = 0; n < buf.length; n++) {
crc = CRC_TABLE[(crc ^ buf[n]) & 0xff] ^ (crc >>> 8);
}
return (crc ^ -1);
}
function crc32() {
return bufferizeInt(_crc32.apply(null, arguments));
}
crc32.signed = function () {
return _crc32.apply(null, arguments);
};
crc32.unsigned = function () {
return _crc32.apply(null, arguments) >>> 0;
};
module.exports = crc32;
{
"author": {
"name": "Brian J. Brennan",
"email": "[email protected]",
"url": "http://bjb.io"
},
"name": "buffer-crc32",
"description": "A pure javascript CRC32 algorithm that plays nice with binary data",
"version": "0.2.1",
"contributors": [
{
"name": "Vladimir Kuznetsov"
}
],
"homepage": "https://github.com/brianloveswords/buffer-crc32",
"repository": {
"type": "git",
"url": "git://github.com/brianloveswords/buffer-crc32.git"
},
"main": "index.js",
"scripts": {
"test": "tap tests/*.test.js"
},
"dependencies": {},
"devDependencies": {
"tap": "~0.2.5"
},
"optionalDependencies": {},
"engines": {
"node": "*"
},
"readme": "# buffer-crc32\n\n[![Build Status](https://secure.travis-ci.org/brianloveswords/buffer-crc32.png?branch=master)](http://travis-ci.org/brianloveswords/buffer-crc32)\n\ncrc32 that works with binary data and fancy character sets, outputs\nbuffer, signed or unsigned data and has tests.\n\nDerived from the sample CRC implementation in the PNG specification: http://www.w3.org/TR/PNG/#D-CRCAppendix\n\n# install\n```\nnpm install buffer-crc32\n```\n\n# example\n```js\nvar crc32 = require('buffer-crc32');\n// works with buffers\nvar buf = Buffer([0x00, 0x73, 0x75, 0x70, 0x20, 0x62, 0x72, 0x6f, 0x00])\ncrc32(buf) // -> <Buffer 94 5a ab 4a>\n\n// has convenience methods for getting signed or unsigned ints\ncrc32.signed(buf) // -> -1805997238\ncrc32.unsigned(buf) // -> 2488970058\n\n// will cast to buffer if given a string, so you can\n// directly use foreign characters safely\ncrc32('自動販売機') // -> <Buffer cb 03 1a c5>\n\n// and works in append mode too\nvar partialCrc = crc32('hey');\nvar partialCrc = crc32(' ', partialCrc);\nvar partialCrc = crc32('sup', partialCrc);\nvar partialCrc = crc32(' ', partialCrc);\nvar finalCrc = crc32('bros', partialCrc); // -> <Buffer 47 fa 55 70>\n```\n\n# tests\nThis was tested against the output of zlib's crc32 method. You can run\nthe tests with`npm test` (requires tap)\n\n# see also\nhttps://github.com/alexgorbatchev/node-crc, `crc.buffer.crc32` also\nsupports buffer inputs and return unsigned ints (thanks @tjholowaychuk).\n\n# license\nMIT/X11\n",
"readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/brianloveswords/buffer-crc32/issues"
},
"_id": "[email protected]",
"_from": "[email protected]"
}

buffer-crc32

Build Status

crc32 that works with binary data and fancy character sets, outputs buffer, signed or unsigned data and has tests.

Derived from the sample CRC implementation in the PNG specification: http://www.w3.org/TR/PNG/#D-CRCAppendix

install

npm install buffer-crc32

example

var crc32 = require('buffer-crc32');
// works with buffers
var buf = Buffer([0x00, 0x73, 0x75, 0x70, 0x20, 0x62, 0x72, 0x6f, 0x00])
crc32(buf) // -> <Buffer 94 5a ab 4a>

// has convenience methods for getting signed or unsigned ints
crc32.signed(buf) // -> -1805997238
crc32.unsigned(buf) // -> 2488970058

// will cast to buffer if given a string, so you can
// directly use foreign characters safely
crc32('自動販売機') // -> <Buffer cb 03 1a c5>

// and works in append mode too
var partialCrc = crc32('hey');
var partialCrc = crc32(' ', partialCrc);
var partialCrc = crc32('sup', partialCrc);
var partialCrc = crc32(' ', partialCrc);
var finalCrc = crc32('bros', partialCrc); // -> <Buffer 47 fa 55 70>

tests

This was tested against the output of zlib's crc32 method. You can run the tests withnpm test (requires tap)

see also

https://github.com/alexgorbatchev/node-crc, crc.buffer.crc32 also supports buffer inputs and return unsigned ints (thanks @tjholowaychuk).

license

MIT/X11

var crc32 = require('..');
var test = require('tap').test;
test('simple crc32 is no problem', function (t) {
var input = Buffer('hey sup bros');
var expected = Buffer([0x47, 0xfa, 0x55, 0x70]);
t.same(crc32(input), expected);
t.end();
});
test('another simple one', function (t) {
var input = Buffer('IEND');
var expected = Buffer([0xae, 0x42, 0x60, 0x82]);
t.same(crc32(input), expected);
t.end();
});
test('slightly more complex', function (t) {
var input = Buffer([0x00, 0x00, 0x00]);
var expected = Buffer([0xff, 0x41, 0xd9, 0x12]);
t.same(crc32(input), expected);
t.end();
});
test('complex crc32 gets calculated like a champ', function (t) {
var input = Buffer('शीर्षक');
var expected = Buffer([0x17, 0xb8, 0xaf, 0xf1]);
t.same(crc32(input), expected);
t.end();
});
test('casts to buffer if necessary', function (t) {
var input = 'शीर्षक';
var expected = Buffer([0x17, 0xb8, 0xaf, 0xf1]);
t.same(crc32(input), expected);
t.end();
});
test('can do signed', function (t) {
var input = 'ham sandwich';
var expected = -1891873021;
t.same(crc32.signed(input), expected);
t.end();
});
test('can do unsigned', function (t) {
var input = 'bear sandwich';
var expected = 3711466352;
t.same(crc32.unsigned(input), expected);
t.end();
});
test('simple crc32 in append mode', function (t) {
var input = [Buffer('hey'), Buffer(' '), Buffer('sup'), Buffer(' '), Buffer('bros')];
var expected = Buffer([0x47, 0xfa, 0x55, 0x70]);
for (var crc = 0, i = 0; i < input.length; i++) {
crc = crc32(input[i], crc);
}
t.same(crc, expected);
t.end();
});
test('can do signed in append mode', function (t) {
var input1 = 'ham';
var input2 = ' ';
var input3 = 'sandwich';
var expected = -1891873021;
var crc = crc32.signed(input1);
crc = crc32.signed(input2, crc);
crc = crc32.signed(input3, crc);
t.same(crc, expected);
t.end();
});
test('can do unsigned in append mode', function (t) {
var input1 = 'bear san';
var input2 = 'dwich';
var expected = 3711466352;
var crc = crc32.unsigned(input1);
crc = crc32.unsigned(input2, crc);
t.same(crc, expected);
t.end();
});
/**
* Expose `debug()` as the module.
*/
module.exports = debug;
/**
* Create a debugger with the given `name`.
*
* @param {String} name
* @return {Type}
* @api public
*/
function debug(name) {
if (!debug.enabled(name)) return function () {
};
return function (fmt) {
fmt = coerce(fmt);
var curr = new Date;
var ms = curr - (debug[name] || curr);
debug[name] = curr;
fmt = name
+ ' '
+ fmt
+ ' +' + debug.humanize(ms);
// This hackery is required for IE8
// where `console.log` doesn't have 'apply'
window.console
&& console.log
&& Function.prototype.apply.call(console.log, console, arguments);
}
}
/**
* The currently active debug mode names.
*/
debug.names = [];
debug.skips = [];
/**
* Enables a debug mode by name. This can include modes
* separated by a colon and wildcards.
*
* @param {String} name
* @api public
*/
debug.enable = function (name) {
try {
localStorage.debug = name;
} catch (e) {
}
var split = (name || '').split(/[\s,]+/)
, len = split.length;
for (var i = 0; i < len; i++) {
name = split[i].replace('*', '.*?');
if (name[0] === '-') {
debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
}
else {
debug.names.push(new RegExp('^' + name + '$'));
}
}
};
/**
* Disable debug output.
*
* @api public
*/
debug.disable = function () {
debug.enable('');
};
/**
* Humanize the given `ms`.
*
* @param {Number} m
* @return {String}
* @api private
*/
debug.humanize = function (ms) {
var sec = 1000
, min = 60 * 1000
, hour = 60 * min;
if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
if (ms >= min) return (ms / min).toFixed(1) + 'm';
if (ms >= sec) return (ms / sec | 0) + 's';
return ms + 'ms';
};
/**
* Returns true if the given mode name is enabled, false otherwise.
*
* @param {String} name
* @return {Boolean}
* @api public
*/
debug.enabled = function (name) {
for (var i = 0, len = debug.skips.length; i < len; i++) {
if (debug.skips[i].test(name)) {
return false;
}
}
for (var i = 0, len = debug.names.length; i < len; i++) {
if (debug.names[i].test(name)) {
return true;
}
}
return false;
};
/**
* Coerce `val`.
*/
function coerce(val) {
if (val instanceof Error) return val.stack || val.message;
return val;
}
// persist
try {
if (window.localStorage) debug.enable(localStorage.debug);
} catch (e) {
}
/**
* Module dependencies.
*/
var tty = require('tty');
/**
* Expose `debug()` as the module.
*/
module.exports = debug;
/**
* Enabled debuggers.
*/
var names = []
, skips = [];
/**
* Colors.
*/
var colors = [6, 2, 3, 4, 5, 1];
/**
* Previous debug() call.
*/
var prev = {};
/**
* Previously assigned color.
*/
var prevColor = 0;
/**
* Is stdout a TTY? Colored output is disabled when `true`.
*/
var isatty = tty.isatty(1);
/**
* Select a color.
*
* @return {Number}
* @api private
*/
function color() {
return colors[prevColor++ % colors.length];
}
/**
* Humanize the given `ms`.
*
* @param {Number} m
* @return {String}
* @api private
*/
function humanize(ms) {
var sec = 1000
, min = 60 * 1000
, hour = 60 * min;
if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
if (ms >= min) return (ms / min).toFixed(1) + 'm';
if (ms >= sec) return (ms / sec | 0) + 's';
return ms + 'ms';
}
/**
* Create a debugger with the given `name`.
*
* @param {String} name
* @return {Type}
* @api public
*/
function debug(name) {
function disabled() {
}
disabled.enabled = false;
var match = skips.some(function (re) {
return re.test(name);
});
if (match) return disabled;
match = names.some(function (re) {
return re.test(name);
});
if (!match) return disabled;
var c = color();
function colored(fmt) {
fmt = coerce(fmt);
var curr = new Date;
var ms = curr - (prev[name] || curr);
prev[name] = curr;
fmt = ' \u001b[9' + c + 'm' + name + ' '
+ '\u001b[3' + c + 'm\u001b[90m'
+ fmt + '\u001b[3' + c + 'm'
+ ' +' + humanize(ms) + '\u001b[0m';
console.log.apply(this, arguments);
}
function plain(fmt) {
fmt = coerce(fmt);
fmt = new Date().toUTCString()
+ ' ' + name + ' ' + fmt;
console.log.apply(this, arguments);
}
colored.enabled = plain.enabled = true;
return isatty || process.env.DEBUG_COLORS
? colored
: plain;
}
/**
* Coerce `val`.
*/
function coerce(val) {
if (val instanceof Error) return val.stack || val.message;
return val;
}
/**
* Enable specified `namespaces` for debugging.
*/
debug.enable = function (namespaces) {
namespaces.split(/[\s,]+/)
.forEach(function (name) {
name = name.replace('*', '.*?');
if (name[0] == '-') {
skips.push(new RegExp('^' + name.substr(1) + '$'));
} else {
names.push(new RegExp('^' + name + '$'));
}
});
};
/**
* Enable namespaces listed in `process.env.DEBUG` initially.
*/
debug.enable(process.env.DEBUG || '');
{
"name": "debug",
"version": "0.8.1",
"repository": {
"type": "git",
"url": "git://github.com/visionmedia/debug.git"
},
"description": "small debugging utility",
"keywords": [
"debug",
"log",
"debugger"
],
"author": {
"name": "TJ Holowaychuk",
"email": "[email protected]"
},
"dependencies": {},
"devDependencies": {
"mocha": "*"
},
"main": "lib/debug.js",
"browser": "./debug.js",
"engines": {
"node": "*"
},
"files": [
"lib/debug.js",
"debug.js"
],
"component": {
"scripts": {
"debug/index.js": "debug.js"
}
},
"readme": "# debug\n\n tiny node.js debugging utility modelled after node core's debugging technique.\n\n## Installation\n\n```\n$ npm install debug\n```\n\n## Usage\n\n With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.\n\nExample _app.js_:\n\n```js\nvar debug = require('debug')('http')\n , http = require('http')\n , name = 'My App';\n\n// fake app\n\ndebug('booting %s', name);\n\nhttp.createServer(function(req, res){\n debug(req.method + ' ' + req.url);\n res.end('hello\\n');\n}).listen(3000, function(){\n debug('listening');\n});\n\n// fake worker of some kind\n\nrequire('./worker');\n```\n\nExample _worker.js_:\n\n```js\nvar debug = require('debug')('worker');\n\nsetInterval(function(){\n debug('doing some work');\n}, 1000);\n```\n\n The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:\n\n ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)\n\n ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)\n\n## Millisecond diff\n\n When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the \"+NNNms\" will show you how much time was spent between calls.\n\n ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)\n\n When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:\n\n ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)\n\n## Conventions\n\n If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use \":\" to separate features. For example \"bodyParser\" from Connect would then be \"connect:bodyParser\".\n\n## Wildcards\n\n The `*` character may be used as a wildcard. Suppose for example your library has debuggers named \"connect:bodyParser\", \"connect:compress\", \"connect:session\", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.\n\n You can also exclude specific debuggers by prefixing them with a \"-\" character. For example, `DEBUG=* -connect:*` would include all debuggers except those starting with \"connect:\".\n\n## Browser support\n\n Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`.\n\n```js\na = debug('worker:a');\nb = debug('worker:b');\n\nsetInterval(function(){\n a('doing some work');\n}, 1000);\n\nsetInterval(function(){\n a('doing some work');\n}, 1200);\n```\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk &lt;[email protected]&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
"readmeFilename": "Readme.md",
"bugs": {
"url": "https://github.com/visionmedia/debug/issues"
},
"homepage": "https://github.com/visionmedia/debug",
"_id": "[email protected]",
"dist": {
"shasum": "6bebd978100e0c2f791b4e4f52efc8149de7f60a"
},
"_from": "[email protected]",
"_resolved": "https://registry.npmjs.org/debug/-/debug-0.8.1.tgz"
}

debug

tiny node.js debugging utility modelled after node core's debugging technique.

Installation

$ npm install debug

Usage

With debug you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated console.error, so all of the console format string goodies you're used to work fine. A unique color is selected per-function for visibility.

Example app.js:

var debug = require('debug')('http')
  , http = require('http')
  , name = 'My App';

// fake app

debug('booting %s', name);

http.createServer(function(req, res){
  debug(req.method + ' ' + req.url);
  res.end('hello\n');
}).listen(3000, function(){
  debug('listening');
});

// fake worker of some kind

require('./worker');

Example worker.js:

var debug = require('debug')('worker');

setInterval(function(){
  debug('doing some work');
}, 1000);

The DEBUG environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:

debug http and worker

debug worker

Millisecond diff

When actively developing an application it can be useful to see when the time spent between one debug() call and the next. Suppose for example you invoke debug() before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.

When stdout is not a TTY, Date#toUTCString() is used, making it more useful for logging the debug information as shown below:

Conventions

If you're using this in one or more of your libraries, you should use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you should prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".

Wildcards

The * character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with DEBUG=connect:bodyParser,connect.compress,connect:session, you may simply do DEBUG=connect:*, or to run everything using this module simply use DEBUG=*.

You can also exclude specific debuggers by prefixing them with a "-" character. For example, DEBUG=* -connect:* would include all debuggers except those starting with "connect:".

Browser support

Debug works in the browser as well, currently persisted by localStorage. For example if you have worker:a and worker:b as shown below, and wish to debug both type debug.enable('worker:*') in the console and refresh the page, this will remain until you disable with debug.disable().

a = debug('worker:a');
b = debug('worker:b');

setInterval(function(){
  a('doing some work');
}, 1000);

setInterval(function(){
  a('doing some work');
}, 1200);

License

(The MIT License)

Copyright (c) 2011 TJ Holowaychuk <[email protected]>

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.

{
"name": "escape-html",
"description": "Escape HTML entities",
"version": "1.0.1",
"keywords": ["escape", "html", "utility"],
"dependencies": {},
"scripts": [
"index.js"
]
}
/**
* Escape special characters in the given string of html.
*
* @param {String} html
* @return {String}
* @api private
*/
module.exports = function (html) {
return String(html)
.replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}
build: components index.js
@component build
components:
@Component install
clean:
rm -fr build components template.js
.PHONY: clean
{
"name": "escape-html",
"description": "Escape HTML entities",
"version": "1.0.1",
"keywords": [
"escape",
"html",
"utility"
],
"dependencies": {},
"main": "index.js",
"component": {
"scripts": {
"escape-html/index.js": "index.js"
}
},
"repository": {
"type": "git",
"url": "https://github.com/component/escape-html.git"
},
"readme": "\n# escape-html\n\n Escape HTML entities\n\n## Example\n\n```js\nvar escape = require('escape-html');\nescape(str);\n```\n\n## License\n\n MIT",
"readmeFilename": "Readme.md",
"bugs": {
"url": "https://github.com/component/escape-html/issues"
},
"homepage": "https://github.com/component/escape-html",
"_id": "[email protected]",
"_from": "[email protected]"
}

escape-html

Escape HTML entities

Example

var escape = require('escape-html');
escape(str);

License

MIT

0.2.1 / 2014-01-29

  • fix: support max-age=0 for end-to-end revalidation

0.2.0 / 2013-08-11

  • fix: return false for no-cache
/**
* Expose `fresh()`.
*/
module.exports = fresh;
/**
* Check freshness of `req` and `res` headers.
*
* When the cache is "fresh" __true__ is returned,
* otherwise __false__ is returned to indicate that
* the cache is now stale.
*
* @param {Object} req
* @param {Object} res
* @return {Boolean}
* @api public
*/
function fresh(req, res) {
// defaults
var etagMatches = true;
var notModified = true;
// fields
var modifiedSince = req['if-modified-since'];
var noneMatch = req['if-none-match'];
var lastModified = res['last-modified'];
var etag = res['etag'];
var cc = req['cache-control'];
// unconditional request
if (!modifiedSince && !noneMatch) return false;
// check for no-cache cache request directive
if (cc && cc.indexOf('no-cache') !== -1) return false;
// parse if-none-match
if (noneMatch) noneMatch = noneMatch.split(/ *, */);
// if-none-match
if (noneMatch) etagMatches = ~noneMatch.indexOf(etag) || '*' == noneMatch[0];
// if-modified-since
if (modifiedSince) {
modifiedSince = new Date(modifiedSince);
lastModified = new Date(lastModified);
notModified = lastModified <= modifiedSince;
}
return !!(etagMatches && notModified);
}
test:
@./node_modules/.bin/mocha \
--reporter spec \
--require should
.PHONY: test
{
"name": "fresh",
"author": {
"name": "TJ Holowaychuk",
"email": "[email protected]",
"url": "http://tjholowaychuk.com"
},
"description": "HTTP response freshness testing",
"version": "0.2.2",
"main": "index.js",
"repository": {
"type": "git",
"url": "https://github.com/visionmedia/node-fresh.git"
},
"dependencies": {},
"devDependencies": {
"mocha": "*",
"should": "*"
},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/visionmedia/node-fresh/blob/master/Readme.md#license"
}
],
"readme": "\n# node-fresh\n\n HTTP response freshness testing\n\n## fresh(req, res)\n\n Check freshness of `req` and `res` headers.\n\n When the cache is \"fresh\" __true__ is returned,\n otherwise __false__ is returned to indicate that\n the cache is now stale.\n\n## Example:\n\n```js\nvar req = { 'if-none-match': 'tobi' };\nvar res = { 'etag': 'luna' };\nfresh(req, res);\n// => false\n\nvar req = { 'if-none-match': 'tobi' };\nvar res = { 'etag': 'tobi' };\nfresh(req, res);\n// => true\n```\n\n## Installation\n\n```\n$ npm install fresh\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk &lt;[email protected]&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
"readmeFilename": "Readme.md",
"bugs": {
"url": "https://github.com/visionmedia/node-fresh/issues"
},
"homepage": "https://github.com/visionmedia/node-fresh",
"_id": "[email protected]",
"_from": "[email protected]"
}

node-fresh

HTTP response freshness testing

fresh(req, res)

Check freshness of req and res headers.

When the cache is "fresh" true is returned, otherwise false is returned to indicate that the cache is now stale.

Example:

var req = { 'if-none-match': 'tobi' };
var res = { 'etag': 'luna' };
fresh(req, res);
// => false

var req = { 'if-none-match': 'tobi' };
var res = { 'etag': 'tobi' };
fresh(req, res);
// => true

Installation

$ npm install fresh

License

(The MIT License)

Copyright (c) 2012 TJ Holowaychuk <[email protected]>

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.

# 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
Icon?
Thumbs.db
# Node.js #
###########
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
pids
logs
results
node_modules
npm-debug.log
# Components #
##############
/build
/components
/vendors
{
"name": "merge-descriptors",
"description": "Merge objects using descriptors",
"version": "0.0.2",
"scripts": [
"index.js"
],
"repo": "component/merge-descriptors",
"license": "MIT"
}
module.exports = function (dest, src) {
Object.getOwnPropertyNames(src).forEach(function (name) {
var descriptor = Object.getOwnPropertyDescriptor(src, name)
Object.defineProperty(dest, name, descriptor)
})
return dest
}
{
"name": "merge-descriptors",
"description": "Merge objects using descriptors",
"version": "0.0.2",
"author": {
"name": "Jonathan Ong",
"email": "[email protected]",
"url": "http://jongleberry.com"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/component/merge-descriptors.git"
},
"bugs": {
"url": "https://github.com/component/merge-descriptors/issues"
},
"scripts": {
"test": "make test;"
},
"readme": "# Merge Descriptors [![Build Status](https://travis-ci.org/component/merge-descriptors.png)](https://travis-ci.org/component/merge-descriptors)\n\nMerge objects using descriptors.\n\n```js\nvar thing = {\n get name() {\n return 'jon'\n }\n}\n\nvar animal = {\n\n}\n\nmerge(animal, thing)\n\nanimal.name === 'jon'\n```\n\n## API\n\n### merge(destination, source)\n\nOverwrites `destination`'s descriptors with `source`'s.\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 Jonathan Ong [email protected]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.",
"readmeFilename": "README.md",
"homepage": "https://github.com/component/merge-descriptors",
"_id": "[email protected]",
"dist": {
"shasum": "92d5742606f522b6855714880136719106b8f505"
},
"_from": "[email protected]",
"_resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-0.0.2.tgz"
}

Merge Descriptors Build Status

Merge objects using descriptors.

var thing = {
  get name() {
    return 'jon'
  }
}

var animal = {

}

merge(animal, thing)

animal.name === 'jon'

API

merge(destination, source)

Overwrites destination's descriptors with source's.

License

The MIT License (MIT)

Copyright (c) 2013 Jonathan Ong [email protected]

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.

1.0.0 / 2014-05-08

  • add PURGE. Closes #9

0.1.0 / 2013-10-28

  • add http.METHODS support
var http = require('http');
if (http.METHODS) {
module.exports = http.METHODS.map(function (method) {
return method.toLowerCase();
});
return;
}
module.exports = [
'get',
'post',
'put',
'head',
'delete',
'options',
'trace',
'copy',
'lock',
'mkcol',
'move',
'purge',
'propfind',
'proppatch',
'unlock',
'report',
'mkactivity',
'checkout',
'merge',
'm-search',
'notify',
'subscribe',
'unsubscribe',
'patch',
'search'
];
(The MIT License)
Copyright (c) 2013-2014 TJ Holowaychuk <[email protected]>
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.
{
"name": "methods",
"version": "1.0.0",
"description": "HTTP methods that node supports",
"main": "index.js",
"scripts": {
"test": "./node_modules/mocha/bin/mocha"
},
"keywords": [
"http",
"methods"
],
"author": {
"name": "TJ Holowaychuk"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/visionmedia/node-methods.git"
},
"devDependencies": {
"mocha": "1.17.x"
},
"readme": "\n# Methods\n\n HTTP verbs that node core's parser supports.\n",
"readmeFilename": "Readme.md",
"bugs": {
"url": "https://github.com/visionmedia/node-methods/issues"
},
"homepage": "https://github.com/visionmedia/node-methods",
"_id": "[email protected]",
"dist": {
"shasum": "fc333298c7a3b4fa01df64bae4e07661f466fd16"
},
"_from": "[email protected]",
"_resolved": "https://registry.npmjs.org/methods/-/methods-1.0.0.tgz"
}

Methods

HTTP verbs that node core's parser supports.

var http = require('http');
var assert = require('assert');
var methods = require('..');
describe('methods', function () {
if (http.METHODS) {
it('is a lowercased http.METHODS', function () {
var lowercased = http.METHODS.map(function (method) {
return method.toLowerCase();
});
assert.deepEqual(lowercased, methods);
});
} else {
it('contains GET, POST, PUT, and DELETE', function () {
assert.notEqual(methods.indexOf('get'), -1);
assert.notEqual(methods.indexOf('post'), -1);
assert.notEqual(methods.indexOf('put'), -1);
assert.notEqual(methods.indexOf('delete'), -1);
});
it('is all lowercase', function () {
for (var i = 0; i < methods.length; i++) {
assert(methods[i], methods[i].toLowerCase(), methods[i] + " isn't all lowercase");
}
});
}
});
# 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*
# Icon?
ehthumbs.db
Thumbs.db
# Node.js #
###########
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
pids
logs
results
node_modules
npm-debug.log
# Components #
##############
/build
/components
/public
var parse = require('url').parse;
/**
* Parse the `req` url with memoization.
*
* @param {ServerRequest} req
* @return {Object}
* @api private
*/
module.exports = function parseUrl(req) {
var parsed = req._parsedUrl;
if (parsed && parsed.href == req.url) {
return parsed;
} else {
parsed = parse(req.url);
if (parsed.auth && !parsed.protocol && ~parsed.href.indexOf('//')) {
// This parses pathnames, and a strange pathname like //r@e should work
parsed = parse(req.url.replace(/@/g, '%40'));
}
return req._parsedUrl = parsed;
}
};
{
"name": "parseurl",
"description": "parse a url with memoization",
"version": "1.0.1",
"author": {
"name": "Jonathan Ong",
"email": "[email protected]",
"url": "http://jongleberry.com"
},
"repository": {
"type": "git",
"url": "https://github.com/expressjs/parseurl.git"
},
"bugs": {
"url": "https://github.com/expressjs/parseurl/issues",
"email": "[email protected]"
},
"license": "MIT",
"readme": "# parseurl\n\nParse a URL with memoization.\n\n## API\n\n### var pathname = parseurl(req)\n\n`pathname` can then be passed to a router or something.\n\n## LICENSE\n\n(The MIT License)\n\nCopyright (c) 2014 Jonathan Ong <[email protected]>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
"readmeFilename": "README.md",
"homepage": "https://github.com/expressjs/parseurl",
"_id": "[email protected]",
"_from": "[email protected]"
}

parseurl

Parse a URL with memoization.

API

var pathname = parseurl(req)

pathname can then be passed to a router or something.

LICENSE

(The MIT License)

Copyright (c) 2014 Jonathan Ong [email protected]

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.

{
"name": "path-to-regexp",
"description": "Express style path to RegExp utility",
"version": "0.1.0",
"keywords": [
"express",
"regexp",
"route",
"routing"
],
"scripts": [
"index.js"
],
"license": "MIT"
}

0.1.0 / 2014-03-06

  • add options.end

0.0.2 / 2013-02-10

  • Update to match current express
  • add .license property to component.json
/**
* Expose `pathtoRegexp`.
*/
module.exports = pathtoRegexp;
/**
* Normalize the given path string,
* returning a regular expression.
*
* An empty array should be passed,
* which will contain the placeholder
* key names. For example "/user/:id" will
* then contain ["id"].
*
* @param {String|RegExp|Array} path
* @param {Array} keys
* @param {Object} options
* @return {RegExp}
* @api private
*/
function pathtoRegexp(path, keys, options) {
options = options || {};
var sensitive = options.sensitive;
var strict = options.strict;
var end = options.end !== false;
keys = keys || [];
if (path instanceof RegExp) return path;
if (path instanceof Array) path = '(' + path.join('|') + ')';
path = path
.concat(strict ? '' : '/?')
.replace(/\/\(/g, '/(?:')
.replace(/([\/\.])/g, '\\$1')
.replace(/(\\\/)?(\\\.)?:(\w+)(\(.*?\))?(\*)?(\?)?/g, function (match, slash, format, key, capture, star, optional) {
slash = slash || '';
format = format || '';
capture = capture || '([^/' + format + ']+?)';
optional = optional || '';
keys.push({ name: key, optional: !!optional });
return ''
+ (optional ? '' : slash)
+ '(?:'
+ format + (optional ? slash : '') + capture
+ (star ? '((?:[\\/' + format + '].+?)?)' : '')
+ ')'
+ optional;
})
.replace(/\*/g, '(.*)');
return new RegExp('^' + path + (end ? '$' : '(?=\/|$)'), sensitive ? '' : 'i');
};
{
"name": "path-to-regexp",
"description": "Express style path to RegExp utility",
"version": "0.1.2",
"scripts": {
"test": "istanbul cover _mocha -- -R spec"
},
"keywords": [
"express",
"regexp"
],
"component": {
"scripts": {
"path-to-regexp": "index.js"
}
},
"repository": {
"type": "git",
"url": "https://github.com/component/path-to-regexp.git"
},
"devDependencies": {
"mocha": "^1.17.1",
"istanbul": "^0.2.6"
},
"readme": "\n# Path-to-RegExp\n\n Turn an Express-style path string such as `/user/:name` into a regular expression.\n\n## Usage\n\n```javascript\nvar pathToRegexp = require('path-to-regexp');\n```\n### pathToRegexp(path, keys, options)\n\n - **path** A string in the express format, an array of such strings, or a regular expression\n - **keys** An array to be populated with the keys present in the url. Once the function completes, this will be an array of strings.\n - **options**\n - **options.sensitive** Defaults to false, set this to true to make routes case sensitive\n - **options.strict** Defaults to false, set this to true to make the trailing slash matter.\n - **options.end** Defaults to true, set this to false to only match the prefix of the URL.\n\n```javascript\nvar keys = [];\nvar exp = pathToRegexp('/foo/:bar', keys);\n//keys = ['bar']\n//exp = /^\\/foo\\/(?:([^\\/]+?))\\/?$/i\n```\n\n## Live Demo\n\nYou can see a live demo of this library in use at [express-route-tester](http://forbeslindesay.github.com/express-route-tester/).\n\n## License\n\n MIT",
"readmeFilename": "Readme.md",
"bugs": {
"url": "https://github.com/component/path-to-regexp/issues"
},
"homepage": "https://github.com/component/path-to-regexp",
"_id": "[email protected]",
"dist": {
"shasum": "927ef81437546826c81442f86009686802c6ec92"
},
"_from": "[email protected]",
"_resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.2.tgz"
}

Path-to-RegExp

Turn an Express-style path string such as /user/:name into a regular expression.

Usage

var pathToRegexp = require('path-to-regexp');

pathToRegexp(path, keys, options)

  • path A string in the express format, an array of such strings, or a regular expression
  • keys An array to be populated with the keys present in the url. Once the function completes, this will be an array of strings.
  • options
    • options.sensitive Defaults to false, set this to true to make routes case sensitive
    • options.strict Defaults to false, set this to true to make the trailing slash matter.
    • options.end Defaults to true, set this to false to only match the prefix of the URL.
var keys = [];
var exp = pathToRegexp('/foo/:bar', keys);
//keys = ['bar']
//exp = /^\/foo\/(?:([^\/]+?))\/?$/i

Live Demo

You can see a live demo of this library in use at express-route-tester.

License

MIT

var pathToRegExp = require('./');
var assert = require('assert');
describe('path-to-regexp', function () {
describe('strings', function () {
it('should match simple paths', function () {
var params = [];
var m = pathToRegExp('/test', params).exec('/test');
assert.equal(params.length, 0);
assert.equal(m.length, 1);
assert.equal(m[0], '/test');
});
it('should match express format params', function () {
var params = [];
var m = pathToRegExp('/:test', params).exec('/pathname');
assert.equal(params.length, 1);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
assert.equal(m.length, 2);
assert.equal(m[0], '/pathname');
assert.equal(m[1], 'pathname');
});
it('should do strict matches', function () {
var params = [];
var re = pathToRegExp('/:test', params, { strict: true });
var m;
assert.equal(params.length, 1);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
m = re.exec('/route');
assert.equal(m.length, 2);
assert.equal(m[0], '/route');
assert.equal(m[1], 'route');
m = re.exec('/route/');
assert.ok(!m);
});
it('should allow optional express format params', function () {
var params = [];
var re = pathToRegExp('/:test?', params);
var m;
assert.equal(params.length, 1);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, true);
m = re.exec('/route');
assert.equal(m.length, 2);
assert.equal(m[0], '/route');
assert.equal(m[1], 'route');
m = re.exec('/');
assert.equal(m.length, 2);
assert.equal(m[0], '/');
assert.equal(m[1], undefined);
});
it('should allow express format param regexps', function () {
var params = [];
var m = pathToRegExp('/:page(\\d+)', params).exec('/56');
assert.equal(params.length, 1);
assert.equal(params[0].name, 'page');
assert.equal(params[0].optional, false);
assert.equal(m.length, 2);
assert.equal(m[0], '/56');
assert.equal(m[1], '56');
});
it('should match without a prefixed slash', function () {
var params = [];
var m = pathToRegExp(':test', params).exec('string');
assert.equal(params.length, 1);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
assert.equal(m.length, 2);
assert.equal(m[0], 'string');
assert.equal(m[1], 'string');
});
it('should not match format parts', function () {
var params = [];
var m = pathToRegExp('/:test.json', params).exec('/route.json');
assert.equal(params.length, 1);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
assert.equal(m.length, 2);
assert.equal(m[0], '/route.json');
assert.equal(m[1], 'route');
});
it('should match format parts', function () {
var params = [];
var re = pathToRegExp('/:test.:format', params);
var m;
assert.equal(params.length, 2);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
assert.equal(params[1].name, 'format');
assert.equal(params[1].optional, false);
m = re.exec('/route.json');
assert.equal(m.length, 3);
assert.equal(m[0], '/route.json');
assert.equal(m[1], 'route');
assert.equal(m[2], 'json');
m = re.exec('/route');
assert.ok(!m);
});
it('should match route parts with a trailing format', function () {
var params = [];
var m = pathToRegExp('/:test.json', params).exec('/route.json');
assert.equal(params.length, 1);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
assert.equal(m.length, 2);
assert.equal(m[0], '/route.json');
assert.equal(m[1], 'route');
});
it('should match optional trailing routes', function () {
var params = [];
var m = pathToRegExp('/test*', params).exec('/test/route');
assert.equal(params.length, 0);
assert.equal(m.length, 2);
assert.equal(m[0], '/test/route');
assert.equal(m[1], '/route');
});
it('should match optional trailing routes after a param', function () {
var params = [];
var re = pathToRegExp('/:test*', params);
var m;
assert.equal(params.length, 1);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
m = re.exec('/test/route');
assert.equal(m.length, 3);
assert.equal(m[0], '/test/route');
assert.equal(m[1], 'test');
assert.equal(m[2], '/route');
m = re.exec('/testing');
assert.equal(m.length, 3);
assert.equal(m[0], '/testing');
assert.equal(m[1], 'testing');
assert.equal(m[2], '');
});
it('should match optional trailing routes before a format', function () {
var params = [];
var re = pathToRegExp('/test*.json', params);
var m;
assert.equal(params.length, 0);
m = re.exec('/test.json');
assert.equal(m.length, 2);
assert.equal(m[0], '/test.json');
assert.equal(m[1], '');
m = re.exec('/testing.json');
assert.equal(m.length, 2);
assert.equal(m[0], '/testing.json');
assert.equal(m[1], 'ing');
m = re.exec('/test/route.json');
assert.equal(m.length, 2);
assert.equal(m[0], '/test/route.json');
assert.equal(m[1], '/route');
});
it('should match optional trailing routes after a param and before a format', function () {
var params = [];
var re = pathToRegExp('/:test*.json', params);
var m;
assert.equal(params.length, 1);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
m = re.exec('/testing.json');
assert.equal(m.length, 3);
assert.equal(m[0], '/testing.json');
assert.equal(m[1], 'testing');
assert.equal(m[2], '');
m = re.exec('/test/route.json');
assert.equal(m.length, 3);
assert.equal(m[0], '/test/route.json');
assert.equal(m[1], 'test');
assert.equal(m[2], '/route');
m = re.exec('.json');
assert.ok(!m);
});
it('should match optional trailing routes between a normal param and a format param', function () {
var params = [];
var re = pathToRegExp('/:test*.:format', params);
var m;
assert.equal(params.length, 2);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
assert.equal(params[1].name, 'format');
assert.equal(params[1].optional, false);
m = re.exec('/testing.json');
assert.equal(m.length, 4);
assert.equal(m[0], '/testing.json');
assert.equal(m[1], 'testing');
assert.equal(m[2], '');
assert.equal(m[3], 'json');
m = re.exec('/test/route.json');
assert.equal(m.length, 4);
assert.equal(m[0], '/test/route.json');
assert.equal(m[1], 'test');
assert.equal(m[2], '/route');
assert.equal(m[3], 'json');
m = re.exec('/test');
assert.ok(!m);
m = re.exec('.json');
assert.ok(!m);
});
it('should match optional trailing routes after a param and before an optional format param', function () {
var params = [];
var re = pathToRegExp('/:test*.:format?', params);
var m;
assert.equal(params.length, 2);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
assert.equal(params[1].name, 'format');
assert.equal(params[1].optional, true);
m = re.exec('/testing.json');
assert.equal(m.length, 4);
assert.equal(m[0], '/testing.json');
assert.equal(m[1], 'testing');
assert.equal(m[2], '');
assert.equal(m[3], 'json');
m = re.exec('/test/route.json');
assert.equal(m.length, 4);
assert.equal(m[0], '/test/route.json');
assert.equal(m[1], 'test');
assert.equal(m[2], '/route');
assert.equal(m[3], 'json');
m = re.exec('/test');
assert.equal(m.length, 4);
assert.equal(m[0], '/test');
assert.equal(m[1], 'test');
assert.equal(m[2], '');
assert.equal(m[3], undefined);
m = re.exec('.json');
assert.ok(!m);
});
it('should match optional trailing routes inside optional express param', function () {
var params = [];
var re = pathToRegExp('/:test*?', params);
var m;
assert.equal(params.length, 1);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, true);
m = re.exec('/test/route');
assert.equal(m.length, 3);
assert.equal(m[0], '/test/route');
assert.equal(m[1], 'test');
assert.equal(m[2], '/route');
m = re.exec('/test');
assert.equal(m.length, 3);
assert.equal(m[0], '/test');
assert.equal(m[1], 'test');
assert.equal(m[2], '');
m = re.exec('/');
assert.equal(m.length, 3);
assert.equal(m[0], '/');
assert.equal(m[1], undefined);
assert.equal(m[2], undefined);
});
it('should do case insensitive matches', function () {
var m = pathToRegExp('/test').exec('/TEST');
assert.equal(m[0], '/TEST');
});
it('should do case sensitive matches', function () {
var re = pathToRegExp('/test', null, { sensitive: true });
var m;
m = re.exec('/test');
assert.equal(m.length, 1);
assert.equal(m[0], '/test');
m = re.exec('/TEST');
assert.ok(!m);
});
it('should do non-ending matches', function () {
var params = [];
var m = pathToRegExp('/:test', params, { end: false }).exec('/test/route');
assert.equal(params.length, 1);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
assert.equal(m.length, 2);
assert.equal(m[0], '/test');
assert.equal(m[1], 'test');
});
it('should match trailing slashes in non-ending non-strict mode', function () {
var params = [];
var re = pathToRegExp('/:test', params, { end: false });
var m;
assert.equal(params.length, 1);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
m = re.exec('/test/');
assert.equal(m.length, 2);
assert.equal(m[0], '/test/');
assert.equal(m[1], 'test');
});
it('should not match trailing slashes in non-ending strict mode', function () {
var params = [];
var re = pathToRegExp('/:test', params, { end: false, strict: true });
assert.equal(params.length, 1);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
m = re.exec('/test/');
assert.equal(m.length, 2);
assert.equal(m[0], '/test');
assert.equal(m[1], 'test');
});
it('should match text after an express param', function () {
var params = [];
var re = pathToRegExp('/(:test)route', params);
assert.equal(params.length, 1);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
m = re.exec('/route');
assert.ok(!m);
m = re.exec('/testroute');
assert.equal(m.length, 2);
assert.equal(m[0], '/testroute');
assert.equal(m[1], 'test');
m = re.exec('testroute');
assert.ok(!m);
});
it('should match text after an optional express param', function () {
var params = [];
var re = pathToRegExp('/(:test?)route', params);
var m;
assert.equal(params.length, 1);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, true);
m = re.exec('/route');
assert.equal(m.length, 2);
assert.equal(m[0], '/route');
assert.equal(m[1], undefined);
m = re.exec('/testroute');
assert.equal(m.length, 2);
assert.equal(m[0], '/testroute');
assert.equal(m[1], 'test');
m = re.exec('route');
assert.ok(!m);
});
it('should match optional formats', function () {
var params = [];
var re = pathToRegExp('/:test.:format?', params);
var m;
assert.equal(params.length, 2);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
assert.equal(params[1].name, 'format');
assert.equal(params[1].optional, true);
m = re.exec('/route');
assert.equal(m.length, 3);
assert.equal(m[0], '/route');
assert.equal(m[1], 'route');
assert.equal(m[2], undefined);
m = re.exec('/route.json');
assert.equal(m.length, 3);
assert.equal(m[0], '/route.json');
assert.equal(m[1], 'route');
assert.equal(m[2], 'json');
});
it('should match full paths with format by default', function () {
var params = [];
var m = pathToRegExp('/:test', params).exec('/test.json');
assert.equal(params.length, 1);
assert.equal(params[0].name, 'test');
assert.equal(params[0].optional, false);
assert.equal(m.length, 2);
assert.equal(m[0], '/test.json');
assert.equal(m[1], 'test.json');
});
});
describe('regexps', function () {
it('should return the regexp', function () {
assert.deepEqual(pathToRegExp(/.*/), /.*/);
});
});
describe('arrays', function () {
it('should join arrays parts', function () {
var re = pathToRegExp(['/test', '/route']);
assert.ok(re.exec('/test'));
assert.ok(re.exec('/route'));
assert.ok(!re.exec('/else'));
});
});
});
[submodule "support/expresso"]
path = support/expresso
url = git://github.com/visionmedia/expresso.git
[submodule "support/should"]
path = support/should
url = git://github.com/visionmedia/should.js.git
test
.travis.yml
benchmark.js
component.json
examples.js
History.md
Makefile
/**
* Object#toString() ref for stringify().
*/
var toString = Object.prototype.toString;
/**
* Object#hasOwnProperty ref
*/
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* Array#indexOf shim.
*/
var indexOf = typeof Array.prototype.indexOf === 'function'
? function (arr, el) {
return arr.indexOf(el);
}
: function (arr, el) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] === el) return i;
}
return -1;
};
/**
* Array.isArray shim.
*/
var isArray = Array.isArray || function (arr) {
return toString.call(arr) == '[object Array]';
};
/**
* Object.keys shim.
*/
var objectKeys = Object.keys || function (obj) {
var ret = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
ret.push(key);
}
}
return ret;
};
/**
* Array#forEach shim.
*/
var forEach = typeof Array.prototype.forEach === 'function'
? function (arr, fn) {
return arr.forEach(fn);
}
: function (arr, fn) {
for (var i = 0; i < arr.length; i++) fn(arr[i]);
};
/**
* Array#reduce shim.
*/
var reduce = function (arr, fn, initial) {
if (typeof arr.reduce === 'function') return arr.reduce(fn, initial);
var res = initial;
for (var i = 0; i < arr.length; i++) res = fn(res, arr[i]);
return res;
};
/**
* Cache non-integer test regexp.
*/
var isint = /^[0-9]+$/;
function promote(parent, key) {
if (parent[key].length == 0) return parent[key] = {}
var t = {};
for (var i in parent[key]) {
if (hasOwnProperty.call(parent[key], i)) {
t[i] = parent[key][i];
}
}
parent[key] = t;
return t;
}
function parse(parts, parent, key, val) {
var part = parts.shift();
// illegal
if (Object.getOwnPropertyDescriptor(Object.prototype, key)) return;
// end
if (!part) {
if (isArray(parent[key])) {
parent[key].push(val);
} else if ('object' == typeof parent[key]) {
parent[key] = val;
} else if ('undefined' == typeof parent[key]) {
parent[key] = val;
} else {
parent[key] = [parent[key], val];
}
// array
} else {
var obj = parent[key] = parent[key] || [];
if (']' == part) {
if (isArray(obj)) {
if ('' != val) obj.push(val);
} else if ('object' == typeof obj) {
obj[objectKeys(obj).length] = val;
} else {
obj = parent[key] = [parent[key], val];
}
// prop
} else if (~indexOf(part, ']')) {
part = part.substr(0, part.length - 1);
if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
parse(parts, obj, part, val);
// key
} else {
if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
parse(parts, obj, part, val);
}
}
}
/**
* Merge parent key/val pair.
*/
function merge(parent, key, val) {
if (~indexOf(key, ']')) {
var parts = key.split('[')
, len = parts.length
, last = len - 1;
parse(parts, parent, 'base', val);
// optimize
} else {
if (!isint.test(key) && isArray(parent.base)) {
var t = {};
for (var k in parent.base) t[k] = parent.base[k];
parent.base = t;
}
set(parent.base, key, val);
}
return parent;
}
/**
* Compact sparse arrays.
*/
function compact(obj) {
if ('object' != typeof obj) return obj;
if (isArray(obj)) {
var ret = [];
for (var i in obj) {
if (hasOwnProperty.call(obj, i)) {
ret.push(obj[i]);
}
}
return ret;
}
for (var key in obj) {
obj[key] = compact(obj[key]);
}
return obj;
}
/**
* Parse the given obj.
*/
function parseObject(obj) {
var ret = { base: {} };
forEach(objectKeys(obj), function (name) {
merge(ret, name, obj[name]);
});
return compact(ret.base);
}
/**
* Parse the given str.
*/
function parseString(str) {
var ret = reduce(String(str).split('&'), function (ret, pair) {
var eql = indexOf(pair, '=')
, brace = lastBraceInKey(pair)
, key = pair.substr(0, brace || eql)
, val = pair.substr(brace || eql, pair.length)
, val = val.substr(indexOf(val, '=') + 1, val.length);
// ?foo
if ('' == key) key = pair, val = '';
if ('' == key) return ret;
return merge(ret, decode(key), decode(val));
}, { base: {} }).base;
return compact(ret);
}
/**
* Parse the given query `str` or `obj`, returning an object.
*
* @param {String} str | {Object} obj
* @return {Object}
* @api public
*/
exports.parse = function (str) {
if (null == str || '' == str) return {};
return 'object' == typeof str
? parseObject(str)
: parseString(str);
};
/**
* Turn the given `obj` into a query string
*
* @param {Object} obj
* @return {String}
* @api public
*/
var stringify = exports.stringify = function (obj, prefix) {
if (isArray(obj)) {
return stringifyArray(obj, prefix);
} else if ('[object Object]' == toString.call(obj)) {
return stringifyObject(obj, prefix);
} else if ('string' == typeof obj) {
return stringifyString(obj, prefix);
} else {
return prefix + '=' + encodeURIComponent(String(obj));
}
};
/**
* Stringify the given `str`.
*
* @param {String} str
* @param {String} prefix
* @return {String}
* @api private
*/
function stringifyString(str, prefix) {
if (!prefix) throw new TypeError('stringify expects an object');
return prefix + '=' + encodeURIComponent(str);
}
/**
* Stringify the given `arr`.
*
* @param {Array} arr
* @param {String} prefix
* @return {String}
* @api private
*/
function stringifyArray(arr, prefix) {
var ret = [];
if (!prefix) throw new TypeError('stringify expects an object');
for (var i = 0; i < arr.length; i++) {
ret.push(stringify(arr[i], prefix + '[' + i + ']'));
}
return ret.join('&');
}
/**
* Stringify the given `obj`.
*
* @param {Object} obj
* @param {String} prefix
* @return {String}
* @api private
*/
function stringifyObject(obj, prefix) {
var ret = []
, keys = objectKeys(obj)
, key;
for (var i = 0, len = keys.length; i < len; ++i) {
key = keys[i];
if ('' == key) continue;
if (null == obj[key]) {
ret.push(encodeURIComponent(key) + '=');
} else {
ret.push(stringify(obj[key], prefix
? prefix + '[' + encodeURIComponent(key) + ']'
: encodeURIComponent(key)));
}
}
return ret.join('&');
}
/**
* Set `obj`'s `key` to `val` respecting
* the weird and wonderful syntax of a qs,
* where "foo=bar&foo=baz" becomes an array.
*
* @param {Object} obj
* @param {String} key
* @param {String} val
* @api private
*/
function set(obj, key, val) {
var v = obj[key];
if (Object.getOwnPropertyDescriptor(Object.prototype, key)) return;
if (undefined === v) {
obj[key] = val;
} else if (isArray(v)) {
v.push(val);
} else {
obj[key] = [v, val];
}
}
/**
* Locate last brace in `str` within the key.
*
* @param {String} str
* @return {Number}
* @api private
*/
function lastBraceInKey(str) {
var len = str.length
, brace
, c;
for (var i = 0; i < len; ++i) {
c = str[i];
if (']' == c) brace = false;
if ('[' == c) brace = true;
if ('=' == c && !brace) return i;
}
}
/**
* Decode `str`.
*
* @param {String} str
* @return {String}
* @api private
*/
function decode(str) {
try {
return decodeURIComponent(str.replace(/\+/g, ' '));
} catch (err) {
return str;
}
}
{
"name": "qs",
"description": "querystring parser",
"version": "0.6.6",
"keywords": [
"query string",
"parser",
"component"
],
"repository": {
"type": "git",
"url": "git://github.com/visionmedia/node-querystring.git"
},
"devDependencies": {
"mocha": "*",
"expect.js": "*"
},
"scripts": {
"test": "make test"
},
"author": {
"name": "TJ Holowaychuk",
"email": "[email protected]",
"url": "http://tjholowaychuk.com"
},
"main": "index",
"engines": {
"node": "*"
},
"readme": "# node-querystring\n\n query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.\n\n## Installation\n\n $ npm install qs\n\n## Examples\n\n```js\nvar qs = require('qs');\n\nqs.parse('user[name][first]=Tobi&user[email][email protected]');\n// => { user: { name: { first: 'Tobi' }, email: '[email protected]' } }\n\nqs.stringify({ user: { name: 'Tobi', email: '[email protected]' }})\n// => user[name]=Tobi&user[email]=tobi%40learnboost.com\n```\n\n## Testing\n\nInstall dev dependencies:\n\n $ npm install -d\n\nand execute:\n\n $ make test\n\nbrowser:\n\n $ open test/browser/index.html\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2010 TJ Holowaychuk &lt;[email protected]&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
"readmeFilename": "Readme.md",
"bugs": {
"url": "https://github.com/visionmedia/node-querystring/issues"
},
"homepage": "https://github.com/visionmedia/node-querystring",
"_id": "[email protected]",
"dist": {
"shasum": "971541a143106eea48b882de809e3d433d1c52b1"
},
"_from": "qs@~0.6.6",
"_resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz"
}

node-querystring

query string parser for node and the browser supporting nesting, as it was removed from 0.3.x, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by express, connect and others.

Installation

$ npm install qs

Examples

var qs = require('qs');

qs.parse('user[name][first]=Tobi&user[email][email protected]');
// => { user: { name: { first: 'Tobi' }, email: '[email protected]' } }

qs.stringify({ user: { name: 'Tobi', email: '[email protected]' }})
// => user[name]=Tobi&user[email]=tobi%40learnboost.com

Testing

Install dev dependencies:

$ npm install -d

and execute:

$ make test

browser:

$ open test/browser/index.html

License

(The MIT License)

Copyright (c) 2010 TJ Holowaychuk <[email protected]>

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.

1.0.0 / 2013-12-11

  • add repository to package.json
  • add MIT license

0.0.4 / 2012-06-17

  • changed: ret -1 for unsatisfiable and -2 when invalid

0.0.3 / 2012-06-17

  • fix last-byte-pos default to len - 1

0.0.2 / 2012-06-14

  • add .type
/**
* Parse "Range" header `str` relative to the given file `size`.
*
* @param {Number} size
* @param {String} str
* @return {Array}
* @api public
*/
module.exports = function (size, str) {
var valid = true;
var i = str.indexOf('=');
if (-1 == i) return -2;
var arr = str.slice(i + 1).split(',').map(function (range) {
var range = range.split('-')
, start = parseInt(range[0], 10)
, end = parseInt(range[1], 10);
// -nnn
if (isNaN(start)) {
start = size - end;
end = size - 1;
// nnn-
} else if (isNaN(end)) {
end = size - 1;
}
// limit last-byte-pos to current length
if (end > size - 1) end = size - 1;
// invalid
if (isNaN(start)
|| isNaN(end)
|| start > end
|| start < 0) valid = false;
return {
start: start,
end: end
};
});
arr.type = str.slice(0, i);
return valid ? arr : -1;
};
test:
@./node_modules/.bin/mocha \
--reporter spec \
--require should
.PHONY: test
{
"name": "range-parser",
"author": {
"name": "TJ Holowaychuk",
"email": "[email protected]",
"url": "http://tjholowaychuk.com"
},
"description": "Range header field string parser",
"version": "1.0.0",
"repository": {
"type": "git",
"url": "https://github.com/visionmedia/node-range-parser.git"
},
"main": "index.js",
"dependencies": {},
"devDependencies": {
"mocha": "*",
"should": "*"
},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/visionmedia/node-range-parser#license"
}
],
"readme": "\n# node-range-parser\n\n Range header field parser.\n\n## Example:\n\n```js\nassert(-1 == parse(200, 'bytes=500-20'));\nassert(-2 == parse(200, 'bytes=malformed'));\nparse(200, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 199 }]));\nparse(1000, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 499 }]));\nparse(1000, 'bytes=40-80').should.eql(arr('bytes', [{ start: 40, end: 80 }]));\nparse(1000, 'bytes=-500').should.eql(arr('bytes', [{ start: 500, end: 999 }]));\nparse(1000, 'bytes=-400').should.eql(arr('bytes', [{ start: 600, end: 999 }]));\nparse(1000, 'bytes=500-').should.eql(arr('bytes', [{ start: 500, end: 999 }]));\nparse(1000, 'bytes=400-').should.eql(arr('bytes', [{ start: 400, end: 999 }]));\nparse(1000, 'bytes=0-0').should.eql(arr('bytes', [{ start: 0, end: 0 }]));\nparse(1000, 'bytes=-1').should.eql(arr('bytes', [{ start: 999, end: 999 }]));\nparse(1000, 'items=0-5').should.eql(arr('items', [{ start: 0, end: 5 }]));\nparse(1000, 'bytes=40-80,-1').should.eql(arr('bytes', [{ start: 40, end: 80 }, { start: 999, end: 999 }]));\n```\n\n## Installation\n\n```\n$ npm install range-parser\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk &lt;[email protected]&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
"readmeFilename": "Readme.md",
"bugs": {
"url": "https://github.com/visionmedia/node-range-parser/issues"
},
"homepage": "https://github.com/visionmedia/node-range-parser",
"_id": "[email protected]",
"_from": "[email protected]"
}

node-range-parser

Range header field parser.

Example:

assert(-1 == parse(200, 'bytes=500-20'));
assert(-2 == parse(200, 'bytes=malformed'));
parse(200, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 199 }]));
parse(1000, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 499 }]));
parse(1000, 'bytes=40-80').should.eql(arr('bytes', [{ start: 40, end: 80 }]));
parse(1000, 'bytes=-500').should.eql(arr('bytes', [{ start: 500, end: 999 }]));
parse(1000, 'bytes=-400').should.eql(arr('bytes', [{ start: 600, end: 999 }]));
parse(1000, 'bytes=500-').should.eql(arr('bytes', [{ start: 500, end: 999 }]));
parse(1000, 'bytes=400-').should.eql(arr('bytes', [{ start: 400, end: 999 }]));
parse(1000, 'bytes=0-0').should.eql(arr('bytes', [{ start: 0, end: 0 }]));
parse(1000, 'bytes=-1').should.eql(arr('bytes', [{ start: 999, end: 999 }]));
parse(1000, 'items=0-5').should.eql(arr('items', [{ start: 0, end: 5 }]));
parse(1000, 'bytes=40-80,-1').should.eql(arr('bytes', [{ start: 40, end: 80 }, { start: 999, end: 999 }]));

Installation

$ npm install range-parser

License

(The MIT License)

Copyright (c) 2012 TJ Holowaychuk <[email protected]>

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.

0.3.0 / 2014-04-24

  • Fix sending files with dots without root set
  • Coerce option types
  • Accept API options in options object
  • Set etags to "weak"
  • Include file path in etag
  • Make "Can't set headers after they are sent." catchable
  • Send full entity-body for multi range requests
  • Default directory access to 403 when index disabled
  • Support multiple index paths
  • Support "If-Range" header
  • Control whether to generate etags
  • deps: [email protected]

0.2.0 / 2014-01-29

  • update range-parser and fresh

0.1.4 / 2013-08-11

  • update fresh

0.1.3 / 2013-07-08

  • Revert "Fix fd leak"

0.1.2 / 2013-07-03

  • Fix fd leak

0.1.0 / 2012-08-25

  • add options parameter to send() that is passed to fs.createReadStream() [kanongil]

0.0.4 / 2012-08-16

  • allow custom "Accept-Ranges" definition

0.0.3 / 2012-07-16

  • fix normalization of the root directory. Closes #3

0.0.2 / 2012-07-09

  • add passing of req explicitly for now (YUCK)

0.0.1 / 2010-01-03

  • Initial release
/**
* Module dependencies.
*/
var debug = require('debug')('send')
, parseRange = require('range-parser')
, Stream = require('stream')
, mime = require('mime')
, fresh = require('fresh')
, path = require('path')
, http = require('http')
, fs = require('fs')
, basename = path.basename
, normalize = path.normalize
, join = path.join
, utils = require('./utils');
var upPathRegexp = /(?:^|[\\\/])\.\.(?:[\\\/]|$)/;
/**
* Expose `send`.
*/
exports = module.exports = send;
/**
* Expose mime module.
*/
exports.mime = mime;
/**
* Return a `SendStream` for `req` and `path`.
*
* @param {Request} req
* @param {String} path
* @param {Object} options
* @return {SendStream}
* @api public
*/
function send(req, path, options) {
return new SendStream(req, path, options);
}
/**
* Initialize a `SendStream` with the given `path`.
*
* Events:
*
* - `error` an error occurred
* - `stream` file streaming has started
* - `end` streaming has completed
* - `directory` a directory was requested
*
* @param {Request} req
* @param {String} path
* @param {Object} options
* @api private
*/
function SendStream(req, path, options) {
var self = this;
options = options || {};
this.req = req;
this.path = path;
this.options = options;
this.etag(('etag' in options) ? options.etag : true);
this.maxage(options.maxage);
this.hidden(options.hidden);
this.index(('index' in options) ? options.index : 'index.html');
if (options.root || options.from) this.root(options.root || options.from);
}
/**
* Inherits from `Stream.prototype`.
*/
SendStream.prototype.__proto__ = Stream.prototype;
/**
* Enable or disable etag generation.
*
* @param {Boolean} val
* @return {SendStream}
* @api public
*/
SendStream.prototype.etag = function (val) {
val = Boolean(val);
debug('etag %s', val);
this._etag = val;
return this;
};
/**
* Enable or disable "hidden" (dot) files.
*
* @param {Boolean} path
* @return {SendStream}
* @api public
*/
SendStream.prototype.hidden = function (val) {
val = Boolean(val);
debug('hidden %s', val);
this._hidden = val;
return this;
};
/**
* Set index `paths`, set to a falsy
* value to disable index support.
*
* @param {String|Boolean|Array} paths
* @return {SendStream}
* @api public
*/
SendStream.prototype.index = function index(paths) {
var index = !paths ? [] : Array.isArray(paths) ? paths : [paths];
debug('index %j', index);
this._index = index;
return this;
};
/**
* Set root `path`.
*
* @param {String} path
* @return {SendStream}
* @api public
*/
SendStream.prototype.root =
SendStream.prototype.from = function (path) {
path = String(path);
this._root = normalize(path);
return this;
};
/**
* Set max-age to `ms`.
*
* @param {Number} ms
* @return {SendStream}
* @api public
*/
SendStream.prototype.maxage = function (ms) {
ms = Number(ms);
if (isNaN(ms)) ms = 0;
if (Infinity == ms) ms = 60 * 60 * 24 * 365 * 1000;
debug('max-age %d', ms);
this._maxage = ms;
return this;
};
/**
* Emit error with `status`.
*
* @param {Number} status
* @api private
*/
SendStream.prototype.error = function (status, err) {
var res = this.res;
var msg = http.STATUS_CODES[status];
err = err || new Error(msg);
err.status = status;
if (this.listeners('error').length) return this.emit('error', err);
res.statusCode = err.status;
res.end(msg);
};
/**
* Check if the pathname is potentially malicious.
*
* @return {Boolean}
* @api private
*/
SendStream.prototype.isMalicious = function () {
return !this._root && ~this.path.indexOf('..') && upPathRegexp.test(this.path);
};
/**
* Check if the pathname ends with "/".
*
* @return {Boolean}
* @api private
*/
SendStream.prototype.hasTrailingSlash = function () {
return '/' == this.path[this.path.length - 1];
};
/**
* Check if the basename leads with ".".
*
* @return {Boolean}
* @api private
*/
SendStream.prototype.hasLeadingDot = function () {
return '.' == basename(this.path)[0];
};
/**
* Check if this is a conditional GET request.
*
* @return {Boolean}
* @api private
*/
SendStream.prototype.isConditionalGET = function () {
return this.req.headers['if-none-match']
|| this.req.headers['if-modified-since'];
};
/**
* Strip content-* header fields.
*
* @api private
*/
SendStream.prototype.removeContentHeaderFields = function () {
var res = this.res;
Object.keys(res._headers).forEach(function (field) {
if (0 == field.indexOf('content')) {
res.removeHeader(field);
}
});
};
/**
* Respond with 304 not modified.
*
* @api private
*/
SendStream.prototype.notModified = function () {
var res = this.res;
debug('not modified');
this.removeContentHeaderFields();
res.statusCode = 304;
res.end();
};
/**
* Raise error that headers already sent.
*
* @api private
*/
SendStream.prototype.headersAlreadySent = function headersAlreadySent() {
var err = new Error('Can\'t set headers after they are sent.');
debug('headers already sent');
this.error(500, err);
};
/**
* Check if the request is cacheable, aka
* responded with 2xx or 304 (see RFC 2616 section 14.2{5,6}).
*
* @return {Boolean}
* @api private
*/
SendStream.prototype.isCachable = function () {
var res = this.res;
return (res.statusCode >= 200 && res.statusCode < 300) || 304 == res.statusCode;
};
/**
* Handle stat() error.
*
* @param {Error} err
* @api private
*/
SendStream.prototype.onStatError = function (err) {
var notfound = ['ENOENT', 'ENAMETOOLONG', 'ENOTDIR'];
if (~notfound.indexOf(err.code)) return this.error(404, err);
this.error(500, err);
};
/**
* Check if the cache is fresh.
*
* @return {Boolean}
* @api private
*/
SendStream.prototype.isFresh = function () {
return fresh(this.req.headers, this.res._headers);
};
/**
* Check if the range is fresh.
*
* @return {Boolean}
* @api private
*/
SendStream.prototype.isRangeFresh = function isRangeFresh() {
var ifRange = this.req.headers['if-range'];
if (!ifRange) return true;
return ~ifRange.indexOf('"')
? ~ifRange.indexOf(this.res._headers['etag'])
: Date.parse(this.res._headers['last-modified']) <= Date.parse(ifRange);
};
/**
* Redirect to `path`.
*
* @param {String} path
* @api private
*/
SendStream.prototype.redirect = function (path) {
if (this.listeners('directory').length) return this.emit('directory');
if (this.hasTrailingSlash()) return this.error(403);
var res = this.res;
path += '/';
res.statusCode = 301;
res.setHeader('Location', path);
res.end('Redirecting to ' + utils.escape(path));
};
/**
* Pipe to `res.
*
* @param {Stream} res
* @return {Stream} res
* @api public
*/
SendStream.prototype.pipe = function (res) {
var self = this
, args = arguments
, path = this.path
, root = this._root;
// references
this.res = res;
// invalid request uri
path = utils.decode(path);
if (-1 == path) return this.error(400);
// null byte(s)
if (~path.indexOf('\0')) return this.error(400);
// join / normalize from optional root dir
if (root) path = normalize(join(this._root, path));
// ".." is malicious without "root"
if (this.isMalicious()) return this.error(403);
// malicious path
if (root && 0 != path.indexOf(root)) return this.error(403);
// hidden file support
if (!this._hidden && this.hasLeadingDot()) return this.error(404);
// index file support
if (this._index.length && this.hasTrailingSlash()) {
this.sendIndex(path);
return res;
}
debug('stat "%s"', path);
fs.stat(path, function (err, stat) {
if (err) return self.onStatError(err);
if (stat.isDirectory()) return self.redirect(self.path);
self.emit('file', path, stat);
self.send(path, stat);
});
return res;
};
/**
* Transfer `path`.
*
* @param {String} path
* @api public
*/
SendStream.prototype.send = function (path, stat) {
var options = this.options;
var len = stat.size;
var res = this.res;
var req = this.req;
var ranges = req.headers.range;
var offset = options.start || 0;
if (res._header) {
// impossible to send now
return this.headersAlreadySent();
}
// set header fields
this.setHeader(path, stat);
// set content-type
this.type(path);
// conditional GET support
if (this.isConditionalGET()
&& this.isCachable()
&& this.isFresh()) {
return this.notModified();
}
// adjust len to start/end options
len = Math.max(0, len - offset);
if (options.end !== undefined) {
var bytes = options.end - offset + 1;
if (len > bytes) len = bytes;
}
// Range support
if (ranges) {
ranges = parseRange(len, ranges);
// If-Range support
if (!this.isRangeFresh()) {
debug('range stale');
ranges = -2;
}
// unsatisfiable
if (-1 == ranges) {
debug('range unsatisfiable');
res.setHeader('Content-Range', 'bytes */' + stat.size);
return this.error(416);
}
// valid (syntactically invalid/multiple ranges are treated as a regular response)
if (-2 != ranges && ranges.length === 1) {
debug('range %j', ranges);
options.start = offset + ranges[0].start;
options.end = offset + ranges[0].end;
// Content-Range
res.statusCode = 206;
res.setHeader('Content-Range', 'bytes '
+ ranges[0].start
+ '-'
+ ranges[0].end
+ '/'
+ len);
len = options.end - options.start + 1;
}
}
// content-length
res.setHeader('Content-Length', len);
// HEAD support
if ('HEAD' == req.method) return res.end();
this.stream(path, options);
};
/**
* Transfer index for `path`.
*
* @param {String} path
* @api private
*/
SendStream.prototype.sendIndex = function sendIndex(path) {
var i = -1;
var self = this;
function next(err) {
if (i++ >= self._index.length) {
if (err) return self.onStatError(err);
return self.redirect(self.path);
}
var p = path + self._index[i];
debug('stat "%s"', p);
fs.stat(p, function (err, stat) {
if (err) return next(err);
if (stat.isDirectory()) return self.redirect(self.path);
self.emit('file', p, stat);
self.send(p, stat);
});
}
if (!this.hasTrailingSlash()) path += '/';
next();
};
/**
* Stream `path` to the response.
*
* @param {String} path
* @param {Object} options
* @api private
*/
SendStream.prototype.stream = function (path, options) {
// TODO: this is all lame, refactor meeee
var self = this;
var res = this.res;
var req = this.req;
// pipe
var stream = fs.createReadStream(path, options);
this.emit('stream', stream);
stream.pipe(res);
// socket closed, done with the fd
req.on('close', stream.destroy.bind(stream));
// error handling code-smell
stream.on('error', function (err) {
// no hope in responding
if (res._header) {
console.error(err.stack);
req.destroy();
return;
}
// 500
err.status = 500;
self.emit('error', err);
});
// end
stream.on('end', function () {
self.emit('end');
});
};
/**
* Set content-type based on `path`
* if it hasn't been explicitly set.
*
* @param {String} path
* @api private
*/
SendStream.prototype.type = function (path) {
var res = this.res;
if (res.getHeader('Content-Type')) return;
var type = mime.lookup(path);
var charset = mime.charsets.lookup(type);
debug('content-type %s', type);
res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
};
/**
* Set response header fields, most
* fields may be pre-defined.
*
* @param {String} path
* @param {Object} stat
* @api private
*/
SendStream.prototype.setHeader = function setHeader(path, stat) {
var res = this.res;
if (!res.getHeader('Accept-Ranges')) res.setHeader('Accept-Ranges', 'bytes');
if (!res.getHeader('Date')) res.setHeader('Date', new Date().toUTCString());
if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + (this._maxage / 1000));
if (!res.getHeader('Last-Modified')) res.setHeader('Last-Modified', stat.mtime.toUTCString());
if (this._etag && !res.getHeader('ETag')) {
var etag = utils.etag(path, stat);
debug('etag %s', etag);
res.setHeader('ETag', etag);
}
};
/**
* Module dependencies.
*/
var crc32 = require('buffer-crc32').unsigned;
/**
* Return a weak ETag from the given `path` and `stat`.
*
* @param {String} path
* @param {Object} stat
* @return {String}
* @api private
*/
exports.etag = function etag(path, stat) {
var tag = String(stat.mtime.getTime()) + ':' + String(stat.size) + ':' + path;
return 'W/"' + crc32(tag) + '"';
};
/**
* decodeURIComponent.
*
* Allows V8 to only deoptimize this fn instead of all
* of send().
*
* @param {String} path
* @api private
*/
exports.decode = function (path) {
try {
return decodeURIComponent(path);
} catch (err) {
return -1;
}
};
/**
* Escape the given string of `html`.
*
* @param {String} html
* @return {String}
* @api private
*/
exports.escape = function (html) {
return String(html)
.replace(/&(?!\w+;)/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
};
/**
* Expose `debug()` as the module.
*/
module.exports = debug;
/**
* Create a debugger with the given `name`.
*
* @param {String} name
* @return {Type}
* @api public
*/
function debug(name) {
if (!debug.enabled(name)) return function () {
};
return function (fmt) {
fmt = coerce(fmt);
var curr = new Date;
var ms = curr - (debug[name] || curr);
debug[name] = curr;
fmt = name
+ ' '
+ fmt
+ ' +' + debug.humanize(ms);
// This hackery is required for IE8
// where `console.log` doesn't have 'apply'
window.console
&& console.log
&& Function.prototype.apply.call(console.log, console, arguments);
}
}
/**
* The currently active debug mode names.
*/
debug.names = [];
debug.skips = [];
/**
* Enables a debug mode by name. This can include modes
* separated by a colon and wildcards.
*
* @param {String} name
* @api public
*/
debug.enable = function (name) {
try {
localStorage.debug = name;
} catch (e) {
}
var split = (name || '').split(/[\s,]+/)
, len = split.length;
for (var i = 0; i < len; i++) {
name = split[i].replace('*', '.*?');
if (name[0] === '-') {
debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
}
else {
debug.names.push(new RegExp('^' + name + '$'));
}
}
};
/**
* Disable debug output.
*
* @api public
*/
debug.disable = function () {
debug.enable('');
};
/**
* Humanize the given `ms`.
*
* @param {Number} m
* @return {String}
* @api private
*/
debug.humanize = function (ms) {
var sec = 1000
, min = 60 * 1000
, hour = 60 * min;
if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
if (ms >= min) return (ms / min).toFixed(1) + 'm';
if (ms >= sec) return (ms / sec | 0) + 's';
return ms + 'ms';
};
/**
* Returns true if the given mode name is enabled, false otherwise.
*
* @param {String} name
* @return {Boolean}
* @api public
*/
debug.enabled = function (name) {
for (var i = 0, len = debug.skips.length; i < len; i++) {
if (debug.skips[i].test(name)) {
return false;
}
}
for (var i = 0, len = debug.names.length; i < len; i++) {
if (debug.names[i].test(name)) {
return true;
}
}
return false;
};
/**
* Coerce `val`.
*/
function coerce(val) {
if (val instanceof Error) return val.stack || val.message;
return val;
}
// persist
try {
if (window.localStorage) debug.enable(localStorage.debug);
} catch (e) {
}
/**
* Module dependencies.
*/
var tty = require('tty');
/**
* Expose `debug()` as the module.
*/
module.exports = debug;
/**
* Enabled debuggers.
*/
var names = []
, skips = [];
/**
* Colors.
*/
var colors = [6, 2, 3, 4, 5, 1];
/**
* Previous debug() call.
*/
var prev = {};
/**
* Previously assigned color.
*/
var prevColor = 0;
/**
* Is stdout a TTY? Colored output is disabled when `true`.
*/
var isatty = tty.isatty(1);
/**
* Select a color.
*
* @return {Number}
* @api private
*/
function color() {
return colors[prevColor++ % colors.length];
}
/**
* Humanize the given `ms`.
*
* @param {Number} m
* @return {String}
* @api private
*/
function humanize(ms) {
var sec = 1000
, min = 60 * 1000
, hour = 60 * min;
if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
if (ms >= min) return (ms / min).toFixed(1) + 'm';
if (ms >= sec) return (ms / sec | 0) + 's';
return ms + 'ms';
}
/**
* Create a debugger with the given `name`.
*
* @param {String} name
* @return {Type}
* @api public
*/
function debug(name) {
function disabled() {
}
disabled.enabled = false;
var match = skips.some(function (re) {
return re.test(name);
});
if (match) return disabled;
match = names.some(function (re) {
return re.test(name);
});
if (!match) return disabled;
var c = color();
function colored(fmt) {
fmt = coerce(fmt);
var curr = new Date;
var ms = curr - (prev[name] || curr);
prev[name] = curr;
fmt = ' \u001b[9' + c + 'm' + name + ' '
+ '\u001b[3' + c + 'm\u001b[90m'
+ fmt + '\u001b[3' + c + 'm'
+ ' +' + humanize(ms) + '\u001b[0m';
console.log.apply(this, arguments);
}
function plain(fmt) {
fmt = coerce(fmt);
fmt = new Date().toUTCString()
+ ' ' + name + ' ' + fmt;
console.log.apply(this, arguments);
}
colored.enabled = plain.enabled = true;
return isatty || process.env.DEBUG_COLORS
? colored
: plain;
}
/**
* Coerce `val`.
*/
function coerce(val) {
if (val instanceof Error) return val.stack || val.message;
return val;
}
/**
* Enable specified `namespaces` for debugging.
*/
debug.enable = function (namespaces) {
namespaces.split(/[\s,]+/)
.forEach(function (name) {
name = name.replace('*', '.*?');
if (name[0] == '-') {
skips.push(new RegExp('^' + name.substr(1) + '$'));
} else {
names.push(new RegExp('^' + name + '$'));
}
});
};
/**
* Enable namespaces listed in `process.env.DEBUG` initially.
*/
debug.enable(process.env.DEBUG || '');
{
"name": "debug",
"version": "0.8.0",
"repository": {
"type": "git",
"url": "git://github.com/visionmedia/debug.git"
},
"description": "small debugging utility",
"keywords": [
"debug",
"log",
"debugger"
],
"author": {
"name": "TJ Holowaychuk",
"email": "[email protected]"
},
"dependencies": {},
"devDependencies": {
"mocha": "*"
},
"main": "lib/debug.js",
"browser": "./debug.js",
"engines": {
"node": "*"
},
"files": [
"lib/debug.js",
"debug.js"
],
"readme": "# debug\n\n tiny node.js debugging utility modelled after node core's debugging technique.\n\n## Installation\n\n```\n$ npm install debug\n```\n\n## Usage\n\n With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.\n\nExample _app.js_:\n\n```js\nvar debug = require('debug')('http')\n , http = require('http')\n , name = 'My App';\n\n// fake app\n\ndebug('booting %s', name);\n\nhttp.createServer(function(req, res){\n debug(req.method + ' ' + req.url);\n res.end('hello\\n');\n}).listen(3000, function(){\n debug('listening');\n});\n\n// fake worker of some kind\n\nrequire('./worker');\n```\n\nExample _worker.js_:\n\n```js\nvar debug = require('debug')('worker');\n\nsetInterval(function(){\n debug('doing some work');\n}, 1000);\n```\n\n The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:\n\n ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)\n\n ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)\n\n## Millisecond diff\n\n When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the \"+NNNms\" will show you how much time was spent between calls.\n\n ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)\n\n When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:\n\n ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)\n\n## Conventions\n\n If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use \":\" to separate features. For example \"bodyParser\" from Connect would then be \"connect:bodyParser\".\n\n## Wildcards\n\n The `*` character may be used as a wildcard. Suppose for example your library has debuggers named \"connect:bodyParser\", \"connect:compress\", \"connect:session\", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.\n\n You can also exclude specific debuggers by prefixing them with a \"-\" character. For example, `DEBUG=* -connect:*` would include all debuggers except those starting with \"connect:\".\n\n## Browser support\n\n Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`.\n\n```js\na = debug('worker:a');\nb = debug('worker:b');\n\nsetInterval(function(){\n a('doing some work');\n}, 1000);\n\nsetInterval(function(){\n a('doing some work');\n}, 1200);\n```\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk &lt;[email protected]&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
"readmeFilename": "Readme.md",
"bugs": {
"url": "https://github.com/visionmedia/debug/issues"
},
"homepage": "https://github.com/visionmedia/debug",
"_id": "[email protected]",
"dist": {
"shasum": "6f38eda347ebc5353c87f4476a183b11a235089c"
},
"_from": "[email protected]",
"_resolved": "https://registry.npmjs.org/debug/-/debug-0.8.0.tgz"
}

debug

tiny node.js debugging utility modelled after node core's debugging technique.

Installation

$ npm install debug

Usage

With debug you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated console.error, so all of the console format string goodies you're used to work fine. A unique color is selected per-function for visibility.

Example app.js:

var debug = require('debug')('http')
  , http = require('http')
  , name = 'My App';

// fake app

debug('booting %s', name);

http.createServer(function(req, res){
  debug(req.method + ' ' + req.url);
  res.end('hello\n');
}).listen(3000, function(){
  debug('listening');
});

// fake worker of some kind

require('./worker');

Example worker.js:

var debug = require('debug')('worker');

setInterval(function(){
  debug('doing some work');
}, 1000);

The DEBUG environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:

debug http and worker

debug worker

Millisecond diff

When actively developing an application it can be useful to see when the time spent between one debug() call and the next. Suppose for example you invoke debug() before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.

When stdout is not a TTY, Date#toUTCString() is used, making it more useful for logging the debug information as shown below:

Conventions

If you're using this in one or more of your libraries, you should use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you should prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".

Wildcards

The * character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with DEBUG=connect:bodyParser,connect.compress,connect:session, you may simply do DEBUG=connect:*, or to run everything using this module simply use DEBUG=*.

You can also exclude specific debuggers by prefixing them with a "-" character. For example, DEBUG=* -connect:* would include all debuggers except those starting with "connect:".

Browser support

Debug works in the browser as well, currently persisted by localStorage. For example if you have worker:a and worker:b as shown below, and wish to debug both type debug.enable('worker:*') in the console and refresh the page, this will remain until you disable with debug.disable().

a = debug('worker:a');
b = debug('worker:b');

setInterval(function(){
  a('doing some work');
}, 1000);

setInterval(function(){
  a('doing some work');
}, 1200);

License

(The MIT License)

Copyright (c) 2011 TJ Holowaychuk <[email protected]>

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.

Copyright (c) 2010 Benjamin Thomas, Robert Kieffer
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.
var path = require('path');
var fs = require('fs');
function Mime() {
// Map of extension -> mime type
this.types = Object.create(null);
// Map of mime type -> extension
this.extensions = Object.create(null);
}
/**
* Define mimetype -> extension mappings. Each key is a mime-type that maps
* to an array of extensions associated with the type. The first extension is
* used as the default extension for the type.
*
* e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']});
*
* @param map (Object) type definitions
*/
Mime.prototype.define = function (map) {
for (var type in map) {
var exts = map[type];
for (var i = 0; i < exts.length; i++) {
if (process.env.DEBUG_MIME && this.types[exts]) {
console.warn(this._loading.replace(/.*\//, ''), 'changes "' + exts[i] + '" extension type from ' +
this.types[exts] + ' to ' + type);
}
this.types[exts[i]] = type;
}
// Default extension is the first one we encounter
if (!this.extensions[type]) {
this.extensions[type] = exts[0];
}
}
};
/**
* Load an Apache2-style ".types" file
*
* This may be called multiple times (it's expected). Where files declare
* overlapping types/extensions, the last file wins.
*
* @param file (String) path of file to load.
*/
Mime.prototype.load = function (file) {
this._loading = file;
// Read file and split into lines
var map = {},
content = fs.readFileSync(file, 'ascii'),
lines = content.split(/[\r\n]+/);
lines.forEach(function (line) {
// Clean up whitespace/comments, and split into fields
var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/);
map[fields.shift()] = fields;
});
this.define(map);
this._loading = null;
};
/**
* Lookup a mime type based on extension
*/
Mime.prototype.lookup = function (path, fallback) {
var ext = path.replace(/.*[\.\/\\]/, '').toLowerCase();
return this.types[ext] || fallback || this.default_type;
};
/**
* Return file extension associated with a mime type
*/
Mime.prototype.extension = function (mimeType) {
var type = mimeType.match(/^\s*([^;\s]*)(?:;|\s|$)/)[1].toLowerCase();
return this.extensions[type];
};
// Default instance
var mime = new Mime();
// Load local copy of
// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
mime.load(path.join(__dirname, 'types/mime.types'));
// Load additional types from node.js community
mime.load(path.join(__dirname, 'types/node.types'));
// Default type
mime.default_type = mime.lookup('bin');
//
// Additional API specific to the default instance
//
mime.Mime = Mime;
/**
* Lookup a charset based on mime type.
*/
mime.charsets = {
lookup: function (mimeType, fallback) {
// Assume text types are utf8
return (/^text\//).test(mimeType) ? 'UTF-8' : fallback;
}
};
module.exports = mime;
{
"author": {
"name": "Robert Kieffer",
"email": "[email protected]",
"url": "http://github.com/broofa"
},
"contributors": [
{
"name": "Benjamin Thomas",
"email": "[email protected]",
"url": "http://github.com/bentomas"
}
],
"dependencies": {},
"description": "A comprehensive library for mime-type mapping",
"devDependencies": {},
"keywords": [
"util",
"mime"
],
"main": "mime.js",
"name": "mime",
"repository": {
"url": "https://github.com/broofa/node-mime",
"type": "git"
},
"version": "1.2.11",
"readme": "# mime\n\nComprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.\n\n## Install\n\nInstall with [npm](http://github.com/isaacs/npm):\n\n npm install mime\n\n## API - Queries\n\n### mime.lookup(path)\nGet the mime type associated with a file, if no mime type is found `application/octet-stream` is returned. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.'). E.g.\n\n var mime = require('mime');\n\n mime.lookup('/path/to/file.txt'); // => 'text/plain'\n mime.lookup('file.txt'); // => 'text/plain'\n mime.lookup('.TXT'); // => 'text/plain'\n mime.lookup('htm'); // => 'text/html'\n\n### mime.default_type\nSets the mime type returned when `mime.lookup` fails to find the extension searched for. (Default is `application/octet-stream`.)\n\n### mime.extension(type)\nGet the default extension for `type`\n\n mime.extension('text/html'); // => 'html'\n mime.extension('application/octet-stream'); // => 'bin'\n\n### mime.charsets.lookup()\n\nMap mime-type to charset\n\n mime.charsets.lookup('text/plain'); // => 'UTF-8'\n\n(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.)\n\n## API - Defining Custom Types\n\nThe following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types).\n\n### mime.define()\n\nAdd custom mime/extension mappings\n\n mime.define({\n 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],\n 'application/x-my-type': ['x-mt', 'x-mtt'],\n // etc ...\n });\n\n mime.lookup('x-sft'); // => 'text/x-some-format'\n\nThe first entry in the extensions array is returned by `mime.extension()`. E.g.\n\n mime.extension('text/x-some-format'); // => 'x-sf'\n\n### mime.load(filepath)\n\nLoad mappings from an Apache \".types\" format file\n\n mime.load('./my_project.types');\n\nThe .types file format is simple - See the `types` dir for examples.\n",
"readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/broofa/node-mime/issues"
},
"homepage": "https://github.com/broofa/node-mime",
"_id": "[email protected]",
"dist": {
"shasum": "8401d4ab4f06fcf4bc53e86d918c0443ccaa7274"
},
"_from": "mime@~1.2.11",
"_resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz"
}

mime

Comprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.

Install

Install with npm:

npm install mime

API - Queries

mime.lookup(path)

Get the mime type associated with a file, if no mime type is found application/octet-stream is returned. Performs a case-insensitive lookup using the extension in path (the substring after the last '/' or '.'). E.g.

var mime = require('mime');

mime.lookup('/path/to/file.txt');         // => 'text/plain'
mime.lookup('file.txt');                  // => 'text/plain'
mime.lookup('.TXT');                      // => 'text/plain'
mime.lookup('htm');                       // => 'text/html'

mime.default_type

Sets the mime type returned when mime.lookup fails to find the extension searched for. (Default is application/octet-stream.)

mime.extension(type)

Get the default extension for type

mime.extension('text/html');                 // => 'html'
mime.extension('application/octet-stream');  // => 'bin'

mime.charsets.lookup()

Map mime-type to charset

mime.charsets.lookup('text/plain');        // => 'UTF-8'

(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.)

API - Defining Custom Types

The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see requesting new types.

mime.define()

Add custom mime/extension mappings

mime.define({
    'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],
    'application/x-my-type': ['x-mt', 'x-mtt'],
    // etc ...
});

mime.lookup('x-sft');                 // => 'text/x-some-format'

The first entry in the extensions array is returned by mime.extension(). E.g.

mime.extension('text/x-some-format'); // => 'x-sf'

mime.load(filepath)

Load mappings from an Apache ".types" format file

mime.load('./my_project.types');

The .types file format is simple - See the types dir for examples.

/**
* Usage: node test.js
*/
var mime = require('./mime');
var assert = require('assert');
var path = require('path');
function eq(a, b) {
console.log('Test: ' + a + ' === ' + b);
assert.strictEqual.apply(null, arguments);
}
console.log(Object.keys(mime.extensions).length + ' types');
console.log(Object.keys(mime.types).length + ' extensions\n');
//
// Test mime lookups
//
eq('text/plain', mime.lookup('text.txt')); // normal file
eq('text/plain', mime.lookup('TEXT.TXT')); // uppercase
eq('text/plain', mime.lookup('dir/text.txt')); // dir + file
eq('text/plain', mime.lookup('.text.txt')); // hidden file
eq('text/plain', mime.lookup('.txt')); // nameless
eq('text/plain', mime.lookup('txt')); // extension-only
eq('text/plain', mime.lookup('/txt')); // extension-less ()
eq('text/plain', mime.lookup('\\txt')); // Windows, extension-less
eq('application/octet-stream', mime.lookup('text.nope')); // unrecognized
eq('fallback', mime.lookup('text.fallback', 'fallback')); // alternate default
//
// Test extensions
//
eq('txt', mime.extension(mime.types.text));
eq('html', mime.extension(mime.types.htm));
eq('bin', mime.extension('application/octet-stream'));
eq('bin', mime.extension('application/octet-stream '));
eq('html', mime.extension(' text/html; charset=UTF-8'));
eq('html', mime.extension('text/html; charset=UTF-8 '));
eq('html', mime.extension('text/html; charset=UTF-8'));
eq('html', mime.extension('text/html ; charset=UTF-8'));
eq('html', mime.extension('text/html;charset=UTF-8'));
eq('html', mime.extension('text/Html;charset=UTF-8'));
eq(undefined, mime.extension('unrecognized'));
//
// Test node.types lookups
//
eq('application/font-woff', mime.lookup('file.woff'));
eq('application/octet-stream', mime.lookup('file.buffer'));
eq('audio/mp4', mime.lookup('file.m4a'));
eq('font/opentype', mime.lookup('file.otf'));
//
// Test charsets
//
eq('UTF-8', mime.charsets.lookup('text/plain'));
eq(undefined, mime.charsets.lookup(mime.types.js));
eq('fallback', mime.charsets.lookup('application/octet-stream', 'fallback'));
//
// Test for overlaps between mime.types and node.types
//
var apacheTypes = new mime.Mime(), nodeTypes = new mime.Mime();
apacheTypes.load(path.join(__dirname, 'types/mime.types'));
nodeTypes.load(path.join(__dirname, 'types/node.types'));
var keys = [].concat(Object.keys(apacheTypes.types))
.concat(Object.keys(nodeTypes.types));
keys.sort();
for (var i = 1; i < keys.length; i++) {
if (keys[i] == keys[i - 1]) {
console.warn('Warning: ' +
'node.types defines ' + keys[i] + '->' + nodeTypes.types[keys[i]] +
', mime.types defines ' + keys[i] + '->' + apacheTypes.types[keys[i]]);
}
}
console.log('\nOK');
# This file maps Internet media types to unique file extension(s).
# Although created for httpd, this file is used by many software systems
# and has been placed in the public domain for unlimited redisribution.
#
# The table below contains both registered and (common) unregistered types.
# A type that has no unique extension can be ignored -- they are listed
# here to guide configurations toward known types and to make it easier to
# identify "new" types. File extensions are also commonly used to indicate
# content languages and encodings, so choose them carefully.
#
# Internet media types should be registered as described in RFC 4288.
# The registry is at <http://www.iana.org/assignments/media-types/>.
#
# MIME type (lowercased) Extensions
# ============================================ ==========
# application/1d-interleaved-parityfec
# application/3gpp-ims+xml
# application/activemessage
application/andrew-inset ez
# application/applefile
application/applixware aw
application/atom+xml atom
application/atomcat+xml atomcat
# application/atomicmail
application/atomsvc+xml atomsvc
# application/auth-policy+xml
# application/batch-smtp
# application/beep+xml
# application/calendar+xml
# application/cals-1840
# application/ccmp+xml
application/ccxml+xml ccxml
application/cdmi-capability cdmia
application/cdmi-container cdmic
application/cdmi-domain cdmid
application/cdmi-object cdmio
application/cdmi-queue cdmiq
# application/cea-2018+xml
# application/cellml+xml
# application/cfw
# application/cnrp+xml
# application/commonground
# application/conference-info+xml
# application/cpl+xml
# application/csta+xml
# application/cstadata+xml
application/cu-seeme cu
# application/cybercash
application/davmount+xml davmount
# application/dca-rft
# application/dec-dx
# application/dialog-info+xml
# application/dicom
# application/dns
application/docbook+xml dbk
# application/dskpp+xml
application/dssc+der dssc
application/dssc+xml xdssc
# application/dvcs
application/ecmascript ecma
# application/edi-consent
# application/edi-x12
# application/edifact
application/emma+xml emma
# application/epp+xml
application/epub+zip epub
# application/eshop
# application/example
application/exi exi
# application/fastinfoset
# application/fastsoap
# application/fits
application/font-tdpfr pfr
# application/framework-attributes+xml
application/gml+xml gml
application/gpx+xml gpx
application/gxf gxf
# application/h224
# application/held+xml
# application/http
application/hyperstudio stk
# application/ibe-key-request+xml
# application/ibe-pkg-reply+xml
# application/ibe-pp-data
# application/iges
# application/im-iscomposing+xml
# application/index
# application/index.cmd
# application/index.obj
# application/index.response
# application/index.vnd
application/inkml+xml ink inkml
# application/iotp
application/ipfix ipfix
# application/ipp
# application/isup
application/java-archive jar
application/java-serialized-object ser
application/java-vm class
application/javascript js
application/json json
application/jsonml+json jsonml
# application/kpml-request+xml
# application/kpml-response+xml
application/lost+xml lostxml
application/mac-binhex40 hqx
application/mac-compactpro cpt
# application/macwriteii
application/mads+xml mads
application/marc mrc
application/marcxml+xml mrcx
application/mathematica ma nb mb
# application/mathml-content+xml
# application/mathml-presentation+xml
application/mathml+xml mathml
# application/mbms-associated-procedure-description+xml
# application/mbms-deregister+xml
# application/mbms-envelope+xml
# application/mbms-msk+xml
# application/mbms-msk-response+xml
# application/mbms-protection-description+xml
# application/mbms-reception-report+xml
# application/mbms-register+xml
# application/mbms-register-response+xml
# application/mbms-user-service-description+xml
application/mbox mbox
# application/media_control+xml
application/mediaservercontrol+xml mscml
application/metalink+xml metalink
application/metalink4+xml meta4
application/mets+xml mets
# application/mikey
application/mods+xml mods
# application/moss-keys
# application/moss-signature
# application/mosskey-data
# application/mosskey-request
application/mp21 m21 mp21
application/mp4 mp4s
# application/mpeg4-generic
# application/mpeg4-iod
# application/mpeg4-iod-xmt
# application/msc-ivr+xml
# application/msc-mixer+xml
application/msword doc dot
application/mxf mxf
# application/nasdata
# application/news-checkgroups
# application/news-groupinfo
# application/news-transmission
# application/nss
# application/ocsp-request
# application/ocsp-response
application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy
application/oda oda
application/oebps-package+xml opf
application/ogg ogx
application/omdoc+xml omdoc
application/onenote onetoc onetoc2 onetmp onepkg
application/oxps oxps
# application/parityfec
application/patch-ops-error+xml xer
application/pdf pdf
application/pgp-encrypted pgp
# application/pgp-keys
application/pgp-signature asc sig
application/pics-rules prf
# application/pidf+xml
# application/pidf-diff+xml
application/pkcs10 p10
application/pkcs7-mime p7m p7c
application/pkcs7-signature p7s
application/pkcs8 p8
application/pkix-attr-cert ac
application/pkix-cert cer
application/pkix-crl crl
application/pkix-pkipath pkipath
application/pkixcmp pki
application/pls+xml pls
# application/poc-settings+xml
application/postscript ai eps ps
# application/prs.alvestrand.titrax-sheet
application/prs.cww cww
# application/prs.nprend
# application/prs.plucker
# application/prs.rdf-xml-crypt
# application/prs.xsf+xml
application/pskc+xml pskcxml
# application/qsig
application/rdf+xml rdf
application/reginfo+xml rif
application/relax-ng-compact-syntax rnc
# application/remote-printing
application/resource-lists+xml rl
application/resource-lists-diff+xml rld
# application/riscos
# application/rlmi+xml
application/rls-services+xml rs
application/rpki-ghostbusters gbr
application/rpki-manifest mft
application/rpki-roa roa
# application/rpki-updown
application/rsd+xml rsd
application/rss+xml rss
application/rtf rtf
# application/rtx
# application/samlassertion+xml
# application/samlmetadata+xml
application/sbml+xml sbml
application/scvp-cv-request scq
application/scvp-cv-response scs
application/scvp-vp-request spq
application/scvp-vp-response spp
application/sdp sdp
# application/set-payment
application/set-payment-initiation setpay
# application/set-registration
application/set-registration-initiation setreg
# application/sgml
# application/sgml-open-catalog
application/shf+xml shf
# application/sieve
# application/simple-filter+xml
# application/simple-message-summary
# application/simplesymbolcontainer
# application/slate
# application/smil
application/smil+xml smi smil
# application/soap+fastinfoset
# application/soap+xml
application/sparql-query rq
application/sparql-results+xml srx
# application/spirits-event+xml
application/srgs gram
application/srgs+xml grxml
application/sru+xml sru
application/ssdl+xml ssdl
application/ssml+xml ssml
# application/tamp-apex-update
# application/tamp-apex-update-confirm
# application/tamp-community-update
# application/tamp-community-update-confirm
# application/tamp-error
# application/tamp-sequence-adjust
# application/tamp-sequence-adjust-confirm
# application/tamp-status-query
# application/tamp-status-response
# application/tamp-update
# application/tamp-update-confirm
application/tei+xml tei teicorpus
application/thraud+xml tfi
# application/timestamp-query
# application/timestamp-reply
application/timestamped-data tsd
# application/tve-trigger
# application/ulpfec
# application/vcard+xml
# application/vemmi
# application/vividence.scriptfile
# application/vnd.3gpp.bsf+xml
application/vnd.3gpp.pic-bw-large plb
application/vnd.3gpp.pic-bw-small psb
application/vnd.3gpp.pic-bw-var pvb
# application/vnd.3gpp.sms
# application/vnd.3gpp2.bcmcsinfo+xml
# application/vnd.3gpp2.sms
application/vnd.3gpp2.tcap tcap
application/vnd.3m.post-it-notes pwn
application/vnd.accpac.simply.aso aso
application/vnd.accpac.simply.imp imp
application/vnd.acucobol acu
application/vnd.acucorp atc acutc
application/vnd.adobe.air-application-installer-package+zip air
application/vnd.adobe.formscentral.fcdt fcdt
application/vnd.adobe.fxp fxp fxpl
# application/vnd.adobe.partial-upload
application/vnd.adobe.xdp+xml xdp
application/vnd.adobe.xfdf xfdf
# application/vnd.aether.imp
# application/vnd.ah-barcode
application/vnd.ahead.space ahead
application/vnd.airzip.filesecure.azf azf
application/vnd.airzip.filesecure.azs azs
application/vnd.amazon.ebook azw
application/vnd.americandynamics.acc acc
application/vnd.amiga.ami ami
# application/vnd.amundsen.maze+xml
application/vnd.android.package-archive apk
application/vnd.anser-web-certificate-issue-initiation cii
application/vnd.anser-web-funds-transfer-initiation fti
application/vnd.antix.game-component atx
application/vnd.apple.installer+xml mpkg
application/vnd.apple.mpegurl m3u8
# application/vnd.arastra.swi
application/vnd.aristanetworks.swi swi
application/vnd.astraea-software.iota iota
application/vnd.audiograph aep
# application/vnd.autopackage
# application/vnd.avistar+xml
application/vnd.blueice.multipass mpm
# application/vnd.bluetooth.ep.oob
application/vnd.bmi bmi
application/vnd.businessobjects rep
# application/vnd.cab-jscript
# application/vnd.canon-cpdl
# application/vnd.canon-lips
# application/vnd.cendio.thinlinc.clientconf
application/vnd.chemdraw+xml cdxml
application/vnd.chipnuts.karaoke-mmd mmd
application/vnd.cinderella cdy
# application/vnd.cirpack.isdn-ext
application/vnd.claymore cla
application/vnd.cloanto.rp9 rp9
application/vnd.clonk.c4group c4g c4d c4f c4p c4u
application/vnd.cluetrust.cartomobile-config c11amc
application/vnd.cluetrust.cartomobile-config-pkg c11amz
# application/vnd.collection+json
# application/vnd.commerce-battelle
application/vnd.commonspace csp
application/vnd.contact.cmsg cdbcmsg
application/vnd.cosmocaller cmc
application/vnd.crick.clicker clkx
application/vnd.crick.clicker.keyboard clkk
application/vnd.crick.clicker.palette clkp
application/vnd.crick.clicker.template clkt
application/vnd.crick.clicker.wordbank clkw
application/vnd.criticaltools.wbs+xml wbs
application/vnd.ctc-posml pml
# application/vnd.ctct.ws+xml
# application/vnd.cups-pdf
# application/vnd.cups-postscript
application/vnd.cups-ppd ppd
# application/vnd.cups-raster
# application/vnd.cups-raw
# application/vnd.curl
application/vnd.curl.car car
application/vnd.curl.pcurl pcurl
# application/vnd.cybank
application/vnd.dart dart
application/vnd.data-vision.rdz rdz
application/vnd.dece.data uvf uvvf uvd uvvd
application/vnd.dece.ttml+xml uvt uvvt
application/vnd.dece.unspecified uvx uvvx
application/vnd.dece.zip uvz uvvz
application/vnd.denovo.fcselayout-link fe_launch
# application/vnd.dir-bi.plate-dl-nosuffix
application/vnd.dna dna
application/vnd.dolby.mlp mlp
# application/vnd.dolby.mobile.1
# application/vnd.dolby.mobile.2
application/vnd.dpgraph dpg
application/vnd.dreamfactory dfac
application/vnd.ds-keypoint kpxx
application/vnd.dvb.ait ait
# application/vnd.dvb.dvbj
# application/vnd.dvb.esgcontainer
# application/vnd.dvb.ipdcdftnotifaccess
# application/vnd.dvb.ipdcesgaccess
# application/vnd.dvb.ipdcesgaccess2
# application/vnd.dvb.ipdcesgpdd
# application/vnd.dvb.ipdcroaming
# application/vnd.dvb.iptv.alfec-base
# application/vnd.dvb.iptv.alfec-enhancement
# application/vnd.dvb.notif-aggregate-root+xml
# application/vnd.dvb.notif-container+xml
# application/vnd.dvb.notif-generic+xml
# application/vnd.dvb.notif-ia-msglist+xml
# application/vnd.dvb.notif-ia-registration-request+xml
# application/vnd.dvb.notif-ia-registration-response+xml
# application/vnd.dvb.notif-init+xml
# application/vnd.dvb.pfr
application/vnd.dvb.service svc
# application/vnd.dxr
application/vnd.dynageo geo
# application/vnd.easykaraoke.cdgdownload
# application/vnd.ecdis-update
application/vnd.ecowin.chart mag
# application/vnd.ecowin.filerequest
# application/vnd.ecowin.fileupdate
# application/vnd.ecowin.series
# application/vnd.ecowin.seriesrequest
# application/vnd.ecowin.seriesupdate
# application/vnd.emclient.accessrequest+xml
application/vnd.enliven nml
# application/vnd.eprints.data+xml
application/vnd.epson.esf esf
application/vnd.epson.msf msf
application/vnd.epson.quickanime qam
application/vnd.epson.salt slt
application/vnd.epson.ssf ssf
# application/vnd.ericsson.quickcall
application/vnd.eszigno3+xml es3 et3
# application/vnd.etsi.aoc+xml
# application/vnd.etsi.cug+xml
# application/vnd.etsi.iptvcommand+xml
# application/vnd.etsi.iptvdiscovery+xml
# application/vnd.etsi.iptvprofile+xml
# application/vnd.etsi.iptvsad-bc+xml
# application/vnd.etsi.iptvsad-cod+xml
# application/vnd.etsi.iptvsad-npvr+xml
# application/vnd.etsi.iptvservice+xml
# application/vnd.etsi.iptvsync+xml
# application/vnd.etsi.iptvueprofile+xml
# application/vnd.etsi.mcid+xml
# application/vnd.etsi.overload-control-policy-dataset+xml
# application/vnd.etsi.sci+xml
# application/vnd.etsi.simservs+xml
# application/vnd.etsi.tsl+xml
# application/vnd.etsi.tsl.der
# application/vnd.eudora.data
application/vnd.ezpix-album ez2
application/vnd.ezpix-package ez3
# application/vnd.f-secure.mobile
application/vnd.fdf fdf
application/vnd.fdsn.mseed mseed
application/vnd.fdsn.seed seed dataless
# application/vnd.ffsns
# application/vnd.fints
application/vnd.flographit gph
application/vnd.fluxtime.clip ftc
# application/vnd.font-fontforge-sfd
application/vnd.framemaker fm frame maker book
application/vnd.frogans.fnc fnc
application/vnd.frogans.ltf ltf
application/vnd.fsc.weblaunch fsc
application/vnd.fujitsu.oasys oas
application/vnd.fujitsu.oasys2 oa2
application/vnd.fujitsu.oasys3 oa3
application/vnd.fujitsu.oasysgp fg5
application/vnd.fujitsu.oasysprs bh2
# application/vnd.fujixerox.art-ex
# application/vnd.fujixerox.art4
# application/vnd.fujixerox.hbpl
application/vnd.fujixerox.ddd ddd
application/vnd.fujixerox.docuworks xdw
application/vnd.fujixerox.docuworks.binder xbd
# application/vnd.fut-misnet
application/vnd.fuzzysheet fzs
application/vnd.genomatix.tuxedo txd
# application/vnd.geocube+xml
application/vnd.geogebra.file ggb
application/vnd.geogebra.tool ggt
application/vnd.geometry-explorer gex gre
application/vnd.geonext gxt
application/vnd.geoplan g2w
application/vnd.geospace g3w
# application/vnd.globalplatform.card-content-mgt
# application/vnd.globalplatform.card-content-mgt-response
application/vnd.gmx gmx
application/vnd.google-earth.kml+xml kml
application/vnd.google-earth.kmz kmz
application/vnd.grafeq gqf gqs
# application/vnd.gridmp
application/vnd.groove-account gac
application/vnd.groove-help ghf
application/vnd.groove-identity-message gim
application/vnd.groove-injector grv
application/vnd.groove-tool-message gtm
application/vnd.groove-tool-template tpl
application/vnd.groove-vcard vcg
# application/vnd.hal+json
application/vnd.hal+xml hal
application/vnd.handheld-entertainment+xml zmm
application/vnd.hbci hbci
# application/vnd.hcl-bireports
application/vnd.hhe.lesson-player les
application/vnd.hp-hpgl hpgl
application/vnd.hp-hpid hpid
application/vnd.hp-hps hps
application/vnd.hp-jlyt jlt
application/vnd.hp-pcl pcl
application/vnd.hp-pclxl pclxl
# application/vnd.httphone
application/vnd.hydrostatix.sof-data sfd-hdstx
# application/vnd.hzn-3d-crossword
# application/vnd.ibm.afplinedata
# application/vnd.ibm.electronic-media
application/vnd.ibm.minipay mpy
application/vnd.ibm.modcap afp listafp list3820
application/vnd.ibm.rights-management irm
application/vnd.ibm.secure-container sc
application/vnd.iccprofile icc icm
application/vnd.igloader igl
application/vnd.immervision-ivp ivp
application/vnd.immervision-ivu ivu
# application/vnd.informedcontrol.rms+xml
# application/vnd.informix-visionary
# application/vnd.infotech.project
# application/vnd.infotech.project+xml
# application/vnd.innopath.wamp.notification
application/vnd.insors.igm igm
application/vnd.intercon.formnet xpw xpx
application/vnd.intergeo i2g
# application/vnd.intertrust.digibox
# application/vnd.intertrust.nncp
application/vnd.intu.qbo qbo
application/vnd.intu.qfx qfx
# application/vnd.iptc.g2.conceptitem+xml
# application/vnd.iptc.g2.knowledgeitem+xml
# application/vnd.iptc.g2.newsitem+xml
# application/vnd.iptc.g2.newsmessage+xml
# application/vnd.iptc.g2.packageitem+xml
# application/vnd.iptc.g2.planningitem+xml
application/vnd.ipunplugged.rcprofile rcprofile
application/vnd.irepository.package+xml irp
application/vnd.is-xpr xpr
application/vnd.isac.fcs fcs
application/vnd.jam jam
# application/vnd.japannet-directory-service
# application/vnd.japannet-jpnstore-wakeup
# application/vnd.japannet-payment-wakeup
# application/vnd.japannet-registration
# application/vnd.japannet-registration-wakeup
# application/vnd.japannet-setstore-wakeup
# application/vnd.japannet-verification
# application/vnd.japannet-verification-wakeup
application/vnd.jcp.javame.midlet-rms rms
application/vnd.jisp jisp
application/vnd.joost.joda-archive joda
application/vnd.kahootz ktz ktr
application/vnd.kde.karbon karbon
application/vnd.kde.kchart chrt
application/vnd.kde.kformula kfo
application/vnd.kde.kivio flw
application/vnd.kde.kontour kon
application/vnd.kde.kpresenter kpr kpt
application/vnd.kde.kspread ksp
application/vnd.kde.kword kwd kwt
application/vnd.kenameaapp htke
application/vnd.kidspiration kia
application/vnd.kinar kne knp
application/vnd.koan skp skd skt skm
application/vnd.kodak-descriptor sse
application/vnd.las.las+xml lasxml
# application/vnd.liberty-request+xml
application/vnd.llamagraphics.life-balance.desktop lbd
application/vnd.llamagraphics.life-balance.exchange+xml lbe
application/vnd.lotus-1-2-3 123
application/vnd.lotus-approach apr
application/vnd.lotus-freelance pre
application/vnd.lotus-notes nsf
application/vnd.lotus-organizer org
application/vnd.lotus-screencam scm
application/vnd.lotus-wordpro lwp
application/vnd.macports.portpkg portpkg
# application/vnd.marlin.drm.actiontoken+xml
# application/vnd.marlin.drm.conftoken+xml
# application/vnd.marlin.drm.license+xml
# application/vnd.marlin.drm.mdcf
application/vnd.mcd mcd
application/vnd.medcalcdata mc1
application/vnd.mediastation.cdkey cdkey
# application/vnd.meridian-slingshot
application/vnd.mfer mwf
application/vnd.mfmp mfm
application/vnd.micrografx.flo flo
application/vnd.micrografx.igx igx
application/vnd.mif mif
# application/vnd.minisoft-hp3000-save
# application/vnd.mitsubishi.misty-guard.trustweb
application/vnd.mobius.daf daf
application/vnd.mobius.dis dis
application/vnd.mobius.mbk mbk
application/vnd.mobius.mqy mqy
application/vnd.mobius.msl msl
application/vnd.mobius.plc plc
application/vnd.mobius.txf txf
application/vnd.mophun.application mpn
application/vnd.mophun.certificate mpc
# application/vnd.motorola.flexsuite
# application/vnd.motorola.flexsuite.adsi
# application/vnd.motorola.flexsuite.fis
# application/vnd.motorola.flexsuite.gotap
# application/vnd.motorola.flexsuite.kmr
# application/vnd.motorola.flexsuite.ttc
# application/vnd.motorola.flexsuite.wem
# application/vnd.motorola.iprm
application/vnd.mozilla.xul+xml xul
application/vnd.ms-artgalry cil
# application/vnd.ms-asf
application/vnd.ms-cab-compressed cab
# application/vnd.ms-color.iccprofile
application/vnd.ms-excel xls xlm xla xlc xlt xlw
application/vnd.ms-excel.addin.macroenabled.12 xlam
application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb
application/vnd.ms-excel.sheet.macroenabled.12 xlsm
application/vnd.ms-excel.template.macroenabled.12 xltm
application/vnd.ms-fontobject eot
application/vnd.ms-htmlhelp chm
application/vnd.ms-ims ims
application/vnd.ms-lrm lrm
# application/vnd.ms-office.activex+xml
application/vnd.ms-officetheme thmx
# application/vnd.ms-opentype
# application/vnd.ms-package.obfuscated-opentype
application/vnd.ms-pki.seccat cat
application/vnd.ms-pki.stl stl
# application/vnd.ms-playready.initiator+xml
application/vnd.ms-powerpoint ppt pps pot
application/vnd.ms-powerpoint.addin.macroenabled.12 ppam
application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm
application/vnd.ms-powerpoint.slide.macroenabled.12 sldm
application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm
application/vnd.ms-powerpoint.template.macroenabled.12 potm
# application/vnd.ms-printing.printticket+xml
application/vnd.ms-project mpp mpt
# application/vnd.ms-tnef
# application/vnd.ms-wmdrm.lic-chlg-req
# application/vnd.ms-wmdrm.lic-resp
# application/vnd.ms-wmdrm.meter-chlg-req
# application/vnd.ms-wmdrm.meter-resp
application/vnd.ms-word.document.macroenabled.12 docm
application/vnd.ms-word.template.macroenabled.12 dotm
application/vnd.ms-works wps wks wcm wdb
application/vnd.ms-wpl wpl
application/vnd.ms-xpsdocument xps
application/vnd.mseq mseq
# application/vnd.msign
# application/vnd.multiad.creator
# application/vnd.multiad.creator.cif
# application/vnd.music-niff
application/vnd.musician mus
application/vnd.muvee.style msty
application/vnd.mynfc taglet
# application/vnd.ncd.control
# application/vnd.ncd.reference
# application/vnd.nervana
# application/vnd.netfpx
application/vnd.neurolanguage.nlu nlu
application/vnd.nitf ntf nitf
application/vnd.noblenet-directory nnd
application/vnd.noblenet-sealer nns
application/vnd.noblenet-web nnw
# application/vnd.nokia.catalogs
# application/vnd.nokia.conml+wbxml
# application/vnd.nokia.conml+xml
# application/vnd.nokia.isds-radio-presets
# application/vnd.nokia.iptv.config+xml
# application/vnd.nokia.landmark+wbxml
# application/vnd.nokia.landmark+xml
# application/vnd.nokia.landmarkcollection+xml
# application/vnd.nokia.n-gage.ac+xml
application/vnd.nokia.n-gage.data ngdat
application/vnd.nokia.n-gage.symbian.install n-gage
# application/vnd.nokia.ncd
# application/vnd.nokia.pcd+wbxml
# application/vnd.nokia.pcd+xml
application/vnd.nokia.radio-preset rpst
application/vnd.nokia.radio-presets rpss
application/vnd.novadigm.edm edm
application/vnd.novadigm.edx edx
application/vnd.novadigm.ext ext
# application/vnd.ntt-local.file-transfer
# application/vnd.ntt-local.sip-ta_remote
# application/vnd.ntt-local.sip-ta_tcp_stream
application/vnd.oasis.opendocument.chart odc
application/vnd.oasis.opendocument.chart-template otc
application/vnd.oasis.opendocument.database odb
application/vnd.oasis.opendocument.formula odf
application/vnd.oasis.opendocument.formula-template odft
application/vnd.oasis.opendocument.graphics odg
application/vnd.oasis.opendocument.graphics-template otg
application/vnd.oasis.opendocument.image odi
application/vnd.oasis.opendocument.image-template oti
application/vnd.oasis.opendocument.presentation odp
application/vnd.oasis.opendocument.presentation-template otp
application/vnd.oasis.opendocument.spreadsheet ods
application/vnd.oasis.opendocument.spreadsheet-template ots
application/vnd.oasis.opendocument.text odt
application/vnd.oasis.opendocument.text-master odm
application/vnd.oasis.opendocument.text-template ott
application/vnd.oasis.opendocument.text-web oth
# application/vnd.obn
# application/vnd.oftn.l10n+json
# application/vnd.oipf.contentaccessdownload+xml
# application/vnd.oipf.contentaccessstreaming+xml
# application/vnd.oipf.cspg-hexbinary
# application/vnd.oipf.dae.svg+xml
# application/vnd.oipf.dae.xhtml+xml
# application/vnd.oipf.mippvcontrolmessage+xml
# application/vnd.oipf.pae.gem
# application/vnd.oipf.spdiscovery+xml
# application/vnd.oipf.spdlist+xml
# application/vnd.oipf.ueprofile+xml
# application/vnd.oipf.userprofile+xml
application/vnd.olpc-sugar xo
# application/vnd.oma-scws-config
# application/vnd.oma-scws-http-request
# application/vnd.oma-scws-http-response
# application/vnd.oma.bcast.associated-procedure-parameter+xml
# application/vnd.oma.bcast.drm-trigger+xml
# application/vnd.oma.bcast.imd+xml
# application/vnd.oma.bcast.ltkm
# application/vnd.oma.bcast.notification+xml
# application/vnd.oma.bcast.provisioningtrigger
# application/vnd.oma.bcast.sgboot
# application/vnd.oma.bcast.sgdd+xml
# application/vnd.oma.bcast.sgdu
# application/vnd.oma.bcast.simple-symbol-container
# application/vnd.oma.bcast.smartcard-trigger+xml
# application/vnd.oma.bcast.sprov+xml
# application/vnd.oma.bcast.stkm
# application/vnd.oma.cab-address-book+xml
# application/vnd.oma.cab-feature-handler+xml
# application/vnd.oma.cab-pcc+xml
# application/vnd.oma.cab-user-prefs+xml
# application/vnd.oma.dcd
# application/vnd.oma.dcdc
application/vnd.oma.dd2+xml dd2
# application/vnd.oma.drm.risd+xml
# application/vnd.oma.group-usage-list+xml
# application/vnd.oma.pal+xml
# application/vnd.oma.poc.detailed-progress-report+xml
# application/vnd.oma.poc.final-report+xml
# application/vnd.oma.poc.groups+xml
# application/vnd.oma.poc.invocation-descriptor+xml
# application/vnd.oma.poc.optimized-progress-report+xml
# application/vnd.oma.push
# application/vnd.oma.scidm.messages+xml
# application/vnd.oma.xcap-directory+xml
# application/vnd.omads-email+xml
# application/vnd.omads-file+xml
# application/vnd.omads-folder+xml
# application/vnd.omaloc-supl-init
application/vnd.openofficeorg.extension oxt
# application/vnd.openxmlformats-officedocument.custom-properties+xml
# application/vnd.openxmlformats-officedocument.customxmlproperties+xml
# application/vnd.openxmlformats-officedocument.drawing+xml
# application/vnd.openxmlformats-officedocument.drawingml.chart+xml
# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml
# application/vnd.openxmlformats-officedocument.extended-properties+xml
# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml
# application/vnd.openxmlformats-officedocument.presentationml.comments+xml
# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml
# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml
# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml
application/vnd.openxmlformats-officedocument.presentationml.presentation pptx
# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml
# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml
application/vnd.openxmlformats-officedocument.presentationml.slide sldx
# application/vnd.openxmlformats-officedocument.presentationml.slide+xml
# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml
# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml
application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx
# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml
# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml
# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml
# application/vnd.openxmlformats-officedocument.presentationml.tags+xml
application/vnd.openxmlformats-officedocument.presentationml.template potx
# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml
# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx
# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml
application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx
# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml
# application/vnd.openxmlformats-officedocument.theme+xml
# application/vnd.openxmlformats-officedocument.themeoverride+xml
# application/vnd.openxmlformats-officedocument.vmldrawing
# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml
application/vnd.openxmlformats-officedocument.wordprocessingml.document docx
# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml
application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx
# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml
# application/vnd.openxmlformats-package.core-properties+xml
# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml
# application/vnd.openxmlformats-package.relationships+xml
# application/vnd.quobject-quoxdocument
# application/vnd.osa.netdeploy
application/vnd.osgeo.mapguide.package mgp
# application/vnd.osgi.bundle
application/vnd.osgi.dp dp
application/vnd.osgi.subsystem esa
# application/vnd.otps.ct-kip+xml
application/vnd.palm pdb pqa oprc
# application/vnd.paos.xml
application/vnd.pawaafile paw
application/vnd.pg.format str
application/vnd.pg.osasli ei6
# application/vnd.piaccess.application-licence
application/vnd.picsel efif
application/vnd.pmi.widget wg
# application/vnd.poc.group-advertisement+xml
application/vnd.pocketlearn plf
application/vnd.powerbuilder6 pbd
# application/vnd.powerbuilder6-s
# application/vnd.powerbuilder7
# application/vnd.powerbuilder7-s
# application/vnd.powerbuilder75
# application/vnd.powerbuilder75-s
# application/vnd.preminet
application/vnd.previewsystems.box box
application/vnd.proteus.magazine mgz
application/vnd.publishare-delta-tree qps
application/vnd.pvi.ptid1 ptid
# application/vnd.pwg-multiplexed
# application/vnd.pwg-xhtml-print+xml
# application/vnd.qualcomm.brew-app-res
application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb
# application/vnd.radisys.moml+xml
# application/vnd.radisys.msml+xml
# application/vnd.radisys.msml-audit+xml
# application/vnd.radisys.msml-audit-conf+xml
# application/vnd.radisys.msml-audit-conn+xml
# application/vnd.radisys.msml-audit-dialog+xml
# application/vnd.radisys.msml-audit-stream+xml
# application/vnd.radisys.msml-conf+xml
# application/vnd.radisys.msml-dialog+xml
# application/vnd.radisys.msml-dialog-base+xml
# application/vnd.radisys.msml-dialog-fax-detect+xml
# application/vnd.radisys.msml-dialog-fax-sendrecv+xml
# application/vnd.radisys.msml-dialog-group+xml
# application/vnd.radisys.msml-dialog-speech+xml
# application/vnd.radisys.msml-dialog-transform+xml
# application/vnd.rainstor.data
# application/vnd.rapid
application/vnd.realvnc.bed bed
application/vnd.recordare.musicxml mxl
application/vnd.recordare.musicxml+xml musicxml
# application/vnd.renlearn.rlprint
application/vnd.rig.cryptonote cryptonote
application/vnd.rim.cod cod
application/vnd.rn-realmedia rm
application/vnd.rn-realmedia-vbr rmvb
application/vnd.route66.link66+xml link66
# application/vnd.rs-274x
# application/vnd.ruckus.download
# application/vnd.s3sms
application/vnd.sailingtracker.track st
# application/vnd.sbm.cid
# application/vnd.sbm.mid2
# application/vnd.scribus
# application/vnd.sealed.3df
# application/vnd.sealed.csf
# application/vnd.sealed.doc
# application/vnd.sealed.eml
# application/vnd.sealed.mht
# application/vnd.sealed.net
# application/vnd.sealed.ppt
# application/vnd.sealed.tiff
# application/vnd.sealed.xls
# application/vnd.sealedmedia.softseal.html
# application/vnd.sealedmedia.softseal.pdf
application/vnd.seemail see
application/vnd.sema sema
application/vnd.semd semd
application/vnd.semf semf
application/vnd.shana.informed.formdata ifm
application/vnd.shana.informed.formtemplate itp
application/vnd.shana.informed.interchange iif
application/vnd.shana.informed.package ipk
application/vnd.simtech-mindmapper twd twds
application/vnd.smaf mmf
# application/vnd.smart.notebook
application/vnd.smart.teacher teacher
# application/vnd.software602.filler.form+xml
# application/vnd.software602.filler.form-xml-zip
application/vnd.solent.sdkm+xml sdkm sdkd
application/vnd.spotfire.dxp dxp
application/vnd.spotfire.sfs sfs
# application/vnd.sss-cod
# application/vnd.sss-dtf
# application/vnd.sss-ntf
application/vnd.stardivision.calc sdc
application/vnd.stardivision.draw sda
application/vnd.stardivision.impress sdd
application/vnd.stardivision.math smf
application/vnd.stardivision.writer sdw vor
application/vnd.stardivision.writer-global sgl
application/vnd.stepmania.package smzip
application/vnd.stepmania.stepchart sm
# application/vnd.street-stream
application/vnd.sun.xml.calc sxc
application/vnd.sun.xml.calc.template stc
application/vnd.sun.xml.draw sxd
application/vnd.sun.xml.draw.template std
application/vnd.sun.xml.impress sxi
application/vnd.sun.xml.impress.template sti
application/vnd.sun.xml.math sxm
application/vnd.sun.xml.writer sxw
application/vnd.sun.xml.writer.global sxg
application/vnd.sun.xml.writer.template stw
# application/vnd.sun.wadl+xml
application/vnd.sus-calendar sus susp
application/vnd.svd svd
# application/vnd.swiftview-ics
application/vnd.symbian.install sis sisx
application/vnd.syncml+xml xsm
application/vnd.syncml.dm+wbxml bdm
application/vnd.syncml.dm+xml xdm
# application/vnd.syncml.dm.notification
# application/vnd.syncml.ds.notification
application/vnd.tao.intent-module-archive tao
application/vnd.tcpdump.pcap pcap cap dmp
application/vnd.tmobile-livetv tmo
application/vnd.trid.tpt tpt
application/vnd.triscape.mxs mxs
application/vnd.trueapp tra
# application/vnd.truedoc
# application/vnd.ubisoft.webplayer
application/vnd.ufdl ufd ufdl
application/vnd.uiq.theme utz
application/vnd.umajin umj
application/vnd.unity unityweb
application/vnd.uoml+xml uoml
# application/vnd.uplanet.alert
# application/vnd.uplanet.alert-wbxml
# application/vnd.uplanet.bearer-choice
# application/vnd.uplanet.bearer-choice-wbxml
# application/vnd.uplanet.cacheop
# application/vnd.uplanet.cacheop-wbxml
# application/vnd.uplanet.channel
# application/vnd.uplanet.channel-wbxml
# application/vnd.uplanet.list
# application/vnd.uplanet.list-wbxml
# application/vnd.uplanet.listcmd
# application/vnd.uplanet.listcmd-wbxml
# application/vnd.uplanet.signal
application/vnd.vcx vcx
# application/vnd.vd-study
# application/vnd.vectorworks
# application/vnd.verimatrix.vcas
# application/vnd.vidsoft.vidconference
application/vnd.visio vsd vst vss vsw
application/vnd.visionary vis
# application/vnd.vividence.scriptfile
application/vnd.vsf vsf
# application/vnd.wap.sic
# application/vnd.wap.slc
application/vnd.wap.wbxml wbxml
application/vnd.wap.wmlc wmlc
application/vnd.wap.wmlscriptc wmlsc
application/vnd.webturbo wtb
# application/vnd.wfa.wsc
# application/vnd.wmc
# application/vnd.wmf.bootstrap
# application/vnd.wolfram.mathematica
# application/vnd.wolfram.mathematica.package
application/vnd.wolfram.player nbp
application/vnd.wordperfect wpd
application/vnd.wqd wqd
# application/vnd.wrq-hp3000-labelled
application/vnd.wt.stf stf
# application/vnd.wv.csp+wbxml
# application/vnd.wv.csp+xml
# application/vnd.wv.ssp+xml
application/vnd.xara xar
application/vnd.xfdl xfdl
# application/vnd.xfdl.webform
# application/vnd.xmi+xml
# application/vnd.xmpie.cpkg
# application/vnd.xmpie.dpkg
# application/vnd.xmpie.plan
# application/vnd.xmpie.ppkg
# application/vnd.xmpie.xlim
application/vnd.yamaha.hv-dic hvd
application/vnd.yamaha.hv-script hvs
application/vnd.yamaha.hv-voice hvp
application/vnd.yamaha.openscoreformat osf
application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg
# application/vnd.yamaha.remote-setup
application/vnd.yamaha.smaf-audio saf
application/vnd.yamaha.smaf-phrase spf
# application/vnd.yamaha.through-ngn
# application/vnd.yamaha.tunnel-udpencap
application/vnd.yellowriver-custom-menu cmp
application/vnd.zul zir zirz
application/vnd.zzazz.deck+xml zaz
application/voicexml+xml vxml
# application/vq-rtcpxr
# application/watcherinfo+xml
# application/whoispp-query
# application/whoispp-response
application/widget wgt
application/winhlp hlp
# application/wita
# application/wordperfect5.1
application/wsdl+xml wsdl
application/wspolicy+xml wspolicy
application/x-7z-compressed 7z
application/x-abiword abw
application/x-ace-compressed ace
# application/x-amf
application/x-apple-diskimage dmg
application/x-authorware-bin aab x32 u32 vox
application/x-authorware-map aam
application/x-authorware-seg aas
application/x-bcpio bcpio
application/x-bittorrent torrent
application/x-blorb blb blorb
application/x-bzip bz
application/x-bzip2 bz2 boz
application/x-cbr cbr cba cbt cbz cb7
application/x-cdlink vcd
application/x-cfs-compressed cfs
application/x-chat chat
application/x-chess-pgn pgn
application/x-conference nsc
# application/x-compress
application/x-cpio cpio
application/x-csh csh
application/x-debian-package deb udeb
application/x-dgc-compressed dgc
application/x-director dir dcr dxr cst cct cxt w3d fgd swa
application/x-doom wad
application/x-dtbncx+xml ncx
application/x-dtbook+xml dtb
application/x-dtbresource+xml res
application/x-dvi dvi
application/x-envoy evy
application/x-eva eva
application/x-font-bdf bdf
# application/x-font-dos
# application/x-font-framemaker
application/x-font-ghostscript gsf
# application/x-font-libgrx
application/x-font-linux-psf psf
application/x-font-otf otf
application/x-font-pcf pcf
application/x-font-snf snf
# application/x-font-speedo
# application/x-font-sunos-news
application/x-font-ttf ttf ttc
application/x-font-type1 pfa pfb pfm afm
application/font-woff woff
# application/x-font-vfont
application/x-freearc arc
application/x-futuresplash spl
application/x-gca-compressed gca
application/x-glulx ulx
application/x-gnumeric gnumeric
application/x-gramps-xml gramps
application/x-gtar gtar
# application/x-gzip
application/x-hdf hdf
application/x-install-instructions install
application/x-iso9660-image iso
application/x-java-jnlp-file jnlp
application/x-latex latex
application/x-lzh-compressed lzh lha
application/x-mie mie
application/x-mobipocket-ebook prc mobi
application/x-ms-application application
application/x-ms-shortcut lnk
application/x-ms-wmd wmd
application/x-ms-wmz wmz
application/x-ms-xbap xbap
application/x-msaccess mdb
application/x-msbinder obd
application/x-mscardfile crd
application/x-msclip clp
application/x-msdownload exe dll com bat msi
application/x-msmediaview mvb m13 m14
application/x-msmetafile wmf wmz emf emz
application/x-msmoney mny
application/x-mspublisher pub
application/x-msschedule scd
application/x-msterminal trm
application/x-mswrite wri
application/x-netcdf nc cdf
application/x-nzb nzb
application/x-pkcs12 p12 pfx
application/x-pkcs7-certificates p7b spc
application/x-pkcs7-certreqresp p7r
application/x-rar-compressed rar
application/x-research-info-systems ris
application/x-sh sh
application/x-shar shar
application/x-shockwave-flash swf
application/x-silverlight-app xap
application/x-sql sql
application/x-stuffit sit
application/x-stuffitx sitx
application/x-subrip srt
application/x-sv4cpio sv4cpio
application/x-sv4crc sv4crc
application/x-t3vm-image t3
application/x-tads gam
application/x-tar tar
application/x-tcl tcl
application/x-tex tex
application/x-tex-tfm tfm
application/x-texinfo texinfo texi
application/x-tgif obj
application/x-ustar ustar
application/x-wais-source src
application/x-x509-ca-cert der crt
application/x-xfig fig
application/x-xliff+xml xlf
application/x-xpinstall xpi
application/x-xz xz
application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8
# application/x400-bp
application/xaml+xml xaml
# application/xcap-att+xml
# application/xcap-caps+xml
application/xcap-diff+xml xdf
# application/xcap-el+xml
# application/xcap-error+xml
# application/xcap-ns+xml
# application/xcon-conference-info-diff+xml
# application/xcon-conference-info+xml
application/xenc+xml xenc
application/xhtml+xml xhtml xht
# application/xhtml-voice+xml
application/xml xml xsl
application/xml-dtd dtd
# application/xml-external-parsed-entity
# application/xmpp+xml
application/xop+xml xop
application/xproc+xml xpl
application/xslt+xml xslt
application/xspf+xml xspf
application/xv+xml mxml xhvml xvml xvm
application/yang yang
application/yin+xml yin
application/zip zip
# audio/1d-interleaved-parityfec
# audio/32kadpcm
# audio/3gpp
# audio/3gpp2
# audio/ac3
audio/adpcm adp
# audio/amr
# audio/amr-wb
# audio/amr-wb+
# audio/asc
# audio/atrac-advanced-lossless
# audio/atrac-x
# audio/atrac3
audio/basic au snd
# audio/bv16
# audio/bv32
# audio/clearmode
# audio/cn
# audio/dat12
# audio/dls
# audio/dsr-es201108
# audio/dsr-es202050
# audio/dsr-es202211
# audio/dsr-es202212
# audio/dv
# audio/dvi4
# audio/eac3
# audio/evrc
# audio/evrc-qcp
# audio/evrc0
# audio/evrc1
# audio/evrcb
# audio/evrcb0
# audio/evrcb1
# audio/evrcwb
# audio/evrcwb0
# audio/evrcwb1
# audio/example
# audio/fwdred
# audio/g719
# audio/g722
# audio/g7221
# audio/g723
# audio/g726-16
# audio/g726-24
# audio/g726-32
# audio/g726-40
# audio/g728
# audio/g729
# audio/g7291
# audio/g729d
# audio/g729e
# audio/gsm
# audio/gsm-efr
# audio/gsm-hr-08
# audio/ilbc
# audio/ip-mr_v2.5
# audio/isac
# audio/l16
# audio/l20
# audio/l24
# audio/l8
# audio/lpc
audio/midi mid midi kar rmi
# audio/mobile-xmf
audio/mp4 mp4a
# audio/mp4a-latm
# audio/mpa
# audio/mpa-robust
audio/mpeg mpga mp2 mp2a mp3 m2a m3a
# audio/mpeg4-generic
# audio/musepack
audio/ogg oga ogg spx
# audio/opus
# audio/parityfec
# audio/pcma
# audio/pcma-wb
# audio/pcmu-wb
# audio/pcmu
# audio/prs.sid
# audio/qcelp
# audio/red
# audio/rtp-enc-aescm128
# audio/rtp-midi
# audio/rtx
audio/s3m s3m
audio/silk sil
# audio/smv
# audio/smv0
# audio/smv-qcp
# audio/sp-midi
# audio/speex
# audio/t140c
# audio/t38
# audio/telephone-event
# audio/tone
# audio/uemclip
# audio/ulpfec
# audio/vdvi
# audio/vmr-wb
# audio/vnd.3gpp.iufp
# audio/vnd.4sb
# audio/vnd.audiokoz
# audio/vnd.celp
# audio/vnd.cisco.nse
# audio/vnd.cmles.radio-events
# audio/vnd.cns.anp1
# audio/vnd.cns.inf1
audio/vnd.dece.audio uva uvva
audio/vnd.digital-winds eol
# audio/vnd.dlna.adts
# audio/vnd.dolby.heaac.1
# audio/vnd.dolby.heaac.2
# audio/vnd.dolby.mlp
# audio/vnd.dolby.mps
# audio/vnd.dolby.pl2
# audio/vnd.dolby.pl2x
# audio/vnd.dolby.pl2z
# audio/vnd.dolby.pulse.1
audio/vnd.dra dra
audio/vnd.dts dts
audio/vnd.dts.hd dtshd
# audio/vnd.dvb.file
# audio/vnd.everad.plj
# audio/vnd.hns.audio
audio/vnd.lucent.voice lvp
audio/vnd.ms-playready.media.pya pya
# audio/vnd.nokia.mobile-xmf
# audio/vnd.nortel.vbk
audio/vnd.nuera.ecelp4800 ecelp4800
audio/vnd.nuera.ecelp7470 ecelp7470
audio/vnd.nuera.ecelp9600 ecelp9600
# audio/vnd.octel.sbc
# audio/vnd.qcelp
# audio/vnd.rhetorex.32kadpcm
audio/vnd.rip rip
# audio/vnd.sealedmedia.softseal.mpeg
# audio/vnd.vmx.cvsd
# audio/vorbis
# audio/vorbis-config
audio/webm weba
audio/x-aac aac
audio/x-aiff aif aiff aifc
audio/x-caf caf
audio/x-flac flac
audio/x-matroska mka
audio/x-mpegurl m3u
audio/x-ms-wax wax
audio/x-ms-wma wma
audio/x-pn-realaudio ram ra
audio/x-pn-realaudio-plugin rmp
# audio/x-tta
audio/x-wav wav
audio/xm xm
chemical/x-cdx cdx
chemical/x-cif cif
chemical/x-cmdf cmdf
chemical/x-cml cml
chemical/x-csml csml
# chemical/x-pdb
chemical/x-xyz xyz
image/bmp bmp
image/cgm cgm
# image/example
# image/fits
image/g3fax g3
image/gif gif
image/ief ief
# image/jp2
image/jpeg jpeg jpg jpe
# image/jpm
# image/jpx
image/ktx ktx
# image/naplps
image/png png
image/prs.btif btif
# image/prs.pti
image/sgi sgi
image/svg+xml svg svgz
# image/t38
image/tiff tiff tif
# image/tiff-fx
image/vnd.adobe.photoshop psd
# image/vnd.cns.inf2
image/vnd.dece.graphic uvi uvvi uvg uvvg
image/vnd.dvb.subtitle sub
image/vnd.djvu djvu djv
image/vnd.dwg dwg
image/vnd.dxf dxf
image/vnd.fastbidsheet fbs
image/vnd.fpx fpx
image/vnd.fst fst
image/vnd.fujixerox.edmics-mmr mmr
image/vnd.fujixerox.edmics-rlc rlc
# image/vnd.globalgraphics.pgb
# image/vnd.microsoft.icon
# image/vnd.mix
image/vnd.ms-modi mdi
image/vnd.ms-photo wdp
image/vnd.net-fpx npx
# image/vnd.radiance
# image/vnd.sealed.png
# image/vnd.sealedmedia.softseal.gif
# image/vnd.sealedmedia.softseal.jpg
# image/vnd.svf
image/vnd.wap.wbmp wbmp
image/vnd.xiff xif
image/webp webp
image/x-3ds 3ds
image/x-cmu-raster ras
image/x-cmx cmx
image/x-freehand fh fhc fh4 fh5 fh7
image/x-icon ico
image/x-mrsid-image sid
image/x-pcx pcx
image/x-pict pic pct
image/x-portable-anymap pnm
image/x-portable-bitmap pbm
image/x-portable-graymap pgm
image/x-portable-pixmap ppm
image/x-rgb rgb
image/x-tga tga
image/x-xbitmap xbm
image/x-xpixmap xpm
image/x-xwindowdump xwd
# message/cpim
# message/delivery-status
# message/disposition-notification
# message/example
# message/external-body
# message/feedback-report
# message/global
# message/global-delivery-status
# message/global-disposition-notification
# message/global-headers
# message/http
# message/imdn+xml
# message/news
# message/partial
message/rfc822 eml mime
# message/s-http
# message/sip
# message/sipfrag
# message/tracking-status
# message/vnd.si.simp
# model/example
model/iges igs iges
model/mesh msh mesh silo
model/vnd.collada+xml dae
model/vnd.dwf dwf
# model/vnd.flatland.3dml
model/vnd.gdl gdl
# model/vnd.gs-gdl
# model/vnd.gs.gdl
model/vnd.gtw gtw
# model/vnd.moml+xml
model/vnd.mts mts
# model/vnd.parasolid.transmit.binary
# model/vnd.parasolid.transmit.text
model/vnd.vtu vtu
model/vrml wrl vrml
model/x3d+binary x3db x3dbz
model/x3d+vrml x3dv x3dvz
model/x3d+xml x3d x3dz
# multipart/alternative
# multipart/appledouble
# multipart/byteranges
# multipart/digest
# multipart/encrypted
# multipart/example
# multipart/form-data
# multipart/header-set
# multipart/mixed
# multipart/parallel
# multipart/related
# multipart/report
# multipart/signed
# multipart/voice-message
# text/1d-interleaved-parityfec
text/cache-manifest appcache
text/calendar ics ifb
text/css css
text/csv csv
# text/directory
# text/dns
# text/ecmascript
# text/enriched
# text/example
# text/fwdred
text/html html htm
# text/javascript
text/n3 n3
# text/parityfec
text/plain txt text conf def list log in
# text/prs.fallenstein.rst
text/prs.lines.tag dsc
# text/vnd.radisys.msml-basic-layout
# text/red
# text/rfc822-headers
text/richtext rtx
# text/rtf
# text/rtp-enc-aescm128
# text/rtx
text/sgml sgml sgm
# text/t140
text/tab-separated-values tsv
text/troff t tr roff man me ms
text/turtle ttl
# text/ulpfec
text/uri-list uri uris urls
text/vcard vcard
# text/vnd.abc
text/vnd.curl curl
text/vnd.curl.dcurl dcurl
text/vnd.curl.scurl scurl
text/vnd.curl.mcurl mcurl
# text/vnd.dmclientscript
text/vnd.dvb.subtitle sub
# text/vnd.esmertec.theme-descriptor
text/vnd.fly fly
text/vnd.fmi.flexstor flx
text/vnd.graphviz gv
text/vnd.in3d.3dml 3dml
text/vnd.in3d.spot spot
# text/vnd.iptc.newsml
# text/vnd.iptc.nitf
# text/vnd.latex-z
# text/vnd.motorola.reflex
# text/vnd.ms-mediapackage
# text/vnd.net2phone.commcenter.command
# text/vnd.si.uricatalogue
text/vnd.sun.j2me.app-descriptor jad
# text/vnd.trolltech.linguist
# text/vnd.wap.si
# text/vnd.wap.sl
text/vnd.wap.wml wml
text/vnd.wap.wmlscript wmls
text/x-asm s asm
text/x-c c cc cxx cpp h hh dic
text/x-fortran f for f77 f90
text/x-java-source java
text/x-opml opml
text/x-pascal p pas
text/x-nfo nfo
text/x-setext etx
text/x-sfv sfv
text/x-uuencode uu
text/x-vcalendar vcs
text/x-vcard vcf
# text/xml
# text/xml-external-parsed-entity
# video/1d-interleaved-parityfec
video/3gpp 3gp
# video/3gpp-tt
video/3gpp2 3g2
# video/bmpeg
# video/bt656
# video/celb
# video/dv
# video/example
video/h261 h261
video/h263 h263
# video/h263-1998
# video/h263-2000
video/h264 h264
# video/h264-rcdo
# video/h264-svc
video/jpeg jpgv
# video/jpeg2000
video/jpm jpm jpgm
video/mj2 mj2 mjp2
# video/mp1s
# video/mp2p
# video/mp2t
video/mp4 mp4 mp4v mpg4
# video/mp4v-es
video/mpeg mpeg mpg mpe m1v m2v
# video/mpeg4-generic
# video/mpv
# video/nv
video/ogg ogv
# video/parityfec
# video/pointer
video/quicktime qt mov
# video/raw
# video/rtp-enc-aescm128
# video/rtx
# video/smpte292m
# video/ulpfec
# video/vc1
# video/vnd.cctv
video/vnd.dece.hd uvh uvvh
video/vnd.dece.mobile uvm uvvm
# video/vnd.dece.mp4
video/vnd.dece.pd uvp uvvp
video/vnd.dece.sd uvs uvvs
video/vnd.dece.video uvv uvvv
# video/vnd.directv.mpeg
# video/vnd.directv.mpeg-tts
# video/vnd.dlna.mpeg-tts
video/vnd.dvb.file dvb
video/vnd.fvt fvt
# video/vnd.hns.video
# video/vnd.iptvforum.1dparityfec-1010
# video/vnd.iptvforum.1dparityfec-2005
# video/vnd.iptvforum.2dparityfec-1010
# video/vnd.iptvforum.2dparityfec-2005
# video/vnd.iptvforum.ttsavc
# video/vnd.iptvforum.ttsmpeg2
# video/vnd.motorola.video
# video/vnd.motorola.videop
video/vnd.mpegurl mxu m4u
video/vnd.ms-playready.media.pyv pyv
# video/vnd.nokia.interleaved-multimedia
# video/vnd.nokia.videovoip
# video/vnd.objectvideo
# video/vnd.sealed.mpeg1
# video/vnd.sealed.mpeg4
# video/vnd.sealed.swf
# video/vnd.sealedmedia.softseal.mov
video/vnd.uvvu.mp4 uvu uvvu
video/vnd.vivo viv
video/webm webm
video/x-f4v f4v
video/x-fli fli
video/x-flv flv
video/x-m4v m4v
video/x-matroska mkv mk3d mks
video/x-mng mng
video/x-ms-asf asf asx
video/x-ms-vob vob
video/x-ms-wm wm
video/x-ms-wmv wmv
video/x-ms-wmx wmx
video/x-ms-wvx wvx
video/x-msvideo avi
video/x-sgi-movie movie
video/x-smv smv
x-conference/x-cooltalk ice
# What: WebVTT
# Why: To allow formats intended for marking up external text track resources.
# http://dev.w3.org/html5/webvtt/
# Added by: niftylettuce
text/vtt vtt
# What: Google Chrome Extension
# Why: To allow apps to (work) be served with the right content type header.
# http://codereview.chromium.org/2830017
# Added by: niftylettuce
application/x-chrome-extension crx
# What: HTC support
# Why: To properly render .htc files such as CSS3PIE
# Added by: niftylettuce
text/x-component htc
# What: HTML5 application cache manifes ('.manifest' extension)
# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps
# per https://developer.mozilla.org/en/offline_resources_in_firefox
# Added by: louisremi
text/cache-manifest manifest
# What: node binary buffer format
# Why: semi-standard extension w/in the node community
# Added by: tootallnate
application/octet-stream buffer
# What: The "protected" MP-4 formats used by iTunes.
# Why: Required for streaming music to browsers (?)
# Added by: broofa
application/mp4 m4p
audio/mp4 m4a
# What: Video format, Part of RFC1890
# Why: See https://github.com/bentomas/node-mime/pull/6
# Added by: mjrusso
video/MP2T ts
# What: EventSource mime type
# Why: mime type of Server-Sent Events stream
# http://www.w3.org/TR/eventsource/#text-event-stream
# Added by: francois2metz
text/event-stream event-stream
# What: Mozilla App manifest mime type
# Why: https://developer.mozilla.org/en/Apps/Manifest#Serving_manifests
# Added by: ednapiranha
application/x-web-app-manifest+json webapp
# What: Lua file types
# Why: Googling around shows de-facto consensus on these
# Added by: creationix (Issue #45)
text/x-lua lua
application/x-lua-bytecode luac
# What: Markdown files, as per http://daringfireball.net/projects/markdown/syntax
# Why: http://stackoverflow.com/questions/10701983/what-is-the-mime-type-for-markdown
# Added by: avoidwork
text/x-markdown markdown md mkd
# What: ini files
# Why: because they're just text files
# Added by: Matthew Kastor
text/plain ini
# What: DASH Adaptive Streaming manifest
# Why: https://developer.mozilla.org/en-US/docs/DASH_Adaptive_Streaming_for_HTML_5_Video
# Added by: eelcocramer
application/dash+xml mdp
# What: OpenType font files - http://www.microsoft.com/typography/otspec/
# Why: Browsers usually ignore the font MIME types and sniff the content,
# but Chrome, shows a warning if OpenType fonts aren't served with
# the `font/opentype` MIME type: http://i.imgur.com/8c5RN8M.png.
# Added by: alrra
font/opentype otf
{
"name": "send",
"version": "0.3.0",
"description": "Better streaming static file server with Range and conditional-GET support",
"keywords": [
"static",
"file",
"server"
],
"author": {
"name": "TJ Holowaychuk",
"email": "[email protected]"
},
"dependencies": {
"buffer-crc32": "0.2.1",
"debug": "0.8.0",
"fresh": "~0.2.1",
"mime": "1.2.11",
"range-parser": "~1.0.0"
},
"devDependencies": {
"mocha": "*",
"should": "*",
"supertest": "0.10.0",
"connect": "2.x"
},
"scripts": {
"test": "mocha --require should --reporter spec --bail"
},
"repository": {
"type": "git",
"url": "git://github.com/visionmedia/send.git"
},
"main": "index",
"readme": "# send\n\n Send is Connect's `static()` extracted for generalized use, a streaming static file\n server supporting partial responses (Ranges), conditional-GET negotiation, high test coverage, and granular events which may be leveraged to take appropriate actions in your application or framework.\n\n## Installation\n\n $ npm install send\n\n## Examples\n\n Small:\n\n```js\nvar http = require('http');\nvar send = require('send');\n\nvar app = http.createServer(function(req, res){\n send(req, req.url).pipe(res);\n}).listen(3000);\n```\n\n Serving from a root directory with custom error-handling:\n\n```js\nvar http = require('http');\nvar send = require('send');\nvar url = require('url');\n\nvar app = http.createServer(function(req, res){\n // your custom error-handling logic:\n function error(err) {\n res.statusCode = err.status || 500;\n res.end(err.message);\n }\n\n // your custom directory handling logic:\n function redirect() {\n res.statusCode = 301;\n res.setHeader('Location', req.url + '/');\n res.end('Redirecting to ' + req.url + '/');\n }\n\n // transfer arbitrary files from within\n // /www/example.com/public/*\n send(req, url.parse(req.url).pathname, {root: '/www/example.com/public'})\n .on('error', error)\n .on('directory', redirect)\n .pipe(res);\n}).listen(3000);\n```\n\n## API\n\n### Options\n\n#### etag\n\n Enable or disable etag generation, defaults to true.\n\n#### hidden\n\n Enable or disable transfer of hidden files, defaults to false.\n\n#### index\n\n By default send supports \"index.html\" files, to disable this\n set `false` or to supply a new index pass a string or an array\n in preferred order.\n\n#### maxage\n\n Provide a max-age in milliseconds for http caching, defaults to 0.\n\n#### root\n\n Serve files relative to `path`.\n\n### Events\n\n - `error` an error occurred `(err)`\n - `directory` a directory was requested\n - `file` a file was requested `(path, stat)`\n - `stream` file streaming has started `(stream)`\n - `end` streaming has completed\n\n### .etag(bool)\n\n Enable or disable etag generation, defaults to true.\n\n### .root(dir)\n\n Serve files relative to `path`. Aliased as `.from(dir)`.\n\n### .index(paths)\n\n By default send supports \"index.html\" files, to disable this\n invoke `.index(false)` or to supply a new index pass a string\n or an array in preferred order.\n\n### .maxage(ms)\n\n Provide a max-age in milliseconds for http caching, defaults to 0.\n\n### .hidden(bool)\n\n Enable or disable transfer of hidden files, defaults to false.\n\n## Error-handling\n\n By default when no `error` listeners are present an automatic response will be made, otherwise you have full control over the response, aka you may show a 5xx page etc.\n\n## Caching\n\n It does _not_ perform internal caching, you should use a reverse proxy cache such\n as Varnish for this, or those fancy things called CDNs. If your application is small enough that it would benefit from single-node memory caching, it's small enough that it does not need caching at all ;).\n\n## Debugging\n\n To enable `debug()` instrumentation output export __DEBUG__:\n\n```\n$ DEBUG=send node app\n```\n\n## Running tests\n\n```\n$ npm install\n$ make test\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk &lt;[email protected]&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
"readmeFilename": "Readme.md",
"bugs": {
"url": "https://github.com/visionmedia/send/issues"
},
"homepage": "https://github.com/visionmedia/send",
"_id": "[email protected]",
"dist": {
"shasum": "0e24b0aa7dcdac0c6131f03e1c5592a4c020c0e9"
},
"_from": "[email protected]",
"_resolved": "https://registry.npmjs.org/send/-/send-0.3.0.tgz"
}

send

Send is Connect's static() extracted for generalized use, a streaming static file server supporting partial responses (Ranges), conditional-GET negotiation, high test coverage, and granular events which may be leveraged to take appropriate actions in your application or framework.

Installation

$ npm install send

Examples

Small:

var http = require('http');
var send = require('send');

var app = http.createServer(function(req, res){
  send(req, req.url).pipe(res);
}).listen(3000);

Serving from a root directory with custom error-handling:

var http = require('http');
var send = require('send');
var url = require('url');

var app = http.createServer(function(req, res){
  // your custom error-handling logic:
  function error(err) {
    res.statusCode = err.status || 500;
    res.end(err.message);
  }

  // your custom directory handling logic:
  function redirect() {
    res.statusCode = 301;
    res.setHeader('Location', req.url + '/');
    res.end('Redirecting to ' + req.url + '/');
  }

  // transfer arbitrary files from within
  // /www/example.com/public/*
  send(req, url.parse(req.url).pathname, {root: '/www/example.com/public'})
  .on('error', error)
  .on('directory', redirect)
  .pipe(res);
}).listen(3000);

API

Options

etag

Enable or disable etag generation, defaults to true.

hidden

Enable or disable transfer of hidden files, defaults to false.

index

By default send supports "index.html" files, to disable this set false or to supply a new index pass a string or an array in preferred order.

maxage

Provide a max-age in milliseconds for http caching, defaults to 0.

root

Serve files relative to path.

Events

  • error an error occurred (err)
  • directory a directory was requested
  • file a file was requested (path, stat)
  • stream file streaming has started (stream)
  • end streaming has completed

.etag(bool)

Enable or disable etag generation, defaults to true.

.root(dir)

Serve files relative to path. Aliased as .from(dir).

.index(paths)

By default send supports "index.html" files, to disable this invoke .index(false) or to supply a new index pass a string or an array in preferred order.

.maxage(ms)

Provide a max-age in milliseconds for http caching, defaults to 0.

.hidden(bool)

Enable or disable transfer of hidden files, defaults to false.

Error-handling

By default when no error listeners are present an automatic response will be made, otherwise you have full control over the response, aka you may show a 5xx page etc.

Caching

It does not perform internal caching, you should use a reverse proxy cache such as Varnish for this, or those fancy things called CDNs. If your application is small enough that it would benefit from single-node memory caching, it's small enough that it does not need caching at all ;).

Debugging

To enable debug() instrumentation output export DEBUG:

$ DEBUG=send node app

Running tests

$ npm install
$ make test

License

(The MIT License)

Copyright (c) 2012 TJ Holowaychuk <[email protected]>

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.

language: node_js
node_js:
- "0.8"
- "0.10"
- "0.11"

1.1.0 / 2014-04-24

1.0.4 / 2014-04-07

  • Resolve relative paths at middleware setup
  • Use parseurl to parse the URL from request

1.0.3 / 2014-03-20

  • Do not rely on connect-like environments

1.0.2 / 2014-03-06

1.0.1 / 2014-03-05

  • Add mime export for back-compat

1.0.0 / 2014-03-05

  • Genesis from connect
/*!
* Connect - static
* Copyright(c) 2010 Sencha Inc.
* Copyright(c) 2011 TJ Holowaychuk
* Copyright(c) 2014 Douglas Christopher Wilson
* MIT Licensed
*/
/**
* Module dependencies.
*/
var parseurl = require('parseurl');
var resolve = require('path').resolve;
var send = require('send');
var url = require('url');
/**
* Static:
*
* Static file server with the given `root` path.
*
* Examples:
*
* var oneDay = 86400000;
* var serveStatic = require('serve-static');
*
* connect()
* .use(serveStatic(__dirname + '/public'))
*
* connect()
* .use(serveStatic(__dirname + '/public', { maxAge: oneDay }))
*
* Options:
*
* - `maxAge` Browser cache maxAge in milliseconds. defaults to 0
* - `hidden` Allow transfer of hidden files. defaults to false
* - `redirect` Redirect to trailing "/" when the pathname is a dir. defaults to true
* - `index` Default file name, defaults to 'index.html'
*
* Further options are forwarded on to `send`.
*
* @param {String} root
* @param {Object} options
* @return {Function}
* @api public
*/
exports = module.exports = function (root, options) {
options = extend({}, options);
// root required
if (!root) throw new TypeError('root path required');
// resolve root to absolute
root = resolve(root);
// default redirect
var redirect = false !== options.redirect;
// setup options for send
options.maxage = options.maxage || options.maxAge || 0;
options.root = root;
return function staticMiddleware(req, res, next) {
if ('GET' != req.method && 'HEAD' != req.method) return next();
var opts = extend({}, options);
var originalUrl = url.parse(req.originalUrl || req.url);
var path = parseurl(req).pathname;
if (path == '/' && originalUrl.pathname[originalUrl.pathname.length - 1] != '/') {
return directory();
}
function directory() {
if (!redirect) return next();
var target;
originalUrl.pathname += '/';
target = url.format(originalUrl);
res.statusCode = 303;
res.setHeader('Location', target);
res.end('Redirecting to ' + escape(target));
}
function error(err) {
if (404 == err.status) return next();
next(err);
}
send(req, path, opts)
.on('error', error)
.on('directory', directory)
.pipe(res);
};
};
/**
* Expose mime module.
*
* If you wish to extend the mime table use this
* reference to the "mime" module in the npm registry.
*/
exports.mime = send.mime;
/**
* Escape the given string of `html`.
*
* @param {String} html
* @return {String}
* @api private
*/
function escape(html) {
return String(html)
.replace(/&(?!\w+;)/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
};
/**
* Shallow clone a single object.
*
* @param {Object} obj
* @param {Object} source
* @return {Object}
* @api private
*/
function extend(obj, source) {
if (!source) return obj;
for (var prop in source) {
obj[prop] = source[prop];
}
return obj;
};
(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.
{
"name": "serve-static",
"description": "Serve static files",
"version": "1.1.0",
"author": {
"name": "Douglas Christopher Wilson",
"email": "[email protected]"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/expressjs/serve-static.git"
},
"bugs": {
"url": "https://github.com/expressjs/serve-static/issues"
},
"dependencies": {
"parseurl": "1.0.1",
"send": "0.3.0"
},
"devDependencies": {
"connect": "~2.14.1",
"mocha": "~1.18.2",
"should": "~3.3.0",
"supertest": "~0.11.0"
},
"engines": {
"node": ">= 0.8.0"
},
"scripts": {
"test": "mocha --reporter spec --require should"
},
"readme": "# Serve Static\n\nPreviously `connect.static()`.\n\n[![Build Status](https://travis-ci.org/expressjs/serve-static.svg?branch=master)](https://travis-ci.org/expressjs/serve-static)\n\nUsage:\n\n```js\nvar connect = require('connect');\nvar serveStatic = require('serve-static');\n\nvar app = connect();\n\napp.use(serveStatic('public/ftp', {'index': ['default.html', 'default.htm']}));\napp.listen();\n```\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Douglas Christopher Wilson\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n",
"readmeFilename": "Readme.md",
"homepage": "https://github.com/expressjs/serve-static",
"_id": "[email protected]",
"dist": {
"shasum": "3e21b7f155096e4e43bafe531f0383a230966a5e"
},
"_from": "[email protected]",
"_resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.1.0.tgz"
}

Serve Static

Previously connect.static().

Build Status

Usage:

var connect = require('connect');
var serveStatic = require('serve-static');

var app = connect();

app.use(serveStatic('public/ftp', {'index': ['default.html', 'default.htm']}));
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.

1.1.0 / 2014-04-12

  • add non-array values support

  • expose internal utilities:

    • .is()
    • .hasBody()
    • .normalize()
    • .match()

1.0.1 / 2014-03-30

  • add multipart as a shorthand
var mime = require('mime');
var slice = [].slice;
module.exports = typeofrequest;
typeofrequest.is = typeis;
typeofrequest.hasBody = hasbody;
typeofrequest.normalize = normalize;
typeofrequest.match = mimeMatch;
/**
* Compare a `value` content-type with `types`.
* Each `type` can be an extension like `html`,
* a special shortcut like `multipart` or `urlencoded`,
* or a mime type.
*
* If no types match, `false` is returned.
* Otherwise, the first `type` that matches is returned.
*
* @param {String} value
* @param {Array} types
* @return String
*/
function typeis(value, types) {
if (!value) return false;
if (types && !Array.isArray(types)) types = slice.call(arguments, 1);
// remove stuff like charsets
var index = value.indexOf(';')
value = ~index ? value.slice(0, index) : value
// no types, return the content type
if (!types || !types.length) return value;
var type;
for (var i = 0; i < types.length; i++)
if (mimeMatch(normalize(type = types[i]), value))
return ~type.indexOf('*') ? value : type;
// no matches
return false;
}
/**
* Check if a request has a request body.
* A request with a body __must__ either have `transfer-encoding`
* or `content-length` headers set.
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
*
* @param {Object} request
* @return {Boolean}
* @api public
*/
function hasbody(req) {
var headers = req.headers;
if ('transfer-encoding' in headers) return true;
var length = headers['content-length'];
if (!length) return false;
// no idea when this would happen, but `isNaN(null) === false`
if (isNaN(length)) return false;
return !!parseInt(length, 10);
}
/**
* Check if the incoming request contains the "Content-Type"
* header field, and it contains any of the give mime `type`s.
* If there is no request body, `null` is returned.
* If there is no content type, `false` is returned.
* Otherwise, it returns the first `type` that matches.
*
* Examples:
*
* // With Content-Type: text/html; charset=utf-8
* this.is('html'); // => 'html'
* this.is('text/html'); // => 'text/html'
* this.is('text/*', 'application/json'); // => 'text/html'
*
* // When Content-Type is application/json
* this.is('json', 'urlencoded'); // => 'json'
* this.is('application/json'); // => 'application/json'
* this.is('html', 'application/*'); // => 'application/json'
*
* this.is('html'); // => false
*
* @param {String|Array} types...
* @return {String|false|null}
* @api public
*/
function typeofrequest(req, types) {
if (!hasbody(req)) return null;
if (types && !Array.isArray(types)) types = slice.call(arguments, 1);
return typeis(req.headers['content-type'], types);
}
/**
* Normalize a mime type.
* If it's a shorthand, expand it to a valid mime type.
*
* In general, you probably want:
*
* var type = is(req, ['urlencoded', 'json', 'multipart']);
*
* Then use the appropriate body parsers.
* These three are the most common request body types
* and are thus ensured to work.
*
* @param {String} type
* @api private
*/
function normalize(type) {
switch (type) {
case 'urlencoded':
return 'application/x-www-form-urlencoded';
case 'multipart':
type = 'multipart/*';
break;
}
return ~type.indexOf('/') ? type : mime.lookup(type);
}
/**
* Check if `exected` mime type
* matches `actual` mime type with
* wildcard support.
*
* @param {String} expected
* @param {String} actual
* @return {Boolean}
* @api private
*/
function mimeMatch(expected, actual) {
if (expected === actual) return true;
if (!~expected.indexOf('*')) return false;
actual = actual.split('/');
expected = expected.split('/');
if ('*' === expected[0] && expected[1] === actual[1]) return true;
if ('*' === expected[1] && expected[0] === actual[0]) return true;
return false;
}
Copyright (c) 2010 Benjamin Thomas, Robert Kieffer
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.
var path = require('path');
var fs = require('fs');
function Mime() {
// Map of extension -> mime type
this.types = Object.create(null);
// Map of mime type -> extension
this.extensions = Object.create(null);
}
/**
* Define mimetype -> extension mappings. Each key is a mime-type that maps
* to an array of extensions associated with the type. The first extension is
* used as the default extension for the type.
*
* e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']});
*
* @param map (Object) type definitions
*/
Mime.prototype.define = function (map) {
for (var type in map) {
var exts = map[type];
for (var i = 0; i < exts.length; i++) {
if (process.env.DEBUG_MIME && this.types[exts]) {
console.warn(this._loading.replace(/.*\//, ''), 'changes "' + exts[i] + '" extension type from ' +
this.types[exts] + ' to ' + type);
}
this.types[exts[i]] = type;
}
// Default extension is the first one we encounter
if (!this.extensions[type]) {
this.extensions[type] = exts[0];
}
}
};
/**
* Load an Apache2-style ".types" file
*
* This may be called multiple times (it's expected). Where files declare
* overlapping types/extensions, the last file wins.
*
* @param file (String) path of file to load.
*/
Mime.prototype.load = function (file) {
this._loading = file;
// Read file and split into lines
var map = {},
content = fs.readFileSync(file, 'ascii'),
lines = content.split(/[\r\n]+/);
lines.forEach(function (line) {
// Clean up whitespace/comments, and split into fields
var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/);
map[fields.shift()] = fields;
});
this.define(map);
this._loading = null;
};
/**
* Lookup a mime type based on extension
*/
Mime.prototype.lookup = function (path, fallback) {
var ext = path.replace(/.*[\.\/\\]/, '').toLowerCase();
return this.types[ext] || fallback || this.default_type;
};
/**
* Return file extension associated with a mime type
*/
Mime.prototype.extension = function (mimeType) {
var type = mimeType.match(/^\s*([^;\s]*)(?:;|\s|$)/)[1].toLowerCase();
return this.extensions[type];
};
// Default instance
var mime = new Mime();
// Load local copy of
// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
mime.load(path.join(__dirname, 'types/mime.types'));
// Load additional types from node.js community
mime.load(path.join(__dirname, 'types/node.types'));
// Default type
mime.default_type = mime.lookup('bin');
//
// Additional API specific to the default instance
//
mime.Mime = Mime;
/**
* Lookup a charset based on mime type.
*/
mime.charsets = {
lookup: function (mimeType, fallback) {
// Assume text types are utf8
return (/^text\//).test(mimeType) ? 'UTF-8' : fallback;
}
};
module.exports = mime;
{
"author": {
"name": "Robert Kieffer",
"email": "[email protected]",
"url": "http://github.com/broofa"
},
"contributors": [
{
"name": "Benjamin Thomas",
"email": "[email protected]",
"url": "http://github.com/bentomas"
}
],
"dependencies": {},
"description": "A comprehensive library for mime-type mapping",
"devDependencies": {},
"keywords": [
"util",
"mime"
],
"main": "mime.js",
"name": "mime",
"repository": {
"url": "https://github.com/broofa/node-mime",
"type": "git"
},
"version": "1.2.11",
"readme": "# mime\n\nComprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.\n\n## Install\n\nInstall with [npm](http://github.com/isaacs/npm):\n\n npm install mime\n\n## API - Queries\n\n### mime.lookup(path)\nGet the mime type associated with a file, if no mime type is found `application/octet-stream` is returned. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.'). E.g.\n\n var mime = require('mime');\n\n mime.lookup('/path/to/file.txt'); // => 'text/plain'\n mime.lookup('file.txt'); // => 'text/plain'\n mime.lookup('.TXT'); // => 'text/plain'\n mime.lookup('htm'); // => 'text/html'\n\n### mime.default_type\nSets the mime type returned when `mime.lookup` fails to find the extension searched for. (Default is `application/octet-stream`.)\n\n### mime.extension(type)\nGet the default extension for `type`\n\n mime.extension('text/html'); // => 'html'\n mime.extension('application/octet-stream'); // => 'bin'\n\n### mime.charsets.lookup()\n\nMap mime-type to charset\n\n mime.charsets.lookup('text/plain'); // => 'UTF-8'\n\n(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.)\n\n## API - Defining Custom Types\n\nThe following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types).\n\n### mime.define()\n\nAdd custom mime/extension mappings\n\n mime.define({\n 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],\n 'application/x-my-type': ['x-mt', 'x-mtt'],\n // etc ...\n });\n\n mime.lookup('x-sft'); // => 'text/x-some-format'\n\nThe first entry in the extensions array is returned by `mime.extension()`. E.g.\n\n mime.extension('text/x-some-format'); // => 'x-sf'\n\n### mime.load(filepath)\n\nLoad mappings from an Apache \".types\" format file\n\n mime.load('./my_project.types');\n\nThe .types file format is simple - See the `types` dir for examples.\n",
"readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/broofa/node-mime/issues"
},
"homepage": "https://github.com/broofa/node-mime",
"_id": "[email protected]",
"dist": {
"shasum": "8401d4ab4f06fcf4bc53e86d918c0443ccaa7274"
},
"_from": "mime@~1.2.11",
"_resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz"
}

mime

Comprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.

Install

Install with npm:

npm install mime

API - Queries

mime.lookup(path)

Get the mime type associated with a file, if no mime type is found application/octet-stream is returned. Performs a case-insensitive lookup using the extension in path (the substring after the last '/' or '.'). E.g.

var mime = require('mime');

mime.lookup('/path/to/file.txt');         // => 'text/plain'
mime.lookup('file.txt');                  // => 'text/plain'
mime.lookup('.TXT');                      // => 'text/plain'
mime.lookup('htm');                       // => 'text/html'

mime.default_type

Sets the mime type returned when mime.lookup fails to find the extension searched for. (Default is application/octet-stream.)

mime.extension(type)

Get the default extension for type

mime.extension('text/html');                 // => 'html'
mime.extension('application/octet-stream');  // => 'bin'

mime.charsets.lookup()

Map mime-type to charset

mime.charsets.lookup('text/plain');        // => 'UTF-8'

(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.)

API - Defining Custom Types

The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see requesting new types.

mime.define()

Add custom mime/extension mappings

mime.define({
    'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],
    'application/x-my-type': ['x-mt', 'x-mtt'],
    // etc ...
});

mime.lookup('x-sft');                 // => 'text/x-some-format'

The first entry in the extensions array is returned by mime.extension(). E.g.

mime.extension('text/x-some-format'); // => 'x-sf'

mime.load(filepath)

Load mappings from an Apache ".types" format file

mime.load('./my_project.types');

The .types file format is simple - See the types dir for examples.

/**
* Usage: node test.js
*/
var mime = require('./mime');
var assert = require('assert');
var path = require('path');
function eq(a, b) {
console.log('Test: ' + a + ' === ' + b);
assert.strictEqual.apply(null, arguments);
}
console.log(Object.keys(mime.extensions).length + ' types');
console.log(Object.keys(mime.types).length + ' extensions\n');
//
// Test mime lookups
//
eq('text/plain', mime.lookup('text.txt')); // normal file
eq('text/plain', mime.lookup('TEXT.TXT')); // uppercase
eq('text/plain', mime.lookup('dir/text.txt')); // dir + file
eq('text/plain', mime.lookup('.text.txt')); // hidden file
eq('text/plain', mime.lookup('.txt')); // nameless
eq('text/plain', mime.lookup('txt')); // extension-only
eq('text/plain', mime.lookup('/txt')); // extension-less ()
eq('text/plain', mime.lookup('\\txt')); // Windows, extension-less
eq('application/octet-stream', mime.lookup('text.nope')); // unrecognized
eq('fallback', mime.lookup('text.fallback', 'fallback')); // alternate default
//
// Test extensions
//
eq('txt', mime.extension(mime.types.text));
eq('html', mime.extension(mime.types.htm));
eq('bin', mime.extension('application/octet-stream'));
eq('bin', mime.extension('application/octet-stream '));
eq('html', mime.extension(' text/html; charset=UTF-8'));
eq('html', mime.extension('text/html; charset=UTF-8 '));
eq('html', mime.extension('text/html; charset=UTF-8'));
eq('html', mime.extension('text/html ; charset=UTF-8'));
eq('html', mime.extension('text/html;charset=UTF-8'));
eq('html', mime.extension('text/Html;charset=UTF-8'));
eq(undefined, mime.extension('unrecognized'));
//
// Test node.types lookups
//
eq('application/font-woff', mime.lookup('file.woff'));
eq('application/octet-stream', mime.lookup('file.buffer'));
eq('audio/mp4', mime.lookup('file.m4a'));
eq('font/opentype', mime.lookup('file.otf'));
//
// Test charsets
//
eq('UTF-8', mime.charsets.lookup('text/plain'));
eq(undefined, mime.charsets.lookup(mime.types.js));
eq('fallback', mime.charsets.lookup('application/octet-stream', 'fallback'));
//
// Test for overlaps between mime.types and node.types
//
var apacheTypes = new mime.Mime(), nodeTypes = new mime.Mime();
apacheTypes.load(path.join(__dirname, 'types/mime.types'));
nodeTypes.load(path.join(__dirname, 'types/node.types'));
var keys = [].concat(Object.keys(apacheTypes.types))
.concat(Object.keys(nodeTypes.types));
keys.sort();
for (var i = 1; i < keys.length; i++) {
if (keys[i] == keys[i - 1]) {
console.warn('Warning: ' +
'node.types defines ' + keys[i] + '->' + nodeTypes.types[keys[i]] +
', mime.types defines ' + keys[i] + '->' + apacheTypes.types[keys[i]]);
}
}
console.log('\nOK');
# This file maps Internet media types to unique file extension(s).
# Although created for httpd, this file is used by many software systems
# and has been placed in the public domain for unlimited redisribution.
#
# The table below contains both registered and (common) unregistered types.
# A type that has no unique extension can be ignored -- they are listed
# here to guide configurations toward known types and to make it easier to
# identify "new" types. File extensions are also commonly used to indicate
# content languages and encodings, so choose them carefully.
#
# Internet media types should be registered as described in RFC 4288.
# The registry is at <http://www.iana.org/assignments/media-types/>.
#
# MIME type (lowercased) Extensions
# ============================================ ==========
# application/1d-interleaved-parityfec
# application/3gpp-ims+xml
# application/activemessage
application/andrew-inset ez
# application/applefile
application/applixware aw
application/atom+xml atom
application/atomcat+xml atomcat
# application/atomicmail
application/atomsvc+xml atomsvc
# application/auth-policy+xml
# application/batch-smtp
# application/beep+xml
# application/calendar+xml
# application/cals-1840
# application/ccmp+xml
application/ccxml+xml ccxml
application/cdmi-capability cdmia
application/cdmi-container cdmic
application/cdmi-domain cdmid
application/cdmi-object cdmio
application/cdmi-queue cdmiq
# application/cea-2018+xml
# application/cellml+xml
# application/cfw
# application/cnrp+xml
# application/commonground
# application/conference-info+xml
# application/cpl+xml
# application/csta+xml
# application/cstadata+xml
application/cu-seeme cu
# application/cybercash
application/davmount+xml davmount
# application/dca-rft
# application/dec-dx
# application/dialog-info+xml
# application/dicom
# application/dns
application/docbook+xml dbk
# application/dskpp+xml
application/dssc+der dssc
application/dssc+xml xdssc
# application/dvcs
application/ecmascript ecma
# application/edi-consent
# application/edi-x12
# application/edifact
application/emma+xml emma
# application/epp+xml
application/epub+zip epub
# application/eshop
# application/example
application/exi exi
# application/fastinfoset
# application/fastsoap
# application/fits
application/font-tdpfr pfr
# application/framework-attributes+xml
application/gml+xml gml
application/gpx+xml gpx
application/gxf gxf
# application/h224
# application/held+xml
# application/http
application/hyperstudio stk
# application/ibe-key-request+xml
# application/ibe-pkg-reply+xml
# application/ibe-pp-data
# application/iges
# application/im-iscomposing+xml
# application/index
# application/index.cmd
# application/index.obj
# application/index.response
# application/index.vnd
application/inkml+xml ink inkml
# application/iotp
application/ipfix ipfix
# application/ipp
# application/isup
application/java-archive jar
application/java-serialized-object ser
application/java-vm class
application/javascript js
application/json json
application/jsonml+json jsonml
# application/kpml-request+xml
# application/kpml-response+xml
application/lost+xml lostxml
application/mac-binhex40 hqx
application/mac-compactpro cpt
# application/macwriteii
application/mads+xml mads
application/marc mrc
application/marcxml+xml mrcx
application/mathematica ma nb mb
# application/mathml-content+xml
# application/mathml-presentation+xml
application/mathml+xml mathml
# application/mbms-associated-procedure-description+xml
# application/mbms-deregister+xml
# application/mbms-envelope+xml
# application/mbms-msk+xml
# application/mbms-msk-response+xml
# application/mbms-protection-description+xml
# application/mbms-reception-report+xml
# application/mbms-register+xml
# application/mbms-register-response+xml
# application/mbms-user-service-description+xml
application/mbox mbox
# application/media_control+xml
application/mediaservercontrol+xml mscml
application/metalink+xml metalink
application/metalink4+xml meta4
application/mets+xml mets
# application/mikey
application/mods+xml mods
# application/moss-keys
# application/moss-signature
# application/mosskey-data
# application/mosskey-request
application/mp21 m21 mp21
application/mp4 mp4s
# application/mpeg4-generic
# application/mpeg4-iod
# application/mpeg4-iod-xmt
# application/msc-ivr+xml
# application/msc-mixer+xml
application/msword doc dot
application/mxf mxf
# application/nasdata
# application/news-checkgroups
# application/news-groupinfo
# application/news-transmission
# application/nss
# application/ocsp-request
# application/ocsp-response
application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy
application/oda oda
application/oebps-package+xml opf
application/ogg ogx
application/omdoc+xml omdoc
application/onenote onetoc onetoc2 onetmp onepkg
application/oxps oxps
# application/parityfec
application/patch-ops-error+xml xer
application/pdf pdf
application/pgp-encrypted pgp
# application/pgp-keys
application/pgp-signature asc sig
application/pics-rules prf
# application/pidf+xml
# application/pidf-diff+xml
application/pkcs10 p10
application/pkcs7-mime p7m p7c
application/pkcs7-signature p7s
application/pkcs8 p8
application/pkix-attr-cert ac
application/pkix-cert cer
application/pkix-crl crl
application/pkix-pkipath pkipath
application/pkixcmp pki
application/pls+xml pls
# application/poc-settings+xml
application/postscript ai eps ps
# application/prs.alvestrand.titrax-sheet
application/prs.cww cww
# application/prs.nprend
# application/prs.plucker
# application/prs.rdf-xml-crypt
# application/prs.xsf+xml
application/pskc+xml pskcxml
# application/qsig
application/rdf+xml rdf
application/reginfo+xml rif
application/relax-ng-compact-syntax rnc
# application/remote-printing
application/resource-lists+xml rl
application/resource-lists-diff+xml rld
# application/riscos
# application/rlmi+xml
application/rls-services+xml rs
application/rpki-ghostbusters gbr
application/rpki-manifest mft
application/rpki-roa roa
# application/rpki-updown
application/rsd+xml rsd
application/rss+xml rss
application/rtf rtf
# application/rtx
# application/samlassertion+xml
# application/samlmetadata+xml
application/sbml+xml sbml
application/scvp-cv-request scq
application/scvp-cv-response scs
application/scvp-vp-request spq
application/scvp-vp-response spp
application/sdp sdp
# application/set-payment
application/set-payment-initiation setpay
# application/set-registration
application/set-registration-initiation setreg
# application/sgml
# application/sgml-open-catalog
application/shf+xml shf
# application/sieve
# application/simple-filter+xml
# application/simple-message-summary
# application/simplesymbolcontainer
# application/slate
# application/smil
application/smil+xml smi smil
# application/soap+fastinfoset
# application/soap+xml
application/sparql-query rq
application/sparql-results+xml srx
# application/spirits-event+xml
application/srgs gram
application/srgs+xml grxml
application/sru+xml sru
application/ssdl+xml ssdl
application/ssml+xml ssml
# application/tamp-apex-update
# application/tamp-apex-update-confirm
# application/tamp-community-update
# application/tamp-community-update-confirm
# application/tamp-error
# application/tamp-sequence-adjust
# application/tamp-sequence-adjust-confirm
# application/tamp-status-query
# application/tamp-status-response
# application/tamp-update
# application/tamp-update-confirm
application/tei+xml tei teicorpus
application/thraud+xml tfi
# application/timestamp-query
# application/timestamp-reply
application/timestamped-data tsd
# application/tve-trigger
# application/ulpfec
# application/vcard+xml
# application/vemmi
# application/vividence.scriptfile
# application/vnd.3gpp.bsf+xml
application/vnd.3gpp.pic-bw-large plb
application/vnd.3gpp.pic-bw-small psb
application/vnd.3gpp.pic-bw-var pvb
# application/vnd.3gpp.sms
# application/vnd.3gpp2.bcmcsinfo+xml
# application/vnd.3gpp2.sms
application/vnd.3gpp2.tcap tcap
application/vnd.3m.post-it-notes pwn
application/vnd.accpac.simply.aso aso
application/vnd.accpac.simply.imp imp
application/vnd.acucobol acu
application/vnd.acucorp atc acutc
application/vnd.adobe.air-application-installer-package+zip air
application/vnd.adobe.formscentral.fcdt fcdt
application/vnd.adobe.fxp fxp fxpl
# application/vnd.adobe.partial-upload
application/vnd.adobe.xdp+xml xdp
application/vnd.adobe.xfdf xfdf
# application/vnd.aether.imp
# application/vnd.ah-barcode
application/vnd.ahead.space ahead
application/vnd.airzip.filesecure.azf azf
application/vnd.airzip.filesecure.azs azs
application/vnd.amazon.ebook azw
application/vnd.americandynamics.acc acc
application/vnd.amiga.ami ami
# application/vnd.amundsen.maze+xml
application/vnd.android.package-archive apk
application/vnd.anser-web-certificate-issue-initiation cii
application/vnd.anser-web-funds-transfer-initiation fti
application/vnd.antix.game-component atx
application/vnd.apple.installer+xml mpkg
application/vnd.apple.mpegurl m3u8
# application/vnd.arastra.swi
application/vnd.aristanetworks.swi swi
application/vnd.astraea-software.iota iota
application/vnd.audiograph aep
# application/vnd.autopackage
# application/vnd.avistar+xml
application/vnd.blueice.multipass mpm
# application/vnd.bluetooth.ep.oob
application/vnd.bmi bmi
application/vnd.businessobjects rep
# application/vnd.cab-jscript
# application/vnd.canon-cpdl
# application/vnd.canon-lips
# application/vnd.cendio.thinlinc.clientconf
application/vnd.chemdraw+xml cdxml
application/vnd.chipnuts.karaoke-mmd mmd
application/vnd.cinderella cdy
# application/vnd.cirpack.isdn-ext
application/vnd.claymore cla
application/vnd.cloanto.rp9 rp9
application/vnd.clonk.c4group c4g c4d c4f c4p c4u
application/vnd.cluetrust.cartomobile-config c11amc
application/vnd.cluetrust.cartomobile-config-pkg c11amz
# application/vnd.collection+json
# application/vnd.commerce-battelle
application/vnd.commonspace csp
application/vnd.contact.cmsg cdbcmsg
application/vnd.cosmocaller cmc
application/vnd.crick.clicker clkx
application/vnd.crick.clicker.keyboard clkk
application/vnd.crick.clicker.palette clkp
application/vnd.crick.clicker.template clkt
application/vnd.crick.clicker.wordbank clkw
application/vnd.criticaltools.wbs+xml wbs
application/vnd.ctc-posml pml
# application/vnd.ctct.ws+xml
# application/vnd.cups-pdf
# application/vnd.cups-postscript
application/vnd.cups-ppd ppd
# application/vnd.cups-raster
# application/vnd.cups-raw
# application/vnd.curl
application/vnd.curl.car car
application/vnd.curl.pcurl pcurl
# application/vnd.cybank
application/vnd.dart dart
application/vnd.data-vision.rdz rdz
application/vnd.dece.data uvf uvvf uvd uvvd
application/vnd.dece.ttml+xml uvt uvvt
application/vnd.dece.unspecified uvx uvvx
application/vnd.dece.zip uvz uvvz
application/vnd.denovo.fcselayout-link fe_launch
# application/vnd.dir-bi.plate-dl-nosuffix
application/vnd.dna dna
application/vnd.dolby.mlp mlp
# application/vnd.dolby.mobile.1
# application/vnd.dolby.mobile.2
application/vnd.dpgraph dpg
application/vnd.dreamfactory dfac
application/vnd.ds-keypoint kpxx
application/vnd.dvb.ait ait
# application/vnd.dvb.dvbj
# application/vnd.dvb.esgcontainer
# application/vnd.dvb.ipdcdftnotifaccess
# application/vnd.dvb.ipdcesgaccess
# application/vnd.dvb.ipdcesgaccess2
# application/vnd.dvb.ipdcesgpdd
# application/vnd.dvb.ipdcroaming
# application/vnd.dvb.iptv.alfec-base
# application/vnd.dvb.iptv.alfec-enhancement
# application/vnd.dvb.notif-aggregate-root+xml
# application/vnd.dvb.notif-container+xml
# application/vnd.dvb.notif-generic+xml
# application/vnd.dvb.notif-ia-msglist+xml
# application/vnd.dvb.notif-ia-registration-request+xml
# application/vnd.dvb.notif-ia-registration-response+xml
# application/vnd.dvb.notif-init+xml
# application/vnd.dvb.pfr
application/vnd.dvb.service svc
# application/vnd.dxr
application/vnd.dynageo geo
# application/vnd.easykaraoke.cdgdownload
# application/vnd.ecdis-update
application/vnd.ecowin.chart mag
# application/vnd.ecowin.filerequest
# application/vnd.ecowin.fileupdate
# application/vnd.ecowin.series
# application/vnd.ecowin.seriesrequest
# application/vnd.ecowin.seriesupdate
# application/vnd.emclient.accessrequest+xml
application/vnd.enliven nml
# application/vnd.eprints.data+xml
application/vnd.epson.esf esf
application/vnd.epson.msf msf
application/vnd.epson.quickanime qam
application/vnd.epson.salt slt
application/vnd.epson.ssf ssf
# application/vnd.ericsson.quickcall
application/vnd.eszigno3+xml es3 et3
# application/vnd.etsi.aoc+xml
# application/vnd.etsi.cug+xml
# application/vnd.etsi.iptvcommand+xml
# application/vnd.etsi.iptvdiscovery+xml
# application/vnd.etsi.iptvprofile+xml
# application/vnd.etsi.iptvsad-bc+xml
# application/vnd.etsi.iptvsad-cod+xml
# application/vnd.etsi.iptvsad-npvr+xml
# application/vnd.etsi.iptvservice+xml
# application/vnd.etsi.iptvsync+xml
# application/vnd.etsi.iptvueprofile+xml
# application/vnd.etsi.mcid+xml
# application/vnd.etsi.overload-control-policy-dataset+xml
# application/vnd.etsi.sci+xml
# application/vnd.etsi.simservs+xml
# application/vnd.etsi.tsl+xml
# application/vnd.etsi.tsl.der
# application/vnd.eudora.data
application/vnd.ezpix-album ez2
application/vnd.ezpix-package ez3
# application/vnd.f-secure.mobile
application/vnd.fdf fdf
application/vnd.fdsn.mseed mseed
application/vnd.fdsn.seed seed dataless
# application/vnd.ffsns
# application/vnd.fints
application/vnd.flographit gph
application/vnd.fluxtime.clip ftc
# application/vnd.font-fontforge-sfd
application/vnd.framemaker fm frame maker book
application/vnd.frogans.fnc fnc
application/vnd.frogans.ltf ltf
application/vnd.fsc.weblaunch fsc
application/vnd.fujitsu.oasys oas
application/vnd.fujitsu.oasys2 oa2
application/vnd.fujitsu.oasys3 oa3
application/vnd.fujitsu.oasysgp fg5
application/vnd.fujitsu.oasysprs bh2
# application/vnd.fujixerox.art-ex
# application/vnd.fujixerox.art4
# application/vnd.fujixerox.hbpl
application/vnd.fujixerox.ddd ddd
application/vnd.fujixerox.docuworks xdw
application/vnd.fujixerox.docuworks.binder xbd
# application/vnd.fut-misnet
application/vnd.fuzzysheet fzs
application/vnd.genomatix.tuxedo txd
# application/vnd.geocube+xml
application/vnd.geogebra.file ggb
application/vnd.geogebra.tool ggt
application/vnd.geometry-explorer gex gre
application/vnd.geonext gxt
application/vnd.geoplan g2w
application/vnd.geospace g3w
# application/vnd.globalplatform.card-content-mgt
# application/vnd.globalplatform.card-content-mgt-response
application/vnd.gmx gmx
application/vnd.google-earth.kml+xml kml
application/vnd.google-earth.kmz kmz
application/vnd.grafeq gqf gqs
# application/vnd.gridmp
application/vnd.groove-account gac
application/vnd.groove-help ghf
application/vnd.groove-identity-message gim
application/vnd.groove-injector grv
application/vnd.groove-tool-message gtm
application/vnd.groove-tool-template tpl
application/vnd.groove-vcard vcg
# application/vnd.hal+json
application/vnd.hal+xml hal
application/vnd.handheld-entertainment+xml zmm
application/vnd.hbci hbci
# application/vnd.hcl-bireports
application/vnd.hhe.lesson-player les
application/vnd.hp-hpgl hpgl
application/vnd.hp-hpid hpid
application/vnd.hp-hps hps
application/vnd.hp-jlyt jlt
application/vnd.hp-pcl pcl
application/vnd.hp-pclxl pclxl
# application/vnd.httphone
application/vnd.hydrostatix.sof-data sfd-hdstx
# application/vnd.hzn-3d-crossword
# application/vnd.ibm.afplinedata
# application/vnd.ibm.electronic-media
application/vnd.ibm.minipay mpy
application/vnd.ibm.modcap afp listafp list3820
application/vnd.ibm.rights-management irm
application/vnd.ibm.secure-container sc
application/vnd.iccprofile icc icm
application/vnd.igloader igl
application/vnd.immervision-ivp ivp
application/vnd.immervision-ivu ivu
# application/vnd.informedcontrol.rms+xml
# application/vnd.informix-visionary
# application/vnd.infotech.project
# application/vnd.infotech.project+xml
# application/vnd.innopath.wamp.notification
application/vnd.insors.igm igm
application/vnd.intercon.formnet xpw xpx
application/vnd.intergeo i2g
# application/vnd.intertrust.digibox
# application/vnd.intertrust.nncp
application/vnd.intu.qbo qbo
application/vnd.intu.qfx qfx
# application/vnd.iptc.g2.conceptitem+xml
# application/vnd.iptc.g2.knowledgeitem+xml
# application/vnd.iptc.g2.newsitem+xml
# application/vnd.iptc.g2.newsmessage+xml
# application/vnd.iptc.g2.packageitem+xml
# application/vnd.iptc.g2.planningitem+xml
application/vnd.ipunplugged.rcprofile rcprofile
application/vnd.irepository.package+xml irp
application/vnd.is-xpr xpr
application/vnd.isac.fcs fcs
application/vnd.jam jam
# application/vnd.japannet-directory-service
# application/vnd.japannet-jpnstore-wakeup
# application/vnd.japannet-payment-wakeup
# application/vnd.japannet-registration
# application/vnd.japannet-registration-wakeup
# application/vnd.japannet-setstore-wakeup
# application/vnd.japannet-verification
# application/vnd.japannet-verification-wakeup
application/vnd.jcp.javame.midlet-rms rms
application/vnd.jisp jisp
application/vnd.joost.joda-archive joda
application/vnd.kahootz ktz ktr
application/vnd.kde.karbon karbon
application/vnd.kde.kchart chrt
application/vnd.kde.kformula kfo
application/vnd.kde.kivio flw
application/vnd.kde.kontour kon
application/vnd.kde.kpresenter kpr kpt
application/vnd.kde.kspread ksp
application/vnd.kde.kword kwd kwt
application/vnd.kenameaapp htke
application/vnd.kidspiration kia
application/vnd.kinar kne knp
application/vnd.koan skp skd skt skm
application/vnd.kodak-descriptor sse
application/vnd.las.las+xml lasxml
# application/vnd.liberty-request+xml
application/vnd.llamagraphics.life-balance.desktop lbd
application/vnd.llamagraphics.life-balance.exchange+xml lbe
application/vnd.lotus-1-2-3 123
application/vnd.lotus-approach apr
application/vnd.lotus-freelance pre
application/vnd.lotus-notes nsf
application/vnd.lotus-organizer org
application/vnd.lotus-screencam scm
application/vnd.lotus-wordpro lwp
application/vnd.macports.portpkg portpkg
# application/vnd.marlin.drm.actiontoken+xml
# application/vnd.marlin.drm.conftoken+xml
# application/vnd.marlin.drm.license+xml
# application/vnd.marlin.drm.mdcf
application/vnd.mcd mcd
application/vnd.medcalcdata mc1
application/vnd.mediastation.cdkey cdkey
# application/vnd.meridian-slingshot
application/vnd.mfer mwf
application/vnd.mfmp mfm
application/vnd.micrografx.flo flo
application/vnd.micrografx.igx igx
application/vnd.mif mif
# application/vnd.minisoft-hp3000-save
# application/vnd.mitsubishi.misty-guard.trustweb
application/vnd.mobius.daf daf
application/vnd.mobius.dis dis
application/vnd.mobius.mbk mbk
application/vnd.mobius.mqy mqy
application/vnd.mobius.msl msl
application/vnd.mobius.plc plc
application/vnd.mobius.txf txf
application/vnd.mophun.application mpn
application/vnd.mophun.certificate mpc
# application/vnd.motorola.flexsuite
# application/vnd.motorola.flexsuite.adsi
# application/vnd.motorola.flexsuite.fis
# application/vnd.motorola.flexsuite.gotap
# application/vnd.motorola.flexsuite.kmr
# application/vnd.motorola.flexsuite.ttc
# application/vnd.motorola.flexsuite.wem
# application/vnd.motorola.iprm
application/vnd.mozilla.xul+xml xul
application/vnd.ms-artgalry cil
# application/vnd.ms-asf
application/vnd.ms-cab-compressed cab
# application/vnd.ms-color.iccprofile
application/vnd.ms-excel xls xlm xla xlc xlt xlw
application/vnd.ms-excel.addin.macroenabled.12 xlam
application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb
application/vnd.ms-excel.sheet.macroenabled.12 xlsm
application/vnd.ms-excel.template.macroenabled.12 xltm
application/vnd.ms-fontobject eot
application/vnd.ms-htmlhelp chm
application/vnd.ms-ims ims
application/vnd.ms-lrm lrm
# application/vnd.ms-office.activex+xml
application/vnd.ms-officetheme thmx
# application/vnd.ms-opentype
# application/vnd.ms-package.obfuscated-opentype
application/vnd.ms-pki.seccat cat
application/vnd.ms-pki.stl stl
# application/vnd.ms-playready.initiator+xml
application/vnd.ms-powerpoint ppt pps pot
application/vnd.ms-powerpoint.addin.macroenabled.12 ppam
application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm
application/vnd.ms-powerpoint.slide.macroenabled.12 sldm
application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm
application/vnd.ms-powerpoint.template.macroenabled.12 potm
# application/vnd.ms-printing.printticket+xml
application/vnd.ms-project mpp mpt
# application/vnd.ms-tnef
# application/vnd.ms-wmdrm.lic-chlg-req
# application/vnd.ms-wmdrm.lic-resp
# application/vnd.ms-wmdrm.meter-chlg-req
# application/vnd.ms-wmdrm.meter-resp
application/vnd.ms-word.document.macroenabled.12 docm
application/vnd.ms-word.template.macroenabled.12 dotm
application/vnd.ms-works wps wks wcm wdb
application/vnd.ms-wpl wpl
application/vnd.ms-xpsdocument xps
application/vnd.mseq mseq
# application/vnd.msign
# application/vnd.multiad.creator
# application/vnd.multiad.creator.cif
# application/vnd.music-niff
application/vnd.musician mus
application/vnd.muvee.style msty
application/vnd.mynfc taglet
# application/vnd.ncd.control
# application/vnd.ncd.reference
# application/vnd.nervana
# application/vnd.netfpx
application/vnd.neurolanguage.nlu nlu
application/vnd.nitf ntf nitf
application/vnd.noblenet-directory nnd
application/vnd.noblenet-sealer nns
application/vnd.noblenet-web nnw
# application/vnd.nokia.catalogs
# application/vnd.nokia.conml+wbxml
# application/vnd.nokia.conml+xml
# application/vnd.nokia.isds-radio-presets
# application/vnd.nokia.iptv.config+xml
# application/vnd.nokia.landmark+wbxml
# application/vnd.nokia.landmark+xml
# application/vnd.nokia.landmarkcollection+xml
# application/vnd.nokia.n-gage.ac+xml
application/vnd.nokia.n-gage.data ngdat
application/vnd.nokia.n-gage.symbian.install n-gage
# application/vnd.nokia.ncd
# application/vnd.nokia.pcd+wbxml
# application/vnd.nokia.pcd+xml
application/vnd.nokia.radio-preset rpst
application/vnd.nokia.radio-presets rpss
application/vnd.novadigm.edm edm
application/vnd.novadigm.edx edx
application/vnd.novadigm.ext ext
# application/vnd.ntt-local.file-transfer
# application/vnd.ntt-local.sip-ta_remote
# application/vnd.ntt-local.sip-ta_tcp_stream
application/vnd.oasis.opendocument.chart odc
application/vnd.oasis.opendocument.chart-template otc
application/vnd.oasis.opendocument.database odb
application/vnd.oasis.opendocument.formula odf
application/vnd.oasis.opendocument.formula-template odft
application/vnd.oasis.opendocument.graphics odg
application/vnd.oasis.opendocument.graphics-template otg
application/vnd.oasis.opendocument.image odi
application/vnd.oasis.opendocument.image-template oti
application/vnd.oasis.opendocument.presentation odp
application/vnd.oasis.opendocument.presentation-template otp
application/vnd.oasis.opendocument.spreadsheet ods
application/vnd.oasis.opendocument.spreadsheet-template ots
application/vnd.oasis.opendocument.text odt
application/vnd.oasis.opendocument.text-master odm
application/vnd.oasis.opendocument.text-template ott
application/vnd.oasis.opendocument.text-web oth
# application/vnd.obn
# application/vnd.oftn.l10n+json
# application/vnd.oipf.contentaccessdownload+xml
# application/vnd.oipf.contentaccessstreaming+xml
# application/vnd.oipf.cspg-hexbinary
# application/vnd.oipf.dae.svg+xml
# application/vnd.oipf.dae.xhtml+xml
# application/vnd.oipf.mippvcontrolmessage+xml
# application/vnd.oipf.pae.gem
# application/vnd.oipf.spdiscovery+xml
# application/vnd.oipf.spdlist+xml
# application/vnd.oipf.ueprofile+xml
# application/vnd.oipf.userprofile+xml
application/vnd.olpc-sugar xo
# application/vnd.oma-scws-config
# application/vnd.oma-scws-http-request
# application/vnd.oma-scws-http-response
# application/vnd.oma.bcast.associated-procedure-parameter+xml
# application/vnd.oma.bcast.drm-trigger+xml
# application/vnd.oma.bcast.imd+xml
# application/vnd.oma.bcast.ltkm
# application/vnd.oma.bcast.notification+xml
# application/vnd.oma.bcast.provisioningtrigger
# application/vnd.oma.bcast.sgboot
# application/vnd.oma.bcast.sgdd+xml
# application/vnd.oma.bcast.sgdu
# application/vnd.oma.bcast.simple-symbol-container
# application/vnd.oma.bcast.smartcard-trigger+xml
# application/vnd.oma.bcast.sprov+xml
# application/vnd.oma.bcast.stkm
# application/vnd.oma.cab-address-book+xml
# application/vnd.oma.cab-feature-handler+xml
# application/vnd.oma.cab-pcc+xml
# application/vnd.oma.cab-user-prefs+xml
# application/vnd.oma.dcd
# application/vnd.oma.dcdc
application/vnd.oma.dd2+xml dd2
# application/vnd.oma.drm.risd+xml
# application/vnd.oma.group-usage-list+xml
# application/vnd.oma.pal+xml
# application/vnd.oma.poc.detailed-progress-report+xml
# application/vnd.oma.poc.final-report+xml
# application/vnd.oma.poc.groups+xml
# application/vnd.oma.poc.invocation-descriptor+xml
# application/vnd.oma.poc.optimized-progress-report+xml
# application/vnd.oma.push
# application/vnd.oma.scidm.messages+xml
# application/vnd.oma.xcap-directory+xml
# application/vnd.omads-email+xml
# application/vnd.omads-file+xml
# application/vnd.omads-folder+xml
# application/vnd.omaloc-supl-init
application/vnd.openofficeorg.extension oxt
# application/vnd.openxmlformats-officedocument.custom-properties+xml
# application/vnd.openxmlformats-officedocument.customxmlproperties+xml
# application/vnd.openxmlformats-officedocument.drawing+xml
# application/vnd.openxmlformats-officedocument.drawingml.chart+xml
# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml
# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml
# application/vnd.openxmlformats-officedocument.extended-properties+xml
# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml
# application/vnd.openxmlformats-officedocument.presentationml.comments+xml
# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml
# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml
# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml
application/vnd.openxmlformats-officedocument.presentationml.presentation pptx
# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml
# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml
application/vnd.openxmlformats-officedocument.presentationml.slide sldx
# application/vnd.openxmlformats-officedocument.presentationml.slide+xml
# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml
# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml
application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx
# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml
# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml
# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml
# application/vnd.openxmlformats-officedocument.presentationml.tags+xml
application/vnd.openxmlformats-officedocument.presentationml.template potx
# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml
# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx
# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml
application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx
# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml
# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml
# application/vnd.openxmlformats-officedocument.theme+xml
# application/vnd.openxmlformats-officedocument.themeoverride+xml
# application/vnd.openxmlformats-officedocument.vmldrawing
# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml
application/vnd.openxmlformats-officedocument.wordprocessingml.document docx
# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml
application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx
# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml
# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml
# application/vnd.openxmlformats-package.core-properties+xml
# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml
# application/vnd.openxmlformats-package.relationships+xml
# application/vnd.quobject-quoxdocument
# application/vnd.osa.netdeploy
application/vnd.osgeo.mapguide.package mgp
# application/vnd.osgi.bundle
application/vnd.osgi.dp dp
application/vnd.osgi.subsystem esa
# application/vnd.otps.ct-kip+xml
application/vnd.palm pdb pqa oprc
# application/vnd.paos.xml
application/vnd.pawaafile paw
application/vnd.pg.format str
application/vnd.pg.osasli ei6
# application/vnd.piaccess.application-licence
application/vnd.picsel efif
application/vnd.pmi.widget wg
# application/vnd.poc.group-advertisement+xml
application/vnd.pocketlearn plf
application/vnd.powerbuilder6 pbd
# application/vnd.powerbuilder6-s
# application/vnd.powerbuilder7
# application/vnd.powerbuilder7-s
# application/vnd.powerbuilder75
# application/vnd.powerbuilder75-s
# application/vnd.preminet
application/vnd.previewsystems.box box
application/vnd.proteus.magazine mgz
application/vnd.publishare-delta-tree qps
application/vnd.pvi.ptid1 ptid
# application/vnd.pwg-multiplexed
# application/vnd.pwg-xhtml-print+xml
# application/vnd.qualcomm.brew-app-res
application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb
# application/vnd.radisys.moml+xml
# application/vnd.radisys.msml+xml
# application/vnd.radisys.msml-audit+xml
# application/vnd.radisys.msml-audit-conf+xml
# application/vnd.radisys.msml-audit-conn+xml
# application/vnd.radisys.msml-audit-dialog+xml
# application/vnd.radisys.msml-audit-stream+xml
# application/vnd.radisys.msml-conf+xml
# application/vnd.radisys.msml-dialog+xml
# application/vnd.radisys.msml-dialog-base+xml
# application/vnd.radisys.msml-dialog-fax-detect+xml
# application/vnd.radisys.msml-dialog-fax-sendrecv+xml
# application/vnd.radisys.msml-dialog-group+xml
# application/vnd.radisys.msml-dialog-speech+xml
# application/vnd.radisys.msml-dialog-transform+xml
# application/vnd.rainstor.data
# application/vnd.rapid
application/vnd.realvnc.bed bed
application/vnd.recordare.musicxml mxl
application/vnd.recordare.musicxml+xml musicxml
# application/vnd.renlearn.rlprint
application/vnd.rig.cryptonote cryptonote
application/vnd.rim.cod cod
application/vnd.rn-realmedia rm
application/vnd.rn-realmedia-vbr rmvb
application/vnd.route66.link66+xml link66
# application/vnd.rs-274x
# application/vnd.ruckus.download
# application/vnd.s3sms
application/vnd.sailingtracker.track st
# application/vnd.sbm.cid
# application/vnd.sbm.mid2
# application/vnd.scribus
# application/vnd.sealed.3df
# application/vnd.sealed.csf
# application/vnd.sealed.doc
# application/vnd.sealed.eml
# application/vnd.sealed.mht
# application/vnd.sealed.net
# application/vnd.sealed.ppt
# application/vnd.sealed.tiff
# application/vnd.sealed.xls
# application/vnd.sealedmedia.softseal.html
# application/vnd.sealedmedia.softseal.pdf
application/vnd.seemail see
application/vnd.sema sema
application/vnd.semd semd
application/vnd.semf semf
application/vnd.shana.informed.formdata ifm
application/vnd.shana.informed.formtemplate itp
application/vnd.shana.informed.interchange iif
application/vnd.shana.informed.package ipk
application/vnd.simtech-mindmapper twd twds
application/vnd.smaf mmf
# application/vnd.smart.notebook
application/vnd.smart.teacher teacher
# application/vnd.software602.filler.form+xml
# application/vnd.software602.filler.form-xml-zip
application/vnd.solent.sdkm+xml sdkm sdkd
application/vnd.spotfire.dxp dxp
application/vnd.spotfire.sfs sfs
# application/vnd.sss-cod
# application/vnd.sss-dtf
# application/vnd.sss-ntf
application/vnd.stardivision.calc sdc
application/vnd.stardivision.draw sda
application/vnd.stardivision.impress sdd
application/vnd.stardivision.math smf
application/vnd.stardivision.writer sdw vor
application/vnd.stardivision.writer-global sgl
application/vnd.stepmania.package smzip
application/vnd.stepmania.stepchart sm
# application/vnd.street-stream
application/vnd.sun.xml.calc sxc
application/vnd.sun.xml.calc.template stc
application/vnd.sun.xml.draw sxd
application/vnd.sun.xml.draw.template std
application/vnd.sun.xml.impress sxi
application/vnd.sun.xml.impress.template sti
application/vnd.sun.xml.math sxm
application/vnd.sun.xml.writer sxw
application/vnd.sun.xml.writer.global sxg
application/vnd.sun.xml.writer.template stw
# application/vnd.sun.wadl+xml
application/vnd.sus-calendar sus susp
application/vnd.svd svd
# application/vnd.swiftview-ics
application/vnd.symbian.install sis sisx
application/vnd.syncml+xml xsm
application/vnd.syncml.dm+wbxml bdm
application/vnd.syncml.dm+xml xdm
# application/vnd.syncml.dm.notification
# application/vnd.syncml.ds.notification
application/vnd.tao.intent-module-archive tao
application/vnd.tcpdump.pcap pcap cap dmp
application/vnd.tmobile-livetv tmo
application/vnd.trid.tpt tpt
application/vnd.triscape.mxs mxs
application/vnd.trueapp tra
# application/vnd.truedoc
# application/vnd.ubisoft.webplayer
application/vnd.ufdl ufd ufdl
application/vnd.uiq.theme utz
application/vnd.umajin umj
application/vnd.unity unityweb
application/vnd.uoml+xml uoml
# application/vnd.uplanet.alert
# application/vnd.uplanet.alert-wbxml
# application/vnd.uplanet.bearer-choice
# application/vnd.uplanet.bearer-choice-wbxml
# application/vnd.uplanet.cacheop
# application/vnd.uplanet.cacheop-wbxml
# application/vnd.uplanet.channel
# application/vnd.uplanet.channel-wbxml
# application/vnd.uplanet.list
# application/vnd.uplanet.list-wbxml
# application/vnd.uplanet.listcmd
# application/vnd.uplanet.listcmd-wbxml
# application/vnd.uplanet.signal
application/vnd.vcx vcx
# application/vnd.vd-study
# application/vnd.vectorworks
# application/vnd.verimatrix.vcas
# application/vnd.vidsoft.vidconference
application/vnd.visio vsd vst vss vsw
application/vnd.visionary vis
# application/vnd.vividence.scriptfile
application/vnd.vsf vsf
# application/vnd.wap.sic
# application/vnd.wap.slc
application/vnd.wap.wbxml wbxml
application/vnd.wap.wmlc wmlc
application/vnd.wap.wmlscriptc wmlsc
application/vnd.webturbo wtb
# application/vnd.wfa.wsc
# application/vnd.wmc
# application/vnd.wmf.bootstrap
# application/vnd.wolfram.mathematica
# application/vnd.wolfram.mathematica.package
application/vnd.wolfram.player nbp
application/vnd.wordperfect wpd
application/vnd.wqd wqd
# application/vnd.wrq-hp3000-labelled
application/vnd.wt.stf stf
# application/vnd.wv.csp+wbxml
# application/vnd.wv.csp+xml
# application/vnd.wv.ssp+xml
application/vnd.xara xar
application/vnd.xfdl xfdl
# application/vnd.xfdl.webform
# application/vnd.xmi+xml
# application/vnd.xmpie.cpkg
# application/vnd.xmpie.dpkg
# application/vnd.xmpie.plan
# application/vnd.xmpie.ppkg
# application/vnd.xmpie.xlim
application/vnd.yamaha.hv-dic hvd
application/vnd.yamaha.hv-script hvs
application/vnd.yamaha.hv-voice hvp
application/vnd.yamaha.openscoreformat osf
application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg
# application/vnd.yamaha.remote-setup
application/vnd.yamaha.smaf-audio saf
application/vnd.yamaha.smaf-phrase spf
# application/vnd.yamaha.through-ngn
# application/vnd.yamaha.tunnel-udpencap
application/vnd.yellowriver-custom-menu cmp
application/vnd.zul zir zirz
application/vnd.zzazz.deck+xml zaz
application/voicexml+xml vxml
# application/vq-rtcpxr
# application/watcherinfo+xml
# application/whoispp-query
# application/whoispp-response
application/widget wgt
application/winhlp hlp
# application/wita
# application/wordperfect5.1
application/wsdl+xml wsdl
application/wspolicy+xml wspolicy
application/x-7z-compressed 7z
application/x-abiword abw
application/x-ace-compressed ace
# application/x-amf
application/x-apple-diskimage dmg
application/x-authorware-bin aab x32 u32 vox
application/x-authorware-map aam
application/x-authorware-seg aas
application/x-bcpio bcpio
application/x-bittorrent torrent
application/x-blorb blb blorb
application/x-bzip bz
application/x-bzip2 bz2 boz
application/x-cbr cbr cba cbt cbz cb7
application/x-cdlink vcd
application/x-cfs-compressed cfs
application/x-chat chat
application/x-chess-pgn pgn
application/x-conference nsc
# application/x-compress
application/x-cpio cpio
application/x-csh csh
application/x-debian-package deb udeb
application/x-dgc-compressed dgc
application/x-director dir dcr dxr cst cct cxt w3d fgd swa
application/x-doom wad
application/x-dtbncx+xml ncx
application/x-dtbook+xml dtb
application/x-dtbresource+xml res
application/x-dvi dvi
application/x-envoy evy
application/x-eva eva
application/x-font-bdf bdf
# application/x-font-dos
# application/x-font-framemaker
application/x-font-ghostscript gsf
# application/x-font-libgrx
application/x-font-linux-psf psf
application/x-font-otf otf
application/x-font-pcf pcf
application/x-font-snf snf
# application/x-font-speedo
# application/x-font-sunos-news
application/x-font-ttf ttf ttc
application/x-font-type1 pfa pfb pfm afm
application/font-woff woff
# application/x-font-vfont
application/x-freearc arc
application/x-futuresplash spl
application/x-gca-compressed gca
application/x-glulx ulx
application/x-gnumeric gnumeric
application/x-gramps-xml gramps
application/x-gtar gtar
# application/x-gzip
application/x-hdf hdf
application/x-install-instructions install
application/x-iso9660-image iso
application/x-java-jnlp-file jnlp
application/x-latex latex
application/x-lzh-compressed lzh lha
application/x-mie mie
application/x-mobipocket-ebook prc mobi
application/x-ms-application application
application/x-ms-shortcut lnk
application/x-ms-wmd wmd
application/x-ms-wmz wmz
application/x-ms-xbap xbap
application/x-msaccess mdb
application/x-msbinder obd
application/x-mscardfile crd
application/x-msclip clp
application/x-msdownload exe dll com bat msi
application/x-msmediaview mvb m13 m14
application/x-msmetafile wmf wmz emf emz
application/x-msmoney mny
application/x-mspublisher pub
application/x-msschedule scd
application/x-msterminal trm
application/x-mswrite wri
application/x-netcdf nc cdf
application/x-nzb nzb
application/x-pkcs12 p12 pfx
application/x-pkcs7-certificates p7b spc
application/x-pkcs7-certreqresp p7r
application/x-rar-compressed rar
application/x-research-info-systems ris
application/x-sh sh
application/x-shar shar
application/x-shockwave-flash swf
application/x-silverlight-app xap
application/x-sql sql
application/x-stuffit sit
application/x-stuffitx sitx
application/x-subrip srt
application/x-sv4cpio sv4cpio
application/x-sv4crc sv4crc
application/x-t3vm-image t3
application/x-tads gam
application/x-tar tar
application/x-tcl tcl
application/x-tex tex
application/x-tex-tfm tfm
application/x-texinfo texinfo texi
application/x-tgif obj
application/x-ustar ustar
application/x-wais-source src
application/x-x509-ca-cert der crt
application/x-xfig fig
application/x-xliff+xml xlf
application/x-xpinstall xpi
application/x-xz xz
application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8
# application/x400-bp
application/xaml+xml xaml
# application/xcap-att+xml
# application/xcap-caps+xml
application/xcap-diff+xml xdf
# application/xcap-el+xml
# application/xcap-error+xml
# application/xcap-ns+xml
# application/xcon-conference-info-diff+xml
# application/xcon-conference-info+xml
application/xenc+xml xenc
application/xhtml+xml xhtml xht
# application/xhtml-voice+xml
application/xml xml xsl
application/xml-dtd dtd
# application/xml-external-parsed-entity
# application/xmpp+xml
application/xop+xml xop
application/xproc+xml xpl
application/xslt+xml xslt
application/xspf+xml xspf
application/xv+xml mxml xhvml xvml xvm
application/yang yang
application/yin+xml yin
application/zip zip
# audio/1d-interleaved-parityfec
# audio/32kadpcm
# audio/3gpp
# audio/3gpp2
# audio/ac3
audio/adpcm adp
# audio/amr
# audio/amr-wb
# audio/amr-wb+
# audio/asc
# audio/atrac-advanced-lossless
# audio/atrac-x
# audio/atrac3
audio/basic au snd
# audio/bv16
# audio/bv32
# audio/clearmode
# audio/cn
# audio/dat12
# audio/dls
# audio/dsr-es201108
# audio/dsr-es202050
# audio/dsr-es202211
# audio/dsr-es202212
# audio/dv
# audio/dvi4
# audio/eac3
# audio/evrc
# audio/evrc-qcp
# audio/evrc0
# audio/evrc1
# audio/evrcb
# audio/evrcb0
# audio/evrcb1
# audio/evrcwb
# audio/evrcwb0
# audio/evrcwb1
# audio/example
# audio/fwdred
# audio/g719
# audio/g722
# audio/g7221
# audio/g723
# audio/g726-16
# audio/g726-24
# audio/g726-32
# audio/g726-40
# audio/g728
# audio/g729
# audio/g7291
# audio/g729d
# audio/g729e
# audio/gsm
# audio/gsm-efr
# audio/gsm-hr-08
# audio/ilbc
# audio/ip-mr_v2.5
# audio/isac
# audio/l16
# audio/l20
# audio/l24
# audio/l8
# audio/lpc
audio/midi mid midi kar rmi
# audio/mobile-xmf
audio/mp4 mp4a
# audio/mp4a-latm
# audio/mpa
# audio/mpa-robust
audio/mpeg mpga mp2 mp2a mp3 m2a m3a
# audio/mpeg4-generic
# audio/musepack
audio/ogg oga ogg spx
# audio/opus
# audio/parityfec
# audio/pcma
# audio/pcma-wb
# audio/pcmu-wb
# audio/pcmu
# audio/prs.sid
# audio/qcelp
# audio/red
# audio/rtp-enc-aescm128
# audio/rtp-midi
# audio/rtx
audio/s3m s3m
audio/silk sil
# audio/smv
# audio/smv0
# audio/smv-qcp
# audio/sp-midi
# audio/speex
# audio/t140c
# audio/t38
# audio/telephone-event
# audio/tone
# audio/uemclip
# audio/ulpfec
# audio/vdvi
# audio/vmr-wb
# audio/vnd.3gpp.iufp
# audio/vnd.4sb
# audio/vnd.audiokoz
# audio/vnd.celp
# audio/vnd.cisco.nse
# audio/vnd.cmles.radio-events
# audio/vnd.cns.anp1
# audio/vnd.cns.inf1
audio/vnd.dece.audio uva uvva
audio/vnd.digital-winds eol
# audio/vnd.dlna.adts
# audio/vnd.dolby.heaac.1
# audio/vnd.dolby.heaac.2
# audio/vnd.dolby.mlp
# audio/vnd.dolby.mps
# audio/vnd.dolby.pl2
# audio/vnd.dolby.pl2x
# audio/vnd.dolby.pl2z
# audio/vnd.dolby.pulse.1
audio/vnd.dra dra
audio/vnd.dts dts
audio/vnd.dts.hd dtshd
# audio/vnd.dvb.file
# audio/vnd.everad.plj
# audio/vnd.hns.audio
audio/vnd.lucent.voice lvp
audio/vnd.ms-playready.media.pya pya
# audio/vnd.nokia.mobile-xmf
# audio/vnd.nortel.vbk
audio/vnd.nuera.ecelp4800 ecelp4800
audio/vnd.nuera.ecelp7470 ecelp7470
audio/vnd.nuera.ecelp9600 ecelp9600
# audio/vnd.octel.sbc
# audio/vnd.qcelp
# audio/vnd.rhetorex.32kadpcm
audio/vnd.rip rip
# audio/vnd.sealedmedia.softseal.mpeg
# audio/vnd.vmx.cvsd
# audio/vorbis
# audio/vorbis-config
audio/webm weba
audio/x-aac aac
audio/x-aiff aif aiff aifc
audio/x-caf caf
audio/x-flac flac
audio/x-matroska mka
audio/x-mpegurl m3u
audio/x-ms-wax wax
audio/x-ms-wma wma
audio/x-pn-realaudio ram ra
audio/x-pn-realaudio-plugin rmp
# audio/x-tta
audio/x-wav wav
audio/xm xm
chemical/x-cdx cdx
chemical/x-cif cif
chemical/x-cmdf cmdf
chemical/x-cml cml
chemical/x-csml csml
# chemical/x-pdb
chemical/x-xyz xyz
image/bmp bmp
image/cgm cgm
# image/example
# image/fits
image/g3fax g3
image/gif gif
image/ief ief
# image/jp2
image/jpeg jpeg jpg jpe
# image/jpm
# image/jpx
image/ktx ktx
# image/naplps
image/png png
image/prs.btif btif
# image/prs.pti
image/sgi sgi
image/svg+xml svg svgz
# image/t38
image/tiff tiff tif
# image/tiff-fx
image/vnd.adobe.photoshop psd
# image/vnd.cns.inf2
image/vnd.dece.graphic uvi uvvi uvg uvvg
image/vnd.dvb.subtitle sub
image/vnd.djvu djvu djv
image/vnd.dwg dwg
image/vnd.dxf dxf
image/vnd.fastbidsheet fbs
image/vnd.fpx fpx
image/vnd.fst fst
image/vnd.fujixerox.edmics-mmr mmr
image/vnd.fujixerox.edmics-rlc rlc
# image/vnd.globalgraphics.pgb
# image/vnd.microsoft.icon
# image/vnd.mix
image/vnd.ms-modi mdi
image/vnd.ms-photo wdp
image/vnd.net-fpx npx
# image/vnd.radiance
# image/vnd.sealed.png
# image/vnd.sealedmedia.softseal.gif
# image/vnd.sealedmedia.softseal.jpg
# image/vnd.svf
image/vnd.wap.wbmp wbmp
image/vnd.xiff xif
image/webp webp
image/x-3ds 3ds
image/x-cmu-raster ras
image/x-cmx cmx
image/x-freehand fh fhc fh4 fh5 fh7
image/x-icon ico
image/x-mrsid-image sid
image/x-pcx pcx
image/x-pict pic pct
image/x-portable-anymap pnm
image/x-portable-bitmap pbm
image/x-portable-graymap pgm
image/x-portable-pixmap ppm
image/x-rgb rgb
image/x-tga tga
image/x-xbitmap xbm
image/x-xpixmap xpm
image/x-xwindowdump xwd
# message/cpim
# message/delivery-status
# message/disposition-notification
# message/example
# message/external-body
# message/feedback-report
# message/global
# message/global-delivery-status
# message/global-disposition-notification
# message/global-headers
# message/http
# message/imdn+xml
# message/news
# message/partial
message/rfc822 eml mime
# message/s-http
# message/sip
# message/sipfrag
# message/tracking-status
# message/vnd.si.simp
# model/example
model/iges igs iges
model/mesh msh mesh silo
model/vnd.collada+xml dae
model/vnd.dwf dwf
# model/vnd.flatland.3dml
model/vnd.gdl gdl
# model/vnd.gs-gdl
# model/vnd.gs.gdl
model/vnd.gtw gtw
# model/vnd.moml+xml
model/vnd.mts mts
# model/vnd.parasolid.transmit.binary
# model/vnd.parasolid.transmit.text
model/vnd.vtu vtu
model/vrml wrl vrml
model/x3d+binary x3db x3dbz
model/x3d+vrml x3dv x3dvz
model/x3d+xml x3d x3dz
# multipart/alternative
# multipart/appledouble
# multipart/byteranges
# multipart/digest
# multipart/encrypted
# multipart/example
# multipart/form-data
# multipart/header-set
# multipart/mixed
# multipart/parallel
# multipart/related
# multipart/report
# multipart/signed
# multipart/voice-message
# text/1d-interleaved-parityfec
text/cache-manifest appcache
text/calendar ics ifb
text/css css
text/csv csv
# text/directory
# text/dns
# text/ecmascript
# text/enriched
# text/example
# text/fwdred
text/html html htm
# text/javascript
text/n3 n3
# text/parityfec
text/plain txt text conf def list log in
# text/prs.fallenstein.rst
text/prs.lines.tag dsc
# text/vnd.radisys.msml-basic-layout
# text/red
# text/rfc822-headers
text/richtext rtx
# text/rtf
# text/rtp-enc-aescm128
# text/rtx
text/sgml sgml sgm
# text/t140
text/tab-separated-values tsv
text/troff t tr roff man me ms
text/turtle ttl
# text/ulpfec
text/uri-list uri uris urls
text/vcard vcard
# text/vnd.abc
text/vnd.curl curl
text/vnd.curl.dcurl dcurl
text/vnd.curl.scurl scurl
text/vnd.curl.mcurl mcurl
# text/vnd.dmclientscript
text/vnd.dvb.subtitle sub
# text/vnd.esmertec.theme-descriptor
text/vnd.fly fly
text/vnd.fmi.flexstor flx
text/vnd.graphviz gv
text/vnd.in3d.3dml 3dml
text/vnd.in3d.spot spot
# text/vnd.iptc.newsml
# text/vnd.iptc.nitf
# text/vnd.latex-z
# text/vnd.motorola.reflex
# text/vnd.ms-mediapackage
# text/vnd.net2phone.commcenter.command
# text/vnd.si.uricatalogue
text/vnd.sun.j2me.app-descriptor jad
# text/vnd.trolltech.linguist
# text/vnd.wap.si
# text/vnd.wap.sl
text/vnd.wap.wml wml
text/vnd.wap.wmlscript wmls
text/x-asm s asm
text/x-c c cc cxx cpp h hh dic
text/x-fortran f for f77 f90
text/x-java-source java
text/x-opml opml
text/x-pascal p pas
text/x-nfo nfo
text/x-setext etx
text/x-sfv sfv
text/x-uuencode uu
text/x-vcalendar vcs
text/x-vcard vcf
# text/xml
# text/xml-external-parsed-entity
# video/1d-interleaved-parityfec
video/3gpp 3gp
# video/3gpp-tt
video/3gpp2 3g2
# video/bmpeg
# video/bt656
# video/celb
# video/dv
# video/example
video/h261 h261
video/h263 h263
# video/h263-1998
# video/h263-2000
video/h264 h264
# video/h264-rcdo
# video/h264-svc
video/jpeg jpgv
# video/jpeg2000
video/jpm jpm jpgm
video/mj2 mj2 mjp2
# video/mp1s
# video/mp2p
# video/mp2t
video/mp4 mp4 mp4v mpg4
# video/mp4v-es
video/mpeg mpeg mpg mpe m1v m2v
# video/mpeg4-generic
# video/mpv
# video/nv
video/ogg ogv
# video/parityfec
# video/pointer
video/quicktime qt mov
# video/raw
# video/rtp-enc-aescm128
# video/rtx
# video/smpte292m
# video/ulpfec
# video/vc1
# video/vnd.cctv
video/vnd.dece.hd uvh uvvh
video/vnd.dece.mobile uvm uvvm
# video/vnd.dece.mp4
video/vnd.dece.pd uvp uvvp
video/vnd.dece.sd uvs uvvs
video/vnd.dece.video uvv uvvv
# video/vnd.directv.mpeg
# video/vnd.directv.mpeg-tts
# video/vnd.dlna.mpeg-tts
video/vnd.dvb.file dvb
video/vnd.fvt fvt
# video/vnd.hns.video
# video/vnd.iptvforum.1dparityfec-1010
# video/vnd.iptvforum.1dparityfec-2005
# video/vnd.iptvforum.2dparityfec-1010
# video/vnd.iptvforum.2dparityfec-2005
# video/vnd.iptvforum.ttsavc
# video/vnd.iptvforum.ttsmpeg2
# video/vnd.motorola.video
# video/vnd.motorola.videop
video/vnd.mpegurl mxu m4u
video/vnd.ms-playready.media.pyv pyv
# video/vnd.nokia.interleaved-multimedia
# video/vnd.nokia.videovoip
# video/vnd.objectvideo
# video/vnd.sealed.mpeg1
# video/vnd.sealed.mpeg4
# video/vnd.sealed.swf
# video/vnd.sealedmedia.softseal.mov
video/vnd.uvvu.mp4 uvu uvvu
video/vnd.vivo viv
video/webm webm
video/x-f4v f4v
video/x-fli fli
video/x-flv flv
video/x-m4v m4v
video/x-matroska mkv mk3d mks
video/x-mng mng
video/x-ms-asf asf asx
video/x-ms-vob vob
video/x-ms-wm wm
video/x-ms-wmv wmv
video/x-ms-wmx wmx
video/x-ms-wvx wvx
video/x-msvideo avi
video/x-sgi-movie movie
video/x-smv smv
x-conference/x-cooltalk ice
# What: WebVTT
# Why: To allow formats intended for marking up external text track resources.
# http://dev.w3.org/html5/webvtt/
# Added by: niftylettuce
text/vtt vtt
# What: Google Chrome Extension
# Why: To allow apps to (work) be served with the right content type header.
# http://codereview.chromium.org/2830017
# Added by: niftylettuce
application/x-chrome-extension crx
# What: HTC support
# Why: To properly render .htc files such as CSS3PIE
# Added by: niftylettuce
text/x-component htc
# What: HTML5 application cache manifes ('.manifest' extension)
# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps
# per https://developer.mozilla.org/en/offline_resources_in_firefox
# Added by: louisremi
text/cache-manifest manifest
# What: node binary buffer format
# Why: semi-standard extension w/in the node community
# Added by: tootallnate
application/octet-stream buffer
# What: The "protected" MP-4 formats used by iTunes.
# Why: Required for streaming music to browsers (?)
# Added by: broofa
application/mp4 m4p
audio/mp4 m4a
# What: Video format, Part of RFC1890
# Why: See https://github.com/bentomas/node-mime/pull/6
# Added by: mjrusso
video/MP2T ts
# What: EventSource mime type
# Why: mime type of Server-Sent Events stream
# http://www.w3.org/TR/eventsource/#text-event-stream
# Added by: francois2metz
text/event-stream event-stream
# What: Mozilla App manifest mime type
# Why: https://developer.mozilla.org/en/Apps/Manifest#Serving_manifests
# Added by: ednapiranha
application/x-web-app-manifest+json webapp
# What: Lua file types
# Why: Googling around shows de-facto consensus on these
# Added by: creationix (Issue #45)
text/x-lua lua
application/x-lua-bytecode luac
# What: Markdown files, as per http://daringfireball.net/projects/markdown/syntax
# Why: http://stackoverflow.com/questions/10701983/what-is-the-mime-type-for-markdown
# Added by: avoidwork
text/x-markdown markdown md mkd
# What: ini files
# Why: because they're just text files
# Added by: Matthew Kastor
text/plain ini
# What: DASH Adaptive Streaming manifest
# Why: https://developer.mozilla.org/en-US/docs/DASH_Adaptive_Streaming_for_HTML_5_Video
# Added by: eelcocramer
application/dash+xml mdp
# What: OpenType font files - http://www.microsoft.com/typography/otspec/
# Why: Browsers usually ignore the font MIME types and sniff the content,
# but Chrome, shows a warning if OpenType fonts aren't served with
# the `font/opentype` MIME type: http://i.imgur.com/8c5RN8M.png.
# Added by: alrra
font/opentype otf
{
"name": "type-is",
"description": "Infer the content type if a request",
"version": "1.1.0",
"author": {
"name": "Jonathan Ong",
"email": "[email protected]",
"url": "http://jongleberry.com"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/expressjs/type-is"
},
"dependencies": {
"mime": "~1.2.11"
},
"devDependencies": {
"mocha": "*",
"should": "*"
},
"scripts": {
"test": "mocha --require should --reporter spec --bail"
},
"readme": "# Type Is [![Build Status](https://travis-ci.org/expressjs/type-is.png)](https://travis-ci.org/expressjs/type-is)\n\nInfer the content type of a request. \nExtracted from [koa](https://github.com/koajs/koa) for general use.\n\nHere's an example body parser:\n\n```js\nvar is = require('type-is');\nvar parse = require('body');\nvar busboy = require('busboy');\n\nfunction bodyParser(req, res, next) {\n var hasRequestBody = 'content-type' in req.headers\n || 'transfer-encoding' in req.headers;\n if (!hasRequestBody) return next();\n \n switch (is(req, ['urlencoded', 'json', 'multipart'])) {\n case 'urlencoded':\n // parse urlencoded body\n break\n case 'json':\n // parse json body\n break\n case 'multipart':\n // parse multipart body\n break\n default:\n // 415 error code\n }\n}\n```\n\n## API\n\n### var type = is(request, types)\n\n```js\nvar is = require('type-is')\n\nhttp.createServer(function (req, res) {\n is(req, ['text/*'])\n})\n```\n\n`request` is the node HTTP request. `types` is an array of types. Each type can be:\n\n- An extension name such as `json`. This name will be returned if matched.\n- A mime type such as `application/json`.\n- A mime type with a wildcard such as `*/json` or `application/*`. The full mime type will be returned if matched\n\n`false` will be returned if no type matches.\n\nExamples:\n\n```js\n// req.headers.content-type = 'application/json'\nis(req, ['json']) // -> 'json'\nis(req, ['html', 'json']) // -> 'json'\nis(req, ['application/*']) // -> 'application/json'\nis(req, ['application/json']) // -> 'application/json'\nis(req, ['html']) // -> false\n```\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 Jonathan Ong [email protected]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n",
"readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/expressjs/type-is/issues"
},
"homepage": "https://github.com/expressjs/type-is",
"_id": "[email protected]",
"dist": {
"shasum": "a595b3f01c7851e8c33dcb39f5233c9a0378272b"
},
"_from": "type-is@~1.1.0",
"_resolved": "https://registry.npmjs.org/type-is/-/type-is-1.1.0.tgz"
}

Type Is Build Status

Infer the content type of a request. Extracted from koa for general use.

Here's an example body parser:

var is = require('type-is');
var parse = require('body');
var busboy = require('busboy');

function bodyParser(req, res, next) {
  var hasRequestBody = 'content-type' in req.headers
    || 'transfer-encoding' in req.headers;
  if (!hasRequestBody) return next();
  
  switch (is(req, ['urlencoded', 'json', 'multipart'])) {
    case 'urlencoded':
      // parse urlencoded body
      break
    case 'json':
      // parse json body
      break
    case 'multipart':
      // parse multipart body
      break
    default:
      // 415 error code
  }
}

API

var type = is(request, types)

var is = require('type-is')

http.createServer(function (req, res) {
  is(req, ['text/*'])
})

request is the node HTTP request. types is an array of types. Each type can be:

  • An extension name such as json. This name will be returned if matched.
  • A mime type such as application/json.
  • A mime type with a wildcard such as */json or application/*. The full mime type will be returned if matched

false will be returned if no type matches.

Examples:

// req.headers.content-type = 'application/json'
is(req, ['json']) // -> 'json'
is(req, ['html', 'json']) // -> 'json'
is(req, ['application/*']) // -> 'application/json'
is(req, ['application/json']) // -> 'application/json'
is(req, ['html']) // -> false

License

The MIT License (MIT)

Copyright (c) 2013 Jonathan Ong [email protected]

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.

language: "node_js"
node_js:
- "0.4"
- "0.6"
- "0.8"
- "0.10"
/**
* Merge object b with object a.
*
* var a = { foo: 'bar' }
* , b = { bar: 'baz' };
*
* merge(a, b);
* // => { foo: 'bar', bar: 'baz' }
*
* @param {Object} a
* @param {Object} b
* @return {Object}
* @api public
*/
exports = module.exports = function (a, b) {
if (a && b) {
for (var key in b) {
a[key] = b[key];
}
}
return a;
};
(The MIT License)
Copyright (c) 2013 Jared Hanson
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.
{
"name": "utils-merge",
"version": "1.0.0",
"description": "merge() utility function",
"keywords": [
"util"
],
"repository": {
"type": "git",
"url": "git://github.com/jaredhanson/utils-merge.git"
},
"bugs": {
"url": "http://github.com/jaredhanson/utils-merge/issues"
},
"author": {
"name": "Jared Hanson",
"email": "[email protected]",
"url": "http://www.jaredhanson.net/"
},
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/MIT"
}
],
"main": "./index",
"dependencies": {},
"devDependencies": {
"mocha": "1.x.x",
"chai": "1.x.x"
},
"scripts": {
"test": "mocha --reporter spec --require test/bootstrap/node test/*.test.js"
},
"engines": {
"node": ">= 0.4.0"
},
"readme": "# utils-merge\n\nMerges the properties from a source object into a destination object.\n\n## Install\n\n $ npm install utils-merge\n\n## Usage\n\n```javascript\nvar a = { foo: 'bar' }\n , b = { bar: 'baz' };\n\nmerge(a, b);\n// => { foo: 'bar', bar: 'baz' }\n```\n\n## Tests\n\n $ npm install\n $ npm test\n\n[![Build Status](https://secure.travis-ci.org/jaredhanson/utils-merge.png)](http://travis-ci.org/jaredhanson/utils-merge)\n\n## Credits\n\n - [Jared Hanson](http://github.com/jaredhanson)\n\n## License\n\n[The MIT License](http://opensource.org/licenses/MIT)\n\nCopyright (c) 2013 Jared Hanson <[http://jaredhanson.net/](http://jaredhanson.net/)>\n",
"readmeFilename": "README.md",
"homepage": "https://github.com/jaredhanson/utils-merge",
"_id": "[email protected]",
"_from": "[email protected]"
}

utils-merge

Merges the properties from a source object into a destination object.

Install

$ npm install utils-merge

Usage

var a = { foo: 'bar' }
  , b = { bar: 'baz' };

merge(a, b);
// => { foo: 'bar', bar: 'baz' }

Tests

$ npm install
$ npm test

Build Status

Credits

License

The MIT License

Copyright (c) 2013 Jared Hanson <http://jaredhanson.net/>

{
"name": "express",
"description": "Sinatra inspired web development framework",
"version": "4.2.0",
"author": {
"name": "TJ Holowaychuk",
"email": "[email protected]"
},
"contributors": [
{
"name": "TJ Holowaychuk",
"email": "[email protected]"
},
{
"name": "Aaron Heckmann",
"email": "[email protected]"
},
{
"name": "Ciaran Jessup",
"email": "[email protected]"
},
{
"name": "Douglas Christopher Wilson",
"email": "[email protected]"
},
{
"name": "Guillermo Rauch",
"email": "[email protected]"
},
{
"name": "Jonathan Ong",
"email": "[email protected]"
},
{
"name": "Roman Shtylman",
"email": "[email protected]"
}
],
"dependencies": {
"parseurl": "1.0.1",
"accepts": "1.0.1",
"type-is": "1.1.0",
"range-parser": "1.0.0",
"cookie": "0.1.2",
"buffer-crc32": "0.2.1",
"fresh": "0.2.2",
"methods": "1.0.0",
"send": "0.3.0",
"cookie-signature": "1.0.3",
"merge-descriptors": "0.0.2",
"utils-merge": "1.0.0",
"escape-html": "1.0.1",
"qs": "0.6.6",
"serve-static": "1.1.0",
"path-to-regexp": "0.1.2",
"debug": "0.8.1"
},
"devDependencies": {
"mocha": "~1.18.2",
"body-parser": "~1.1.2",
"connect-redis": "~2.0.0",
"ejs": "~1.0.0",
"jade": "~0.35.0",
"marked": "0.3.2",
"multiparty": "~3.2.4",
"hjs": "~0.0.6",
"should": "~3.3.1",
"supertest": "~0.12.0",
"method-override": "1.0.0",
"cookie-parser": "1.0.1",
"express-session": "1.0.4",
"morgan": "1.0.1",
"vhost": "1.0.0"
},
"keywords": [
"express",
"framework",
"sinatra",
"web",
"rest",
"restful",
"router",
"app",
"api"
],
"repository": {
"type": "git",
"url": "git://github.com/visionmedia/express"
},
"scripts": {
"prepublish": "npm prune",
"test": "make test"
},
"engines": {
"node": ">= 0.10.0"
},
"license": "MIT",
"readme": "[![express logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](http://expressjs.com/)\n\n Fast, unopinionated, minimalist web framework for [node](http://nodejs.org).\n\n [![Build Status](https://travis-ci.org/visionmedia/express.svg?branch=master)](https://travis-ci.org/visionmedia/express) [![Gittip](http://img.shields.io/gittip/visionmedia.svg)](https://www.gittip.com/visionmedia/) [![NPM version](https://badge.fury.io/js/express.svg)](http://badge.fury.io/js/express)\n\n```js\nvar express = require('express');\nvar app = express();\n\napp.get('/', function(req, res){\n res.send('Hello World');\n});\n\napp.listen(3000);\n```\n\n**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/visionmedia/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/visionmedia/express/wiki/New-features-in-4.x).\n\n## Installation\n\n $ npm install express\n\n## Quick Start\n\n The quickest way to get started with express is to utilize the executable [`express(1)`](http://github.com/expressjs/generator) to generate an application as shown below:\n \n Install the executable. The executable's major version will match Express's:\n \n $ npm install -g express-generator@3\n\n Create the app:\n\n $ express /tmp/foo && cd /tmp/foo\n\n Install dependencies:\n\n $ npm install\n\n Start the server:\n\n $ npm start\n\n## Features\n\n * Robust routing\n * HTTP helpers (redirection, caching, etc)\n * View system supporting 14+ template engines\n * Content negotiation\n * Focus on high performance\n * Executable for generating applications quickly\n * High test coverage\n\n## Philosophy\n\n The Express philosophy is to provide small, robust tooling for HTTP servers, making\n it a great solution for single page applications, web sites, hybrids, or public\n HTTP APIs.\n\n Express does not force you to use any specific ORM or template engine. With support for over\n 14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js),\n you can quickly craft your perfect framework.\n\n## More Information\n\n * [Website and Documentation](http://expressjs.com/) stored at [visionmedia/expressjs.com](https://github.com/visionmedia/expressjs.com)\n * Join #express on freenode\n * [Google Group](http://groups.google.com/group/express-js) for discussion\n * Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) and [defunctzombie](https://twitter.com/defunctzombie) on twitter for updates\n * Visit the [Wiki](http://github.com/visionmedia/express/wiki)\n * [Русскоязычная документация](http://jsman.ru/express/)\n * Run express examples [online](https://runnable.com/express)\n\n## Viewing Examples\n\nClone the Express repo, then install the dev dependencies to install all the example / test suite dependencies:\n\n $ git clone git://github.com/visionmedia/express.git --depth 1\n $ cd express\n $ npm install\n\nThen run whichever tests you want:\n\n $ node examples/content-negotiation\n\nYou can also view live examples here:\n\n<a href=\"https://runnable.com/express\" target=\"_blank\"><img src=\"https://runnable.com/external/styles/assets/runnablebtn.png\" style=\"width:67px;height:25px;\"></a>\n\n## Running Tests\n\nTo run the test suite, first invoke the following command within the repo, installing the development dependencies:\n\n $ npm install\n\nThen run the tests:\n\n $ make test\n\n## Contributors\n \n Author: [TJ Holowaychuk](http://github.com/visionmedia) \n Lead Maintainer: [Roman Shtylman](https://github.com/defunctzombie) \n Contributors: https://github.com/visionmedia/express/graphs/contributors \n\n## License\n\nMIT\n",
"readmeFilename": "Readme.md",
"bugs": {
"url": "https://github.com/visionmedia/express/issues"
},
"homepage": "https://github.com/visionmedia/express",
"_id": "[email protected]",
"_from": "express@~4.2.0"
}

express logo

Fast, unopinionated, minimalist web framework for node.

Build Status Gittip NPM version

var express = require('express');
var app = express();

app.get('/', function(req, res){
  res.send('Hello World');
});

app.listen(3000);

PROTIP Be sure to read Migrating from 3.x to 4.x as well as New features in 4.x.

Installation

$ npm install express

Quick Start

The quickest way to get started with express is to utilize the executable express(1) to generate an application as shown below:

Install the executable. The executable's major version will match Express's:

$ npm install -g express-generator@3

Create the app:

$ express /tmp/foo && cd /tmp/foo

Install dependencies:

$ npm install

Start the server:

$ npm start

Features

  • Robust routing
  • HTTP helpers (redirection, caching, etc)
  • View system supporting 14+ template engines
  • Content negotiation
  • Focus on high performance
  • Executable for generating applications quickly
  • High test coverage

Philosophy

The Express philosophy is to provide small, robust tooling for HTTP servers, making it a great solution for single page applications, web sites, hybrids, or public HTTP APIs.

Express does not force you to use any specific ORM or template engine. With support for over 14 template engines via Consolidate.js, you can quickly craft your perfect framework.

More Information

Viewing Examples

Clone the Express repo, then install the dev dependencies to install all the example / test suite dependencies:

$ git clone git://github.com/visionmedia/express.git --depth 1
$ cd express
$ npm install

Then run whichever tests you want:

$ node examples/content-negotiation

You can also view live examples here:

Running Tests

To run the test suite, first invoke the following command within the repo, installing the development dependencies:

$ npm install

Then run the tests:

$ make test

Contributors

Author: TJ Holowaychuk
Lead Maintainer: Roman Shtylman
Contributors: https://github.com/visionmedia/express/graphs/contributors

License

MIT

test
support
benchmarks
examples
lib-cov
coverage
.gitmodules
.travis.yml
History.md
Makefile
test/
support/
benchmarks/
examples/
#!/usr/bin/env node
/**
* Module dependencies.
*/
var fs = require('fs')
, program = require('commander')
, path = require('path')
, basename = path.basename
, dirname = path.dirname
, resolve = path.resolve
, exists = fs.existsSync || path.existsSync
, join = path.join
, monocle = require('monocle')()
, mkdirp = require('mkdirp')
, jade = require('../');
// jade options
var options = {};
// options
program
.version(require('../package.json').version)
.usage('[options] [dir|file ...]')
.option('-O, --obj <str>', 'javascript options object')
.option('-o, --out <dir>', 'output the compiled html to <dir>')
.option('-p, --path <path>', 'filename used to resolve includes')
.option('-P, --pretty', 'compile pretty html output')
.option('-c, --client', 'compile function for client-side runtime.js')
.option('-D, --no-debug', 'compile without debugging (smaller functions)')
.option('-w, --watch', 'watch files for changes and automatically re-render')
program.on('--help', function () {
console.log(' Examples:');
console.log('');
console.log(' # translate jade the templates dir');
console.log(' $ jade templates');
console.log('');
console.log(' # create {foo,bar}.html');
console.log(' $ jade {foo,bar}.jade');
console.log('');
console.log(' # jade over stdio');
console.log(' $ jade < my.jade > my.html');
console.log('');
console.log(' # jade over stdio');
console.log(' $ echo \'h1 Jade!\' | jade');
console.log('');
console.log(' # foo, bar dirs rendering to /tmp');
console.log(' $ jade foo bar --out /tmp ');
console.log('');
});
program.parse(process.argv);
// options given, parse them
if (program.obj) {
if (exists(program.obj)) {
options = JSON.parse(fs.readFileSync(program.obj));
} else {
options = eval('(' + program.obj + ')');
}
}
// --filename
if (program.path) options.filename = program.path;
// --no-debug
options.compileDebug = program.debug;
// --client
options.client = program.client;
// --pretty
options.pretty = program.pretty;
// --watch
options.watch = program.watch;
// left-over args are file paths
var files = program.args;
// compile files
if (files.length) {
console.log();
files.forEach(renderFile);
if (options.watch) {
monocle.watchFiles({
files: files,
listener: function (file) {
renderFile(file.absolutePath);
}
});
}
process.on('exit', function () {
console.log();
});
// stdio
} else {
stdin();
}
/**
* Compile from stdin.
*/
function stdin() {
var buf = '';
process.stdin.setEncoding('utf8');
process.stdin.on('data', function (chunk) {
buf += chunk;
});
process.stdin.on('end', function () {
var output;
if (options.client) {
output = jade.compileClient(buf, options);
} else {
var fn = jade.compile(buf, options);
var output = fn(options);
}
process.stdout.write(output);
}).resume();
process.on('SIGINT', function () {
process.stdout.write('\n');
process.stdin.emit('end');
process.stdout.write('\n');
process.exit();
})
}
/**
* Process the given path, compiling the jade files found.
* Always walk the subdirectories.
*/
function renderFile(path) {
var re = /\.jade$/;
fs.lstat(path, function (err, stat) {
if (err) throw err;
// Found jade file
if (stat.isFile() && re.test(path)) {
fs.readFile(path, 'utf8', function (err, str) {
if (err) throw err;
options.filename = path;
var fn = options.client ? jade.compileClient(str, options) : jade.compile(str, options);
var extname = options.client ? '.js' : '.html';
path = path.replace(re, extname);
if (program.out) path = join(program.out, basename(path));
var dir = resolve(dirname(path));
mkdirp(dir, 0755, function (err) {
if (err) throw err;
try {
var output = options.client ? fn : fn(options);
fs.writeFile(path, output, function (err) {
if (err) throw err;
console.log(' \033[90mrendered \033[36m%s\033[0m', path);
});
} catch (e) {
if (options.watch) {
console.error(e.stack || e.message || e);
} else {
throw e
}
}
});
});
// Found directory
} else if (stat.isDirectory()) {
fs.readdir(path, function (err, files) {
if (err) throw err;
files.map(function (filename) {
return path + '/' + filename;
}).forEach(renderFile);
});
}
});
}
{
"name": "jade",
"repo": "visionmedia/jade",
"description": "Jade template runtime",
"version": "1.3.1",
"keywords": [
"template"
],
"dependencies": {},
"development": {},
"license": "MIT",
"scripts": [
"lib/runtime.js"
],
"main": "lib/runtime.js"
}
module.exports = require('./lib/jade');
## Syntax ### Tags

A tag is simply a leading word:

html

for example is converted to <html></html>

tags can also have ids:

div#container

which would render <div id="container"></div>

how about some classes?

div.user-details

renders <div class="user-details"></div>

multiple classes? and an id? sure:

div#foo.bar.baz

renders <div id="foo" class="bar baz"></div>

div div div sure is annoying, how about:

#foo
.bar

which is syntactic sugar for what we have already been doing, and outputs:

<div id="foo"></div><div class="bar"></div>
### Tag Text

Simply place some content after the tag:

p wahoo!

renders <p>wahoo!</p>.

well cool, but how about large bodies of text:

p
  | foo bar baz
  | rawr rawr
  | super cool
  | go jade go

renders <p>foo bar baz rawr.....</p>

interpolation? yup! both types of text can utilize interpolation, if we passed { name: 'tj', email: '[email protected]' } to the compiled function we can do the following:

#user #{name} &lt;#{email}&gt;

outputs <div id="user">tj &lt;[email protected]&gt;</div>

Actually want #{} for some reason? escape it!

p \#{something}

now we have <p>#{something}</p>

We can also utilize the unescaped variant !{html}, so the following will result in a literal script tag:

- var html = "<script></script>"
| !{html}

Nested tags that also contain text can optionally use a text block:

label
  | Username:
  input(name='user[name]')

or immediate tag text:

label Username:
  input(name='user[name]')

As an alternative, we may use a trailing . to indicate a text block, for example:

p.
  foo asdf
  asdf
   asdfasdfaf
   asdf
  asd.

outputs:

<p>foo asdf
asdf
  asdfasdfaf
  asdf
asd.
</p>

This however differs from a trailing . followed by a space, which although is ignored by the Jade parser, tells Jade that this period is a literal:

p .

outputs:

<p>.</p>

It should be noted that text blocks should be doubled escaped. For example if you desire the following output.

<p>foo\bar</p>

use:

p.
  foo\\bar
### Comments

Single line comments currently look the same as JavaScript comments, aka // and must be placed on their own line:

// just some paragraphs
p foo
p bar

would output

<!-- just some paragraphs -->
<p>foo</p>
<p>bar</p>

Jade also supports unbuffered comments, by simply adding a hyphen:

//- will not output within markup
p foo
p bar

outputting

<p>foo</p>
<p>bar</p>
### Block Comments

A block comment is legal as well:

body
  //
    #content
      h1 Example

outputting

<body>
  <!--
  <div id="content">
    <h1>Example</h1>
  </div>
  -->
</body>

Jade supports conditional-comments as well, for example:

head
  //if lt IE 8
    script(src='/ie-sucks.js')

outputs:

<head>
  <!--[if lt IE 8]>
  <script src="/ie-sucks.js"></script>
  <![endif]-->
</head>
### Nesting

Jade supports nesting to define the tags in a natural way:

ul
  li.first
    a(href='#') foo
  li
    a(href='#') bar
  li.last
    a(href='#') baz
### Block Expansion

Block expansion allows you to create terse single-line nested tags, the following example is equivalent to the nesting example above.

ul
  li.first: a(href='#') foo
  li: a(href='#') bar
  li.last: a(href='#') baz
### Case

The case statement takes the following form:

html
  body
    friends = 10
    case friends
      when 0
        p you have no friends
      when 1
        p you have a friend
      default
        p you have #{friends} friends

Block expansion may also be used:

friends = 5

html
  body
    case friends
      when 0: p you have no friends
      when 1: p you have a friend
      default: p you have #{friends} friends
### Attributes

Jade currently supports ( and ) as attribute delimiters.

a(href='/login', title='View login page') Login

When a value is undefined or null the attribute is not added, so this is fine, it will not compile something="null".

div(something=null)

Boolean attributes are also supported:

input(type="checkbox", checked)

Boolean attributes with code will only output the attribute when true:

input(type="checkbox", checked=someValue)

Multiple lines work too:

input(type='checkbox',
  name='agreement',
  checked)

Multiple lines without the comma work fine:

input(type='checkbox'
  name='agreement'
  checked)

Funky whitespace? fine:

input(
  type='checkbox'
  name='agreement'
  checked)

Colons work:

rss(xmlns:atom="atom")

Suppose we have the user local { id: 12, name: 'tobi' } and we wish to create an anchor tag with href pointing to "/user/12" we could use regular javascript concatenation:

a(href='/user/' + user.id)= user.name

or we could use jade's interpolation, which I added because everyone using Ruby or CoffeeScript seems to think this is legal js..:

a(href='/user/#{user.id}')= user.name

The class attribute is special-cased when an array is given, allowing you to pass an array such as bodyClasses = ['user', 'authenticated'] directly:

body(class=bodyClasses)
### HTML

Inline html is fine, we can use the pipe syntax to write arbitrary text, in this case some html:

html
  body
    | <h1>Title</h1>
    | <p>foo bar baz</p>

Or we can use the trailing . to indicate to Jade that we only want text in this block, allowing us to omit the pipes:

html
  body.
    <h1>Title</h1>
    <p>foo bar baz</p>

Both of these examples yield the same result:

<html><body><h1>Title</h1>
<p>foo bar baz</p>
</body></html>

The same rule applies for anywhere you can have text in jade, raw html is fine:

html
  body
    h1 User <em>#{name}</em>
### Doctypes

To add a doctype simply use !!!, or doctype followed by an optional value:

!!!

or

doctype

Will output the html 5 doctype, however:

!!! transitional

Will output the transitional doctype.

Doctypes are case-insensitive, so the following are equivalent:

doctype Basic
doctype basic

it's also possible to simply pass a doctype literal:

doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"

yielding:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN">

Below are the doctypes defined by default, which can easily be extended:

var doctypes = exports.doctypes = {
  '5': '<!DOCTYPE html>',
  'default': '<!DOCTYPE html>',
  'xml': '<?xml version="1.0" encoding="utf-8" ?>',
  'transitional': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
  'strict': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
  'frameset': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
  '1.1': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
  'basic': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
  'mobile': '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">'
};

To alter the default simply change:

jade.doctypes.default = 'whatever you want';
## Filters

Filters are prefixed with :, for example :markdown and pass the following block of text to an arbitrary function for processing. View the features at the top of this document for available filters.

body
  :markdown
    Woah! jade _and_ markdown, very **cool**
    we can even link to [stuff](http://google.com)

Renders:

<body><p>Woah! jade <em>and</em> markdown, very <strong>cool</strong> we can even link to <a href="http://google.com">stuff</a></p></body>
## Code

Jade currently supports three classifications of executable code. The first is prefixed by -, and is not buffered:

- var foo = 'bar';

This can be used for conditionals, or iteration:

- for (var key in obj)
  p= obj[key]

Due to Jade's buffering techniques the following is valid as well:

- if (foo)
  ul
    li yay
    li foo
    li worked
- else
  p oh no! didnt work

Hell, even verbose iteration:

- if (items.length)
  ul
    - items.forEach(function(item){
      li= item
    - })

Anything you want!

Next up we have escaped buffered code, which is used to buffer a return value, which is prefixed by =:

- var foo = 'bar'
= foo
h1= foo

Which outputs bar<h1>bar</h1>. Code buffered by = is escaped by default for security, however to output unescaped return values you may use !=:

p!= aVarContainingMoreHTML

Jade also has designer-friendly variants, making the literal JavaScript more expressive and declarative. For example the following assignments are equivalent, and the expression is still regular javascript:

- var foo = 'foo ' + 'bar'
foo = 'foo ' + 'bar'

Likewise Jade has first-class if, else if, else, until, while, unless among others, however you must remember that the expressions are still regular javascript:

if foo == 'bar'
  ul
    li yay
    li foo
    li worked
else
  p oh no! didnt work
## Iteration

Along with vanilla JavaScript Jade also supports a subset of constructs that allow you to create more designer-friendly templates, one of these constructs is each, taking the form:

each VAL[, KEY] in OBJ

An example iterating over an array:

- var items = ["one", "two", "three"]
each item in items
  li= item

outputs:

<li>one</li>
<li>two</li>
<li>three</li>

iterating an array with index:

items = ["one", "two", "three"]
each item, i in items
  li #{item}: #{i}

outputs:

<li>one: 0</li>
<li>two: 1</li>
<li>three: 2</li>

iterating an object's keys and values:

obj = { foo: 'bar' }
each val, key in obj
  li #{key}: #{val}

would output <li>foo: bar</li>

Internally Jade converts these statements to regular JavaScript loops such as users.forEach(function(user){, so lexical scope and nesting applies as it would with regular JavaScript:

each user in users
  each role in user.roles
    li= role

You may also use for if you prefer:

for user in users
  for role in user.roles
    li= role
## Conditionals

Jade conditionals are equivalent to those using the code (-) prefix, however allow you to ditch parenthesis to become more designer friendly, however keep in mind the expression given is regular JavaScript:

for user in users
  if user.role == 'admin'
    p #{user.name} is an admin
  else
    p= user.name

is equivalent to the following using vanilla JavaScript literals:

for user in users
  - if (user.role == 'admin')
    p #{user.name} is an admin
  - else
    p= user.name

Jade also provides unless which is equivalent to if (!(expr)):

for user in users
  unless user.isAnonymous
    p
      | Click to view
      a(href='/users/' + user.id)= user.name
## Template inheritance

Jade supports template inheritance via the block and extends keywords. A block is simply a "block" of Jade that may be replaced within a child template, this process is recursive. To activate template inheritance in Express 2.x you must add: app.set('view options', { layout: false });.

Jade blocks can provide default content if desired, however optional as shown below by block scripts, block content, and block foot.

html
  head
    title My Site - #{title}
    block scripts
      script(src='/jquery.js')
  body
    block content
    block foot
      #footer
        p some footer content

Now to extend the layout, simply create a new file and use the extends directive as shown below, giving the path (with or without the .jade extension). You may now define one or more blocks that will override the parent block content, note that here the foot block is not redefined and will output "some footer content".

extends layout

block scripts
  script(src='/jquery.js')
  script(src='/pets.js')

block content
  h1= title
  each pet in pets
    include pet

It's also possible to override a block to provide additional blocks, as shown in the following example where content now exposes a sidebar and primary block for overriding, or the child template could override content all together.

extends regular-layout

block content
  .sidebar
    block sidebar
      p nothing
  .primary
    block primary
      p nothing
## Block append / prepend

Jade allows you to replace (default), prepend, or append blocks. Suppose for example you have default scripts in a "head" block that you wish to utilize on every page, you might do this:

html
  head
    block head
      script(src='/vendor/jquery.js')
      script(src='/vendor/caustic.js')
  body
    block content

Now suppose you have a page of your application for a JavaScript game, you want some game related scripts as well as these defaults, you can simply append the block:

extends layout

block append head
  script(src='/vendor/three.js')
  script(src='/game.js')

When using block append or block prepend the block is optional:

extends layout

append head
  script(src='/vendor/three.js')
  script(src='/game.js')
## Includes

Includes allow you to statically include chunks of Jade, or other content like css, or html which lives in separate files. The classical example is including a header and footer. Suppose we have the following directory structure:

./layout.jade
./includes/
  ./head.jade
  ./foot.jade

and the following layout.jade:

html
  include includes/head
  body
    h1 My Site
    p Welcome to my super amazing site.
    include includes/foot

both includes includes/head and includes/foot are read relative to the filename option given to layout.jade, which should be an absolute path to this file, however Express does this for you. Include then parses these files, and injects the AST produced to render what you would expect:

<html>
  <head>
    <title>My Site</title>
    <script src="/javascripts/jquery.js">
    </script><script src="/javascripts/app.js"></script>
  </head>
  <body>
    <h1>My Site</h1>
    <p>Welcome to my super lame site.</p>
    <div id="footer">
      <p>Copyright>(c) foobar</p>
    </div>
  </body>
</html>

As mentioned include can be used to include other content such as html or css. By providing an explicit filter name with include:, Jade will read that file in, apply the filter, and insert that content into the output.

html
  head
    //- css and js have simple filters that wrap them in
        <style> and <script> tags, respectively
    include stylesheet.css
    include script.js
  body
    //- use the "markdown" filter to convert Markdown to HTML
    include:markdown introduction.markdown
    //- html files have no filter and are included verbatim
    include content.html

Include directives may also accept a block, in which case the the given block will be appended to the last block defined in the file. For example if head.jade contains:

head
  script(src='/jquery.js')

We may append values by providing a block to include head as shown below, adding the two scripts.

html
  include head
    script(src='/foo.js')
    script(src='/bar.js')
  body
    h1 test

You may also yield within an included template, allowing you to explicitly mark where the block given to include will be placed. Suppose for example you wish to prepend scripts rather than append, you might do the following:

head
  yield
  script(src='/jquery.js')
  script(src='/jquery.ui.js')

Since included Jade is parsed and literally merges the AST, lexically scoped variables function as if the included Jade was written right in the same file. This means include may be used as sort of partial, for example suppose we have user.jade which utilizes a user variable.

h1= user.name
p= user.occupation

We could then simply include user while iterating users, and since the user variable is already defined within the loop the included template will have access to it.

users = [{ name: 'Tobi', occupation: 'Ferret' }]

each user in users
  .user
    include user

yielding:

<div class="user">
  <h1>Tobi</h1>
  <p>Ferret</p>
</div>

If we wanted to expose a different variable name as user since user.jade references that name, we could simply define a new variable as shown here with user = person:

each person in users
  .user
    user = person
    include user
## Mixins

Mixins are converted to regular JavaScript functions in the compiled template that Jade constructs. Mixins may take arguments, though not required:

mixin list
  ul
    li foo
    li bar
    li baz

Utilizing a mixin without args looks similar, just without a block:

h2 Groceries
mixin list

Mixins may take one or more arguments as well, the arguments are regular javascripts expressions, so for example the following:

mixin pets(pets)
  ul.pets
    - each pet in pets
      li= pet

mixin profile(user)
  .user
    h2= user.name
    mixin pets(user.pets)

Would yield something similar to the following html:

<div class="user">
  <h2>tj</h2>
  <ul class="pets">
    <li>tobi</li>
    <li>loki</li>
    <li>jane</li>
    <li>manny</li>
  </ul>
</div>
## Generated Output

Suppose we have the following Jade:

- var title = 'yay'
h1.title #{title}
p Just an example

When the compileDebug option is not explicitly false, Jade will compile the function instrumented with __.lineno = n;, which in the event of an exception is passed to rethrow() which constructs a useful message relative to the initial Jade input.

function anonymous(locals) {
  var __ = { lineno: 1, input: "- var title = 'yay'\nh1.title #{title}\np Just an example", filename: "testing/test.js" };
  var rethrow = jade.rethrow;
  try {
    var attrs = jade.attrs, escape = jade.escape;
    var buf = [];
    with (locals || {}) {
      var interp;
      __.lineno = 1;
       var title = 'yay'
      __.lineno = 2;
      buf.push('<h1');
      buf.push(attrs({ "class": ('title') }));
      buf.push('>');
      buf.push('' + escape((interp = title) == null ? '' : interp) + '');
      buf.push('</h1>');
      __.lineno = 3;
      buf.push('<p>');
      buf.push('Just an example');
      buf.push('</p>');
    }
    return buf.join("");
  } catch (err) {
    rethrow(err, __.input, __.filename, __.lineno);
  }
}

When the compileDebug option is explicitly false, this instrumentation is stripped, which is very helpful for light-weight client-side templates. Combining Jade's options with the ./runtime.js file in this repo allows you to toString() compiled templates and avoid running the entire Jade library on the client, increasing performance, and decreasing the amount of JavaScript required.

function anonymous(locals) {
  var attrs = jade.attrs, escape = jade.escape;
  var buf = [];
  with (locals || {}) {
    var interp;
    var title = 'yay'
    buf.push('<h1');
    buf.push(attrs({ "class": ('title') }));
    buf.push('>');
    buf.push('' + escape((interp = title) == null ? '' : interp) + '');
    buf.push('</h1>');
    buf.push('<p>');
    buf.push('Just an example');
    buf.push('</p>');
  }
  return buf.join("");
}
(The MIT License)
Copyright (c) 2009-2014 TJ Holowaychuk <[email protected]>
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.

Jade - template engine

Full documentation is at jade-lang.com

Jade is a high performance template engine heavily influenced by Haml and implemented with JavaScript for node. For discussion join the Google Group.

You can test drive Jade online here.

Build Status Dependency Status NPM version

Installation

via npm:

$ npm install jade

Syntax

Jade is a clean, whitespace sensitive syntax for writing html. Here is a simple example:

doctype html
html(lang="en")
  head
    title= pageTitle
    script(type='text/javascript').
      if (foo) bar(1 + 5)
  body
    h1 Jade - node template engine
    #container.col
      if youAreUsingJade
        p You are amazing
      else
        p Get on it!
      p.
        Jade is a terse and simple templating language with a
        strong focus on performance and powerful features.

becomes

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Jade</title>
    <script type="text/javascript">
      if (foo) bar(1 + 5)
    </script>
  </head>
  <body>
    <h1>Jade - node template engine</h1>
    <div id="container" class="col">
      <p>You are amazing</p>
      <p>Jade is a terse and simple templating language with a strong focus on performance and powerful features.</p>
    </div>
  </body>
</html>

The official jade tutorial is a great place to start. While that (and the syntax documentation) is being finished, you can view some of the old documentation here and here

API

For full API, see jade-lang.com/api

var jade = require('jade');

// compile
var fn = jade.compile('string of jade', options);
var html = fn(locals);

// render
var html = jade.render('string of jade', merge(options, locals));

// renderFile
var html = jade.renderFile('filename.jade', merge(options, locals));

Options

  • filename Used in exceptions, and required when using includes
  • compileDebug When false no debug instrumentation is compiled
  • pretty Add pretty-indentation whitespace to output (false by default)

Browser Support

The latest version of jade can be download for the browser in standalone form from here. It only supports the very latest browsers though, and is a large file. It is recommended that you pre-compile your jade templates to JavaScript and then just use the runtime.js library on the client.

To compile a template for use on the client using the command line, do:

$ jade --client --no-debug filename.jade

which will produce filename.js containing the compiled template.

Command Line

After installing the latest version of node, install with:

$ npm install jade -g

and run with

$ jade --help

Additional Resources

Tutorials:

Implementations in other languages:

Other:

License

MIT

Jade - 模板引擎

Jade 是一个高性能的模板引擎,它深受 Haml 影响,它是用 JavaScript 实现的, 并且可以供 Node 使用.

翻译: 草依山

声明

从 Jade v0.31.0 开始放弃了对于 <script><style> 标签的平文本支持. 这个问题你可以在 <script> <style> 标签后加上 . 来解决.

希望这一点能让 Jade 对新手更友好, 同时也不影响到 Jade 本身的能力或者导致过度冗长.

如果你有大量的文件需要转换你可以用下 fix-jade 尝试自动完成这个过程.

Test drive

你可以在网上试玩 Jade.

README 目录

## 特性
  • 客户端支持
  • 代码高可读
  • 灵活的缩进
  • 块展开
  • Mixins
  • 静态包含
  • 属性改写
  • 安全,默认代码是转义的
  • 运行时和编译时上下文错误报告
  • 命令行下编译jade模板
  • HTML5 模式 (使用 !!! 5 文档类型)
  • 在内存中缓存(可选)
  • 合并动态和静态标签类
  • 可以通过 filters 修改树
  • 模板继承
  • 原生支持 Express JS
  • 通过 each 枚举对象、数组甚至是不能枚举的对象
  • 块注释
  • 没有前缀的标签
  • AST Filters
  • 过滤器
  • Emacs Mode
  • Vim Syntax
  • TextMate Bundle
  • Coda/SubEtha syntax Mode
  • Screencasts
  • html2jade converter
## 其它实现 ## 安装

通过 NPM:

npm install jade
## 浏览器支持

把 Jade 编译为一个可供浏览器使用的单文件,只需要简单的执行:

$ make jade.js

如果你已经安装了 uglifyjs (npm install uglify-js),你可以执行下面的命令它会生成所有的文件。其实每一个正式版本里都帮你做了这事。

make jade.min.js

默认情况下,为了方便调试Jade会把模板组织成带有形如 __.lineno = 3 的行号的形式。 在浏览器里使用的时候,你可以通过传递一个选项 { compileDebug: false } 来去掉这个。 下面的模板

p Hello #{name}

会被翻译成下面的函数:

function anonymous(locals, attrs, escape, rethrow) {
  var buf = [];
  with (locals || {}) {
    var interp;
    buf.push('\n<p>Hello ' + escape((interp = name) == null ? '' : interp) + '\n</p>');
  }
  return buf.join("");
}

通过使用 Jade 的 ./runtime.js你可以在浏览器使用这些预编译的模板而不需要使用 Jade, 你只需要使用 runtime.js 里的工具函数, 它们会放在 jade.attrs, jade.escape 这些里。 把选项 { client: true } 传递给 jade.compile(), Jade 会把这些帮助函数的引用放在jade.attrs, jade.escape.

function anonymous(locals, attrs, escape, rethrow) {
  var attrs = jade.attrs, escape = jade.escape, rethrow = jade.rethrow;
  var buf = [];
  with (locals || {}) {
    var interp;
    buf.push('\n<p>Hello ' + escape((interp = name) == null ? '' : interp) + '\n</p>');
  }
  return buf.join("");
}
## 公开 API
var jade = require('jade');

// Compile a function
var fn = jade.compile('string of jade', options);
fn(locals);
  • self 使用 self 命名空间来持有本地变量. (默认为 false)
  • locals 本地变量对象
  • filename 异常发生时使用,includes 时必需
  • debug 输出 token 和翻译后的函数体
  • compiler 替换掉 jade 默认的编译器
  • compileDebug false的时候调试的结构不会被输出
  • pretty 为输出加上了漂亮的空格缩进 (默认为 false)
## 语法 ### 行结束标志

CRLFCR 会在编译之前被转换为 LF

### 标签

标签就是一个简单的单词:

html

它会被转换为 <html></html>

标签也是可以有 id 的:

div#container

它会被转换为 <div id="container"></div>

怎么加 class 呢?

div.user-details

转换为 <div class="user-details"></div>

多个 class 和 id? 也是可以搞定的:

div#foo.bar.baz

转换为 <div id="foo" class="bar baz"></div>

不停的 div div div 很讨厌啊 , 可以这样:

#foo
.bar

这个算是我们的语法糖,它已经被很好的支持了,上面的会输出:

<div id="foo"></div><div class="bar"></div>
### 标签文本

只需要简单的把内容放在标签之后:

p wahoo!

它会被渲染为 <p>wahoo!</p>.

很帅吧,但是大段的文本怎么办呢:

p
  | foo bar baz
  | rawr rawr
  | super cool
  | go jade go

渲染为 <p>foo bar baz rawr.....</p>

怎么和数据结合起来? 所有类型的文本展示都可以和数据结合起来,如果我们把 { name: 'tj', email: '[email protected]' } 传给编译函数,下面是模板上的写法:

#user #{name} &lt;#{email}&gt;

它会被渲染为 <div id="user">tj &lt;[email protected]&gt;</div>

当就是要输出 #{} 的时候怎么办? 转义一下!

p \#{something}

它会输出 <p>#{something}</p>

同样可以使用非转义的变量 !{html}, 下面的模板将直接输出一个 <script> 标签:

- var html = "<script></script>"
| !{html}

内联标签同样可以使用文本块来包含文本:

label
  | Username:
  input(name='user[name]')

或者直接使用标签文本:

label Username:
  input(name='user[name]')

包含文本的标签,比如 <script>, <style>, 和 <textarea> 不需要前缀 | 字符, 比如:

html
  head
    title Example
    script
      if (foo) {
        bar();
      } else {
        baz();
      }

这里还有一种选择,可以使用 . 来开始一段文本块,比如:

p.
  foo asdf
  asdf
   asdfasdfaf
   asdf
  asd.

会被渲染为:

<p>foo asdf
asdf
  asdfasdfaf
  asdf
asd
.
</p>

这和带一个空格的 . 是不一样的, 带空格的会被 Jade 的解析器忽略,当作一个普通的文字:

p .

渲染为:

<p>.</p>

需要注意的是文本块需要两次转义。比如想要输出下面的文本:

</p>foo\bar</p>

使用:

p.
  foo\\bar
### 注释

单行注释和 JavaScript 里是一样的,通过 // 来开始,并且必须单独一行:

// just some paragraphs
p foo
p bar

渲染为:

<!-- just some paragraphs -->
<p>foo</p>
<p>bar</p>

Jade 同样支持不输出的注释,加一个短横线就行了:

//- will not output within markup
p foo
p bar

渲染为:

<p>foo</p>
<p>bar</p>
### 块注释

块注释也是支持的:

body
  //
    #content
      h1 Example

渲染为:

<body>
  <!--
  <div id="content">
    <h1>Example</h1>
  </div>
  -->
</body>

Jade 同样很好的支持了条件注释:

body
  //if IE
    a(href='http://www.mozilla.com/en-US/firefox/') Get Firefox

渲染为:

<body>
  <!--[if IE]>
    <a href="http://www.mozilla.com/en-US/firefox/">Get Firefox</a>
  <![endif]-->
</body>
### 内联

Jade 支持以自然的方式定义标签嵌套:

ul
  li.first
    a(href='#') foo
  li
    a(href='#') bar
  li.last
    a(href='#') baz
### 块展开

块展开可以帮助你在一行内创建嵌套的标签,下面的例子和上面的是一样的:

ul
  li.first: a(href='#') foo
  li: a(href='#') bar
  li.last: a(href='#') baz
### Case

case 表达式按下面这样的形式写:

html
  body
    friends = 10
    case friends
      when 0
        p you have no friends
      when 1
        p you have a friend
      default
        p you have #{friends} friends

块展开在这里也可以使用:

friends = 5

html
  body
    case friends
      when 0: p you have no friends
      when 1: p you have a friend
      default: p you have #{friends} friends
### 属性

Jade 现在支持使用 () 作为属性分隔符

a(href='/login', title='View login page') Login

当一个值是 undefined 或者 null 属性 会被加上, 所以呢,它不会编译出 'something="null"'.

div(something=null)

Boolean 属性也是支持的:

input(type="checkbox", checked)

使用代码的 Boolean 属性只有当属性为 true 时才会输出:

input(type="checkbox", checked=someValue)

多行同样也是可用的:

input(type='checkbox',
  name='agreement',
  checked)

多行的时候可以不加逗号:

input(type='checkbox'
  name='agreement'
  checked)

加点空格,格式好看一点?同样支持

input(
  type='checkbox'
  name='agreement'
  checked)

冒号也是支持的:

rss(xmlns:atom="atom")

假如我有一个 user 对象 { id: 12, name: 'tobi' } 我们希望创建一个指向 /user/12 的链接 href, 我们可以使用普通的 JavaScript 字符串连接,如下:

a(href='/user/' + user.id)= user.name

或者我们使用 Jade 的修改方式, 这个我想很多使用 Ruby 或者 CoffeeScript 的人会看起来像普通的 JS..:

a(href='/user/#{user.id}')= user.name

class 属性是一个特殊的属性,你可以直接传递一个数组,比如 bodyClasses = ['user', 'authenticated'] :

body(class=bodyClasses)
### HTML

内联的 HTML 是可以的,我们可以使用管道定义一段文本 :

html
  body
    | <h1>Title</h1>
    | <p>foo bar baz</p>

或者我们可以使用 . 来告诉 Jade 我们需要一段文本:

html
  body.
    <h1>Title</h1>
    <p>foo bar baz</p>

上面的两个例子都会渲染成相同的结果:

<html><body><h1>Title</h1>
<p>foo bar baz</p>
</body></html>

这条规则适应于在 Jade 里的任何文本:

html
  body
    h1 User <em>#{name}</em>
### Doctypes

添加文档类型只需要简单的使用 !!!, 或者 doctype 跟上下面的可选项:

!!!

会渲染出 transitional 文档类型, 或者:

!!! 5

!!! html

doctype html

Doctype 是大小写不敏感的, 所以下面两个是一样的:

doctype Basic
doctype basic

当然也是可以直接传递一段文档类型的文本:

doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"

渲染后:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN">

会输出 HTML5 文档类型. 下面的默认的文档类型,可以很简单的扩展:

var doctypes = exports.doctypes = {
  '5': '<!DOCTYPE html>',
  'xml': '<?xml version="1.0" encoding="utf-8" ?>',
  'default': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
  'transitional': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
  'strict': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
  'frameset': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
  '1.1': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
  'basic': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
  'mobile': '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">'
};

通过下面的代码可以很简单的改变默认的文档类型:

    jade.doctypes.default = 'whatever you want';
## 过滤器

过滤器前缀 :, 比如 :markdown 会把下面块里的文本交给专门的函数进行处理。查看顶部 特性 里有哪些可用的过滤器。

body
  :markdown
    Woah! jade _and_ markdown, very **cool**
    we can even link to [stuff](http://google.com)

渲染为:

<body><p>Woah! jade <em>and</em> markdown, very <strong>cool</strong> we can even link to <a href="http://google.com">stuff</a></p></body>
## 代码

Jade 目前支持三种类型的可执行代码。第一种是前缀 -, 这是不会被输出的:

- var foo = 'bar';

这可以用在条件语句或者循环中:

- for (var key in obj)
  p= obj[key]

由于 Jade 的缓存技术,下面的代码也是可以的:

- if (foo)
  ul
    li yay
    li foo
    li worked
- else
  p oh no! didnt work

哈哈,甚至是很长的循环也是可以的:

- if (items.length)
  ul
    - items.forEach(function(item){
      li= item
    - })

所以你想要的!

下一步我们要 转义 输出的代码,比如我们返回一个值,只要前缀一个 =

- var foo = 'bar'
= foo
h1= foo

它会渲染为 bar<h1>bar</h1>. 为了安全起见,使用 = 输出的代码默认是转义的,如果想直接输出不转义的值可以使用 !=

p!= aVarContainingMoreHTML

Jade 同样是设计师友好的,它可以使 JavaScript 更直接更富表现力。比如下面的赋值语句是相等的,同时表达式还是通常的 JavaScript:

- var foo = 'foo ' + 'bar'
foo = 'foo ' + 'bar'

Jade 会把 if, else if, else, until, while, unless 同别的优先对待, 但是你得记住它们还是普通的 JavaScript:

if foo == 'bar'
  ul
    li yay
    li foo
    li worked
else
  p oh no! didnt work  
## 循环

尽管已经支持 JavaScript 原生代码,Jade 还是支持了一些特殊的标签,它们可以让模板更加易于理解,其中之一就是 each, 这种形式:

each VAL[, KEY] in OBJ

一个遍历数组的例子 :

- var items = ["one", "two", "three"]
each item in items
  li= item

渲染为:

<li>one</li>
<li>two</li>
<li>three</li>

遍历一个数组同时带上索引:

items = ["one", "two", "three"]
each item, i in items
  li #{item}: #{i}

渲染为:

<li>one: 0</li>
<li>two: 1</li>
<li>three: 2</li>

遍历一个数组的键值:

obj = { foo: 'bar' }
each val, key in obj
  li #{key}: #{val}

将会渲染为:<li>foo: bar</li>

Jade 在内部会把这些语句转换成原生的 JavaScript 语句,就像使用 users.forEach(function(user){, 词法作用域和嵌套会像在普通的 JavaScript 中一样:

each user in users
  each role in user.roles
    li= role

如果你喜欢,也可以使用 for

for user in users
  for role in user.roles
    li= role
## 条件语句

Jade 条件语句和使用了(-) 前缀的 JavaScript 语句是一致的,然后它允许你不使用圆括号,这样会看上去对设计师更友好一点, 同时要在心里记住这个表达式渲染出的是 常规 JavaScript:

for user in users
  if user.role == 'admin'
    p #{user.name} is an admin
  else
    p= user.name

和下面的使用了常规 JavaScript 的代码是相等的:

for user in users
  - if (user.role == 'admin')
    p #{user.name} is an admin
  - else
    p= user.name

Jade 同时支持 unless, 这和 if (!(expr)) 是等价的:

for user in users
  unless user.isAnonymous
    p
      | Click to view
      a(href='/users/' + user.id)= user.name 
## 模板继承

Jade 支持通过 blockextends 关键字来实现模板继承。 一个块就是一个 Jade 的 block ,它将在子模板中实现,同时是支持递归的。

Jade 块如果没有内容,Jade 会添加默认内容,下面的代码默认会输出 block scripts, block content, 和 block foot.

html
  head
    h1 My Site - #{title}
    block scripts
      script(src='/jquery.js')
  body
    block content
    block foot
      #footer
        p some footer content

现在我们来继承这个布局,简单创建一个新文件,像下面那样直接使用 extends,给定路径(可以选择带 .jade 扩展名或者不带). 你可以定义一个或者更多的块来覆盖父级块内容, 注意到这里的 foot没有 定义,所以它还会输出父级的 "some footer content"。

extends extend-layout

block scripts
  script(src='/jquery.js')
  script(src='/pets.js')

block content
  h1= title
  each pet in pets
    include pet

同样可以在一个子块里添加块,就像下面实现的块 content 里又定义了两个可以被实现的块 sidebarprimary,或者子模板直接实现 content

extends regular-layout

block content
  .sidebar
    block sidebar
      p nothing
  .primary
    block primary
      p nothing

Jade允许你 替换 (默认)、 前置追加 blocks. 比如,假设你希望在 所有 页面的头部都加上默认的脚本,你可以这么做:

html
  head
    block head
      script(src='/vendor/jquery.js')
      script(src='/vendor/caustic.js')
  body
    block content

现在假设你有一个Javascript游戏的页面,你希望在默认的脚本之外添加一些游戏相关的脚本,你可以直接append上代码块:

extends layout

block append head
  script(src='/vendor/three.js')
  script(src='/game.js')

使用 block appendblock prependblock 是可选的:

extends layout

append head
  script(src='/vendor/three.js')
  script(src='/game.js')
## 包含

Includes 允许你静态包含一段 Jade, 或者别的存放在单个文件中的东西比如 CSS, HTML 非常常见的例子是包含头部和页脚。 假设我们有一个下面目录结构的文件夹:

./layout.jade
./includes/
  ./head.jade
  ./tail.jade

下面是 layout.jade 的内容:

html
  include includes/head  
  body
    h1 My Site
    p Welcome to my super amazing site.
    include includes/foot

这两个包含 includes/headincludes/foot 都会读取相对于给 layout.jade 参数filename 的路径的文件, 这是一个绝对路径,不用担心Express帮你搞定这些了。Include 会解析这些文件,并且插入到已经生成的语法树中,然后渲染为你期待的内容:

<html>
  <head>
    <title>My Site</title>
    <script src="/javascripts/jquery.js">
    </script><script src="/javascripts/app.js"></script>
  </head>
  <body>
    <h1>My Site</h1>
    <p>Welcome to my super lame site.</p>
    <div id="footer">
      <p>Copyright>(c) foobar</p>
    </div>
  </body>
</html>

前面已经提到,include 可以包含比如 HTML 或者 CSS 这样的内容。给定一个扩展名后,Jade 不会把这个文件当作一个 Jade 源代码,并且会把它当作一个普通文本包含进来:

html
  head
    //- css and js have simple filters that wrap them in
        <style> and <script> tags, respectively
    include stylesheet.css
    include script.js
  body
    //- "markdown" files will use the "markdown" filter
        to convert Markdown to HTML
    include introduction.markdown
    //- html files have no filter and are included verbatim
    include content.html

Include 也可以接受块内容,给定的块将会附加到包含文件 最后 的块里。 举个例子,head.jade 包含下面的内容:

head
  script(src='/jquery.js')

我们可以像下面给include head添加内容, 这里是添加两个脚本.

html
  include head
    script(src='/foo.js')
    script(src='/bar.js')
  body
    h1 test

在被包含的模板中,你也可以使用yield语句。yield语句允许你明确地标明include的代码块的放置位置。比如,假设你希望把代码块放在scripts之前,而不是附加在scripts之后:

head
  yield
  script(src='/jquery.js')
  script(src='/jquery.ui.js')

由于被包含的Jade会按字面解析并合并到AST中,词法范围的变量的效果和直接写在同一个文件中的相同。这就意味着include可以用作partial的替代,例如,假设我们有一个引用了user变量的user.jade`文件:

h1= user.name
p= user.occupation

接着,当我们迭代users的时候,只需简单地加上include user。因为在循环中user变量已经被定义了,被包含的模板可以访问它。

users = [{ name: 'Tobi', occupation: 'Ferret' }]

each user in users
  .user
    include user

以上代码会生成:

<div class="user">
  <h1>Tobi</h1>
  <p>Ferret</p>
</div>

user.jade引用了user变量,如果我们希望使用一个不同的变量user,那么我们可以直接定义一个新变量user = person,如下所示:

each person in users
  .user
    user = person
    include user
## Mixins

Mixins 在编译的模板里会被 Jade 转换为普通的 JavaScript 函数。 Mixins 可以还参数,但不是必需的:

mixin list
  ul
    li foo
    li bar
    li baz

使用不带参数的 mixin 看上去非常简单,在一个块外:

h2 Groceries
mixin list

Mixins 也可以带一个或者多个参数,参数就是普通的 JavaScript 表达式,比如下面的例子:

mixin pets(pets)
  ul.pets
    - each pet in pets
      li= pet

mixin profile(user)
  .user
    h2= user.name
    mixin pets(user.pets)

会输出像下面的 HTML:

<div class="user">
  <h2>tj</h2>
  <ul class="pets">
    <li>tobi</li>
    <li>loki</li>
    <li>jane</li>
    <li>manny</li>
  </ul>
</div>
## 产生输出

假设我们有下面的 Jade 源码:

- var title = 'yay'
h1.title #{title}
p Just an example

compileDebug 选项不是 false, Jade 会编译时会把函数里加上 __.lineno = n;, 这个参数会在编译出错时传递给 rethrow(), 而这个函数会在 Jade 初始输出时给出一个有用的错误信息。

function anonymous(locals) {
  var __ = { lineno: 1, input: "- var title = 'yay'\nh1.title #{title}\np Just an example", filename: "testing/test.js" };
  var rethrow = jade.rethrow;
  try {
    var attrs = jade.attrs, escape = jade.escape;
    var buf = [];
    with (locals || {}) {
      var interp;
      __.lineno = 1;
       var title = 'yay'
      __.lineno = 2;
      buf.push('<h1');
      buf.push(attrs({ "class": ('title') }));
      buf.push('>');
      buf.push('' + escape((interp = title) == null ? '' : interp) + '');
      buf.push('</h1>');
      __.lineno = 3;
      buf.push('<p>');
      buf.push('Just an example');
      buf.push('</p>');
    }
    return buf.join("");
  } catch (err) {
    rethrow(err, __.input, __.filename, __.lineno);
  }
}

compileDebug 参数是 false, 这个参数会被去掉,这样对于轻量级的浏览器端模板是非常有用的。结合 Jade 的参数和当前源码库里的 ./runtime.js 文件,你可以通过 toString() 来编译模板而不需要在浏览器端运行整个 Jade 库,这样可以提高性能,也可以减少载入的 JavaScript 数量。

function anonymous(locals) {
  var attrs = jade.attrs, escape = jade.escape;
  var buf = [];
  with (locals || {}) {
    var interp;
    var title = 'yay'
    buf.push('<h1');
    buf.push(attrs({ "class": ('title') }));
    buf.push('>');
    buf.push('' + escape((interp = title) == null ? '' : interp) + '');
    buf.push('</h1>');
    buf.push('<p>');
    buf.push('Just an example');
    buf.push('</p>');
  }
  return buf.join("");
}
## Makefile 的一个例子

通过执行 make, 下面的 Makefile 例子可以把 pages/*.jade 编译为 pages/*.html

JADE = $(shell find pages/*.jade)
HTML = $(JADE:.jade=.html)

all: $(HTML)
	
%.html: %.jade
	jade < $< --path $< > $@

clean:
	rm -f $(HTML)

.PHONY: clean

这个可以和 watch(1) 命令起来产生像下面的行为:

$ watch make
## 命令行的 Jade

使用: jade [options] [dir|file ...]

选项:

  -h, --help         输出帮助信息
  -v, --version      输出版本号
  -o, --out <dir>    输出编译后的 HTML 到 <dir>
  -O, --obj <str>    JavaScript 选项
  -p, --path <path>  在处理 stdio 时,查找包含文件时的查找路径
  -P, --pretty       格式化 HTML 输出
  -c, --client       编译浏览器端可用的 runtime.js
  -D, --no-debug     关闭编译的调试选项(函数会更小)
  -w, --watch        监视文件改变自动刷新编译结果

Examples:

  # 编译整个目录
  $ jade templates

  # 生成 {foo,bar}.html
  $ jade {foo,bar}.jade

  # 在标准IO下使用jade 
  $ jade < my.jade > my.html

  # 在标准IO下使用jade, 同时指定用于查找包含的文件
  $ jade < my.jade -p my.jade > my.html

  # 在标准IO下使用jade 
  $ echo "h1 Jade!" | jade

  # foo, bar 目录渲染到 /tmp
  $ jade foo bar --out /tmp 

注意: 从 v0.31.0-o 选项已经指向 --out, -O 相应做了交换

## 教程 ## License

(The MIT License)

Copyright (c) 2009-2010 TJ Holowaychuk <[email protected]>

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.

This file has been truncated, but you can view the full file.
!function (e) {
if ("object" == typeof exports)module.exports = e(); else if ("function" == typeof define && define.amd)define(e); else {
var f;
"undefined" != typeof window ? f = window : "undefined" != typeof global ? f = global : "undefined" != typeof self && (f = self), f.jade = e()
}
}(function () {
var define, module, exports;
return (function e(t, n, r) {
function s(o, u) {
if (!n[o]) {
if (!t[o]) {
var a = typeof require == "function" && require;
if (!u && a)return a(o, !0);
if (i)return i(o, !0);
throw new Error("Cannot find module '" + o + "'")
}
var f = n[o] = {exports: {}};
t[o][0].call(f.exports, function (e) {
var n = t[o][1][e];
return s(n ? n : e)
}, f, f.exports, e, t, n, r)
}
return n[o].exports
}
var i = typeof require == "function" && require;
for (var o = 0; o < r.length; o++)s(r[o]);
return s
})({1: [function (_dereq_, module, exports) {
'use strict';
var nodes = _dereq_('./nodes');
var filters = _dereq_('./filters');
var doctypes = _dereq_('./doctypes');
var runtime = _dereq_('./runtime');
var utils = _dereq_('./utils');
var selfClosing = _dereq_('./self-closing');
var parseJSExpression = _dereq_('character-parser').parseMax;
var constantinople = _dereq_('constantinople');
function isConstant(src) {
return constantinople(src, {jade: runtime, 'jade_interp': undefined});
}
function toConstant(src) {
return constantinople.toConstant(src, {jade: runtime, 'jade_interp': undefined});
}
function errorAtNode(node, error) {
error.line = node.line;
error.filename = node.filename;
return error;
}
/**
* Initialize `Compiler` with the given `node`.
*
* @param {Node} node
* @param {Object} options
* @api public
*/
var Compiler = module.exports = function Compiler(node, options) {
this.options = options = options || {};
this.node = node;
this.hasCompiledDoctype = false;
this.hasCompiledTag = false;
this.pp = options.pretty || false;
this.debug = false !== options.compileDebug;
this.indents = 0;
this.parentIndents = 0;
this.terse = false;
this.mixins = {};
this.dynamicMixins = false;
if (options.doctype) this.setDoctype(options.doctype);
};
/**
* Compiler prototype.
*/
Compiler.prototype = {
/**
* Compile parse tree to JavaScript.
*
* @api public
*/
compile: function () {
this.buf = [];
if (this.pp) this.buf.push("var jade_indent = [];");
this.lastBufferedIdx = -1;
this.visit(this.node);
if (!this.dynamicMixins) {
// if there are no dynamic mixins we can remove any un-used mixins
var mixinNames = Object.keys(this.mixins);
for (var i = 0; i < mixinNames.length; i++) {
var mixin = this.mixins[mixinNames[i]];
if (!mixin.used) {
for (var x = 0; x < mixin.instances.length; x++) {
for (var y = mixin.instances[x].start; y < mixin.instances[x].end; y++) {
this.buf[y] = '';
}
}
}
}
}
return this.buf.join('\n');
},
/**
* Sets the default doctype `name`. Sets terse mode to `true` when
* html 5 is used, causing self-closing tags to end with ">" vs "/>",
* and boolean attributes are not mirrored.
*
* @param {string} name
* @api public
*/
setDoctype: function (name) {
this.doctype = doctypes[name.toLowerCase()] || '<!DOCTYPE ' + name + '>';
this.terse = this.doctype.toLowerCase() == '<!doctype html>';
this.xml = 0 == this.doctype.indexOf('<?xml');
},
/**
* Buffer the given `str` exactly as is or with interpolation
*
* @param {String} str
* @param {Boolean} interpolate
* @api public
*/
buffer: function (str, interpolate) {
var self = this;
if (interpolate) {
var match = /(\\)?([#!]){((?:.|\n)*)$/.exec(str);
if (match) {
this.buffer(str.substr(0, match.index), false);
if (match[1]) { // escape
this.buffer(match[2] + '{', false);
this.buffer(match[3], true);
return;
} else {
var rest = match[3];
var range = parseJSExpression(rest);
var code = ('!' == match[2] ? '' : 'jade.escape') + "((jade_interp = " + range.src + ") == null ? '' : jade_interp)";
this.bufferExpression(code);
this.buffer(rest.substr(range.end + 1), true);
return;
}
}
}
str = JSON.stringify(str);
str = str.substr(1, str.length - 2);
if (this.lastBufferedIdx == this.buf.length) {
if (this.lastBufferedType === 'code') this.lastBuffered += ' + "';
this.lastBufferedType = 'text';
this.lastBuffered += str;
this.buf[this.lastBufferedIdx - 1] = 'buf.push(' + this.bufferStartChar + this.lastBuffered + '");'
} else {
this.buf.push('buf.push("' + str + '");');
this.lastBufferedType = 'text';
this.bufferStartChar = '"';
this.lastBuffered = str;
this.lastBufferedIdx = this.buf.length;
}
},
/**
* Buffer the given `src` so it is evaluated at run time
*
* @param {String} src
* @api public
*/
bufferExpression: function (src) {
if (isConstant(src)) {
return this.buffer(toConstant(src) + '', false)
}
if (this.lastBufferedIdx == this.buf.length) {
if (this.lastBufferedType === 'text') this.lastBuffered += '"';
this.lastBufferedType = 'code';
this.lastBuffered += ' + (' + src + ')';
this.buf[this.lastBufferedIdx - 1] = 'buf.push(' + this.bufferStartChar + this.lastBuffered + ');'
} else {
this.buf.push('buf.push(' + src + ');');
this.lastBufferedType = 'code';
this.bufferStartChar = '';
this.lastBuffered = '(' + src + ')';
this.lastBufferedIdx = this.buf.length;
}
},
/**
* Buffer an indent based on the current `indent`
* property and an additional `offset`.
*
* @param {Number} offset
* @param {Boolean} newline
* @api public
*/
prettyIndent: function (offset, newline) {
offset = offset || 0;
newline = newline ? '\n' : '';
this.buffer(newline + Array(this.indents + offset).join(' '));
if (this.parentIndents)
this.buf.push("buf.push.apply(buf, jade_indent);");
},
/**
* Visit `node`.
*
* @param {Node} node
* @api public
*/
visit: function (node) {
var debug = this.debug;
if (debug) {
this.buf.push('jade_debug.unshift({ lineno: ' + node.line
+ ', filename: ' + (node.filename
? JSON.stringify(node.filename)
: 'jade_debug[0].filename')
+ ' });');
}
// Massive hack to fix our context
// stack for - else[ if] etc
if (false === node.debug && this.debug) {
this.buf.pop();
this.buf.pop();
}
this.visitNode(node);
if (debug) this.buf.push('jade_debug.shift();');
},
/**
* Visit `node`.
*
* @param {Node} node
* @api public
*/
visitNode: function (node) {
return this['visit' + node.type](node);
},
/**
* Visit case `node`.
*
* @param {Literal} node
* @api public
*/
visitCase: function (node) {
var _ = this.withinCase;
this.withinCase = true;
this.buf.push('switch (' + node.expr + '){');
this.visit(node.block);
this.buf.push('}');
this.withinCase = _;
},
/**
* Visit when `node`.
*
* @param {Literal} node
* @api public
*/
visitWhen: function (node) {
if ('default' == node.expr) {
this.buf.push('default:');
} else {
this.buf.push('case ' + node.expr + ':');
}
if (node.block) {
this.visit(node.block);
this.buf.push(' break;');
}
},
/**
* Visit literal `node`.
*
* @param {Literal} node
* @api public
*/
visitLiteral: function (node) {
this.buffer(node.str);
},
/**
* Visit all nodes in `block`.
*
* @param {Block} block
* @api public
*/
visitBlock: function (block) {
var len = block.nodes.length
, escape = this.escape
, pp = this.pp
// Pretty print multi-line text
if (pp && len > 1 && !escape && block.nodes[0].isText && block.nodes[1].isText)
this.prettyIndent(1, true);
for (var i = 0; i < len; ++i) {
// Pretty print text
if (pp && i > 0 && !escape && block.nodes[i].isText && block.nodes[i - 1].isText)
this.prettyIndent(1, false);
this.visit(block.nodes[i]);
// Multiple text nodes are separated by newlines
if (block.nodes[i + 1] && block.nodes[i].isText && block.nodes[i + 1].isText)
this.buffer('\n');
}
},
/**
* Visit a mixin's `block` keyword.
*
* @param {MixinBlock} block
* @api public
*/
visitMixinBlock: function (block) {
if (this.pp) this.buf.push("jade_indent.push('" + Array(this.indents + 1).join(' ') + "');");
this.buf.push('block && block();');
if (this.pp) this.buf.push("jade_indent.pop();");
},
/**
* Visit `doctype`. Sets terse mode to `true` when html 5
* is used, causing self-closing tags to end with ">" vs "/>",
* and boolean attributes are not mirrored.
*
* @param {Doctype} doctype
* @api public
*/
visitDoctype: function (doctype) {
if (doctype && (doctype.val || !this.doctype)) {
this.setDoctype(doctype.val || 'default');
}
if (this.doctype) this.buffer(this.doctype);
this.hasCompiledDoctype = true;
},
/**
* Visit `mixin`, generating a function that
* may be called within the template.
*
* @param {Mixin} mixin
* @api public
*/
visitMixin: function (mixin) {
var name = 'jade_mixins[';
var args = mixin.args || '';
var block = mixin.block;
var attrs = mixin.attrs;
var attrsBlocks = mixin.attributeBlocks;
var pp = this.pp;
var dynamic = mixin.name[0] === '#';
var key = mixin.name;
if (dynamic) this.dynamicMixins = true;
name += (dynamic ? mixin.name.substr(2, mixin.name.length - 3) : '"' + mixin.name + '"') + ']';
this.mixins[key] = this.mixins[key] || {used: false, instances: []};
if (mixin.call) {
this.mixins[key].used = true;
if (pp) this.buf.push("jade_indent.push('" + Array(this.indents + 1).join(' ') + "');")
if (block || attrs.length || attrsBlocks.length) {
this.buf.push(name + '.call({');
if (block) {
this.buf.push('block: function(){');
// Render block with no indents, dynamically added when rendered
this.parentIndents++;
var _indents = this.indents;
this.indents = 0;
this.visit(mixin.block);
this.indents = _indents;
this.parentIndents--;
if (attrs.length || attrsBlocks.length) {
this.buf.push('},');
} else {
this.buf.push('}');
}
}
if (attrsBlocks.length) {
if (attrs.length) {
var val = this.attrs(attrs);
attrsBlocks.unshift(val);
}
this.buf.push('attributes: jade.merge([' + attrsBlocks.join(',') + '])');
} else if (attrs.length) {
var val = this.attrs(attrs);
this.buf.push('attributes: ' + val);
}
if (args) {
this.buf.push('}, ' + args + ');');
} else {
this.buf.push('});');
}
} else {
this.buf.push(name + '(' + args + ');');
}
if (pp) this.buf.push("jade_indent.pop();")
} else {
var mixin_start = this.buf.length;
this.buf.push(name + ' = function(' + args + '){');
this.buf.push('var block = (this && this.block), attributes = (this && this.attributes) || {};');
this.parentIndents++;
this.visit(block);
this.parentIndents--;
this.buf.push('};');
var mixin_end = this.buf.length;
this.mixins[key].instances.push({start: mixin_start, end: mixin_end});
}
},
/**
* Visit `tag` buffering tag markup, generating
* attributes, visiting the `tag`'s code and block.
*
* @param {Tag} tag
* @api public
*/
visitTag: function (tag) {
this.indents++;
var name = tag.name
, pp = this.pp
, self = this;
function bufferName() {
if (tag.buffer) self.bufferExpression(name);
else self.buffer(name);
}
if ('pre' == tag.name) this.escape = true;
if (!this.hasCompiledTag) {
if (!this.hasCompiledDoctype && 'html' == name) {
this.visitDoctype();
}
this.hasCompiledTag = true;
}
// pretty print
if (pp && !tag.isInline())
this.prettyIndent(0, true);
if (tag.selfClosing || (!this.xml && selfClosing.indexOf(tag.name) !== -1)) {
this.buffer('<');
bufferName();
this.visitAttributes(tag.attrs, tag.attributeBlocks);
this.terse
? this.buffer('>')
: this.buffer('/>');
// if it is non-empty throw an error
if (tag.block && !(tag.block.type === 'Block' && tag.block.nodes.length === 0) &&
tag.block.nodes.some(function (tag) {
return tag.type !== 'Text' || !/^\s*$/.test(tag.val)
})) {
throw errorAtNode(tag, new Error(name + ' is self closing and should not have content.'));
}
} else {
// Optimize attributes buffering
this.buffer('<');
bufferName();
this.visitAttributes(tag.attrs, tag.attributeBlocks);
this.buffer('>');
if (tag.code) this.visitCode(tag.code);
this.visit(tag.block);
// pretty print
if (pp && !tag.isInline() && 'pre' != tag.name && !tag.canInline())
this.prettyIndent(0, true);
this.buffer('</');
bufferName();
this.buffer('>');
}
if ('pre' == tag.name) this.escape = false;
this.indents--;
},
/**
* Visit `filter`, throwing when the filter does not exist.
*
* @param {Filter} filter
* @api public
*/
visitFilter: function (filter) {
var text = filter.block.nodes.map(
function (node) {
return node.val;
}
).join('\n');
filter.attrs.filename = this.options.filename;
try {
this.buffer(filters(filter.name, text, filter.attrs), true);
} catch (err) {
throw errorAtNode(filter, err);
}
},
/**
* Visit `text` node.
*
* @param {Text} text
* @api public
*/
visitText: function (text) {
this.buffer(text.val, true);
},
/**
* Visit a `comment`, only buffering when the buffer flag is set.
*
* @param {Comment} comment
* @api public
*/
visitComment: function (comment) {
if (!comment.buffer) return;
if (this.pp) this.prettyIndent(1, true);
this.buffer('<!--' + comment.val + '-->');
},
/**
* Visit a `BlockComment`.
*
* @param {Comment} comment
* @api public
*/
visitBlockComment: function (comment) {
if (!comment.buffer) return;
if (this.pp) this.prettyIndent(1, true);
this.buffer('<!--' + comment.val);
this.visit(comment.block);
if (this.pp) this.prettyIndent(1, true);
this.buffer('-->');
},
/**
* Visit `code`, respecting buffer / escape flags.
* If the code is followed by a block, wrap it in
* a self-calling function.
*
* @param {Code} code
* @api public
*/
visitCode: function (code) {
// Wrap code blocks with {}.
// we only wrap unbuffered code blocks ATM
// since they are usually flow control
// Buffer code
if (code.buffer) {
var val = code.val.trimLeft();
val = 'null == (jade_interp = ' + val + ') ? "" : jade_interp';
if (code.escape) val = 'jade.escape(' + val + ')';
this.bufferExpression(val);
} else {
this.buf.push(code.val);
}
// Block support
if (code.block) {
if (!code.buffer) this.buf.push('{');
this.visit(code.block);
if (!code.buffer) this.buf.push('}');
}
},
/**
* Visit `each` block.
*
* @param {Each} each
* @api public
*/
visitEach: function (each) {
this.buf.push(''
+ '// iterate ' + each.obj + '\n'
+ ';(function(){\n'
+ ' var $$obj = ' + each.obj + ';\n'
+ ' if (\'number\' == typeof $$obj.length) {\n');
if (each.alternative) {
this.buf.push(' if ($$obj.length) {');
}
this.buf.push(''
+ ' for (var ' + each.key + ' = 0, $$l = $$obj.length; ' + each.key + ' < $$l; ' + each.key + '++) {\n'
+ ' var ' + each.val + ' = $$obj[' + each.key + '];\n');
this.visit(each.block);
this.buf.push(' }\n');
if (each.alternative) {
this.buf.push(' } else {');
this.visit(each.alternative);
this.buf.push(' }');
}
this.buf.push(''
+ ' } else {\n'
+ ' var $$l = 0;\n'
+ ' for (var ' + each.key + ' in $$obj) {\n'
+ ' $$l++;'
+ ' var ' + each.val + ' = $$obj[' + each.key + '];\n');
this.visit(each.block);
this.buf.push(' }\n');
if (each.alternative) {
this.buf.push(' if ($$l === 0) {');
this.visit(each.alternative);
this.buf.push(' }');
}
this.buf.push(' }\n}).call(this);\n');
},
/**
* Visit `attrs`.
*
* @param {Array} attrs
* @api public
*/
visitAttributes: function (attrs, attributeBlocks) {
if (attributeBlocks.length) {
if (attrs.length) {
var val = this.attrs(attrs);
attributeBlocks.unshift(val);
}
this.bufferExpression('jade.attrs(jade.merge([' + attributeBlocks.join(',') + ']), ' + JSON.stringify(this.terse) + ')');
} else if (attrs.length) {
this.attrs(attrs, true);
}
},
/**
* Compile attributes.
*/
attrs: function (attrs, buffer) {
var buf = [];
var classes = [];
var classEscaping = [];
attrs.forEach(function (attr) {
var key = attr.name;
var escaped = attr.escaped;
if (key === 'class') {
classes.push(attr.val);
classEscaping.push(attr.escaped);
} else if (isConstant(attr.val)) {
if (buffer) {
this.buffer(runtime.attr(key, toConstant(attr.val), escaped, this.terse));
} else {
var val = toConstant(attr.val);
if (escaped && !(key.indexOf('data') === 0 && typeof val !== 'string')) {
val = runtime.escape(val);
}
buf.push(JSON.stringify(key) + ': ' + JSON.stringify(val));
}
} else {
if (buffer) {
this.bufferExpression('jade.attr("' + key + '", ' + attr.val + ', ' + JSON.stringify(escaped) + ', ' + JSON.stringify(this.terse) + ')');
} else {
var val = attr.val;
if (escaped && !(key.indexOf('data') === 0)) {
val = 'jade.escape(' + val + ')';
} else if (escaped) {
val = '(typeof (jade_interp = ' + val + ') == "string" ? jade.escape(jade_interp) : jade_interp)';
}
buf.push(JSON.stringify(key) + ': ' + val);
}
}
}.bind(this));
if (buffer) {
if (classes.every(isConstant)) {
this.buffer(runtime.cls(classes.map(toConstant), classEscaping));
} else {
this.bufferExpression('jade.cls([' + classes.join(',') + '], ' + JSON.stringify(classEscaping) + ')');
}
} else if (classes.length) {
if (classes.every(isConstant)) {
classes = JSON.stringify(runtime.joinClasses(classes.map(toConstant).map(runtime.joinClasses).map(function (cls, i) {
return classEscaping[i] ? runtime.escape(cls) : cls;
})));
} else {
classes = '(jade_interp = ' + JSON.stringify(classEscaping) + ',' +
' jade.joinClasses([' + classes.join(',') + '].map(jade.joinClasses).map(function (cls, i) {' +
' return jade_interp[i] ? jade.escape(cls) : cls' +
' }))' +
')';
}
if (classes.length)
buf.push('"class": ' + classes);
}
return '{' + buf.join(',') + '}';
}
};
}, {"./doctypes": 2, "./filters": 3, "./nodes": 16, "./runtime": 24, "./self-closing": 25, "./utils": 26, "character-parser": 33, "constantinople": 34}], 2: [function (_dereq_, module, exports) {
'use strict';
module.exports = {
'default': '<!DOCTYPE html>', 'xml': '<?xml version="1.0" encoding="utf-8" ?>', 'transitional': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">', 'strict': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">', 'frameset': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">', '1.1': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">', 'basic': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">', 'mobile': '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">'
};
}, {}], 3: [function (_dereq_, module, exports) {
'use strict';
module.exports = filter;
function filter(name, str, options) {
if (typeof filter[name] === 'function') {
var res = filter[name](str, options);
} else {
throw new Error('unknown filter ":' + name + '"');
}
return res;
}
}, {}], 4: [function (_dereq_, module, exports) {
'use strict';
module.exports = [
'a'
, 'abbr'
, 'acronym'
, 'b'
, 'br'
, 'code'
, 'em'
, 'font'
, 'i'
, 'img'
, 'ins'
, 'kbd'
, 'map'
, 'samp'
, 'small'
, 'span'
, 'strong'
, 'sub'
, 'sup'
];
}, {}], 5: [function (_dereq_, module, exports) {
'use strict';
/*!
* Jade
* Copyright(c) 2010 TJ Holowaychuk <[email protected]>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Parser = _dereq_('./parser')
, Lexer = _dereq_('./lexer')
, Compiler = _dereq_('./compiler')
, runtime = _dereq_('./runtime')
, addWith = _dereq_('with')
, fs = _dereq_('fs');
/**
* Expose self closing tags.
*/
exports.selfClosing = _dereq_('./self-closing');
/**
* Default supported doctypes.
*/
exports.doctypes = _dereq_('./doctypes');
/**
* Text filters.
*/
exports.filters = _dereq_('./filters');
/**
* Utilities.
*/
exports.utils = _dereq_('./utils');
/**
* Expose `Compiler`.
*/
exports.Compiler = Compiler;
/**
* Expose `Parser`.
*/
exports.Parser = Parser;
/**
* Expose `Lexer`.
*/
exports.Lexer = Lexer;
/**
* Nodes.
*/
exports.nodes = _dereq_('./nodes');
/**
* Jade runtime helpers.
*/
exports.runtime = runtime;
/**
* Template function cache.
*/
exports.cache = {};
/**
* Parse the given `str` of jade and return a function body.
*
* @param {String} str
* @param {Object} options
* @return {String}
* @api private
*/
function parse(str, options) {
// Parse
var parser = new (options.parser || Parser)(str, options.filename, options);
var tokens;
try {
// Parse
tokens = parser.parse();
} catch (err) {
parser = parser.context();
runtime.rethrow(err, parser.filename, parser.lexer.lineno, parser.input);
}
// Compile
var compiler = new (options.compiler || Compiler)(tokens, options);
var js;
try {
js = compiler.compile();
} catch (err) {
if (err.line && (err.filename || !options.filename)) {
runtime.rethrow(err, err.filename, err.line, parser.input);
}
}
// Debug compiler
if (options.debug) {
console.error('\nCompiled Function:\n\n\u001b[90m%s\u001b[0m', js.replace(/^/gm, ' '));
}
var globals = [];
globals.push('jade');
globals.push('jade_mixins');
globals.push('jade_interp');
globals.push('jade_debug');
globals.push('buf');
return ''
+ 'var buf = [];\n'
+ 'var jade_mixins = {};\n'
+ 'var jade_interp;\n'
+ (options.self
? 'var self = locals || {};\n' + js
: addWith('locals || {}', '\n' + js, globals)) + ';'
+ 'return buf.join("");';
}
/**
* Compile a `Function` representation of the given jade `str`.
*
* Options:
*
* - `compileDebug` when `false` debugging code is stripped from the compiled
template, when it is explicitly `true`, the source code is included in
the compiled template for better accuracy.
* - `filename` used to improve errors when `compileDebug` is not `false` and to resolve imports/extends
*
* @param {String} str
* @param {Options} options
* @return {Function}
* @api public
*/
exports.compile = function (str, options) {
var options = options || {}
, filename = options.filename
? JSON.stringify(options.filename)
: 'undefined'
, fn;
str = String(str);
if (options.compileDebug !== false) {
fn = [
'var jade_debug = [{ lineno: 1, filename: ' + filename + ' }];'
, 'try {'
, parse(str, options)
, '} catch (err) {'
, ' jade.rethrow(err, jade_debug[0].filename, jade_debug[0].lineno' + (options.compileDebug === true ? ',' + JSON.stringify(str) : '') + ');'
, '}'
].join('\n');
} else {
fn = parse(str, options);
}
fn = new Function('locals, jade', fn)
var res = function (locals) {
return fn(locals, Object.create(runtime))
};
if (options.client) {
res.toString = function () {
var err = new Error('The `client` option is deprecated, use `jade.compileClient`');
console.error(err.stack || err.message);
return exports.compileClient(str, options);
};
}
return res;
};
/**
* Compile a JavaScript source representation of the given jade `str`.
*
* Options:
*
* - `compileDebug` When it is `true`, the source code is included in
the compiled template for better error messages.
* - `filename` used to improve errors when `compileDebug` is not `true` and to resolve imports/extends
*
* @param {String} str
* @param {Options} options
* @return {String}
* @api public
*/
exports.compileClient = function (str, options) {
var options = options || {}
, filename = options.filename
? JSON.stringify(options.filename)
: 'undefined'
, fn;
str = String(str);
if (options.compileDebug) {
options.compileDebug = true;
fn = [
'var jade_debug = [{ lineno: 1, filename: ' + filename + ' }];'
, 'try {'
, parse(str, options)
, '} catch (err) {'
, ' jade.rethrow(err, jade_debug[0].filename, jade_debug[0].lineno, ' + JSON.stringify(str) + ');'
, '}'
].join('\n');
} else {
options.compileDebug = false;
fn = parse(str, options);
}
return 'function template(locals) {\n' + fn + '\n}';
};
/**
* Render the given `str` of jade.
*
* Options:
*
* - `cache` enable template caching
* - `filename` filename required for `include` / `extends` and caching
*
* @param {String} str
* @param {Object|Function} options or fn
* @param {Function|undefined} fn
* @returns {String}
* @api public
*/
exports.render = function (str, options, fn) {
// support callback API
if ('function' == typeof options) {
fn = options, options = undefined;
}
if (typeof fn === 'function') {
var res
try {
res = exports.render(str, options);
} catch (ex) {
return fn(ex);
}
return fn(null, res);
}
options = options || {};
// cache requires .filename
if (options.cache && !options.filename) {
throw new Error('the "filename" option is required for caching');
}
var path = options.filename;
var tmpl = options.cache
? exports.cache[path] || (exports.cache[path] = exports.compile(str, options))
: exports.compile(str, options);
return tmpl(options);
};
/**
* Render a Jade file at the given `path`.
*
* @param {String} path
* @param {Object|Function} options or callback
* @param {Function|undefined} fn
* @returns {String}
* @api public
*/
exports.renderFile = function (path, options, fn) {
// support callback API
if ('function' == typeof options) {
fn = options, options = undefined;
}
if (typeof fn === 'function') {
var res
try {
res = exports.renderFile(path, options);
} catch (ex) {
return fn(ex);
}
return fn(null, res);
}
options = options || {};
var key = path + ':string';
options.filename = path;
var str = options.cache
? exports.cache[key] || (exports.cache[key] = fs.readFileSync(path, 'utf8'))
: fs.readFileSync(path, 'utf8');
return exports.render(str, options);
};
/**
* Compile a Jade file at the given `path` for use on the client.
*
* @param {String} path
* @param {Object} options
* @returns {String}
* @api public
*/
exports.compileFileClient = function (path, options) {
options = options || {};
var key = path + ':string';
options.filename = path;
var str = options.cache
? exports.cache[key] || (exports.cache[key] = fs.readFileSync(path, 'utf8'))
: fs.readFileSync(path, 'utf8');
return exports.compileClient(str, options);
};
/**
* Express support.
*/
exports.__express = exports.renderFile;
}, {"./compiler": 1, "./doctypes": 2, "./filters": 3, "./lexer": 6, "./nodes": 16, "./parser": 23, "./runtime": 24, "./self-closing": 25, "./utils": 26, "fs": 27, "with": 46}], 6: [function (_dereq_, module, exports) {
'use strict';
var utils = _dereq_('./utils');
var characterParser = _dereq_('character-parser');
/**
* Initialize `Lexer` with the given `str`.
*
* @param {String} str
* @param {String} filename
* @api private
*/
var Lexer = module.exports = function Lexer(str, filename) {
this.input = str.replace(/\r\n|\r/g, '\n');
this.filename = filename;
this.deferredTokens = [];
this.lastIndents = 0;
this.lineno = 1;
this.stash = [];
this.indentStack = [];
this.indentRe = null;
this.pipeless = false;
};
function assertExpression(exp) {
//this verifies that a JavaScript expression is valid
Function('', 'return (' + exp + ')');
}
function assertNestingCorrect(exp) {
//this verifies that code is properly nested, but allows
//invalid JavaScript such as the contents of `attributes`
var res = characterParser(exp)
if (res.isNesting()) {
throw new Error('Nesting must match on expression `' + exp + '`')
}
}
/**
* Lexer prototype.
*/
Lexer.prototype = {
/**
* Construct a token with the given `type` and `val`.
*
* @param {String} type
* @param {String} val
* @return {Object}
* @api private
*/
tok: function (type, val) {
return {
type: type, line: this.lineno, val: val
}
},
/**
* Consume the given `len` of input.
*
* @param {Number} len
* @api private
*/
consume: function (len) {
this.input = this.input.substr(len);
},
/**
* Scan for `type` with the given `regexp`.
*
* @param {String} type
* @param {RegExp} regexp
* @return {Object}
* @api private
*/
scan: function (regexp, type) {
var captures;
if (captures = regexp.exec(this.input)) {
this.consume(captures[0].length);
return this.tok(type, captures[1]);
}
},
/**
* Defer the given `tok`.
*
* @param {Object} tok
* @api private
*/
defer: function (tok) {
this.deferredTokens.push(tok);
},
/**
* Lookahead `n` tokens.
*
* @param {Number} n
* @return {Object}
* @api private
*/
lookahead: function (n) {
var fetch = n - this.stash.length;
while (fetch-- > 0) this.stash.push(this.next());
return this.stash[--n];
},
/**
* Return the indexOf `(` or `{` or `[` / `)` or `}` or `]` delimiters.
*
* @return {Number}
* @api private
*/
bracketExpression: function (skip) {
skip = skip || 0;
var start = this.input[skip];
if (start != '(' && start != '{' && start != '[') throw new Error('unrecognized start character');
var end = ({'(': ')', '{': '}', '[': ']'})[start];
var range = characterParser.parseMax(this.input, {start: skip + 1});
if (this.input[range.end] !== end) throw new Error('start character ' + start + ' does not match end character ' + this.input[range.end]);
return range;
},
/**
* Stashed token.
*/
stashed: function () {
return this.stash.length
&& this.stash.shift();
},
/**
* Deferred token.
*/
deferred: function () {
return this.deferredTokens.length
&& this.deferredTokens.shift();
},
/**
* end-of-source.
*/
eos: function () {
if (this.input.length) return;
if (this.indentStack.length) {
this.indentStack.shift();
return this.tok('outdent');
} else {
return this.tok('eos');
}
},
/**
* Blank line.
*/
blank: function () {
var captures;
if (captures = /^\n *\n/.exec(this.input)) {
this.consume(captures[0].length - 1);
++this.lineno;
if (this.pipeless) return this.tok('text', '');
return this.next();
}
},
/**
* Comment.
*/
comment: function () {
var captures;
if (captures = /^\/\/(-)?([^\n]*)/.exec(this.input)) {
this.consume(captures[0].length);
var tok = this.tok('comment', captures[2]);
tok.buffer = '-' != captures[1];
return tok;
}
},
/**
* Interpolated tag.
*/
interpolation: function () {
if (/^#\{/.test(this.input)) {
var match;
try {
match = this.bracketExpression(1);
} catch (ex) {
return;//not an interpolation expression, just an unmatched open interpolation
}
this.consume(match.end + 1);
return this.tok('interpolation', match.src);
}
},
/**
* Tag.
*/
tag: function () {
var captures;
if (captures = /^(\w[-:\w]*)(\/?)/.exec(this.input)) {
this.consume(captures[0].length);
var tok, name = captures[1];
if (':' == name[name.length - 1]) {
name = name.slice(0, -1);
tok = this.tok('tag', name);
this.defer(this.tok(':'));
while (' ' == this.input[0]) this.input = this.input.substr(1);
} else {
tok = this.tok('tag', name);
}
tok.selfClosing = !!captures[2];
return tok;
}
},
/**
* Filter.
*/
filter: function () {
return this.scan(/^:([\w\-]+)/, 'filter');
},
/**
* Doctype.
*/
doctype: function () {
if (this.scan(/^!!! *([^\n]+)?/, 'doctype')) {
throw new Error('`!!!` is deprecated, you must now use `doctype`');
}
var node = this.scan(/^(?:doctype) *([^\n]+)?/, 'doctype');
if (node && node.val && node.val.trim() === '5') {
throw new Error('`doctype 5` is deprecated, you must now use `doctype html`');
}
return node;
},
/**
* Id.
*/
id: function () {
return this.scan(/^#([\w-]+)/, 'id');
},
/**
* Class.
*/
className: function () {
return this.scan(/^\.([\w-]+)/, 'class');
},
/**
* Text.
*/
text: function () {
return this.scan(/^(?:\| ?| )([^\n]+)/, 'text') || this.scan(/^(<[^\n]*)/, 'text');
},
textFail: function () {
var tok;
if (tok = this.scan(/^([^\.\n][^\n]+)/, 'text')) {
console.warn('Warning: missing space before text for line ' + this.lineno +
' of jade file "' + this.filename + '"');
return tok;
}
},
/**
* Dot.
*/
dot: function () {
return this.scan(/^\./, 'dot');
},
/**
* Extends.
*/
"extends": function () {
return this.scan(/^extends? +([^\n]+)/, 'extends');
},
/**
* Block prepend.
*/
prepend: function () {
var captures;
if (captures = /^prepend +([^\n]+)/.exec(this.input)) {
this.consume(captures[0].length);
var mode = 'prepend'
, name = captures[1]
, tok = this.tok('block', name);
tok.mode = mode;
return tok;
}
},
/**
* Block append.
*/
append: function () {
var captures;
if (captures = /^append +([^\n]+)/.exec(this.input)) {
this.consume(captures[0].length);
var mode = 'append'
, name = captures[1]
, tok = this.tok('block', name);
tok.mode = mode;
return tok;
}
},
/**
* Block.
*/
block: function () {
var captures;
if (captures = /^block\b *(?:(prepend|append) +)?([^\n]+)/.exec(this.input)) {
this.consume(captures[0].length);
var mode = captures[1] || 'replace'
, name = captures[2]
, tok = this.tok('block', name);
tok.mode = mode;
return tok;
}
},
/**
* Mixin Block.
*/
mixinBlock: function () {
var captures;
if (captures = /^block\s*(\n|$)/.exec(this.input)) {
this.consume(captures[0].length - 1);
return this.tok('mixin-block');
}
},
/**
* Yield.
*/
yield: function () {
return this.scan(/^yield */, 'yield');
},
/**
* Include.
*/
include: function () {
return this.scan(/^include +([^\n]+)/, 'include');
},
/**
* Include with filter
*/
includeFiltered: function () {
var captures;
if (captures = /^include:([\w\-]+) +([^\n]+)/.exec(this.input)) {
this.consume(captures[0].length);
var filter = captures[1];
var path = captures[2];
var tok = this.tok('include', path);
tok.filter = filter;
return tok;
}
},
/**
* Case.
*/
"case": function () {
return this.scan(/^case +([^\n]+)/, 'case');
},
/**
* When.
*/
when: function () {
return this.scan(/^when +([^:\n]+)/, 'when');
},
/**
* Default.
*/
"default": function () {
return this.scan(/^default */, 'default');
},
/**
* Call mixin.
*/
call: function () {
var tok, captures;
if (captures = /^\+(([-\w]+)|(#\{))/.exec(this.input)) {
// try to consume simple or interpolated call
if (captures[2]) {
// simple call
this.consume(captures[0].length);
tok = this.tok('call', captures[2]);
} else {
// interpolated call
var match;
try {
match = this.bracketExpression(2);
} catch (ex) {
return;//not an interpolation expression, just an unmatched open interpolation
}
this.consume(match.end + 1);
assertExpression(match.src);
tok = this.tok('call', '#{'+match.src+'}');
}
// Check for args (not attributes)
if (captures = /^ *\(/.exec(this.input)) {
try {
var range = this.bracketExpression(captures[0].length - 1);
if (!/^ *[-\w]+ *=/.test(range.src)) { // not attributes
this.consume(range.end + 1);
tok.args = range.src;
}
} catch (ex) {
//not a bracket expcetion, just unmatched open parens
}
}
return tok;
}
},
/**
* Mixin.
*/
mixin: function () {
var captures;
if (captures = /^mixin +([-\w]+)(?: *\((.*)\))? */.exec(this.input)) {
this.consume(captures[0].length);
var tok = this.tok('mixin', captures[1]);
tok.args = captures[2];
return tok;
}
},
/**
* Conditional.
*/
conditional: function () {
var captures;
if (captures = /^(if|unless|else if|else)\b([^\n]*)/.exec(this.input)) {
this.consume(captures[0].length);
var type = captures[1]
var js = captures[2];
var isIf = false;
var isElse = false;
switch (type) {
case 'if':
assertExpression(js)
js = 'if (' + js + ')';
isIf = true;
break;
case 'unless':
assertExpression(js)
js = 'if (!(' + js + '))';
isIf = true;
break;
case 'else if':
assertExpression(js)
js = 'else if (' + js + ')';
isIf = true;
isElse = true;
break;
case 'else':
if (js && js.trim()) {
throw new Error('`else` cannot have a condition, perhaps you meant `else if`');
}
js = 'else';
isElse = true;
break;
}
var tok = this.tok('code', js);
tok.isElse = isElse;
tok.isIf = isIf;
tok.requiresBlock = true;
return tok;
}
},
/**
* While.
*/
"while": function () {
var captures;
if (captures = /^while +([^\n]+)/.exec(this.input)) {
this.consume(captures[0].length);
assertExpression(captures[1])
var tok = this.tok('code', 'while (' + captures[1] + ')');
tok.requiresBlock = true;
return tok;
}
},
/**
* Each.
*/
each: function () {
var captures;
if (captures = /^(?:- *)?(?:each|for) +([a-zA-Z_$][\w$]*)(?: *, *([a-zA-Z_$][\w$]*))? * in *([^\n]+)/.exec(this.input)) {
this.consume(captures[0].length);
var tok = this.tok('each', captures[1]);
tok.key = captures[2] || '$index';
assertExpression(captures[3])
tok.code = captures[3];
return tok;
}
},
/**
* Code.
*/
code: function () {
var captures;
if (captures = /^(!?=|-)[ \t]*([^\n]+)/.exec(this.input)) {
this.consume(captures[0].length);
var flags = captures[1];
captures[1] = captures[2];
var tok = this.tok('code', captures[1]);
tok.escape = flags.charAt(0) === '=';
tok.buffer = flags.charAt(0) === '=' || flags.charAt(1) === '=';
if (tok.buffer) assertExpression(captures[1])
return tok;
}
},
/**
* Attributes.
*/
attrs: function () {
if ('(' == this.input.charAt(0)) {
var index = this.bracketExpression().end
, str = this.input.substr(1, index - 1)
, tok = this.tok('attrs');
assertNestingCorrect(str);
var quote = '';
var interpolate = function (attr) {
return attr.replace(/(\\)?#\{(.+)/g, function (_, escape, expr) {
if (escape) return _;
try {
var range = characterParser.parseMax(expr);
if (expr[range.end] !== '}') return _.substr(0, 2) + interpolate(_.substr(2));
assertExpression(range.src)
return quote + " + (" + range.src + ") + " + quote + interpolate(expr.substr(range.end + 1));
} catch (ex) {
return _.substr(0, 2) + interpolate(_.substr(2));
}
});
}
this.consume(index + 1);
tok.attrs = [];
var escapedAttr = true
var key = '';
var val = '';
var interpolatable = '';
var state = characterParser.defaultState();
var loc = 'key';
var isEndOfAttribute = function (i) {
if (key.trim() === '') return false;
if (i === str.length) return true;
if (loc === 'key') {
if (str[i] === ' ' || str[i] === '\n') {
for (var x = i; x < str.length; x++) {
if (str[x] != ' ' && str[x] != '\n') {
if (str[x] === '=' || str[x] === '!' || str[x] === ',') return false;
else return true;
}
}
}
return str[i] === ','
} else if (loc === 'value' && !state.isNesting()) {
try {
Function('', 'return (' + val + ');');
if (str[i] === ' ' || str[i] === '\n') {
for (var x = i; x < str.length; x++) {
if (str[x] != ' ' && str[x] != '\n') {
if (characterParser.isPunctuator(str[x]) && str[x] != '"' && str[x] != "'") return false;
else return true;
}
}
}
return str[i] === ',';
} catch (ex) {
return false;
}
}
}
this.lineno += str.split("\n").length - 1;
for (var i = 0; i <= str.length; i++) {
if (isEndOfAttribute(i)) {
val = val.trim();
if (val) assertExpression(val)
key = key.trim();
key = key.replace(/^['"]|['"]$/g, '');
tok.attrs.push({
name: key,
val: '' == val ? true : val,
escaped: escapedAttr
});
key = val = '';
loc = 'key';
escapedAttr = false;
} else {
switch (loc) {
case 'key-char':
if (str[i] === quote) {
loc = 'key';
if (i + 1 < str.length && [' ', ',', '!', '=', '\n'].indexOf(str[i + 1]) === -1)
throw new Error('Unexpected character ' + str[i + 1] + ' expected ` `, `\\n`, `,`, `!` or `=`');
} else {
key += str[i];
}
break;
case 'key':
if (key === '' && (str[i] === '"' || str[i] === "'")) {
loc = 'key-char';
quote = str[i];
} else if (str[i] === '!' || str[i] === '=') {
escapedAttr = str[i] !== '!';
if (str[i] === '!') i++;
if (str[i] !== '=') throw new Error('Unexpected character ' + str[i] + ' expected `=`');
loc = 'value';
state = characterParser.defaultState();
} else {
key += str[i]
}
break;
case 'value':
state = characterParser.parseChar(str[i], state);
if (state.isString()) {
loc = 'string';
quote = str[i];
interpolatable = str[i];
} else {
val += str[i];
}
break;
case 'string':
state = characterParser.parseChar(str[i], state);
interpolatable += str[i];
if (!state.isString()) {
loc = 'value';
val += interpolate(interpolatable);
}
break;
}
}
}
if ('/' == this.input.charAt(0)) {
this.consume(1);
tok.selfClosing = true;
}
return tok;
}
},
/**
* &attributes block
*/
attributesBlock: function () {
var captures;
if (/^&attributes\b/.test(this.input)) {
this.consume(11);
var args = this.bracketExpression();
this.consume(args.end + 1);
return this.tok('&attributes', args.src);
}
},
/**
* Indent | Outdent | Newline.
*/
indent: function () {
var captures, re;
// established regexp
if (this.indentRe) {
captures = this.indentRe.exec(this.input);
// determine regexp
} else {
// tabs
re = /^\n(\t*) */;
captures = re.exec(this.input);
// spaces
if (captures && !captures[1].length) {
re = /^\n( *)/;
captures = re.exec(this.input);
}
// established
if (captures && captures[1].length) this.indentRe = re;
}
if (captures) {
var tok
, indents = captures[1].length;
++this.lineno;
this.consume(indents + 1);
if (' ' == this.input[0] || '\t' == this.input[0]) {
throw new Error('Invalid indentation, you can use tabs or spaces but not both');
}
// blank line
if ('\n' == this.input[0]) return this.tok('newline');
// outdent
if (this.indentStack.length && indents < this.indentStack[0]) {
while (this.indentStack.length && this.indentStack[0] > indents) {
this.stash.push(this.tok('outdent'));
this.indentStack.shift();
}
tok = this.stash.pop();
// indent
} else if (indents && indents != this.indentStack[0]) {
this.indentStack.unshift(indents);
tok = this.tok('indent', indents);
// newline
} else {
tok = this.tok('newline');
}
return tok;
}
},
/**
* Pipe-less text consumed only when
* pipeless is true;
*/
pipelessText: function () {
if (this.pipeless) {
if ('\n' == this.input[0]) return;
var i = this.input.indexOf('\n');
if (-1 == i) i = this.input.length;
var str = this.input.substr(0, i);
this.consume(str.length);
return this.tok('text', str);
}
},
/**
* ':'
*/
colon: function () {
return this.scan(/^: */, ':');
},
fail: function () {
if (/^ ($|\n)/.test(this.input)) {
this.consume(1);
return this.next();
}
throw new Error('unexpected text ' + this.input.substr(0, 5));
},
/**
* Return the next token object, or those
* previously stashed by lookahead.
*
* @return {Object}
* @api private
*/
advance: function () {
return this.stashed()
|| this.next();
},
/**
* Return the next token object.
*
* @return {Object}
* @api private
*/
next: function () {
return this.deferred()
|| this.blank()
|| this.eos()
|| this.pipelessText()
|| this.yield()
|| this.doctype()
|| this.interpolation()
|| this["case"]()
|| this.when()
|| this["default"]()
|| this["extends"]()
|| this.append()
|| this.prepend()
|| this.block()
|| this.mixinBlock()
|| this.include()
|| this.includeFiltered()
|| this.mixin()
|| this.call()
|| this.conditional()
|| this.each()
|| this["while"]()
|| this.tag()
|| this.filter()
|| this.code()
|| this.id()
|| this.className()
|| this.attrs()
|| this.attributesBlock()
|| this.indent()
|| this.text()
|| this.comment()
|| this.colon()
|| this.dot()
|| this.textFail()
|| this.fail();
}
};
}, {"./utils": 26, "character-parser": 33}], 7: [function (_dereq_, module, exports) {
'use strict';
var Node = _dereq_('./node');
/**
* Initialize a `Attrs` node.
*
* @api public
*/
var Attrs = module.exports = function Attrs() {
this.attributeNames = [];
this.attrs = [];
this.attributeBlocks = [];
};
// Inherit from `Node`.
Attrs.prototype = Object.create(Node.prototype);
Attrs.prototype.constructor = Attrs;
Attrs.prototype.type = 'Attrs';
/**
* Set attribute `name` to `val`, keep in mind these become
* part of a raw js object literal, so to quote a value you must
* '"quote me"', otherwise or example 'user.name' is literal JavaScript.
*
* @param {String} name
* @param {String} val
* @param {Boolean} escaped
* @return {Tag} for chaining
* @api public
*/
Attrs.prototype.setAttribute = function (name, val, escaped) {
if (name !== 'class' && this.attributeNames.indexOf(name) !== -1) {
throw new Error('Duplicate attribute "' + name + '" is not allowed.');
}
this.attributeNames.push(name);
this.attrs.push({ name: name, val: val, escaped: escaped });
return this;
};
/**
* Remove attribute `name` when present.
*
* @param {String} name
* @api public
*/
Attrs.prototype.removeAttribute = function (name) {
var err = new Error('attrs.removeAttribute is deprecated and will be removed in v2.0.0');
console.warn(err.stack);
for (var i = 0, len = this.attrs.length; i < len; ++i) {
if (this.attrs[i] && this.attrs[i].name == name) {
delete this.attrs[i];
}
}
};
/**
* Get attribute value by `name`.
*
* @param {String} name
* @return {String}
* @api public
*/
Attrs.prototype.getAttribute = function (name) {
var err = new Error('attrs.getAttribute is deprecated and will be removed in v2.0.0');
console.warn(err.stack);
for (var i = 0, len = this.attrs.length; i < len; ++i) {
if (this.attrs[i] && this.attrs[i].name == name) {
return this.attrs[i].val;
}
}
};
Attrs.prototype.addAttributes = function (src) {
this.attributeBlocks.push(src);
};
}, {"./node": 20}], 8: [function (_dereq_, module, exports) {
'use strict';
var Node = _dereq_('./node');
/**
* Initialize a `BlockComment` with the given `block`.
*
* @param {String} val
* @param {Block} block
* @param {Boolean} buffer
* @api public
*/
var BlockComment = module.exports = function BlockComment(val, block, buffer) {
this.block = block;
this.val = val;
this.buffer = buffer;
};
// Inherit from `Node`.
BlockComment.prototype = Object.create(Node.prototype);
BlockComment.prototype.constructor = BlockComment;
BlockComment.prototype.type = 'BlockComment';
}, {"./node": 20}], 9: [function (_dereq_, module, exports) {
'use strict';
var Node = _dereq_('./node');
/**
* Initialize a new `Block` with an optional `node`.
*
* @param {Node} node
* @api public
*/
var Block = module.exports = function Block(node) {
this.nodes = [];
if (node) this.push(node);
};
// Inherit from `Node`.
Block.prototype = Object.create(Node.prototype);
Block.prototype.constructor = Block;
Block.prototype.type = 'Block';
/**
* Block flag.
*/
Block.prototype.isBlock = true;
/**
* Replace the nodes in `other` with the nodes
* in `this` block.
*
* @param {Block} other
* @api private
*/
Block.prototype.replace = function (other) {
var err = new Error('block.replace is deprecated and will be removed in v2.0.0');
console.warn(err.stack);
other.nodes = this.nodes;
};
/**
* Push the given `node`.
*
* @param {Node} node
* @return {Number}
* @api public
*/
Block.prototype.push = function (node) {
return this.nodes.push(node);
};
/**
* Check if this block is empty.
*
* @return {Boolean}
* @api public
*/
Block.prototype.isEmpty = function () {
return 0 == this.nodes.length;
};
/**
* Unshift the given `node`.
*
* @param {Node} node
* @return {Number}
* @api public
*/
Block.prototype.unshift = function (node) {
return this.nodes.unshift(node);
};
/**
* Return the "last" block, or the first `yield` node.
*
* @return {Block}
* @api private
*/
Block.prototype.includeBlock = function () {
var ret = this
, node;
for (var i = 0, len = this.nodes.length; i < len; ++i) {
node = this.nodes[i];
if (node.yield) return node;
else if (node.textOnly) continue;
else if (node.includeBlock) ret = node.includeBlock();
else if (node.block && !node.block.isEmpty()) ret = node.block.includeBlock();
if (ret.yield) return ret;
}
return ret;
};
/**
* Return a clone of this block.
*
* @return {Block}
* @api private
*/
Block.prototype.clone = function () {
var err = new Error('block.clone is deprecated and will be removed in v2.0.0');
console.warn(err.stack);
var clone = new Block;
for (var i = 0, len = this.nodes.length; i < len; ++i) {
clone.push(this.nodes[i].clone());
}
return clone;
};
}, {"./node": 20}], 10: [function (_dereq_, module, exports) {
'use strict';
var Node = _dereq_('./node');
/**
* Initialize a new `Case` with `expr`.
*
* @param {String} expr
* @api public
*/
var Case = exports = module.exports = function Case(expr, block) {
this.expr = expr;
this.block = block;
};
// Inherit from `Node`.
Case.prototype = Object.create(Node.prototype);
Case.prototype.constructor = Case;
Case.prototype.type = 'Case';
var When = exports.When = function When(expr, block) {
this.expr = expr;
this.block = block;
this.debug = false;
};
// Inherit from `Node`.
When.prototype = Object.create(Node.prototype);
When.prototype.constructor = When;
When.prototype.type = 'When';
}, {"./node": 20}], 11: [function (_dereq_, module, exports) {
'use strict';
var Node = _dereq_('./node');
/**
* Initialize a `Code` node with the given code `val`.
* Code may also be optionally buffered and escaped.
*
* @param {String} val
* @param {Boolean} buffer
* @param {Boolean} escape
* @api public
*/
var Code = module.exports = function Code(val, buffer, escape) {
this.val = val;
this.buffer = buffer;
this.escape = escape;
if (val.match(/^ *else/)) this.debug = false;
};
// Inherit from `Node`.
Code.prototype = Object.create(Node.prototype);
Code.prototype.constructor = Code;
Code.prototype.type = 'Code'; // prevent the minifiers removing this
}, {"./node": 20}], 12: [function (_dereq_, module, exports) {
'use strict';
var Node = _dereq_('./node');
/**
* Initialize a `Comment` with the given `val`, optionally `buffer`,
* otherwise the comment may render in the output.
*
* @param {String} val
* @param {Boolean} buffer
* @api public
*/
var Comment = module.exports = function Comment(val, buffer) {
this.val = val;
this.buffer = buffer;
};
// Inherit from `Node`.
Comment.prototype = Object.create(Node.prototype);
Comment.prototype.constructor = Comment;
Comment.prototype.type = 'Comment';
}, {"./node": 20}], 13: [function (_dereq_, module, exports) {
'use strict';
var Node = _dereq_('./node');
/**
* Initialize a `Doctype` with the given `val`.
*
* @param {String} val
* @api public
*/
var Doctype = module.exports = function Doctype(val) {
this.val = val;
};
// Inherit from `Node`.
Doctype.prototype = Object.create(Node.prototype);
Doctype.prototype.constructor = Doctype;
Doctype.prototype.type = 'Doctype';
}, {"./node": 20}], 14: [function (_dereq_, module, exports) {
'use strict';
var Node = _dereq_('./node');
/**
* Initialize an `Each` node, representing iteration
*
* @param {String} obj
* @param {String} val
* @param {String} key
* @param {Block} block
* @api public
*/
var Each = module.exports = function Each(obj, val, key, block) {
this.obj = obj;
this.val = val;
this.key = key;
this.block = block;
};
// Inherit from `Node`.
Each.prototype = Object.create(Node.prototype);
Each.prototype.constructor = Each;
Each.prototype.type = 'Each';
}, {"./node": 20}], 15: [function (_dereq_, module, exports) {
'use strict';
var Node = _dereq_('./node');
/**
* Initialize a `Filter` node with the given
* filter `name` and `block`.
*
* @param {String} name
* @param {Block|Node} block
* @api public
*/
var Filter = module.exports = function Filter(name, block, attrs) {
this.name = name;
this.block = block;
this.attrs = attrs;
};
// Inherit from `Node`.
Filter.prototype = Object.create(Node.prototype);
Filter.prototype.constructor = Filter;
Filter.prototype.type = 'Filter';
}, {"./node": 20}], 16: [function (_dereq_, module, exports) {
'use strict';
exports.Node = _dereq_('./node');
exports.Tag = _dereq_('./tag');
exports.Code = _dereq_('./code');
exports.Each = _dereq_('./each');
exports.Case = _dereq_('./case');
exports.Text = _dereq_('./text');
exports.Block = _dereq_('./block');
exports.MixinBlock = _dereq_('./mixin-block');
exports.Mixin = _dereq_('./mixin');
exports.Filter = _dereq_('./filter');
exports.Comment = _dereq_('./comment');
exports.Literal = _dereq_('./literal');
exports.BlockComment = _dereq_('./block-comment');
exports.Doctype = _dereq_('./doctype');
}, {"./block": 9, "./block-comment": 8, "./case": 10, "./code": 11, "./comment": 12, "./doctype": 13, "./each": 14, "./filter": 15, "./literal": 17, "./mixin": 19, "./mixin-block": 18, "./node": 20, "./tag": 21, "./text": 22}], 17: [function (_dereq_, module, exports) {
'use strict';
var Node = _dereq_('./node');
/**
* Initialize a `Literal` node with the given `str.
*
* @param {String} str
* @api public
*/
var Literal = module.exports = function Literal(str) {
this.str = str;
};
// Inherit from `Node`.
Literal.prototype = Object.create(Node.prototype);
Literal.prototype.constructor = Literal;
Literal.prototype.type = 'Literal';
}, {"./node": 20}], 18: [function (_dereq_, module, exports) {
'use strict';
var Node = _dereq_('./node');
/**
* Initialize a new `Block` with an optional `node`.
*
* @param {Node} node
* @api public
*/
var MixinBlock = module.exports = function MixinBlock() {
};
// Inherit from `Node`.
MixinBlock.prototype = Object.create(Node.prototype);
MixinBlock.prototype.constructor = MixinBlock;
MixinBlock.prototype.type = 'MixinBlock';
}, {"./node": 20}], 19: [function (_dereq_, module, exports) {
'use strict';
var Attrs = _dereq_('./attrs');
/**
* Initialize a new `Mixin` with `name` and `block`.
*
* @param {String} name
* @param {String} args
* @param {Block} block
* @api public
*/
var Mixin = module.exports = function Mixin(name, args, block, call) {
Attrs.call(this);
this.name = name;
this.args = args;
this.block = block;
this.call = call;
};
// Inherit from `Attrs`.
Mixin.prototype = Object.create(Attrs.prototype);
Mixin.prototype.constructor = Mixin;
Mixin.prototype.type = 'Mixin';
}, {"./attrs": 7}], 20: [function (_dereq_, module, exports) {
'use strict';
var Node = module.exports = function Node() {
};
/**
* Clone this node (return itself)
*
* @return {Node}
* @api private
*/
Node.prototype.clone = function () {
var err = new Error('node.clone is deprecated and will be removed in v2.0.0');
console.warn(err.stack);
return this;
};
Node.prototype.type = '';
}, {}], 21: [function (_dereq_, module, exports) {
'use strict';
var Attrs = _dereq_('./attrs');
var Block = _dereq_('./block');
var inlineTags = _dereq_('../inline-tags');
/**
* Initialize a `Tag` node with the given tag `name` and optional `block`.
*
* @param {String} name
* @param {Block} block
* @api public
*/
var Tag = module.exports = function Tag(name, block) {
Attrs.call(this);
this.name = name;
this.block = block || new Block;
};
// Inherit from `Attrs`.
Tag.prototype = Object.create(Attrs.prototype);
Tag.prototype.constructor = Tag;
Tag.prototype.type = 'Tag';
/**
* Clone this tag.
*
* @return {Tag}
* @api private
*/
Tag.prototype.clone = function () {
var err = new Error('tag.clone is deprecated and will be removed in v2.0.0');
console.warn(err.stack);
var clone = new Tag(this.name, this.block.clone());
clone.line = this.line;
clone.attrs = this.attrs;
clone.textOnly = this.textOnly;
return clone;
};
/**
* Check if this tag is an inline tag.
*
* @return {Boolean}
* @api private
*/
Tag.prototype.isInline = function () {
return ~inlineTags.indexOf(this.name);
};
/**
* Check if this tag's contents can be inlined. Used for pretty printing.
*
* @return {Boolean}
* @api private
*/
Tag.prototype.canInline = function () {
var nodes = this.block.nodes;
function isInline(node) {
// Recurse if the node is a block
if (node.isBlock) return node.nodes.every(isInline);
return node.isText || (node.isInline && node.isInline());
}
// Empty tag
if (!nodes.length) return true;
// Text-only or inline-only tag
if (1 == nodes.length) return isInline(nodes[0]);
// Multi-line inline-only tag
if (this.block.nodes.every(isInline)) {
for (var i = 1, len = nodes.length; i < len; ++i) {
if (nodes[i - 1].isText && nodes[i].isText)
return false;
}
return true;
}
// Mixed tag
return false;
};
}, {"../inline-tags": 4, "./attrs": 7, "./block": 9}], 22: [function (_dereq_, module, exports) {
'use strict';
var Node = _dereq_('./node');
/**
* Initialize a `Text` node with optional `line`.
*
* @param {String} line
* @api public
*/
var Text = module.exports = function Text(line) {
this.val = line;
};
// Inherit from `Node`.
Text.prototype = Object.create(Node.prototype);
Text.prototype.constructor = Text;
Text.prototype.type = 'Text';
/**
* Flag as text.
*/
Text.prototype.isText = true;
}, {"./node": 20}], 23: [function (_dereq_, module, exports) {
'use strict';
var Lexer = _dereq_('./lexer');
var nodes = _dereq_('./nodes');
var utils = _dereq_('./utils');
var filters = _dereq_('./filters');
var path = _dereq_('path');
var constantinople = _dereq_('constantinople');
var parseJSExpression = _dereq_('character-parser').parseMax;
var extname = path.extname;
/**
* Initialize `Parser` with the given input `str` and `filename`.
*
* @param {String} str
* @param {String} filename
* @param {Object} options
* @api public
*/
var Parser = exports = module.exports = function Parser(str, filename, options) {
//Strip any UTF-8 BOM off of the start of `str`, if it exists.
this.input = str.replace(/^\uFEFF/, '');
this.lexer = new Lexer(this.input, filename);
this.filename = filename;
this.blocks = {};
this.mixins = {};
this.options = options;
this.contexts = [this];
this.inMixin = false;
};
/**
* Parser prototype.
*/
Parser.prototype = {
/**
* Save original constructor
*/
constructor: Parser,
/**
* Push `parser` onto the context stack,
* or pop and return a `Parser`.
*/
context: function (parser) {
if (parser) {
this.contexts.push(parser);
} else {
return this.contexts.pop();
}
},
/**
* Return the next token object.
*
* @return {Object}
* @api private
*/
advance: function () {
return this.lexer.advance();
},
/**
* Single token lookahead.
*
* @return {Object}
* @api private
*/
peek: function () {
return this.lookahead(1);
},
/**
* Return lexer lineno.
*
* @return {Number}
* @api private
*/
line: function () {
return this.lexer.lineno;
},
/**
* `n` token lookahead.
*
* @param {Number} n
* @return {Object}
* @api private
*/
lookahead: function (n) {
return this.lexer.lookahead(n);
},
/**
* Parse input returning a string of js for evaluation.
*
* @return {String}
* @api public
*/
parse: function () {
var block = new nodes.Block, parser;
block.line = 0;
block.filename = this.filename;
while ('eos' != this.peek().type) {
if ('newline' == this.peek().type) {
this.advance();
} else {
var next = this.peek();
var expr = this.parseExpr();
expr.filename = expr.filename || this.filename;
expr.line = next.line;
block.push(expr);
}
}
if (parser = this.extending) {
this.context(parser);
var ast = parser.parse();
this.context();
// hoist mixins
for (var name in this.mixins)
ast.unshift(this.mixins[name]);
return ast;
}
return block;
},
/**
* Expect the given type, or throw an exception.
*
* @param {String} type
* @api private
*/
expect: function (type) {
if (this.peek().type === type) {
return this.advance();
} else {
throw new Error('expected "' + type + '", but got "' + this.peek().type + '"');
}
},
/**
* Accept the given `type`.
*
* @param {String} type
* @api private
*/
accept: function (type) {
if (this.peek().type === type) {
return this.advance();
}
},
/**
* tag
* | doctype
* | mixin
* | include
* | filter
* | comment
* | text
* | each
* | code
* | yield
* | id
* | class
* | interpolation
*/
parseExpr: function () {
switch (this.peek().type) {
case 'tag':
return this.parseTag();
case 'mixin':
return this.parseMixin();
case 'block':
return this.parseBlock();
case 'mixin-block':
return this.parseMixinBlock();
case 'case':
return this.parseCase();
case 'extends':
return this.parseExtends();
case 'include':
return this.parseInclude();
case 'doctype':
return this.parseDoctype();
case 'filter':
return this.parseFilter();
case 'comment':
return this.parseComment();
case 'text':
return this.parseText();
case 'each':
return this.parseEach();
case 'code':
return this.parseCode();
case 'call':
return this.parseCall();
case 'interpolation':
return this.parseInterpolation();
case 'yield':
this.advance();
var block = new nodes.Block;
block.yield = true;
return block;
case 'id':
case 'class':
var tok = this.advance();
this.lexer.defer(this.lexer.tok('tag', 'div'));
this.lexer.defer(tok);
return this.parseExpr();
default:
throw new Error('unexpected token "' + this.peek().type + '"');
}
},
/**
* Text
*/
parseText: function () {
var tok = this.expect('text');
var tokens = this.parseTextWithInlineTags(tok.val);
if (tokens.length === 1) return tokens[0];
var node = new nodes.Block;
for (var i = 0; i < tokens.length; i++) {
node.push(tokens[i]);
}
;
return node;
},
/**
* ':' expr
* | block
*/
parseBlockExpansion: function () {
if (':' == this.peek().type) {
this.advance();
return new nodes.Block(this.parseExpr());
} else {
return this.block();
}
},
/**
* case
*/
parseCase: function () {
var val = this.expect('case').val;
var node = new nodes.Case(val);
node.line = this.line();
var block = new nodes.Block;
block.line = this.line();
block.filename = this.filename;
this.expect('indent');
while ('outdent' != this.peek().type) {
switch (this.peek().type) {
case 'newline':
this.advance();
break;
case 'when':
block.push(this.parseWhen());
break;
case 'default':
block.push(this.parseDefault());
break;
default:
throw new Error('Unexpected token "' + this.peek().type
+ '", expected "when", "default" or "newline"');
}
}
this.expect('outdent');
node.block = block;
return node;
},
/**
* when
*/
parseWhen: function () {
var val = this.expect('when').val;
if (this.peek().type !== 'newline')
return new nodes.Case.When(val, this.parseBlockExpansion());
else
return new nodes.Case.When(val);
},
/**
* default
*/
parseDefault: function () {
this.expect('default');
return new nodes.Case.When('default', this.parseBlockExpansion());
},
/**
* code
*/
parseCode: function (afterIf) {
var tok = this.expect('code');
var node = new nodes.Code(tok.val, tok.buffer, tok.escape);
var block;
node.line = this.line();
// throw an error if an else does not have an if
if (tok.isElse && !tok.hasIf) {
throw new Error('Unexpected else without if');
}
// handle block
block = 'indent' == this.peek().type;
if (block) {
node.block = this.block();
}
// handle missing block
if (tok.requiresBlock && !block) {
node.block = new nodes.Block();
}
// mark presense of if for future elses
if (tok.isIf && this.peek().isElse) {
this.peek().hasIf = true;
} else if (tok.isIf && this.peek().type === 'newline' && this.lookahead(2).isElse) {
this.lookahead(2).hasIf = true;
}
return node;
},
/**
* comment
*/
parseComment: function () {
var tok = this.expect('comment');
var node;
if ('indent' == this.peek().type) {
this.lexer.pipeless = true;
node = new nodes.BlockComment(tok.val, this.parseTextBlock(), tok.buffer);
this.lexer.pipeless = false;
} else {
node = new nodes.Comment(tok.val, tok.buffer);
}
node.line = this.line();
return node;
},
/**
* doctype
*/
parseDoctype: function () {
var tok = this.expect('doctype');
var node = new nodes.Doctype(tok.val);
node.line = this.line();
return node;
},
/**
* filter attrs? text-block
*/
parseFilter: function () {
var tok = this.expect('filter');
var attrs = this.accept('attrs');
var block;
if ('indent' == this.peek().type) {
this.lexer.pipeless = true;
block = this.parseTextBlock();
this.lexer.pipeless = false;
} else {
block = new nodes.Block;
}
var options = {};
if (attrs) {
attrs.attrs.forEach(function (attribute) {
options[attribute.name] = constantinople.toConstant(attribute.val);
});
}
var node = new nodes.Filter(tok.val, block, options);
node.line = this.line();
return node;
},
/**
* each block
*/
parseEach: function () {
var tok = this.expect('each');
var node = new nodes.Each(tok.code, tok.val, tok.key);
node.line = this.line();
node.block = this.block();
if (this.peek().type == 'code' && this.peek().val == 'else') {
this.advance();
node.alternative = this.block();
}
return node;
},
/**
* Resolves a path relative to the template for use in
* includes and extends
*
* @param {String} path
* @param {String} purpose Used in error messages.
* @return {String}
* @api private
*/
resolvePath: function (path, purpose) {
var p = _dereq_('path');
var dirname = p.dirname;
var basename = p.basename;
var join = p.join;
if (path[0] !== '/' && !this.filename)
throw new Error('the "filename" option is required to use "' + purpose + '" with "relative" paths');
if (path[0] === '/' && !this.options.basedir)
throw new Error('the "basedir" option is required to use "' + purpose + '" with "absolute" paths');
path = join(path[0] === '/' ? this.options.basedir : dirname(this.filename), path);
if (basename(path).indexOf('.') === -1) path += '.jade';
return path;
},
/**
* 'extends' name
*/
parseExtends: function () {
var fs = _dereq_('fs');
var path = this.resolvePath(this.expect('extends').val.trim(), 'extends');
if ('.jade' != path.substr(-5)) path += '.jade';
var str = fs.readFileSync(path, 'utf8');
var parser = new this.constructor(str, path, this.options);
parser.blocks = this.blocks;
parser.contexts = this.contexts;
this.extending = parser;
// TODO: null node
return new nodes.Literal('');
},
/**
* 'block' name block
*/
parseBlock: function () {
var block = this.expect('block');
var mode = block.mode;
var name = block.val.trim();
block = 'indent' == this.peek().type
? this.block()
: new nodes.Block(new nodes.Literal(''));
var prev = this.blocks[name] || {prepended: [], appended: []}
if (prev.mode === 'replace') return this.blocks[name] = prev;
var allNodes = prev.prepended.concat(block.nodes).concat(prev.appended);
switch (mode) {
case 'append':
prev.appended = prev.parser === this ?
prev.appended.concat(block.nodes) :
block.nodes.concat(prev.appended);
break;
case 'prepend':
prev.prepended = prev.parser === this ?
block.nodes.concat(prev.prepended) :
prev.prepended.concat(block.nodes);
break;
}
block.nodes = allNodes;
block.appended = prev.appended;
block.prepended = prev.prepended;
block.mode = mode;
block.parser = this;
return this.blocks[name] = block;
},
parseMixinBlock: function () {
var block = this.expect('mixin-block');
if (!this.inMixin) {
throw new Error('Anonymous blocks are not allowed unless they are part of a mixin.');
}
return new nodes.MixinBlock();
},
/**
* include block?
*/
parseInclude: function () {
var fs = _dereq_('fs');
var tok = this.expect('include');
var path = this.resolvePath(tok.val.trim(), 'include');
// has-filter
if (tok.filter) {
var str = fs.readFileSync(path, 'utf8').replace(/\r/g, '');
str = filters(tok.filter, str, { filename: path });
return new nodes.Literal(str);
}
// non-jade
if ('.jade' != path.substr(-5)) {
var str = fs.readFileSync(path, 'utf8').replace(/\r/g, '');
return new nodes.Literal(str);
}
var str = fs.readFileSync(path, 'utf8');
var parser = new this.constructor(str, path, this.options);
parser.blocks = utils.merge({}, this.blocks);
parser.mixins = this.mixins;
this.context(parser);
var ast = parser.parse();
this.context();
ast.filename = path;
if ('indent' == this.peek().type) {
ast.includeBlock().push(this.block());
}
return ast;
},
/**
* call ident block
*/
parseCall: function () {
var tok = this.expect('call');
var name = tok.val;
var args = tok.args;
var mixin = new nodes.Mixin(name, args, new nodes.Block, true);
this.tag(mixin);
if (mixin.code) {
mixin.block.push(mixin.code);
mixin.code = null;
}
if (mixin.block.isEmpty()) mixin.block = null;
return mixin;
},
/**
* mixin block
*/
parseMixin: function () {
var tok = this.expect('mixin');
var name = tok.val;
var args = tok.args;
var mixin;
// definition
if ('indent' == this.peek().type) {
this.inMixin = true;
mixin = new nodes.Mixin(name, args, this.block(), false);
this.mixins[name] = mixin;
this.inMixin = false;
return mixin;
// call
} else {
return new nodes.Mixin(name, args, null, true);
}
},
parseTextWithInlineTags: function (str) {
var line = this.line();
var match = /(\\)?#\[((?:.|\n)*)$/.exec(str);
if (match) {
if (match[1]) { // escape
var text = new nodes.Text(str.substr(0, match.index) + '#[');
text.line = line;
var rest = this.parseTextWithInlineTags(match[2]);
if (rest[0].type === 'Text') {
text.val += rest[0].val;
rest.shift();
}
return [text].concat(rest);
} else {
var text = new nodes.Text(str.substr(0, match.index));
text.line = line;
var buffer = [text];
var rest = match[2];
var range = parseJSExpression(rest);
var inner = new Parser(range.src, this.filename, this.options);
buffer.push(inner.parse());
return buffer.concat(this.parseTextWithInlineTags(rest.substr(range.end + 1)));
}
} else {
var text = new nodes.Text(str);
text.line = line;
return [text];
}
},
/**
* indent (text | newline)* outdent
*/
parseTextBlock: function () {
var block = new nodes.Block;
block.line = this.line();
var spaces = this.expect('indent').val;
if (null == this._spaces) this._spaces = spaces;
var indent = Array(spaces - this._spaces + 1).join(' ');
while ('outdent' != this.peek().type) {
switch (this.peek().type) {
case 'newline':
this.advance();
break;
case 'indent':
this.parseTextBlock(true).nodes.forEach(function (node) {
block.push(node);
});
break;
default:
var texts = this.parseTextWithInlineTags(indent + this.advance().val);
texts.forEach(function (text) {
block.push(text);
});
}
}
if (spaces == this._spaces) this._spaces = null;
this.expect('outdent');
return block;
},
/**
* indent expr* outdent
*/
block: function () {
var block = new nodes.Block;
block.line = this.line();
block.filename = this.filename;
this.expect('indent');
while ('outdent' != this.peek().type) {
if ('newline' == this.peek().type) {
this.advance();
} else {
var expr = this.parseExpr();
expr.filename = this.filename;
block.push(expr);
}
}
this.expect('outdent');
return block;
},
/**
* interpolation (attrs | class | id)* (text | code | ':')? newline* block?
*/
parseInterpolation: function () {
var tok = this.advance();
var tag = new nodes.Tag(tok.val);
tag.buffer = true;
return this.tag(tag);
},
/**
* tag (attrs | class | id)* (text | code | ':')? newline* block?
*/
parseTag: function () {
var tok = this.advance();
var tag = new nodes.Tag(tok.val);
tag.selfClosing = tok.selfClosing;
return this.tag(tag);
},
/**
* Parse tag.
*/
tag: function (tag) {
tag.line = this.line();
var seenAttrs = false;
// (attrs | class | id)*
out:
while (true) {
switch (this.peek().type) {
case 'id':
case 'class':
var tok = this.advance();
tag.setAttribute(tok.type, "'" + tok.val + "'");
continue;
case 'attrs':
if (seenAttrs) {
console.warn(this.filename + ', line ' + this.peek().line + ':\nYou should not have jade tags with multiple attributes.');
}
seenAttrs = true;
var tok = this.advance();
var attrs = tok.attrs;
if (tok.selfClosing) tag.selfClosing = true;
for (var i = 0; i < attrs.length; i++) {
tag.setAttribute(attrs[i].name, attrs[i].val, attrs[i].escaped);
}
continue;
case '&attributes':
var tok = this.advance();
tag.addAttributes(tok.val);
break;
default:
break out;
}
}
// check immediate '.'
if ('dot' == this.peek().type) {
tag.textOnly = true;
this.advance();
}
// (text | code | ':')?
switch (this.peek().type) {
case 'text':
tag.block.push(this.parseText());
break;
case 'code':
tag.code = this.parseCode();
break;
case ':':
this.advance();
tag.block = new nodes.Block;
tag.block.push(this.parseExpr());
break;
case 'newline':
case 'indent':
case 'outdent':
case 'eos':
break;
default:
throw new Error('Unexpected token `' + this.peek().type + '` expected `text`, `code`, `:`, `newline` or `eos`')
}
// newline*
while ('newline' == this.peek().type) this.advance();
// block?
if ('indent' == this.peek().type) {
if (tag.textOnly) {
this.lexer.pipeless = true;
tag.block = this.parseTextBlock();
this.lexer.pipeless = false;
} else {
var block = this.block();
for (var i = 0, len = block.nodes.length; i < len; ++i) {
tag.block.push(block.nodes[i]);
}
}
}
return tag;
}
};
}, {"./filters": 3, "./lexer": 6, "./nodes": 16, "./utils": 26, "character-parser": 33, "constantinople": 34, "fs": 27, "path": 30}], 24: [function (_dereq_, module, exports) {
'use strict';
/**
* Merge two attribute objects giving precedence
* to values in object `b`. Classes are special-cased
* allowing for arrays and merging/joining appropriately
* resulting in a string.
*
* @param {Object} a
* @param {Object} b
* @return {Object} a
* @api private
*/
exports.merge = function merge(a, b) {
if (arguments.length === 1) {
var attrs = a[0];
for (var i = 1; i < a.length; i++) {
attrs = merge(attrs, a[i]);
}
return attrs;
}
var ac = a['class'];
var bc = b['class'];
if (ac || bc) {
ac = ac || [];
bc = bc || [];
if (!Array.isArray(ac)) ac = [ac];
if (!Array.isArray(bc)) bc = [bc];
a['class'] = ac.concat(bc).filter(nulls);
}
for (var key in b) {
if (key != 'class') {
a[key] = b[key];
}
}
return a;
};
/**
* Filter null `val`s.
*
* @param {*} val
* @return {Boolean}
* @api private
*/
function nulls(val) {
return val != null && val !== '';
}
/**
* join array as classes.
*
* @param {*} val
* @return {String}
*/
exports.joinClasses = joinClasses;
function joinClasses(val) {
return Array.isArray(val) ? val.map(joinClasses).filter(nulls).join(' ') : val;
}
/**
* Render the given classes.
*
* @param {Array} classes
* @param {Array.<Boolean>} escaped
* @return {String}
*/
exports.cls = function cls(classes, escaped) {
var buf = [];
for (var i = 0; i < classes.length; i++) {
if (escaped && escaped[i]) {
buf.push(exports.escape(joinClasses([classes[i]])));
} else {
buf.push(joinClasses(classes[i]));
}
}
var text = joinClasses(buf);
if (text.length) {
return ' class="' + text + '"';
} else {
return '';
}
};
/**
* Render the given attribute.
*
* @param {String} key
* @param {String} val
* @param {Boolean} escaped
* @param {Boolean} terse
* @return {String}
*/
exports.attr = function attr(key, val, escaped, terse) {
if ('boolean' == typeof val || null == val) {
if (val) {
return ' ' + (terse ? key : key + '="' + key + '"');
} else {
return '';
}
} else if (0 == key.indexOf('data') && 'string' != typeof val) {
return ' ' + key + "='" + JSON.stringify(val).replace(/'/g, '&apos;') + "'";
} else if (escaped) {
return ' ' + key + '="' + exports.escape(val) + '"';
} else {
return ' ' + key + '="' + val + '"';
}
};
/**
* Render the given attributes object.
*
* @param {Object} obj
* @param {Object} escaped
* @return {String}
*/
exports.attrs = function attrs(obj, terse) {
var buf = [];
var keys = Object.keys(obj);
if (keys.length) {
for (var i = 0; i < keys.length; ++i) {
var key = keys[i]
, val = obj[key];
if ('class' == key) {
if (val = joinClasses(val)) {
buf.push(' ' + key + '="' + val + '"');
}
} else {
buf.push(exports.attr(key, val, false, terse));
}
}
}
return buf.join('');
};
/**
* Escape the given string of `html`.
*
* @param {String} html
* @return {String}
* @api private
*/
exports.escape = function escape(html) {
var result = String(html)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
if (result === '' + html) return html;
else return result;
};
/**
* Re-throw the given `err` in context to the
* the jade in `filename` at the given `lineno`.
*
* @param {Error} err
* @param {String} filename
* @param {String} lineno
* @api private
*/
exports.rethrow = function rethrow(err, filename, lineno, str) {
if (!(err instanceof Error)) throw err;
if ((typeof window != 'undefined' || !filename) && !str) {
err.message += ' on line ' + lineno;
throw err;
}
try {
str = str || _dereq_('fs').readFileSync(filename, 'utf8')
} catch (ex) {
rethrow(err, null, lineno)
}
var context = 3
, lines = str.split('\n')
, start = Math.max(lineno - context, 0)
, end = Math.min(lines.length, lineno + context);
// Error context
var context = lines.slice(start, end).map(function (line, i) {
var curr = i + start + 1;
return (curr == lineno ? ' > ' : ' ')
+ curr
+ '| '
+ line;
}).join('\n');
// Alter exception message
err.path = filename;
err.message = (filename || 'Jade') + ':' + lineno
+ '\n' + context + '\n\n' + err.message;
throw err;
};
}, {"fs": 27}], 25: [function (_dereq_, module, exports) {
'use strict';
// source: http://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements
module.exports = [
'area'
, 'base'
, 'br'
, 'col'
, 'embed'
, 'hr'
, 'img'
, 'input'
, 'keygen'
, 'link'
, 'menuitem'
, 'meta'
, 'param'
, 'source'
, 'track'
, 'wbr'
];
}, {}], 26: [function (_dereq_, module, exports) {
'use strict';
/**
* Merge `b` into `a`.
*
* @param {Object} a
* @param {Object} b
* @return {Object}
* @api public
*/
exports.merge = function (a, b) {
for (var key in b) a[key] = b[key];
return a;
};
}, {}], 27: [function (_dereq_, module, exports) {
}, {}], 28: [function (_dereq_, module, exports) {
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
} else {
// old school shim for old browsers
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
var TempCtor = function () {
}
TempCtor.prototype = superCtor.prototype
ctor.prototype = new TempCtor()
ctor.prototype.constructor = ctor
}
}
}, {}], 29: [function (_dereq_, module, exports) {
// shim for using process in browser
var process = module.exports = {};
process.nextTick = (function () {
var canSetImmediate = typeof window !== 'undefined'
&& window.setImmediate;
var canPost = typeof window !== 'undefined'
&& window.postMessage && window.addEventListener
;
if (canSetImmediate) {
return function (f) {
return window.setImmediate(f)
};
}
if (canPost) {
var queue = [];
window.addEventListener('message', function (ev) {
var source = ev.source;
if ((source === window || source === null) && ev.data === 'process-tick') {
ev.stopPropagation();
if (queue.length > 0) {
var fn = queue.shift();
fn();
}
}
}, true);
return function nextTick(fn) {
queue.push(fn);
window.postMessage('process-tick', '*');
};
}
return function nextTick(fn) {
setTimeout(fn, 0);
};
})();
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.binding = function (name) {
throw new Error('process.binding is not supported');
}
// TODO(shtylman)
process.cwd = function () {
return '/'
};
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
}, {}], 30: [function (_dereq_, module, exports) {
(function (process) {
// Copyright Joyent, Inc. and other Node contributors.
//
// 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.
// resolves . and .. elements in a path array with directory names there
// must be no slashes, empty elements, or device names (c:\) in the array
// (so also no leading and trailing slashes - it does not distinguish
// relative and absolute paths)
function normalizeArray(parts, allowAboveRoot) {
// if the path tries to go above the root, `up` ends up > 0
var up = 0;
for (var i = parts.length - 1; i >= 0; i--) {
var last = parts[i];
if (last === '.') {
parts.splice(i, 1);
} else if (last === '..') {
parts.splice(i, 1);
up++;
} else if (up) {
parts.splice(i, 1);
up--;
}
}
// if the path is allowed to go above the root, restore leading ..s
if (allowAboveRoot) {
for (; up--; up) {
parts.unshift('..');
}
}
return parts;
}
// Split a filename into [root, dir, basename, ext], unix version
// 'root' is just a slash, or nothing.
var splitPathRe =
/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
var splitPath = function (filename) {
return splitPathRe.exec(filename).slice(1);
};
// path.resolve([from ...], to)
// posix version
exports.resolve = function () {
var resolvedPath = '',
resolvedAbsolute = false;
for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
var path = (i >= 0) ? arguments[i] : process.cwd();
// Skip empty and invalid entries
if (typeof path !== 'string') {
throw new TypeError('Arguments to path.resolve must be strings');
} else if (!path) {
continue;
}
resolvedPath = path + '/' + resolvedPath;
resolvedAbsolute = path.charAt(0) === '/';
}
// At this point the path should be resolved to a full absolute path, but
// handle relative paths to be safe (might happen when process.cwd() fails)
// Normalize the path
resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function (p) {
return !!p;
}), !resolvedAbsolute).join('/');
return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
};
// path.normalize(path)
// posix version
exports.normalize = function (path) {
var isAbsolute = exports.isAbsolute(path),
trailingSlash = substr(path, -1) === '/';
// Normalize the path
path = normalizeArray(filter(path.split('/'), function (p) {
return !!p;
}), !isAbsolute).join('/');
if (!path && !isAbsolute) {
path = '.';
}
if (path && trailingSlash) {
path += '/';
}
return (isAbsolute ? '/' : '') + path;
};
// posix version
exports.isAbsolute = function (path) {
return path.charAt(0) === '/';
};
// posix version
exports.join = function () {
var paths = Array.prototype.slice.call(arguments, 0);
return exports.normalize(filter(paths, function (p, index) {
if (typeof p !== 'string') {
throw new TypeError('Arguments to path.join must be strings');
}
return p;
}).join('/'));
};
// path.relative(from, to)
// posix version
exports.relative = function (from, to) {
from = exports.resolve(from).substr(1);
to = exports.resolve(to).substr(1);
function trim(arr) {
var start = 0;
for (; start < arr.length; start++) {
if (arr[start] !== '') break;
}
var end = arr.length - 1;
for (; end >= 0; end--) {
if (arr[end] !== '') break;
}
if (start > end) return [];
return arr.slice(start, end - start + 1);
}
var fromParts = trim(from.split('/'));
var toParts = trim(to.split('/'));
var length = Math.min(fromParts.length, toParts.length);
var samePartsLength = length;
for (var i = 0; i < length; i++) {
if (fromParts[i] !== toParts[i]) {
samePartsLength = i;
break;
}
}
var outputParts = [];
for (var i = samePartsLength; i < fromParts.length; i++) {
outputParts.push('..');
}
outputParts = outputParts.concat(toParts.slice(samePartsLength));
return outputParts.join('/');
};
exports.sep = '/';
exports.delimiter = ':';
exports.dirname = function (path) {
var result = splitPath(path),
root = result[0],
dir = result[1];
if (!root && !dir) {
// No dirname whatsoever
return '.';
}
if (dir) {
// It has a dirname, strip trailing slash
dir = dir.substr(0, dir.length - 1);
}
return root + dir;
};
exports.basename = function (path, ext) {
var f = splitPath(path)[2];
// TODO: make this comparison case-insensitive on windows?
if (ext && f.substr(-1 * ext.length) === ext) {
f = f.substr(0, f.length - ext.length);
}
return f;
};
exports.extname = function (path) {
return splitPath(path)[3];
};
function filter(xs, f) {
if (xs.filter) return xs.filter(f);
var res = [];
for (var i = 0; i < xs.length; i++) {
if (f(xs[i], i, xs)) res.push(xs[i]);
}
return res;
}
// String.prototype.substr - negative index don't work in IE8
var substr = 'ab'.substr(-1) === 'b'
? function (str, start, len) {
return str.substr(start, len)
}
: function (str, start, len) {
if (start < 0) start = str.length + start;
return str.substr(start, len);
}
;
}).call(this, _dereq_("/Users/forbeslindesay/GitHub/jade/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
}, {"/Users/forbeslindesay/GitHub/jade/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js": 29}], 31: [function (_dereq_, module, exports) {
module.exports = function isBuffer(arg) {
return arg && typeof arg === 'object'
&& typeof arg.copy === 'function'
&& typeof arg.fill === 'function'
&& typeof arg.readUInt8 === 'function';
}
}, {}], 32: [function (_dereq_, module, exports) {
(function (process, global) {
// Copyright Joyent, Inc. and other Node contributors.
//
// 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.
var formatRegExp = /%[sdj%]/g;
exports.format = function (f) {
if (!isString(f)) {
var objects = [];
for (var i = 0; i < arguments.length; i++) {
objects.push(inspect(arguments[i]));
}
return objects.join(' ');
}
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(formatRegExp, function (x) {
if (x === '%%') return '%';
if (i >= len) return x;
switch (x) {
case '%s':
return String(args[i++]);
case '%d':
return Number(args[i++]);
case '%j':
try {
return JSON.stringify(args[i++]);
} catch (_) {
return '[Circular]';
}
default:
return x;
}
});
for (var x = args[i]; i < len; x = args[++i]) {
if (isNull(x) || !isObject(x)) {
str += ' ' + x;
} else {
str += ' ' + inspect(x);
}
}
return str;
};
// Mark that a method should not be used.
// Returns a modified function which warns once by default.
// If --no-deprecation is set, then it is a no-op.
exports.deprecate = function (fn, msg) {
// Allow for deprecating things in the process of starting up.
if (isUndefined(global.process)) {
return function () {
return exports.deprecate(fn, msg).apply(this, arguments);
};
}
if (process.noDeprecation === true) {
return fn;
}
var warned = false;
function deprecated() {
if (!warned) {
if (process.throwDeprecation) {
throw new Error(msg);
} else if (process.traceDeprecation) {
console.trace(msg);
} else {
console.error(msg);
}
warned = true;
}
return fn.apply(this, arguments);
}
return deprecated;
};
var debugs = {};
var debugEnviron;
exports.debuglog = function (set) {
if (isUndefined(debugEnviron))
debugEnviron = process.env.NODE_DEBUG || '';
set = set.toUpperCase();
if (!debugs[set]) {
if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
var pid = process.pid;
debugs[set] = function () {
var msg = exports.format.apply(exports, arguments);
console.error('%s %d: %s', set, pid, msg);
};
} else {
debugs[set] = function () {
};
}
}
return debugs[set];
};
/**
* Echos the value of a value. Trys to print the value out
* in the best way possible given the different types.
*
* @param {Object} obj The object to print out.
* @param {Object} opts Optional options object that alters the output.
*/
/* legacy: obj, showHidden, depth, colors*/
function inspect(obj, opts) {
// default options
var ctx = {
seen: [],
stylize: stylizeNoColor
};
// legacy...
if (arguments.length >= 3) ctx.depth = arguments[2];
if (arguments.length >= 4) ctx.colors = arguments[3];
if (isBoolean(opts)) {
// legacy...
ctx.showHidden = opts;
} else if (opts) {
// got an "options" object
exports._extend(ctx, opts);
}
// set default options
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
if (isUndefined(ctx.depth)) ctx.depth = 2;
if (isUndefined(ctx.colors)) ctx.colors = false;
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
if (ctx.colors) ctx.stylize = stylizeWithColor;
return formatValue(ctx, obj, ctx.depth);
}
exports.inspect = inspect;
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = {
'bold': [1, 22],
'italic': [3, 23],
'underline': [4, 24],
'inverse': [7, 27],
'white': [37, 39],
'grey': [90, 39],
'black': [30, 39],
'blue': [34, 39],
'cyan': [36, 39],
'green': [32, 39],
'magenta': [35, 39],
'red': [31, 39],
'yellow': [33, 39]
};
// Don't use 'blue' not visible on cmd.exe
inspect.styles = {
'special': 'cyan',
'number': 'yellow',
'boolean': 'yellow',
'undefined': 'grey',
'null': 'bold',
'string': 'green',
'date': 'magenta',
// "name": intentionally not styling
'regexp': 'red'
};
function stylizeWithColor(str, styleType) {
var style = inspect.styles[styleType];
if (style) {
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
'\u001b[' + inspect.colors[style][1] + 'm';
} else {
return str;
}
}
function stylizeNoColor(str, styleType) {
return str;
}
function arrayToHash(array) {
var hash = {};
array.forEach(function (val, idx) {
hash[val] = true;
});
return hash;
}
function formatValue(ctx, value, recurseTimes) {
// Provide a hook for user-specified inspect functions.
// Check that value is an object with an inspect function on it
if (ctx.customInspect &&
value &&
isFunction(value.inspect) &&
// Filter out the util module, it's inspect function is special
value.inspect !== exports.inspect &&
// Also filter out any prototype objects using the circular check.
!(value.constructor && value.constructor.prototype === value)) {
var ret = value.inspect(recurseTimes, ctx);
if (!isString(ret)) {
ret = formatValue(ctx, ret, recurseTimes);
}
return ret;
}
// Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value);
if (primitive) {
return primitive;
}
// Look up the keys of the object.
var keys = Object.keys(value);
var visibleKeys = arrayToHash(keys);
if (ctx.showHidden) {
keys = Object.getOwnPropertyNames(value);
}
// IE doesn't make error fields non-enumerable
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
if (isError(value)
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
return formatError(value);
}
// Some type of object without properties can be shortcutted.
if (keys.length === 0) {
if (isFunction(value)) {
var name = value.name ? ': ' + value.name : '';
return ctx.stylize('[Function' + name + ']', 'special');
}
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
}
if (isDate(value)) {
return ctx.stylize(Date.prototype.toString.call(value), 'date');
}
if (isError(value)) {
return formatError(value);
}
}
var base = '', array = false, braces = ['{', '}'];
// Make Array say that they are Array
if (isArray(value)) {
array = true;
braces = ['[', ']'];
}
// Make functions say that they are functions
if (isFunction(value)) {
var n = value.name ? ': ' + value.name : '';
base = ' [Function' + n + ']';
}
// Make RegExps say that they are RegExps
if (isRegExp(value)) {
base = ' ' + RegExp.prototype.toString.call(value);
}
// Make dates with properties first say the date
if (isDate(value)) {
base = ' ' + Date.prototype.toUTCString.call(value);
}
// Make error with message first say the error
if (isError(value)) {
base = ' ' + formatError(value);
}
if (keys.length === 0 && (!array || value.length == 0)) {
return braces[0] + base + braces[1];
}
if (recurseTimes < 0) {
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
} else {
return ctx.stylize('[Object]', 'special');
}
}
ctx.seen.push(value);
var output;
if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else {
output = keys.map(function (key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
});
}
ctx.seen.pop();
return reduceToSingleString(output, base, braces);
}
function formatPrimitive(ctx, value) {
if (isUndefined(value))
return ctx.stylize('undefined', 'undefined');
if (isString(value)) {
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
.replace(/'/g, "\\'")
.replace(/\\"/g, '"') + '\'';
return ctx.stylize(simple, 'string');
}
if (isNumber(value))
return ctx.stylize('' + value, 'number');
if (isBoolean(value))
return ctx.stylize('' + value, 'boolean');
// For some reason typeof null is "object", so special case here.
if (isNull(value))
return ctx.stylize('null', 'null');
}
function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']';
}
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
for (var i = 0, l = value.length; i < l; ++i) {
if (hasOwnProperty(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
String(i), true));
} else {
output.push('');
}
}
keys.forEach(function (key) {
if (!key.match(/^\d+$/)) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
key, true));
}
});
return output;
}
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc;
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
if (desc.get) {
if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (desc.set) {
str = ctx.stylize('[Setter]', 'special');
}
}
if (!hasOwnProperty(visibleKeys, key)) {
name = '[' + key + ']';
}
if (!str) {
if (ctx.seen.indexOf(desc.value) < 0) {
if (isNull(recurseTimes)) {
str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (array) {
str = str.split('\n').map(function (line) {
return ' ' + line;
}).join('\n').substr(2);
} else {
str = '\n' + str.split('\n').map(function (line) {
return ' ' + line;
}).join('\n');
}
}
} else {
str = ctx.stylize('[Circular]', 'special');
}
}
if (isUndefined(name)) {
if (array && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'")
.replace(/\\"/g, '"')
.replace(/(^"|"$)/g, "'");
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str;
}
function reduceToSingleString(output, base, braces) {
var numLinesEst = 0;
var length = output.reduce(function (prev, cur) {
numLinesEst++;
if (cur.indexOf('\n') >= 0) numLinesEst++;
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
}, 0);
if (length > 60) {
return braces[0] +
(base === '' ? '' : base + '\n ') +
' ' +
output.join(',\n ') +
' ' +
braces[1];
}
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(ar) {
return Array.isArray(ar);
}
exports.isArray = isArray;
function isBoolean(arg) {
return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;
function isNull(arg) {
return arg === null;
}
exports.isNull = isNull;
function isNullOrUndefined(arg) {
return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;
function isNumber(arg) {
return typeof arg === 'number';
}
exports.isNumber = isNumber;
function isString(arg) {
return typeof arg === 'string';
}
exports.isString = isString;
function isSymbol(arg) {
return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;
function isUndefined(arg) {
return arg === void 0;
}
exports.isUndefined = isUndefined;
function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
exports.isObject = isObject;
function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]';
}
exports.isDate = isDate;
function isError(e) {
return isObject(e) &&
(objectToString(e) === '[object Error]' || e instanceof Error);
}
exports.isError = isError;
function isFunction(arg) {
return typeof arg === 'function';
}
exports.isFunction = isFunction;
function isPrimitive(arg) {
return arg === null ||
typeof arg === 'boolean' ||
typeof arg === 'number' ||
typeof arg === 'string' ||
typeof arg === 'symbol' || // ES6 symbol
typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;
exports.isBuffer = _dereq_('./support/isBuffer');
function objectToString(o) {
return Object.prototype.toString.call(o);
}
function pad(n) {
return n < 10 ? '0' + n.toString(10) : n.toString(10);
}
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
'Oct', 'Nov', 'Dec'];
// 26 Feb 16:19:34
function timestamp() {
var d = new Date();
var time = [pad(d.getHours()),
pad(d.getMinutes()),
pad(d.getSeconds())].join(':');
return [d.getDate(), months[d.getMonth()], time].join(' ');
}
// log is just a thin wrapper to console.log that prepends a timestamp
exports.log = function () {
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
};
/**
* Inherit the prototype methods from one constructor into another.
*
* The Function.prototype.inherits from lang.js rewritten as a standalone
* function (not on Function.prototype). NOTE: If this file is to be loaded
* during bootstrapping this function needs to be rewritten using some native
* functions as prototype setup using normal JavaScript does not work as
* expected during bootstrapping (see mirror.js in r114903).
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype.
* @param {function} superCtor Constructor function to inherit prototype from.
*/
exports.inherits = _dereq_('inherits');
exports._extend = function (origin, add) {
// Don't do anything if add isn't an object
if (!add || !isObject(add)) return origin;
var keys = Object.keys(add);
var i = keys.length;
while (i--) {
origin[keys[i]] = add[keys[i]];
}
return origin;
};
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
}).call(this, _dereq_("/Users/forbeslindesay/GitHub/jade/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"), typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
}, {"./support/isBuffer": 31, "/Users/forbeslindesay/GitHub/jade/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js": 29, "inherits": 28}], 33: [function (_dereq_, module, exports) {
exports = (module.exports = parse);
exports.parse = parse;
function parse(src, state, options) {
options = options || {};
state = state || exports.defaultState();
var start = options.start || 0;
var end = options.end || src.length;
var index = start;
while (index < end) {
if (state.roundDepth < 0 || state.curlyDepth < 0 || state.squareDepth < 0) {
throw new SyntaxError('Mismatched Bracket: ' + src[index - 1]);
}
exports.parseChar(src[index++], state);
}
return state;
}
exports.parseMax = parseMax;
function parseMax(src, options) {
options = options || {};
var start = options.start || 0;
var index = start;
var state = exports.defaultState();
while (state.roundDepth >= 0 && state.curlyDepth >= 0 && state.squareDepth >= 0) {
if (index >= src.length) {
throw new Error('The end of the string was reached with no closing bracket found.');
}
exports.parseChar(src[index++], state);
}
var end = index - 1;
return {
start: start,
end: end,
src: src.substring(start, end)
};
}
exports.parseUntil = parseUntil;
function parseUntil(src, delimiter, options) {
options = options || {};
var includeLineComment = options.includeLineComment || false;
var start = options.start || 0;
var index = start;
var state = exports.defaultState();
while (state.isString() || state.regexp || state.blockComment ||
(!includeLineComment && state.lineComment) || !startsWith(src, delimiter, index)) {
exports.parseChar(src[index++], state);
}
var end = index;
return {
start: start,
end: end,
src: src.substring(start, end)
};
}
exports.parseChar = parseChar;
function parseChar(character, state) {
if (character.length !== 1) throw new Error('Character must be a string of length 1');
state = state || exports.defaultState();
var wasComment = state.blockComment || state.lineComment;
var lastChar = state.history ? state.history[0] : '';
if (state.lineComment) {
if (character === '\n') {
state.lineComment = false;
}
} else if (state.blockComment) {
if (state.lastChar === '*' && character === '/') {
state.blockComment = false;
}
} else if (state.singleQuote) {
if (character === '\'' && !state.escaped) {
state.singleQuote = false;
} else if (character === '\\' && !state.escaped) {
state.escaped = true;
} else {
state.escaped = false;
}
} else if (state.doubleQuote) {
if (character === '"' && !state.escaped) {
state.doubleQuote = false;
} else if (character === '\\' && !state.escaped) {
state.escaped = true;
} else {
state.escaped = false;
}
} else if (state.regexp) {
if (character === '/' && !state.escaped) {
state.regexp = false;
} else if (character === '\\' && !state.escaped) {
state.escaped = true;
} else {
state.escaped = false;
}
} else if (lastChar === '/' && character === '/') {
state.history = state.history.substr(1);
state.lineComment = true;
} else if (lastChar === '/' && character === '*') {
state.history = state.history.substr(1);
state.blockComment = true;
} else if (character === '/' && isRegexp(state.history)) {
state.regexp = true;
} else if (character === '\'') {
state.singleQuote = true;
} else if (character === '"') {
state.doubleQuote = true;
} else if (character === '(') {
state.roundDepth++;
} else if (character === ')') {
state.roundDepth--;
} else if (character === '{') {
state.curlyDepth++;
} else if (character === '}') {
state.curlyDepth--;
} else if (character === '[') {
state.squareDepth++;
} else if (character === ']') {
state.squareDepth--;
}
if (!state.blockComment && !state.lineComment && !wasComment) state.history = character + state.history;
return state;
}
exports.defaultState = function () {
return new State()
};
function State() {
this.lineComment = false;
this.blockComment = false;
this.singleQuote = false;
this.doubleQuote = false;
this.regexp = false;
this.escaped = false;
this.roundDepth = 0;
this.curlyDepth = 0;
this.squareDepth = 0;
this.history = ''
}
State.prototype.isString = function () {
return this.singleQuote || this.doubleQuote;
}
State.prototype.isComment = function () {
return this.lineComment || this.blockComment;
}
State.prototype.isNesting = function () {
return this.isString() || this.isComment() || this.regexp || this.roundDepth > 0 || this.curlyDepth > 0 || this.squareDepth > 0
}
function startsWith(str, start, i) {
return str.substr(i || 0, start.length) === start;
}
exports.isPunctuator = isPunctuator
function isPunctuator(c) {
var code = c.charCodeAt(0)
switch (code) {
case 46: // . dot
case 40: // ( open bracket
case 41: // ) close bracket
case 59: // ; semicolon
case 44: // , comma
case 123: // { open curly brace
case 125: // } close curly brace
case 91: // [
case 93: // ]
case 58: // :
case 63: // ?
case 126: // ~
case 37: // %
case 38: // &
case 42: // *:
case 43: // +
case 45: // -
case 47: // /
case 60: // <
case 62: // >
case 94: // ^
case 124: // |
case 33: // !
case 61: // =
return true;
default:
return false;
}
}
exports.isKeyword = isKeyword
function isKeyword(id) {
return (id === 'if') || (id === 'in') || (id === 'do') || (id === 'var') || (id === 'for') || (id === 'new') ||
(id === 'try') || (id === 'let') || (id === 'this') || (id === 'else') || (id === 'case') ||
(id === 'void') || (id === 'with') || (id === 'enum') || (id === 'while') || (id === 'break') || (id === 'catch') ||
(id === 'throw') || (id === 'const') || (id === 'yield') || (id === 'class') || (id === 'super') ||
(id === 'return') || (id === 'typeof') || (id === 'delete') || (id === 'switch') || (id === 'export') ||
(id === 'import') || (id === 'default') || (id === 'finally') || (id === 'extends') || (id === 'function') ||
(id === 'continue') || (id === 'debugger') || (id === 'package') || (id === 'private') || (id === 'interface') ||
(id === 'instanceof') || (id === 'implements') || (id === 'protected') || (id === 'public') || (id === 'static') ||
(id === 'yield') || (id === 'let');
}
function isRegexp(history) {
//could be start of regexp or divide sign
history = history.replace(/^\s*/, '');
//unless its an `if`, `while`, `for` or `with` it's a divide, so we assume it's a divide
if (history[0] === ')') return false;
//unless it's a function expression, it's a regexp, so we assume it's a regexp
if (history[0] === '}') return true;
//any punctuation means it's a regexp
if (isPunctuator(history[0])) return true;
//if the last thing was a keyword then it must be a regexp (e.g. `typeof /foo/`)
if (/^\w+\b/.test(history) && isKeyword(/^\w+\b/.exec(history)[0].split('').reverse().join(''))) return true;
return false;
}
}, {}], 34: [function (_dereq_, module, exports) {
'use strict'
var uglify = _dereq_('uglify-js')
var lastSRC = '(null)'
var lastRes = true
var lastConstants = undefined;
module.exports = isConstant
function isConstant(src, constants) {
src = '(' + src + ')'
if (lastSRC === src && lastConstants === constants) return lastRes
lastSRC = src
try {
return lastRes = (detect(src).filter(function (key) {
return !constants || !(key in constants)
}).length === 0)
} catch (ex) {
return lastRes = false
}
}
isConstant.isConstant = isConstant
isConstant.toConstant = toConstant
function toConstant(src, constants) {
if (!isConstant(src, constants)) throw new Error(JSON.stringify(src) + ' is not constant.')
return Function(Object.keys(constants || {}).join(','), 'return (' + src + ')').apply(null, Object.keys(constants || {}).map(function (key) {
return constants[key];
}));
}
function detect(src) {
var ast = uglify.parse(src.toString())
ast.figure_out_scope()
var globals = ast.globals
.map(function (node, name) {
return name
})
return globals
}
}, {"uglify-js": 45}], 35: [function (_dereq_, module, exports) {
/*
* Copyright 2009-2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE.txt or:
* http://opensource.org/licenses/BSD-3-Clause
*/
exports.SourceMapGenerator = _dereq_('./source-map/source-map-generator').SourceMapGenerator;
exports.SourceMapConsumer = _dereq_('./source-map/source-map-consumer').SourceMapConsumer;
exports.SourceNode = _dereq_('./source-map/source-node').SourceNode;
}, {"./source-map/source-map-consumer": 40, "./source-map/source-map-generator": 41, "./source-map/source-node": 42}], 36: [function (_dereq_, module, exports) {
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
if (typeof define !== 'function') {
var define = _dereq_('amdefine')(module, _dereq_);
}
define(function (_dereq_, exports, module) {
var util = _dereq_('./util');
/**
* A data structure which is a combination of an array and a set. Adding a new
* member is O(1), testing for membership is O(1), and finding the index of an
* element is O(1). Removing elements from the set is not supported. Only
* strings are supported for membership.
*/
function ArraySet() {
this._array = [];
this._set = {};
}
/**
* Static method for creating ArraySet instances from an existing array.
*/
ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {
var set = new ArraySet();
for (var i = 0, len = aArray.length; i < len; i++) {
set.add(aArray[i], aAllowDuplicates);
}
return set;
};
/**
* Add the given string to this set.
*
* @param String aStr
*/
ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {
var isDuplicate = this.has(aStr);
var idx = this._array.length;
if (!isDuplicate || aAllowDuplicates) {
this._array.push(aStr);
}
if (!isDuplicate) {
this._set[util.toSetString(aStr)] = idx;
}
};
/**
* Is the given string a member of this set?
*
* @param String aStr
*/
ArraySet.prototype.has = function ArraySet_has(aStr) {
return Object.prototype.hasOwnProperty.call(this._set,
util.toSetString(aStr));
};
/**
* What is the index of the given string in the array?
*
* @param String aStr
*/
ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
if (this.has(aStr)) {
return this._set[util.toSetString(aStr)];
}
throw new Error('"' + aStr + '" is not in the set.');
};
/**
* What is the element at the given index?
*
* @param Number aIdx
*/
ArraySet.prototype.at = function ArraySet_at(aIdx) {
if (aIdx >= 0 && aIdx < this._array.length) {
return this._array[aIdx];
}
throw new Error('No element indexed by ' + aIdx);
};
/**
* Returns the array representation of this set (which has the proper indices
* indicated by indexOf). Note that this is a copy of the internal array used
* for storing the members so that no one can mess with internal state.
*/
ArraySet.prototype.toArray = function ArraySet_toArray() {
return this._array.slice();
};
exports.ArraySet = ArraySet;
});
}, {"./util": 43, "amdefine": 44}], 37: [function (_dereq_, module, exports) {
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*
* Based on the Base 64 VLQ implementation in Closure Compiler:
* https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/source
View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment