mime2
Advanced tools
Comparing version 0.0.9 to 0.0.10
132
index.js
@@ -1,3 +0,3 @@ | ||
const Stream = require('stream'); | ||
const types = require('./types'); | ||
const { Duplex } = require('stream'); | ||
const types = require('./types'); | ||
@@ -7,9 +7,9 @@ /** | ||
*/ | ||
class MIME extends Stream { | ||
constructor(headers, body){ | ||
class MIME extends Duplex { | ||
constructor(headers, body) { | ||
super(); | ||
this.status = 0; | ||
this.body = body || ''; | ||
this.headers = Array.isArray(headers) ? | ||
headers.map(x => new Header(x)) : | ||
this.headers = Array.isArray(headers) ? | ||
headers.map(x => new Header(x)) : | ||
Object.keys(headers || {}).map(name => new Header(name, headers[name])); | ||
@@ -28,15 +28,22 @@ return this; | ||
MIME.PARSE_STATUS = { | ||
HEADER : 0x00, | ||
BODY : 0x01, | ||
HEADER: 0x00, | ||
BODY: 0x01, | ||
}; | ||
MIME.parse = function(content){ | ||
return new MIME().end(content); | ||
MIME.parse = function (content, contentType) { | ||
const mime = new MIME(); | ||
if (contentType) { | ||
mime.headers = [ | ||
Header.parseValue(contentType, 'content-type') | ||
]; | ||
mime.status = MIME.PARSE_STATUS.BODY; | ||
} | ||
return mime.end(content); | ||
}; | ||
MIME.trim = function(s){ | ||
MIME.trim = function (s) { | ||
return s.replace(/^"|"$/g, ''); | ||
} | ||
MIME.filter = function(str){ | ||
MIME.filter = function (str) { | ||
return !!str.trim(); | ||
@@ -50,4 +57,4 @@ }; | ||
*/ | ||
MIME.extension = function(type){ | ||
return MIME.TYPES[ type ].extensions; | ||
MIME.extension = function (type) { | ||
return MIME.TYPES[type].extensions; | ||
}; | ||
@@ -60,7 +67,7 @@ | ||
*/ | ||
MIME.lookup = function(filename){ | ||
MIME.lookup = function (filename) { | ||
var ext = filename.replace(/.*[\.\/\\]/, '').toLowerCase(); | ||
return Object.keys(MIME.TYPES).filter(function(type){ | ||
var def = MIME.TYPES[ type ]; | ||
return ~(def.extensions||[]).indexOf(ext); | ||
return Object.keys(MIME.TYPES).filter(function (type) { | ||
var def = MIME.TYPES[type]; | ||
return ~(def.extensions || []).indexOf(ext); | ||
})[0]; | ||
@@ -70,7 +77,7 @@ }; | ||
class Header { | ||
constructor(name, value, options){ | ||
if(arguments.length === 1){ | ||
constructor(name, value, options) { | ||
if (arguments.length === 1) { | ||
Object.assign(this, | ||
typeof name === 'string' ? Header.parse(name) : name); | ||
}else{ | ||
} else { | ||
this.name = name; | ||
@@ -81,3 +88,3 @@ this.value = value; | ||
} | ||
toString(){ | ||
toString() { | ||
const { name, value, options } = this; | ||
@@ -88,6 +95,6 @@ return Object.keys(options || {}).reduce((s, k) => { | ||
} | ||
static parse(str){ | ||
static parse(str) { | ||
// a: b; a=1;b=2 | ||
var p = str.indexOf(':'); | ||
if(p > -1){ | ||
if (p > -1) { | ||
const k = str.substr(0, p).trim(); | ||
@@ -101,7 +108,7 @@ const s = str.substr(++p).trim(); | ||
} | ||
static parseValue(str){ | ||
static parseValue(str, name = null) { | ||
var v, o = {}; | ||
str.split(/;\s?/).forEach(p => { | ||
const kv = p.match(/^(.+?)=(.*)$/); | ||
if(kv) o[kv[1]] = MIME.trim(kv[2]); | ||
if (kv) o[kv[1]] = MIME.trim(kv[2]); | ||
else { | ||
@@ -112,3 +119,3 @@ v && (v = [v]); | ||
}); | ||
return new Header(null, v, o); | ||
return new Header(name, v, o); | ||
} | ||
@@ -119,4 +126,4 @@ } | ||
MIME.prototype.addHeader = function(header, value, options){ | ||
if(!(header instanceof Header)) | ||
MIME.prototype.addHeader = function (header, value, options) { | ||
if (!(header instanceof Header)) | ||
header = new Header(header, value, options); | ||
@@ -127,4 +134,4 @@ this.headers.push(header); | ||
MIME.prototype.setHeader = function(header, value, options){ | ||
if(!(header instanceof Header)) | ||
MIME.prototype.setHeader = function (header, value, options) { | ||
if (!(header instanceof Header)) | ||
header = new Header(header, value, options); | ||
@@ -134,5 +141,5 @@ const i = this.headers.findIndex(h => { | ||
}); | ||
if(i === -1){ | ||
if (i === -1) { | ||
this.headers.push(header); | ||
}else{ | ||
} else { | ||
this.headers[i] = header; | ||
@@ -144,7 +151,7 @@ } | ||
'from,to,cc'.split(',').forEach(field => { | ||
MIME.prototype.__defineGetter__(field, function(){ | ||
MIME.prototype.__defineGetter__(field, function () { | ||
const header = this.getHeader(field); | ||
return header && MIME.parseAddress(header.value); | ||
}); | ||
MIME.prototype.__defineSetter__(field, function(address){ | ||
MIME.prototype.__defineSetter__(field, function (address) { | ||
const value = MIME.parseAddress(address); | ||
@@ -161,3 +168,3 @@ const name = field.charAt(0).toUpperCase() + field.slice(1); | ||
*/ | ||
MIME.prototype.write = function(buf){ | ||
MIME.prototype.write = function (buf) { | ||
this.content = this.content || ''; | ||
@@ -170,7 +177,7 @@ this.content += buf; | ||
.replace(/\n/g, '\r\n'); | ||
if(this.status === MIME.PARSE_STATUS.HEADER){ | ||
if (this.status === MIME.PARSE_STATUS.HEADER) { | ||
var p; | ||
while(~(p = this.content.indexOf('\r\n'))){ | ||
while (~(p = this.content.indexOf('\r\n'))) { | ||
const h = this.content.slice(0, p); | ||
if(!h){ | ||
if (!h) { | ||
this.emit('headers', this.headers); | ||
@@ -183,16 +190,16 @@ this.status = MIME.PARSE_STATUS.BODY; | ||
this.emit('header', header); | ||
this.content = this.content.slice(p+2); | ||
this.content = this.content.slice(p + 2); | ||
} | ||
} | ||
if(this.status === MIME.PARSE_STATUS.BODY){ | ||
if (this.status === MIME.PARSE_STATUS.BODY) { | ||
const contentType = this.getHeader('content-type'); | ||
if(contentType && contentType.value.indexOf('multipart/') === 0){ | ||
if (contentType && contentType.value.indexOf('multipart/') === 0) { | ||
var r; | ||
const { boundary } = contentType.options; | ||
this.body = Array.isArray(this.body) ? this.body : []; | ||
while(r = new RegExp(`--${boundary}(--)?\r\n`).exec(this.content)){ | ||
while (r = new RegExp(`--${boundary}(--)?\r\n`).exec(this.content)) { | ||
this.body.push(MIME.parse(this.content.slice(0, r.index).trim())) | ||
this.content = this.content.slice(r.index+boundary.length+2); | ||
this.content = this.content.slice(r.index + boundary.length + 2); | ||
} | ||
}else{ | ||
} else { | ||
this.body = this.content; | ||
@@ -209,4 +216,4 @@ } | ||
*/ | ||
MIME.prototype.end = function(buf){ | ||
if(buf) this.write(buf); | ||
MIME.prototype.end = function (buf) { | ||
if (buf) this.write(buf); | ||
this.status === 0 && (this.body = this.content); | ||
@@ -217,3 +224,3 @@ this.emit('end', this.headers, this.body, this); | ||
MIME.prototype.getHeader = function(name){ | ||
MIME.prototype.getHeader = function (name) { | ||
const low = x => x.toLowerCase(); | ||
@@ -226,6 +233,6 @@ return this.headers.find(x => low(x.name) === low(name)); | ||
*/ | ||
MIME.prototype.toString = function(){ | ||
MIME.prototype.toString = function () { | ||
const { headers, body } = this; | ||
var message = [], boundary; | ||
if(Array.isArray(body)){ | ||
if (Array.isArray(body)) { | ||
boundary = (Math.random() + Date.now()).toString(36); | ||
@@ -236,6 +243,6 @@ this.addHeader('Content-Type', 'multipart/alternative', { | ||
} | ||
headers.forEach(header => | ||
message.push(header.toString())); | ||
headers.forEach(header => | ||
message.push(header.toString())); | ||
message.push(null); | ||
if(boundary){ | ||
if (boundary) { | ||
body.forEach(part => { | ||
@@ -247,3 +254,3 @@ message.push('--' + boundary); | ||
message.push('--' + boundary + '--'); | ||
}else{ | ||
} else { | ||
message.push(body); | ||
@@ -261,16 +268,16 @@ } | ||
*/ | ||
MIME.parseAddress = function(address){ | ||
MIME.parseAddress = function (address) { | ||
const r1 = /(.+)@(.+)/; | ||
const r2 = /^([^<]+)?<(.+)@(.+)>$/; | ||
if(typeof address !== 'string') | ||
if (typeof address !== 'string') | ||
throw new TypeError(`[MIME] address must be a string, but got ${address}`); | ||
if(!r1.test(address)) | ||
if (!r1.test(address)) | ||
throw new SyntaxError(`[MIME] address syntax error: ${address}`); | ||
var _, name, user, host; | ||
if(r2.test(address)){ | ||
if (r2.test(address)) { | ||
// Liu song <hi@lsong.org> | ||
[ _, name, user, host ] = address.match(r2); | ||
}else{ | ||
[_, name, user, host] = address.match(r2); | ||
} else { | ||
// hi@lsong.org | ||
[ _, user, host ] = address.match(r1); | ||
[_, user, host] = address.match(r1); | ||
} | ||
@@ -285,3 +292,3 @@ host = host.trim(); | ||
address: `${user}@${host}`, | ||
toString(){ | ||
toString() { | ||
name = name ? `"${name}"` : name; | ||
@@ -293,2 +300,3 @@ return `${name}<${this.address}>`; | ||
module.exports = MIME; |
{ | ||
"name": "mime2", | ||
"version": "0.0.9", | ||
"version": "0.0.10", | ||
"description": "MIME in node.js", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
178802
7053