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

Browserify compatibility fixes #61 #96

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
var Mime = require('./lib/mime');
var fs = require('fs');
var mime = new Mime();
var map = {};

process.argv.slice(2).forEach(function(file) {
mime.parse(fs.readFileSync(file, 'ascii'), map);
});

console.log(JSON.stringify(map, null, 2));
102 changes: 102 additions & 0 deletions lib/mime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
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];
}
}
};

/**
*
* Parses Apache2-style ".types" content
*
* @param content (String) content to parse.
* @param map (Object) existing map.
* @returns map (Object) map.
*/
Mime.prototype.parse = function(content, map) {

map = map || {};

// Read file and split into lines
var 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+/);
var type = fields.shift();
map[type] = (map[type] || []).concat(fields);
});

return map;

};

/**
* 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;

this.define(this.parse(fs.readFileSync(file, 'ascii')));

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];
};

module.exports = Mime;
93 changes: 4 additions & 89 deletions mime.js
Original file line number Diff line number Diff line change
@@ -1,86 +1,5 @@
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];
};
var defaultTypes = require('./types.json');
var Mime = require('./lib/mime');

// Default instance
var mime = new Mime();
Expand All @@ -97,12 +16,8 @@ Object.keys(Mime.prototype).forEach(function(key) {
}
});

// 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 types
mime.define(defaultTypes);

// Default type
mime.default_type = mime.lookup('bin');
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"email": "robert@broofa.com"
},
"scripts": {
"build": "node build.js types/*.types > ./types.json",
"test": "node test.js"
},
"contributors": [
Expand Down
27 changes: 15 additions & 12 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
var mime = require('./mime');
var assert = require('assert');
var path = require('path');
var fs = require('fs');

function eq(a, b) {
console.log('Test: ' + a + ' === ' + b);
Expand Down Expand Up @@ -66,18 +67,20 @@ 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]]);
if(fs.hasOwnProperty('readFileSync')) {
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]]);
}
}
}

Expand Down