UNPKG

3.66 kBJavaScriptView Raw
1/*!
2 * mime-types
3 * Copyright(c) 2014 Jonathan Ong
4 * Copyright(c) 2015 Douglas Christopher Wilson
5 * MIT Licensed
6 */
7
8'use strict'
9
10/**
11 * Module dependencies.
12 * @private
13 */
14
15var db = require('mime-db')
16var extname = require('path').extname
17
18/**
19 * Module variables.
20 * @private
21 */
22
23var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/
24var TEXT_TYPE_REGEXP = /^text\//i
25
26/**
27 * Module exports.
28 * @public
29 */
30
31exports.charset = charset
32exports.charsets = { lookup: charset }
33exports.contentType = contentType
34exports.extension = extension
35exports.extensions = Object.create(null)
36exports.lookup = lookup
37exports.types = Object.create(null)
38
39// Populate the extensions/types maps
40populateMaps(exports.extensions, exports.types)
41
42/**
43 * Get the default charset for a MIME type.
44 *
45 * @param {string} type
46 * @return {boolean|string}
47 */
48
49function charset (type) {
50 if (!type || typeof type !== 'string') {
51 return false
52 }
53
54 // TODO: use media-typer
55 var match = EXTRACT_TYPE_REGEXP.exec(type)
56 var mime = match && db[match[1].toLowerCase()]
57
58 if (mime && mime.charset) {
59 return mime.charset
60 }
61
62 // default text/* to utf-8
63 if (match && TEXT_TYPE_REGEXP.test(match[1])) {
64 return 'UTF-8'
65 }
66
67 return false
68}
69
70/**
71 * Create a full Content-Type header given a MIME type or extension.
72 *
73 * @param {string} str
74 * @return {boolean|string}
75 */
76
77function contentType (str) {
78 // TODO: should this even be in this module?
79 if (!str || typeof str !== 'string') {
80 return false
81 }
82
83 var mime = str.indexOf('/') === -1
84 ? exports.lookup(str)
85 : str
86
87 if (!mime) {
88 return false
89 }
90
91 // TODO: use content-type or other module
92 if (mime.indexOf('charset') === -1) {
93 var charset = exports.charset(mime)
94 if (charset) mime += '; charset=' + charset.toLowerCase()
95 }
96
97 return mime
98}
99
100/**
101 * Get the default extension for a MIME type.
102 *
103 * @param {string} type
104 * @return {boolean|string}
105 */
106
107function extension (type) {
108 if (!type || typeof type !== 'string') {
109 return false
110 }
111
112 // TODO: use media-typer
113 var match = EXTRACT_TYPE_REGEXP.exec(type)
114
115 // get extensions
116 var exts = match && exports.extensions[match[1].toLowerCase()]
117
118 if (!exts || !exts.length) {
119 return false
120 }
121
122 return exts[0]
123}
124
125/**
126 * Lookup the MIME type for a file path/extension.
127 *
128 * @param {string} path
129 * @return {boolean|string}
130 */
131
132function lookup (path) {
133 if (!path || typeof path !== 'string') {
134 return false
135 }
136
137 // get the extension ("ext" or ".ext" or full path)
138 var extension = extname('x.' + path)
139 .toLowerCase()
140 .substr(1)
141
142 if (!extension) {
143 return false
144 }
145
146 return exports.types[extension] || false
147}
148
149/**
150 * Populate the extensions and types maps.
151 * @private
152 */
153
154function populateMaps (extensions, types) {
155 // source preference (least -> most)
156 var preference = ['nginx', 'apache', undefined, 'iana']
157
158 Object.keys(db).forEach(function forEachMimeType (type) {
159 var mime = db[type]
160 var exts = mime.extensions
161
162 if (!exts || !exts.length) {
163 return
164 }
165
166 // mime -> extensions
167 extensions[type] = exts
168
169 // extension -> mime
170 for (var i = 0; i < exts.length; i++) {
171 var extension = exts[i]
172
173 if (types[extension]) {
174 var from = preference.indexOf(db[types[extension]].source)
175 var to = preference.indexOf(mime.source)
176
177 if (types[extension] !== 'application/octet-stream' &&
178 (from > to || (from === to && types[extension].substr(0, 12) === 'application/'))) {
179 // skip the remapping
180 continue
181 }
182 }
183
184 // set the extension -> mime
185 types[extension] = type
186 }
187 })
188}