Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanong committed May 2, 2014
0 parents commit 1da5f79
Show file tree
Hide file tree
Showing 13 changed files with 3,782 additions and 0 deletions.
52 changes: 52 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# 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
22 changes: 22 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

The 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.
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

build:
node --harmony-generators build.js

test:
node test/mime.js
mocha --require should --reporter spec test/test.js

.PHONY: build test
61 changes: 61 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# MIME Types

The ultimate mime type utility.
Similar to [mime](https://github.com/broofa/node-mime) except:

- No `new Mime()` business, so you could do `var lookup = require('mime-types').lookup`
- No fallbacks, so do `var type = mime.lookup('unrecognized') || 'application/octet-stream'`
- Additional mime types are added such as jade and stylus. Feel free to add more!
- Browser support via Browserify and Component by converting lists to JSON files

Otherwise, the API is compatible.

## Adding Types

If you'd like to add additional types,
simply create a PR with a link to where it's defined.

Do __NOT__ edit `mime.json` or `node.json`.
Those are pulled using `build.js`.
You should only touch `custom.json`.

## API

### mime.lookup(path)

Lookup the mime type associated with a file.
If no type is found, returns `false`.

### mime.extension(type)

Get the default extension for the type

### mime.charsets.lookup(type)

Lookup the given charset of a mime type.

### mime.contentType(type)

Create a full `content-type` header given a mime-type or extension.

### mime.types[extension] = type

Lookup a type via extension.

### mime.extensions[type] = [extensions]

Lookup all the associated extensions of a mime type.

### mime.define(types)

Globally add definitions.
`types` must be an object of the form:

```js
{
"<mime-type>": [extensions...],
"<mime-type>": [extensions...]
}
```

See the `.json` files in `lib/` for examples.
44 changes: 44 additions & 0 deletions build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

/**
* http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
* https://github.com/broofa/node-mime/blob/master/types/node.types
*
* Convert these text files to JSON for browser usage.
*/

var co = require('co')
var fs = require('fs')
var path = require('path')
var cogent = require('cogent')

function* get(url) {
var res = yield* cogent(url, {
string: true
})

if (res.statusCode !== 200)
throw new Error('got status code ' + res.statusCode + ' from ' + url)

var text = res.text
var json = {}
// http://en.wikipedia.org/wiki/Internet_media_type#Naming
var re = /^(?:# )?([\w-]+\/[\w\+\.-]+)(?:\s+\w+)*$/
text = text.split('\n')
.filter(Boolean)
.forEach(function (line) {
line = line.trim()
if (!line) return
var match = re.exec(line)
if (!match) return
json[match[1]] = line.replace(/^(?:# )?([\w-]+\/[\w\+\.-]+)/, '').split(/\s+/).filter(Boolean)
})
fs.writeFileSync('lib/' + path.basename(url).split('.')[0] + '.json',
JSON.stringify(json, null, 2))
}

co(function* () {
yield [
get('http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types'),
get('https://raw.githubusercontent.com/broofa/node-mime/master/types/node.types')
]
})()
16 changes: 16 additions & 0 deletions component.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "mime-types",
"description": "ultimate mime type utility",
"version": "0.1.0",
"author": {
"name": "Jonathan Ong",
"email": "[email protected]",
"url": "http://jongleberry.com",
"twitter": "https://twitter.com/jongleberry"
},
"repository": "expressjs/mime-types",
"license": "MIT",
"main": "lib/index.js",
"scripts": ["lib/index.js"],
"json": ["mime.json", "node.json", "custom.json"]
}
24 changes: 24 additions & 0 deletions lib/custom.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"text/jade": [
"jade"
],
"text/stylus": [
"stylus",
"styl"
],
"text/less": [
"less"
],
"text/x-sass": [
"sass"
],
"text/x-scss": [
"scss"
],
"text/coffeescript": [
"coffee"
],
"text/x-handlebars-template": [
"hbs"
]
}
62 changes: 62 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@

// types[extension] = type
exports.types = Object.create(null)
// extensions[type] = [extensions]
exports.extensions = Object.create(null)

This comment has been minimized.

Copy link
@Fishrock123

Fishrock123 May 2, 2014

Member

Why not just {}?

Edit: le sigh

This comment has been minimized.

Copy link
@jonathanong

jonathanong May 2, 2014

Author Member

i generally use Object.create(null) for lookup maps because people are inevitably going to complain when someone does lookup('__proto__') or something stupid like that

This comment has been minimized.

Copy link
@Fishrock123

Fishrock123 May 2, 2014

Member

On the note of these, we could probably just make define() create them if they don't already exist.

This comment has been minimized.

Copy link
@dougwilson

dougwilson May 2, 2014

Contributor

Yea, Object.create(null) for dictionaries in JS :(

This comment has been minimized.

Copy link
@jonathanong

jonathanong May 2, 2014

Author Member

create them if they don't already exist.

create what?

This comment has been minimized.

Copy link
@Fishrock123

Fishrock123 May 2, 2014

Member

Oops, I read it wrong. Define adds to these maps, there aren't separate ones for each json. facepalm

// define more mime types
exports.define = define

// store the json files
exports.json = {
mime: require('./mime.json'),
node: require('./node.json'),
custom: require('./custom.json'),
}

exports.lookup = function (string) {
if (!string) return false
string = string.replace(/.*[\.\/\\]/, '').toLowerCase()
if (!string) return false
return exports.types[string] || false
}

exports.extension = function (type) {
if (!type) return false
type = type.match(/^\s*([^;\s]*)(?:;|\s|$)/)

This comment has been minimized.

Copy link
@Fishrock123

Fishrock123 May 2, 2014

Member

Comments describing what these regexs actually do would be nice. Even if just for posterity.

This comment has been minimized.

Copy link
@jonathanong

jonathanong May 2, 2014

Author Member

done. like the new comments say, we can remove these complexities if we don't care about mime types without extensions. up to you guys!

This comment has been minimized.

Copy link
@Fishrock123

Fishrock123 May 2, 2014

Member

You only got the build.js regex's haha, I didn't pay too much attention to the builder yet.

This comment has been minimized.

Copy link
@jonathanong

jonathanong May 2, 2014

Author Member

ohhh i think those are self-evident though. i pretty much just copied those from mime

This comment has been minimized.

Copy link
@Fishrock123

Fishrock123 May 2, 2014

Member

Eh, I still think it would be a good idea.

if (!type) return false
var exts = exports.extensions[type[1].toLowerCase()]
if (!exts || !exts.length) return false
return exts[0]
}

exports.charsets = {
lookup: function (type) {
return /^text\//.test(type)
? 'UTF-8'
: false
}
}

This comment has been minimized.

Copy link
@Fishrock123

Fishrock123 May 2, 2014

Member

I wish there was a better solution to this.

This comment has been minimized.

Copy link
@jonathanong

jonathanong May 2, 2014

Author Member

yeah. i'm sure you could think of one too.

This comment has been minimized.

Copy link
@Fishrock123

Fishrock123 May 2, 2014

Member

Also, would it be sane to just rename this to exports.charset(type) ?

This comment has been minimized.

Copy link
@jonathanong

jonathanong May 2, 2014

Author Member

+1. i just wanted to copy mime's API for now, but i think that's a better solution because i have no idea what else you'd want to do with charsets.

This comment has been minimized.

Copy link
@jonathanong

jonathanong May 2, 2014

Author Member

unless .charsets(type) tried to parse any charset= stuff in the content-type header as well? meh


exports.contentType = function (type) {
if (!~type.indexOf('/')) type = exports.lookup(type)
if (!~type.indexOf('charset')) {
var charset = exports.charsets.lookup(type)
if (charset) type += '; charset=' + charset.toLowerCase()
}
return type
}

define(exports.json.mime)
define(exports.json.node)
define(exports.json.custom)

function define(json) {
Object.keys(json).forEach(function (type) {
var exts = json[type] || []
exports.extensions[type] = exports.extensions[type] || []
exts.forEach(function (ext) {
if (!~exports.extensions[type].indexOf(ext)) exports.extensions[type].push(ext)
exports.types[ext] = type
})
})
}
Loading

0 comments on commit 1da5f79

Please sign in to comment.