正在显示
51 个修改的文件
包含
4413 行增加
和
2 行删除
@@ -6,12 +6,23 @@ const onerror = require('koa-onerror') | @@ -6,12 +6,23 @@ const onerror = require('koa-onerror') | ||
6 | const bodyparser = require('koa-bodyparser') | 6 | const bodyparser = require('koa-bodyparser') |
7 | const logger = require('koa-logger') | 7 | const logger = require('koa-logger') |
8 | const cors = require('koa-cors'); | 8 | const cors = require('koa-cors'); |
9 | +const koaBody = require('koa-body'); | ||
10 | +const route = require('koa-router'); | ||
11 | + | ||
12 | +// app.use(route.post('/profile', uploads.single('avatar'))); | ||
13 | + | ||
14 | + | ||
9 | 15 | ||
10 | 16 | ||
11 | const index = require('./routes/index') | 17 | const index = require('./routes/index') |
12 | const users = require('./routes/users') | 18 | const users = require('./routes/users') |
13 | const meeting = require('./routes/meeting') | 19 | const meeting = require('./routes/meeting') |
14 | const studentMeeting = require('./routes/studentMeeting') | 20 | const studentMeeting = require('./routes/studentMeeting') |
21 | +const upload = require('./routes/upload') | ||
22 | +const email = require('./routes/email') | ||
23 | + | ||
24 | + | ||
25 | + | ||
15 | const filterUrl = require(__dirname+'/util/filterUrl') | 26 | const filterUrl = require(__dirname+'/util/filterUrl') |
16 | var tokenUtil = require('./util/tokenUtil'); | 27 | var tokenUtil = require('./util/tokenUtil'); |
17 | const _ = require('lodash'); | 28 | const _ = require('lodash'); |
@@ -20,6 +31,8 @@ var status = require('./util/resTemplate') | @@ -20,6 +31,8 @@ var status = require('./util/resTemplate') | ||
20 | // error handler | 31 | // error handler |
21 | onerror(app) | 32 | onerror(app) |
22 | 33 | ||
34 | +app.use(koaBody({ multipart: true })); | ||
35 | + | ||
23 | // middlewares | 36 | // middlewares |
24 | app.use(cors()); | 37 | app.use(cors()); |
25 | app.use(bodyparser({ | 38 | app.use(bodyparser({ |
@@ -30,9 +43,11 @@ app.use(logger()) | @@ -30,9 +43,11 @@ app.use(logger()) | ||
30 | app.use(require('koa-static')(__dirname + '/public')) | 43 | app.use(require('koa-static')(__dirname + '/public')) |
31 | 44 | ||
32 | app.use(views(__dirname + '/views', { | 45 | app.use(views(__dirname + '/views', { |
33 | - extension: 'pug' | 46 | + extension: 'html' |
34 | })) | 47 | })) |
35 | 48 | ||
49 | + | ||
50 | + | ||
36 | // logger | 51 | // logger |
37 | app.use(async (ctx, next) => { | 52 | app.use(async (ctx, next) => { |
38 | try{ | 53 | try{ |
@@ -60,6 +75,10 @@ app.use(index.routes(), index.allowedMethods()) | @@ -60,6 +75,10 @@ app.use(index.routes(), index.allowedMethods()) | ||
60 | app.use(users.routes(), users.allowedMethods()) | 75 | app.use(users.routes(), users.allowedMethods()) |
61 | app.use(meeting.routes(), meeting.allowedMethods()) | 76 | app.use(meeting.routes(), meeting.allowedMethods()) |
62 | app.use(studentMeeting.routes(), studentMeeting.allowedMethods()) | 77 | app.use(studentMeeting.routes(), studentMeeting.allowedMethods()) |
78 | +app.use(upload.routes(), upload.allowedMethods()) | ||
79 | +app.use(email.routes(), email.allowedMethods()) | ||
80 | + | ||
81 | + | ||
63 | 82 | ||
64 | 83 | ||
65 | 84 |
img.png
0 → 100644

32 字节
node_modules/.bin/which
0 → 120000
1 | +../which/bin/which |
node_modules/array-parallel/.npmignore
0 → 100644
1 | +# Compiled source # | ||
2 | +################### | ||
3 | +*.com | ||
4 | +*.class | ||
5 | +*.dll | ||
6 | +*.exe | ||
7 | +*.o | ||
8 | +*.so | ||
9 | + | ||
10 | +# Packages # | ||
11 | +############ | ||
12 | +# it's better to unpack these files and commit the raw source | ||
13 | +# git has its own built in compression methods | ||
14 | +*.7z | ||
15 | +*.dmg | ||
16 | +*.gz | ||
17 | +*.iso | ||
18 | +*.jar | ||
19 | +*.rar | ||
20 | +*.tar | ||
21 | +*.zip | ||
22 | + | ||
23 | +# Logs and databases # | ||
24 | +###################### | ||
25 | +*.log | ||
26 | +*.sql | ||
27 | +*.sqlite | ||
28 | + | ||
29 | +# OS generated files # | ||
30 | +###################### | ||
31 | +.DS_Store* | ||
32 | +ehthumbs.db | ||
33 | +Icon? | ||
34 | +Thumbs.db | ||
35 | + | ||
36 | +# Node.js # | ||
37 | +########### | ||
38 | +lib-cov | ||
39 | +*.seed | ||
40 | +*.log | ||
41 | +*.csv | ||
42 | +*.dat | ||
43 | +*.out | ||
44 | +*.pid | ||
45 | +*.gz | ||
46 | + | ||
47 | +pids | ||
48 | +logs | ||
49 | +results | ||
50 | + | ||
51 | +node_modules | ||
52 | +npm-debug.log | ||
53 | + | ||
54 | +# Components # | ||
55 | +############## | ||
56 | + | ||
57 | +/build | ||
58 | +/components |
node_modules/array-parallel/.travis.yml
0 → 100644
node_modules/array-parallel/README.md
0 → 100644
1 | +# Array Series [](https://travis-ci.org/component/array-parallel) | ||
2 | + | ||
3 | +Call an array of asynchronous functions in parallel | ||
4 | + | ||
5 | +### API | ||
6 | + | ||
7 | +#### parallel(fns[, context[, callback]]) | ||
8 | + | ||
9 | +```js | ||
10 | +var parallel = require('array-parallel') | ||
11 | + | ||
12 | +parallel([ | ||
13 | + function (done) { | ||
14 | + done() | ||
15 | + } | ||
16 | +], this, function (err) { | ||
17 | + | ||
18 | +}) | ||
19 | +``` | ||
20 | + | ||
21 | +#### fns | ||
22 | + | ||
23 | +`fns` is an array of functions to call in parallel. | ||
24 | +The argument signature should be: | ||
25 | + | ||
26 | +```js | ||
27 | +function (done) { | ||
28 | + done(new Error()) | ||
29 | + // or | ||
30 | + done(null, result) | ||
31 | +} | ||
32 | +``` | ||
33 | + | ||
34 | +That is, each function should only take a `done` as an argument. | ||
35 | +Each callback should only take an `Error` as the first argument, | ||
36 | +or a value as the second. | ||
37 | + | ||
38 | +#### context | ||
39 | + | ||
40 | +Optional context to pass to each `fn`. | ||
41 | +Basically `fn.call(context, done)`. | ||
42 | + | ||
43 | +#### callback(err, results) | ||
44 | + | ||
45 | +```js | ||
46 | +function (err, results) { | ||
47 | + | ||
48 | +} | ||
49 | +``` | ||
50 | + | ||
51 | +Only argument is an `Error` argument. | ||
52 | +It will be the first error retrieved from all the `fns`. | ||
53 | +`results` will be an array of results from each `fn`, | ||
54 | +thus this could be considered an asynchronous version of `[].map`. | ||
55 | + | ||
56 | +### License | ||
57 | + | ||
58 | +The MIT License (MIT) | ||
59 | + | ||
60 | +Copyright (c) 2013 Jonathan Ong me@jongleberry.com | ||
61 | + | ||
62 | +Permission is hereby granted, free of charge, to any person obtaining a copy | ||
63 | +of this software and associated documentation files (the "Software"), to deal | ||
64 | +in the Software without restriction, including without limitation the rights | ||
65 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
66 | +copies of the Software, and to permit persons to whom the Software is | ||
67 | +furnished to do so, subject to the following conditions: | ||
68 | + | ||
69 | +The above copyright notice and this permission notice shall be included in | ||
70 | +all copies or substantial portions of the Software. | ||
71 | + | ||
72 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
73 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
74 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
75 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
76 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
77 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
78 | +THE SOFTWARE. |
node_modules/array-parallel/component.json
0 → 100644
node_modules/array-parallel/index.js
0 → 100644
1 | +module.exports = function parallel(fns, context, callback) { | ||
2 | + if (!callback) { | ||
3 | + if (typeof context === 'function') { | ||
4 | + callback = context | ||
5 | + context = null | ||
6 | + } else { | ||
7 | + callback = noop | ||
8 | + } | ||
9 | + } | ||
10 | + | ||
11 | + var pending = fns && fns.length | ||
12 | + if (!pending) return callback(null, []); | ||
13 | + | ||
14 | + var finished = false | ||
15 | + var results = new Array(pending) | ||
16 | + | ||
17 | + fns.forEach(context ? function (fn, i) { | ||
18 | + fn.call(context, maybeDone(i)) | ||
19 | + } : function (fn, i) { | ||
20 | + fn(maybeDone(i)) | ||
21 | + }) | ||
22 | + | ||
23 | + function maybeDone(i) { | ||
24 | + return function (err, result) { | ||
25 | + if (finished) return; | ||
26 | + | ||
27 | + if (err) { | ||
28 | + callback(err, results) | ||
29 | + finished = true | ||
30 | + return | ||
31 | + } | ||
32 | + | ||
33 | + results[i] = result | ||
34 | + | ||
35 | + if (!--pending) callback(null, results); | ||
36 | + } | ||
37 | + } | ||
38 | +} | ||
39 | + | ||
40 | +function noop() {} |
node_modules/array-parallel/package.json
0 → 100644
1 | +{ | ||
2 | + "_args": [ | ||
3 | + [ | ||
4 | + { | ||
5 | + "raw": "array-parallel@~0.1.3", | ||
6 | + "scope": null, | ||
7 | + "escapedName": "array-parallel", | ||
8 | + "name": "array-parallel", | ||
9 | + "rawSpec": "~0.1.3", | ||
10 | + "spec": ">=0.1.3 <0.2.0", | ||
11 | + "type": "range" | ||
12 | + }, | ||
13 | + "/Users/fzy/project/koa2_Sequelize_project/node_modules/gm" | ||
14 | + ] | ||
15 | + ], | ||
16 | + "_from": "array-parallel@>=0.1.3 <0.2.0", | ||
17 | + "_id": "array-parallel@0.1.3", | ||
18 | + "_inCache": true, | ||
19 | + "_location": "/array-parallel", | ||
20 | + "_npmUser": { | ||
21 | + "name": "jongleberry", | ||
22 | + "email": "jonathanrichardong@gmail.com" | ||
23 | + }, | ||
24 | + "_npmVersion": "1.3.17", | ||
25 | + "_phantomChildren": {}, | ||
26 | + "_requested": { | ||
27 | + "raw": "array-parallel@~0.1.3", | ||
28 | + "scope": null, | ||
29 | + "escapedName": "array-parallel", | ||
30 | + "name": "array-parallel", | ||
31 | + "rawSpec": "~0.1.3", | ||
32 | + "spec": ">=0.1.3 <0.2.0", | ||
33 | + "type": "range" | ||
34 | + }, | ||
35 | + "_requiredBy": [ | ||
36 | + "/gm" | ||
37 | + ], | ||
38 | + "_resolved": "https://registry.npmjs.org/array-parallel/-/array-parallel-0.1.3.tgz", | ||
39 | + "_shasum": "8f785308926ed5aa478c47e64d1b334b6c0c947d", | ||
40 | + "_shrinkwrap": null, | ||
41 | + "_spec": "array-parallel@~0.1.3", | ||
42 | + "_where": "/Users/fzy/project/koa2_Sequelize_project/node_modules/gm", | ||
43 | + "author": { | ||
44 | + "name": "Jonathan Ong", | ||
45 | + "email": "me@jongleberry.com", | ||
46 | + "url": "http://jongleberry.com" | ||
47 | + }, | ||
48 | + "bugs": { | ||
49 | + "url": "https://github.com/component/array-parallel/issues", | ||
50 | + "email": "me@jongleberry.com" | ||
51 | + }, | ||
52 | + "dependencies": {}, | ||
53 | + "description": "Call an array of asynchronous functions in parallel", | ||
54 | + "devDependencies": {}, | ||
55 | + "directories": {}, | ||
56 | + "dist": { | ||
57 | + "shasum": "8f785308926ed5aa478c47e64d1b334b6c0c947d", | ||
58 | + "tarball": "https://registry.npmjs.org/array-parallel/-/array-parallel-0.1.3.tgz" | ||
59 | + }, | ||
60 | + "homepage": "https://github.com/component/array-parallel#readme", | ||
61 | + "license": "MIT", | ||
62 | + "maintainers": [ | ||
63 | + { | ||
64 | + "name": "jongleberry", | ||
65 | + "email": "jonathanrichardong@gmail.com" | ||
66 | + } | ||
67 | + ], | ||
68 | + "name": "array-parallel", | ||
69 | + "optionalDependencies": {}, | ||
70 | + "readme": "# Array Series [](https://travis-ci.org/component/array-parallel)\n\nCall an array of asynchronous functions in parallel\n\n### API\n\n#### parallel(fns[, context[, callback]])\n\n```js\nvar parallel = require('array-parallel')\n\nparallel([\n function (done) {\n done()\n }\n], this, function (err) {\n\n})\n```\n\n#### fns\n\n`fns` is an array of functions to call in parallel.\nThe argument signature should be:\n\n```js\nfunction (done) {\n done(new Error())\n // or\n done(null, result)\n}\n```\n\nThat is, each function should only take a `done` as an argument.\nEach callback should only take an `Error` as the first argument,\nor a value as the second.\n\n#### context\n\nOptional context to pass to each `fn`.\nBasically `fn.call(context, done)`.\n\n#### callback(err, results)\n\n```js\nfunction (err, results) {\n\n}\n```\n\nOnly argument is an `Error` argument.\nIt will be the first error retrieved from all the `fns`.\n`results` will be an array of results from each `fn`,\nthus this could be considered an asynchronous version of `[].map`.\n\n### License\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 Jonathan Ong me@jongleberry.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n", | ||
71 | + "readmeFilename": "README.md", | ||
72 | + "repository": { | ||
73 | + "type": "git", | ||
74 | + "url": "git+https://github.com/component/array-parallel.git" | ||
75 | + }, | ||
76 | + "scripts": { | ||
77 | + "test": "node test" | ||
78 | + }, | ||
79 | + "version": "0.1.3" | ||
80 | +} |
node_modules/array-parallel/test.js
0 → 100644
1 | +var assert = require('assert') | ||
2 | +var parallel = require('./') | ||
3 | + | ||
4 | +var a, b, c | ||
5 | +parallel([ | ||
6 | + function (done) { | ||
7 | + setTimeout(function () { | ||
8 | + done(null, a = 0) | ||
9 | + }, 5) | ||
10 | + }, | ||
11 | + function (done) { | ||
12 | + setTimeout(function () { | ||
13 | + done(null, b = 1) | ||
14 | + }, 10) | ||
15 | + }, | ||
16 | + function (done) { | ||
17 | + setTimeout(function () { | ||
18 | + done(null, c = 2) | ||
19 | + }, 15) | ||
20 | + } | ||
21 | +], function (err, results) { | ||
22 | + assert.equal(a, 0) | ||
23 | + assert.equal(b, 1) | ||
24 | + assert.equal(c, 2) | ||
25 | + | ||
26 | + assert.deepEqual(results, [0, 1, 2]) | ||
27 | +}) | ||
28 | + | ||
29 | +var d, e | ||
30 | +parallel([ | ||
31 | + function (done) { | ||
32 | + setTimeout(function () { | ||
33 | + d = 1 | ||
34 | + done(new Error('message')) | ||
35 | + }, 5) | ||
36 | + }, | ||
37 | + function (done) { | ||
38 | + setTimeout(function () { | ||
39 | + e = 2 | ||
40 | + done() | ||
41 | + }, 10) | ||
42 | + } | ||
43 | +], function (err) { | ||
44 | + assert.equal(err.message, 'message') | ||
45 | + assert.equal(d, 1) | ||
46 | + assert.equal(e, undefined) | ||
47 | +}) | ||
48 | + | ||
49 | +var context = 'hello' | ||
50 | +parallel([function (done) { | ||
51 | + assert.equal(this, context) | ||
52 | +}], context) | ||
53 | + | ||
54 | +var f | ||
55 | +parallel([function (done) { | ||
56 | + f = true | ||
57 | + done() | ||
58 | +}]) | ||
59 | + | ||
60 | +process.nextTick(function () { | ||
61 | + assert.equal(f, true) | ||
62 | +}) |
node_modules/array-series/.npmignore
0 → 100644
1 | +# Compiled source # | ||
2 | +################### | ||
3 | +*.com | ||
4 | +*.class | ||
5 | +*.dll | ||
6 | +*.exe | ||
7 | +*.o | ||
8 | +*.so | ||
9 | + | ||
10 | +# Packages # | ||
11 | +############ | ||
12 | +# it's better to unpack these files and commit the raw source | ||
13 | +# git has its own built in compression methods | ||
14 | +*.7z | ||
15 | +*.dmg | ||
16 | +*.gz | ||
17 | +*.iso | ||
18 | +*.jar | ||
19 | +*.rar | ||
20 | +*.tar | ||
21 | +*.zip | ||
22 | + | ||
23 | +# Logs and databases # | ||
24 | +###################### | ||
25 | +*.log | ||
26 | +*.sql | ||
27 | +*.sqlite | ||
28 | + | ||
29 | +# OS generated files # | ||
30 | +###################### | ||
31 | +.DS_Store* | ||
32 | +ehthumbs.db | ||
33 | +Icon? | ||
34 | +Thumbs.db | ||
35 | + | ||
36 | +# Node.js # | ||
37 | +########### | ||
38 | +lib-cov | ||
39 | +*.seed | ||
40 | +*.log | ||
41 | +*.csv | ||
42 | +*.dat | ||
43 | +*.out | ||
44 | +*.pid | ||
45 | +*.gz | ||
46 | + | ||
47 | +pids | ||
48 | +logs | ||
49 | +results | ||
50 | + | ||
51 | +node_modules | ||
52 | +npm-debug.log | ||
53 | + | ||
54 | +# Components # | ||
55 | +############## | ||
56 | + | ||
57 | +/build | ||
58 | +/components |
node_modules/array-series/.travis.yml
0 → 100644
node_modules/array-series/README.md
0 → 100644
1 | +# Array Series [](https://travis-ci.org/component/array-series) | ||
2 | + | ||
3 | +Call an array of asynchronous functions in series | ||
4 | + | ||
5 | +### API | ||
6 | + | ||
7 | +#### series(fns[, context[, callback]]) | ||
8 | + | ||
9 | +```js | ||
10 | +var series = require('array-series') | ||
11 | + | ||
12 | +series([ | ||
13 | + function (done) { | ||
14 | + done() | ||
15 | + } | ||
16 | +], this, function (err) { | ||
17 | + | ||
18 | +}) | ||
19 | +``` | ||
20 | + | ||
21 | +#### fns | ||
22 | + | ||
23 | +`fns` is an array of functions to call in series. | ||
24 | +The argument signature should be: | ||
25 | + | ||
26 | +```js | ||
27 | +function (done) { | ||
28 | + done(new Error()) | ||
29 | + // or | ||
30 | + done() | ||
31 | +} | ||
32 | +``` | ||
33 | + | ||
34 | +That is, each function should only take a `done` as an argument. | ||
35 | +Each callback should only take an optional `Error` as an argument. | ||
36 | + | ||
37 | +#### context | ||
38 | + | ||
39 | +Optional context to pass to each `fn`. | ||
40 | +Basically `fn.call(context, done)`. | ||
41 | + | ||
42 | +#### callback(err) | ||
43 | + | ||
44 | +```js | ||
45 | +function (err) { | ||
46 | + | ||
47 | +} | ||
48 | +``` | ||
49 | + | ||
50 | +Only argument is an `Error` argument. | ||
51 | +It will return the first error in the series of functions that returns an error, | ||
52 | +and no function after will be called. | ||
53 | + | ||
54 | +### License | ||
55 | + | ||
56 | +The MIT License (MIT) | ||
57 | + | ||
58 | +Copyright (c) 2013 Jonathan Ong me@jongleberry.com | ||
59 | + | ||
60 | +Permission is hereby granted, free of charge, to any person obtaining a copy | ||
61 | +of this software and associated documentation files (the "Software"), to deal | ||
62 | +in the Software without restriction, including without limitation the rights | ||
63 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
64 | +copies of the Software, and to permit persons to whom the Software is | ||
65 | +furnished to do so, subject to the following conditions: | ||
66 | + | ||
67 | +The above copyright notice and this permission notice shall be included in | ||
68 | +all copies or substantial portions of the Software. | ||
69 | + | ||
70 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
71 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
72 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
73 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
74 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
75 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
76 | +THE SOFTWARE. |
node_modules/array-series/component.json
0 → 100644
node_modules/array-series/index.js
0 → 100644
1 | +module.exports = function series(fns, context, callback) { | ||
2 | + if (!callback) { | ||
3 | + if (typeof context === 'function') { | ||
4 | + callback = context | ||
5 | + context = null | ||
6 | + } else { | ||
7 | + callback = noop | ||
8 | + } | ||
9 | + } | ||
10 | + | ||
11 | + if (!(fns && fns.length)) return callback(); | ||
12 | + | ||
13 | + fns = fns.slice(0) | ||
14 | + | ||
15 | + var call = context | ||
16 | + ? function () { | ||
17 | + fns.length | ||
18 | + ? fns.shift().call(context, next) | ||
19 | + : callback() | ||
20 | + } | ||
21 | + : function () { | ||
22 | + fns.length | ||
23 | + ? fns.shift()(next) | ||
24 | + : callback() | ||
25 | + } | ||
26 | + | ||
27 | + call() | ||
28 | + | ||
29 | + function next(err) { | ||
30 | + err ? callback(err) : call() | ||
31 | + } | ||
32 | +} | ||
33 | + | ||
34 | +function noop() {} |
node_modules/array-series/package.json
0 → 100644
1 | +{ | ||
2 | + "_args": [ | ||
3 | + [ | ||
4 | + { | ||
5 | + "raw": "array-series@~0.1.5", | ||
6 | + "scope": null, | ||
7 | + "escapedName": "array-series", | ||
8 | + "name": "array-series", | ||
9 | + "rawSpec": "~0.1.5", | ||
10 | + "spec": ">=0.1.5 <0.2.0", | ||
11 | + "type": "range" | ||
12 | + }, | ||
13 | + "/Users/fzy/project/koa2_Sequelize_project/node_modules/gm" | ||
14 | + ] | ||
15 | + ], | ||
16 | + "_from": "array-series@>=0.1.5 <0.2.0", | ||
17 | + "_id": "array-series@0.1.5", | ||
18 | + "_inCache": true, | ||
19 | + "_location": "/array-series", | ||
20 | + "_npmUser": { | ||
21 | + "name": "jongleberry", | ||
22 | + "email": "jonathanrichardong@gmail.com" | ||
23 | + }, | ||
24 | + "_npmVersion": "1.3.17", | ||
25 | + "_phantomChildren": {}, | ||
26 | + "_requested": { | ||
27 | + "raw": "array-series@~0.1.5", | ||
28 | + "scope": null, | ||
29 | + "escapedName": "array-series", | ||
30 | + "name": "array-series", | ||
31 | + "rawSpec": "~0.1.5", | ||
32 | + "spec": ">=0.1.5 <0.2.0", | ||
33 | + "type": "range" | ||
34 | + }, | ||
35 | + "_requiredBy": [ | ||
36 | + "/gm" | ||
37 | + ], | ||
38 | + "_resolved": "https://registry.npmjs.org/array-series/-/array-series-0.1.5.tgz", | ||
39 | + "_shasum": "df5d37bfc5c2ef0755e2aa4f92feae7d4b5a972f", | ||
40 | + "_shrinkwrap": null, | ||
41 | + "_spec": "array-series@~0.1.5", | ||
42 | + "_where": "/Users/fzy/project/koa2_Sequelize_project/node_modules/gm", | ||
43 | + "author": { | ||
44 | + "name": "Jonathan Ong", | ||
45 | + "email": "me@jongleberry.com", | ||
46 | + "url": "http://jongleberry.com" | ||
47 | + }, | ||
48 | + "bugs": { | ||
49 | + "url": "https://github.com/component/array-series/issues", | ||
50 | + "email": "me@jongleberry.com" | ||
51 | + }, | ||
52 | + "dependencies": {}, | ||
53 | + "description": "Call an array of asynchronous functions in series", | ||
54 | + "devDependencies": {}, | ||
55 | + "directories": {}, | ||
56 | + "dist": { | ||
57 | + "shasum": "df5d37bfc5c2ef0755e2aa4f92feae7d4b5a972f", | ||
58 | + "tarball": "https://registry.npmjs.org/array-series/-/array-series-0.1.5.tgz" | ||
59 | + }, | ||
60 | + "homepage": "https://github.com/component/array-series#readme", | ||
61 | + "license": "MIT", | ||
62 | + "maintainers": [ | ||
63 | + { | ||
64 | + "name": "jongleberry", | ||
65 | + "email": "jonathanrichardong@gmail.com" | ||
66 | + } | ||
67 | + ], | ||
68 | + "name": "array-series", | ||
69 | + "optionalDependencies": {}, | ||
70 | + "readme": "# Array Series [](https://travis-ci.org/component/array-series)\n\nCall an array of asynchronous functions in series\n\n### API\n\n#### series(fns[, context[, callback]])\n\n```js\nvar series = require('array-series')\n\nseries([\n function (done) {\n done()\n }\n], this, function (err) {\n\n})\n```\n\n#### fns\n\n`fns` is an array of functions to call in series.\nThe argument signature should be:\n\n```js\nfunction (done) {\n done(new Error())\n // or\n done()\n}\n```\n\nThat is, each function should only take a `done` as an argument.\nEach callback should only take an optional `Error` as an argument.\n\n#### context\n\nOptional context to pass to each `fn`.\nBasically `fn.call(context, done)`.\n\n#### callback(err)\n\n```js\nfunction (err) {\n\n}\n```\n\nOnly argument is an `Error` argument.\nIt will return the first error in the series of functions that returns an error,\nand no function after will be called.\n\n### License\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 Jonathan Ong me@jongleberry.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.", | ||
71 | + "readmeFilename": "README.md", | ||
72 | + "repository": { | ||
73 | + "type": "git", | ||
74 | + "url": "git+https://github.com/component/array-series.git" | ||
75 | + }, | ||
76 | + "scripts": { | ||
77 | + "test": "node test" | ||
78 | + }, | ||
79 | + "version": "0.1.5" | ||
80 | +} |
node_modules/array-series/test.js
0 → 100644
1 | +var assert = require('assert') | ||
2 | +var series = require('./') | ||
3 | + | ||
4 | +var a, b, c | ||
5 | + | ||
6 | +series([ | ||
7 | + function (done) { | ||
8 | + a = 1 | ||
9 | + process.nextTick(done) | ||
10 | + check('a') | ||
11 | + }, | ||
12 | + function (done) { | ||
13 | + b = 2 | ||
14 | + process.nextTick(done) | ||
15 | + check('b') | ||
16 | + }, | ||
17 | + function (done) { | ||
18 | + c = 3 | ||
19 | + process.nextTick(done) | ||
20 | + check('c') | ||
21 | + } | ||
22 | +], function (err) { | ||
23 | + assert.ifError(err) | ||
24 | + assert.equal(a, 1) | ||
25 | + assert.equal(b, 2) | ||
26 | + assert.equal(c, 3) | ||
27 | +}) | ||
28 | + | ||
29 | +function check(x) { | ||
30 | + switch (x) { | ||
31 | + case 'a': | ||
32 | + assert.equal(a, 1) | ||
33 | + assert.equal(b, undefined) | ||
34 | + assert.equal(c, undefined) | ||
35 | + break | ||
36 | + case 'b': | ||
37 | + assert.equal(a, 1) | ||
38 | + assert.equal(b, 2) | ||
39 | + assert.equal(c, undefined) | ||
40 | + break | ||
41 | + case 'c': | ||
42 | + assert.equal(a, 1) | ||
43 | + assert.equal(b, 2) | ||
44 | + assert.equal(c, 3) | ||
45 | + break | ||
46 | + } | ||
47 | +} | ||
48 | + | ||
49 | +var context = 'hello' | ||
50 | +series([function (done) { | ||
51 | + assert.equal(this, context) | ||
52 | + done() | ||
53 | +}], context) | ||
54 | + | ||
55 | +var finished | ||
56 | +series([], function (err) { | ||
57 | + finished = true | ||
58 | +}) | ||
59 | + | ||
60 | +process.nextTick(function () { | ||
61 | + if (!finished) | ||
62 | + throw new Error('Failed with no functions.'); | ||
63 | +}) | ||
64 | + | ||
65 | +var r, d, o | ||
66 | +series([ | ||
67 | + function (done) { | ||
68 | + r = 1 | ||
69 | + process.nextTick(done) | ||
70 | + }, | ||
71 | + function (done) { | ||
72 | + d = 0 | ||
73 | + process.nextTick(function () { | ||
74 | + done(new Error('message')) | ||
75 | + }) | ||
76 | + }, | ||
77 | + function (done) { | ||
78 | + o = 0 | ||
79 | + process.nextTick(done) | ||
80 | + } | ||
81 | +], function (err) { | ||
82 | + assert.equal(err.message, 'message') | ||
83 | + assert.equal(r, 1) | ||
84 | + assert.equal(d, 0) | ||
85 | + assert.equal(o, undefined) | ||
86 | +}) | ||
87 | + | ||
88 | +console.log('Array series tests pass!') |
node_modules/cross-spawn/LICENSE
0 → 100644
1 | +Copyright (c) 2014 IndigoUnited | ||
2 | + | ||
3 | +Permission is hereby granted, free of charge, to any person obtaining a copy | ||
4 | +of this software and associated documentation files (the "Software"), to deal | ||
5 | +in the Software without restriction, including without limitation the rights | ||
6 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
7 | +copies of the Software, and to permit persons to whom the Software is furnished | ||
8 | +to do so, subject to the following conditions: | ||
9 | + | ||
10 | +The above copyright notice and this permission notice shall be included in all | ||
11 | +copies or substantial portions of the Software. | ||
12 | + | ||
13 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
14 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
15 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
16 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
17 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
18 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
19 | +THE SOFTWARE. |
node_modules/cross-spawn/README.md
0 → 100644
1 | +# cross-spawn | ||
2 | + | ||
3 | +[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Build status][appveyor-image]][appveyor-url] [![Dependency status][david-dm-image]][david-dm-url] [![Dev Dependency status][david-dm-dev-image]][david-dm-dev-url] | ||
4 | + | ||
5 | +[npm-url]:https://npmjs.org/package/cross-spawn | ||
6 | +[downloads-image]:http://img.shields.io/npm/dm/cross-spawn.svg | ||
7 | +[npm-image]:http://img.shields.io/npm/v/cross-spawn.svg | ||
8 | +[travis-url]:https://travis-ci.org/IndigoUnited/node-cross-spawn | ||
9 | +[travis-image]:http://img.shields.io/travis/IndigoUnited/node-cross-spawn/master.svg | ||
10 | +[appveyor-url]:https://ci.appveyor.com/project/satazor/node-cross-spawn | ||
11 | +[appveyor-image]:https://img.shields.io/appveyor/ci/satazor/node-cross-spawn/master.svg | ||
12 | +[david-dm-url]:https://david-dm.org/IndigoUnited/node-cross-spawn | ||
13 | +[david-dm-image]:https://img.shields.io/david/IndigoUnited/node-cross-spawn.svg | ||
14 | +[david-dm-dev-url]:https://david-dm.org/IndigoUnited/node-cross-spawn#info=devDependencies | ||
15 | +[david-dm-dev-image]:https://img.shields.io/david/dev/IndigoUnited/node-cross-spawn.svg | ||
16 | + | ||
17 | +A cross platform solution to node's spawn and spawnSync. | ||
18 | + | ||
19 | + | ||
20 | +## Installation | ||
21 | + | ||
22 | +`$ npm install cross-spawn` | ||
23 | + | ||
24 | +If you are using `spawnSync` on node 0.10 or older, you will also need to install `spawn-sync`: | ||
25 | + | ||
26 | +`$ npm install spawn-sync` | ||
27 | + | ||
28 | + | ||
29 | +## Why | ||
30 | + | ||
31 | +Node has issues when using spawn on Windows: | ||
32 | + | ||
33 | +- It ignores [PATHEXT](https://github.com/joyent/node/issues/2318) | ||
34 | +- It does not support [shebangs](http://pt.wikipedia.org/wiki/Shebang) | ||
35 | +- It does not allow you to run `del` or `dir` | ||
36 | +- It does not properly escape arguments with spaces or special characters | ||
37 | + | ||
38 | +All these issues are handled correctly by `cross-spawn`. | ||
39 | +There are some known modules, such as [win-spawn](https://github.com/ForbesLindesay/win-spawn), that try to solve this but they are either broken or provide faulty escaping of shell arguments. | ||
40 | + | ||
41 | + | ||
42 | +## Usage | ||
43 | + | ||
44 | +Exactly the same way as node's [`spawn`](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) or [`spawnSync`](https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options), so it's a drop in replacement. | ||
45 | + | ||
46 | +```javascript | ||
47 | +var spawn = require('cross-spawn'); | ||
48 | + | ||
49 | +// Spawn NPM asynchronously | ||
50 | +var child = spawn('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' }); | ||
51 | + | ||
52 | +// Spawn NPM synchronously | ||
53 | +var results = spawn.sync('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' }); | ||
54 | +``` | ||
55 | + | ||
56 | +## Caveat | ||
57 | + | ||
58 | +On Windows, cross-spawn will only spawn `cmd.exe` if necessary. If the extension | ||
59 | +of the executable is `.exe` or `.com`, it will spawn it directly. If you wish | ||
60 | +to override this behavior and *always* spawn a shell, pass the `{shell: true}` | ||
61 | +option. | ||
62 | + | ||
63 | + | ||
64 | +## Tests | ||
65 | + | ||
66 | +`$ npm test` | ||
67 | + | ||
68 | + | ||
69 | +## License | ||
70 | + | ||
71 | +Released under the [MIT License](http://www.opensource.org/licenses/mit-license.php). |
node_modules/cross-spawn/index.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +var cp = require('child_process'); | ||
4 | +var parse = require('./lib/parse'); | ||
5 | +var enoent = require('./lib/enoent'); | ||
6 | + | ||
7 | +var cpSpawnSync = cp.spawnSync; | ||
8 | + | ||
9 | +function spawn(command, args, options) { | ||
10 | + var parsed; | ||
11 | + var spawned; | ||
12 | + | ||
13 | + // Parse the arguments | ||
14 | + parsed = parse(command, args, options); | ||
15 | + | ||
16 | + // Spawn the child process | ||
17 | + spawned = cp.spawn(parsed.command, parsed.args, parsed.options); | ||
18 | + | ||
19 | + // Hook into child process "exit" event to emit an error if the command | ||
20 | + // does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 | ||
21 | + enoent.hookChildProcess(spawned, parsed); | ||
22 | + | ||
23 | + return spawned; | ||
24 | +} | ||
25 | + | ||
26 | +function spawnSync(command, args, options) { | ||
27 | + var parsed; | ||
28 | + var result; | ||
29 | + | ||
30 | + if (!cpSpawnSync) { | ||
31 | + try { | ||
32 | + cpSpawnSync = require('spawn-sync'); // eslint-disable-line global-require | ||
33 | + } catch (ex) { | ||
34 | + throw new Error( | ||
35 | + 'In order to use spawnSync on node 0.10 or older, you must ' + | ||
36 | + 'install spawn-sync:\n\n' + | ||
37 | + ' npm install spawn-sync --save' | ||
38 | + ); | ||
39 | + } | ||
40 | + } | ||
41 | + | ||
42 | + // Parse the arguments | ||
43 | + parsed = parse(command, args, options); | ||
44 | + | ||
45 | + // Spawn the child process | ||
46 | + result = cpSpawnSync(parsed.command, parsed.args, parsed.options); | ||
47 | + | ||
48 | + // Analyze if the command does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 | ||
49 | + result.error = result.error || enoent.verifyENOENTSync(result.status, parsed); | ||
50 | + | ||
51 | + return result; | ||
52 | +} | ||
53 | + | ||
54 | +module.exports = spawn; | ||
55 | +module.exports.spawn = spawn; | ||
56 | +module.exports.sync = spawnSync; | ||
57 | + | ||
58 | +module.exports._parse = parse; | ||
59 | +module.exports._enoent = enoent; |
node_modules/cross-spawn/lib/enoent.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +var isWin = process.platform === 'win32'; | ||
4 | +var resolveCommand = require('./resolveCommand'); | ||
5 | + | ||
6 | +var isNode10 = process.version.indexOf('v0.10.') === 0; | ||
7 | + | ||
8 | +function notFoundError(command, syscall) { | ||
9 | + var err; | ||
10 | + | ||
11 | + err = new Error(syscall + ' ' + command + ' ENOENT'); | ||
12 | + err.code = err.errno = 'ENOENT'; | ||
13 | + err.syscall = syscall + ' ' + command; | ||
14 | + | ||
15 | + return err; | ||
16 | +} | ||
17 | + | ||
18 | +function hookChildProcess(cp, parsed) { | ||
19 | + var originalEmit; | ||
20 | + | ||
21 | + if (!isWin) { | ||
22 | + return; | ||
23 | + } | ||
24 | + | ||
25 | + originalEmit = cp.emit; | ||
26 | + cp.emit = function (name, arg1) { | ||
27 | + var err; | ||
28 | + | ||
29 | + // If emitting "exit" event and exit code is 1, we need to check if | ||
30 | + // the command exists and emit an "error" instead | ||
31 | + // See: https://github.com/IndigoUnited/node-cross-spawn/issues/16 | ||
32 | + if (name === 'exit') { | ||
33 | + err = verifyENOENT(arg1, parsed, 'spawn'); | ||
34 | + | ||
35 | + if (err) { | ||
36 | + return originalEmit.call(cp, 'error', err); | ||
37 | + } | ||
38 | + } | ||
39 | + | ||
40 | + return originalEmit.apply(cp, arguments); | ||
41 | + }; | ||
42 | +} | ||
43 | + | ||
44 | +function verifyENOENT(status, parsed) { | ||
45 | + if (isWin && status === 1 && !parsed.file) { | ||
46 | + return notFoundError(parsed.original, 'spawn'); | ||
47 | + } | ||
48 | + | ||
49 | + return null; | ||
50 | +} | ||
51 | + | ||
52 | +function verifyENOENTSync(status, parsed) { | ||
53 | + if (isWin && status === 1 && !parsed.file) { | ||
54 | + return notFoundError(parsed.original, 'spawnSync'); | ||
55 | + } | ||
56 | + | ||
57 | + // If we are in node 10, then we are using spawn-sync; if it exited | ||
58 | + // with -1 it probably means that the command does not exist | ||
59 | + if (isNode10 && status === -1) { | ||
60 | + parsed.file = isWin ? parsed.file : resolveCommand(parsed.original); | ||
61 | + | ||
62 | + if (!parsed.file) { | ||
63 | + return notFoundError(parsed.original, 'spawnSync'); | ||
64 | + } | ||
65 | + } | ||
66 | + | ||
67 | + return null; | ||
68 | +} | ||
69 | + | ||
70 | +module.exports.hookChildProcess = hookChildProcess; | ||
71 | +module.exports.verifyENOENT = verifyENOENT; | ||
72 | +module.exports.verifyENOENTSync = verifyENOENTSync; | ||
73 | +module.exports.notFoundError = notFoundError; |
node_modules/cross-spawn/lib/parse.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +var fs = require('fs'); | ||
4 | +var LRU = require('lru-cache'); | ||
5 | +var resolveCommand = require('./resolveCommand'); | ||
6 | +var hasBrokenSpawn = require('./hasBrokenSpawn'); | ||
7 | + | ||
8 | +var isWin = process.platform === 'win32'; | ||
9 | +var shebangCache = new LRU({ max: 50, maxAge: 30 * 1000 }); // Cache just for 30sec | ||
10 | + | ||
11 | +function readShebang(command) { | ||
12 | + var buffer; | ||
13 | + var fd; | ||
14 | + var match; | ||
15 | + var shebang; | ||
16 | + | ||
17 | + // Check if it is in the cache first | ||
18 | + if (shebangCache.has(command)) { | ||
19 | + return shebangCache.get(command); | ||
20 | + } | ||
21 | + | ||
22 | + // Read the first 150 bytes from the file | ||
23 | + buffer = new Buffer(150); | ||
24 | + | ||
25 | + try { | ||
26 | + fd = fs.openSync(command, 'r'); | ||
27 | + fs.readSync(fd, buffer, 0, 150, 0); | ||
28 | + fs.closeSync(fd); | ||
29 | + } catch (e) { /* empty */ } | ||
30 | + | ||
31 | + // Check if it is a shebang | ||
32 | + match = buffer.toString().trim().match(/#!(.+)/i); | ||
33 | + | ||
34 | + if (match) { | ||
35 | + shebang = match[1].replace(/\/usr\/bin\/env\s+/i, ''); // Remove /usr/bin/env | ||
36 | + } | ||
37 | + | ||
38 | + // Store the shebang in the cache | ||
39 | + shebangCache.set(command, shebang); | ||
40 | + | ||
41 | + return shebang; | ||
42 | +} | ||
43 | + | ||
44 | +function escapeArg(arg, quote) { | ||
45 | + // Convert to string | ||
46 | + arg = '' + arg; | ||
47 | + | ||
48 | + // If we are not going to quote the argument, | ||
49 | + // escape shell metacharacters, including double and single quotes: | ||
50 | + if (!quote) { | ||
51 | + arg = arg.replace(/([\(\)%!\^<>&|;,"'\s])/g, '^$1'); | ||
52 | + } else { | ||
53 | + // Sequence of backslashes followed by a double quote: | ||
54 | + // double up all the backslashes and escape the double quote | ||
55 | + arg = arg.replace(/(\\*)"/g, '$1$1\\"'); | ||
56 | + | ||
57 | + // Sequence of backslashes followed by the end of the string | ||
58 | + // (which will become a double quote later): | ||
59 | + // double up all the backslashes | ||
60 | + arg = arg.replace(/(\\*)$/, '$1$1'); | ||
61 | + | ||
62 | + // All other backslashes occur literally | ||
63 | + | ||
64 | + // Quote the whole thing: | ||
65 | + arg = '"' + arg + '"'; | ||
66 | + } | ||
67 | + | ||
68 | + return arg; | ||
69 | +} | ||
70 | + | ||
71 | +function escapeCommand(command) { | ||
72 | + // Do not escape if this command is not dangerous.. | ||
73 | + // We do this so that commands like "echo" or "ifconfig" work | ||
74 | + // Quoting them, will make them unaccessible | ||
75 | + return /^[a-z0-9_-]+$/i.test(command) ? command : escapeArg(command, true); | ||
76 | +} | ||
77 | + | ||
78 | +function requiresShell(command) { | ||
79 | + return !/\.(?:com|exe)$/i.test(command); | ||
80 | +} | ||
81 | + | ||
82 | +function parse(command, args, options) { | ||
83 | + var shebang; | ||
84 | + var applyQuotes; | ||
85 | + var file; | ||
86 | + var original; | ||
87 | + var shell; | ||
88 | + | ||
89 | + // Normalize arguments, similar to nodejs | ||
90 | + if (args && !Array.isArray(args)) { | ||
91 | + options = args; | ||
92 | + args = null; | ||
93 | + } | ||
94 | + | ||
95 | + args = args ? args.slice(0) : []; // Clone array to avoid changing the original | ||
96 | + options = options || {}; | ||
97 | + original = command; | ||
98 | + | ||
99 | + if (isWin) { | ||
100 | + // Detect & add support for shebangs | ||
101 | + file = resolveCommand(command); | ||
102 | + file = file || resolveCommand(command, true); | ||
103 | + shebang = file && readShebang(file); | ||
104 | + shell = options.shell || hasBrokenSpawn; | ||
105 | + | ||
106 | + if (shebang) { | ||
107 | + args.unshift(file); | ||
108 | + command = shebang; | ||
109 | + shell = shell || requiresShell(resolveCommand(shebang) || resolveCommand(shebang, true)); | ||
110 | + } else { | ||
111 | + shell = shell || requiresShell(file); | ||
112 | + } | ||
113 | + | ||
114 | + if (shell) { | ||
115 | + // Escape command & arguments | ||
116 | + applyQuotes = (command !== 'echo'); // Do not quote arguments for the special "echo" command | ||
117 | + command = escapeCommand(command); | ||
118 | + args = args.map(function (arg) { | ||
119 | + return escapeArg(arg, applyQuotes); | ||
120 | + }); | ||
121 | + | ||
122 | + // Use cmd.exe | ||
123 | + args = ['/s', '/c', '"' + command + (args.length ? ' ' + args.join(' ') : '') + '"']; | ||
124 | + command = process.env.comspec || 'cmd.exe'; | ||
125 | + | ||
126 | + // Tell node's spawn that the arguments are already escaped | ||
127 | + options.windowsVerbatimArguments = true; | ||
128 | + } | ||
129 | + } | ||
130 | + | ||
131 | + return { | ||
132 | + command: command, | ||
133 | + args: args, | ||
134 | + options: options, | ||
135 | + file: file, | ||
136 | + original: original, | ||
137 | + }; | ||
138 | +} | ||
139 | + | ||
140 | +module.exports = parse; |
1 | +'use strict'; | ||
2 | + | ||
3 | +var path = require('path'); | ||
4 | +var which = require('which'); | ||
5 | +var LRU = require('lru-cache'); | ||
6 | + | ||
7 | +var commandCache = new LRU({ max: 50, maxAge: 30 * 1000 }); // Cache just for 30sec | ||
8 | + | ||
9 | +function resolveCommand(command, noExtension) { | ||
10 | + var resolved; | ||
11 | + | ||
12 | + noExtension = !!noExtension; | ||
13 | + resolved = commandCache.get(command + '!' + noExtension); | ||
14 | + | ||
15 | + // Check if its resolved in the cache | ||
16 | + if (commandCache.has(command)) { | ||
17 | + return commandCache.get(command); | ||
18 | + } | ||
19 | + | ||
20 | + try { | ||
21 | + resolved = !noExtension ? | ||
22 | + which.sync(command) : | ||
23 | + which.sync(command, { pathExt: path.delimiter + (process.env.PATHEXT || '') }); | ||
24 | + } catch (e) { /* empty */ } | ||
25 | + | ||
26 | + commandCache.set(command + '!' + noExtension, resolved); | ||
27 | + | ||
28 | + return resolved; | ||
29 | +} | ||
30 | + | ||
31 | +module.exports = resolveCommand; |
node_modules/cross-spawn/package.json
0 → 100644
1 | +{ | ||
2 | + "_args": [ | ||
3 | + [ | ||
4 | + { | ||
5 | + "raw": "cross-spawn@^4.0.0", | ||
6 | + "scope": null, | ||
7 | + "escapedName": "cross-spawn", | ||
8 | + "name": "cross-spawn", | ||
9 | + "rawSpec": "^4.0.0", | ||
10 | + "spec": ">=4.0.0 <5.0.0", | ||
11 | + "type": "range" | ||
12 | + }, | ||
13 | + "/Users/fzy/project/koa2_Sequelize_project/node_modules/gm" | ||
14 | + ] | ||
15 | + ], | ||
16 | + "_from": "cross-spawn@>=4.0.0 <5.0.0", | ||
17 | + "_id": "cross-spawn@4.0.2", | ||
18 | + "_inCache": true, | ||
19 | + "_location": "/cross-spawn", | ||
20 | + "_nodeVersion": "4.5.0", | ||
21 | + "_npmOperationalInternal": { | ||
22 | + "host": "packages-12-west.internal.npmjs.com", | ||
23 | + "tmp": "tmp/cross-spawn-4.0.2.tgz_1474803799646_0.017929385183379054" | ||
24 | + }, | ||
25 | + "_npmUser": { | ||
26 | + "name": "satazor", | ||
27 | + "email": "andremiguelcruz@msn.com" | ||
28 | + }, | ||
29 | + "_npmVersion": "2.15.9", | ||
30 | + "_phantomChildren": {}, | ||
31 | + "_requested": { | ||
32 | + "raw": "cross-spawn@^4.0.0", | ||
33 | + "scope": null, | ||
34 | + "escapedName": "cross-spawn", | ||
35 | + "name": "cross-spawn", | ||
36 | + "rawSpec": "^4.0.0", | ||
37 | + "spec": ">=4.0.0 <5.0.0", | ||
38 | + "type": "range" | ||
39 | + }, | ||
40 | + "_requiredBy": [ | ||
41 | + "/gm" | ||
42 | + ], | ||
43 | + "_resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", | ||
44 | + "_shasum": "7b9247621c23adfdd3856004a823cbe397424d41", | ||
45 | + "_shrinkwrap": null, | ||
46 | + "_spec": "cross-spawn@^4.0.0", | ||
47 | + "_where": "/Users/fzy/project/koa2_Sequelize_project/node_modules/gm", | ||
48 | + "author": { | ||
49 | + "name": "IndigoUnited", | ||
50 | + "email": "hello@indigounited.com", | ||
51 | + "url": "http://indigounited.com" | ||
52 | + }, | ||
53 | + "bugs": { | ||
54 | + "url": "https://github.com/IndigoUnited/node-cross-spawn/issues/" | ||
55 | + }, | ||
56 | + "dependencies": { | ||
57 | + "lru-cache": "^4.0.1", | ||
58 | + "which": "^1.2.9" | ||
59 | + }, | ||
60 | + "description": "Cross platform child_process#spawn and child_process#spawnSync", | ||
61 | + "devDependencies": { | ||
62 | + "@satazor/eslint-config": "^3.0.0", | ||
63 | + "eslint": "^3.0.0", | ||
64 | + "expect.js": "^0.3.0", | ||
65 | + "glob": "^7.0.0", | ||
66 | + "mkdirp": "^0.5.1", | ||
67 | + "mocha": "^3.0.2", | ||
68 | + "rimraf": "^2.5.0" | ||
69 | + }, | ||
70 | + "directories": {}, | ||
71 | + "dist": { | ||
72 | + "shasum": "7b9247621c23adfdd3856004a823cbe397424d41", | ||
73 | + "tarball": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz" | ||
74 | + }, | ||
75 | + "files": [ | ||
76 | + "index.js", | ||
77 | + "lib" | ||
78 | + ], | ||
79 | + "gitHead": "674ceb2f2b69ad64b5dcad661b9bf048d6ec4c22", | ||
80 | + "homepage": "https://github.com/IndigoUnited/node-cross-spawn#readme", | ||
81 | + "keywords": [ | ||
82 | + "spawn", | ||
83 | + "spawnSync", | ||
84 | + "windows", | ||
85 | + "cross", | ||
86 | + "platform", | ||
87 | + "path", | ||
88 | + "ext", | ||
89 | + "path-ext", | ||
90 | + "path_ext", | ||
91 | + "shebang", | ||
92 | + "hashbang", | ||
93 | + "cmd", | ||
94 | + "execute" | ||
95 | + ], | ||
96 | + "license": "MIT", | ||
97 | + "main": "index.js", | ||
98 | + "maintainers": [ | ||
99 | + { | ||
100 | + "name": "satazor", | ||
101 | + "email": "andremiguelcruz@msn.com" | ||
102 | + } | ||
103 | + ], | ||
104 | + "name": "cross-spawn", | ||
105 | + "optionalDependencies": {}, | ||
106 | + "readme": "# cross-spawn\n\n[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Build status][appveyor-image]][appveyor-url] [![Dependency status][david-dm-image]][david-dm-url] [![Dev Dependency status][david-dm-dev-image]][david-dm-dev-url]\n\n[npm-url]:https://npmjs.org/package/cross-spawn\n[downloads-image]:http://img.shields.io/npm/dm/cross-spawn.svg\n[npm-image]:http://img.shields.io/npm/v/cross-spawn.svg\n[travis-url]:https://travis-ci.org/IndigoUnited/node-cross-spawn\n[travis-image]:http://img.shields.io/travis/IndigoUnited/node-cross-spawn/master.svg\n[appveyor-url]:https://ci.appveyor.com/project/satazor/node-cross-spawn\n[appveyor-image]:https://img.shields.io/appveyor/ci/satazor/node-cross-spawn/master.svg\n[david-dm-url]:https://david-dm.org/IndigoUnited/node-cross-spawn\n[david-dm-image]:https://img.shields.io/david/IndigoUnited/node-cross-spawn.svg\n[david-dm-dev-url]:https://david-dm.org/IndigoUnited/node-cross-spawn#info=devDependencies\n[david-dm-dev-image]:https://img.shields.io/david/dev/IndigoUnited/node-cross-spawn.svg\n\nA cross platform solution to node's spawn and spawnSync.\n\n\n## Installation\n\n`$ npm install cross-spawn`\n\nIf you are using `spawnSync` on node 0.10 or older, you will also need to install `spawn-sync`:\n\n`$ npm install spawn-sync`\n\n\n## Why\n\nNode has issues when using spawn on Windows:\n\n- It ignores [PATHEXT](https://github.com/joyent/node/issues/2318)\n- It does not support [shebangs](http://pt.wikipedia.org/wiki/Shebang)\n- It does not allow you to run `del` or `dir`\n- It does not properly escape arguments with spaces or special characters\n\nAll these issues are handled correctly by `cross-spawn`.\nThere are some known modules, such as [win-spawn](https://github.com/ForbesLindesay/win-spawn), that try to solve this but they are either broken or provide faulty escaping of shell arguments.\n\n\n## Usage\n\nExactly the same way as node's [`spawn`](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) or [`spawnSync`](https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options), so it's a drop in replacement.\n\n```javascript\nvar spawn = require('cross-spawn');\n\n// Spawn NPM asynchronously\nvar child = spawn('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' });\n\n// Spawn NPM synchronously\nvar results = spawn.sync('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' });\n```\n\n## Caveat\n\nOn Windows, cross-spawn will only spawn `cmd.exe` if necessary. If the extension\nof the executable is `.exe` or `.com`, it will spawn it directly. If you wish\nto override this behavior and *always* spawn a shell, pass the `{shell: true}`\noption.\n\n\n## Tests\n\n`$ npm test`\n\n\n## License\n\nReleased under the [MIT License](http://www.opensource.org/licenses/mit-license.php).\n", | ||
107 | + "readmeFilename": "README.md", | ||
108 | + "repository": { | ||
109 | + "type": "git", | ||
110 | + "url": "git://github.com/IndigoUnited/node-cross-spawn.git" | ||
111 | + }, | ||
112 | + "scripts": { | ||
113 | + "lint": "eslint '{*.js,lib/**/*.js,test/**/*.js}'", | ||
114 | + "test": "node test/prepare && mocha --bail test/test" | ||
115 | + }, | ||
116 | + "version": "4.0.2" | ||
117 | +} |
1 | -Copyright (c) 2012-2014 Raynos. | 1 | +The MIT License (MIT) |
2 | + | ||
3 | +Copyright (c) 2014-2015, Jon Schlinkert. | ||
2 | 4 | ||
3 | Permission is hereby granted, free of charge, to any person obtaining a copy | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy |
4 | of this software and associated documentation files (the "Software"), to deal | 6 | of this software and associated documentation files (the "Software"), to deal |
node_modules/extend-shallow/README.md
0 → 100644
1 | +# extend-shallow [](http://badge.fury.io/js/extend-shallow) [](https://travis-ci.org/jonschlinkert/extend-shallow) | ||
2 | + | ||
3 | +> Extend an object with the properties of additional objects. node.js/javascript util. | ||
4 | + | ||
5 | +## Install | ||
6 | + | ||
7 | +Install with [npm](https://www.npmjs.com/) | ||
8 | + | ||
9 | +```sh | ||
10 | +$ npm i extend-shallow --save | ||
11 | +``` | ||
12 | + | ||
13 | +## Usage | ||
14 | + | ||
15 | +```js | ||
16 | +var extend = require('extend-shallow'); | ||
17 | + | ||
18 | +extend({a: 'b'}, {c: 'd'}) | ||
19 | +//=> {a: 'b', c: 'd'} | ||
20 | +``` | ||
21 | + | ||
22 | +Pass an empty object to shallow clone: | ||
23 | + | ||
24 | +```js | ||
25 | +var obj = {}; | ||
26 | +extend(obj, {a: 'b'}, {c: 'd'}) | ||
27 | +//=> {a: 'b', c: 'd'} | ||
28 | +``` | ||
29 | + | ||
30 | +## Related | ||
31 | + | ||
32 | +* [extend-shallow](https://github.com/jonschlinkert/extend-shallow): Extend an object with the properties of additional objects. node.js/javascript util. | ||
33 | +* [for-own](https://github.com/jonschlinkert/for-own): Iterate over the own enumerable properties of an object, and return an object with properties… [more](https://github.com/jonschlinkert/for-own) | ||
34 | +* [for-in](https://github.com/jonschlinkert/for-in): Iterate over the own and inherited enumerable properties of an objecte, and return an object… [more](https://github.com/jonschlinkert/for-in) | ||
35 | +* [is-plain-object](https://github.com/jonschlinkert/is-plain-object): Returns true if an object was created by the `Object` constructor. | ||
36 | +* [isobject](https://github.com/jonschlinkert/isobject): Returns true if the value is an object and not an array or null. | ||
37 | +* [kind-of](https://github.com/jonschlinkert/kind-of): Get the native type of a value. | ||
38 | + | ||
39 | +## Running tests | ||
40 | + | ||
41 | +Install dev dependencies: | ||
42 | + | ||
43 | +```sh | ||
44 | +$ npm i -d && npm test | ||
45 | +``` | ||
46 | + | ||
47 | +## Author | ||
48 | + | ||
49 | +**Jon Schlinkert** | ||
50 | + | ||
51 | ++ [github/jonschlinkert](https://github.com/jonschlinkert) | ||
52 | ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) | ||
53 | + | ||
54 | +## License | ||
55 | + | ||
56 | +Copyright © 2015 Jon Schlinkert | ||
57 | +Released under the MIT license. | ||
58 | + | ||
59 | +*** | ||
60 | + | ||
61 | +_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on June 29, 2015._ |
node_modules/extend-shallow/index.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +var isObject = require('is-extendable'); | ||
4 | + | ||
5 | +module.exports = function extend(o/*, objects*/) { | ||
6 | + if (!isObject(o)) { o = {}; } | ||
7 | + | ||
8 | + var len = arguments.length; | ||
9 | + for (var i = 1; i < len; i++) { | ||
10 | + var obj = arguments[i]; | ||
11 | + | ||
12 | + if (isObject(obj)) { | ||
13 | + assign(o, obj); | ||
14 | + } | ||
15 | + } | ||
16 | + return o; | ||
17 | +}; | ||
18 | + | ||
19 | +function assign(a, b) { | ||
20 | + for (var key in b) { | ||
21 | + if (hasOwn(b, key)) { | ||
22 | + a[key] = b[key]; | ||
23 | + } | ||
24 | + } | ||
25 | +} | ||
26 | + | ||
27 | +/** | ||
28 | + * Returns true if the given `key` is an own property of `obj`. | ||
29 | + */ | ||
30 | + | ||
31 | +function hasOwn(obj, key) { | ||
32 | + return Object.prototype.hasOwnProperty.call(obj, key); | ||
33 | +} |
node_modules/extend-shallow/package.json
0 → 100644
1 | +{ | ||
2 | + "_args": [ | ||
3 | + [ | ||
4 | + { | ||
5 | + "raw": "extend-shallow@^2.0.1", | ||
6 | + "scope": null, | ||
7 | + "escapedName": "extend-shallow", | ||
8 | + "name": "extend-shallow", | ||
9 | + "rawSpec": "^2.0.1", | ||
10 | + "spec": ">=2.0.1 <3.0.0", | ||
11 | + "type": "range" | ||
12 | + }, | ||
13 | + "/Users/fzy/project/koa2_Sequelize_project/node_modules/koa-better-body" | ||
14 | + ] | ||
15 | + ], | ||
16 | + "_from": "extend-shallow@>=2.0.1 <3.0.0", | ||
17 | + "_id": "extend-shallow@2.0.1", | ||
18 | + "_inCache": true, | ||
19 | + "_location": "/extend-shallow", | ||
20 | + "_nodeVersion": "0.12.4", | ||
21 | + "_npmUser": { | ||
22 | + "name": "jonschlinkert", | ||
23 | + "email": "github@sellside.com" | ||
24 | + }, | ||
25 | + "_npmVersion": "2.10.1", | ||
26 | + "_phantomChildren": {}, | ||
27 | + "_requested": { | ||
28 | + "raw": "extend-shallow@^2.0.1", | ||
29 | + "scope": null, | ||
30 | + "escapedName": "extend-shallow", | ||
31 | + "name": "extend-shallow", | ||
32 | + "rawSpec": "^2.0.1", | ||
33 | + "spec": ">=2.0.1 <3.0.0", | ||
34 | + "type": "range" | ||
35 | + }, | ||
36 | + "_requiredBy": [ | ||
37 | + "/koa-better-body" | ||
38 | + ], | ||
39 | + "_resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", | ||
40 | + "_shasum": "51af7d614ad9a9f610ea1bafbb989d6b1c56890f", | ||
41 | + "_shrinkwrap": null, | ||
42 | + "_spec": "extend-shallow@^2.0.1", | ||
43 | + "_where": "/Users/fzy/project/koa2_Sequelize_project/node_modules/koa-better-body", | ||
44 | + "author": { | ||
45 | + "name": "Jon Schlinkert", | ||
46 | + "url": "https://github.com/jonschlinkert" | ||
47 | + }, | ||
48 | + "bugs": { | ||
49 | + "url": "https://github.com/jonschlinkert/extend-shallow/issues" | ||
50 | + }, | ||
51 | + "dependencies": { | ||
52 | + "is-extendable": "^0.1.0" | ||
53 | + }, | ||
54 | + "description": "Extend an object with the properties of additional objects. node.js/javascript util.", | ||
55 | + "devDependencies": { | ||
56 | + "array-slice": "^0.2.3", | ||
57 | + "benchmarked": "^0.1.4", | ||
58 | + "chalk": "^1.0.0", | ||
59 | + "for-own": "^0.1.3", | ||
60 | + "glob": "^5.0.12", | ||
61 | + "is-plain-object": "^2.0.1", | ||
62 | + "kind-of": "^2.0.0", | ||
63 | + "minimist": "^1.1.1", | ||
64 | + "mocha": "^2.2.5", | ||
65 | + "should": "^7.0.1" | ||
66 | + }, | ||
67 | + "directories": {}, | ||
68 | + "dist": { | ||
69 | + "shasum": "51af7d614ad9a9f610ea1bafbb989d6b1c56890f", | ||
70 | + "tarball": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" | ||
71 | + }, | ||
72 | + "engines": { | ||
73 | + "node": ">=0.10.0" | ||
74 | + }, | ||
75 | + "files": [ | ||
76 | + "index.js" | ||
77 | + ], | ||
78 | + "gitHead": "e9b1f1d2ff9d2990ec4a127afa7c14732d1eec8a", | ||
79 | + "homepage": "https://github.com/jonschlinkert/extend-shallow", | ||
80 | + "keywords": [ | ||
81 | + "assign", | ||
82 | + "extend", | ||
83 | + "javascript", | ||
84 | + "js", | ||
85 | + "keys", | ||
86 | + "merge", | ||
87 | + "obj", | ||
88 | + "object", | ||
89 | + "prop", | ||
90 | + "properties", | ||
91 | + "property", | ||
92 | + "props", | ||
93 | + "shallow", | ||
94 | + "util", | ||
95 | + "utility", | ||
96 | + "utils", | ||
97 | + "value" | ||
98 | + ], | ||
99 | + "license": "MIT", | ||
100 | + "main": "index.js", | ||
101 | + "maintainers": [ | ||
102 | + { | ||
103 | + "name": "jonschlinkert", | ||
104 | + "email": "github@sellside.com" | ||
105 | + } | ||
106 | + ], | ||
107 | + "name": "extend-shallow", | ||
108 | + "optionalDependencies": {}, | ||
109 | + "readme": "# extend-shallow [](http://badge.fury.io/js/extend-shallow) [](https://travis-ci.org/jonschlinkert/extend-shallow)\n\n> Extend an object with the properties of additional objects. node.js/javascript util.\n\n## Install\n\nInstall with [npm](https://www.npmjs.com/)\n\n```sh\n$ npm i extend-shallow --save\n```\n\n## Usage\n\n```js\nvar extend = require('extend-shallow');\n\nextend({a: 'b'}, {c: 'd'})\n//=> {a: 'b', c: 'd'}\n```\n\nPass an empty object to shallow clone:\n\n```js\nvar obj = {};\nextend(obj, {a: 'b'}, {c: 'd'})\n//=> {a: 'b', c: 'd'}\n```\n\n## Related\n\n* [extend-shallow](https://github.com/jonschlinkert/extend-shallow): Extend an object with the properties of additional objects. node.js/javascript util.\n* [for-own](https://github.com/jonschlinkert/for-own): Iterate over the own enumerable properties of an object, and return an object with properties… [more](https://github.com/jonschlinkert/for-own)\n* [for-in](https://github.com/jonschlinkert/for-in): Iterate over the own and inherited enumerable properties of an objecte, and return an object… [more](https://github.com/jonschlinkert/for-in)\n* [is-plain-object](https://github.com/jonschlinkert/is-plain-object): Returns true if an object was created by the `Object` constructor.\n* [isobject](https://github.com/jonschlinkert/isobject): Returns true if the value is an object and not an array or null.\n* [kind-of](https://github.com/jonschlinkert/kind-of): Get the native type of a value.\n\n## Running tests\n\nInstall dev dependencies:\n\n```sh\n$ npm i -d && npm test\n```\n\n## Author\n\n**Jon Schlinkert**\n\n+ [github/jonschlinkert](https://github.com/jonschlinkert)\n+ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)\n\n## License\n\nCopyright © 2015 Jon Schlinkert\nReleased under the MIT license.\n\n***\n\n_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on June 29, 2015._", | ||
110 | + "readmeFilename": "README.md", | ||
111 | + "repository": { | ||
112 | + "type": "git", | ||
113 | + "url": "git+https://github.com/jonschlinkert/extend-shallow.git" | ||
114 | + }, | ||
115 | + "scripts": { | ||
116 | + "test": "mocha" | ||
117 | + }, | ||
118 | + "version": "2.0.1" | ||
119 | +} |
node_modules/formidable/.npmignore
0 → 100644
node_modules/formidable/.travis.yml
0 → 100644
node_modules/formidable/LICENSE
0 → 100644
1 | +Copyright (C) 2011 Felix Geisendörfer | ||
2 | + | ||
3 | +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: | ||
4 | + | ||
5 | +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
6 | + | ||
7 | +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. |
node_modules/formidable/Readme.md
0 → 100644
1 | +# Formidable | ||
2 | + | ||
3 | +[](https://travis-ci.org/felixge/node-formidable) | ||
4 | + | ||
5 | +## Purpose | ||
6 | + | ||
7 | +A Node.js module for parsing form data, especially file uploads. | ||
8 | + | ||
9 | +## Current status | ||
10 | + | ||
11 | +**Maintainers Wanted:** Please see https://github.com/felixge/node-formidable/issues/412 | ||
12 | + | ||
13 | +This module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading | ||
14 | +and encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from | ||
15 | +a large variety of clients and is considered production-ready. | ||
16 | + | ||
17 | +## Features | ||
18 | + | ||
19 | +* Fast (~500mb/sec), non-buffering multipart parser | ||
20 | +* Automatically writing file uploads to disk | ||
21 | +* Low memory footprint | ||
22 | +* Graceful error handling | ||
23 | +* Very high test coverage | ||
24 | + | ||
25 | +## Installation | ||
26 | + | ||
27 | +```sh | ||
28 | +npm i -S formidable | ||
29 | +``` | ||
30 | + | ||
31 | +This is a low level package, and if you're using a high level framework such as Express, chances are it's already included in it. You can [read this discussion](http://stackoverflow.com/questions/11295554/how-to-disable-express-bodyparser-for-file-uploads-node-js) about how Formidable is integrated with Express. | ||
32 | + | ||
33 | +Note: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library. | ||
34 | + | ||
35 | +## Example | ||
36 | + | ||
37 | +Parse an incoming file upload. | ||
38 | +```javascript | ||
39 | +var formidable = require('formidable'), | ||
40 | + http = require('http'), | ||
41 | + util = require('util'); | ||
42 | + | ||
43 | +http.createServer(function(req, res) { | ||
44 | + if (req.url == '/upload' && req.method.toLowerCase() == 'post') { | ||
45 | + // parse a file upload | ||
46 | + var form = new formidable.IncomingForm(); | ||
47 | + | ||
48 | + form.parse(req, function(err, fields, files) { | ||
49 | + res.writeHead(200, {'content-type': 'text/plain'}); | ||
50 | + res.write('received upload:\n\n'); | ||
51 | + res.end(util.inspect({fields: fields, files: files})); | ||
52 | + }); | ||
53 | + | ||
54 | + return; | ||
55 | + } | ||
56 | + | ||
57 | + // show a file upload form | ||
58 | + res.writeHead(200, {'content-type': 'text/html'}); | ||
59 | + res.end( | ||
60 | + '<form action="/upload" enctype="multipart/form-data" method="post">'+ | ||
61 | + '<input type="text" name="title"><br>'+ | ||
62 | + '<input type="file" name="upload" multiple="multiple"><br>'+ | ||
63 | + '<input type="submit" value="Upload">'+ | ||
64 | + '</form>' | ||
65 | + ); | ||
66 | +}).listen(8080); | ||
67 | +``` | ||
68 | +## API | ||
69 | + | ||
70 | +### Formidable.IncomingForm | ||
71 | +```javascript | ||
72 | +var form = new formidable.IncomingForm() | ||
73 | +``` | ||
74 | +Creates a new incoming form. | ||
75 | + | ||
76 | +```javascript | ||
77 | +form.encoding = 'utf-8'; | ||
78 | +``` | ||
79 | +Sets encoding for incoming form fields. | ||
80 | + | ||
81 | +```javascript | ||
82 | +form.uploadDir = "/my/dir"; | ||
83 | +``` | ||
84 | +Sets the directory for placing file uploads in. You can move them later on using | ||
85 | +`fs.rename()`. The default is `os.tmpdir()`. | ||
86 | + | ||
87 | +```javascript | ||
88 | +form.keepExtensions = false; | ||
89 | +``` | ||
90 | +If you want the files written to `form.uploadDir` to include the extensions of the original files, set this property to `true`. | ||
91 | + | ||
92 | +```javascript | ||
93 | +form.type | ||
94 | +``` | ||
95 | +Either 'multipart' or 'urlencoded' depending on the incoming request. | ||
96 | + | ||
97 | +```javascript | ||
98 | +form.maxFieldsSize = 2 * 1024 * 1024; | ||
99 | +``` | ||
100 | +Limits the amount of memory all fields together (except files) can allocate in bytes. | ||
101 | +If this value is exceeded, an `'error'` event is emitted. The default | ||
102 | +size is 2MB. | ||
103 | + | ||
104 | +```javascript | ||
105 | +form.maxFields = 1000; | ||
106 | +``` | ||
107 | +Limits the number of fields that the querystring parser will decode. Defaults | ||
108 | +to 1000 (0 for unlimited). | ||
109 | + | ||
110 | +```javascript | ||
111 | +form.hash = false; | ||
112 | +``` | ||
113 | +If you want checksums calculated for incoming files, set this to either `'sha1'` or `'md5'`. | ||
114 | + | ||
115 | +```javascript | ||
116 | +form.multiples = false; | ||
117 | +``` | ||
118 | +If this option is enabled, when you call `form.parse`, the `files` argument will contain arrays of files for inputs which submit multiple files using the HTML5 `multiple` attribute. | ||
119 | + | ||
120 | +```javascript | ||
121 | +form.bytesReceived | ||
122 | +``` | ||
123 | +The amount of bytes received for this form so far. | ||
124 | + | ||
125 | +```javascript | ||
126 | +form.bytesExpected | ||
127 | +``` | ||
128 | +The expected number of bytes in this form. | ||
129 | + | ||
130 | +```javascript | ||
131 | +form.parse(request, [cb]); | ||
132 | +``` | ||
133 | +Parses an incoming node.js `request` containing form data. If `cb` is provided, all fields and files are collected and passed to the callback: | ||
134 | + | ||
135 | + | ||
136 | +```javascript | ||
137 | +form.parse(req, function(err, fields, files) { | ||
138 | + // ... | ||
139 | +}); | ||
140 | + | ||
141 | +form.onPart(part); | ||
142 | +``` | ||
143 | +You may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events processing which would occur otherwise, making you fully responsible for handling the processing. | ||
144 | + | ||
145 | +```javascript | ||
146 | +form.onPart = function(part) { | ||
147 | + part.addListener('data', function() { | ||
148 | + // ... | ||
149 | + }); | ||
150 | +} | ||
151 | +``` | ||
152 | +If you want to use formidable to only handle certain parts for you, you can do so: | ||
153 | +```javascript | ||
154 | +form.onPart = function(part) { | ||
155 | + if (!part.filename) { | ||
156 | + // let formidable handle all non-file parts | ||
157 | + form.handlePart(part); | ||
158 | + } | ||
159 | +} | ||
160 | +``` | ||
161 | +Check the code in this method for further inspiration. | ||
162 | + | ||
163 | + | ||
164 | +### Formidable.File | ||
165 | +```javascript | ||
166 | +file.size = 0 | ||
167 | +``` | ||
168 | +The size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet. | ||
169 | +```javascript | ||
170 | +file.path = null | ||
171 | +``` | ||
172 | +The path this file is being written to. You can modify this in the `'fileBegin'` event in | ||
173 | +case you are unhappy with the way formidable generates a temporary path for your files. | ||
174 | +```javascript | ||
175 | +file.name = null | ||
176 | +``` | ||
177 | +The name this file had according to the uploading client. | ||
178 | +```javascript | ||
179 | +file.type = null | ||
180 | +``` | ||
181 | +The mime type of this file, according to the uploading client. | ||
182 | +```javascript | ||
183 | +file.lastModifiedDate = null | ||
184 | +``` | ||
185 | +A date object (or `null`) containing the time this file was last written to. Mostly | ||
186 | +here for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/). | ||
187 | +```javascript | ||
188 | +file.hash = null | ||
189 | +``` | ||
190 | +If hash calculation was set, you can read the hex digest out of this var. | ||
191 | + | ||
192 | +#### Formidable.File#toJSON() | ||
193 | + | ||
194 | + This method returns a JSON-representation of the file, allowing you to | ||
195 | + `JSON.stringify()` the file which is useful for logging and responding | ||
196 | + to requests. | ||
197 | + | ||
198 | +### Events | ||
199 | + | ||
200 | + | ||
201 | +#### 'progress' | ||
202 | + | ||
203 | +Emitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar. | ||
204 | + | ||
205 | +```javascript | ||
206 | +form.on('progress', function(bytesReceived, bytesExpected) { | ||
207 | +}); | ||
208 | +``` | ||
209 | + | ||
210 | + | ||
211 | + | ||
212 | +#### 'field' | ||
213 | + | ||
214 | +Emitted whenever a field / value pair has been received. | ||
215 | + | ||
216 | +```javascript | ||
217 | +form.on('field', function(name, value) { | ||
218 | +}); | ||
219 | +``` | ||
220 | + | ||
221 | +#### 'fileBegin' | ||
222 | + | ||
223 | +Emitted whenever a new file is detected in the upload stream. Use this event if | ||
224 | +you want to stream the file to somewhere else while buffering the upload on | ||
225 | +the file system. | ||
226 | + | ||
227 | +```javascript | ||
228 | +form.on('fileBegin', function(name, file) { | ||
229 | +}); | ||
230 | +``` | ||
231 | + | ||
232 | +#### 'file' | ||
233 | + | ||
234 | +Emitted whenever a field / file pair has been received. `file` is an instance of `File`. | ||
235 | + | ||
236 | +```javascript | ||
237 | +form.on('file', function(name, file) { | ||
238 | +}); | ||
239 | +``` | ||
240 | + | ||
241 | +#### 'error' | ||
242 | + | ||
243 | +Emitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events. | ||
244 | + | ||
245 | +```javascript | ||
246 | +form.on('error', function(err) { | ||
247 | +}); | ||
248 | +``` | ||
249 | + | ||
250 | +#### 'aborted' | ||
251 | + | ||
252 | + | ||
253 | +Emitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. After this event is emitted, an `error` event will follow. In the future there will be a separate 'timeout' event (needs a change in the node core). | ||
254 | +```javascript | ||
255 | +form.on('aborted', function() { | ||
256 | +}); | ||
257 | +``` | ||
258 | + | ||
259 | +##### 'end' | ||
260 | +```javascript | ||
261 | +form.on('end', function() { | ||
262 | +}); | ||
263 | +``` | ||
264 | +Emitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response. | ||
265 | + | ||
266 | + | ||
267 | + | ||
268 | +## Changelog | ||
269 | + | ||
270 | +### v1.1.1 (2017-01-15) | ||
271 | + | ||
272 | + * Fix DeprecationWarning about os.tmpDir() (Christian) | ||
273 | + * Update `buffer.write` order of arguments for Node 7 (Kornel Lesiński) | ||
274 | + * JSON Parser emits error events to the IncomingForm (alessio.montagnani) | ||
275 | + * Improved Content-Disposition parsing (Sebastien) | ||
276 | + * Access WriteStream of fs during runtime instead of include time (Jonas Amundsen) | ||
277 | + * Use built-in toString to convert buffer to hex (Charmander) | ||
278 | + * Add hash to json if present (Nick Stamas) | ||
279 | + * Add license to package.json (Simen Bekkhus) | ||
280 | + | ||
281 | +### v1.0.14 (2013-05-03) | ||
282 | + | ||
283 | +* Add failing hash tests. (Ben Trask) | ||
284 | +* Enable hash calculation again (Eugene Girshov) | ||
285 | +* Test for immediate data events (Tim Smart) | ||
286 | +* Re-arrange IncomingForm#parse (Tim Smart) | ||
287 | + | ||
288 | +### v1.0.13 | ||
289 | + | ||
290 | +* Only update hash if update method exists (Sven Lito) | ||
291 | +* According to travis v0.10 needs to go quoted (Sven Lito) | ||
292 | +* Bumping build node versions (Sven Lito) | ||
293 | +* Additional fix for empty requests (Eugene Girshov) | ||
294 | +* Change the default to 1000, to match the new Node behaviour. (OrangeDog) | ||
295 | +* Add ability to control maxKeys in the querystring parser. (OrangeDog) | ||
296 | +* Adjust test case to work with node 0.9.x (Eugene Girshov) | ||
297 | +* Update package.json (Sven Lito) | ||
298 | +* Path adjustment according to eb4468b (Markus Ast) | ||
299 | + | ||
300 | +### v1.0.12 | ||
301 | + | ||
302 | +* Emit error on aborted connections (Eugene Girshov) | ||
303 | +* Add support for empty requests (Eugene Girshov) | ||
304 | +* Fix name/filename handling in Content-Disposition (jesperp) | ||
305 | +* Tolerate malformed closing boundary in multipart (Eugene Girshov) | ||
306 | +* Ignore preamble in multipart messages (Eugene Girshov) | ||
307 | +* Add support for application/json (Mike Frey, Carlos Rodriguez) | ||
308 | +* Add support for Base64 encoding (Elmer Bulthuis) | ||
309 | +* Add File#toJSON (TJ Holowaychuk) | ||
310 | +* Remove support for Node.js 0.4 & 0.6 (Andrew Kelley) | ||
311 | +* Documentation improvements (Sven Lito, Andre Azevedo) | ||
312 | +* Add support for application/octet-stream (Ion Lupascu, Chris Scribner) | ||
313 | +* Use os.tmpdir() to get tmp directory (Andrew Kelley) | ||
314 | +* Improve package.json (Andrew Kelley, Sven Lito) | ||
315 | +* Fix benchmark script (Andrew Kelley) | ||
316 | +* Fix scope issue in incoming_forms (Sven Lito) | ||
317 | +* Fix file handle leak on error (OrangeDog) | ||
318 | + | ||
319 | +## License | ||
320 | + | ||
321 | +Formidable is licensed under the MIT license. | ||
322 | + | ||
323 | +## Ports | ||
324 | + | ||
325 | +* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable | ||
326 | + | ||
327 | +## Credits | ||
328 | + | ||
329 | +* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js |
node_modules/formidable/index.js
0 → 100644
1 | +module.exports = require('./lib'); |
node_modules/formidable/lib/file.js
0 → 100644
1 | +if (global.GENTLY) require = GENTLY.hijack(require); | ||
2 | + | ||
3 | +var util = require('util'), | ||
4 | + fs = require('fs'), | ||
5 | + EventEmitter = require('events').EventEmitter, | ||
6 | + crypto = require('crypto'); | ||
7 | + | ||
8 | +function File(properties) { | ||
9 | + EventEmitter.call(this); | ||
10 | + | ||
11 | + this.size = 0; | ||
12 | + this.path = null; | ||
13 | + this.name = null; | ||
14 | + this.type = null; | ||
15 | + this.hash = null; | ||
16 | + this.lastModifiedDate = null; | ||
17 | + | ||
18 | + this._writeStream = null; | ||
19 | + | ||
20 | + for (var key in properties) { | ||
21 | + this[key] = properties[key]; | ||
22 | + } | ||
23 | + | ||
24 | + if(typeof this.hash === 'string') { | ||
25 | + this.hash = crypto.createHash(properties.hash); | ||
26 | + } else { | ||
27 | + this.hash = null; | ||
28 | + } | ||
29 | +} | ||
30 | +module.exports = File; | ||
31 | +util.inherits(File, EventEmitter); | ||
32 | + | ||
33 | +File.prototype.open = function() { | ||
34 | + this._writeStream = new fs.WriteStream(this.path); | ||
35 | +}; | ||
36 | + | ||
37 | +File.prototype.toJSON = function() { | ||
38 | + var json = { | ||
39 | + size: this.size, | ||
40 | + path: this.path, | ||
41 | + name: this.name, | ||
42 | + type: this.type, | ||
43 | + mtime: this.lastModifiedDate, | ||
44 | + length: this.length, | ||
45 | + filename: this.filename, | ||
46 | + mime: this.mime | ||
47 | + }; | ||
48 | + if (this.hash && this.hash != "") { | ||
49 | + json.hash = this.hash; | ||
50 | + } | ||
51 | + return json; | ||
52 | +}; | ||
53 | + | ||
54 | +File.prototype.write = function(buffer, cb) { | ||
55 | + var self = this; | ||
56 | + if (self.hash) { | ||
57 | + self.hash.update(buffer); | ||
58 | + } | ||
59 | + this._writeStream.write(buffer, function() { | ||
60 | + self.lastModifiedDate = new Date(); | ||
61 | + self.size += buffer.length; | ||
62 | + self.emit('progress', self.size); | ||
63 | + cb(); | ||
64 | + }); | ||
65 | +}; | ||
66 | + | ||
67 | +File.prototype.end = function(cb) { | ||
68 | + var self = this; | ||
69 | + if (self.hash) { | ||
70 | + self.hash = self.hash.digest('hex'); | ||
71 | + } | ||
72 | + this._writeStream.end(function() { | ||
73 | + self.emit('end'); | ||
74 | + cb(); | ||
75 | + }); | ||
76 | +}; |
node_modules/formidable/lib/incoming_form.js
0 → 100644
1 | +if (global.GENTLY) require = GENTLY.hijack(require); | ||
2 | + | ||
3 | +var crypto = require('crypto'); | ||
4 | +var fs = require('fs'); | ||
5 | +var util = require('util'), | ||
6 | + path = require('path'), | ||
7 | + File = require('./file'), | ||
8 | + MultipartParser = require('./multipart_parser').MultipartParser, | ||
9 | + QuerystringParser = require('./querystring_parser').QuerystringParser, | ||
10 | + OctetParser = require('./octet_parser').OctetParser, | ||
11 | + JSONParser = require('./json_parser').JSONParser, | ||
12 | + StringDecoder = require('string_decoder').StringDecoder, | ||
13 | + EventEmitter = require('events').EventEmitter, | ||
14 | + Stream = require('stream').Stream, | ||
15 | + os = require('os'); | ||
16 | + | ||
17 | +function IncomingForm(opts) { | ||
18 | + if (!(this instanceof IncomingForm)) return new IncomingForm(opts); | ||
19 | + EventEmitter.call(this); | ||
20 | + | ||
21 | + opts=opts||{}; | ||
22 | + | ||
23 | + this.error = null; | ||
24 | + this.ended = false; | ||
25 | + | ||
26 | + this.maxFields = opts.maxFields || 1000; | ||
27 | + this.maxFieldsSize = opts.maxFieldsSize || 2 * 1024 * 1024; | ||
28 | + this.keepExtensions = opts.keepExtensions || false; | ||
29 | + this.uploadDir = opts.uploadDir || (os.tmpdir && os.tmpdir()) || os.tmpDir(); | ||
30 | + this.encoding = opts.encoding || 'utf-8'; | ||
31 | + this.headers = null; | ||
32 | + this.type = null; | ||
33 | + this.hash = opts.hash || false; | ||
34 | + this.multiples = opts.multiples || false; | ||
35 | + | ||
36 | + this.bytesReceived = null; | ||
37 | + this.bytesExpected = null; | ||
38 | + | ||
39 | + this._parser = null; | ||
40 | + this._flushing = 0; | ||
41 | + this._fieldsSize = 0; | ||
42 | + this.openedFiles = []; | ||
43 | + | ||
44 | + return this; | ||
45 | +} | ||
46 | +util.inherits(IncomingForm, EventEmitter); | ||
47 | +exports.IncomingForm = IncomingForm; | ||
48 | + | ||
49 | +IncomingForm.prototype.parse = function(req, cb) { | ||
50 | + this.pause = function() { | ||
51 | + try { | ||
52 | + req.pause(); | ||
53 | + } catch (err) { | ||
54 | + // the stream was destroyed | ||
55 | + if (!this.ended) { | ||
56 | + // before it was completed, crash & burn | ||
57 | + this._error(err); | ||
58 | + } | ||
59 | + return false; | ||
60 | + } | ||
61 | + return true; | ||
62 | + }; | ||
63 | + | ||
64 | + this.resume = function() { | ||
65 | + try { | ||
66 | + req.resume(); | ||
67 | + } catch (err) { | ||
68 | + // the stream was destroyed | ||
69 | + if (!this.ended) { | ||
70 | + // before it was completed, crash & burn | ||
71 | + this._error(err); | ||
72 | + } | ||
73 | + return false; | ||
74 | + } | ||
75 | + | ||
76 | + return true; | ||
77 | + }; | ||
78 | + | ||
79 | + // Setup callback first, so we don't miss anything from data events emitted | ||
80 | + // immediately. | ||
81 | + if (cb) { | ||
82 | + var fields = {}, files = {}; | ||
83 | + this | ||
84 | + .on('field', function(name, value) { | ||
85 | + fields[name] = value; | ||
86 | + }) | ||
87 | + .on('file', function(name, file) { | ||
88 | + if (this.multiples) { | ||
89 | + if (files[name]) { | ||
90 | + if (!Array.isArray(files[name])) { | ||
91 | + files[name] = [files[name]]; | ||
92 | + } | ||
93 | + files[name].push(file); | ||
94 | + } else { | ||
95 | + files[name] = file; | ||
96 | + } | ||
97 | + } else { | ||
98 | + files[name] = file; | ||
99 | + } | ||
100 | + }) | ||
101 | + .on('error', function(err) { | ||
102 | + cb(err, fields, files); | ||
103 | + }) | ||
104 | + .on('end', function() { | ||
105 | + cb(null, fields, files); | ||
106 | + }); | ||
107 | + } | ||
108 | + | ||
109 | + // Parse headers and setup the parser, ready to start listening for data. | ||
110 | + this.writeHeaders(req.headers); | ||
111 | + | ||
112 | + // Start listening for data. | ||
113 | + var self = this; | ||
114 | + req | ||
115 | + .on('error', function(err) { | ||
116 | + self._error(err); | ||
117 | + }) | ||
118 | + .on('aborted', function() { | ||
119 | + self.emit('aborted'); | ||
120 | + self._error(new Error('Request aborted')); | ||
121 | + }) | ||
122 | + .on('data', function(buffer) { | ||
123 | + self.write(buffer); | ||
124 | + }) | ||
125 | + .on('end', function() { | ||
126 | + if (self.error) { | ||
127 | + return; | ||
128 | + } | ||
129 | + | ||
130 | + var err = self._parser.end(); | ||
131 | + if (err) { | ||
132 | + self._error(err); | ||
133 | + } | ||
134 | + }); | ||
135 | + | ||
136 | + return this; | ||
137 | +}; | ||
138 | + | ||
139 | +IncomingForm.prototype.writeHeaders = function(headers) { | ||
140 | + this.headers = headers; | ||
141 | + this._parseContentLength(); | ||
142 | + this._parseContentType(); | ||
143 | +}; | ||
144 | + | ||
145 | +IncomingForm.prototype.write = function(buffer) { | ||
146 | + if (this.error) { | ||
147 | + return; | ||
148 | + } | ||
149 | + if (!this._parser) { | ||
150 | + this._error(new Error('uninitialized parser')); | ||
151 | + return; | ||
152 | + } | ||
153 | + | ||
154 | + this.bytesReceived += buffer.length; | ||
155 | + this.emit('progress', this.bytesReceived, this.bytesExpected); | ||
156 | + | ||
157 | + var bytesParsed = this._parser.write(buffer); | ||
158 | + if (bytesParsed !== buffer.length) { | ||
159 | + this._error(new Error('parser error, '+bytesParsed+' of '+buffer.length+' bytes parsed')); | ||
160 | + } | ||
161 | + | ||
162 | + return bytesParsed; | ||
163 | +}; | ||
164 | + | ||
165 | +IncomingForm.prototype.pause = function() { | ||
166 | + // this does nothing, unless overwritten in IncomingForm.parse | ||
167 | + return false; | ||
168 | +}; | ||
169 | + | ||
170 | +IncomingForm.prototype.resume = function() { | ||
171 | + // this does nothing, unless overwritten in IncomingForm.parse | ||
172 | + return false; | ||
173 | +}; | ||
174 | + | ||
175 | +IncomingForm.prototype.onPart = function(part) { | ||
176 | + // this method can be overwritten by the user | ||
177 | + this.handlePart(part); | ||
178 | +}; | ||
179 | + | ||
180 | +IncomingForm.prototype.handlePart = function(part) { | ||
181 | + var self = this; | ||
182 | + | ||
183 | + if (part.filename === undefined) { | ||
184 | + var value = '' | ||
185 | + , decoder = new StringDecoder(this.encoding); | ||
186 | + | ||
187 | + part.on('data', function(buffer) { | ||
188 | + self._fieldsSize += buffer.length; | ||
189 | + if (self._fieldsSize > self.maxFieldsSize) { | ||
190 | + self._error(new Error('maxFieldsSize exceeded, received '+self._fieldsSize+' bytes of field data')); | ||
191 | + return; | ||
192 | + } | ||
193 | + value += decoder.write(buffer); | ||
194 | + }); | ||
195 | + | ||
196 | + part.on('end', function() { | ||
197 | + self.emit('field', part.name, value); | ||
198 | + }); | ||
199 | + return; | ||
200 | + } | ||
201 | + | ||
202 | + this._flushing++; | ||
203 | + | ||
204 | + var file = new File({ | ||
205 | + path: this._uploadPath(part.filename), | ||
206 | + name: part.filename, | ||
207 | + type: part.mime, | ||
208 | + hash: self.hash | ||
209 | + }); | ||
210 | + | ||
211 | + this.emit('fileBegin', part.name, file); | ||
212 | + | ||
213 | + file.open(); | ||
214 | + this.openedFiles.push(file); | ||
215 | + | ||
216 | + part.on('data', function(buffer) { | ||
217 | + if (buffer.length == 0) { | ||
218 | + return; | ||
219 | + } | ||
220 | + self.pause(); | ||
221 | + file.write(buffer, function() { | ||
222 | + self.resume(); | ||
223 | + }); | ||
224 | + }); | ||
225 | + | ||
226 | + part.on('end', function() { | ||
227 | + file.end(function() { | ||
228 | + self._flushing--; | ||
229 | + self.emit('file', part.name, file); | ||
230 | + self._maybeEnd(); | ||
231 | + }); | ||
232 | + }); | ||
233 | +}; | ||
234 | + | ||
235 | +function dummyParser(self) { | ||
236 | + return { | ||
237 | + end: function () { | ||
238 | + self.ended = true; | ||
239 | + self._maybeEnd(); | ||
240 | + return null; | ||
241 | + } | ||
242 | + }; | ||
243 | +} | ||
244 | + | ||
245 | +IncomingForm.prototype._parseContentType = function() { | ||
246 | + if (this.bytesExpected === 0) { | ||
247 | + this._parser = dummyParser(this); | ||
248 | + return; | ||
249 | + } | ||
250 | + | ||
251 | + if (!this.headers['content-type']) { | ||
252 | + this._error(new Error('bad content-type header, no content-type')); | ||
253 | + return; | ||
254 | + } | ||
255 | + | ||
256 | + if (this.headers['content-type'].match(/octet-stream/i)) { | ||
257 | + this._initOctetStream(); | ||
258 | + return; | ||
259 | + } | ||
260 | + | ||
261 | + if (this.headers['content-type'].match(/urlencoded/i)) { | ||
262 | + this._initUrlencoded(); | ||
263 | + return; | ||
264 | + } | ||
265 | + | ||
266 | + if (this.headers['content-type'].match(/multipart/i)) { | ||
267 | + var m = this.headers['content-type'].match(/boundary=(?:"([^"]+)"|([^;]+))/i); | ||
268 | + if (m) { | ||
269 | + this._initMultipart(m[1] || m[2]); | ||
270 | + } else { | ||
271 | + this._error(new Error('bad content-type header, no multipart boundary')); | ||
272 | + } | ||
273 | + return; | ||
274 | + } | ||
275 | + | ||
276 | + if (this.headers['content-type'].match(/json/i)) { | ||
277 | + this._initJSONencoded(); | ||
278 | + return; | ||
279 | + } | ||
280 | + | ||
281 | + this._error(new Error('bad content-type header, unknown content-type: '+this.headers['content-type'])); | ||
282 | +}; | ||
283 | + | ||
284 | +IncomingForm.prototype._error = function(err) { | ||
285 | + if (this.error || this.ended) { | ||
286 | + return; | ||
287 | + } | ||
288 | + | ||
289 | + this.error = err; | ||
290 | + this.emit('error', err); | ||
291 | + | ||
292 | + if (Array.isArray(this.openedFiles)) { | ||
293 | + this.openedFiles.forEach(function(file) { | ||
294 | + file._writeStream.destroy(); | ||
295 | + setTimeout(fs.unlink, 0, file.path, function(error) { }); | ||
296 | + }); | ||
297 | + } | ||
298 | +}; | ||
299 | + | ||
300 | +IncomingForm.prototype._parseContentLength = function() { | ||
301 | + this.bytesReceived = 0; | ||
302 | + if (this.headers['content-length']) { | ||
303 | + this.bytesExpected = parseInt(this.headers['content-length'], 10); | ||
304 | + } else if (this.headers['transfer-encoding'] === undefined) { | ||
305 | + this.bytesExpected = 0; | ||
306 | + } | ||
307 | + | ||
308 | + if (this.bytesExpected !== null) { | ||
309 | + this.emit('progress', this.bytesReceived, this.bytesExpected); | ||
310 | + } | ||
311 | +}; | ||
312 | + | ||
313 | +IncomingForm.prototype._newParser = function() { | ||
314 | + return new MultipartParser(); | ||
315 | +}; | ||
316 | + | ||
317 | +IncomingForm.prototype._initMultipart = function(boundary) { | ||
318 | + this.type = 'multipart'; | ||
319 | + | ||
320 | + var parser = new MultipartParser(), | ||
321 | + self = this, | ||
322 | + headerField, | ||
323 | + headerValue, | ||
324 | + part; | ||
325 | + | ||
326 | + parser.initWithBoundary(boundary); | ||
327 | + | ||
328 | + parser.onPartBegin = function() { | ||
329 | + part = new Stream(); | ||
330 | + part.readable = true; | ||
331 | + part.headers = {}; | ||
332 | + part.name = null; | ||
333 | + part.filename = null; | ||
334 | + part.mime = null; | ||
335 | + | ||
336 | + part.transferEncoding = 'binary'; | ||
337 | + part.transferBuffer = ''; | ||
338 | + | ||
339 | + headerField = ''; | ||
340 | + headerValue = ''; | ||
341 | + }; | ||
342 | + | ||
343 | + parser.onHeaderField = function(b, start, end) { | ||
344 | + headerField += b.toString(self.encoding, start, end); | ||
345 | + }; | ||
346 | + | ||
347 | + parser.onHeaderValue = function(b, start, end) { | ||
348 | + headerValue += b.toString(self.encoding, start, end); | ||
349 | + }; | ||
350 | + | ||
351 | + parser.onHeaderEnd = function() { | ||
352 | + headerField = headerField.toLowerCase(); | ||
353 | + part.headers[headerField] = headerValue; | ||
354 | + | ||
355 | + // matches either a quoted-string or a token (RFC 2616 section 19.5.1) | ||
356 | + var m = headerValue.match(/\bname=("([^"]*)"|([^\(\)<>@,;:\\"\/\[\]\?=\{\}\s\t/]+))/i); | ||
357 | + if (headerField == 'content-disposition') { | ||
358 | + if (m) { | ||
359 | + part.name = m[2] || m[3] || ''; | ||
360 | + } | ||
361 | + | ||
362 | + part.filename = self._fileName(headerValue); | ||
363 | + } else if (headerField == 'content-type') { | ||
364 | + part.mime = headerValue; | ||
365 | + } else if (headerField == 'content-transfer-encoding') { | ||
366 | + part.transferEncoding = headerValue.toLowerCase(); | ||
367 | + } | ||
368 | + | ||
369 | + headerField = ''; | ||
370 | + headerValue = ''; | ||
371 | + }; | ||
372 | + | ||
373 | + parser.onHeadersEnd = function() { | ||
374 | + switch(part.transferEncoding){ | ||
375 | + case 'binary': | ||
376 | + case '7bit': | ||
377 | + case '8bit': | ||
378 | + parser.onPartData = function(b, start, end) { | ||
379 | + part.emit('data', b.slice(start, end)); | ||
380 | + }; | ||
381 | + | ||
382 | + parser.onPartEnd = function() { | ||
383 | + part.emit('end'); | ||
384 | + }; | ||
385 | + break; | ||
386 | + | ||
387 | + case 'base64': | ||
388 | + parser.onPartData = function(b, start, end) { | ||
389 | + part.transferBuffer += b.slice(start, end).toString('ascii'); | ||
390 | + | ||
391 | + /* | ||
392 | + four bytes (chars) in base64 converts to three bytes in binary | ||
393 | + encoding. So we should always work with a number of bytes that | ||
394 | + can be divided by 4, it will result in a number of buytes that | ||
395 | + can be divided vy 3. | ||
396 | + */ | ||
397 | + var offset = parseInt(part.transferBuffer.length / 4, 10) * 4; | ||
398 | + part.emit('data', new Buffer(part.transferBuffer.substring(0, offset), 'base64')); | ||
399 | + part.transferBuffer = part.transferBuffer.substring(offset); | ||
400 | + }; | ||
401 | + | ||
402 | + parser.onPartEnd = function() { | ||
403 | + part.emit('data', new Buffer(part.transferBuffer, 'base64')); | ||
404 | + part.emit('end'); | ||
405 | + }; | ||
406 | + break; | ||
407 | + | ||
408 | + default: | ||
409 | + return self._error(new Error('unknown transfer-encoding')); | ||
410 | + } | ||
411 | + | ||
412 | + self.onPart(part); | ||
413 | + }; | ||
414 | + | ||
415 | + | ||
416 | + parser.onEnd = function() { | ||
417 | + self.ended = true; | ||
418 | + self._maybeEnd(); | ||
419 | + }; | ||
420 | + | ||
421 | + this._parser = parser; | ||
422 | +}; | ||
423 | + | ||
424 | +IncomingForm.prototype._fileName = function(headerValue) { | ||
425 | + // matches either a quoted-string or a token (RFC 2616 section 19.5.1) | ||
426 | + var m = headerValue.match(/\bfilename=("(.*?)"|([^\(\)<>@,;:\\"\/\[\]\?=\{\}\s\t/]+))($|;\s)/i); | ||
427 | + if (!m) return; | ||
428 | + | ||
429 | + var match = m[2] || m[3] || ''; | ||
430 | + var filename = match.substr(match.lastIndexOf('\\') + 1); | ||
431 | + filename = filename.replace(/%22/g, '"'); | ||
432 | + filename = filename.replace(/&#([\d]{4});/g, function(m, code) { | ||
433 | + return String.fromCharCode(code); | ||
434 | + }); | ||
435 | + return filename; | ||
436 | +}; | ||
437 | + | ||
438 | +IncomingForm.prototype._initUrlencoded = function() { | ||
439 | + this.type = 'urlencoded'; | ||
440 | + | ||
441 | + var parser = new QuerystringParser(this.maxFields) | ||
442 | + , self = this; | ||
443 | + | ||
444 | + parser.onField = function(key, val) { | ||
445 | + self.emit('field', key, val); | ||
446 | + }; | ||
447 | + | ||
448 | + parser.onEnd = function() { | ||
449 | + self.ended = true; | ||
450 | + self._maybeEnd(); | ||
451 | + }; | ||
452 | + | ||
453 | + this._parser = parser; | ||
454 | +}; | ||
455 | + | ||
456 | +IncomingForm.prototype._initOctetStream = function() { | ||
457 | + this.type = 'octet-stream'; | ||
458 | + var filename = this.headers['x-file-name']; | ||
459 | + var mime = this.headers['content-type']; | ||
460 | + | ||
461 | + var file = new File({ | ||
462 | + path: this._uploadPath(filename), | ||
463 | + name: filename, | ||
464 | + type: mime | ||
465 | + }); | ||
466 | + | ||
467 | + this.emit('fileBegin', filename, file); | ||
468 | + file.open(); | ||
469 | + | ||
470 | + this._flushing++; | ||
471 | + | ||
472 | + var self = this; | ||
473 | + | ||
474 | + self._parser = new OctetParser(); | ||
475 | + | ||
476 | + //Keep track of writes that haven't finished so we don't emit the file before it's done being written | ||
477 | + var outstandingWrites = 0; | ||
478 | + | ||
479 | + self._parser.on('data', function(buffer){ | ||
480 | + self.pause(); | ||
481 | + outstandingWrites++; | ||
482 | + | ||
483 | + file.write(buffer, function() { | ||
484 | + outstandingWrites--; | ||
485 | + self.resume(); | ||
486 | + | ||
487 | + if(self.ended){ | ||
488 | + self._parser.emit('doneWritingFile'); | ||
489 | + } | ||
490 | + }); | ||
491 | + }); | ||
492 | + | ||
493 | + self._parser.on('end', function(){ | ||
494 | + self._flushing--; | ||
495 | + self.ended = true; | ||
496 | + | ||
497 | + var done = function(){ | ||
498 | + file.end(function() { | ||
499 | + self.emit('file', 'file', file); | ||
500 | + self._maybeEnd(); | ||
501 | + }); | ||
502 | + }; | ||
503 | + | ||
504 | + if(outstandingWrites === 0){ | ||
505 | + done(); | ||
506 | + } else { | ||
507 | + self._parser.once('doneWritingFile', done); | ||
508 | + } | ||
509 | + }); | ||
510 | +}; | ||
511 | + | ||
512 | +IncomingForm.prototype._initJSONencoded = function() { | ||
513 | + this.type = 'json'; | ||
514 | + | ||
515 | + var parser = new JSONParser(this) | ||
516 | + , self = this; | ||
517 | + | ||
518 | + if (this.bytesExpected) { | ||
519 | + parser.initWithLength(this.bytesExpected); | ||
520 | + } | ||
521 | + | ||
522 | + parser.onField = function(key, val) { | ||
523 | + self.emit('field', key, val); | ||
524 | + }; | ||
525 | + | ||
526 | + parser.onEnd = function() { | ||
527 | + self.ended = true; | ||
528 | + self._maybeEnd(); | ||
529 | + }; | ||
530 | + | ||
531 | + this._parser = parser; | ||
532 | +}; | ||
533 | + | ||
534 | +IncomingForm.prototype._uploadPath = function(filename) { | ||
535 | + var buf = crypto.randomBytes(16); | ||
536 | + var name = 'upload_' + buf.toString('hex'); | ||
537 | + | ||
538 | + if (this.keepExtensions) { | ||
539 | + var ext = path.extname(filename); | ||
540 | + ext = ext.replace(/(\.[a-z0-9]+).*/i, '$1'); | ||
541 | + | ||
542 | + name += ext; | ||
543 | + } | ||
544 | + | ||
545 | + return path.join(this.uploadDir, name); | ||
546 | +}; | ||
547 | + | ||
548 | +IncomingForm.prototype._maybeEnd = function() { | ||
549 | + if (!this.ended || this._flushing || this.error) { | ||
550 | + return; | ||
551 | + } | ||
552 | + | ||
553 | + this.emit('end'); | ||
554 | +}; | ||
555 | + |
node_modules/formidable/lib/index.js
0 → 100644
node_modules/formidable/lib/json_parser.js
0 → 100644
1 | +if (global.GENTLY) require = GENTLY.hijack(require); | ||
2 | + | ||
3 | +var Buffer = require('buffer').Buffer; | ||
4 | + | ||
5 | +function JSONParser(parent) { | ||
6 | + this.parent = parent; | ||
7 | + this.data = new Buffer(''); | ||
8 | + this.bytesWritten = 0; | ||
9 | +} | ||
10 | +exports.JSONParser = JSONParser; | ||
11 | + | ||
12 | +JSONParser.prototype.initWithLength = function(length) { | ||
13 | + this.data = new Buffer(length); | ||
14 | +}; | ||
15 | + | ||
16 | +JSONParser.prototype.write = function(buffer) { | ||
17 | + if (this.data.length >= this.bytesWritten + buffer.length) { | ||
18 | + buffer.copy(this.data, this.bytesWritten); | ||
19 | + } else { | ||
20 | + this.data = Buffer.concat([this.data, buffer]); | ||
21 | + } | ||
22 | + this.bytesWritten += buffer.length; | ||
23 | + return buffer.length; | ||
24 | +}; | ||
25 | + | ||
26 | +JSONParser.prototype.end = function() { | ||
27 | + try { | ||
28 | + var fields = JSON.parse(this.data.toString('utf8')); | ||
29 | + for (var field in fields) { | ||
30 | + this.onField(field, fields[field]); | ||
31 | + } | ||
32 | + } catch (e) { | ||
33 | + this.parent.emit('error', e); | ||
34 | + } | ||
35 | + this.data = null; | ||
36 | + | ||
37 | + this.onEnd(); | ||
38 | +}; |
1 | +var Buffer = require('buffer').Buffer, | ||
2 | + s = 0, | ||
3 | + S = | ||
4 | + { PARSER_UNINITIALIZED: s++, | ||
5 | + START: s++, | ||
6 | + START_BOUNDARY: s++, | ||
7 | + HEADER_FIELD_START: s++, | ||
8 | + HEADER_FIELD: s++, | ||
9 | + HEADER_VALUE_START: s++, | ||
10 | + HEADER_VALUE: s++, | ||
11 | + HEADER_VALUE_ALMOST_DONE: s++, | ||
12 | + HEADERS_ALMOST_DONE: s++, | ||
13 | + PART_DATA_START: s++, | ||
14 | + PART_DATA: s++, | ||
15 | + PART_END: s++, | ||
16 | + END: s++ | ||
17 | + }, | ||
18 | + | ||
19 | + f = 1, | ||
20 | + F = | ||
21 | + { PART_BOUNDARY: f, | ||
22 | + LAST_BOUNDARY: f *= 2 | ||
23 | + }, | ||
24 | + | ||
25 | + LF = 10, | ||
26 | + CR = 13, | ||
27 | + SPACE = 32, | ||
28 | + HYPHEN = 45, | ||
29 | + COLON = 58, | ||
30 | + A = 97, | ||
31 | + Z = 122, | ||
32 | + | ||
33 | + lower = function(c) { | ||
34 | + return c | 0x20; | ||
35 | + }; | ||
36 | + | ||
37 | +for (s in S) { | ||
38 | + exports[s] = S[s]; | ||
39 | +} | ||
40 | + | ||
41 | +function MultipartParser() { | ||
42 | + this.boundary = null; | ||
43 | + this.boundaryChars = null; | ||
44 | + this.lookbehind = null; | ||
45 | + this.state = S.PARSER_UNINITIALIZED; | ||
46 | + | ||
47 | + this.index = null; | ||
48 | + this.flags = 0; | ||
49 | +} | ||
50 | +exports.MultipartParser = MultipartParser; | ||
51 | + | ||
52 | +MultipartParser.stateToString = function(stateNumber) { | ||
53 | + for (var state in S) { | ||
54 | + var number = S[state]; | ||
55 | + if (number === stateNumber) return state; | ||
56 | + } | ||
57 | +}; | ||
58 | + | ||
59 | +MultipartParser.prototype.initWithBoundary = function(str) { | ||
60 | + this.boundary = new Buffer(str.length+4); | ||
61 | + this.boundary.write('\r\n--', 0); | ||
62 | + this.boundary.write(str, 4); | ||
63 | + this.lookbehind = new Buffer(this.boundary.length+8); | ||
64 | + this.state = S.START; | ||
65 | + | ||
66 | + this.boundaryChars = {}; | ||
67 | + for (var i = 0; i < this.boundary.length; i++) { | ||
68 | + this.boundaryChars[this.boundary[i]] = true; | ||
69 | + } | ||
70 | +}; | ||
71 | + | ||
72 | +MultipartParser.prototype.write = function(buffer) { | ||
73 | + var self = this, | ||
74 | + i = 0, | ||
75 | + len = buffer.length, | ||
76 | + prevIndex = this.index, | ||
77 | + index = this.index, | ||
78 | + state = this.state, | ||
79 | + flags = this.flags, | ||
80 | + lookbehind = this.lookbehind, | ||
81 | + boundary = this.boundary, | ||
82 | + boundaryChars = this.boundaryChars, | ||
83 | + boundaryLength = this.boundary.length, | ||
84 | + boundaryEnd = boundaryLength - 1, | ||
85 | + bufferLength = buffer.length, | ||
86 | + c, | ||
87 | + cl, | ||
88 | + | ||
89 | + mark = function(name) { | ||
90 | + self[name+'Mark'] = i; | ||
91 | + }, | ||
92 | + clear = function(name) { | ||
93 | + delete self[name+'Mark']; | ||
94 | + }, | ||
95 | + callback = function(name, buffer, start, end) { | ||
96 | + if (start !== undefined && start === end) { | ||
97 | + return; | ||
98 | + } | ||
99 | + | ||
100 | + var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1); | ||
101 | + if (callbackSymbol in self) { | ||
102 | + self[callbackSymbol](buffer, start, end); | ||
103 | + } | ||
104 | + }, | ||
105 | + dataCallback = function(name, clear) { | ||
106 | + var markSymbol = name+'Mark'; | ||
107 | + if (!(markSymbol in self)) { | ||
108 | + return; | ||
109 | + } | ||
110 | + | ||
111 | + if (!clear) { | ||
112 | + callback(name, buffer, self[markSymbol], buffer.length); | ||
113 | + self[markSymbol] = 0; | ||
114 | + } else { | ||
115 | + callback(name, buffer, self[markSymbol], i); | ||
116 | + delete self[markSymbol]; | ||
117 | + } | ||
118 | + }; | ||
119 | + | ||
120 | + for (i = 0; i < len; i++) { | ||
121 | + c = buffer[i]; | ||
122 | + switch (state) { | ||
123 | + case S.PARSER_UNINITIALIZED: | ||
124 | + return i; | ||
125 | + case S.START: | ||
126 | + index = 0; | ||
127 | + state = S.START_BOUNDARY; | ||
128 | + case S.START_BOUNDARY: | ||
129 | + if (index == boundary.length - 2) { | ||
130 | + if (c == HYPHEN) { | ||
131 | + flags |= F.LAST_BOUNDARY; | ||
132 | + } else if (c != CR) { | ||
133 | + return i; | ||
134 | + } | ||
135 | + index++; | ||
136 | + break; | ||
137 | + } else if (index - 1 == boundary.length - 2) { | ||
138 | + if (flags & F.LAST_BOUNDARY && c == HYPHEN){ | ||
139 | + callback('end'); | ||
140 | + state = S.END; | ||
141 | + flags = 0; | ||
142 | + } else if (!(flags & F.LAST_BOUNDARY) && c == LF) { | ||
143 | + index = 0; | ||
144 | + callback('partBegin'); | ||
145 | + state = S.HEADER_FIELD_START; | ||
146 | + } else { | ||
147 | + return i; | ||
148 | + } | ||
149 | + break; | ||
150 | + } | ||
151 | + | ||
152 | + if (c != boundary[index+2]) { | ||
153 | + index = -2; | ||
154 | + } | ||
155 | + if (c == boundary[index+2]) { | ||
156 | + index++; | ||
157 | + } | ||
158 | + break; | ||
159 | + case S.HEADER_FIELD_START: | ||
160 | + state = S.HEADER_FIELD; | ||
161 | + mark('headerField'); | ||
162 | + index = 0; | ||
163 | + case S.HEADER_FIELD: | ||
164 | + if (c == CR) { | ||
165 | + clear('headerField'); | ||
166 | + state = S.HEADERS_ALMOST_DONE; | ||
167 | + break; | ||
168 | + } | ||
169 | + | ||
170 | + index++; | ||
171 | + if (c == HYPHEN) { | ||
172 | + break; | ||
173 | + } | ||
174 | + | ||
175 | + if (c == COLON) { | ||
176 | + if (index == 1) { | ||
177 | + // empty header field | ||
178 | + return i; | ||
179 | + } | ||
180 | + dataCallback('headerField', true); | ||
181 | + state = S.HEADER_VALUE_START; | ||
182 | + break; | ||
183 | + } | ||
184 | + | ||
185 | + cl = lower(c); | ||
186 | + if (cl < A || cl > Z) { | ||
187 | + return i; | ||
188 | + } | ||
189 | + break; | ||
190 | + case S.HEADER_VALUE_START: | ||
191 | + if (c == SPACE) { | ||
192 | + break; | ||
193 | + } | ||
194 | + | ||
195 | + mark('headerValue'); | ||
196 | + state = S.HEADER_VALUE; | ||
197 | + case S.HEADER_VALUE: | ||
198 | + if (c == CR) { | ||
199 | + dataCallback('headerValue', true); | ||
200 | + callback('headerEnd'); | ||
201 | + state = S.HEADER_VALUE_ALMOST_DONE; | ||
202 | + } | ||
203 | + break; | ||
204 | + case S.HEADER_VALUE_ALMOST_DONE: | ||
205 | + if (c != LF) { | ||
206 | + return i; | ||
207 | + } | ||
208 | + state = S.HEADER_FIELD_START; | ||
209 | + break; | ||
210 | + case S.HEADERS_ALMOST_DONE: | ||
211 | + if (c != LF) { | ||
212 | + return i; | ||
213 | + } | ||
214 | + | ||
215 | + callback('headersEnd'); | ||
216 | + state = S.PART_DATA_START; | ||
217 | + break; | ||
218 | + case S.PART_DATA_START: | ||
219 | + state = S.PART_DATA; | ||
220 | + mark('partData'); | ||
221 | + case S.PART_DATA: | ||
222 | + prevIndex = index; | ||
223 | + | ||
224 | + if (index === 0) { | ||
225 | + // boyer-moore derrived algorithm to safely skip non-boundary data | ||
226 | + i += boundaryEnd; | ||
227 | + while (i < bufferLength && !(buffer[i] in boundaryChars)) { | ||
228 | + i += boundaryLength; | ||
229 | + } | ||
230 | + i -= boundaryEnd; | ||
231 | + c = buffer[i]; | ||
232 | + } | ||
233 | + | ||
234 | + if (index < boundary.length) { | ||
235 | + if (boundary[index] == c) { | ||
236 | + if (index === 0) { | ||
237 | + dataCallback('partData', true); | ||
238 | + } | ||
239 | + index++; | ||
240 | + } else { | ||
241 | + index = 0; | ||
242 | + } | ||
243 | + } else if (index == boundary.length) { | ||
244 | + index++; | ||
245 | + if (c == CR) { | ||
246 | + // CR = part boundary | ||
247 | + flags |= F.PART_BOUNDARY; | ||
248 | + } else if (c == HYPHEN) { | ||
249 | + // HYPHEN = end boundary | ||
250 | + flags |= F.LAST_BOUNDARY; | ||
251 | + } else { | ||
252 | + index = 0; | ||
253 | + } | ||
254 | + } else if (index - 1 == boundary.length) { | ||
255 | + if (flags & F.PART_BOUNDARY) { | ||
256 | + index = 0; | ||
257 | + if (c == LF) { | ||
258 | + // unset the PART_BOUNDARY flag | ||
259 | + flags &= ~F.PART_BOUNDARY; | ||
260 | + callback('partEnd'); | ||
261 | + callback('partBegin'); | ||
262 | + state = S.HEADER_FIELD_START; | ||
263 | + break; | ||
264 | + } | ||
265 | + } else if (flags & F.LAST_BOUNDARY) { | ||
266 | + if (c == HYPHEN) { | ||
267 | + callback('partEnd'); | ||
268 | + callback('end'); | ||
269 | + state = S.END; | ||
270 | + flags = 0; | ||
271 | + } else { | ||
272 | + index = 0; | ||
273 | + } | ||
274 | + } else { | ||
275 | + index = 0; | ||
276 | + } | ||
277 | + } | ||
278 | + | ||
279 | + if (index > 0) { | ||
280 | + // when matching a possible boundary, keep a lookbehind reference | ||
281 | + // in case it turns out to be a false lead | ||
282 | + lookbehind[index-1] = c; | ||
283 | + } else if (prevIndex > 0) { | ||
284 | + // if our boundary turned out to be rubbish, the captured lookbehind | ||
285 | + // belongs to partData | ||
286 | + callback('partData', lookbehind, 0, prevIndex); | ||
287 | + prevIndex = 0; | ||
288 | + mark('partData'); | ||
289 | + | ||
290 | + // reconsider the current character even so it interrupted the sequence | ||
291 | + // it could be the beginning of a new sequence | ||
292 | + i--; | ||
293 | + } | ||
294 | + | ||
295 | + break; | ||
296 | + case S.END: | ||
297 | + break; | ||
298 | + default: | ||
299 | + return i; | ||
300 | + } | ||
301 | + } | ||
302 | + | ||
303 | + dataCallback('headerField'); | ||
304 | + dataCallback('headerValue'); | ||
305 | + dataCallback('partData'); | ||
306 | + | ||
307 | + this.index = index; | ||
308 | + this.state = state; | ||
309 | + this.flags = flags; | ||
310 | + | ||
311 | + return len; | ||
312 | +}; | ||
313 | + | ||
314 | +MultipartParser.prototype.end = function() { | ||
315 | + var callback = function(self, name) { | ||
316 | + var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1); | ||
317 | + if (callbackSymbol in self) { | ||
318 | + self[callbackSymbol](); | ||
319 | + } | ||
320 | + }; | ||
321 | + if ((this.state == S.HEADER_FIELD_START && this.index === 0) || | ||
322 | + (this.state == S.PART_DATA && this.index == this.boundary.length)) { | ||
323 | + callback(this, 'partEnd'); | ||
324 | + callback(this, 'end'); | ||
325 | + } else if (this.state != S.END) { | ||
326 | + return new Error('MultipartParser.end(): stream ended unexpectedly: ' + this.explain()); | ||
327 | + } | ||
328 | +}; | ||
329 | + | ||
330 | +MultipartParser.prototype.explain = function() { | ||
331 | + return 'state = ' + MultipartParser.stateToString(this.state); | ||
332 | +}; |
node_modules/formidable/lib/octet_parser.js
0 → 100644
1 | +var EventEmitter = require('events').EventEmitter | ||
2 | + , util = require('util'); | ||
3 | + | ||
4 | +function OctetParser(options){ | ||
5 | + if(!(this instanceof OctetParser)) return new OctetParser(options); | ||
6 | + EventEmitter.call(this); | ||
7 | +} | ||
8 | + | ||
9 | +util.inherits(OctetParser, EventEmitter); | ||
10 | + | ||
11 | +exports.OctetParser = OctetParser; | ||
12 | + | ||
13 | +OctetParser.prototype.write = function(buffer) { | ||
14 | + this.emit('data', buffer); | ||
15 | + return buffer.length; | ||
16 | +}; | ||
17 | + | ||
18 | +OctetParser.prototype.end = function() { | ||
19 | + this.emit('end'); | ||
20 | +}; |
1 | +if (global.GENTLY) require = GENTLY.hijack(require); | ||
2 | + | ||
3 | +// This is a buffering parser, not quite as nice as the multipart one. | ||
4 | +// If I find time I'll rewrite this to be fully streaming as well | ||
5 | +var querystring = require('querystring'); | ||
6 | + | ||
7 | +function QuerystringParser(maxKeys) { | ||
8 | + this.maxKeys = maxKeys; | ||
9 | + this.buffer = ''; | ||
10 | +} | ||
11 | +exports.QuerystringParser = QuerystringParser; | ||
12 | + | ||
13 | +QuerystringParser.prototype.write = function(buffer) { | ||
14 | + this.buffer += buffer.toString('ascii'); | ||
15 | + return buffer.length; | ||
16 | +}; | ||
17 | + | ||
18 | +QuerystringParser.prototype.end = function() { | ||
19 | + var fields = querystring.parse(this.buffer, '&', '=', { maxKeys: this.maxKeys }); | ||
20 | + for (var field in fields) { | ||
21 | + this.onField(field, fields[field]); | ||
22 | + } | ||
23 | + this.buffer = ''; | ||
24 | + | ||
25 | + this.onEnd(); | ||
26 | +}; | ||
27 | + |
node_modules/formidable/package.json
0 → 100644
1 | +{ | ||
2 | + "_args": [ | ||
3 | + [ | ||
4 | + { | ||
5 | + "raw": "formidable@1.1.1", | ||
6 | + "scope": null, | ||
7 | + "escapedName": "formidable", | ||
8 | + "name": "formidable", | ||
9 | + "rawSpec": "1.1.1", | ||
10 | + "spec": "1.1.1", | ||
11 | + "type": "version" | ||
12 | + }, | ||
13 | + "/Users/fzy/project/koa2_Sequelize_project/node_modules/koa-body" | ||
14 | + ] | ||
15 | + ], | ||
16 | + "_from": "formidable@1.1.1", | ||
17 | + "_id": "formidable@1.1.1", | ||
18 | + "_inCache": true, | ||
19 | + "_location": "/formidable", | ||
20 | + "_nodeVersion": "7.2.1", | ||
21 | + "_npmOperationalInternal": { | ||
22 | + "host": "packages-12-west.internal.npmjs.com", | ||
23 | + "tmp": "tmp/formidable-1.1.1.tgz_1484514649272_0.35996662196703255" | ||
24 | + }, | ||
25 | + "_npmUser": { | ||
26 | + "name": "kornel", | ||
27 | + "email": "pornel@pornel.net" | ||
28 | + }, | ||
29 | + "_npmVersion": "4.0.5", | ||
30 | + "_phantomChildren": {}, | ||
31 | + "_requested": { | ||
32 | + "raw": "formidable@1.1.1", | ||
33 | + "scope": null, | ||
34 | + "escapedName": "formidable", | ||
35 | + "name": "formidable", | ||
36 | + "rawSpec": "1.1.1", | ||
37 | + "spec": "1.1.1", | ||
38 | + "type": "version" | ||
39 | + }, | ||
40 | + "_requiredBy": [ | ||
41 | + "/koa-body" | ||
42 | + ], | ||
43 | + "_resolved": "https://registry.npmjs.org/formidable/-/formidable-1.1.1.tgz", | ||
44 | + "_shasum": "96b8886f7c3c3508b932d6bd70c4d3a88f35f1a9", | ||
45 | + "_shrinkwrap": null, | ||
46 | + "_spec": "formidable@1.1.1", | ||
47 | + "_where": "/Users/fzy/project/koa2_Sequelize_project/node_modules/koa-body", | ||
48 | + "bugs": { | ||
49 | + "url": "http://github.com/felixge/node-formidable/issues" | ||
50 | + }, | ||
51 | + "dependencies": {}, | ||
52 | + "description": "A node.js module for parsing form data, especially file uploads.", | ||
53 | + "devDependencies": { | ||
54 | + "findit": "^0.1.2", | ||
55 | + "gently": "^0.8.0", | ||
56 | + "hashish": "^0.0.4", | ||
57 | + "request": "^2.11.4", | ||
58 | + "urun": "^0.0.6", | ||
59 | + "utest": "^0.0.8" | ||
60 | + }, | ||
61 | + "directories": { | ||
62 | + "lib": "./lib" | ||
63 | + }, | ||
64 | + "dist": { | ||
65 | + "shasum": "96b8886f7c3c3508b932d6bd70c4d3a88f35f1a9", | ||
66 | + "tarball": "https://registry.npmjs.org/formidable/-/formidable-1.1.1.tgz" | ||
67 | + }, | ||
68 | + "engines": { | ||
69 | + "node": ">=0.8.0" | ||
70 | + }, | ||
71 | + "gitHead": "7a36a8e932044252fe648c81dbd8cf837d0178d0", | ||
72 | + "homepage": "https://github.com/felixge/node-formidable", | ||
73 | + "license": "MIT", | ||
74 | + "main": "./lib/index", | ||
75 | + "maintainers": [ | ||
76 | + { | ||
77 | + "name": "felixge", | ||
78 | + "email": "felix@debuggable.com" | ||
79 | + }, | ||
80 | + { | ||
81 | + "name": "kornel", | ||
82 | + "email": "pornel@pornel.net" | ||
83 | + }, | ||
84 | + { | ||
85 | + "name": "superjoe", | ||
86 | + "email": "superjoe30@gmail.com" | ||
87 | + }, | ||
88 | + { | ||
89 | + "name": "svnlto", | ||
90 | + "email": "me@svenlito.com" | ||
91 | + }, | ||
92 | + { | ||
93 | + "name": "tim-smart", | ||
94 | + "email": "tim@fostle.com" | ||
95 | + }, | ||
96 | + { | ||
97 | + "name": "tunnckocore", | ||
98 | + "email": "mameto_100@mail.bg" | ||
99 | + } | ||
100 | + ], | ||
101 | + "name": "formidable", | ||
102 | + "optionalDependencies": {}, | ||
103 | + "readme": "# Formidable\n\n[](https://travis-ci.org/felixge/node-formidable)\n\n## Purpose\n\nA Node.js module for parsing form data, especially file uploads.\n\n## Current status\n\n**Maintainers Wanted:** Please see https://github.com/felixge/node-formidable/issues/412\n\nThis module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading\nand encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from\na large variety of clients and is considered production-ready.\n\n## Features\n\n* Fast (~500mb/sec), non-buffering multipart parser\n* Automatically writing file uploads to disk\n* Low memory footprint\n* Graceful error handling\n* Very high test coverage\n\n## Installation\n\n```sh\nnpm i -S formidable\n```\n\nThis is a low level package, and if you're using a high level framework such as Express, chances are it's already included in it. You can [read this discussion](http://stackoverflow.com/questions/11295554/how-to-disable-express-bodyparser-for-file-uploads-node-js) about how Formidable is integrated with Express.\n\nNote: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library.\n\n## Example\n\nParse an incoming file upload.\n```javascript\nvar formidable = require('formidable'),\n http = require('http'),\n util = require('util');\n\nhttp.createServer(function(req, res) {\n if (req.url == '/upload' && req.method.toLowerCase() == 'post') {\n // parse a file upload\n var form = new formidable.IncomingForm();\n\n form.parse(req, function(err, fields, files) {\n res.writeHead(200, {'content-type': 'text/plain'});\n res.write('received upload:\\n\\n');\n res.end(util.inspect({fields: fields, files: files}));\n });\n\n return;\n }\n\n // show a file upload form\n res.writeHead(200, {'content-type': 'text/html'});\n res.end(\n '<form action=\"/upload\" enctype=\"multipart/form-data\" method=\"post\">'+\n '<input type=\"text\" name=\"title\"><br>'+\n '<input type=\"file\" name=\"upload\" multiple=\"multiple\"><br>'+\n '<input type=\"submit\" value=\"Upload\">'+\n '</form>'\n );\n}).listen(8080);\n```\n## API\n\n### Formidable.IncomingForm\n```javascript\nvar form = new formidable.IncomingForm()\n```\nCreates a new incoming form.\n\n```javascript\nform.encoding = 'utf-8';\n```\nSets encoding for incoming form fields.\n\n```javascript\nform.uploadDir = \"/my/dir\";\n```\nSets the directory for placing file uploads in. You can move them later on using\n`fs.rename()`. The default is `os.tmpdir()`.\n\n```javascript\nform.keepExtensions = false;\n```\nIf you want the files written to `form.uploadDir` to include the extensions of the original files, set this property to `true`.\n\n```javascript\nform.type\n```\nEither 'multipart' or 'urlencoded' depending on the incoming request.\n\n```javascript\nform.maxFieldsSize = 2 * 1024 * 1024;\n```\nLimits the amount of memory all fields together (except files) can allocate in bytes.\nIf this value is exceeded, an `'error'` event is emitted. The default\nsize is 2MB.\n\n```javascript\nform.maxFields = 1000;\n```\nLimits the number of fields that the querystring parser will decode. Defaults\nto 1000 (0 for unlimited).\n\n```javascript\nform.hash = false;\n```\nIf you want checksums calculated for incoming files, set this to either `'sha1'` or `'md5'`.\n\n```javascript\nform.multiples = false;\n```\nIf this option is enabled, when you call `form.parse`, the `files` argument will contain arrays of files for inputs which submit multiple files using the HTML5 `multiple` attribute.\n\n```javascript\nform.bytesReceived\n```\nThe amount of bytes received for this form so far.\n\n```javascript\nform.bytesExpected\n```\nThe expected number of bytes in this form.\n\n```javascript\nform.parse(request, [cb]);\n```\nParses an incoming node.js `request` containing form data. If `cb` is provided, all fields and files are collected and passed to the callback:\n\n\n```javascript\nform.parse(req, function(err, fields, files) {\n // ...\n});\n\nform.onPart(part);\n```\nYou may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events processing which would occur otherwise, making you fully responsible for handling the processing.\n\n```javascript\nform.onPart = function(part) {\n part.addListener('data', function() {\n // ...\n });\n}\n```\nIf you want to use formidable to only handle certain parts for you, you can do so:\n```javascript\nform.onPart = function(part) {\n if (!part.filename) {\n // let formidable handle all non-file parts\n form.handlePart(part);\n }\n}\n```\nCheck the code in this method for further inspiration.\n\n\n### Formidable.File\n```javascript\nfile.size = 0\n```\nThe size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet.\n```javascript\nfile.path = null\n```\nThe path this file is being written to. You can modify this in the `'fileBegin'` event in\ncase you are unhappy with the way formidable generates a temporary path for your files.\n```javascript\nfile.name = null\n```\nThe name this file had according to the uploading client.\n```javascript\nfile.type = null\n```\nThe mime type of this file, according to the uploading client.\n```javascript\nfile.lastModifiedDate = null\n```\nA date object (or `null`) containing the time this file was last written to. Mostly\nhere for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).\n```javascript\nfile.hash = null\n```\nIf hash calculation was set, you can read the hex digest out of this var.\n\n#### Formidable.File#toJSON()\n\n This method returns a JSON-representation of the file, allowing you to\n `JSON.stringify()` the file which is useful for logging and responding\n to requests.\n\n### Events\n\n\n#### 'progress'\n\nEmitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar.\n\n```javascript\nform.on('progress', function(bytesReceived, bytesExpected) {\n});\n```\n\n\n\n#### 'field'\n\nEmitted whenever a field / value pair has been received.\n\n```javascript\nform.on('field', function(name, value) {\n});\n```\n\n#### 'fileBegin'\n\nEmitted whenever a new file is detected in the upload stream. Use this event if\nyou want to stream the file to somewhere else while buffering the upload on\nthe file system.\n\n```javascript\nform.on('fileBegin', function(name, file) {\n});\n```\n\n#### 'file'\n\nEmitted whenever a field / file pair has been received. `file` is an instance of `File`.\n\n```javascript\nform.on('file', function(name, file) {\n});\n```\n\n#### 'error'\n\nEmitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events.\n\n```javascript\nform.on('error', function(err) {\n});\n```\n\n#### 'aborted'\n\n\nEmitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. After this event is emitted, an `error` event will follow. In the future there will be a separate 'timeout' event (needs a change in the node core).\n```javascript\nform.on('aborted', function() {\n});\n```\n\n##### 'end'\n```javascript\nform.on('end', function() {\n});\n```\nEmitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response.\n\n\n\n## Changelog\n\n### v1.1.1 (2017-01-15)\n\n * Fix DeprecationWarning about os.tmpDir() (Christian)\n * Update `buffer.write` order of arguments for Node 7 (Kornel Lesiński)\n * JSON Parser emits error events to the IncomingForm (alessio.montagnani)\n * Improved Content-Disposition parsing (Sebastien)\n * Access WriteStream of fs during runtime instead of include time (Jonas Amundsen)\n * Use built-in toString to convert buffer to hex (Charmander)\n * Add hash to json if present (Nick Stamas)\n * Add license to package.json (Simen Bekkhus)\n\n### v1.0.14 (2013-05-03)\n\n* Add failing hash tests. (Ben Trask)\n* Enable hash calculation again (Eugene Girshov)\n* Test for immediate data events (Tim Smart)\n* Re-arrange IncomingForm#parse (Tim Smart)\n\n### v1.0.13\n\n* Only update hash if update method exists (Sven Lito)\n* According to travis v0.10 needs to go quoted (Sven Lito)\n* Bumping build node versions (Sven Lito)\n* Additional fix for empty requests (Eugene Girshov)\n* Change the default to 1000, to match the new Node behaviour. (OrangeDog)\n* Add ability to control maxKeys in the querystring parser. (OrangeDog)\n* Adjust test case to work with node 0.9.x (Eugene Girshov)\n* Update package.json (Sven Lito)\n* Path adjustment according to eb4468b (Markus Ast)\n\n### v1.0.12\n\n* Emit error on aborted connections (Eugene Girshov)\n* Add support for empty requests (Eugene Girshov)\n* Fix name/filename handling in Content-Disposition (jesperp)\n* Tolerate malformed closing boundary in multipart (Eugene Girshov)\n* Ignore preamble in multipart messages (Eugene Girshov)\n* Add support for application/json (Mike Frey, Carlos Rodriguez)\n* Add support for Base64 encoding (Elmer Bulthuis)\n* Add File#toJSON (TJ Holowaychuk)\n* Remove support for Node.js 0.4 & 0.6 (Andrew Kelley)\n* Documentation improvements (Sven Lito, Andre Azevedo)\n* Add support for application/octet-stream (Ion Lupascu, Chris Scribner)\n* Use os.tmpdir() to get tmp directory (Andrew Kelley)\n* Improve package.json (Andrew Kelley, Sven Lito)\n* Fix benchmark script (Andrew Kelley)\n* Fix scope issue in incoming_forms (Sven Lito)\n* Fix file handle leak on error (OrangeDog)\n\n## License\n\nFormidable is licensed under the MIT license.\n\n## Ports\n\n* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable\n\n## Credits\n\n* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js\n", | ||
104 | + "readmeFilename": "Readme.md", | ||
105 | + "repository": { | ||
106 | + "type": "git", | ||
107 | + "url": "git://github.com/felixge/node-formidable.git" | ||
108 | + }, | ||
109 | + "scripts": { | ||
110 | + "clean": "rm test/tmp/*", | ||
111 | + "test": "node test/run.js" | ||
112 | + }, | ||
113 | + "version": "1.1.1" | ||
114 | +} |
node_modules/fs/README.md
0 → 100644
1 | +# Security holding package | ||
2 | + | ||
3 | +This package name is not currently in use, but was formerly occupied | ||
4 | +by another package. To avoid malicious use, npm is hanging on to the | ||
5 | +package name, but loosely, and we'll probably give it to you if you | ||
6 | +want it. | ||
7 | + | ||
8 | +You may adopt this package by contacting support@npmjs.com and | ||
9 | +requesting the name. |
node_modules/fs/package.json
0 → 100644
1 | +{ | ||
2 | + "_args": [ | ||
3 | + [ | ||
4 | + { | ||
5 | + "raw": "fs", | ||
6 | + "scope": null, | ||
7 | + "escapedName": "fs", | ||
8 | + "name": "fs", | ||
9 | + "rawSpec": "", | ||
10 | + "spec": "latest", | ||
11 | + "type": "tag" | ||
12 | + }, | ||
13 | + "/Users/fzy/project/koa2_Sequelize_project/util/Agora_Recording_SDK_for_Linux_FULL/samples" | ||
14 | + ] | ||
15 | + ], | ||
16 | + "_from": "fs@latest", | ||
17 | + "_id": "fs@0.0.1-security", | ||
18 | + "_inCache": true, | ||
19 | + "_location": "/fs", | ||
20 | + "_nodeVersion": "4.1.2", | ||
21 | + "_npmUser": { | ||
22 | + "name": "ehsalazar", | ||
23 | + "email": "ernie@npmjs.com" | ||
24 | + }, | ||
25 | + "_npmVersion": "3.10.5", | ||
26 | + "_phantomChildren": {}, | ||
27 | + "_requested": { | ||
28 | + "raw": "fs", | ||
29 | + "scope": null, | ||
30 | + "escapedName": "fs", | ||
31 | + "name": "fs", | ||
32 | + "rawSpec": "", | ||
33 | + "spec": "latest", | ||
34 | + "type": "tag" | ||
35 | + }, | ||
36 | + "_requiredBy": [ | ||
37 | + "#DEV:/", | ||
38 | + "#USER" | ||
39 | + ], | ||
40 | + "_resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", | ||
41 | + "_shasum": "8a7bd37186b6dddf3813f23858b57ecaaf5e41d4", | ||
42 | + "_shrinkwrap": null, | ||
43 | + "_spec": "fs", | ||
44 | + "_where": "/Users/fzy/project/koa2_Sequelize_project/util/Agora_Recording_SDK_for_Linux_FULL/samples", | ||
45 | + "author": "", | ||
46 | + "bugs": { | ||
47 | + "url": "https://github.com/npm/security-holder/issues" | ||
48 | + }, | ||
49 | + "dependencies": {}, | ||
50 | + "description": "This package name is not currently in use, but was formerly occupied by another package. To avoid malicious use, npm is hanging on to the package name, but loosely, and we'll probably give it to you if you want it.", | ||
51 | + "devDependencies": {}, | ||
52 | + "directories": {}, | ||
53 | + "dist": { | ||
54 | + "shasum": "8a7bd37186b6dddf3813f23858b57ecaaf5e41d4", | ||
55 | + "tarball": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz" | ||
56 | + }, | ||
57 | + "homepage": "https://github.com/npm/security-holder#readme", | ||
58 | + "keywords": [], | ||
59 | + "license": "ISC", | ||
60 | + "main": "index.js", | ||
61 | + "maintainers": [ | ||
62 | + { | ||
63 | + "name": "ehsalazar", | ||
64 | + "email": "ernie@npmjs.com" | ||
65 | + } | ||
66 | + ], | ||
67 | + "name": "fs", | ||
68 | + "optionalDependencies": {}, | ||
69 | + "readme": "# Security holding package\n\nThis package name is not currently in use, but was formerly occupied\nby another package. To avoid malicious use, npm is hanging on to the\npackage name, but loosely, and we'll probably give it to you if you\nwant it.\n\nYou may adopt this package by contacting support@npmjs.com and\nrequesting the name.\n", | ||
70 | + "readmeFilename": "README.md", | ||
71 | + "repository": { | ||
72 | + "type": "git", | ||
73 | + "url": "git+https://github.com/npm/security-holder.git" | ||
74 | + }, | ||
75 | + "scripts": { | ||
76 | + "test": "echo \"Error: no test specified\" && exit 1" | ||
77 | + }, | ||
78 | + "version": "0.0.1-security" | ||
79 | +} |
node_modules/gm/.npmignore
0 → 100644
node_modules/gm/.travis.yml
0 → 100644
node_modules/gm/1
0 → 100644
1 | +fatal: Invalid refspec '/dev/null' |
node_modules/gm/History.md
0 → 100644
1 | + | ||
2 | +1.23.0 / 2016-08-03 | ||
3 | + | ||
4 | + * fixed; webpack support #547 sean-shirazi | ||
5 | + * fixed; windows support - use cross-spawn to spawn processes #537 bdukes | ||
6 | + * added; allow thumbnail to accept the same options as resize #527 Sebmaster | ||
7 | + * added; dispose support #487 dlwr | ||
8 | + * docs; add example of loading image from URL #544 wahengchang | ||
9 | + * docs; Fix a link in README.md #532 clbn | ||
10 | + * travis; update travis versions #551 amilajack | ||
11 | + | ||
12 | +1.22.0 / 2016-04-07 | ||
13 | + | ||
14 | + * fixed; identity parser: support multi-value keys by creating an array #508 #509 [emaniacs](https://github.com/emaniacs) | ||
15 | + * fixed; error handling if gm is not installed #499 [aeo3](https://github.com/aeo3) | ||
16 | + * fixed; highlightColor typo in compare #504 [DanielHudson](https://github.com/DanielHudson) | ||
17 | + * docs; Fix typo #475 [rodrigoalviani](https://github.com/rodrigoalviani) | ||
18 | + | ||
19 | +1.21.1 / 2015-10-26 | ||
20 | + | ||
21 | +* fixed: Fixed #465 hard coded gm binary, also fixed issues with compare and fixed tests so they will fail on subsequent runs when they should do [rwky](https://github.com/rwky) | ||
22 | + | ||
23 | +1.21.0 / 2015-10-26 **contains security fix** | ||
24 | + | ||
25 | +* fixed: gm.compare fails to escape arguments properly (Reported by Brendan Scarvell) [rwky](https://github.com/rwky) | ||
26 | + | ||
27 | +1.20.0 / 2015-09-23 | ||
28 | + | ||
29 | +* changed: Reverted "Add format inference from filename for buffers/streams" due to errors #448 | ||
30 | + | ||
31 | +1.19.0 / 2015-09-16 | ||
32 | + | ||
33 | +* changed: Added error to notify about image magick not supporting minify [encima](https://github.com/encima) | ||
34 | +* changed: Refactored orientation getter to use faster identify call [lbeschastny](https://github.com/lbeschastny) | ||
35 | +* added: resizeExact function [DanMMX](https://github.com/DanMMX) | ||
36 | +* added: thumbExact function [DanMMX](https://github.com/DanMMX) | ||
37 | +* added: Add format inference from filename for buffers/streams [adurrive](https://github.com/adurrive) | ||
38 | +* fixed: Hex values when passed to compare aren't quoted automatically [DanMMX](https://github.com/DanMMX) | ||
39 | +* fixed: identify returning last frame size instead of the larges on animated gifs [preynal](https://github.com/preynal) | ||
40 | +* docs: Updated docs [laurilehmijoki](https://github.com/laurilehmijoki) | ||
41 | + | ||
42 | +1.18.1 / 2015-05-18 | ||
43 | + | ||
44 | +* changed: Added io.js support [rwky](https://github.com/rwky) | ||
45 | + | ||
46 | +1.18.0 / 2015-05-18 | ||
47 | + | ||
48 | +* changed: Removed support for node 0.8 and added support for 0.12 [rwky](https://github.com/rwky) | ||
49 | +* changed: Listen to stdin error event for spawn errors [kapouer](https://github.com/kapouer) | ||
50 | +* changed: Improved error handling when gm isn't installed [FreshXOpenSource](https://github.com/FreshXOpenSource) | ||
51 | +* changed: Allow append method to use an array of arguments [emohacker](https://github.com/emohacker) | ||
52 | +* changed: appPath option now specifies full path to gm binary John Borkowski | ||
53 | +* changed: Ignore warning messages for identify [asrail](https://github.com/asrail) | ||
54 | +* added: Montage method [donaldpcook](https://github.com/donaldpcook) | ||
55 | +* added: Progressive option to thumb [mohebifar](https://github.com/mohebifar) | ||
56 | +* added: Native gm auto-orient for use with gm >= 1.3.18 [bog](https://github.com/bog) | ||
57 | +* added: Timeout support by passing the timeout option in milliseconds [marcbachmann](https://github.com/marcbachmann) | ||
58 | +* fixed: density when using ImageMagick [syzer](https://github.com/syzer) | ||
59 | +* fixed: resize behaviour for falsy values [adius](https://github.com/adius) | ||
60 | + | ||
61 | + | ||
62 | +1.17.0 / 2014-10-28 | ||
63 | +================== | ||
64 | + | ||
65 | + * changed: extended compare callback also returns the file names #297 [mastix](https://github.com/mastix) | ||
66 | + * changed: pass spawn crash to callback #306 [medikoo](https://github.com/medikoo) | ||
67 | + * changed: geometry supports arbitary string as first argument #330 [jdiez17](https://github.com/jdiez17) | ||
68 | + * added: support for repage+ option #275 [desigens](https://github.com/desigens) | ||
69 | + * added: added the dissolve command #300 [microadm](https://github.com/microadam) | ||
70 | + * added: composite method #332 [jdiez17](https://github.com/jdiez17) | ||
71 | + * fixed: cannot set tolerance to 0 #302 [rwky](https://github.com/rwky) | ||
72 | + * fixed: handle empty buffers #330 [alcidesv](https://github.com/alcidesv) | ||
73 | + | ||
74 | +1.16.0 / 2014-05-09 | ||
75 | +================== | ||
76 | + | ||
77 | + * fixed; dropped "+" when 0 passed as vertical roll amt #267 [dwtkns](https://github.com/dwtkns) | ||
78 | + * added; highlight-style support #272 [fdecampredon](https://github.com/fdecampredon) | ||
79 | + | ||
80 | +1.15.0 / 2014-05-03 | ||
81 | +=================== | ||
82 | + | ||
83 | + * changed; gm.compare logic to always run the mse comparison as expected #258 [Vokkim](https://github.com/Vokkim) | ||
84 | + * added; `tolerance` to gm.compare options object #258 [Vokkim](https://github.com/Vokkim) | ||
85 | + * added; option to set ImageMagick application path explicitly #250 (akreitals) | ||
86 | + * fixed; gm.compare: support values like 9.51582e-05 #260 [normanrz](https://github.com/normanrz) | ||
87 | + * README: add call for maintainers | ||
88 | + | ||
89 | +1.14.2 / 2013-12-24 | ||
90 | +=================== | ||
91 | + | ||
92 | +* fixed; background is now a setting #246 (PEM--) | ||
93 | + | ||
94 | +1.14.1 / 2013-12-09 | ||
95 | +=================== | ||
96 | + | ||
97 | +* fixed; identify -verbose colon behavior #240 ludow | ||
98 | + | ||
99 | +1.14.0 / 2013-12-04 | ||
100 | +=================== | ||
101 | + | ||
102 | +* added; compare method for imagemagick (longlho) | ||
103 | + | ||
104 | +1.13.3 / 2013-10-22 | ||
105 | +=================== | ||
106 | + | ||
107 | +* fixed; escape diffOptions.file in compare (dwabyick) | ||
108 | + | ||
109 | +1.13.2 / 2013-10-18 | ||
110 | +=================== | ||
111 | + | ||
112 | +* fixed; density is a setting not an operator | ||
113 | + | ||
114 | +1.13.1 / 2013-09-15 | ||
115 | +=================== | ||
116 | + | ||
117 | +* added; boolean for % crop | ||
118 | + | ||
119 | +1.13.0 / 2013-09-07 | ||
120 | +=================== | ||
121 | + | ||
122 | +* added; morph more than two images (overra) | ||
123 | + | ||
124 | +1.12.2 / 2013-08-29 | ||
125 | +=================== | ||
126 | + | ||
127 | +* fixed; fallback to through in node 0.8 | ||
128 | + | ||
129 | +1.12.1 / 2013-08-29 (unpublished) | ||
130 | +=================== | ||
131 | + | ||
132 | +* refactor; replace through with stream.PassThrough | ||
133 | + | ||
134 | +1.12.0 / 2013-08-27 | ||
135 | +=================== | ||
136 | + | ||
137 | +* added; diff image output file (chenglou) | ||
138 | + | ||
139 | +1.11.1 / 2013-08-17 | ||
140 | +=================== | ||
141 | + | ||
142 | +* added; proto.selectFrame(#) | ||
143 | +* fixed; getters should not ignore frame selection | ||
144 | + | ||
145 | +1.11.0 / 2013-07-23 | ||
146 | +=================== | ||
147 | + | ||
148 | +* added; optional formatting string for gm().identify(format, callback) (tornillo) | ||
149 | +* removed; error messages when gm/im binary is not installed | ||
150 | + | ||
151 | +1.10.0 / 2013-06-27 | ||
152 | +=================== | ||
153 | + | ||
154 | +* refactor; use native `-auto-orient` for imagemagick | ||
155 | + | ||
156 | +1.9.2 / 2013-06-12 | ||
157 | +================== | ||
158 | + | ||
159 | + * refactor; move `streamToBuffer` to a separate module | ||
160 | + * fixed; .stream(format) without a callback | ||
161 | + | ||
162 | +1.9.1 / 2013-05-07 | ||
163 | +================== | ||
164 | + | ||
165 | + * fixed; gm().resize(width) always only resizes width | ||
166 | + * fixed; gm('img.gif').format() returns the format of the first frame | ||
167 | + | ||
168 | +1.9.0 / 2013-04-21 | ||
169 | +================== | ||
170 | + | ||
171 | + * added; node v0.10 support | ||
172 | + * removed; node < v0.8 support - `Buffer.concat()` | ||
173 | + * tests; all tests now run on Travis | ||
174 | + * added; gm().stream() returns a stream when no callback is present | ||
175 | + * added; gm().toBuffer(callback) | ||
176 | + * fixed; gm().size() only returns the size of the first frame of a GIF | ||
177 | + | ||
178 | +1.8.2 / 2013-03-07 | ||
179 | +================== | ||
180 | + | ||
181 | + * include source path in identify data #126 [soupdiver](https://github.com/soupdiver) | ||
182 | + | ||
183 | +1.8.1 / 2012-12-21 | ||
184 | +================== | ||
185 | + | ||
186 | + * Avoid losing already set arguments on identify #105 #113 #109 [JNissi](https://github.com/JNissi) | ||
187 | + * tests; add autoOrient + thumb() test | ||
188 | + * tests; add test case for #113 | ||
189 | + * tests; added test for #109 | ||
190 | + * tests; add resize on buffer test | ||
191 | + | ||
192 | +1.8.0 / 2012-12-14 | ||
193 | +================== | ||
194 | + | ||
195 | + * added; geometry support to scale() #98 | ||
196 | + * removed; incorrect/broken dissolve() method (never worked) | ||
197 | + * fixed; handle child_proc error when using Buffer input #109 | ||
198 | + * fixed; use of Buffers with identify() #109 | ||
199 | + * fixed; no longer include -size arg with resize() #98 | ||
200 | + * fixed; remove -size arg from extent() #103 | ||
201 | + * fixed; magnify support | ||
202 | + * fixed; autoOrient to work with all types of exif orientations [dambalah](https://github.com/dambalah) #108 | ||
203 | + * tests; npm test runs unit only (now compatible with travis) | ||
204 | + * tests; fix magnify test on imagemagick | ||
205 | + * tests; added for cmd line args | ||
206 | + | ||
207 | +1.7.0 / 2012-12-06 | ||
208 | +================== | ||
209 | + | ||
210 | + * added; gm.compare support | ||
211 | + * added; passing Buffers directly [danmilon](https://github.com/danmilon) | ||
212 | + | ||
213 | +1.6.1 / 2012-11-13 | ||
214 | +================== | ||
215 | + | ||
216 | + * fixed regression; only pass additional params on error #96 | ||
217 | + | ||
218 | +1.6.0 / 2012-11-10 | ||
219 | +================== | ||
220 | + | ||
221 | + * changed; rename internal buffer to _buffer #88 [kof](https://github.com/kof) | ||
222 | + * changed; optimized identify getters (format, depth, size, color, filesize). #83 please read this for details: https://github.com/aheckmann/gm/commit/8fcf3f8f84a02cc2001da874cbebb89bf7084409 | ||
223 | + * added; visionmedia/debug support | ||
224 | + * added; `gm convert -thumbnail` support. _differs from thumb()._ [danmilon](https://github.com/danmilon) | ||
225 | + * fixed; -rotate 0 support #90 | ||
226 | + * fixed; multi-execution of same gm instance arguments corruption | ||
227 | + * fixed; gracefully handle parser errors #94 [eldilibra](https://github.com/eldilibra) | ||
228 | + | ||
229 | +1.5.1 / 2012-10-02 | ||
230 | +================== | ||
231 | + | ||
232 | + * fixed; passing multiple paths to append() #77 | ||
233 | + | ||
234 | +1.5.0 / 2012-09-15 | ||
235 | +================== | ||
236 | + | ||
237 | + * fixed; callback scope | ||
238 | + * fixed; append() usage #77 | ||
239 | + | ||
240 | +1.4.2 / 2012-08-17 | ||
241 | +================== | ||
242 | + | ||
243 | + * fixed; identify parsing for ImageMagick exif data (#58) | ||
244 | + * fixed; when in imageMagick mode, complain about missing imageMagick [bcherry](https://github.com/bcherry) (#73) | ||
245 | + * added; tests | ||
246 | + | ||
247 | +1.4.1 / 2012-07-31 | ||
248 | +================== | ||
249 | + | ||
250 | + * fixed; scenes() args | ||
251 | + * fixed; accept the left-to-right arg of append() | ||
252 | + * added; _subCommand | ||
253 | + | ||
254 | +## v1.4 - 07/28/2012 | ||
255 | + | ||
256 | + * added; adjoin() [Math-] | ||
257 | + * added; affine() [Math-] | ||
258 | + * added; append() [Math-] | ||
259 | + * added; authenticate() [Math-] | ||
260 | + * added; average() [Math-] | ||
261 | + * added; backdrop() [Math-] | ||
262 | + * added; blackThreshold() [Math-] | ||
263 | + * added; bluePrimary() [Math-] | ||
264 | + * added; border() [Math-] | ||
265 | + * added; borderColor() [Math-] | ||
266 | + * added; box() [Math-] | ||
267 | + * added; channel() [Math-] | ||
268 | + * added; clip() [Math-] | ||
269 | + * added; coalesce() [Math-] | ||
270 | + * added; colorMap() [Math-] | ||
271 | + * added; compose() [Math-] | ||
272 | + * added; compress() [Math-] | ||
273 | + * added; convolve() [Math-] | ||
274 | + * added; createDirectories() [Math-] | ||
275 | + * added; deconstruct() [Math-] | ||
276 | + * added; delay() [Math-] | ||
277 | + * added; define() [Math-] | ||
278 | + * added; displace() [Math-] | ||
279 | + * added; display() [Math-] | ||
280 | + * added; dispose() [Math-] | ||
281 | + * added; disolve() [Math-] | ||
282 | + * added; encoding() [Math-] | ||
283 | + * added; endian() [Math-] | ||
284 | + * added; file() [Math-] | ||
285 | + * added; flatten() [Math-] | ||
286 | + * added; foreground() [Math-] | ||
287 | + * added; frame() [Math-] | ||
288 | + * added; fuzz() [Math-] | ||
289 | + * added; gaussian() [Math-] | ||
290 | + * added; geometry() [Math-] | ||
291 | + * added; greenPrimary() [Math-] | ||
292 | + * added; highlightColor() [Math-] | ||
293 | + * added; highlightStyle() [Math-] | ||
294 | + * added; iconGeometry() [Math-] | ||
295 | + * added; intent() [Math-] | ||
296 | + * added; lat() [Math-] | ||
297 | + * added; level() [Math-] | ||
298 | + * added; list() [Math-] | ||
299 | + * added; log() [Math-] | ||
300 | + * added; map() [Math-] | ||
301 | + * added; matte() [Math-] | ||
302 | + * added; matteColor() [Math-] | ||
303 | + * added; mask() [Math-] | ||
304 | + * added; maximumError() [Math-] | ||
305 | + * added; mode() [Math-] | ||
306 | + * added; monitor() [Math-] | ||
307 | + * added; mosaic() [Math-] | ||
308 | + * added; motionBlur() [Math-] | ||
309 | + * added; name() [Math-] | ||
310 | + * added; noop() [Math-] | ||
311 | + * added; normalize() [Math-] | ||
312 | + * added; opaque() [Math-] | ||
313 | + * added; operator() [Math-] | ||
314 | + * added; orderedDither() [Math-] | ||
315 | + * added; outputDirectory() [Math-] | ||
316 | + * added; page() [Math-] | ||
317 | + * added; pause() [Math-] | ||
318 | + * added; pen() [Math-] | ||
319 | + * added; ping() [Math-] | ||
320 | + * added; pointSize() [Math-] | ||
321 | + * added; preview() [Math-] | ||
322 | + * added; process() [Math-] | ||
323 | + * added; profile() [Math-] | ||
324 | + * added; progress() [Math-] | ||
325 | + * added; rawSize() [Math-] | ||
326 | + * added; randomThreshold() [Math-] | ||
327 | + * added; recolor() [Math-] | ||
328 | + * added; redPrimary() [Math-] | ||
329 | + * added; remote() [Math-] | ||
330 | + * added; render() [Math-] | ||
331 | + * added; repage() [Math-] | ||
332 | + * added; sample() [Math-] | ||
333 | + * added; samplingFactor() [Math-] | ||
334 | + * added; scene() [Math-] | ||
335 | + * added; scenes() [Math-] | ||
336 | + * added; screen() [Math-] | ||
337 | + * added; segment() [Math-] | ||
338 | + * added; set() [Math-] | ||
339 | + * added; shade() [Math-] | ||
340 | + * added; shadow() [Math-] | ||
341 | + * added; sharedMemory() [Math-] | ||
342 | + * added; shave() [Math-] | ||
343 | + * added; shear() [Math-] | ||
344 | + * added; silent() [Math-] | ||
345 | + * added; snaps() [Math-] | ||
346 | + * added; stagano() [Math-] | ||
347 | + * added; stereo() [Math-] | ||
348 | + * added; textFont() [Math-] | ||
349 | + * added; texture() [Math-] | ||
350 | + * added; threshold() [Math-] | ||
351 | + * added; tile() [Math-] | ||
352 | + * added; transform() [Math-] | ||
353 | + * added; transparent() [Math-] | ||
354 | + * added; treeDepth() [Math-] | ||
355 | + * added; update() [Math-] | ||
356 | + * added; units() [Math-] | ||
357 | + * added; unsharp() [Math-] | ||
358 | + * added; usePixmap() [Math-] | ||
359 | + * added; view() [Math-] | ||
360 | + * added; virtualPixel() [Math-] | ||
361 | + * added; visual() [Math-] | ||
362 | + * added; watermark() [Math-] | ||
363 | + * added; wave() [Math-] | ||
364 | + * added; whitePoint() [Math-] | ||
365 | + * added; whiteThreshold() [Math-] | ||
366 | + * added; window() [Math-] | ||
367 | + * added; windowGroup() [Math-] | ||
368 | + | ||
369 | +## v1.3.2 - 06/22/2012 | ||
370 | + | ||
371 | + * added; node >= 0.7/0.8 compat | ||
372 | + | ||
373 | +## v1.3.1 - 06/06/2012 | ||
374 | + | ||
375 | + * fixed; thumb() alignment and cropping [thomaschaaf] | ||
376 | + * added; hint when graphicsmagick is not installed (#62) | ||
377 | + * fixed; minify() (#59) | ||
378 | + | ||
379 | +## v1.3.0 - 04/11/2012 | ||
380 | + | ||
381 | + * added; flatten support [jwarchol] | ||
382 | + * added; background support [jwarchol] | ||
383 | + * fixed; identify parser error [chriso] | ||
384 | + | ||
385 | +## v1.2.0 - 03/30/2012 | ||
386 | + | ||
387 | + * added; extent and gravity support [jwarchol] | ||
388 | + | ||
389 | +## v1.1.0 - 03/15/2012 | ||
390 | + | ||
391 | + * added; filter() support [travisbeck] | ||
392 | + * added; density() [travisbeck] | ||
393 | + * fixed; permit either width or height in resize [dambalah] | ||
394 | + * updated; docs | ||
395 | + | ||
396 | +## v1.0.5 - 02/15/2012 | ||
397 | + | ||
398 | + * added; strip() support [Math-] | ||
399 | + * added; interlace() support [Math-] | ||
400 | + * added; setFormat() support [Math-] | ||
401 | + * fixed; regexps for image types [Math-] | ||
402 | + | ||
403 | +## v1.0.4 - 02/09/2012 | ||
404 | + | ||
405 | + * expose utils | ||
406 | + | ||
407 | +## v1.0.3 - 01/27/2012 | ||
408 | + | ||
409 | + * removed; console.log | ||
410 | + | ||
411 | +## v1.0.2 - 01/24/2012 | ||
412 | + | ||
413 | + * added; debugging info on parser errors | ||
414 | + * fixed; exports.version | ||
415 | + | ||
416 | +## v1.0.1 - 01/12/2012 | ||
417 | + | ||
418 | + * fixed; use of reserved keyword `super` for node v0.5+ | ||
419 | + | ||
420 | +## v1.0.0 - 01/12/2012 | ||
421 | + | ||
422 | + * added; autoOrient support [kainosnoema] (#21) | ||
423 | + * added; orientation support [kainosnoema] (#21) | ||
424 | + * fixed; identify parser now properly JSON formats all data output by `gm identify` such as IPTC, GPS, Make, etc (#20) | ||
425 | + * added; support for running as imagemagick (#23, #29) | ||
426 | + * added; subclassing support; useful for setting default constructor options like one constructor for ImageMagick, the other for GM | ||
427 | + * added; more tests | ||
428 | + * changed; remove redundant `orientation`, `resolution`, and `filesize` from `this.data` in `indentify()`. Use their uppercase equivalents. | ||
429 | + | ||
430 | +## v0.6.0 - 12/14/2011 | ||
431 | + | ||
432 | + * added; stream support [kainosnoema] (#22) | ||
433 | + | ||
434 | +## v0.5.0 - 07/07/2011 | ||
435 | + | ||
436 | + * added; gm#trim() support [lepokle] | ||
437 | + * added; gm#inputIs() support | ||
438 | + * fixed; 'geometry does not contain image' error: gh-17 | ||
439 | + | ||
440 | +## v0.4.3 - 05/17/2011 | ||
441 | + | ||
442 | + * added; bunch of tests | ||
443 | + * fixed; polygon, polyline, bezier drawing bug | ||
444 | + | ||
445 | +## v0.4.2 - 05/10/2011 | ||
446 | + | ||
447 | + * added; resize options support | ||
448 | + | ||
449 | +## v0.4.1 - 04/28/2011 | ||
450 | + | ||
451 | + * shell args are now escaped (thanks @visionmedia) | ||
452 | + * added; gm.in() | ||
453 | + * added; gm.out() | ||
454 | + * various refactoring | ||
455 | + | ||
456 | +## v0.4.0 - 9/21/2010 | ||
457 | + | ||
458 | + * removed deprecated `new` method | ||
459 | + * added drawing docs | ||
460 | + | ||
461 | +## v0.3.2 - 9/06/2010 | ||
462 | + | ||
463 | + * new images are now created using same gm() constructor | ||
464 | + | ||
465 | +## v0.3.1 - 9/06/2010 | ||
466 | + | ||
467 | + * can now create images from scratch | ||
468 | + * add type method | ||
469 | + | ||
470 | +## v0.3.0 - 8/26/2010 | ||
471 | + | ||
472 | + * add drawing api | ||
473 | + | ||
474 | +## v0.2.2 - 8/22/2010 | ||
475 | + | ||
476 | + * add quality option to thumb() | ||
477 | + * add teropa to contributors | ||
478 | + * added support for colorspace() | ||
479 | + | ||
480 | +## v0.2.1 - 7/31/2010 | ||
481 | + | ||
482 | + * fixed naming conflict. depth() manipulation method renamed bitdepth() | ||
483 | + * added better docs | ||
484 | + | ||
485 | +## v0.2.0 - 7/29/2010 | ||
486 | + | ||
487 | +new methods | ||
488 | + | ||
489 | + - swirl | ||
490 | + - spread | ||
491 | + - solarize | ||
492 | + - sharpen | ||
493 | + - roll | ||
494 | + - sepia | ||
495 | + - region | ||
496 | + - raise | ||
497 | + - lower | ||
498 | + - paint | ||
499 | + - noise | ||
500 | + - negative | ||
501 | + - morph | ||
502 | + - median | ||
503 | + - antialias | ||
504 | + - limit | ||
505 | + - label | ||
506 | + - implode | ||
507 | + - gamma | ||
508 | + - enhance | ||
509 | + - equalize | ||
510 | + - emboss | ||
511 | + - edge | ||
512 | + - dither | ||
513 | + - monochrome | ||
514 | + - despeckle | ||
515 | + - depth | ||
516 | + - cycle | ||
517 | + - contrast | ||
518 | + - comment | ||
519 | + - colors | ||
520 | + | ||
521 | +added more default args to several methods | ||
522 | +added more examples | ||
523 | + | ||
524 | + | ||
525 | +## v0.1.2 - 7/28/2010 | ||
526 | + | ||
527 | + * refactor project into separate modules | ||
528 | + | ||
529 | + | ||
530 | +## v0.1.1 - 7/27/2010 | ||
531 | + | ||
532 | + * add modulate method | ||
533 | + * add colorize method | ||
534 | + * add charcoal method | ||
535 | + * add chop method | ||
536 | + * bug fix in write without a callback | ||
537 | + | ||
538 | + | ||
539 | +## v0.1.0 - 6/27/2010 | ||
540 | + | ||
541 | + * no longer supporting mogrify | ||
542 | + * add image data getter methods | ||
543 | + | ||
544 | + * size | ||
545 | + * format | ||
546 | + * color | ||
547 | + * res | ||
548 | + * depth | ||
549 | + * filesize | ||
550 | + * identify | ||
551 | + | ||
552 | + * add new convert methods | ||
553 | + | ||
554 | + * scale | ||
555 | + * resample | ||
556 | + * rotate | ||
557 | + * flip | ||
558 | + * flop | ||
559 | + * crop | ||
560 | + * magnify | ||
561 | + * minify | ||
562 | + * quality | ||
563 | + * blur | ||
564 | + * thumb | ||
565 | + | ||
566 | + | ||
567 | +## v0.0.1 - 6/11/2010 | ||
568 | +Initial release |
node_modules/gm/Makefile
0 → 100644
node_modules/gm/README.md
0 → 100644
1 | + | ||
2 | +# gm [](https://travis-ci.org/aheckmann/gm) [](https://www.npmjs.org/package/gm) | ||
3 | + | ||
4 | +GraphicsMagick and ImageMagick for node | ||
5 | + | ||
6 | +## Bug Reports | ||
7 | + | ||
8 | +When reporting bugs please include the version of graphicsmagick/imagemagick you're using (gm -version/convert -version) as well as the version of this module and copies of any images you're having problems with. | ||
9 | + | ||
10 | +## Getting started | ||
11 | +First download and install [GraphicsMagick](http://www.graphicsmagick.org/) or [ImageMagick](http://www.imagemagick.org/). In Mac OS X, you can simply use [Homebrew](http://mxcl.github.io/homebrew/) and do: | ||
12 | + | ||
13 | + brew install imagemagick | ||
14 | + brew install graphicsmagick | ||
15 | + | ||
16 | +If you want WebP support with ImageMagick, you must add the WebP option: | ||
17 | + | ||
18 | + brew install imagemagick --with-webp | ||
19 | + | ||
20 | +then either use npm: | ||
21 | + | ||
22 | + npm install gm | ||
23 | + | ||
24 | +or clone the repo: | ||
25 | + | ||
26 | + git clone git://github.com/aheckmann/gm.git | ||
27 | + | ||
28 | + | ||
29 | +## Use ImageMagick instead of gm | ||
30 | + | ||
31 | +Subclass `gm` to enable ImageMagick | ||
32 | + | ||
33 | +```js | ||
34 | +var fs = require('fs') | ||
35 | + , gm = require('gm').subClass({imageMagick: true}); | ||
36 | + | ||
37 | +// resize and remove EXIF profile data | ||
38 | +gm('/path/to/my/img.jpg') | ||
39 | +.resize(240, 240) | ||
40 | +... | ||
41 | +``` | ||
42 | + | ||
43 | + | ||
44 | +## Basic Usage | ||
45 | + | ||
46 | +```js | ||
47 | +var fs = require('fs') | ||
48 | + , gm = require('gm'); | ||
49 | + | ||
50 | +// resize and remove EXIF profile data | ||
51 | +gm('/path/to/my/img.jpg') | ||
52 | +.resize(240, 240) | ||
53 | +.noProfile() | ||
54 | +.write('/path/to/resize.png', function (err) { | ||
55 | + if (!err) console.log('done'); | ||
56 | +}); | ||
57 | + | ||
58 | +// some files would not be resized appropriately | ||
59 | +// http://stackoverflow.com/questions/5870466/imagemagick-incorrect-dimensions | ||
60 | +// you have two options: | ||
61 | +// use the '!' flag to ignore aspect ratio | ||
62 | +gm('/path/to/my/img.jpg') | ||
63 | +.resize(240, 240, '!') | ||
64 | +.write('/path/to/resize.png', function (err) { | ||
65 | + if (!err) console.log('done'); | ||
66 | +}); | ||
67 | + | ||
68 | +// use the .resizeExact with only width and/or height arguments | ||
69 | +gm('/path/to/my/img.jpg') | ||
70 | +.resizeExact(240, 240) | ||
71 | +.write('/path/to/resize.png', function (err) { | ||
72 | + if (!err) console.log('done'); | ||
73 | +}); | ||
74 | + | ||
75 | +// obtain the size of an image | ||
76 | +gm('/path/to/my/img.jpg') | ||
77 | +.size(function (err, size) { | ||
78 | + if (!err) | ||
79 | + console.log(size.width > size.height ? 'wider' : 'taller than you'); | ||
80 | +}); | ||
81 | + | ||
82 | +// output all available image properties | ||
83 | +gm('/path/to/img.png') | ||
84 | +.identify(function (err, data) { | ||
85 | + if (!err) console.log(data) | ||
86 | +}); | ||
87 | + | ||
88 | +// pull out the first frame of an animated gif and save as png | ||
89 | +gm('/path/to/animated.gif[0]') | ||
90 | +.write('/path/to/firstframe.png', function (err) { | ||
91 | + if (err) console.log('aaw, shucks'); | ||
92 | +}); | ||
93 | + | ||
94 | +// auto-orient an image | ||
95 | +gm('/path/to/img.jpg') | ||
96 | +.autoOrient() | ||
97 | +.write('/path/to/oriented.jpg', function (err) { | ||
98 | + if (err) ... | ||
99 | +}) | ||
100 | + | ||
101 | +// crazytown | ||
102 | +gm('/path/to/my/img.jpg') | ||
103 | +.flip() | ||
104 | +.magnify() | ||
105 | +.rotate('green', 45) | ||
106 | +.blur(7, 3) | ||
107 | +.crop(300, 300, 150, 130) | ||
108 | +.edge(3) | ||
109 | +.write('/path/to/crazy.jpg', function (err) { | ||
110 | + if (!err) console.log('crazytown has arrived'); | ||
111 | +}) | ||
112 | + | ||
113 | +// annotate an image | ||
114 | +gm('/path/to/my/img.jpg') | ||
115 | +.stroke("#ffffff") | ||
116 | +.drawCircle(10, 10, 20, 10) | ||
117 | +.font("Helvetica.ttf", 12) | ||
118 | +.drawText(30, 20, "GMagick!") | ||
119 | +.write("/path/to/drawing.png", function (err) { | ||
120 | + if (!err) console.log('done'); | ||
121 | +}); | ||
122 | + | ||
123 | +// creating an image | ||
124 | +gm(200, 400, "#ddff99f3") | ||
125 | +.drawText(10, 50, "from scratch") | ||
126 | +.write("/path/to/brandNewImg.jpg", function (err) { | ||
127 | + // ... | ||
128 | +}); | ||
129 | +``` | ||
130 | + | ||
131 | +## Streams | ||
132 | + | ||
133 | +```js | ||
134 | +// passing a stream | ||
135 | +var readStream = fs.createReadStream('/path/to/my/img.jpg'); | ||
136 | +gm(readStream, 'img.jpg') | ||
137 | +.write('/path/to/reformat.png', function (err) { | ||
138 | + if (!err) console.log('done'); | ||
139 | +}); | ||
140 | + | ||
141 | + | ||
142 | +// passing a downloadable image by url | ||
143 | + | ||
144 | +var request = require('request'); | ||
145 | +var url = "www.abc.com/pic.jpg" | ||
146 | + | ||
147 | +gm(request(url)) | ||
148 | +.write('/path/to/reformat.png', function (err) { | ||
149 | + if (!err) console.log('done'); | ||
150 | +}); | ||
151 | + | ||
152 | + | ||
153 | +// can also stream output to a ReadableStream | ||
154 | +// (can be piped to a local file or remote server) | ||
155 | +gm('/path/to/my/img.jpg') | ||
156 | +.resize('200', '200') | ||
157 | +.stream(function (err, stdout, stderr) { | ||
158 | + var writeStream = fs.createWriteStream('/path/to/my/resized.jpg'); | ||
159 | + stdout.pipe(writeStream); | ||
160 | +}); | ||
161 | + | ||
162 | +// without a callback, .stream() returns a stream | ||
163 | +// this is just a convenience wrapper for above. | ||
164 | +var writeStream = fs.createWriteStream('/path/to/my/resized.jpg'); | ||
165 | +gm('/path/to/my/img.jpg') | ||
166 | +.resize('200', '200') | ||
167 | +.stream() | ||
168 | +.pipe(writeStream); | ||
169 | + | ||
170 | +// pass a format or filename to stream() and | ||
171 | +// gm will provide image data in that format | ||
172 | +gm('/path/to/my/img.jpg') | ||
173 | +.stream('png', function (err, stdout, stderr) { | ||
174 | + var writeStream = fs.createWriteStream('/path/to/my/reformatted.png'); | ||
175 | + stdout.pipe(writeStream); | ||
176 | +}); | ||
177 | + | ||
178 | +// or without the callback | ||
179 | +var writeStream = fs.createWriteStream('/path/to/my/reformatted.png'); | ||
180 | +gm('/path/to/my/img.jpg') | ||
181 | +.stream('png') | ||
182 | +.pipe(writeStream); | ||
183 | + | ||
184 | +// combine the two for true streaming image processing | ||
185 | +var readStream = fs.createReadStream('/path/to/my/img.jpg'); | ||
186 | +gm(readStream) | ||
187 | +.resize('200', '200') | ||
188 | +.stream(function (err, stdout, stderr) { | ||
189 | + var writeStream = fs.createWriteStream('/path/to/my/resized.jpg'); | ||
190 | + stdout.pipe(writeStream); | ||
191 | +}); | ||
192 | + | ||
193 | +// GOTCHA: | ||
194 | +// when working with input streams and any 'identify' | ||
195 | +// operation (size, format, etc), you must pass "{bufferStream: true}" if | ||
196 | +// you also need to convert (write() or stream()) the image afterwards | ||
197 | +// NOTE: this buffers the readStream in memory! | ||
198 | +var readStream = fs.createReadStream('/path/to/my/img.jpg'); | ||
199 | +gm(readStream) | ||
200 | +.size({bufferStream: true}, function(err, size) { | ||
201 | + this.resize(size.width / 2, size.height / 2) | ||
202 | + this.write('/path/to/resized.jpg', function (err) { | ||
203 | + if (!err) console.log('done'); | ||
204 | + }); | ||
205 | +}); | ||
206 | + | ||
207 | +``` | ||
208 | + | ||
209 | +## Buffers | ||
210 | + | ||
211 | +```js | ||
212 | +// A buffer can be passed instead of a filepath as well | ||
213 | +var buf = require('fs').readFileSync('/path/to/image.jpg'); | ||
214 | + | ||
215 | +gm(buf, 'image.jpg') | ||
216 | +.noise('laplacian') | ||
217 | +.write('/path/to/out.jpg', function (err) { | ||
218 | + if (err) return handle(err); | ||
219 | + console.log('Created an image from a Buffer!'); | ||
220 | +}); | ||
221 | + | ||
222 | +/* | ||
223 | +A buffer can also be returned instead of a stream | ||
224 | +The first argument to toBuffer is optional, it specifies the image format | ||
225 | +*/ | ||
226 | +gm('img.jpg') | ||
227 | +.resize(100, 100) | ||
228 | +.toBuffer('PNG',function (err, buffer) { | ||
229 | + if (err) return handle(err); | ||
230 | + console.log('done!'); | ||
231 | +}) | ||
232 | +``` | ||
233 | + | ||
234 | +## Custom Arguments | ||
235 | + | ||
236 | +If `gm` does not supply you with a method you need or does not work as you'd like, you can simply use `gm().in()` or `gm().out()` to set your own arguments. | ||
237 | + | ||
238 | +- `gm().command()` - Custom command such as `identify` or `convert` | ||
239 | +- `gm().in()` - Custom input arguments | ||
240 | +- `gm().out()` - Custom output arguments | ||
241 | + | ||
242 | +The command will be formatted in the following order: | ||
243 | + | ||
244 | +1. `command` - ie `convert` | ||
245 | +2. `in` - the input arguments | ||
246 | +3. `source` - stdin or an image file | ||
247 | +4. `out` - the output arguments | ||
248 | +5. `output` - stdout or the image file to write to | ||
249 | + | ||
250 | +For example, suppose you want the following command: | ||
251 | + | ||
252 | +```bash | ||
253 | +gm "convert" "label:Offline" "PNG:-" | ||
254 | +``` | ||
255 | + | ||
256 | +However, using `gm().label()` may not work as intended for you: | ||
257 | + | ||
258 | +```js | ||
259 | +gm() | ||
260 | +.label('Offline') | ||
261 | +.stream(); | ||
262 | +``` | ||
263 | + | ||
264 | +would yield: | ||
265 | + | ||
266 | +```bash | ||
267 | +gm "convert" "-label" "\"Offline\"" "PNG:-" | ||
268 | +``` | ||
269 | + | ||
270 | +Instead, you can use `gm().out()`: | ||
271 | + | ||
272 | +```js | ||
273 | +gm() | ||
274 | +.out('label:Offline') | ||
275 | +.stream(); | ||
276 | +``` | ||
277 | + | ||
278 | +which correctly yields: | ||
279 | + | ||
280 | +```bash | ||
281 | +gm "convert" "label:Offline" "PNG:-" | ||
282 | +``` | ||
283 | + | ||
284 | +### Custom Identify Format String | ||
285 | + | ||
286 | +When identifying an image, you may want to use a custom formatting string instead of using `-verbose`, which is quite slow. | ||
287 | +You can use your own [formatting string](http://www.imagemagick.org/script/escape.php) when using `gm().identify(format, callback)`. | ||
288 | +For example, | ||
289 | + | ||
290 | +```js | ||
291 | +gm('img.png').format(function (err, format) { | ||
292 | + | ||
293 | +}) | ||
294 | + | ||
295 | +// is equivalent to | ||
296 | + | ||
297 | +gm('img.png').identify('%m', function (err, format) { | ||
298 | + | ||
299 | +}) | ||
300 | +``` | ||
301 | + | ||
302 | +since `%m` is the format option for getting the image file format. | ||
303 | + | ||
304 | +## Platform differences | ||
305 | + | ||
306 | +Please document and refer to any [platform or ImageMagick/GraphicsMagick issues/differences here](https://github.com/aheckmann/gm/wiki/GraphicsMagick-and-ImageMagick-versions). | ||
307 | + | ||
308 | +## Examples: | ||
309 | + | ||
310 | + Check out the [examples](http://github.com/aheckmann/gm/tree/master/examples/) directory to play around. | ||
311 | + Also take a look at the [extending gm](http://wiki.github.com/aheckmann/gm/extending-gm) | ||
312 | + page to see how to customize gm to your own needs. | ||
313 | + | ||
314 | +## Constructor: | ||
315 | + | ||
316 | + There are a few ways you can use the `gm` image constructor. | ||
317 | + | ||
318 | + - 1) `gm(path)` When you pass a string as the first argument it is interpreted as the path to an image you intend to manipulate. | ||
319 | + - 2) `gm(stream || buffer, [filename])` You may also pass a ReadableStream or Buffer as the first argument, with an optional file name for format inference. | ||
320 | + - 3) `gm(width, height, [color])` When you pass two integer arguments, gm will create a new image on the fly with the provided dimensions and an optional background color. And you can still chain just like you do with pre-existing images too. See [here](http://github.com/aheckmann/gm/blob/master/examples/new.js) for an example. | ||
321 | + | ||
322 | +The links below refer to an older version of gm but everything should still work, if anyone feels like updating them please make a PR | ||
323 | + | ||
324 | +## Methods | ||
325 | + | ||
326 | + - getters | ||
327 | + - [size](http://aheckmann.github.com/gm/docs.html#getters) - returns the size (WxH) of the image | ||
328 | + - [orientation](http://aheckmann.github.com/gm/docs.html#getters) - returns the EXIF orientation of the image | ||
329 | + - [format](http://aheckmann.github.com/gm/docs.html#getters) - returns the image format (gif, jpeg, png, etc) | ||
330 | + - [depth](http://aheckmann.github.com/gm/docs.html#getters) - returns the image color depth | ||
331 | + - [color](http://aheckmann.github.com/gm/docs.html#getters) - returns the number of colors | ||
332 | + - [res](http://aheckmann.github.com/gm/docs.html#getters) - returns the image resolution | ||
333 | + - [filesize](http://aheckmann.github.com/gm/docs.html#getters) - returns image filesize | ||
334 | + - [identify](http://aheckmann.github.com/gm/docs.html#getters) - returns all image data available. Takes an optional format string. | ||
335 | + | ||
336 | + - manipulation | ||
337 | + - [adjoin](http://aheckmann.github.com/gm/docs.html#adjoin) | ||
338 | + - [affine](http://aheckmann.github.com/gm/docs.html#affine) | ||
339 | + - [antialias](http://aheckmann.github.com/gm/docs.html#antialias) | ||
340 | + - [append](http://aheckmann.github.com/gm/docs.html#append) | ||
341 | + - [authenticate](http://aheckmann.github.com/gm/docs.html#authenticate) | ||
342 | + - [autoOrient](http://aheckmann.github.com/gm/docs.html#autoOrient) | ||
343 | + - [average](http://aheckmann.github.com/gm/docs.html#average) | ||
344 | + - [backdrop](http://aheckmann.github.com/gm/docs.html#backdrop) | ||
345 | + - [bitdepth](http://aheckmann.github.com/gm/docs.html#bitdepth) | ||
346 | + - [blackThreshold](http://aheckmann.github.com/gm/docs.html#blackThreshold) | ||
347 | + - [bluePrimary](http://aheckmann.github.com/gm/docs.html#bluePrimary) | ||
348 | + - [blur](http://aheckmann.github.com/gm/docs.html#blur) | ||
349 | + - [border](http://aheckmann.github.com/gm/docs.html#border) | ||
350 | + - [borderColor](http://aheckmann.github.com/gm/docs.html#borderColor) | ||
351 | + - [box](http://aheckmann.github.com/gm/docs.html#box) | ||
352 | + - [channel](http://aheckmann.github.com/gm/docs.html#channel) | ||
353 | + - [charcoal](http://aheckmann.github.com/gm/docs.html#charcoal) | ||
354 | + - [chop](http://aheckmann.github.com/gm/docs.html#chop) | ||
355 | + - [clip](http://aheckmann.github.com/gm/docs.html#clip) | ||
356 | + - [coalesce](http://aheckmann.github.com/gm/docs.html#coalesce) | ||
357 | + - [colors](http://aheckmann.github.com/gm/docs.html#colors) | ||
358 | + - [colorize](http://aheckmann.github.com/gm/docs.html#colorize) | ||
359 | + - [colorMap](http://aheckmann.github.com/gm/docs.html#colorMap) | ||
360 | + - [colorspace](http://aheckmann.github.com/gm/docs.html#colorspace) | ||
361 | + - [comment](http://aheckmann.github.com/gm/docs.html#comment) | ||
362 | + - [compose](http://aheckmann.github.com/gm/docs.html#compose) | ||
363 | + - [compress](http://aheckmann.github.com/gm/docs.html#compress) | ||
364 | + - [contrast](http://aheckmann.github.com/gm/docs.html#contrast) | ||
365 | + - [convolve](http://aheckmann.github.com/gm/docs.html#convolve) | ||
366 | + - [createDirectories](http://aheckmann.github.com/gm/docs.html#createDirectories) | ||
367 | + - [crop](http://aheckmann.github.com/gm/docs.html#crop) | ||
368 | + - [cycle](http://aheckmann.github.com/gm/docs.html#cycle) | ||
369 | + - [deconstruct](http://aheckmann.github.com/gm/docs.html#deconstruct) | ||
370 | + - [delay](http://aheckmann.github.com/gm/docs.html#delay) | ||
371 | + - [define](http://aheckmann.github.com/gm/docs.html#define) | ||
372 | + - [density](http://aheckmann.github.com/gm/docs.html#density) | ||
373 | + - [despeckle](http://aheckmann.github.com/gm/docs.html#despeckle) | ||
374 | + - [dither](http://aheckmann.github.com/gm/docs.html#dither) | ||
375 | + - [displace](http://aheckmann.github.com/gm/docs.html#dither) | ||
376 | + - [display](http://aheckmann.github.com/gm/docs.html#display) | ||
377 | + - [dispose](http://aheckmann.github.com/gm/docs.html#dispose) | ||
378 | + - [dissolve](http://aheckmann.github.com/gm/docs.html#dissolve) | ||
379 | + - [edge](http://aheckmann.github.com/gm/docs.html#edge) | ||
380 | + - [emboss](http://aheckmann.github.com/gm/docs.html#emboss) | ||
381 | + - [encoding](http://aheckmann.github.com/gm/docs.html#encoding) | ||
382 | + - [enhance](http://aheckmann.github.com/gm/docs.html#enhance) | ||
383 | + - [endian](http://aheckmann.github.com/gm/docs.html#endian) | ||
384 | + - [equalize](http://aheckmann.github.com/gm/docs.html#equalize) | ||
385 | + - [extent](http://aheckmann.github.com/gm/docs.html#extent) | ||
386 | + - [file](http://aheckmann.github.com/gm/docs.html#file) | ||
387 | + - [filter](http://aheckmann.github.com/gm/docs.html#filter) | ||
388 | + - [flatten](http://aheckmann.github.com/gm/docs.html#flatten) | ||
389 | + - [flip](http://aheckmann.github.com/gm/docs.html#flip) | ||
390 | + - [flop](http://aheckmann.github.com/gm/docs.html#flop) | ||
391 | + - [foreground](http://aheckmann.github.com/gm/docs.html#foreground) | ||
392 | + - [frame](http://aheckmann.github.com/gm/docs.html#frame) | ||
393 | + - [fuzz](http://aheckmann.github.com/gm/docs.html#fuzz) | ||
394 | + - [gamma](http://aheckmann.github.com/gm/docs.html#gamma) | ||
395 | + - [gaussian](http://aheckmann.github.com/gm/docs.html#gaussian) | ||
396 | + - [geometry](http://aheckmann.github.com/gm/docs.html#geometry) | ||
397 | + - [gravity](http://aheckmann.github.com/gm/docs.html#gravity) | ||
398 | + - [greenPrimary](http://aheckmann.github.com/gm/docs.html#greenPrimary) | ||
399 | + - [highlightColor](http://aheckmann.github.com/gm/docs.html#highlightColor) | ||
400 | + - [highlightStyle](http://aheckmann.github.com/gm/docs.html#highlightStyle) | ||
401 | + - [iconGeometry](http://aheckmann.github.com/gm/docs.html#iconGeometry) | ||
402 | + - [implode](http://aheckmann.github.com/gm/docs.html#implode) | ||
403 | + - [intent](http://aheckmann.github.com/gm/docs.html#intent) | ||
404 | + - [interlace](http://aheckmann.github.com/gm/docs.html#interlace) | ||
405 | + - [label](http://aheckmann.github.com/gm/docs.html#label) | ||
406 | + - [lat](http://aheckmann.github.com/gm/docs.html#lat) | ||
407 | + - [level](http://aheckmann.github.com/gm/docs.html#level) | ||
408 | + - [list](http://aheckmann.github.com/gm/docs.html#list) | ||
409 | + - [limit](http://aheckmann.github.com/gm/docs.html#limit) | ||
410 | + - [log](http://aheckmann.github.com/gm/docs.html#log) | ||
411 | + - [loop](http://aheckmann.github.com/gm/docs.html#loop) | ||
412 | + - [lower](http://aheckmann.github.com/gm/docs.html#lower) | ||
413 | + - [magnify](http://aheckmann.github.com/gm/docs.html#magnify) | ||
414 | + - [map](http://aheckmann.github.com/gm/docs.html#map) | ||
415 | + - [matte](http://aheckmann.github.com/gm/docs.html#matte) | ||
416 | + - [matteColor](http://aheckmann.github.com/gm/docs.html#matteColor) | ||
417 | + - [mask](http://aheckmann.github.com/gm/docs.html#mask) | ||
418 | + - [maximumError](http://aheckmann.github.com/gm/docs.html#maximumError) | ||
419 | + - [median](http://aheckmann.github.com/gm/docs.html#median) | ||
420 | + - [minify](http://aheckmann.github.com/gm/docs.html#minify) | ||
421 | + - [mode](http://aheckmann.github.com/gm/docs.html#mode) | ||
422 | + - [modulate](http://aheckmann.github.com/gm/docs.html#modulate) | ||
423 | + - [monitor](http://aheckmann.github.com/gm/docs.html#monitor) | ||
424 | + - [monochrome](http://aheckmann.github.com/gm/docs.html#monochrome) | ||
425 | + - [morph](http://aheckmann.github.com/gm/docs.html#morph) | ||
426 | + - [mosaic](http://aheckmann.github.com/gm/docs.html#mosaic) | ||
427 | + - [motionBlur](http://aheckmann.github.com/gm/docs.html#motionBlur) | ||
428 | + - [name](http://aheckmann.github.com/gm/docs.html#name) | ||
429 | + - [negative](http://aheckmann.github.com/gm/docs.html#negative) | ||
430 | + - [noise](http://aheckmann.github.com/gm/docs.html#noise) | ||
431 | + - [noop](http://aheckmann.github.com/gm/docs.html#noop) | ||
432 | + - [normalize](http://aheckmann.github.com/gm/docs.html#normalize) | ||
433 | + - [noProfile](http://aheckmann.github.com/gm/docs.html#profile) | ||
434 | + - [opaque](http://aheckmann.github.com/gm/docs.html#opaque) | ||
435 | + - [operator](http://aheckmann.github.com/gm/docs.html#operator) | ||
436 | + - [orderedDither](http://aheckmann.github.com/gm/docs.html#orderedDither) | ||
437 | + - [outputDirectory](http://aheckmann.github.com/gm/docs.html#outputDirectory) | ||
438 | + - [paint](http://aheckmann.github.com/gm/docs.html#paint) | ||
439 | + - [page](http://aheckmann.github.com/gm/docs.html#page) | ||
440 | + - [pause](http://aheckmann.github.com/gm/docs.html#pause) | ||
441 | + - [pen](http://aheckmann.github.com/gm/docs.html#pen) | ||
442 | + - [ping](http://aheckmann.github.com/gm/docs.html#ping) | ||
443 | + - [pointSize](http://aheckmann.github.com/gm/docs.html#pointSize) | ||
444 | + - [preview](http://aheckmann.github.com/gm/docs.html#preview) | ||
445 | + - [process](http://aheckmann.github.com/gm/docs.html#process) | ||
446 | + - [profile](http://aheckmann.github.com/gm/docs.html#profile) | ||
447 | + - [progress](http://aheckmann.github.com/gm/docs.html#progress) | ||
448 | + - [quality](http://aheckmann.github.com/gm/docs.html#quality) | ||
449 | + - [raise](http://aheckmann.github.com/gm/docs.html#raise) | ||
450 | + - [rawSize](http://aheckmann.github.com/gm/docs.html#rawSize) | ||
451 | + - [randomThreshold](http://aheckmann.github.com/gm/docs.html#randomThreshold) | ||
452 | + - [recolor](http://aheckmann.github.com/gm/docs.html#recolor) | ||
453 | + - [redPrimary](http://aheckmann.github.com/gm/docs.html#redPrimary) | ||
454 | + - [region](http://aheckmann.github.com/gm/docs.html#region) | ||
455 | + - [remote](http://aheckmann.github.com/gm/docs.html#remote) | ||
456 | + - [render](http://aheckmann.github.com/gm/docs.html#render) | ||
457 | + - [repage](http://aheckmann.github.com/gm/docs.html#repage) | ||
458 | + - [resample](http://aheckmann.github.com/gm/docs.html#resample) | ||
459 | + - [resize](http://aheckmann.github.com/gm/docs.html#resize) | ||
460 | + - [roll](http://aheckmann.github.com/gm/docs.html#roll) | ||
461 | + - [rotate](http://aheckmann.github.com/gm/docs.html#rotate) | ||
462 | + - [sample](http://aheckmann.github.com/gm/docs.html#sample) | ||
463 | + - [samplingFactor](http://aheckmann.github.com/gm/docs.html#samplingFactor) | ||
464 | + - [scale](http://aheckmann.github.com/gm/docs.html#scale) | ||
465 | + - [scene](http://aheckmann.github.com/gm/docs.html#scene) | ||
466 | + - [scenes](http://aheckmann.github.com/gm/docs.html#scenes) | ||
467 | + - [screen](http://aheckmann.github.com/gm/docs.html#screen) | ||
468 | + - [segment](http://aheckmann.github.com/gm/docs.html#segment) | ||
469 | + - [sepia](http://aheckmann.github.com/gm/docs.html#sepia) | ||
470 | + - [set](http://aheckmann.github.com/gm/docs.html#set) | ||
471 | + - [setFormat](http://aheckmann.github.com/gm/docs.html#setformat) | ||
472 | + - [shade](http://aheckmann.github.com/gm/docs.html#shade) | ||
473 | + - [shadow](http://aheckmann.github.com/gm/docs.html#shadow) | ||
474 | + - [sharedMemory](http://aheckmann.github.com/gm/docs.html#sharedMemory) | ||
475 | + - [sharpen](http://aheckmann.github.com/gm/docs.html#sharpen) | ||
476 | + - [shave](http://aheckmann.github.com/gm/docs.html#shave) | ||
477 | + - [shear](http://aheckmann.github.com/gm/docs.html#shear) | ||
478 | + - [silent](http://aheckmann.github.com/gm/docs.html#silent) | ||
479 | + - [solarize](http://aheckmann.github.com/gm/docs.html#solarize) | ||
480 | + - [snaps](http://aheckmann.github.com/gm/docs.html#snaps) | ||
481 | + - [stegano](http://aheckmann.github.com/gm/docs.html#stegano) | ||
482 | + - [stereo](http://aheckmann.github.com/gm/docs.html#stereo) | ||
483 | + - [strip](http://aheckmann.github.com/gm/docs.html#strip) _imagemagick only_ | ||
484 | + - [spread](http://aheckmann.github.com/gm/docs.html#spread) | ||
485 | + - [swirl](http://aheckmann.github.com/gm/docs.html#swirl) | ||
486 | + - [textFont](http://aheckmann.github.com/gm/docs.html#textFont) | ||
487 | + - [texture](http://aheckmann.github.com/gm/docs.html#texture) | ||
488 | + - [threshold](http://aheckmann.github.com/gm/docs.html#threshold) | ||
489 | + - [thumb](http://aheckmann.github.com/gm/docs.html#thumb) | ||
490 | + - [tile](http://aheckmann.github.com/gm/docs.html#tile) | ||
491 | + - [transform](http://aheckmann.github.com/gm/docs.html#transform) | ||
492 | + - [transparent](http://aheckmann.github.com/gm/docs.html#transparent) | ||
493 | + - [treeDepth](http://aheckmann.github.com/gm/docs.html#treeDepth) | ||
494 | + - [trim](http://aheckmann.github.com/gm/docs.html#trim) | ||
495 | + - [type](http://aheckmann.github.com/gm/docs.html#type) | ||
496 | + - [update](http://aheckmann.github.com/gm/docs.html#update) | ||
497 | + - [units](http://aheckmann.github.com/gm/docs.html#units) | ||
498 | + - [unsharp](http://aheckmann.github.com/gm/docs.html#unsharp) | ||
499 | + - [usePixmap](http://aheckmann.github.com/gm/docs.html#usePixmap) | ||
500 | + - [view](http://aheckmann.github.com/gm/docs.html#view) | ||
501 | + - [virtualPixel](http://aheckmann.github.com/gm/docs.html#virtualPixel) | ||
502 | + - [visual](http://aheckmann.github.com/gm/docs.html#visual) | ||
503 | + - [watermark](http://aheckmann.github.com/gm/docs.html#watermark) | ||
504 | + - [wave](http://aheckmann.github.com/gm/docs.html#wave) | ||
505 | + - [whitePoint](http://aheckmann.github.com/gm/docs.html#whitePoint) | ||
506 | + - [whiteThreshold](http://aheckmann.github.com/gm/docs.html#whiteThreshold) | ||
507 | + - [window](http://aheckmann.github.com/gm/docs.html#window) | ||
508 | + - [windowGroup](http://aheckmann.github.com/gm/docs.html#windowGroup) | ||
509 | + | ||
510 | + - drawing primitives | ||
511 | + - [draw](http://aheckmann.github.com/gm/docs.html#draw) | ||
512 | + - [drawArc](http://aheckmann.github.com/gm/docs.html#drawArc) | ||
513 | + - [drawBezier](http://aheckmann.github.com/gm/docs.html#drawBezier) | ||
514 | + - [drawCircle](http://aheckmann.github.com/gm/docs.html#drawCircle) | ||
515 | + - [drawEllipse](http://aheckmann.github.com/gm/docs.html#drawEllipse) | ||
516 | + - [drawLine](http://aheckmann.github.com/gm/docs.html#drawLine) | ||
517 | + - [drawPoint](http://aheckmann.github.com/gm/docs.html#drawPoint) | ||
518 | + - [drawPolygon](http://aheckmann.github.com/gm/docs.html#drawPolygon) | ||
519 | + - [drawPolyline](http://aheckmann.github.com/gm/docs.html#drawPolyline) | ||
520 | + - [drawRectangle](http://aheckmann.github.com/gm/docs.html#drawRectangle) | ||
521 | + - [drawText](http://aheckmann.github.com/gm/docs.html#drawText) | ||
522 | + - [fill](http://aheckmann.github.com/gm/docs.html#fill) | ||
523 | + - [font](http://aheckmann.github.com/gm/docs.html#font) | ||
524 | + - [fontSize](http://aheckmann.github.com/gm/docs.html#fontSize) | ||
525 | + - [stroke](http://aheckmann.github.com/gm/docs.html#stroke) | ||
526 | + - [strokeWidth](http://aheckmann.github.com/gm/docs.html#strokeWidth) | ||
527 | + - [setDraw](http://aheckmann.github.com/gm/docs.html#setDraw) | ||
528 | + | ||
529 | + - image output | ||
530 | + - **write** - writes the processed image data to the specified filename | ||
531 | + - **stream** - provides a `ReadableStream` with the processed image data | ||
532 | + - **toBuffer** - returns the image as a `Buffer` instead of a stream | ||
533 | + | ||
534 | +##compare | ||
535 | + | ||
536 | +Graphicsmagicks `compare` command is exposed through `gm.compare()`. This allows us to determine if two images can be considered "equal". | ||
537 | + | ||
538 | +Currently `gm.compare` only accepts file paths. | ||
539 | + | ||
540 | + gm.compare(path1, path2 [, options], callback) | ||
541 | + | ||
542 | +```js | ||
543 | +gm.compare('/path/to/image1.jpg', '/path/to/another.png', function (err, isEqual, equality, raw, path1, path2) { | ||
544 | + if (err) return handle(err); | ||
545 | + | ||
546 | + // if the images were considered equal, `isEqual` will be true, otherwise, false. | ||
547 | + console.log('The images were equal: %s', isEqual); | ||
548 | + | ||
549 | + // to see the total equality returned by graphicsmagick we can inspect the `equality` argument. | ||
550 | + console.log('Actual equality: %d', equality); | ||
551 | + | ||
552 | + // inspect the raw output | ||
553 | + console.log(raw); | ||
554 | + | ||
555 | + // print file paths | ||
556 | + console.log(path1, path2); | ||
557 | +}) | ||
558 | +``` | ||
559 | + | ||
560 | +You may wish to pass a custom tolerance threshold to increase or decrease the default level of `0.4`. | ||
561 | + | ||
562 | + | ||
563 | +```js | ||
564 | +gm.compare('/path/to/image1.jpg', '/path/to/another.png', 1.2, function (err, isEqual) { | ||
565 | + ... | ||
566 | +}) | ||
567 | +``` | ||
568 | + | ||
569 | +To output a diff image, pass a configuration object to define the diff options and tolerance. | ||
570 | + | ||
571 | + | ||
572 | +```js | ||
573 | +var options = { | ||
574 | + file: '/path/to/diff.png', | ||
575 | + highlightColor: 'yellow', | ||
576 | + tolerance: 0.02 | ||
577 | +} | ||
578 | +gm.compare('/path/to/image1.jpg', '/path/to/another.png', options, function (err, isEqual, equality, raw) { | ||
579 | + ... | ||
580 | +}) | ||
581 | +``` | ||
582 | + | ||
583 | +##composite | ||
584 | + | ||
585 | +GraphicsMagick supports compositing one image on top of another. This is exposed through `gm.composite()`. Its first argument is an image path with the changes to the base image, and an optional mask image. | ||
586 | + | ||
587 | +Currently, `gm.composite()` only accepts file paths. | ||
588 | + | ||
589 | + gm.composite(other [, mask]) | ||
590 | + | ||
591 | +```js | ||
592 | +gm('/path/to/image.jpg') | ||
593 | +.composite('/path/to/second_image.jpg') | ||
594 | +.geometry('+100+150') | ||
595 | +.write('/path/to/composite.png', function(err) { | ||
596 | + if(!err) console.log("Written composite image."); | ||
597 | +}); | ||
598 | +``` | ||
599 | + | ||
600 | +##montage | ||
601 | + | ||
602 | +GraphicsMagick supports montage for combining images side by side. This is exposed through `gm.montage()`. Its only argument is an image path with the changes to the base image. | ||
603 | + | ||
604 | +Currently, `gm.montage()` only accepts file paths. | ||
605 | + | ||
606 | + gm.montage(other) | ||
607 | + | ||
608 | +```js | ||
609 | +gm('/path/to/image.jpg') | ||
610 | +.montage('/path/to/second_image.jpg') | ||
611 | +.geometry('+100+150') | ||
612 | +.write('/path/to/montage.png', function(err) { | ||
613 | + if(!err) console.log("Written montage image."); | ||
614 | +}); | ||
615 | +``` | ||
616 | + | ||
617 | +## Contributors | ||
618 | +[https://github.com/aheckmann/gm/contributors](https://github.com/aheckmann/gm/contributors) | ||
619 | + | ||
620 | +## Inspiration | ||
621 | +http://github.com/quiiver/magickal-node | ||
622 | + | ||
623 | +## Plugins | ||
624 | +[https://github.com/aheckmann/gm/wiki](https://github.com/aheckmann/gm/wiki) | ||
625 | + | ||
626 | +## License | ||
627 | + | ||
628 | +(The MIT License) | ||
629 | + | ||
630 | +Copyright (c) 2010 [Aaron Heckmann](aaron.heckmann+github@gmail.com) | ||
631 | + | ||
632 | +Permission is hereby granted, free of charge, to any person obtaining | ||
633 | +a copy of this software and associated documentation files (the | ||
634 | +'Software'), to deal in the Software without restriction, including | ||
635 | +without limitation the rights to use, copy, modify, merge, publish, | ||
636 | +distribute, sublicense, and/or sell copies of the Software, and to | ||
637 | +permit persons to whom the Software is furnished to do so, subject to | ||
638 | +the following conditions: | ||
639 | + | ||
640 | +The above copyright notice and this permission notice shall be | ||
641 | +included in all copies or substantial portions of the Software. | ||
642 | + | ||
643 | +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||
644 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
645 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
646 | +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
647 | +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
648 | +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
649 | +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
node_modules/gm/index.js
0 → 100644
1 | + | ||
2 | +/** | ||
3 | + * Module dependencies. | ||
4 | + */ | ||
5 | + | ||
6 | +var Stream = require('stream').Stream; | ||
7 | +var EventEmitter = require('events').EventEmitter; | ||
8 | +var util = require('util'); | ||
9 | + | ||
10 | +util.inherits(gm, EventEmitter); | ||
11 | + | ||
12 | +/** | ||
13 | + * Constructor. | ||
14 | + * | ||
15 | + * @param {String|Number} path - path to img source or ReadableStream or width of img to create | ||
16 | + * @param {Number} [height] - optional filename of ReadableStream or height of img to create | ||
17 | + * @param {String} [color] - optional hex background color of created img | ||
18 | + */ | ||
19 | + | ||
20 | +function gm (source, height, color) { | ||
21 | + var width; | ||
22 | + | ||
23 | + if (!(this instanceof gm)) { | ||
24 | + return new gm(source, height, color); | ||
25 | + } | ||
26 | + | ||
27 | + EventEmitter.call(this); | ||
28 | + | ||
29 | + this._options = {}; | ||
30 | + this.options(this.__proto__._options); | ||
31 | + | ||
32 | + this.data = {}; | ||
33 | + this._in = []; | ||
34 | + this._out = []; | ||
35 | + this._outputFormat = null; | ||
36 | + this._subCommand = 'convert'; | ||
37 | + | ||
38 | + if (source instanceof Stream) { | ||
39 | + this.sourceStream = source; | ||
40 | + source = height || 'unknown.jpg'; | ||
41 | + } else if (Buffer.isBuffer(source)) { | ||
42 | + this.sourceBuffer = source; | ||
43 | + source = height || 'unknown.jpg'; | ||
44 | + } else if (height) { | ||
45 | + // new images | ||
46 | + width = source; | ||
47 | + source = ""; | ||
48 | + | ||
49 | + this.in("-size", width + "x" + height); | ||
50 | + | ||
51 | + if (color) { | ||
52 | + this.in("xc:"+ color); | ||
53 | + } | ||
54 | + } | ||
55 | + | ||
56 | + if (typeof source === "string") { | ||
57 | + // then source is a path | ||
58 | + | ||
59 | + // parse out gif frame brackets from filename | ||
60 | + // since stream doesn't use source path | ||
61 | + // eg. "filename.gif[0]" | ||
62 | + var frames = source.match(/(\[.+\])$/); | ||
63 | + if (frames) { | ||
64 | + this.sourceFrames = source.substr(frames.index, frames[0].length); | ||
65 | + source = source.substr(0, frames.index); | ||
66 | + } | ||
67 | + } | ||
68 | + | ||
69 | + this.source = source; | ||
70 | + | ||
71 | + this.addSrcFormatter(function (src) { | ||
72 | + // must be first source formatter | ||
73 | + | ||
74 | + var inputFromStdin = this.sourceStream || this.sourceBuffer; | ||
75 | + var ret = inputFromStdin ? '-' : this.source; | ||
76 | + | ||
77 | + if (ret && this.sourceFrames) ret += this.sourceFrames; | ||
78 | + | ||
79 | + src.length = 0; | ||
80 | + src[0] = ret; | ||
81 | + }); | ||
82 | +} | ||
83 | + | ||
84 | +/** | ||
85 | + * Subclasses the gm constructor with custom options. | ||
86 | + * | ||
87 | + * @param {options} options | ||
88 | + * @return {gm} the subclasses gm constructor | ||
89 | + */ | ||
90 | + | ||
91 | +var parent = gm; | ||
92 | +gm.subClass = function subClass (options) { | ||
93 | + function gm (source, height, color) { | ||
94 | + if (!(this instanceof parent)) { | ||
95 | + return new gm(source, height, color); | ||
96 | + } | ||
97 | + | ||
98 | + parent.call(this, source, height, color); | ||
99 | + } | ||
100 | + | ||
101 | + gm.prototype.__proto__ = parent.prototype; | ||
102 | + gm.prototype._options = {}; | ||
103 | + gm.prototype.options(options); | ||
104 | + | ||
105 | + return gm; | ||
106 | +} | ||
107 | + | ||
108 | +/** | ||
109 | + * Augment the prototype. | ||
110 | + */ | ||
111 | + | ||
112 | +require("./lib/options")(gm.prototype); | ||
113 | +require("./lib/getters")(gm); | ||
114 | +require("./lib/args")(gm.prototype); | ||
115 | +require("./lib/drawing")(gm.prototype); | ||
116 | +require("./lib/convenience")(gm.prototype); | ||
117 | +require("./lib/command")(gm.prototype); | ||
118 | +require("./lib/compare")(gm.prototype); | ||
119 | +require("./lib/composite")(gm.prototype); | ||
120 | +require("./lib/montage")(gm.prototype); | ||
121 | + | ||
122 | +/** | ||
123 | + * Expose. | ||
124 | + */ | ||
125 | + | ||
126 | +module.exports = exports = gm; | ||
127 | +module.exports.utils = require('./lib/utils'); | ||
128 | +module.exports.compare = require('./lib/compare')(); | ||
129 | +module.exports.version = require('./package.json').version; |
-
请 注册 或 登录 后发表评论