text: 'use strict';
  
  /**
   * @param typeMap [Object] Map of MIME type -> Array[extensions]
   * @param ...
   */
  function Mime() {
    this._types = Object.create(null);
    this._extensions = Object.create(null);
  
    for (var i = 0; i < arguments.length; i++) {
      this.define(arguments[i]);
    }
  }
  
  /**
   * Define mimetype -> xtension 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']});
   *
   * If a type declares an extension that has already been defined, an error will
   * be thrown.  To suppress this error and force the extension to be associated
   * with the new type, pass `force`=true.  Alternatively, you may prefix the
   * extension with "*" to map the type to extension, without mapping the
   * extension to the type.
   *
   * e.g. mime.define({'audio/wav', ['wav']}, {'audio/x-wav', ['*wav']});
   *
   *
   * @param map (Object) type definitions
   * @param force (Boolean) if true, force overriding of existing definitions
   */
  Mime.prototype.define = function(typeMap, force) {
    for (var type in typeMap) {
      var extensions = typeMap[type];
      for (var i = 0; i < extensions.length; i++) {
        var ext = extensions[i];
  
        // '*' prefix = not the preferred type for this extension.  So fixup the
        // extension, and skip it.
        if (ext[0] == '*') {
          continue;
        }
  
        if (!force && (ext in this._types)) {
          throw new Error(
            'Attempt to change mapping for "' + ext +
            '" extension from "' + this._types[ext] + '" to "' + type +
            '". Pass `force=true` to allow this, otherwise remove "' + ext +
            '" from the list of extensions for "' + type + '".'
          );
        }
  
        this._types[ext] = type;
      }
  
      // Use first extension as default
      if (force || !this._extensions[type]) {
        var ext = extensions[0];
        this._extensions[type] = (ext[0] != '*') ? ext : ext.substr(1);
      }
    }
  };
  
  /**
   * Lookup a mime type based on extension
   */
  Mime.prototype.getType = function(path) {
    path = String(path);
    var last = path.replace(/^.*[/\\]/, '').toLowerCase();
    var ext = last.replace(/^.*\./, '').toLowerCase();
  
    var hasPath = last.length < path.length;
    var hasDot = ext.length < last.length - 1;
  
    return (hasDot || !hasPath) && this._types[ext] || null;
  };
  
  /**
   * Return file extension associated with a mime type
   */
  Mime.prototype.getExtension = function(type) {
    type = /^\s*([^;\s]*)/.test(type) && RegExp.$1;
    return type && this._extensions[type.toLowerCase()] || null;
  };
  
  Mime.prototype.charsets = {
    lookup: function(mimeType) {
      // Assume text types are utf8
      return (/^text\/|^application\/(javascript|json)/).test(mimeType) ? 'UTF-8' : '';
    }
  };
  
  module.exports = Mime;
  