Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add in new public function - lookupAll(). #33

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,21 @@ mime.lookup('folder/.htaccess') // false
mime.lookup('cats') // false
```

### mime.lookupAll(path)

Find all MIME type associated with a file.

```js
mime.lookupAll('json') // ['application/json']
mime.lookupAll('.rtf') // ['application/rtf', 'text/rtf']
mime.lookupAll('file.bmp') // ['image/bmp', 'image/x-ms-bmp']
mime.lookupAll('folder/file.js') // ['application/javascript']
mime.lookupAll('folder/.htaccess') // []

mime.lookupAll('cats') // []
mime.lookupAll(42) // false
```

### mime.contentType(type)

Create a full content-type header given a content-type or extension.
Expand Down
74 changes: 71 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ var extname = require('path').extname

var extractTypeRegExp = /^\s*([^;\s]*)(?:;|\s|$)/
var textTypeRegExp = /^text\//i
var typeSets = {}

/**
* Module exports.
Expand All @@ -34,11 +35,15 @@ exports.contentType = contentType
exports.extension = extension
exports.extensions = Object.create(null)
exports.lookup = lookup
exports.lookupAll = lookupAll
exports.types = Object.create(null)

// Populate the extensions/types maps
populateMaps(exports.extensions, exports.types)

// Populate the extensions->[types] set
populateTypeSets(typeSets)

/**
* Get the default charset for a MIME type.
*
Expand Down Expand Up @@ -123,13 +128,16 @@ function extension (type) {
}

/**
* Lookup the MIME type for a file path/extension.
* Obtain the extension of a filename or filepath.
* If the path is not a string or a proper extension isn't found,
* false is returned.
* The path is case insensitive (so hello.html and HELLO.HTML are equal).
*
* @param {string} path
* @return {boolean|string}
* @return {boolean|string} the file extension if available. false otherwise.
*/

function lookup (path) {
function extractExtension (path) {
if (!path || typeof path !== 'string') {
return false
}
Expand All @@ -143,9 +151,43 @@ function lookup (path) {
return false
}

return extension
}

/**
* Lookup the MIME type for a file path/extension.
*
* @param {string} path
* @return {boolean|string}
*/

function lookup (path) {
var extension = extractExtension(path)

if (!extension) {
return false
}

return exports.types[extension] || false
}

/**
* Find all MIME types that are associated with a file extensions.
*
* @param {string} path or file extension
* @return {boolean|array<string>}
*/

function lookupAll (path) {
var extension = extractExtension(path)

if (!extension) {
return false
}

return typeSets[extension] || []
}

/**
* Populate the extensions and types maps.
* @private
Expand Down Expand Up @@ -186,3 +228,29 @@ function populateMaps (extensions, types) {
}
})
}

/**
* Populate the set where extension->[types]
* An example is .rtf -> ['application/rtf', 'text/rtf']
*
* @private
* @param {object<string, array<string>>} the map to fill in
*/

function populateTypeSets (typeSets) {
Object.keys(db).forEach(function (type) {
var exts = db[type].extensions

if (!exts || !exts.length) {
return
}

exts.forEach(function (ext) {
if (typeSets[ext]) {
typeSets[ext].push(type)
} else {
typeSets[ext] = [type]
}
})
})
}
79 changes: 79 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
var assert = require('assert')
var mimeTypes = require('..')

var allMatch = function (actual, expected) {
expected.forEach(function (expectedType) {
assert.ok(actual.indexOf(expectedType) > -1)
})
}

describe('mimeTypes', function () {
describe('.charset(type)', function () {
it('should return "UTF-8" for "application/json"', function () {
Expand Down Expand Up @@ -224,4 +230,77 @@ describe('mimeTypes', function () {
})
})
})

describe('.lookupAll(extension)', function () {
it('should return a list with multiple mime types when many exist', function () {
allMatch(mimeTypes.lookupAll('.rtf'), ['application/rtf', 'text/rtf'])
})

it('should return a list with one mime type when only one exists', function () {
allMatch(mimeTypes.lookupAll('.html'), ['text/html'])
})

it('should work without a leading dot', function () {
allMatch(mimeTypes.lookupAll('rtf'), ['application/rtf', 'text/rtf'])
})

it('should be case-insensitive', function () {
allMatch(mimeTypes.lookupAll('RtF'), ['application/rtf', 'text/rtf'])
allMatch(mimeTypes.lookupAll('.HTML'), ['text/html'])
})

it('should return an empty list for an unknown extension', function () {
allMatch(mimeTypes.lookupAll('bogus'), [])
})

it('should return false for non-strings', function () {
assert.strictEqual(mimeTypes.lookupAll(null), false)
assert.strictEqual(mimeTypes.lookupAll(undefined), false)
assert.strictEqual(mimeTypes.lookupAll(3.141592), false)
assert.strictEqual(mimeTypes.lookupAll({}), false)
})
})

describe('.lookupAll(path)', function () {
it('should return mime type for file name', function () {
allMatch(mimeTypes.lookupAll('page.html'), ['text/html'])
})

it('should return mime type for relative path', function () {
allMatch(mimeTypes.lookupAll('path/to/page.html'), ['text/html'])
allMatch(mimeTypes.lookupAll('path\\to\\doc.rtf'), ['application/rtf', 'text/rtf'])
})

it('should return mime type for absolute path', function () {
allMatch(mimeTypes.lookupAll('/path/to/page.html'), ['text/html'])
allMatch(mimeTypes.lookupAll('C:\\path\\to\\doc.rtf'), ['application/rtf', 'text/rtf'])
})

it('should be case insensitive', function () {
allMatch(mimeTypes.lookupAll('/path/to/PAGE.HTML'), ['text/html'])
allMatch(mimeTypes.lookupAll('C:\\path\\to\\DOC.RTF'), ['application/rtf', 'text/rtf'])
})

it('should return an empty list for unknown extension', function () {
allMatch(mimeTypes.lookupAll('/path/to/file.bogus'), [])
})

it('should return false for path without extension', function () {
assert.strictEqual(mimeTypes.lookupAll('/path/to/json'), false)
})

describe('lookupAll() - path with dotfile', function () {
it('should return false when extension-less', function () {
assert.strictEqual(mimeTypes.lookupAll('/path/to/.json'), false)
})

it('should return all mime types when there is extension', function () {
allMatch(mimeTypes.lookupAll('/path/to/.config.json'), ['application/json'])
})

it('should return all mime types when there is extension, but no path', function () {
allMatch(mimeTypes.lookupAll('.config.json'), ['application/json'])
})
})
})
})