- use
type-is
module
- lower default limits to 100kb
nodejs_event |
<?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" %* | |
) |
test/ |
node_js: | |
- "0.10" | |
language: node_js |
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 <[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", | |
"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" | |
} |
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.
$ npm install qs
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
Install dev dependencies:
$ npm install -d
and execute:
$ make test
browser:
$ open test/browser/index.html
(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.
test/ | |
.travis.yml |
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 |
test |
{ | |
"name": "bytes", | |
"description": "byte size string parser / serializer", | |
"keywords": ["bytes", "utility"], | |
"version": "0.2.1", | |
"scripts": ["index.js"] | |
} |
/** | |
* 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 <[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.\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" | |
} |
Byte string parser / formatter.
bytes('1kb')
// => 1024
bytes('2mb')
// => 2097152
bytes('1gb')
// => 1073741824
bytes(1073741824)
// => 1gb
bytes(1099511627776)
// => 1tb
$ npm install bytes
$ component install visionmedia/bytes.js
(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 [](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" | |
} |
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.
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'
})
})
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 byteslength
and expected
- the expected length of the streamreceived
- the received bytesstatus
and statusCode
- the corresponding status code for the errortype
- 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.
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.
test.js |
node_js: | |
- "0.10" | |
- "0.11" | |
language: node_js |
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" | |
} |
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 with npm:
npm install mime
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'
Sets the mime type returned when mime.lookup
fails to find the extension searched for. (Default is application/octet-stream
.)
Get the default extension for type
mime.extension('text/html'); // => 'html'
mime.extension('application/octet-stream'); // => 'bin'
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.)
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.
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'
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 [](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" | |
} |
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
}
}
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:
json
. This name will be returned if matched.application/json
.*/json
or application/*
. The full mime type will be returned if matchedfalse
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
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 [](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" | |
} |
Connect's body parsing middleware.
var bodyParser = require('body-parser');
var app = connect();
app.use(bodyParser());
app.use(function (req, res, next) {
console.log(req.body) // populated!
next();
})
Returns middleware that parses both json
and urlencoded
. The options
are passed to both middleware.
Returns middleware that only parses json
. The options are:
strict
- only parse objects and arrayslimit
<1mb> - maximum request body sizereviver
- passed to JSON.parse()
Returns middleware that only parses urlencoded
with the qs module. The options are:
limit
<1mb> - maximum request body sizeThe 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 \n\n \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 \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 \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 <[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.\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" | |
} |
tiny node.js debugging utility modelled after node core's debugging technique.
$ npm install debug
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:
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 &
)
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".
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:".
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);
(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 |
app.del()
-- use app.delete()
insteadres.json(obj, status)
-- use res.json(status, obj)
instead
res.json(status, num)
requires res.status(status).json(num)
res.jsonp(obj, status)
-- use res.jsonp(status, obj)
instead
res.jsonp(status, num)
requires res.status(status).jsonp(num)
req.next
when inside router instanceETag
header in HEAD
requestsContent-Type
for res.jsonp
app.purge
router.purge
app.all
enable()
methodreq.host
for IPv6 literalsres.jsonp
error if callback param is objectres.sendfile
to send
res.header
and res.set
res.attachment
and res.download
send
modulemultipart
as a shorthandexpress.createServer()
- it has been deprecated for a long time. Use express()
app.configure
- use logic in your own app codeapp.router
- is removedreq.auth
- use basic-auth
insteadreq.accepted*
- use req.accepts*()
insteadres.location
- relative URL resolution is removedres.charset
- include the charset in the content type when using res.set()
static
app.route
-> app.mountpath
when mounting an express app in another express appjson spaces
no longer enabled by default in developmentreq.accepts*
-> req.accepts*s
- i.e. req.acceptsEncoding
-> req.acceptsEncodings
req.params
is now an object instead of an arrayres.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 objectreq.accepts*
with acceptsreq.is
with type-isapp.router()
- returns the app Router instanceapp.route()
- Proxy to the app's Router#route()
method to create a new routeapp.del()
-- use app.delete()
insteadres.json(obj, status)
-- use res.json(status, obj)
instead
res.json(status, num)
requires res.status(status).json(num)
res.jsonp(obj, status)
-- use res.jsonp(status, obj)
instead
res.jsonp(status, num)
requires res.status(status).jsonp(num)
app.purge
router.purge
app.all
res.appendHeader
res.headerSent
to return Booleanres.headersSent
for node.js 0.8enable()
methodreq.host
for IPv6 literalsres.jsonp
error if callback param is objectreq.subdomains
when no Host is presentreq.host
when no Host is present, return undefinedreq.host
res.set()
req.subdomains
res.location(url)
implementing res.redirect()
-like setting of Locationreq.auth
res.cookie()
options objectres.send()
Etagsres.redirect()
for old browsers interpreting as htmlmake clean
req.auth
test coverageres.jsonp()
. Closes #1374res.redirect()
status. Closes #1336res.json()
to retain previously defined Content-Types. Closes #1349res.redirect()
to utilize a pathname-relative Location again. Closes #1382res.send()
app.disable('x-powered-by')
)res.jsonp()
. Closes #1307connect.cookieParser()
("s:" prefix was missing) [tnydwrds]res.render()
clobbering of "locals".createServer()
& remove old stale examplesres.redirect()
linkres.redirect("//foo.com")
) supportexpress(1)
-h flag, use -H for hogan. Closes #1245res.sendfile()
socket error handling regressionsend()
root normalization regressionerr.view
property for view errors. Closes #1226res.sendfile()
to use send()
moduleres.send
to use "response-send" moduleapp.locals.use
and res.locals.use
, use regular middlewareres.json(obj, status)
support back for BCreq.auth
req.range(size)
res.links(obj)
res.send(body, status)
support back for backwards compat.default()
support to res.format()
req.fresh
res.send()
freshness check, respect res.statusCode--hjs
to express(1) [nullfirm]fresh
depres.send()
always checks freshness+
support to the routerreq.host
req.param()
to check route firstres.format()
callback to override default 406 behaviourres.redirect()
406. Closes #1154req.ip
{ signed: true }
option to res.cookie()
res.signedCookie()
req.ips
req.ips
[]
in jsonp callback. Closes #1128PORT
env var support in generated template. Closes #1118 [benatkin]app.routes
. Closes #887res.locals.use()
. Closes #1120res.send()
res.set()
values to stringsstatic()
in generated apps below routerres.send()
only set ETag when not previously setmake test
now runs unit / acceptance testsmake benchmark
backres.send()
support for String
objectsres.header()
and req.header()
aliases for BCexpress.createServer()
for BCexpressInit()
middleware self-awareapp.locals.use(callback)
app.locals
objectapp.locals(obj)
res.locals
objectres.locals(obj)
res.format()
for content-negotiationapp.engine()
res.cookie()
JSON cookie supportreq.subdomains
req.protocol
req.secure
req.path
req.ips
req.fresh
req.stale
req.accepts()
res.set(obj)
res.set(field, value)
res.get(field)
app.get(setting)
. Closes #842req.acceptsLanguage()
req.acceptsCharset()
req.accepted
req.acceptedLanguages
req.acceptedCharsets
res.redirect()
. Closes #92--less
support to express(1)express.response
prototypeexpress.request
prototypeexpress.application
prototypeapp.path()
app.render()
res.type()
to replace res.contentType()
res.redirect()
to add relative supportres.redirect('home')
supportreq.notify()
app.register()
app.redirect()
app.is()
app.helpers()
app.dynamicHelpers()
res.sendfile()
with non-GET. Closes #723express(1)
generated app app.address()
before listening
[mmalecki]app.all
duplicate DELETE requests [mscdex]filename
on cached templates [matthewleon]express(1)
eol on 0.4.x. Closes #947req.is()
when a charset is presentmake test-cov
since it wont work with node 0.5.xreq.path
res.redirect()
HEAD support. [reported by xerox]req.flash()
, only escape argsapp.routes.all()
. Closes #803Route
to use a single array of callbacksapp.param()
. Closes #801
Closes #805qs >= 0.3.1
res.redirect()
on windows due to join()
usage. Closes #808res.header()
intention of a set, even when undefined
*
, value no longer requiredres.send(204)
support. Closes #771status
option special-case. Closes #739options.filename
, exposing the view path to template enginesres.json()
JSONP support. Closes #737app.configure()
calls. Closes #735res.send()
using res.json()
path === null
don't default itres.status(code)
res.json()
, an explicit version of res.send(obj)
req.get(field, param)
express(1)
generated app outputs the envcontent-negotiation
examplenpm test
express(1)
express(1)
adds express as a depprepublish
req.route
, exposing the current routeexpress(1)
app.param()
function for optional params. Closes #682../' in
res.partial()` callsapp.options()
Collection
, ex: app.get('/user/:id').remove();
app.param(fn)
to define param logicapp.param()
support for callback with return value.view
as alias for .View
./examples/say
res.sendfile()
bug preventing the transfer of files with spacesapp.match()
as app.match.all()
app.lookup()
as app.lookup.all()
app.remove()
for app.remove.all()
app.remove.VERB()
res.clearCookie()
res.helpers()
as alias of res.locals()
res.send()
. Closes #632. [Daniel * Dependency connect >= 1.4.0
app.param()
callbacks once per route middleware.
Closes #638res.download()
connection errorsfilename
option passing to template engineAdded 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
app.lookup.VERB()
, ex app.lookup.put('/user/:id')
. Closes #606app.match.VERB()
, ex app.match.put('/user/12')
. Closes #606app.VERB(path)
as alias of app.lookup.VERB()
.connect >= 1.2.0
err.view
object when failing to locate a viewres.partial()
call next(err)
when no callback is given [reported by aheckmann]res.send(undefined)
responds with 204 [aheckmann]<root>/_?<name>
partial lookup support. Closes #447request
, response
, and app
local variablessettings
local variable, containing the app's settingsreq.flash()
exception if req.session
is not availableres.send(bool)
support (json response)res.render()
res.locals()
without object returns the localsres.locals(obj)
to compliment res.local(key, val)
res.partial()
callback supportres.render()
partial()
"locals" are now optionalSlowBuffer
support. Closes #584 [reported by tyrda01]{req,res}.app
reference when mounting [Ben Weaver]HTTPSServer
constructorres.contentType()
literal
The original res.contentType('.json')
,
res.contentType('application/json')
, and res.contentType('json')
will work now.res.render()
status option support backres.render()
.charset
support (via connect 1.0.4)./views/user/index.jade
if you create
./views/user/layout.jade
it will be used in favour of the root layout.res.redirect()
. RFC states absolute url [reported by unlink]res.send()
string charset to utf8Partial
constructor (not currently used).locals
support back to aid in migration processres.cookie()
maxAge supportreq.header()
Referrer / Referer special-case, either worksres.redirect()
, now respects the mount-pointunion()
util, taking place of merge(clone())
combores.local(name, val)
for progressive view localsreq.param(name, default)
app.disabled()
and app.enabled()
app.register()
support for omitting leading ".", either worksres.partial()
, using the same interface as partial()
within a view. Closes #539app.param()
to map route params to async/sync logicapp.helpers()
as app.locals()
. Closes #481res.contentType()
cache views
setting, defaulting to enabled in "production" envreq.accepts()
support for extensionsres.download()
and res.sendfile()
now utilize Connect's
static file server connect.static.send()
.connect.utils.mime()
with npm mime modulereq.query
to be pre-defined (via middleware or other parentengine.render(str, options, callback)
, now engine.compile(str, options) -> Function
, the returned function accepts fn(locals)
.req.param()
bug returning Array.prototype methods. Closes #552Stream#pipe()
instead of sys.pump()
in res.sendfile()
req.query
to be pre-defined (via middleware or other parent app)render()
setting inheritance.
Mounted apps would not inherit "view engine"view engine
setting bug when period is in dirnamesession()
callqs
dependency to package.jsonrequire()
s for latest connect supportconnect.router
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.partial('forum/post', postObject)
will
give you the post object, providing a meaningful default.res.redirect()
bodyres.redirect()
supporting text/plain and text/html via Accept.req.is()
to aid in content negotiationapp.all()
support [thanks aheckmann]partial('user', user)
providing the "user" local,
vs previously partial('user', { object: user })
.partial()
support for array-like collections. Closes #434res.sendfile()
(and res.download()
etc)express(1)
generated app using 2 spaces instead of 4express(1)
app generation. Closes #391app.flashFormatters
res.sendfile()
using sys.pump()
when >= "stream threshold"res.sendfile()
res.send()
HEAD supportres.clearCookie()
res.cookie()
res.render()
headers optionres.redirect()
response bodiesres.render()
status option support. Closes #425 [thanks aheckmann]res.sendfile()
responding with 403 on malicious pathres.download()
bug; when an error occurs remove Content-Dispositionres.send()
204. Closes #419res.header()
. Closes #402listenFD()
is called instead of listen()
. [thanks guillermo]app.register()
for template engine mapping. Closes #390res.render()
callback support as second argument (no options)res.download()
res.sendfile()
express.middlewareName()
vs connect.middlewareName()
express(1)
generated app. Closes #384res.sendfile()
error handling, defer via next()
res.render()
callback when a layout is used [thanks guillermo]make install
creating ~/.node_libraries when not presentAdded 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
Server
constructorServer#helpers()
for view localsServer#dynamicHelpers()
for dynamic view locals. Closes #349Server#route
for mounted apps. Closes #363res.render()
exceptions, now passed to next()
when no callback is given [thanks guillermo]Array
checks, now Array.isArray()
helpers
export which act as additional local variablesmake install
(for the executable)express
executable for setting up simple app templatesAdded 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
make init
for submodulesmake init
to work with older versions of gitmake test
now builds libxmljs.node before testingmodule.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 |
test/ |
node_js: | |
- "0.10" | |
- "0.11" | |
language: node_js |
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" | |
} |
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 with npm:
npm install mime
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'
Sets the mime type returned when mime.lookup
fails to find the extension searched for. (Default is application/octet-stream
.)
Get the default extension for type
mime.extension('text/html'); // => 'html'
mime.extension('application/octet-stream'); // => 'bin'
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.)
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.
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'
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 |
examples | |
test | |
.travis.yml |
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 [](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" | |
} |
An HTTP content negotiator for node.js written in javascript.
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
.
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.
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
.
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.
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
.
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.
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
.
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.
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 [](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" | |
} |
Higher level content negotation based on negotiator. Extracted from koa for general use.
In addition to negotatior, it allows:
(['text/html', 'application/json'])
as well as ('text/html', 'application/json')
.json
.false
when no types match*
var accepts = require('accepts')
http.createServer(function (req, res) {
var accept = accepts(req)
})
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
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
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.
node_modules |
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[](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]" | |
} |
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
npm install buffer-crc32
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>
This was tested against the output of zlib's crc32 method. You can run
the tests withnpm test
(requires tap)
https://github.com/alexgorbatchev/node-crc, crc.buffer.crc32
also
supports buffer inputs and return unsigned ints (thanks @tjholowaychuk).
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 \n\n \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 \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 \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 <[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.\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" | |
} |
tiny node.js debugging utility modelled after node core's debugging technique.
$ npm install debug
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:
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:
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".
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:".
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);
(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.
components | |
build |
{ | |
"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, '&') | |
.replace(/"/g, '"') | |
.replace(/'/g, ''') | |
.replace(/</g, '<') | |
.replace(/>/g, '>'); | |
} |
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]" | |
} |
test |
/** | |
* 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 <[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", | |
"bugs": { | |
"url": "https://github.com/visionmedia/node-fresh/issues" | |
}, | |
"homepage": "https://github.com/visionmedia/node-fresh", | |
"_id": "[email protected]", | |
"_from": "[email protected]" | |
} |
HTTP response freshness testing
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.
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
$ npm install fresh
(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 [](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 objects using descriptors.
var thing = {
get name() {
return 'jon'
}
}
var animal = {
}
merge(animal, thing)
animal.name === 'jon'
Overwrites destination
's descriptors with source
's.
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.
node_modules/ |
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" | |
} |
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]" | |
} |
Parse a URL with memoization.
pathname
can then be passed to a router or something.
(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.
node_modules | |
coverage |
{ | |
"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" | |
} |
/** | |
* 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" | |
} |
Turn an Express-style path string such as /user/:name
into a regular expression.
var pathToRegexp = require('path-to-regexp');
var keys = [];
var exp = pathToRegexp('/foo/:bar', keys);
//keys = ['bar']
//exp = /^\/foo\/(?:([^\/]+?))\/?$/i
You can see a live demo of this library in use at express-route-tester.
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 <[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", | |
"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" | |
} |
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.
$ npm install qs
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
Install dev dependencies:
$ npm install -d
and execute:
$ make test
browser:
$ open test/browser/index.html
(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.
test |
/** | |
* 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 <[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", | |
"bugs": { | |
"url": "https://github.com/visionmedia/node-range-parser/issues" | |
}, | |
"homepage": "https://github.com/visionmedia/node-range-parser", | |
"_id": "[email protected]", | |
"_from": "[email protected]" | |
} |
Range header field parser.
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 }]));
$ npm install range-parser
(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.
test | |
examples | |
*.sock |
module.exports = require('./lib/send'); |
/** | |
* 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, '&') | |
.replace(/</g, '<') | |
.replace(/>/g, '>') | |
.replace(/"/g, '"'); | |
}; |
/** | |
* 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 \n\n \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 \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 \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 <[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.\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" | |
} |
tiny node.js debugging utility modelled after node core's debugging technique.
$ npm install debug
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:
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:
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".
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:".
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);
(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" | |
} |
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 with npm:
npm install mime
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'
Sets the mime type returned when mime.lookup
fails to find the extension searched for. (Default is application/octet-stream
.)
Get the default extension for type
mime.extension('text/html'); // => 'html'
mime.extension('application/octet-stream'); // => 'bin'
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.)
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.
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'
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 <[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.\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 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.
$ npm install send
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);
Enable or disable etag generation, defaults to true.
Enable or disable transfer of hidden files, defaults to false.
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.
Provide a max-age in milliseconds for http caching, defaults to 0.
Serve files relative to path
.
error
an error occurred (err)
directory
a directory was requestedfile
a file was requested (path, stat)
stream
file streaming has started (stream)
end
streaming has completedEnable or disable etag generation, defaults to true.
Serve files relative to path
. Aliased as .from(dir)
.
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.
Provide a max-age in milliseconds for http caching, defaults to 0.
Enable or disable transfer of hidden files, defaults to false.
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.
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 ;).
To enable debug()
instrumentation output export DEBUG:
$ DEBUG=send node app
$ npm install
$ make test
(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.
test |
language: node_js | |
node_js: | |
- "0.8" | |
- "0.10" | |
- "0.11" |
send
moduleconnect
/*! | |
* 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, '&') | |
.replace(/</g, '<') | |
.replace(/>/g, '>') | |
.replace(/"/g, '"'); | |
}; | |
/** | |
* 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[](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" | |
} |
Previously connect.static()
.
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();
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.
test.js |
node_js: | |
- "0.10" | |
- "0.11" | |
language: node_js |
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" | |
} |
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 with npm:
npm install mime
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'
Sets the mime type returned when mime.lookup
fails to find the extension searched for. (Default is application/octet-stream
.)
Get the default extension for type
mime.extension('text/html'); // => 'html'
mime.extension('application/octet-stream'); // => 'bin'
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.)
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.
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'
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 [](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" | |
} |
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
}
}
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:
json
. This name will be returned if matched.application/json
.*/json
or application/*
. The full mime type will be returned if matchedfalse
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
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[](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]" | |
} |
Merges the properties from a source object into a destination object.
$ npm install utils-merge
var a = { foo: 'bar' }
, b = { bar: 'baz' };
merge(a, b);
// => { foo: 'bar', bar: 'baz' }
$ npm install
$ npm test
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": "[](http://expressjs.com/)\n\n Fast, unopinionated, minimalist web framework for [node](http://nodejs.org).\n\n [](https://travis-ci.org/visionmedia/express) [](https://www.gittip.com/visionmedia/) [](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" | |
} |
Fast, unopinionated, minimalist web framework for node.
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.
$ npm install express
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
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.
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:
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
Author: TJ Holowaychuk
Lead Maintainer: Roman Shtylman
Contributors: https://github.com/visionmedia/express/graphs/contributors
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'); |
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>
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} <#{email}>
outputs <div id="user">tj <[email protected]></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
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>
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>
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 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
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
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)
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>
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 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>
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
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
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
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
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 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 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>
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. |
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.
via npm:
$ npm install jade
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
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));
filename
Used in exceptions, and required when using includescompileDebug
When false
no debug instrumentation is compiledpretty
Add pretty-indentation whitespace to output (false by default)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.
After installing the latest version of node, install with:
$ npm install jade -g
and run with
$ jade --help
Tutorials:
Implementations in other languages:
Other:
MIT
Jade 是一个高性能的模板引擎,它深受 Haml 影响,它是用 JavaScript 实现的, 并且可以供 Node 使用.
翻译: 草依山 等
从 Jade v0.31.0
开始放弃了对于 <script>
和 <style>
标签的平文本支持. 这个问题你可以在 <script> <style>
标签后加上 .
来解决.
希望这一点能让 Jade 对新手更友好, 同时也不影响到 Jade 本身的能力或者导致过度冗长.
如果你有大量的文件需要转换你可以用下 fix-jade 尝试自动完成这个过程.
你可以在网上试玩 Jade.
!!! 5
文档类型)filters
修改树each
枚举对象、数组甚至是不能枚举的对象:stylus
必须已经安装 stylus:less
必须已经安装 less.js:markdown
必须已经安装 markdown-js 或者 node-discount:cdata
:coffeescript
必须已经安装coffee-script通过 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("");
}
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
)CRLF 和 CR 会在编译之前被转换为 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} <#{email}>
它会被渲染为 <div id="user">tj <[email protected]></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
表达式按下面这样的形式写:
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
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 支持通过 block
和 extends
关键字来实现模板继承。 一个块就是一个 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
里又定义了两个可以被实现的块 sidebar
和 primary
,或者子模板直接实现 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 append
或 block prepend
时 block
是可选的:
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/head
和 includes/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 在编译的模板里会被 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("");
}
通过执行 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 [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
相应做了交换
(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.
!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, ''') + "'"; | |
} 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, '&') | |
.replace(/</g, '<') | |
.replace(/>/g, '>') | |
.replace(/"/g, '"'); | |
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 |
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)