Initial commit
This commit is contained in:
+24
@@ -0,0 +1,24 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2012-2014 Federico Romero
|
||||
Copyright (c) 2012-2014 Isaac Z. Schlueter
|
||||
Copyright (c) 2014-2015 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.
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
# negotiator
|
||||
|
||||
[![NPM Version][npm-image]][npm-url]
|
||||
[![NPM Downloads][downloads-image]][downloads-url]
|
||||
[![Node.js Version][node-version-image]][node-version-url]
|
||||
[![Build Status][github-actions-ci-image]][github-actions-ci-url]
|
||||
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||
|
||||
An HTTP content negotiator for Node.js
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
$ npm install negotiator
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```js
|
||||
var Negotiator = require('negotiator')
|
||||
```
|
||||
|
||||
### Accept Negotiation
|
||||
|
||||
```js
|
||||
availableMediaTypes = ['text/html', 'text/plain', 'application/json']
|
||||
|
||||
// The negotiator constructor receives a request object
|
||||
negotiator = new Negotiator(request)
|
||||
|
||||
// Let's say Accept header is 'text/html, application/*;q=0.2, image/jpeg;q=0.8'
|
||||
|
||||
negotiator.mediaTypes()
|
||||
// -> ['text/html', 'image/jpeg', 'application/*']
|
||||
|
||||
negotiator.mediaTypes(availableMediaTypes)
|
||||
// -> ['text/html', 'application/json']
|
||||
|
||||
negotiator.mediaType(availableMediaTypes)
|
||||
// -> 'text/html'
|
||||
```
|
||||
|
||||
You can check a working example at `examples/accept.js`.
|
||||
|
||||
#### Methods
|
||||
|
||||
##### mediaType()
|
||||
|
||||
Returns the most preferred media type from the client.
|
||||
|
||||
##### mediaType(availableMediaType)
|
||||
|
||||
Returns the most preferred media type from a list of available media types.
|
||||
|
||||
##### mediaTypes()
|
||||
|
||||
Returns an array of preferred media types ordered by the client preference.
|
||||
|
||||
##### mediaTypes(availableMediaTypes)
|
||||
|
||||
Returns an array of preferred media types ordered by priority from a list of
|
||||
available media types.
|
||||
|
||||
### Accept-Language Negotiation
|
||||
|
||||
```js
|
||||
negotiator = new Negotiator(request)
|
||||
|
||||
availableLanguages = ['en', 'es', 'fr']
|
||||
|
||||
// Let's say Accept-Language header is 'en;q=0.8, es, pt'
|
||||
|
||||
negotiator.languages()
|
||||
// -> ['es', 'pt', 'en']
|
||||
|
||||
negotiator.languages(availableLanguages)
|
||||
// -> ['es', 'en']
|
||||
|
||||
language = negotiator.language(availableLanguages)
|
||||
// -> 'es'
|
||||
```
|
||||
|
||||
You can check a working example at `examples/language.js`.
|
||||
|
||||
#### Methods
|
||||
|
||||
##### language()
|
||||
|
||||
Returns the most preferred language from the client.
|
||||
|
||||
##### language(availableLanguages)
|
||||
|
||||
Returns the most preferred language from a list of available languages.
|
||||
|
||||
##### languages()
|
||||
|
||||
Returns an array of preferred languages ordered by the client preference.
|
||||
|
||||
##### languages(availableLanguages)
|
||||
|
||||
Returns an array of preferred languages ordered by priority from a list of
|
||||
available languages.
|
||||
|
||||
### Accept-Charset Negotiation
|
||||
|
||||
```js
|
||||
availableCharsets = ['utf-8', 'iso-8859-1', 'iso-8859-5']
|
||||
|
||||
negotiator = new Negotiator(request)
|
||||
|
||||
// Let's say Accept-Charset header is 'utf-8, iso-8859-1;q=0.8, utf-7;q=0.2'
|
||||
|
||||
negotiator.charsets()
|
||||
// -> ['utf-8', 'iso-8859-1', 'utf-7']
|
||||
|
||||
negotiator.charsets(availableCharsets)
|
||||
// -> ['utf-8', 'iso-8859-1']
|
||||
|
||||
negotiator.charset(availableCharsets)
|
||||
// -> 'utf-8'
|
||||
```
|
||||
|
||||
You can check a working example at `examples/charset.js`.
|
||||
|
||||
#### Methods
|
||||
|
||||
##### charset()
|
||||
|
||||
Returns the most preferred charset from the client.
|
||||
|
||||
##### charset(availableCharsets)
|
||||
|
||||
Returns the most preferred charset from a list of available charsets.
|
||||
|
||||
##### charsets()
|
||||
|
||||
Returns an array of preferred charsets ordered by the client preference.
|
||||
|
||||
##### charsets(availableCharsets)
|
||||
|
||||
Returns an array of preferred charsets ordered by priority from a list of
|
||||
available charsets.
|
||||
|
||||
### Accept-Encoding Negotiation
|
||||
|
||||
```js
|
||||
availableEncodings = ['identity', 'gzip']
|
||||
|
||||
negotiator = new Negotiator(request)
|
||||
|
||||
// Let's say Accept-Encoding header is 'gzip, compress;q=0.2, identity;q=0.5'
|
||||
|
||||
negotiator.encodings()
|
||||
// -> ['gzip', 'identity', 'compress']
|
||||
|
||||
negotiator.encodings(availableEncodings)
|
||||
// -> ['gzip', 'identity']
|
||||
|
||||
negotiator.encoding(availableEncodings)
|
||||
// -> 'gzip'
|
||||
```
|
||||
|
||||
You can check a working example at `examples/encoding.js`.
|
||||
|
||||
#### Methods
|
||||
|
||||
##### encoding()
|
||||
|
||||
Returns the most preferred encoding from the client.
|
||||
|
||||
##### encoding(availableEncodings)
|
||||
|
||||
Returns the most preferred encoding from a list of available encodings.
|
||||
|
||||
##### encoding(availableEncodings, { preferred })
|
||||
|
||||
Returns the most preferred encoding from a list of available encodings, while prioritizing based on `preferred` array between same-quality encodings.
|
||||
|
||||
##### encodings()
|
||||
|
||||
Returns an array of preferred encodings ordered by the client preference.
|
||||
|
||||
##### encodings(availableEncodings)
|
||||
|
||||
Returns an array of preferred encodings ordered by priority from a list of
|
||||
available encodings.
|
||||
|
||||
##### encodings(availableEncodings, { preferred })
|
||||
|
||||
Returns an array of preferred encodings ordered by priority from a list of
|
||||
available encodings, while prioritizing based on `preferred` array between same-quality encodings.
|
||||
|
||||
## See Also
|
||||
|
||||
The [accepts](https://npmjs.org/package/accepts#readme) module builds on
|
||||
this module and provides an alternative interface, mime type validation,
|
||||
and more.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/negotiator.svg
|
||||
[npm-url]: https://npmjs.org/package/negotiator
|
||||
[node-version-image]: https://img.shields.io/node/v/negotiator.svg
|
||||
[node-version-url]: https://nodejs.org/en/download/
|
||||
[coveralls-image]: https://img.shields.io/coveralls/jshttp/negotiator/master.svg
|
||||
[coveralls-url]: https://coveralls.io/r/jshttp/negotiator?branch=master
|
||||
[downloads-image]: https://img.shields.io/npm/dm/negotiator.svg
|
||||
[downloads-url]: https://npmjs.org/package/negotiator
|
||||
[github-actions-ci-image]: https://img.shields.io/github/workflow/status/jshttp/negotiator/ci/master?label=ci
|
||||
[github-actions-ci-url]: https://github.com/jshttp/negotiator/actions/workflows/ci.yml
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/*!
|
||||
* negotiator
|
||||
* Copyright(c) 2012 Federico Romero
|
||||
* Copyright(c) 2012-2014 Isaac Z. Schlueter
|
||||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var preferredCharsets = require('./lib/charset')
|
||||
var preferredEncodings = require('./lib/encoding')
|
||||
var preferredLanguages = require('./lib/language')
|
||||
var preferredMediaTypes = require('./lib/mediaType')
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = Negotiator;
|
||||
module.exports.Negotiator = Negotiator;
|
||||
|
||||
/**
|
||||
* Create a Negotiator instance from a request.
|
||||
* @param {object} request
|
||||
* @public
|
||||
*/
|
||||
|
||||
function Negotiator(request) {
|
||||
if (!(this instanceof Negotiator)) {
|
||||
return new Negotiator(request);
|
||||
}
|
||||
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
Negotiator.prototype.charset = function charset(available) {
|
||||
var set = this.charsets(available);
|
||||
return set && set[0];
|
||||
};
|
||||
|
||||
Negotiator.prototype.charsets = function charsets(available) {
|
||||
return preferredCharsets(this.request.headers['accept-charset'], available);
|
||||
};
|
||||
|
||||
Negotiator.prototype.encoding = function encoding(available, opts) {
|
||||
var set = this.encodings(available, opts);
|
||||
return set && set[0];
|
||||
};
|
||||
|
||||
Negotiator.prototype.encodings = function encodings(available, options) {
|
||||
var opts = options || {};
|
||||
return preferredEncodings(this.request.headers['accept-encoding'], available, opts.preferred);
|
||||
};
|
||||
|
||||
Negotiator.prototype.language = function language(available) {
|
||||
var set = this.languages(available);
|
||||
return set && set[0];
|
||||
};
|
||||
|
||||
Negotiator.prototype.languages = function languages(available) {
|
||||
return preferredLanguages(this.request.headers['accept-language'], available);
|
||||
};
|
||||
|
||||
Negotiator.prototype.mediaType = function mediaType(available) {
|
||||
var set = this.mediaTypes(available);
|
||||
return set && set[0];
|
||||
};
|
||||
|
||||
Negotiator.prototype.mediaTypes = function mediaTypes(available) {
|
||||
return preferredMediaTypes(this.request.headers.accept, available);
|
||||
};
|
||||
|
||||
// Backwards compatibility
|
||||
Negotiator.prototype.preferredCharset = Negotiator.prototype.charset;
|
||||
Negotiator.prototype.preferredCharsets = Negotiator.prototype.charsets;
|
||||
Negotiator.prototype.preferredEncoding = Negotiator.prototype.encoding;
|
||||
Negotiator.prototype.preferredEncodings = Negotiator.prototype.encodings;
|
||||
Negotiator.prototype.preferredLanguage = Negotiator.prototype.language;
|
||||
Negotiator.prototype.preferredLanguages = Negotiator.prototype.languages;
|
||||
Negotiator.prototype.preferredMediaType = Negotiator.prototype.mediaType;
|
||||
Negotiator.prototype.preferredMediaTypes = Negotiator.prototype.mediaTypes;
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*!
|
||||
* negotiator
|
||||
* Copyright(c) 2026 Blake Embrey
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var contentType = require('content-type');
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @private
|
||||
*/
|
||||
|
||||
module.exports = parseAccept;
|
||||
|
||||
/**
|
||||
* Parse an Accept-style header.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseAccept(header) {
|
||||
var values = [];
|
||||
var index = 0;
|
||||
|
||||
while (index < header.length) {
|
||||
var start = skipOptionalWhitespace(header, index);
|
||||
var parsed = contentType.parse(header, { comma: true, start: start });
|
||||
|
||||
// `content-type` normalizes the type, but accept methods return original casing.
|
||||
parsed.type = header.slice(start, start + parsed.type.length);
|
||||
values.push(parsed);
|
||||
|
||||
index = parsed.index + 1;
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip optional whitespace.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function skipOptionalWhitespace(header, index) {
|
||||
var cursor = index;
|
||||
|
||||
while (header.charCodeAt(cursor) === 0x20 || header.charCodeAt(cursor) === 0x09) {
|
||||
cursor++;
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
/**
|
||||
* negotiator
|
||||
* Copyright(c) 2012 Isaac Z. Schlueter
|
||||
* Copyright(c) 2014 Federico Romero
|
||||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var parseAccept = require('./accept');
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = preferredCharsets;
|
||||
module.exports.preferredCharsets = preferredCharsets;
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseAcceptCharset(accept) {
|
||||
var accepts = parseAccept(accept);
|
||||
|
||||
for (var i = 0, j = 0; i < accepts.length; i++) {
|
||||
var charset = formatCharset(accepts[i], i);
|
||||
if (charset) accepts[j++] = charset;
|
||||
}
|
||||
|
||||
accepts.length = j;
|
||||
return accepts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a parsed charset for negotiation.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function formatCharset(parsed, i) {
|
||||
if (!parsed.type) return null;
|
||||
|
||||
return {
|
||||
charset: parsed.type,
|
||||
q: parsed.parameters.q ? parseFloat(parsed.parameters.q) : 1,
|
||||
i: i
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the priority of a charset.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getCharsetPriority(charset, accepted, index) {
|
||||
var priority = {o: -1, q: 0, s: 0};
|
||||
|
||||
for (var i = 0; i < accepted.length; i++) {
|
||||
var spec = specify(charset, accepted[i], index);
|
||||
|
||||
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
||||
priority = spec;
|
||||
}
|
||||
}
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specificity of the charset.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function specify(charset, spec, index) {
|
||||
var s = 0;
|
||||
if(spec.charset.toLowerCase() === charset.toLowerCase()){
|
||||
s |= 1;
|
||||
} else if (spec.charset !== '*' ) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
i: index,
|
||||
o: spec.i,
|
||||
q: spec.q,
|
||||
s: s
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the preferred charsets from an Accept-Charset header.
|
||||
* @public
|
||||
*/
|
||||
|
||||
function preferredCharsets(accept, provided) {
|
||||
// RFC 2616 sec 14.2: no header = *
|
||||
var accepts = parseAcceptCharset(accept === undefined ? '*' : accept || '');
|
||||
|
||||
if (!provided) {
|
||||
// sorted list of all charsets
|
||||
return accepts
|
||||
.filter(isQuality)
|
||||
.sort(compareSpecs)
|
||||
.map(getFullCharset);
|
||||
}
|
||||
|
||||
var priorities = provided.map(function getPriority(type, index) {
|
||||
return getCharsetPriority(type, accepts, index);
|
||||
});
|
||||
|
||||
// sorted list of accepted charsets
|
||||
return priorities.filter(isQuality).sort(compareSpecs).map(function getCharset(priority) {
|
||||
return provided[priorities.indexOf(priority)];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two specs.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function compareSpecs(a, b) {
|
||||
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full charset string.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getFullCharset(spec) {
|
||||
return spec.charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a spec has any quality.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function isQuality(spec) {
|
||||
return spec.q > 0;
|
||||
}
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* negotiator
|
||||
* Copyright(c) 2012 Isaac Z. Schlueter
|
||||
* Copyright(c) 2014 Federico Romero
|
||||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var parseAccept = require('./accept');
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = preferredEncodings;
|
||||
module.exports.preferredEncodings = preferredEncodings;
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseAcceptEncoding(accept) {
|
||||
var accepts = parseAccept(accept);
|
||||
var hasIdentity = false;
|
||||
var minQuality = 1;
|
||||
|
||||
for (var i = 0, j = 0; i < accepts.length; i++) {
|
||||
var encoding = formatEncoding(accepts[i], i);
|
||||
|
||||
if (encoding) {
|
||||
accepts[j++] = encoding;
|
||||
hasIdentity = hasIdentity || specify('identity', encoding);
|
||||
minQuality = Math.min(minQuality, encoding.q || 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasIdentity) {
|
||||
/*
|
||||
* If identity doesn't explicitly appear in the accept-encoding header,
|
||||
* it's added to the list of acceptable encoding with the lowest q
|
||||
*/
|
||||
accepts[j++] = {
|
||||
encoding: 'identity',
|
||||
q: minQuality,
|
||||
i: i
|
||||
};
|
||||
}
|
||||
|
||||
accepts.length = j;
|
||||
return accepts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a parsed encoding for negotiation.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function formatEncoding(parsed, i) {
|
||||
if (!parsed.type) return null;
|
||||
|
||||
return {
|
||||
encoding: parsed.type,
|
||||
q: parsed.parameters.q ? parseFloat(parsed.parameters.q) : 1,
|
||||
i: i
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the priority of an encoding.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getEncodingPriority(encoding, accepted, index) {
|
||||
var priority = {encoding: encoding, o: -1, q: 0, s: 0};
|
||||
|
||||
for (var i = 0; i < accepted.length; i++) {
|
||||
var spec = specify(encoding, accepted[i], index);
|
||||
|
||||
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
||||
priority = spec;
|
||||
}
|
||||
}
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specificity of the encoding.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function specify(encoding, spec, index) {
|
||||
var s = 0;
|
||||
if(spec.encoding.toLowerCase() === encoding.toLowerCase()){
|
||||
s |= 1;
|
||||
} else if (spec.encoding !== '*' ) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
encoding: encoding,
|
||||
i: index,
|
||||
o: spec.i,
|
||||
q: spec.q,
|
||||
s: s
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the preferred encodings from an Accept-Encoding header.
|
||||
* @public
|
||||
*/
|
||||
|
||||
function preferredEncodings(accept, provided, preferred) {
|
||||
var accepts = parseAcceptEncoding(accept || '');
|
||||
|
||||
var comparator = preferred ? function comparator (a, b) {
|
||||
if (a.q !== b.q) {
|
||||
return b.q - a.q // higher quality first
|
||||
}
|
||||
|
||||
var aPreferred = preferred.indexOf(a.encoding)
|
||||
var bPreferred = preferred.indexOf(b.encoding)
|
||||
|
||||
if (aPreferred === -1 && bPreferred === -1) {
|
||||
// consider the original specifity/order
|
||||
return (b.s - a.s) || (a.o - b.o) || (a.i - b.i)
|
||||
}
|
||||
|
||||
if (aPreferred !== -1 && bPreferred !== -1) {
|
||||
return aPreferred - bPreferred // consider the preferred order
|
||||
}
|
||||
|
||||
return aPreferred === -1 ? 1 : -1 // preferred first
|
||||
} : compareSpecs;
|
||||
|
||||
if (!provided) {
|
||||
// sorted list of all encodings
|
||||
return accepts
|
||||
.filter(isQuality)
|
||||
.sort(comparator)
|
||||
.map(getFullEncoding);
|
||||
}
|
||||
|
||||
var priorities = provided.map(function getPriority(type, index) {
|
||||
return getEncodingPriority(type, accepts, index);
|
||||
});
|
||||
|
||||
// sorted list of accepted encodings
|
||||
return priorities.filter(isQuality).sort(comparator).map(function getEncoding(priority) {
|
||||
return provided[priorities.indexOf(priority)];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two specs.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function compareSpecs(a, b) {
|
||||
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full encoding string.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getFullEncoding(spec) {
|
||||
return spec.encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a spec has any quality.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function isQuality(spec) {
|
||||
return spec.q > 0;
|
||||
}
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* negotiator
|
||||
* Copyright(c) 2012 Isaac Z. Schlueter
|
||||
* Copyright(c) 2014 Federico Romero
|
||||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var contentType = require('content-type');
|
||||
var parseAccept = require('./accept');
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = preferredLanguages;
|
||||
module.exports.preferredLanguages = preferredLanguages;
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseAcceptLanguage(accept) {
|
||||
var accepts = parseAccept(accept);
|
||||
|
||||
for (var i = 0, j = 0; i < accepts.length; i++) {
|
||||
var language = formatLanguage(accepts[i], i);
|
||||
if (language) accepts[j++] = language;
|
||||
}
|
||||
|
||||
accepts.length = j;
|
||||
return accepts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a parsed language for negotiation.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function formatLanguage(parsed, i) {
|
||||
if (!parsed.type) return null;
|
||||
|
||||
var hyphen = parsed.type.indexOf('-');
|
||||
var prefix = hyphen === -1 ? parsed.type : parsed.type.slice(0, hyphen);
|
||||
var suffix = hyphen === -1 ? undefined : parsed.type.slice(hyphen + 1);
|
||||
|
||||
return {
|
||||
prefix: prefix,
|
||||
suffix: suffix,
|
||||
q: parsed.parameters.q ? parseFloat(parsed.parameters.q) : 1,
|
||||
i: i,
|
||||
full: parsed.type
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the priority of a language.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getLanguagePriority(language, accepted, index) {
|
||||
var priority = {o: -1, q: 0, s: 0};
|
||||
|
||||
for (var i = 0; i < accepted.length; i++) {
|
||||
var spec = specify(language, accepted[i], index);
|
||||
|
||||
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
||||
priority = spec;
|
||||
}
|
||||
}
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specificity of the language.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function specify(language, spec, index) {
|
||||
var p = formatLanguage(contentType.parse(language), 0)
|
||||
if (!p) return null;
|
||||
var s = 0;
|
||||
if(spec.full.toLowerCase() === p.full.toLowerCase()){
|
||||
s |= 4;
|
||||
} else if (spec.prefix.toLowerCase() === p.full.toLowerCase()) {
|
||||
s |= 2;
|
||||
} else if (spec.full.toLowerCase() === p.prefix.toLowerCase()) {
|
||||
s |= 1;
|
||||
} else if (spec.full !== '*' ) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
i: index,
|
||||
o: spec.i,
|
||||
q: spec.q,
|
||||
s: s
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the preferred languages from an Accept-Language header.
|
||||
* @public
|
||||
*/
|
||||
|
||||
function preferredLanguages(accept, provided) {
|
||||
// RFC 2616 sec 14.4: no header = *
|
||||
var accepts = parseAcceptLanguage(accept === undefined ? '*' : accept || '');
|
||||
|
||||
if (!provided) {
|
||||
// sorted list of all languages
|
||||
return accepts
|
||||
.filter(isQuality)
|
||||
.sort(compareSpecs)
|
||||
.map(getFullLanguage);
|
||||
}
|
||||
|
||||
var priorities = provided.map(function getPriority(type, index) {
|
||||
return getLanguagePriority(type, accepts, index);
|
||||
});
|
||||
|
||||
// sorted list of accepted languages
|
||||
return priorities.filter(isQuality).sort(compareSpecs).map(function getLanguage(priority) {
|
||||
return provided[priorities.indexOf(priority)];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two specs.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function compareSpecs(a, b) {
|
||||
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full language string.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getFullLanguage(spec) {
|
||||
return spec.full;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a spec has any quality.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function isQuality(spec) {
|
||||
return spec.q > 0;
|
||||
}
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* negotiator
|
||||
* Copyright(c) 2012 Isaac Z. Schlueter
|
||||
* Copyright(c) 2014 Federico Romero
|
||||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var contentType = require('content-type');
|
||||
var parseAcceptHeader = require('./accept');
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = preferredMediaTypes;
|
||||
module.exports.preferredMediaTypes = preferredMediaTypes;
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseAccept(accept) {
|
||||
var accepts = parseAcceptHeader(accept);
|
||||
|
||||
for (var i = 0, j = 0; i < accepts.length; i++) {
|
||||
var mediaType = formatMediaType(accepts[i], i);
|
||||
if (mediaType) accepts[j++] = mediaType;
|
||||
}
|
||||
|
||||
accepts.length = j;
|
||||
return accepts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a parsed content type for negotiation.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function formatMediaType(parsed, i) {
|
||||
var slash = parsed.type.indexOf('/');
|
||||
if (slash === -1) return null;
|
||||
|
||||
var q = parsed.parameters.q ? parseFloat(parsed.parameters.q) : 1;
|
||||
|
||||
delete parsed.parameters.q;
|
||||
|
||||
return {
|
||||
type: parsed.type.slice(0, slash),
|
||||
subtype: parsed.type.slice(slash + 1),
|
||||
params: parsed.parameters,
|
||||
q: q,
|
||||
i: i
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the priority of a media type.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getMediaTypePriority(type, accepted, index) {
|
||||
var priority = {o: -1, q: 0, s: 0};
|
||||
|
||||
for (var i = 0; i < accepted.length; i++) {
|
||||
var spec = specify(type, accepted[i], index);
|
||||
|
||||
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
||||
priority = spec;
|
||||
}
|
||||
}
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specificity of the media type.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function specify(type, spec, index) {
|
||||
var p = formatMediaType(contentType.parse(type), 0);
|
||||
var s = 0;
|
||||
|
||||
if (!p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(spec.type.toLowerCase() == p.type.toLowerCase()) {
|
||||
s |= 4
|
||||
} else if(spec.type != '*') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(spec.subtype.toLowerCase() == p.subtype.toLowerCase()) {
|
||||
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] || '').toLowerCase() == (p.params[k] || '').toLowerCase();
|
||||
})) {
|
||||
s |= 1
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
i: index,
|
||||
o: spec.i,
|
||||
q: spec.q,
|
||||
s: s,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the preferred media types from an Accept header.
|
||||
* @public
|
||||
*/
|
||||
|
||||
function preferredMediaTypes(accept, provided) {
|
||||
// RFC 2616 sec 14.2: no header = */*
|
||||
var accepts = parseAccept(accept === undefined ? '*/*' : accept || '');
|
||||
|
||||
if (!provided) {
|
||||
// sorted list of all types
|
||||
return accepts
|
||||
.filter(isQuality)
|
||||
.sort(compareSpecs)
|
||||
.map(getFullType);
|
||||
}
|
||||
|
||||
var priorities = provided.map(function getPriority(type, index) {
|
||||
return getMediaTypePriority(type, accepts, index);
|
||||
});
|
||||
|
||||
// sorted list of accepted types
|
||||
return priorities.filter(isQuality).sort(compareSpecs).map(function getType(priority) {
|
||||
return provided[priorities.indexOf(priority)];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two specs.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function compareSpecs(a, b) {
|
||||
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full type string.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getFullType(spec) {
|
||||
return spec.type + '/' + spec.subtype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a spec has any quality.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function isQuality(spec) {
|
||||
return spec.q > 0;
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2015 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.
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
# content-type
|
||||
|
||||
[![NPM version][npm-image]][npm-url]
|
||||
[![NPM downloads][downloads-image]][downloads-url]
|
||||
[![Build status][build-image]][build-url]
|
||||
[![Build coverage][coverage-image]][coverage-url]
|
||||
[![License][license-image]][license-url]
|
||||
|
||||
Create and parse HTTP `Content-Type` header.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
npm install content-type
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```js
|
||||
const contentType = require("content-type");
|
||||
```
|
||||
|
||||
### contentType.parse(string, options?)
|
||||
|
||||
```js
|
||||
const obj = contentType.parse("image/svg+xml; charset=utf-8");
|
||||
```
|
||||
|
||||
Parse a `Content-Type` header. This will return an object with the following properties (examples are shown for the string `'image/svg+xml; charset=utf-8'`):
|
||||
|
||||
- `type`: The media type. Example: `'image/svg+xml'`.
|
||||
- `parameters`: An object of the parameters in the media type (parameter name is always lower case). Example: `{charset: 'utf-8'}`.
|
||||
|
||||
The parser is lenient and does not error. You should validate `type` and `parameters` before trusting them.
|
||||
|
||||
#### Options
|
||||
|
||||
- `parameters` (default: `true`): Set to `false` to skip parameters.
|
||||
- `comma` (default: `false`): Set to `true` to stop on a comma. This can be used to parse the media range in an `Accept` header.
|
||||
- `start` (default: `0`): Set index to start parsing from.
|
||||
|
||||
### contentType.format(obj)
|
||||
|
||||
```js
|
||||
const str = contentType.format({
|
||||
type: "image/svg+xml",
|
||||
parameters: { charset: "utf-8" },
|
||||
});
|
||||
```
|
||||
|
||||
Format an object into a `Content-Type` header. This will return a string of the content type for the given object with the following properties (examples are shown that produce the string `'image/svg+xml; charset=utf-8'`):
|
||||
|
||||
- `type`: The media type. Example: `'image/svg+xml'`.
|
||||
- `parameters`: An optional object of the parameters in the media type. Example: `{charset: 'utf-8'}`.
|
||||
|
||||
Throws a `TypeError` if the object contains an invalid type or parameter names.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/content-type
|
||||
[npm-url]: https://npmjs.org/package/content-type
|
||||
[downloads-image]: https://img.shields.io/npm/dm/content-type
|
||||
[downloads-url]: https://npmjs.org/package/content-type
|
||||
[build-image]: https://img.shields.io/github/actions/workflow/status/jshttp/content-type/ci.yml?branch=master
|
||||
[build-url]: https://github.com/jshttp/content-type/actions/workflows/ci.yml?query=branch%3Amaster
|
||||
[coverage-image]: https://img.shields.io/codecov/c/gh/jshttp/content-type
|
||||
[coverage-url]: https://codecov.io/gh/jshttp/content-type
|
||||
[license-image]: http://img.shields.io/npm/l/content-type.svg?style=flat
|
||||
[license-url]: LICENSE
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*!
|
||||
* content-type
|
||||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
/**
|
||||
* The content type object contains a type string and optional parameters.
|
||||
*/
|
||||
export interface ContentType {
|
||||
type: string;
|
||||
index: number;
|
||||
parameters: Record<string, string>;
|
||||
}
|
||||
/**
|
||||
* Format an object into a `Content-Type` header.
|
||||
*/
|
||||
export declare function format(obj: Partial<ContentType>): string;
|
||||
/**
|
||||
* Options for parsing a `Content-Type` header.
|
||||
*/
|
||||
export interface ParseOptions {
|
||||
/**
|
||||
* Exit early on the first semicolon, returning only the type.
|
||||
* This is useful for parsing the MIME from `Content-Type` headers.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
parameters?: boolean;
|
||||
/**
|
||||
* Exits early on a comma, returning the first value and parameters.
|
||||
* This is useful for parsing `Accept` headers.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
comma?: boolean;
|
||||
/**
|
||||
* The index to start parsing from.
|
||||
*
|
||||
* @default 0
|
||||
*/
|
||||
start?: number;
|
||||
}
|
||||
/**
|
||||
* Parse a `Content-Type` header.
|
||||
*/
|
||||
export declare function parse(header: string, options?: ParseOptions): ContentType;
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
"use strict";
|
||||
/*!
|
||||
* content-type
|
||||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.format = format;
|
||||
exports.parse = parse;
|
||||
const TEXT_REGEXP = /^[\u0009\u0020-\u007e\u0080-\u00ff]*$/;
|
||||
const TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
||||
/**
|
||||
* RegExp to match chars that must be quoted-pair in RFC 9110 sec 5.6.4
|
||||
*/
|
||||
const QUOTE_REGEXP = /[\\"]/g;
|
||||
/**
|
||||
* RegExp to match type in RFC 9110 sec 8.3.1
|
||||
*
|
||||
* media-type = type "/" subtype
|
||||
* type = token
|
||||
* subtype = token
|
||||
*/
|
||||
const TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
||||
/**
|
||||
* Null object perf optimization. Faster than `Object.create(null)` and `{ __proto__: null }`.
|
||||
*/
|
||||
const NullObject = /* @__PURE__ */ (() => {
|
||||
const C = function () { };
|
||||
C.prototype = Object.create(null);
|
||||
return C;
|
||||
})();
|
||||
/**
|
||||
* Format an object into a `Content-Type` header.
|
||||
*/
|
||||
function format(obj) {
|
||||
const { type, parameters } = obj;
|
||||
if (!type || !TYPE_REGEXP.test(type)) {
|
||||
throw new TypeError(`Invalid type: ${type}`);
|
||||
}
|
||||
let result = type;
|
||||
if (parameters) {
|
||||
for (const param of Object.keys(parameters)) {
|
||||
if (!TOKEN_REGEXP.test(param)) {
|
||||
throw new TypeError(`Invalid parameter name: ${param}`);
|
||||
}
|
||||
result += `; ${param}=${qstring(parameters[param])}`;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Parse a `Content-Type` header.
|
||||
*/
|
||||
function parse(header, options) {
|
||||
const stopChar = options?.comma === true ? COMMA : 65536; // Sentinel for "no stop char".
|
||||
const len = header.length;
|
||||
let index = skipOWS(header, options?.start ?? 0, len);
|
||||
const valueStart = index;
|
||||
index = skipValue(header, index, len, stopChar);
|
||||
const valueEnd = trailingOWS(header, valueStart, index);
|
||||
const type = header.slice(valueStart, valueEnd).toLowerCase();
|
||||
if (options?.parameters === false) {
|
||||
return { type, index, parameters: new NullObject() };
|
||||
}
|
||||
return parseParameters(header, type, index, len, stopChar);
|
||||
}
|
||||
const SP = 32; // " "
|
||||
const HTAB = 9; // "\t"
|
||||
const SEMI = 59; // ";"
|
||||
const EQ = 61; // "="
|
||||
const DQUOTE = 34; // '"'
|
||||
const BSLASH = 92; // "\\"
|
||||
const COMMA = 44; // ","
|
||||
/**
|
||||
* Parses the parameters of a `Content-Type` header starting at the given index.
|
||||
*/
|
||||
function parseParameters(header, type, index, len, stopChar) {
|
||||
const parameters = new NullObject();
|
||||
parameter: while (index < len) {
|
||||
if (header.charCodeAt(index) === stopChar)
|
||||
break;
|
||||
index = skipOWS(header, index + 1 /* Skip over ; */, len);
|
||||
const keyStart = index;
|
||||
while (index < len) {
|
||||
const code = header.charCodeAt(index);
|
||||
if (code === stopChar)
|
||||
break parameter;
|
||||
if (code === SEMI)
|
||||
continue parameter;
|
||||
if (code === EQ) {
|
||||
const keyEnd = trailingOWS(header, keyStart, index);
|
||||
const key = header.slice(keyStart, keyEnd).toLowerCase();
|
||||
index = skipOWS(header, index + 1, len);
|
||||
if (index < len && header.charCodeAt(index) === DQUOTE) {
|
||||
index++;
|
||||
let value = "";
|
||||
while (index < len) {
|
||||
const code = header.charCodeAt(index++);
|
||||
if (code === DQUOTE) {
|
||||
index = skipValue(header, index, len, stopChar);
|
||||
if (parameters[key] === undefined)
|
||||
parameters[key] = value;
|
||||
break;
|
||||
}
|
||||
if (code === BSLASH && index < len) {
|
||||
value += header[index++];
|
||||
continue;
|
||||
}
|
||||
value += String.fromCharCode(code);
|
||||
}
|
||||
continue parameter;
|
||||
}
|
||||
const valueStart = index;
|
||||
index = skipValue(header, index, len, stopChar);
|
||||
if (parameters[key] === undefined) {
|
||||
const valueEnd = trailingOWS(header, valueStart, index);
|
||||
parameters[key] = header.slice(valueStart, valueEnd);
|
||||
}
|
||||
continue parameter;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return { type, index, parameters };
|
||||
}
|
||||
/**
|
||||
* Skip over characters until a semicolon or other exit character.
|
||||
*/
|
||||
function skipValue(str, index, len, stopChar) {
|
||||
while (index < len) {
|
||||
const code = str.charCodeAt(index);
|
||||
if (code === SEMI || code === stopChar)
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
/**
|
||||
* Skip optional whitespace (OWS) in an HTTP header value.
|
||||
*
|
||||
* OWS is defined in RFC 9110 sec 5.6.3 as SP (" ") or HTAB ("\t").
|
||||
*/
|
||||
function skipOWS(header, index, len) {
|
||||
while (index < len) {
|
||||
const char = header.charCodeAt(index);
|
||||
if (char !== SP && char !== HTAB)
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
/**
|
||||
* Trim optional whitespace (OWS) from the end of a substring.
|
||||
*
|
||||
* OWS is defined in RFC 9110 sec 5.6.3 as SP (" ") or HTAB ("\t").
|
||||
*/
|
||||
function trailingOWS(header, start, end) {
|
||||
while (end > start) {
|
||||
const char = header.charCodeAt(end - 1);
|
||||
if (char !== SP && char !== HTAB)
|
||||
break;
|
||||
end--;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
/**
|
||||
* Serialize a parameter value.
|
||||
*/
|
||||
function qstring(str) {
|
||||
if (TOKEN_REGEXP.test(str))
|
||||
return str;
|
||||
if (TEXT_REGEXP.test(str))
|
||||
return `"${str.replace(QUOTE_REGEXP, "\\$&")}"`;
|
||||
throw new TypeError(`Invalid parameter value: ${str}`);
|
||||
}
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+52
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "content-type",
|
||||
"version": "2.1.0",
|
||||
"description": "Create and parse HTTP Content-Type header",
|
||||
"keywords": [
|
||||
"content-type",
|
||||
"http",
|
||||
"req",
|
||||
"res",
|
||||
"rfc7231",
|
||||
"rfc9110"
|
||||
],
|
||||
"repository": "jshttp/content-type",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
},
|
||||
"license": "MIT",
|
||||
"author": "Douglas Christopher Wilson <doug@somethingdoug.com>",
|
||||
"type": "commonjs",
|
||||
"exports": "./dist/index.js",
|
||||
"main": "./dist/index.js",
|
||||
"typings": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist/"
|
||||
],
|
||||
"scripts": {
|
||||
"bench": "vitest bench",
|
||||
"build": "ts-scripts build",
|
||||
"format": "ts-scripts format",
|
||||
"prepare": "ts-scripts install && npm run build",
|
||||
"specs": "ts-scripts specs",
|
||||
"test": "ts-scripts test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@borderless/ts-scripts": "^0.15.0",
|
||||
"@vitest/coverage-v8": "^3.0.5",
|
||||
"typescript": "^5.7.3",
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"ts-scripts": {
|
||||
"dist": [
|
||||
"dist"
|
||||
],
|
||||
"project": [
|
||||
"tsconfig.build.json"
|
||||
]
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "negotiator",
|
||||
"description": "HTTP content negotiation",
|
||||
"version": "1.1.0",
|
||||
"contributors": [
|
||||
"Douglas Christopher Wilson <doug@somethingdoug.com>",
|
||||
"Federico Romero <federico.romero@outboxlabs.com>",
|
||||
"Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)"
|
||||
],
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"http",
|
||||
"content negotiation",
|
||||
"accept",
|
||||
"accept-language",
|
||||
"accept-encoding",
|
||||
"accept-charset"
|
||||
],
|
||||
"repository": "jshttp/negotiator",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
},
|
||||
"dependencies": {
|
||||
"content-type": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "7.32.0",
|
||||
"eslint-plugin-markdown": "2.2.1",
|
||||
"mocha": "^11.7.0",
|
||||
"nyc": "^17.1.0",
|
||||
"vitest": "3.2.4"
|
||||
},
|
||||
"files": [
|
||||
"lib/",
|
||||
"index.js"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"scripts": {
|
||||
"bench": "vitest bench",
|
||||
"lint": "eslint .",
|
||||
"test": "mocha --reporter spec --check-leaks test/",
|
||||
"test:debug": "mocha --reporter spec --check-leaks --inspect --inspect-brk test/",
|
||||
"test-ci": "nyc --reporter=lcovonly --reporter=text npm test",
|
||||
"test-cov": "nyc --reporter=html --reporter=text npm test"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user