Showing
39 changed files
with
6431 additions
and
1 deletions
app.js
0 → 100644
1 | +var express = require('express'); | ||
2 | +var path = require('path'); | ||
3 | +var favicon = require('serve-favicon'); | ||
4 | +var logger = require('morgan'); | ||
5 | +var cookieParser = require('cookie-parser'); | ||
6 | +var bodyParser = require('body-parser'); | ||
7 | + | ||
8 | +var message = require('./routes/message'); | ||
9 | +var keyboard = require('./routes/keyboard'); | ||
10 | +var app = express(); | ||
11 | + | ||
12 | +// view engine setup | ||
13 | +app.set('views', path.join(__dirname, 'views')); | ||
14 | +app.set('view engine', 'ejs'); | ||
15 | + | ||
16 | +// uncomment after placing your favicon in /public | ||
17 | +//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); | ||
18 | +app.use(logger('dev')); | ||
19 | +app.use(bodyParser.json()); | ||
20 | +app.use(bodyParser.urlencoded({ extended: false })); | ||
21 | +app.use(cookieParser()); | ||
22 | +app.use(express.static(path.join(__dirname, 'public'))); | ||
23 | + | ||
24 | +app.use('/keyboard',keyboard); | ||
25 | +app.use('/message',message); | ||
26 | + | ||
27 | +// catch 404 and forward to error handler | ||
28 | +app.use(function(req, res, next) { | ||
29 | + var err = new Error('Not Found'); | ||
30 | + err.status = 404; | ||
31 | + next(err); | ||
32 | +}); | ||
33 | + | ||
34 | +// error handler | ||
35 | +app.use(function(err, req, res, next) { | ||
36 | + // set locals, only providing error in development | ||
37 | + res.locals.message = err.message; | ||
38 | + res.locals.error = req.app.get('env') === 'development' ? err : {}; | ||
39 | + | ||
40 | + // render the error page | ||
41 | + res.status(err.status || 500); | ||
42 | + res.render('error'); | ||
43 | +}); | ||
44 | + | ||
45 | +module.exports = app; | ||
46 | + |
bin/www
0 → 100755
1 | +#!/usr/bin/env node | ||
2 | + | ||
3 | +/** | ||
4 | + * Module dependencies. | ||
5 | + */ | ||
6 | + | ||
7 | +var app = require('../app'); | ||
8 | +var debug = require('debug')('project:server'); | ||
9 | +var http = require('http'); | ||
10 | + | ||
11 | +/** | ||
12 | + * Get port from environment and store in Express. | ||
13 | + */ | ||
14 | + | ||
15 | +var port = normalizePort(process.env.PORT || '80'); | ||
16 | +app.set('port', port); | ||
17 | + | ||
18 | +/** | ||
19 | + * Create HTTP server. | ||
20 | + */ | ||
21 | + | ||
22 | +var server = http.createServer(app); | ||
23 | + | ||
24 | +/** | ||
25 | + * Listen on provided port, on all network interfaces. | ||
26 | + */ | ||
27 | + | ||
28 | +server.listen(port); | ||
29 | +server.on('error', onError); | ||
30 | +server.on('listening', onListening); | ||
31 | + | ||
32 | +/** | ||
33 | + * Normalize a port into a number, string, or false. | ||
34 | + */ | ||
35 | + | ||
36 | +function normalizePort(val) { | ||
37 | + var port = parseInt(val, 10); | ||
38 | + | ||
39 | + if (isNaN(port)) { | ||
40 | + // named pipe | ||
41 | + return val; | ||
42 | + } | ||
43 | + | ||
44 | + if (port >= 0) { | ||
45 | + // port number | ||
46 | + return port; | ||
47 | + } | ||
48 | + | ||
49 | + return false; | ||
50 | +} | ||
51 | + | ||
52 | +/** | ||
53 | + * Event listener for HTTP server "error" event. | ||
54 | + */ | ||
55 | + | ||
56 | +function onError(error) { | ||
57 | + if (error.syscall !== 'listen') { | ||
58 | + throw error; | ||
59 | + } | ||
60 | + | ||
61 | + var bind = typeof port === 'string' | ||
62 | + ? 'Pipe ' + port | ||
63 | + : 'Port ' + port; | ||
64 | + | ||
65 | + // handle specific listen errors with friendly messages | ||
66 | + switch (error.code) { | ||
67 | + case 'EACCES': | ||
68 | + console.error(bind + ' requires elevated privileges'); | ||
69 | + process.exit(1); | ||
70 | + break; | ||
71 | + case 'EADDRINUSE': | ||
72 | + console.error(bind + ' is already in use'); | ||
73 | + process.exit(1); | ||
74 | + break; | ||
75 | + default: | ||
76 | + throw error; | ||
77 | + } | ||
78 | +} | ||
79 | + | ||
80 | +/** | ||
81 | + * Event listener for HTTP server "listening" event. | ||
82 | + */ | ||
83 | + | ||
84 | +function onListening() { | ||
85 | + var addr = server.address(); | ||
86 | + var bind = typeof addr === 'string' | ||
87 | + ? 'pipe ' + addr | ||
88 | + : 'port ' + addr.port; | ||
89 | + debug('Listening on ' + bind); | ||
90 | +} |
node_modules/basic-auth/HISTORY.md
0 → 100644
1 | +2.0.0 / 2017-09-12 | ||
2 | +================== | ||
3 | + | ||
4 | + * Drop support for Node.js below 0.8 | ||
5 | + * Remove `auth(ctx)` signature -- pass in header or `auth(ctx.req)` | ||
6 | + * Use `safe-buffer` for improved Buffer API | ||
7 | + | ||
8 | +1.1.0 / 2016-11-18 | ||
9 | +================== | ||
10 | + | ||
11 | + * Add `auth.parse` for low-level string parsing | ||
12 | + | ||
13 | +1.0.4 / 2016-05-10 | ||
14 | +================== | ||
15 | + | ||
16 | + * Improve error message when `req` argument is not an object | ||
17 | + * Improve error message when `req` missing `headers` property | ||
18 | + | ||
19 | +1.0.3 / 2015-07-01 | ||
20 | +================== | ||
21 | + | ||
22 | + * Fix regression accepting a Koa context | ||
23 | + | ||
24 | +1.0.2 / 2015-06-12 | ||
25 | +================== | ||
26 | + | ||
27 | + * Improve error message when `req` argument missing | ||
28 | + * perf: enable strict mode | ||
29 | + * perf: hoist regular expression | ||
30 | + * perf: parse with regular expressions | ||
31 | + * perf: remove argument reassignment | ||
32 | + | ||
33 | +1.0.1 / 2015-05-04 | ||
34 | +================== | ||
35 | + | ||
36 | + * Update readme | ||
37 | + | ||
38 | +1.0.0 / 2014-07-01 | ||
39 | +================== | ||
40 | + | ||
41 | + * Support empty password | ||
42 | + * Support empty username | ||
43 | + | ||
44 | +0.0.1 / 2013-11-30 | ||
45 | +================== | ||
46 | + | ||
47 | + * Initial release |
node_modules/basic-auth/LICENSE
0 → 100644
1 | +(The MIT License) | ||
2 | + | ||
3 | +Copyright (c) 2013 TJ Holowaychuk | ||
4 | +Copyright (c) 2014 Jonathan Ong <me@jongleberry.com> | ||
5 | +Copyright (c) 2015-2016 Douglas Christopher Wilson <doug@somethingdoug.com> | ||
6 | + | ||
7 | +Permission is hereby granted, free of charge, to any person obtaining | ||
8 | +a copy of this software and associated documentation files (the | ||
9 | +'Software'), to deal in the Software without restriction, including | ||
10 | +without limitation the rights to use, copy, modify, merge, publish, | ||
11 | +distribute, sublicense, and/or sell copies of the Software, and to | ||
12 | +permit persons to whom the Software is furnished to do so, subject to | ||
13 | +the following conditions: | ||
14 | + | ||
15 | +The above copyright notice and this permission notice shall be | ||
16 | +included in all copies or substantial portions of the Software. | ||
17 | + | ||
18 | +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||
19 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
20 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
21 | +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
22 | +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
23 | +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
24 | +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
node_modules/basic-auth/README.md
0 → 100644
1 | +# basic-auth | ||
2 | + | ||
3 | +[![NPM Version][npm-image]][npm-url] | ||
4 | +[![NPM Downloads][downloads-image]][downloads-url] | ||
5 | +[![Node.js Version][node-version-image]][node-version-url] | ||
6 | +[![Build Status][travis-image]][travis-url] | ||
7 | +[![Test Coverage][coveralls-image]][coveralls-url] | ||
8 | + | ||
9 | +Generic basic auth Authorization header field parser for whatever. | ||
10 | + | ||
11 | +## Installation | ||
12 | + | ||
13 | +This is a [Node.js](https://nodejs.org/en/) module available through the | ||
14 | +[npm registry](https://www.npmjs.com/). Installation is done using the | ||
15 | +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): | ||
16 | + | ||
17 | +``` | ||
18 | +$ npm install basic-auth | ||
19 | +``` | ||
20 | + | ||
21 | +## API | ||
22 | + | ||
23 | +<!-- eslint-disable no-unused-vars --> | ||
24 | + | ||
25 | +```js | ||
26 | +var auth = require('basic-auth') | ||
27 | +``` | ||
28 | + | ||
29 | +### auth(req) | ||
30 | + | ||
31 | +Get the basic auth credentials from the given request. The `Authorization` | ||
32 | +header is parsed and if the header is invalid, `undefined` is returned, | ||
33 | +otherwise an object with `name` and `pass` properties. | ||
34 | + | ||
35 | +### auth.parse(string) | ||
36 | + | ||
37 | +Parse a basic auth authorization header string. This will return an object | ||
38 | +with `name` and `pass` properties, or `undefined` if the string is invalid. | ||
39 | + | ||
40 | +## Example | ||
41 | + | ||
42 | +Pass a Node.js request object to the module export. If parsing fails | ||
43 | +`undefined` is returned, otherwise an object with `.name` and `.pass`. | ||
44 | + | ||
45 | +<!-- eslint-disable no-unused-vars, no-undef --> | ||
46 | + | ||
47 | +```js | ||
48 | +var auth = require('basic-auth') | ||
49 | +var user = auth(req) | ||
50 | +// => { name: 'something', pass: 'whatever' } | ||
51 | +``` | ||
52 | + | ||
53 | +A header string from any other location can also be parsed with | ||
54 | +`auth.parse`, for example a `Proxy-Authorization` header: | ||
55 | + | ||
56 | +<!-- eslint-disable no-unused-vars, no-undef --> | ||
57 | + | ||
58 | +```js | ||
59 | +var auth = require('basic-auth') | ||
60 | +var user = auth.parse(req.getHeader('Proxy-Authorization')) | ||
61 | +``` | ||
62 | + | ||
63 | +### With vanilla node.js http server | ||
64 | + | ||
65 | +```js | ||
66 | +var http = require('http') | ||
67 | +var auth = require('basic-auth') | ||
68 | + | ||
69 | +// Create server | ||
70 | +var server = http.createServer(function (req, res) { | ||
71 | + var credentials = auth(req) | ||
72 | + | ||
73 | + if (!credentials || credentials.name !== 'john' || credentials.pass !== 'secret') { | ||
74 | + res.statusCode = 401 | ||
75 | + res.setHeader('WWW-Authenticate', 'Basic realm="example"') | ||
76 | + res.end('Access denied') | ||
77 | + } else { | ||
78 | + res.end('Access granted') | ||
79 | + } | ||
80 | +}) | ||
81 | + | ||
82 | +// Listen | ||
83 | +server.listen(3000) | ||
84 | +``` | ||
85 | + | ||
86 | +# License | ||
87 | + | ||
88 | +[MIT](LICENSE) | ||
89 | + | ||
90 | +[npm-image]: https://img.shields.io/npm/v/basic-auth.svg | ||
91 | +[npm-url]: https://npmjs.org/package/basic-auth | ||
92 | +[node-version-image]: https://img.shields.io/node/v/basic-auth.svg | ||
93 | +[node-version-url]: https://nodejs.org/en/download | ||
94 | +[travis-image]: https://img.shields.io/travis/jshttp/basic-auth/master.svg | ||
95 | +[travis-url]: https://travis-ci.org/jshttp/basic-auth | ||
96 | +[coveralls-image]: https://img.shields.io/coveralls/jshttp/basic-auth/master.svg | ||
97 | +[coveralls-url]: https://coveralls.io/r/jshttp/basic-auth?branch=master | ||
98 | +[downloads-image]: https://img.shields.io/npm/dm/basic-auth.svg | ||
99 | +[downloads-url]: https://npmjs.org/package/basic-auth |
node_modules/basic-auth/index.js
0 → 100644
1 | +/*! | ||
2 | + * basic-auth | ||
3 | + * Copyright(c) 2013 TJ Holowaychuk | ||
4 | + * Copyright(c) 2014 Jonathan Ong | ||
5 | + * Copyright(c) 2015-2016 Douglas Christopher Wilson | ||
6 | + * MIT Licensed | ||
7 | + */ | ||
8 | + | ||
9 | +'use strict' | ||
10 | + | ||
11 | +/** | ||
12 | + * Module dependencies. | ||
13 | + * @private | ||
14 | + */ | ||
15 | + | ||
16 | +var Buffer = require('safe-buffer').Buffer | ||
17 | + | ||
18 | +/** | ||
19 | + * Module exports. | ||
20 | + * @public | ||
21 | + */ | ||
22 | + | ||
23 | +module.exports = auth | ||
24 | +module.exports.parse = parse | ||
25 | + | ||
26 | +/** | ||
27 | + * RegExp for basic auth credentials | ||
28 | + * | ||
29 | + * credentials = auth-scheme 1*SP token68 | ||
30 | + * auth-scheme = "Basic" ; case insensitive | ||
31 | + * token68 = 1*( ALPHA / DIGIT / "-" / "." / "_" / "~" / "+" / "/" ) *"=" | ||
32 | + * @private | ||
33 | + */ | ||
34 | + | ||
35 | +var CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/ | ||
36 | + | ||
37 | +/** | ||
38 | + * RegExp for basic auth user/pass | ||
39 | + * | ||
40 | + * user-pass = userid ":" password | ||
41 | + * userid = *<TEXT excluding ":"> | ||
42 | + * password = *TEXT | ||
43 | + * @private | ||
44 | + */ | ||
45 | + | ||
46 | +var USER_PASS_REGEXP = /^([^:]*):(.*)$/ | ||
47 | + | ||
48 | +/** | ||
49 | + * Parse the Authorization header field of a request. | ||
50 | + * | ||
51 | + * @param {object} req | ||
52 | + * @return {object} with .name and .pass | ||
53 | + * @public | ||
54 | + */ | ||
55 | + | ||
56 | +function auth (req) { | ||
57 | + if (!req) { | ||
58 | + throw new TypeError('argument req is required') | ||
59 | + } | ||
60 | + | ||
61 | + if (typeof req !== 'object') { | ||
62 | + throw new TypeError('argument req is required to be an object') | ||
63 | + } | ||
64 | + | ||
65 | + // get header | ||
66 | + var header = getAuthorization(req) | ||
67 | + | ||
68 | + // parse header | ||
69 | + return parse(header) | ||
70 | +} | ||
71 | + | ||
72 | +/** | ||
73 | + * Decode base64 string. | ||
74 | + * @private | ||
75 | + */ | ||
76 | + | ||
77 | +function decodeBase64 (str) { | ||
78 | + return Buffer.from(str, 'base64').toString() | ||
79 | +} | ||
80 | + | ||
81 | +/** | ||
82 | + * Get the Authorization header from request object. | ||
83 | + * @private | ||
84 | + */ | ||
85 | + | ||
86 | +function getAuthorization (req) { | ||
87 | + if (!req.headers || typeof req.headers !== 'object') { | ||
88 | + throw new TypeError('argument req is required to have headers property') | ||
89 | + } | ||
90 | + | ||
91 | + return req.headers.authorization | ||
92 | +} | ||
93 | + | ||
94 | +/** | ||
95 | + * Parse basic auth to object. | ||
96 | + * | ||
97 | + * @param {string} string | ||
98 | + * @return {object} | ||
99 | + * @public | ||
100 | + */ | ||
101 | + | ||
102 | +function parse (string) { | ||
103 | + if (typeof string !== 'string') { | ||
104 | + return undefined | ||
105 | + } | ||
106 | + | ||
107 | + // parse header | ||
108 | + var match = CREDENTIALS_REGEXP.exec(string) | ||
109 | + | ||
110 | + if (!match) { | ||
111 | + return undefined | ||
112 | + } | ||
113 | + | ||
114 | + // decode user pass | ||
115 | + var userPass = USER_PASS_REGEXP.exec(decodeBase64(match[1])) | ||
116 | + | ||
117 | + if (!userPass) { | ||
118 | + return undefined | ||
119 | + } | ||
120 | + | ||
121 | + // return credentials object | ||
122 | + return new Credentials(userPass[1], userPass[2]) | ||
123 | +} | ||
124 | + | ||
125 | +/** | ||
126 | + * Object to represent user credentials. | ||
127 | + * @private | ||
128 | + */ | ||
129 | + | ||
130 | +function Credentials (name, pass) { | ||
131 | + this.name = name | ||
132 | + this.pass = pass | ||
133 | +} |
node_modules/basic-auth/package.json
0 → 100644
1 | +{ | ||
2 | + "_from": "basic-auth@~2.0.0", | ||
3 | + "_id": "basic-auth@2.0.0", | ||
4 | + "_inBundle": false, | ||
5 | + "_integrity": "sha1-AV2z81PgLlY3d1X5YnQuiYHnu7o=", | ||
6 | + "_location": "/basic-auth", | ||
7 | + "_phantomChildren": {}, | ||
8 | + "_requested": { | ||
9 | + "type": "range", | ||
10 | + "registry": true, | ||
11 | + "raw": "basic-auth@~2.0.0", | ||
12 | + "name": "basic-auth", | ||
13 | + "escapedName": "basic-auth", | ||
14 | + "rawSpec": "~2.0.0", | ||
15 | + "saveSpec": null, | ||
16 | + "fetchSpec": "~2.0.0" | ||
17 | + }, | ||
18 | + "_requiredBy": [ | ||
19 | + "/morgan" | ||
20 | + ], | ||
21 | + "_resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.0.tgz", | ||
22 | + "_shasum": "015db3f353e02e56377755f962742e8981e7bbba", | ||
23 | + "_spec": "basic-auth@~2.0.0", | ||
24 | + "_where": "/home/ubuntu/OpenSource_Project/node_modules/morgan", | ||
25 | + "bugs": { | ||
26 | + "url": "https://github.com/jshttp/basic-auth/issues" | ||
27 | + }, | ||
28 | + "bundleDependencies": false, | ||
29 | + "dependencies": { | ||
30 | + "safe-buffer": "5.1.1" | ||
31 | + }, | ||
32 | + "deprecated": false, | ||
33 | + "description": "node.js basic auth parser", | ||
34 | + "devDependencies": { | ||
35 | + "eslint": "3.19.0", | ||
36 | + "eslint-config-standard": "10.2.1", | ||
37 | + "eslint-plugin-import": "2.7.0", | ||
38 | + "eslint-plugin-markdown": "1.0.0-beta.6", | ||
39 | + "eslint-plugin-node": "5.1.1", | ||
40 | + "eslint-plugin-promise": "3.5.0", | ||
41 | + "eslint-plugin-standard": "3.0.1", | ||
42 | + "istanbul": "0.4.5", | ||
43 | + "mocha": "2.5.3" | ||
44 | + }, | ||
45 | + "engines": { | ||
46 | + "node": ">= 0.8" | ||
47 | + }, | ||
48 | + "files": [ | ||
49 | + "HISTORY.md", | ||
50 | + "LICENSE", | ||
51 | + "index.js" | ||
52 | + ], | ||
53 | + "homepage": "https://github.com/jshttp/basic-auth#readme", | ||
54 | + "keywords": [ | ||
55 | + "basic", | ||
56 | + "auth", | ||
57 | + "authorization", | ||
58 | + "basicauth" | ||
59 | + ], | ||
60 | + "license": "MIT", | ||
61 | + "name": "basic-auth", | ||
62 | + "repository": { | ||
63 | + "type": "git", | ||
64 | + "url": "git+https://github.com/jshttp/basic-auth.git" | ||
65 | + }, | ||
66 | + "scripts": { | ||
67 | + "lint": "eslint --plugin markdown --ext js,md .", | ||
68 | + "test": "mocha --check-leaks --reporter spec --bail", | ||
69 | + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", | ||
70 | + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" | ||
71 | + }, | ||
72 | + "version": "2.0.0" | ||
73 | +} |
node_modules/cookie-parser/HISTORY.md
0 → 100644
1 | +1.4.3 / 2016-05-26 | ||
2 | +================== | ||
3 | + | ||
4 | + * deps: cookie@0.3.1 | ||
5 | + - perf: use for loop in parse | ||
6 | + | ||
7 | +1.4.2 / 2016-05-20 | ||
8 | +================== | ||
9 | + | ||
10 | + * deps: cookie@0.2.4 | ||
11 | + - perf: enable strict mode | ||
12 | + - perf: use for loop in parse | ||
13 | + - perf: use string concatination for serialization | ||
14 | + | ||
15 | +1.4.1 / 2016-01-11 | ||
16 | +================== | ||
17 | + | ||
18 | + * deps: cookie@0.2.3 | ||
19 | + * perf: enable strict mode | ||
20 | + | ||
21 | +1.4.0 / 2015-09-18 | ||
22 | +================== | ||
23 | + | ||
24 | + * Accept array of secrets in addition to a single secret | ||
25 | + * Fix `JSONCookie` to return `undefined` for non-string arguments | ||
26 | + * Fix `signedCookie` to return `undefined` for non-string arguments | ||
27 | + * deps: cookie@0.2.2 | ||
28 | + | ||
29 | +1.3.5 / 2015-05-19 | ||
30 | +================== | ||
31 | + | ||
32 | + * deps: cookie@0.1.3 | ||
33 | + - Slight optimizations | ||
34 | + | ||
35 | +1.3.4 / 2015-02-15 | ||
36 | +================== | ||
37 | + | ||
38 | + * deps: cookie-signature@1.0.6 | ||
39 | + | ||
40 | +1.3.3 / 2014-09-05 | ||
41 | +================== | ||
42 | + | ||
43 | + * deps: cookie-signature@1.0.5 | ||
44 | + | ||
45 | +1.3.2 / 2014-06-26 | ||
46 | +================== | ||
47 | + | ||
48 | + * deps: cookie-signature@1.0.4 | ||
49 | + - fix for timing attacks | ||
50 | + | ||
51 | +1.3.1 / 2014-06-17 | ||
52 | +================== | ||
53 | + | ||
54 | + * actually export `signedCookie` | ||
55 | + | ||
56 | +1.3.0 / 2014-06-17 | ||
57 | +================== | ||
58 | + | ||
59 | + * add `signedCookie` export for single cookie unsigning | ||
60 | + | ||
61 | +1.2.0 / 2014-06-17 | ||
62 | +================== | ||
63 | + | ||
64 | + * export parsing functions | ||
65 | + * `req.cookies` and `req.signedCookies` are now plain objects | ||
66 | + * slightly faster parsing of many cookies | ||
67 | + | ||
68 | +1.1.0 / 2014-05-12 | ||
69 | +================== | ||
70 | + | ||
71 | + * Support for NodeJS version 0.8 | ||
72 | + * deps: cookie@0.1.2 | ||
73 | + - Fix for maxAge == 0 | ||
74 | + - made compat with expires field | ||
75 | + - tweak maxAge NaN error message | ||
76 | + | ||
77 | +1.0.1 / 2014-02-20 | ||
78 | +================== | ||
79 | + | ||
80 | + * add missing dependencies | ||
81 | + | ||
82 | +1.0.0 / 2014-02-15 | ||
83 | +================== | ||
84 | + | ||
85 | + * Genesis from `connect` |
node_modules/cookie-parser/LICENSE
0 → 100644
1 | +(The MIT License) | ||
2 | + | ||
3 | +Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca> | ||
4 | +Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com> | ||
5 | + | ||
6 | +Permission is hereby granted, free of charge, to any person obtaining | ||
7 | +a copy of this software and associated documentation files (the | ||
8 | +'Software'), to deal in the Software without restriction, including | ||
9 | +without limitation the rights to use, copy, modify, merge, publish, | ||
10 | +distribute, sublicense, and/or sell copies of the Software, and to | ||
11 | +permit persons to whom the Software is furnished to do so, subject to | ||
12 | +the following conditions: | ||
13 | + | ||
14 | +The above copyright notice and this permission notice shall be | ||
15 | +included in all copies or substantial portions of the Software. | ||
16 | + | ||
17 | +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||
18 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
19 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
20 | +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
21 | +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
22 | +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
23 | +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
node_modules/cookie-parser/README.md
0 → 100644
1 | +# cookie-parser | ||
2 | + | ||
3 | +[![NPM Version][npm-image]][npm-url] | ||
4 | +[![NPM Downloads][downloads-image]][downloads-url] | ||
5 | +[![Node.js Version][node-version-image]][node-version-url] | ||
6 | +[![Build Status][travis-image]][travis-url] | ||
7 | +[![Test Coverage][coveralls-image]][coveralls-url] | ||
8 | + | ||
9 | +Parse `Cookie` header and populate `req.cookies` with an object keyed by the cookie | ||
10 | +names. Optionally you may enable signed cookie support by passing a `secret` string, | ||
11 | +which assigns `req.secret` so it may be used by other middleware. | ||
12 | + | ||
13 | +## Installation | ||
14 | + | ||
15 | +```sh | ||
16 | +$ npm install cookie-parser | ||
17 | +``` | ||
18 | + | ||
19 | +## API | ||
20 | + | ||
21 | +```js | ||
22 | +var express = require('express') | ||
23 | +var cookieParser = require('cookie-parser') | ||
24 | + | ||
25 | +var app = express() | ||
26 | +app.use(cookieParser()) | ||
27 | +``` | ||
28 | + | ||
29 | +### cookieParser(secret, options) | ||
30 | + | ||
31 | +- `secret` a string or array used for signing cookies. This is optional and if not specified, will not parse signed cookies. If a string is provided, this is used as the secret. If an array is provided, an attempt will be made to unsign the cookie with each secret in order. | ||
32 | +- `options` an object that is passed to `cookie.parse` as the second option. See [cookie](https://www.npmjs.org/package/cookie) for more information. | ||
33 | + - `decode` a function to decode the value of the cookie | ||
34 | + | ||
35 | +### cookieParser.JSONCookie(str) | ||
36 | + | ||
37 | +Parse a cookie value as a JSON cookie. This will return the parsed JSON value if it was a JSON cookie, otherwise it will return the passed value. | ||
38 | + | ||
39 | +### cookieParser.JSONCookies(cookies) | ||
40 | + | ||
41 | +Given an object, this will iterate over the keys and call `JSONCookie` on each value. This will return the same object passed in. | ||
42 | + | ||
43 | +### cookieParser.signedCookie(str, secret) | ||
44 | + | ||
45 | +Parse a cookie value as a signed cookie. This will return the parsed unsigned value if it was a signed cookie and the signature was valid, otherwise it will return the passed value. | ||
46 | + | ||
47 | +The `secret` argument can be an array or string. If a string is provided, this is used as the secret. If an array is provided, an attempt will be made to unsign the cookie with each secret in order. | ||
48 | + | ||
49 | +### cookieParser.signedCookies(cookies, secret) | ||
50 | + | ||
51 | +Given an object, this will iterate over the keys and check if any value is a signed cookie. If it is a signed cookie and the signature is valid, the key will be deleted from the object and added to the new object that is returned. | ||
52 | + | ||
53 | +The `secret` argument can be an array or string. If a string is provided, this is used as the secret. If an array is provided, an attempt will be made to unsign the cookie with each secret in order. | ||
54 | + | ||
55 | +## Example | ||
56 | + | ||
57 | +```js | ||
58 | +var express = require('express') | ||
59 | +var cookieParser = require('cookie-parser') | ||
60 | + | ||
61 | +var app = express() | ||
62 | +app.use(cookieParser()) | ||
63 | + | ||
64 | +app.get('/', function(req, res) { | ||
65 | + console.log('Cookies: ', req.cookies) | ||
66 | +}) | ||
67 | + | ||
68 | +app.listen(8080) | ||
69 | + | ||
70 | +// curl command that sends an HTTP request with two cookies | ||
71 | +// curl http://127.0.0.1:8080 --cookie "Cho=Kim;Greet=Hello" | ||
72 | +``` | ||
73 | + | ||
74 | +### [MIT Licensed](LICENSE) | ||
75 | + | ||
76 | +[npm-image]: https://img.shields.io/npm/v/cookie-parser.svg | ||
77 | +[npm-url]: https://npmjs.org/package/cookie-parser | ||
78 | +[node-version-image]: https://img.shields.io/node/v/cookie-parser.svg | ||
79 | +[node-version-url]: https://nodejs.org/en/download | ||
80 | +[travis-image]: https://img.shields.io/travis/expressjs/cookie-parser/master.svg | ||
81 | +[travis-url]: https://travis-ci.org/expressjs/cookie-parser | ||
82 | +[coveralls-image]: https://img.shields.io/coveralls/expressjs/cookie-parser/master.svg | ||
83 | +[coveralls-url]: https://coveralls.io/r/expressjs/cookie-parser?branch=master | ||
84 | +[downloads-image]: https://img.shields.io/npm/dm/cookie-parser.svg | ||
85 | +[downloads-url]: https://npmjs.org/package/cookie-parser |
node_modules/cookie-parser/index.js
0 → 100644
1 | +/*! | ||
2 | + * cookie-parser | ||
3 | + * Copyright(c) 2014 TJ Holowaychuk | ||
4 | + * Copyright(c) 2015 Douglas Christopher Wilson | ||
5 | + * MIT Licensed | ||
6 | + */ | ||
7 | + | ||
8 | +'use strict'; | ||
9 | + | ||
10 | +/** | ||
11 | + * Module dependencies. | ||
12 | + * @private | ||
13 | + */ | ||
14 | + | ||
15 | +var cookie = require('cookie'); | ||
16 | +var signature = require('cookie-signature'); | ||
17 | + | ||
18 | +/** | ||
19 | + * Module exports. | ||
20 | + * @public | ||
21 | + */ | ||
22 | + | ||
23 | +module.exports = cookieParser; | ||
24 | +module.exports.JSONCookie = JSONCookie; | ||
25 | +module.exports.JSONCookies = JSONCookies; | ||
26 | +module.exports.signedCookie = signedCookie; | ||
27 | +module.exports.signedCookies = signedCookies; | ||
28 | + | ||
29 | +/** | ||
30 | + * Parse Cookie header and populate `req.cookies` | ||
31 | + * with an object keyed by the cookie names. | ||
32 | + * | ||
33 | + * @param {string|array} [secret] A string (or array of strings) representing cookie signing secret(s). | ||
34 | + * @param {Object} [options] | ||
35 | + * @return {Function} | ||
36 | + * @public | ||
37 | + */ | ||
38 | + | ||
39 | +function cookieParser(secret, options) { | ||
40 | + return function cookieParser(req, res, next) { | ||
41 | + if (req.cookies) { | ||
42 | + return next(); | ||
43 | + } | ||
44 | + | ||
45 | + var cookies = req.headers.cookie; | ||
46 | + var secrets = !secret || Array.isArray(secret) | ||
47 | + ? (secret || []) | ||
48 | + : [secret]; | ||
49 | + | ||
50 | + req.secret = secrets[0]; | ||
51 | + req.cookies = Object.create(null); | ||
52 | + req.signedCookies = Object.create(null); | ||
53 | + | ||
54 | + // no cookies | ||
55 | + if (!cookies) { | ||
56 | + return next(); | ||
57 | + } | ||
58 | + | ||
59 | + req.cookies = cookie.parse(cookies, options); | ||
60 | + | ||
61 | + // parse signed cookies | ||
62 | + if (secrets.length !== 0) { | ||
63 | + req.signedCookies = signedCookies(req.cookies, secrets); | ||
64 | + req.signedCookies = JSONCookies(req.signedCookies); | ||
65 | + } | ||
66 | + | ||
67 | + // parse JSON cookies | ||
68 | + req.cookies = JSONCookies(req.cookies); | ||
69 | + | ||
70 | + next(); | ||
71 | + }; | ||
72 | +} | ||
73 | + | ||
74 | +/** | ||
75 | + * Parse JSON cookie string. | ||
76 | + * | ||
77 | + * @param {String} str | ||
78 | + * @return {Object} Parsed object or undefined if not json cookie | ||
79 | + * @public | ||
80 | + */ | ||
81 | + | ||
82 | +function JSONCookie(str) { | ||
83 | + if (typeof str !== 'string' || str.substr(0, 2) !== 'j:') { | ||
84 | + return undefined; | ||
85 | + } | ||
86 | + | ||
87 | + try { | ||
88 | + return JSON.parse(str.slice(2)); | ||
89 | + } catch (err) { | ||
90 | + return undefined; | ||
91 | + } | ||
92 | +} | ||
93 | + | ||
94 | +/** | ||
95 | + * Parse JSON cookies. | ||
96 | + * | ||
97 | + * @param {Object} obj | ||
98 | + * @return {Object} | ||
99 | + * @public | ||
100 | + */ | ||
101 | + | ||
102 | +function JSONCookies(obj) { | ||
103 | + var cookies = Object.keys(obj); | ||
104 | + var key; | ||
105 | + var val; | ||
106 | + | ||
107 | + for (var i = 0; i < cookies.length; i++) { | ||
108 | + key = cookies[i]; | ||
109 | + val = JSONCookie(obj[key]); | ||
110 | + | ||
111 | + if (val) { | ||
112 | + obj[key] = val; | ||
113 | + } | ||
114 | + } | ||
115 | + | ||
116 | + return obj; | ||
117 | +} | ||
118 | + | ||
119 | +/** | ||
120 | + * Parse a signed cookie string, return the decoded value. | ||
121 | + * | ||
122 | + * @param {String} str signed cookie string | ||
123 | + * @param {string|array} secret | ||
124 | + * @return {String} decoded value | ||
125 | + * @public | ||
126 | + */ | ||
127 | + | ||
128 | +function signedCookie(str, secret) { | ||
129 | + if (typeof str !== 'string') { | ||
130 | + return undefined; | ||
131 | + } | ||
132 | + | ||
133 | + if (str.substr(0, 2) !== 's:') { | ||
134 | + return str; | ||
135 | + } | ||
136 | + | ||
137 | + var secrets = !secret || Array.isArray(secret) | ||
138 | + ? (secret || []) | ||
139 | + : [secret]; | ||
140 | + | ||
141 | + for (var i = 0; i < secrets.length; i++) { | ||
142 | + var val = signature.unsign(str.slice(2), secrets[i]); | ||
143 | + | ||
144 | + if (val !== false) { | ||
145 | + return val; | ||
146 | + } | ||
147 | + } | ||
148 | + | ||
149 | + return false; | ||
150 | +} | ||
151 | + | ||
152 | +/** | ||
153 | + * Parse signed cookies, returning an object containing the decoded key/value | ||
154 | + * pairs, while removing the signed key from obj. | ||
155 | + * | ||
156 | + * @param {Object} obj | ||
157 | + * @param {string|array} secret | ||
158 | + * @return {Object} | ||
159 | + * @public | ||
160 | + */ | ||
161 | + | ||
162 | +function signedCookies(obj, secret) { | ||
163 | + var cookies = Object.keys(obj); | ||
164 | + var dec; | ||
165 | + var key; | ||
166 | + var ret = Object.create(null); | ||
167 | + var val; | ||
168 | + | ||
169 | + for (var i = 0; i < cookies.length; i++) { | ||
170 | + key = cookies[i]; | ||
171 | + val = obj[key]; | ||
172 | + dec = signedCookie(val, secret); | ||
173 | + | ||
174 | + if (val !== dec) { | ||
175 | + ret[key] = dec; | ||
176 | + delete obj[key]; | ||
177 | + } | ||
178 | + } | ||
179 | + | ||
180 | + return ret; | ||
181 | +} |
node_modules/cookie-parser/package.json
0 → 100644
1 | +{ | ||
2 | + "_from": "cookie-parser@~1.4.3", | ||
3 | + "_id": "cookie-parser@1.4.3", | ||
4 | + "_inBundle": false, | ||
5 | + "_integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=", | ||
6 | + "_location": "/cookie-parser", | ||
7 | + "_phantomChildren": {}, | ||
8 | + "_requested": { | ||
9 | + "type": "range", | ||
10 | + "registry": true, | ||
11 | + "raw": "cookie-parser@~1.4.3", | ||
12 | + "name": "cookie-parser", | ||
13 | + "escapedName": "cookie-parser", | ||
14 | + "rawSpec": "~1.4.3", | ||
15 | + "saveSpec": null, | ||
16 | + "fetchSpec": "~1.4.3" | ||
17 | + }, | ||
18 | + "_requiredBy": [ | ||
19 | + "/" | ||
20 | + ], | ||
21 | + "_resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.3.tgz", | ||
22 | + "_shasum": "0fe31fa19d000b95f4aadf1f53fdc2b8a203baa5", | ||
23 | + "_spec": "cookie-parser@~1.4.3", | ||
24 | + "_where": "/home/ubuntu/OpenSource_Project", | ||
25 | + "author": { | ||
26 | + "name": "TJ Holowaychuk", | ||
27 | + "email": "tj@vision-media.ca", | ||
28 | + "url": "http://tjholowaychuk.com" | ||
29 | + }, | ||
30 | + "bugs": { | ||
31 | + "url": "https://github.com/expressjs/cookie-parser/issues" | ||
32 | + }, | ||
33 | + "bundleDependencies": false, | ||
34 | + "contributors": [ | ||
35 | + { | ||
36 | + "name": "Douglas Christopher Wilson", | ||
37 | + "email": "doug@somethingdoug.com" | ||
38 | + } | ||
39 | + ], | ||
40 | + "dependencies": { | ||
41 | + "cookie": "0.3.1", | ||
42 | + "cookie-signature": "1.0.6" | ||
43 | + }, | ||
44 | + "deprecated": false, | ||
45 | + "description": "cookie parsing with signatures", | ||
46 | + "devDependencies": { | ||
47 | + "istanbul": "0.4.3", | ||
48 | + "mocha": "2.5.3", | ||
49 | + "supertest": "1.1.0" | ||
50 | + }, | ||
51 | + "engines": { | ||
52 | + "node": ">= 0.8.0" | ||
53 | + }, | ||
54 | + "files": [ | ||
55 | + "LICENSE", | ||
56 | + "HISTORY.md", | ||
57 | + "index.js" | ||
58 | + ], | ||
59 | + "homepage": "https://github.com/expressjs/cookie-parser#readme", | ||
60 | + "keywords": [ | ||
61 | + "cookie", | ||
62 | + "middleware" | ||
63 | + ], | ||
64 | + "license": "MIT", | ||
65 | + "name": "cookie-parser", | ||
66 | + "repository": { | ||
67 | + "type": "git", | ||
68 | + "url": "git+https://github.com/expressjs/cookie-parser.git" | ||
69 | + }, | ||
70 | + "scripts": { | ||
71 | + "test": "mocha --reporter spec --bail --check-leaks test/", | ||
72 | + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", | ||
73 | + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" | ||
74 | + }, | ||
75 | + "version": "1.4.3" | ||
76 | +} |
node_modules/ejs/Jakefile
0 → 100644
1 | +var fs = require('fs'); | ||
2 | +var execSync = require('child_process').execSync; | ||
3 | +var exec = function (cmd) { | ||
4 | + execSync(cmd, {stdio: 'inherit'}); | ||
5 | +}; | ||
6 | + | ||
7 | +/* global jake, task, desc, publishTask */ | ||
8 | + | ||
9 | +task('build', ['lint', 'clean', 'browserify', 'minify'], function () { | ||
10 | + console.log('Build completed.'); | ||
11 | +}); | ||
12 | + | ||
13 | +desc('Cleans browerified/minified files and package files'); | ||
14 | +task('clean', ['clobber'], function () { | ||
15 | + jake.rmRf('./ejs.js'); | ||
16 | + jake.rmRf('./ejs.min.js'); | ||
17 | + console.log('Cleaned up compiled files.'); | ||
18 | +}); | ||
19 | + | ||
20 | +desc('Lints the source code'); | ||
21 | +task('lint', function () { | ||
22 | + exec('./node_modules/.bin/eslint \"**/*.js\" Jakefile'); | ||
23 | + console.log('Linting completed.'); | ||
24 | +}); | ||
25 | + | ||
26 | +task('browserify', function () { | ||
27 | + exec('./node_modules/browserify/bin/cmd.js --standalone ejs lib/ejs.js > ejs.js'); | ||
28 | + console.log('Browserification completed.'); | ||
29 | +}); | ||
30 | + | ||
31 | +task('minify', function () { | ||
32 | + exec('./node_modules/uglify-js/bin/uglifyjs ejs.js > ejs.min.js'); | ||
33 | + console.log('Minification completed.'); | ||
34 | +}); | ||
35 | + | ||
36 | +task('doc', function (dev) { | ||
37 | + jake.rmRf('out'); | ||
38 | + var p = dev ? '-p' : ''; | ||
39 | + exec('./node_modules/.bin/jsdoc ' + p + ' -c jsdoc.json lib/* docs/jsdoc/*'); | ||
40 | + console.log('Documentation generated.'); | ||
41 | +}); | ||
42 | + | ||
43 | +task('docPublish', ['doc'], function () { | ||
44 | + fs.writeFileSync('out/CNAME', 'api.ejs.co'); | ||
45 | + console.log('Pushing docs to gh-pages...'); | ||
46 | + exec('./node_modules/.bin/git-directory-deploy --directory out/'); | ||
47 | + console.log('Docs published to gh-pages.'); | ||
48 | +}); | ||
49 | + | ||
50 | +task('test', ['lint'], function () { | ||
51 | + exec('./node_modules/.bin/mocha'); | ||
52 | +}); | ||
53 | + | ||
54 | +publishTask('ejs', ['build'], function () { | ||
55 | + this.packageFiles.include([ | ||
56 | + 'Jakefile', | ||
57 | + 'README.md', | ||
58 | + 'LICENSE', | ||
59 | + 'package.json', | ||
60 | + 'ejs.js', | ||
61 | + 'ejs.min.js', | ||
62 | + 'lib/**' | ||
63 | + ]); | ||
64 | +}); | ||
65 | + | ||
66 | +jake.Task.publish.on('complete', function () { | ||
67 | + console.log('Updating hosted docs...'); | ||
68 | + console.log('If this fails, run jake docPublish to re-try.'); | ||
69 | + jake.Task.docPublish.invoke(); | ||
70 | +}); |
node_modules/ejs/LICENSE
0 → 100644
1 | + | ||
2 | + Apache License | ||
3 | + Version 2.0, January 2004 | ||
4 | + http://www.apache.org/licenses/ | ||
5 | + | ||
6 | + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||
7 | + | ||
8 | + 1. Definitions. | ||
9 | + | ||
10 | + "License" shall mean the terms and conditions for use, reproduction, | ||
11 | + and distribution as defined by Sections 1 through 9 of this document. | ||
12 | + | ||
13 | + "Licensor" shall mean the copyright owner or entity authorized by | ||
14 | + the copyright owner that is granting the License. | ||
15 | + | ||
16 | + "Legal Entity" shall mean the union of the acting entity and all | ||
17 | + other entities that control, are controlled by, or are under common | ||
18 | + control with that entity. For the purposes of this definition, | ||
19 | + "control" means (i) the power, direct or indirect, to cause the | ||
20 | + direction or management of such entity, whether by contract or | ||
21 | + otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||
22 | + outstanding shares, or (iii) beneficial ownership of such entity. | ||
23 | + | ||
24 | + "You" (or "Your") shall mean an individual or Legal Entity | ||
25 | + exercising permissions granted by this License. | ||
26 | + | ||
27 | + "Source" form shall mean the preferred form for making modifications, | ||
28 | + including but not limited to software source code, documentation | ||
29 | + source, and configuration files. | ||
30 | + | ||
31 | + "Object" form shall mean any form resulting from mechanical | ||
32 | + transformation or translation of a Source form, including but | ||
33 | + not limited to compiled object code, generated documentation, | ||
34 | + and conversions to other media types. | ||
35 | + | ||
36 | + "Work" shall mean the work of authorship, whether in Source or | ||
37 | + Object form, made available under the License, as indicated by a | ||
38 | + copyright notice that is included in or attached to the work | ||
39 | + (an example is provided in the Appendix below). | ||
40 | + | ||
41 | + "Derivative Works" shall mean any work, whether in Source or Object | ||
42 | + form, that is based on (or derived from) the Work and for which the | ||
43 | + editorial revisions, annotations, elaborations, or other modifications | ||
44 | + represent, as a whole, an original work of authorship. For the purposes | ||
45 | + of this License, Derivative Works shall not include works that remain | ||
46 | + separable from, or merely link (or bind by name) to the interfaces of, | ||
47 | + the Work and Derivative Works thereof. | ||
48 | + | ||
49 | + "Contribution" shall mean any work of authorship, including | ||
50 | + the original version of the Work and any modifications or additions | ||
51 | + to that Work or Derivative Works thereof, that is intentionally | ||
52 | + submitted to Licensor for inclusion in the Work by the copyright owner | ||
53 | + or by an individual or Legal Entity authorized to submit on behalf of | ||
54 | + the copyright owner. For the purposes of this definition, "submitted" | ||
55 | + means any form of electronic, verbal, or written communication sent | ||
56 | + to the Licensor or its representatives, including but not limited to | ||
57 | + communication on electronic mailing lists, source code control systems, | ||
58 | + and issue tracking systems that are managed by, or on behalf of, the | ||
59 | + Licensor for the purpose of discussing and improving the Work, but | ||
60 | + excluding communication that is conspicuously marked or otherwise | ||
61 | + designated in writing by the copyright owner as "Not a Contribution." | ||
62 | + | ||
63 | + "Contributor" shall mean Licensor and any individual or Legal Entity | ||
64 | + on behalf of whom a Contribution has been received by Licensor and | ||
65 | + subsequently incorporated within the Work. | ||
66 | + | ||
67 | + 2. Grant of Copyright License. Subject to the terms and conditions of | ||
68 | + this License, each Contributor hereby grants to You a perpetual, | ||
69 | + worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||
70 | + copyright license to reproduce, prepare Derivative Works of, | ||
71 | + publicly display, publicly perform, sublicense, and distribute the | ||
72 | + Work and such Derivative Works in Source or Object form. | ||
73 | + | ||
74 | + 3. Grant of Patent License. Subject to the terms and conditions of | ||
75 | + this License, each Contributor hereby grants to You a perpetual, | ||
76 | + worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||
77 | + (except as stated in this section) patent license to make, have made, | ||
78 | + use, offer to sell, sell, import, and otherwise transfer the Work, | ||
79 | + where such license applies only to those patent claims licensable | ||
80 | + by such Contributor that are necessarily infringed by their | ||
81 | + Contribution(s) alone or by combination of their Contribution(s) | ||
82 | + with the Work to which such Contribution(s) was submitted. If You | ||
83 | + institute patent litigation against any entity (including a | ||
84 | + cross-claim or counterclaim in a lawsuit) alleging that the Work | ||
85 | + or a Contribution incorporated within the Work constitutes direct | ||
86 | + or contributory patent infringement, then any patent licenses | ||
87 | + granted to You under this License for that Work shall terminate | ||
88 | + as of the date such litigation is filed. | ||
89 | + | ||
90 | + 4. Redistribution. You may reproduce and distribute copies of the | ||
91 | + Work or Derivative Works thereof in any medium, with or without | ||
92 | + modifications, and in Source or Object form, provided that You | ||
93 | + meet the following conditions: | ||
94 | + | ||
95 | + (a) You must give any other recipients of the Work or | ||
96 | + Derivative Works a copy of this License; and | ||
97 | + | ||
98 | + (b) You must cause any modified files to carry prominent notices | ||
99 | + stating that You changed the files; and | ||
100 | + | ||
101 | + (c) You must retain, in the Source form of any Derivative Works | ||
102 | + that You distribute, all copyright, patent, trademark, and | ||
103 | + attribution notices from the Source form of the Work, | ||
104 | + excluding those notices that do not pertain to any part of | ||
105 | + the Derivative Works; and | ||
106 | + | ||
107 | + (d) If the Work includes a "NOTICE" text file as part of its | ||
108 | + distribution, then any Derivative Works that You distribute must | ||
109 | + include a readable copy of the attribution notices contained | ||
110 | + within such NOTICE file, excluding those notices that do not | ||
111 | + pertain to any part of the Derivative Works, in at least one | ||
112 | + of the following places: within a NOTICE text file distributed | ||
113 | + as part of the Derivative Works; within the Source form or | ||
114 | + documentation, if provided along with the Derivative Works; or, | ||
115 | + within a display generated by the Derivative Works, if and | ||
116 | + wherever such third-party notices normally appear. The contents | ||
117 | + of the NOTICE file are for informational purposes only and | ||
118 | + do not modify the License. You may add Your own attribution | ||
119 | + notices within Derivative Works that You distribute, alongside | ||
120 | + or as an addendum to the NOTICE text from the Work, provided | ||
121 | + that such additional attribution notices cannot be construed | ||
122 | + as modifying the License. | ||
123 | + | ||
124 | + You may add Your own copyright statement to Your modifications and | ||
125 | + may provide additional or different license terms and conditions | ||
126 | + for use, reproduction, or distribution of Your modifications, or | ||
127 | + for any such Derivative Works as a whole, provided Your use, | ||
128 | + reproduction, and distribution of the Work otherwise complies with | ||
129 | + the conditions stated in this License. | ||
130 | + | ||
131 | + 5. Submission of Contributions. Unless You explicitly state otherwise, | ||
132 | + any Contribution intentionally submitted for inclusion in the Work | ||
133 | + by You to the Licensor shall be under the terms and conditions of | ||
134 | + this License, without any additional terms or conditions. | ||
135 | + Notwithstanding the above, nothing herein shall supersede or modify | ||
136 | + the terms of any separate license agreement you may have executed | ||
137 | + with Licensor regarding such Contributions. | ||
138 | + | ||
139 | + 6. Trademarks. This License does not grant permission to use the trade | ||
140 | + names, trademarks, service marks, or product names of the Licensor, | ||
141 | + except as required for reasonable and customary use in describing the | ||
142 | + origin of the Work and reproducing the content of the NOTICE file. | ||
143 | + | ||
144 | + 7. Disclaimer of Warranty. Unless required by applicable law or | ||
145 | + agreed to in writing, Licensor provides the Work (and each | ||
146 | + Contributor provides its Contributions) on an "AS IS" BASIS, | ||
147 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||
148 | + implied, including, without limitation, any warranties or conditions | ||
149 | + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||
150 | + PARTICULAR PURPOSE. You are solely responsible for determining the | ||
151 | + appropriateness of using or redistributing the Work and assume any | ||
152 | + risks associated with Your exercise of permissions under this License. | ||
153 | + | ||
154 | + 8. Limitation of Liability. In no event and under no legal theory, | ||
155 | + whether in tort (including negligence), contract, or otherwise, | ||
156 | + unless required by applicable law (such as deliberate and grossly | ||
157 | + negligent acts) or agreed to in writing, shall any Contributor be | ||
158 | + liable to You for damages, including any direct, indirect, special, | ||
159 | + incidental, or consequential damages of any character arising as a | ||
160 | + result of this License or out of the use or inability to use the | ||
161 | + Work (including but not limited to damages for loss of goodwill, | ||
162 | + work stoppage, computer failure or malfunction, or any and all | ||
163 | + other commercial damages or losses), even if such Contributor | ||
164 | + has been advised of the possibility of such damages. | ||
165 | + | ||
166 | + 9. Accepting Warranty or Additional Liability. While redistributing | ||
167 | + the Work or Derivative Works thereof, You may choose to offer, | ||
168 | + and charge a fee for, acceptance of support, warranty, indemnity, | ||
169 | + or other liability obligations and/or rights consistent with this | ||
170 | + License. However, in accepting such obligations, You may act only | ||
171 | + on Your own behalf and on Your sole responsibility, not on behalf | ||
172 | + of any other Contributor, and only if You agree to indemnify, | ||
173 | + defend, and hold each Contributor harmless for any liability | ||
174 | + incurred by, or claims asserted against, such Contributor by reason | ||
175 | + of your accepting any such warranty or additional liability. | ||
176 | + | ||
177 | + END OF TERMS AND CONDITIONS | ||
178 | + | ||
179 | + APPENDIX: How to apply the Apache License to your work. | ||
180 | + | ||
181 | + To apply the Apache License to your work, attach the following | ||
182 | + boilerplate notice, with the fields enclosed by brackets "[]" | ||
183 | + replaced with your own identifying information. (Don't include | ||
184 | + the brackets!) The text should be enclosed in the appropriate | ||
185 | + comment syntax for the file format. We also recommend that a | ||
186 | + file or class name and description of purpose be included on the | ||
187 | + same "printed page" as the copyright notice for easier | ||
188 | + identification within third-party archives. | ||
189 | + | ||
190 | + Copyright [yyyy] [name of copyright owner] | ||
191 | + | ||
192 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
193 | + you may not use this file except in compliance with the License. | ||
194 | + You may obtain a copy of the License at | ||
195 | + | ||
196 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
197 | + | ||
198 | + Unless required by applicable law or agreed to in writing, software | ||
199 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
200 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
201 | + See the License for the specific language governing permissions and | ||
202 | + limitations under the License. |
node_modules/ejs/README.md
0 → 100644
1 | +# EJS | ||
2 | + | ||
3 | +Embedded JavaScript templates | ||
4 | + | ||
5 | +[![Build Status](https://img.shields.io/travis/mde/ejs/master.svg?style=flat)](https://travis-ci.org/mde/ejs) | ||
6 | +[![Developing Dependencies](https://img.shields.io/david/dev/mde/ejs.svg?style=flat)](https://david-dm.org/mde/ejs?type=dev) | ||
7 | +[![Known Vulnerabilities](https://snyk.io/test/npm/ejs/badge.svg?style=flat-square)](https://snyk.io/test/npm/ejs) | ||
8 | + | ||
9 | +## Installation | ||
10 | + | ||
11 | +```bash | ||
12 | +$ npm install ejs | ||
13 | +``` | ||
14 | + | ||
15 | +## Features | ||
16 | + | ||
17 | + * Control flow with `<% %>` | ||
18 | + * Escaped output with `<%= %>` (escape function configurable) | ||
19 | + * Unescaped raw output with `<%- %>` | ||
20 | + * Newline-trim mode ('newline slurping') with `-%>` ending tag | ||
21 | + * Whitespace-trim mode (slurp all whitespace) for control flow with `<%_ _%>` | ||
22 | + * Custom delimiters (e.g., use `<? ?>` instead of `<% %>`) | ||
23 | + * Includes | ||
24 | + * Client-side support | ||
25 | + * Static caching of intermediate JavaScript | ||
26 | + * Static caching of templates | ||
27 | + * Complies with the [Express](http://expressjs.com) view system | ||
28 | + | ||
29 | +## Example | ||
30 | + | ||
31 | +```html | ||
32 | +<% if (user) { %> | ||
33 | + <h2><%= user.name %></h2> | ||
34 | +<% } %> | ||
35 | +``` | ||
36 | + | ||
37 | +Try EJS online at: https://ionicabizau.github.io/ejs-playground/. | ||
38 | + | ||
39 | +## Usage | ||
40 | + | ||
41 | +```javascript | ||
42 | +var template = ejs.compile(str, options); | ||
43 | +template(data); | ||
44 | +// => Rendered HTML string | ||
45 | + | ||
46 | +ejs.render(str, data, options); | ||
47 | +// => Rendered HTML string | ||
48 | + | ||
49 | +ejs.renderFile(filename, data, options, function(err, str){ | ||
50 | + // str => Rendered HTML string | ||
51 | +}); | ||
52 | +``` | ||
53 | + | ||
54 | +It is also possible to use `ejs.render(dataAndOptions);` where you pass | ||
55 | +everything in a single object. In that case, you'll end up with local variables | ||
56 | +for all the passed options. However, be aware that your code could break if we | ||
57 | +add an option with the same name as one of your data object's properties. | ||
58 | +Therefore, we do not recommend using this shortcut. | ||
59 | + | ||
60 | +## Options | ||
61 | + | ||
62 | + - `cache` Compiled functions are cached, requires `filename` | ||
63 | + - `filename` The name of the file being rendered. Not required if you | ||
64 | + are using `renderFile()`. Used by `cache` to key caches, and for includes. | ||
65 | + - `root` Set project root for includes with an absolute path (/file.ejs). | ||
66 | + - `context` Function execution context | ||
67 | + - `compileDebug` When `false` no debug instrumentation is compiled | ||
68 | + - `client` When `true`, compiles a function that can be rendered | ||
69 | + in the browser without needing to load the EJS Runtime | ||
70 | + ([ejs.min.js](https://github.com/mde/ejs/releases/latest)). | ||
71 | + - `delimiter` Character to use with angle brackets for open/close | ||
72 | + - `debug` Output generated function body | ||
73 | + - `strict` When set to `true`, generated function is in strict mode | ||
74 | + - `_with` Whether or not to use `with() {}` constructs. If `false` then the locals will be stored in the `locals` object. Set to `false` in strict mode. | ||
75 | + - `localsName` Name to use for the object storing local variables when not using `with` Defaults to `locals` | ||
76 | + - `rmWhitespace` Remove all safe-to-remove whitespace, including leading | ||
77 | + and trailing whitespace. It also enables a safer version of `-%>` line | ||
78 | + slurping for all scriptlet tags (it does not strip new lines of tags in | ||
79 | + the middle of a line). | ||
80 | + - `escape` The escaping function used with `<%=` construct. It is | ||
81 | + used in rendering and is `.toString()`ed in the generation of client functions. (By default escapes XML). | ||
82 | + | ||
83 | +This project uses [JSDoc](http://usejsdoc.org/). For the full public API | ||
84 | +documentation, clone the repository and run `npm run doc`. This will run JSDoc | ||
85 | +with the proper options and output the documentation to `out/`. If you want | ||
86 | +the both the public & private API docs, run `npm run devdoc` instead. | ||
87 | + | ||
88 | +## Tags | ||
89 | + | ||
90 | + - `<%` 'Scriptlet' tag, for control-flow, no output | ||
91 | + - `<%_` 'Whitespace Slurping' Scriptlet tag, strips all whitespace before it | ||
92 | + - `<%=` Outputs the value into the template (escaped) | ||
93 | + - `<%-` Outputs the unescaped value into the template | ||
94 | + - `<%#` Comment tag, no execution, no output | ||
95 | + - `<%%` Outputs a literal '<%' | ||
96 | + - `%%>` Outputs a literal '%>' | ||
97 | + - `%>` Plain ending tag | ||
98 | + - `-%>` Trim-mode ('newline slurp') tag, trims following newline | ||
99 | + - `_%>` 'Whitespace Slurping' ending tag, removes all whitespace after it | ||
100 | + | ||
101 | +For the full syntax documentation, please see [docs/syntax.md](https://github.com/mde/ejs/blob/master/docs/syntax.md). | ||
102 | + | ||
103 | +## Includes | ||
104 | + | ||
105 | +Includes either have to be an absolute path, or, if not, are assumed as | ||
106 | +relative to the template with the `include` call. For example if you are | ||
107 | +including `./views/user/show.ejs` from `./views/users.ejs` you would | ||
108 | +use `<%- include('user/show') %>`. | ||
109 | + | ||
110 | +You must specify the `filename` option for the template with the `include` | ||
111 | +call unless you are using `renderFile()`. | ||
112 | + | ||
113 | +You'll likely want to use the raw output tag (`<%-`) with your include to avoid | ||
114 | +double-escaping the HTML output. | ||
115 | + | ||
116 | +```html | ||
117 | +<ul> | ||
118 | + <% users.forEach(function(user){ %> | ||
119 | + <%- include('user/show', {user: user}) %> | ||
120 | + <% }); %> | ||
121 | +</ul> | ||
122 | +``` | ||
123 | + | ||
124 | +Includes are inserted at runtime, so you can use variables for the path in the | ||
125 | +`include` call (for example `<%- include(somePath) %>`). Variables in your | ||
126 | +top-level data object are available to all your includes, but local variables | ||
127 | +need to be passed down. | ||
128 | + | ||
129 | +NOTE: Include preprocessor directives (`<% include user/show %>`) are | ||
130 | +still supported. | ||
131 | + | ||
132 | +## Custom delimiters | ||
133 | + | ||
134 | +Custom delimiters can be applied on a per-template basis, or globally: | ||
135 | + | ||
136 | +```javascript | ||
137 | +var ejs = require('ejs'), | ||
138 | + users = ['geddy', 'neil', 'alex']; | ||
139 | + | ||
140 | +// Just one template | ||
141 | +ejs.render('<?= users.join(" | "); ?>', {users: users}, {delimiter: '?'}); | ||
142 | +// => 'geddy | neil | alex' | ||
143 | + | ||
144 | +// Or globally | ||
145 | +ejs.delimiter = '$'; | ||
146 | +ejs.render('<$= users.join(" | "); $>', {users: users}); | ||
147 | +// => 'geddy | neil | alex' | ||
148 | +``` | ||
149 | + | ||
150 | +## Caching | ||
151 | + | ||
152 | +EJS ships with a basic in-process cache for caching the intermediate JavaScript | ||
153 | +functions used to render templates. It's easy to plug in LRU caching using | ||
154 | +Node's `lru-cache` library: | ||
155 | + | ||
156 | +```javascript | ||
157 | +var ejs = require('ejs') | ||
158 | + , LRU = require('lru-cache'); | ||
159 | +ejs.cache = LRU(100); // LRU cache with 100-item limit | ||
160 | +``` | ||
161 | + | ||
162 | +If you want to clear the EJS cache, call `ejs.clearCache`. If you're using the | ||
163 | +LRU cache and need a different limit, simple reset `ejs.cache` to a new instance | ||
164 | +of the LRU. | ||
165 | + | ||
166 | +## Custom FileLoader | ||
167 | + | ||
168 | +The default file loader is `fs.readFileSync`, if you want to customize it, you can set ejs.fileLoader. | ||
169 | + | ||
170 | +```javascript | ||
171 | +var ejs = require('ejs'); | ||
172 | +var myFileLoad = function (filePath) { | ||
173 | + return 'myFileLoad: ' + fs.readFileSync(filePath); | ||
174 | +}; | ||
175 | + | ||
176 | +ejs.fileLoader = myFileLoad; | ||
177 | +``` | ||
178 | + | ||
179 | +With this feature, you can preprocess the template before reading it. | ||
180 | + | ||
181 | +## Layouts | ||
182 | + | ||
183 | +EJS does not specifically support blocks, but layouts can be implemented by | ||
184 | +including headers and footers, like so: | ||
185 | + | ||
186 | + | ||
187 | +```html | ||
188 | +<%- include('header') -%> | ||
189 | +<h1> | ||
190 | + Title | ||
191 | +</h1> | ||
192 | +<p> | ||
193 | + My page | ||
194 | +</p> | ||
195 | +<%- include('footer') -%> | ||
196 | +``` | ||
197 | + | ||
198 | +## Client-side support | ||
199 | + | ||
200 | +Go to the [Latest Release](https://github.com/mde/ejs/releases/latest), download | ||
201 | +`./ejs.js` or `./ejs.min.js`. Alternately, you can compile it yourself by cloning | ||
202 | +the repository and running `jake build` (or `$(npm bin)/jake build` if jake is | ||
203 | +not installed globally). | ||
204 | + | ||
205 | +Include one of these files on your page, and `ejs` should be available globally. | ||
206 | + | ||
207 | +### Example | ||
208 | + | ||
209 | +```html | ||
210 | +<div id="output"></div> | ||
211 | +<script src="ejs.min.js"></script> | ||
212 | +<script> | ||
213 | + var people = ['geddy', 'neil', 'alex'], | ||
214 | + html = ejs.render('<%= people.join(", "); %>', {people: people}); | ||
215 | + // With jQuery: | ||
216 | + $('#output').html(html); | ||
217 | + // Vanilla JS: | ||
218 | + document.getElementById('output').innerHTML = html; | ||
219 | +</script> | ||
220 | +``` | ||
221 | + | ||
222 | +### Caveats | ||
223 | + | ||
224 | +Most of EJS will work as expected; however, there are a few things to note: | ||
225 | + | ||
226 | +1. Obviously, since you do not have access to the filesystem, `ejs.renderFile()` won't work. | ||
227 | +2. For the same reason, `include`s do not work unless you use an `IncludeCallback`. Here is an example: | ||
228 | + ```javascript | ||
229 | + var str = "Hello <%= include('file', {person: 'John'}); %>", | ||
230 | + fn = ejs.compile(str, {client: true}); | ||
231 | + | ||
232 | + fn(data, null, function(path, d){ // IncludeCallback | ||
233 | + // path -> 'file' | ||
234 | + // d -> {person: 'John'} | ||
235 | + // Put your code here | ||
236 | + // Return the contents of file as a string | ||
237 | + }); // returns rendered string | ||
238 | + ``` | ||
239 | + | ||
240 | +## Related projects | ||
241 | + | ||
242 | +There are a number of implementations of EJS: | ||
243 | + | ||
244 | + * TJ's implementation, the v1 of this library: https://github.com/tj/ejs | ||
245 | + * Jupiter Consulting's EJS: http://www.embeddedjs.com/ | ||
246 | + * EJS Embedded JavaScript Framework on Google Code: https://code.google.com/p/embeddedjavascript/ | ||
247 | + * Sam Stephenson's Ruby implementation: https://rubygems.org/gems/ejs | ||
248 | + * Erubis, an ERB implementation which also runs JavaScript: http://www.kuwata-lab.com/erubis/users-guide.04.html#lang-javascript | ||
249 | + | ||
250 | +## License | ||
251 | + | ||
252 | +Licensed under the Apache License, Version 2.0 | ||
253 | +(<http://www.apache.org/licenses/LICENSE-2.0>) | ||
254 | + | ||
255 | +- - - | ||
256 | +EJS Embedded JavaScript templates copyright 2112 | ||
257 | +mde@fleegix.org. |
node_modules/ejs/ejs.js
0 → 100644
1 | +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ejs = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
2 | +/* | ||
3 | + * EJS Embedded JavaScript templates | ||
4 | + * Copyright 2112 Matthew Eernisse (mde@fleegix.org) | ||
5 | + * | ||
6 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
7 | + * you may not use this file except in compliance with the License. | ||
8 | + * You may obtain a copy of the License at | ||
9 | + * | ||
10 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
11 | + * | ||
12 | + * Unless required by applicable law or agreed to in writing, software | ||
13 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
14 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
15 | + * See the License for the specific language governing permissions and | ||
16 | + * limitations under the License. | ||
17 | + * | ||
18 | +*/ | ||
19 | + | ||
20 | +'use strict'; | ||
21 | + | ||
22 | +/** | ||
23 | + * @file Embedded JavaScript templating engine. {@link http://ejs.co} | ||
24 | + * @author Matthew Eernisse <mde@fleegix.org> | ||
25 | + * @author Tiancheng "Timothy" Gu <timothygu99@gmail.com> | ||
26 | + * @project EJS | ||
27 | + * @license {@link http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0} | ||
28 | + */ | ||
29 | + | ||
30 | +/** | ||
31 | + * EJS internal functions. | ||
32 | + * | ||
33 | + * Technically this "module" lies in the same file as {@link module:ejs}, for | ||
34 | + * the sake of organization all the private functions re grouped into this | ||
35 | + * module. | ||
36 | + * | ||
37 | + * @module ejs-internal | ||
38 | + * @private | ||
39 | + */ | ||
40 | + | ||
41 | +/** | ||
42 | + * Embedded JavaScript templating engine. | ||
43 | + * | ||
44 | + * @module ejs | ||
45 | + * @public | ||
46 | + */ | ||
47 | + | ||
48 | +var fs = require('fs'); | ||
49 | +var path = require('path'); | ||
50 | +var utils = require('./utils'); | ||
51 | + | ||
52 | +var scopeOptionWarned = false; | ||
53 | +var _VERSION_STRING = require('../package.json').version; | ||
54 | +var _DEFAULT_DELIMITER = '%'; | ||
55 | +var _DEFAULT_LOCALS_NAME = 'locals'; | ||
56 | +var _NAME = 'ejs'; | ||
57 | +var _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)'; | ||
58 | +var _OPTS = ['delimiter', 'scope', 'context', 'debug', 'compileDebug', | ||
59 | + 'client', '_with', 'rmWhitespace', 'strict', 'filename']; | ||
60 | +// We don't allow 'cache' option to be passed in the data obj | ||
61 | +// for the normal `render` call, but this is where Express puts it | ||
62 | +// so we make an exception for `renderFile` | ||
63 | +var _OPTS_EXPRESS = _OPTS.concat('cache'); | ||
64 | +var _BOM = /^\uFEFF/; | ||
65 | + | ||
66 | +/** | ||
67 | + * EJS template function cache. This can be a LRU object from lru-cache NPM | ||
68 | + * module. By default, it is {@link module:utils.cache}, a simple in-process | ||
69 | + * cache that grows continuously. | ||
70 | + * | ||
71 | + * @type {Cache} | ||
72 | + */ | ||
73 | + | ||
74 | +exports.cache = utils.cache; | ||
75 | + | ||
76 | +/** | ||
77 | + * Custom file loader. Useful for template preprocessing or restricting access | ||
78 | + * to a certain part of the filesystem. | ||
79 | + * | ||
80 | + * @type {fileLoader} | ||
81 | + */ | ||
82 | + | ||
83 | +exports.fileLoader = fs.readFileSync; | ||
84 | + | ||
85 | +/** | ||
86 | + * Name of the object containing the locals. | ||
87 | + * | ||
88 | + * This variable is overridden by {@link Options}`.localsName` if it is not | ||
89 | + * `undefined`. | ||
90 | + * | ||
91 | + * @type {String} | ||
92 | + * @public | ||
93 | + */ | ||
94 | + | ||
95 | +exports.localsName = _DEFAULT_LOCALS_NAME; | ||
96 | + | ||
97 | +/** | ||
98 | + * Get the path to the included file from the parent file path and the | ||
99 | + * specified path. | ||
100 | + * | ||
101 | + * @param {String} name specified path | ||
102 | + * @param {String} filename parent file path | ||
103 | + * @param {Boolean} isDir parent file path whether is directory | ||
104 | + * @return {String} | ||
105 | + */ | ||
106 | +exports.resolveInclude = function(name, filename, isDir) { | ||
107 | + var dirname = path.dirname; | ||
108 | + var extname = path.extname; | ||
109 | + var resolve = path.resolve; | ||
110 | + var includePath = resolve(isDir ? filename : dirname(filename), name); | ||
111 | + var ext = extname(name); | ||
112 | + if (!ext) { | ||
113 | + includePath += '.ejs'; | ||
114 | + } | ||
115 | + return includePath; | ||
116 | +}; | ||
117 | + | ||
118 | +/** | ||
119 | + * Get the path to the included file by Options | ||
120 | + * | ||
121 | + * @param {String} path specified path | ||
122 | + * @param {Options} options compilation options | ||
123 | + * @return {String} | ||
124 | + */ | ||
125 | +function getIncludePath(path, options) { | ||
126 | + var includePath; | ||
127 | + var filePath; | ||
128 | + var views = options.views; | ||
129 | + | ||
130 | + // Abs path | ||
131 | + if (path.charAt(0) == '/') { | ||
132 | + includePath = exports.resolveInclude(path.replace(/^\/*/,''), options.root || '/', true); | ||
133 | + } | ||
134 | + // Relative paths | ||
135 | + else { | ||
136 | + // Look relative to a passed filename first | ||
137 | + if (options.filename) { | ||
138 | + filePath = exports.resolveInclude(path, options.filename); | ||
139 | + if (fs.existsSync(filePath)) { | ||
140 | + includePath = filePath; | ||
141 | + } | ||
142 | + } | ||
143 | + // Then look in any views directories | ||
144 | + if (!includePath) { | ||
145 | + if (Array.isArray(views) && views.some(function (v) { | ||
146 | + filePath = exports.resolveInclude(path, v, true); | ||
147 | + return fs.existsSync(filePath); | ||
148 | + })) { | ||
149 | + includePath = filePath; | ||
150 | + } | ||
151 | + } | ||
152 | + if (!includePath) { | ||
153 | + throw new Error('Could not find include include file.'); | ||
154 | + } | ||
155 | + } | ||
156 | + return includePath; | ||
157 | +} | ||
158 | + | ||
159 | +/** | ||
160 | + * Get the template from a string or a file, either compiled on-the-fly or | ||
161 | + * read from cache (if enabled), and cache the template if needed. | ||
162 | + * | ||
163 | + * If `template` is not set, the file specified in `options.filename` will be | ||
164 | + * read. | ||
165 | + * | ||
166 | + * If `options.cache` is true, this function reads the file from | ||
167 | + * `options.filename` so it must be set prior to calling this function. | ||
168 | + * | ||
169 | + * @memberof module:ejs-internal | ||
170 | + * @param {Options} options compilation options | ||
171 | + * @param {String} [template] template source | ||
172 | + * @return {(TemplateFunction|ClientFunction)} | ||
173 | + * Depending on the value of `options.client`, either type might be returned. | ||
174 | + * @static | ||
175 | + */ | ||
176 | + | ||
177 | +function handleCache(options, template) { | ||
178 | + var func; | ||
179 | + var filename = options.filename; | ||
180 | + var hasTemplate = arguments.length > 1; | ||
181 | + | ||
182 | + if (options.cache) { | ||
183 | + if (!filename) { | ||
184 | + throw new Error('cache option requires a filename'); | ||
185 | + } | ||
186 | + func = exports.cache.get(filename); | ||
187 | + if (func) { | ||
188 | + return func; | ||
189 | + } | ||
190 | + if (!hasTemplate) { | ||
191 | + template = fileLoader(filename).toString().replace(_BOM, ''); | ||
192 | + } | ||
193 | + } | ||
194 | + else if (!hasTemplate) { | ||
195 | + // istanbul ignore if: should not happen at all | ||
196 | + if (!filename) { | ||
197 | + throw new Error('Internal EJS error: no file name or template ' | ||
198 | + + 'provided'); | ||
199 | + } | ||
200 | + template = fileLoader(filename).toString().replace(_BOM, ''); | ||
201 | + } | ||
202 | + func = exports.compile(template, options); | ||
203 | + if (options.cache) { | ||
204 | + exports.cache.set(filename, func); | ||
205 | + } | ||
206 | + return func; | ||
207 | +} | ||
208 | + | ||
209 | +/** | ||
210 | + * Try calling handleCache with the given options and data and call the | ||
211 | + * callback with the result. If an error occurs, call the callback with | ||
212 | + * the error. Used by renderFile(). | ||
213 | + * | ||
214 | + * @memberof module:ejs-internal | ||
215 | + * @param {Options} options compilation options | ||
216 | + * @param {Object} data template data | ||
217 | + * @param {RenderFileCallback} cb callback | ||
218 | + * @static | ||
219 | + */ | ||
220 | + | ||
221 | +function tryHandleCache(options, data, cb) { | ||
222 | + var result; | ||
223 | + try { | ||
224 | + result = handleCache(options)(data); | ||
225 | + } | ||
226 | + catch (err) { | ||
227 | + return cb(err); | ||
228 | + } | ||
229 | + return cb(null, result); | ||
230 | +} | ||
231 | + | ||
232 | +/** | ||
233 | + * fileLoader is independent | ||
234 | + * | ||
235 | + * @param {String} filePath ejs file path. | ||
236 | + * @return {String} The contents of the specified file. | ||
237 | + * @static | ||
238 | + */ | ||
239 | + | ||
240 | +function fileLoader(filePath){ | ||
241 | + return exports.fileLoader(filePath); | ||
242 | +} | ||
243 | + | ||
244 | +/** | ||
245 | + * Get the template function. | ||
246 | + * | ||
247 | + * If `options.cache` is `true`, then the template is cached. | ||
248 | + * | ||
249 | + * @memberof module:ejs-internal | ||
250 | + * @param {String} path path for the specified file | ||
251 | + * @param {Options} options compilation options | ||
252 | + * @return {(TemplateFunction|ClientFunction)} | ||
253 | + * Depending on the value of `options.client`, either type might be returned | ||
254 | + * @static | ||
255 | + */ | ||
256 | + | ||
257 | +function includeFile(path, options) { | ||
258 | + var opts = utils.shallowCopy({}, options); | ||
259 | + opts.filename = getIncludePath(path, opts); | ||
260 | + return handleCache(opts); | ||
261 | +} | ||
262 | + | ||
263 | +/** | ||
264 | + * Get the JavaScript source of an included file. | ||
265 | + * | ||
266 | + * @memberof module:ejs-internal | ||
267 | + * @param {String} path path for the specified file | ||
268 | + * @param {Options} options compilation options | ||
269 | + * @return {Object} | ||
270 | + * @static | ||
271 | + */ | ||
272 | + | ||
273 | +function includeSource(path, options) { | ||
274 | + var opts = utils.shallowCopy({}, options); | ||
275 | + var includePath; | ||
276 | + var template; | ||
277 | + includePath = getIncludePath(path, opts); | ||
278 | + template = fileLoader(includePath).toString().replace(_BOM, ''); | ||
279 | + opts.filename = includePath; | ||
280 | + var templ = new Template(template, opts); | ||
281 | + templ.generateSource(); | ||
282 | + return { | ||
283 | + source: templ.source, | ||
284 | + filename: includePath, | ||
285 | + template: template | ||
286 | + }; | ||
287 | +} | ||
288 | + | ||
289 | +/** | ||
290 | + * Re-throw the given `err` in context to the `str` of ejs, `filename`, and | ||
291 | + * `lineno`. | ||
292 | + * | ||
293 | + * @implements RethrowCallback | ||
294 | + * @memberof module:ejs-internal | ||
295 | + * @param {Error} err Error object | ||
296 | + * @param {String} str EJS source | ||
297 | + * @param {String} filename file name of the EJS file | ||
298 | + * @param {String} lineno line number of the error | ||
299 | + * @static | ||
300 | + */ | ||
301 | + | ||
302 | +function rethrow(err, str, flnm, lineno, esc){ | ||
303 | + var lines = str.split('\n'); | ||
304 | + var start = Math.max(lineno - 3, 0); | ||
305 | + var end = Math.min(lines.length, lineno + 3); | ||
306 | + var filename = esc(flnm); // eslint-disable-line | ||
307 | + // Error context | ||
308 | + var context = lines.slice(start, end).map(function (line, i){ | ||
309 | + var curr = i + start + 1; | ||
310 | + return (curr == lineno ? ' >> ' : ' ') | ||
311 | + + curr | ||
312 | + + '| ' | ||
313 | + + line; | ||
314 | + }).join('\n'); | ||
315 | + | ||
316 | + // Alter exception message | ||
317 | + err.path = filename; | ||
318 | + err.message = (filename || 'ejs') + ':' | ||
319 | + + lineno + '\n' | ||
320 | + + context + '\n\n' | ||
321 | + + err.message; | ||
322 | + | ||
323 | + throw err; | ||
324 | +} | ||
325 | + | ||
326 | +function stripSemi(str){ | ||
327 | + return str.replace(/;(\s*$)/, '$1'); | ||
328 | +} | ||
329 | + | ||
330 | +/** | ||
331 | + * Compile the given `str` of ejs into a template function. | ||
332 | + * | ||
333 | + * @param {String} template EJS template | ||
334 | + * | ||
335 | + * @param {Options} opts compilation options | ||
336 | + * | ||
337 | + * @return {(TemplateFunction|ClientFunction)} | ||
338 | + * Depending on the value of `opts.client`, either type might be returned. | ||
339 | + * @public | ||
340 | + */ | ||
341 | + | ||
342 | +exports.compile = function compile(template, opts) { | ||
343 | + var templ; | ||
344 | + | ||
345 | + // v1 compat | ||
346 | + // 'scope' is 'context' | ||
347 | + // FIXME: Remove this in a future version | ||
348 | + if (opts && opts.scope) { | ||
349 | + if (!scopeOptionWarned){ | ||
350 | + console.warn('`scope` option is deprecated and will be removed in EJS 3'); | ||
351 | + scopeOptionWarned = true; | ||
352 | + } | ||
353 | + if (!opts.context) { | ||
354 | + opts.context = opts.scope; | ||
355 | + } | ||
356 | + delete opts.scope; | ||
357 | + } | ||
358 | + templ = new Template(template, opts); | ||
359 | + return templ.compile(); | ||
360 | +}; | ||
361 | + | ||
362 | +/** | ||
363 | + * Render the given `template` of ejs. | ||
364 | + * | ||
365 | + * If you would like to include options but not data, you need to explicitly | ||
366 | + * call this function with `data` being an empty object or `null`. | ||
367 | + * | ||
368 | + * @param {String} template EJS template | ||
369 | + * @param {Object} [data={}] template data | ||
370 | + * @param {Options} [opts={}] compilation and rendering options | ||
371 | + * @return {String} | ||
372 | + * @public | ||
373 | + */ | ||
374 | + | ||
375 | +exports.render = function (template, d, o) { | ||
376 | + var data = d || {}; | ||
377 | + var opts = o || {}; | ||
378 | + | ||
379 | + // No options object -- if there are optiony names | ||
380 | + // in the data, copy them to options | ||
381 | + if (arguments.length == 2) { | ||
382 | + utils.shallowCopyFromList(opts, data, _OPTS); | ||
383 | + } | ||
384 | + | ||
385 | + return handleCache(opts, template)(data); | ||
386 | +}; | ||
387 | + | ||
388 | +/** | ||
389 | + * Render an EJS file at the given `path` and callback `cb(err, str)`. | ||
390 | + * | ||
391 | + * If you would like to include options but not data, you need to explicitly | ||
392 | + * call this function with `data` being an empty object or `null`. | ||
393 | + * | ||
394 | + * @param {String} path path to the EJS file | ||
395 | + * @param {Object} [data={}] template data | ||
396 | + * @param {Options} [opts={}] compilation and rendering options | ||
397 | + * @param {RenderFileCallback} cb callback | ||
398 | + * @public | ||
399 | + */ | ||
400 | + | ||
401 | +exports.renderFile = function () { | ||
402 | + var filename = arguments[0]; | ||
403 | + var cb = arguments[arguments.length - 1]; | ||
404 | + var opts = {filename: filename}; | ||
405 | + var data; | ||
406 | + | ||
407 | + if (arguments.length > 2) { | ||
408 | + data = arguments[1]; | ||
409 | + | ||
410 | + // No options object -- if there are optiony names | ||
411 | + // in the data, copy them to options | ||
412 | + if (arguments.length === 3) { | ||
413 | + // Express 4 | ||
414 | + if (data.settings) { | ||
415 | + if (data.settings['view options']) { | ||
416 | + utils.shallowCopyFromList(opts, data.settings['view options'], _OPTS_EXPRESS); | ||
417 | + } | ||
418 | + if (data.settings.views) { | ||
419 | + opts.views = data.settings.views; | ||
420 | + } | ||
421 | + } | ||
422 | + // Express 3 and lower | ||
423 | + else { | ||
424 | + utils.shallowCopyFromList(opts, data, _OPTS_EXPRESS); | ||
425 | + } | ||
426 | + } | ||
427 | + else { | ||
428 | + // Use shallowCopy so we don't pollute passed in opts obj with new vals | ||
429 | + utils.shallowCopy(opts, arguments[2]); | ||
430 | + } | ||
431 | + | ||
432 | + opts.filename = filename; | ||
433 | + } | ||
434 | + else { | ||
435 | + data = {}; | ||
436 | + } | ||
437 | + | ||
438 | + return tryHandleCache(opts, data, cb); | ||
439 | +}; | ||
440 | + | ||
441 | +/** | ||
442 | + * Clear intermediate JavaScript cache. Calls {@link Cache#reset}. | ||
443 | + * @public | ||
444 | + */ | ||
445 | + | ||
446 | +exports.clearCache = function () { | ||
447 | + exports.cache.reset(); | ||
448 | +}; | ||
449 | + | ||
450 | +function Template(text, opts) { | ||
451 | + opts = opts || {}; | ||
452 | + var options = {}; | ||
453 | + this.templateText = text; | ||
454 | + this.mode = null; | ||
455 | + this.truncate = false; | ||
456 | + this.currentLine = 1; | ||
457 | + this.source = ''; | ||
458 | + this.dependencies = []; | ||
459 | + options.client = opts.client || false; | ||
460 | + options.escapeFunction = opts.escape || utils.escapeXML; | ||
461 | + options.compileDebug = opts.compileDebug !== false; | ||
462 | + options.debug = !!opts.debug; | ||
463 | + options.filename = opts.filename; | ||
464 | + options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER; | ||
465 | + options.strict = opts.strict || false; | ||
466 | + options.context = opts.context; | ||
467 | + options.cache = opts.cache || false; | ||
468 | + options.rmWhitespace = opts.rmWhitespace; | ||
469 | + options.root = opts.root; | ||
470 | + options.localsName = opts.localsName || exports.localsName || _DEFAULT_LOCALS_NAME; | ||
471 | + options.views = opts.views; | ||
472 | + | ||
473 | + if (options.strict) { | ||
474 | + options._with = false; | ||
475 | + } | ||
476 | + else { | ||
477 | + options._with = typeof opts._with != 'undefined' ? opts._with : true; | ||
478 | + } | ||
479 | + | ||
480 | + this.opts = options; | ||
481 | + | ||
482 | + this.regex = this.createRegex(); | ||
483 | +} | ||
484 | + | ||
485 | +Template.modes = { | ||
486 | + EVAL: 'eval', | ||
487 | + ESCAPED: 'escaped', | ||
488 | + RAW: 'raw', | ||
489 | + COMMENT: 'comment', | ||
490 | + LITERAL: 'literal' | ||
491 | +}; | ||
492 | + | ||
493 | +Template.prototype = { | ||
494 | + createRegex: function () { | ||
495 | + var str = _REGEX_STRING; | ||
496 | + var delim = utils.escapeRegExpChars(this.opts.delimiter); | ||
497 | + str = str.replace(/%/g, delim); | ||
498 | + return new RegExp(str); | ||
499 | + }, | ||
500 | + | ||
501 | + compile: function () { | ||
502 | + var src; | ||
503 | + var fn; | ||
504 | + var opts = this.opts; | ||
505 | + var prepended = ''; | ||
506 | + var appended = ''; | ||
507 | + var escapeFn = opts.escapeFunction; | ||
508 | + | ||
509 | + if (!this.source) { | ||
510 | + this.generateSource(); | ||
511 | + prepended += ' var __output = [], __append = __output.push.bind(__output);' + '\n'; | ||
512 | + if (opts._with !== false) { | ||
513 | + prepended += ' with (' + opts.localsName + ' || {}) {' + '\n'; | ||
514 | + appended += ' }' + '\n'; | ||
515 | + } | ||
516 | + appended += ' return __output.join("");' + '\n'; | ||
517 | + this.source = prepended + this.source + appended; | ||
518 | + } | ||
519 | + | ||
520 | + if (opts.compileDebug) { | ||
521 | + src = 'var __line = 1' + '\n' | ||
522 | + + ' , __lines = ' + JSON.stringify(this.templateText) + '\n' | ||
523 | + + ' , __filename = ' + (opts.filename ? | ||
524 | + JSON.stringify(opts.filename) : 'undefined') + ';' + '\n' | ||
525 | + + 'try {' + '\n' | ||
526 | + + this.source | ||
527 | + + '} catch (e) {' + '\n' | ||
528 | + + ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\n' | ||
529 | + + '}' + '\n'; | ||
530 | + } | ||
531 | + else { | ||
532 | + src = this.source; | ||
533 | + } | ||
534 | + | ||
535 | + if (opts.client) { | ||
536 | + src = 'escapeFn = escapeFn || ' + escapeFn.toString() + ';' + '\n' + src; | ||
537 | + if (opts.compileDebug) { | ||
538 | + src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\n' + src; | ||
539 | + } | ||
540 | + } | ||
541 | + | ||
542 | + if (opts.strict) { | ||
543 | + src = '"use strict";\n' + src; | ||
544 | + } | ||
545 | + if (opts.debug) { | ||
546 | + console.log(src); | ||
547 | + } | ||
548 | + | ||
549 | + try { | ||
550 | + fn = new Function(opts.localsName + ', escapeFn, include, rethrow', src); | ||
551 | + } | ||
552 | + catch(e) { | ||
553 | + // istanbul ignore else | ||
554 | + if (e instanceof SyntaxError) { | ||
555 | + if (opts.filename) { | ||
556 | + e.message += ' in ' + opts.filename; | ||
557 | + } | ||
558 | + e.message += ' while compiling ejs\n\n'; | ||
559 | + e.message += 'If the above error is not helpful, you may want to try EJS-Lint:\n'; | ||
560 | + e.message += 'https://github.com/RyanZim/EJS-Lint'; | ||
561 | + } | ||
562 | + throw e; | ||
563 | + } | ||
564 | + | ||
565 | + if (opts.client) { | ||
566 | + fn.dependencies = this.dependencies; | ||
567 | + return fn; | ||
568 | + } | ||
569 | + | ||
570 | + // Return a callable function which will execute the function | ||
571 | + // created by the source-code, with the passed data as locals | ||
572 | + // Adds a local `include` function which allows full recursive include | ||
573 | + var returnedFn = function (data) { | ||
574 | + var include = function (path, includeData) { | ||
575 | + var d = utils.shallowCopy({}, data); | ||
576 | + if (includeData) { | ||
577 | + d = utils.shallowCopy(d, includeData); | ||
578 | + } | ||
579 | + return includeFile(path, opts)(d); | ||
580 | + }; | ||
581 | + return fn.apply(opts.context, [data || {}, escapeFn, include, rethrow]); | ||
582 | + }; | ||
583 | + returnedFn.dependencies = this.dependencies; | ||
584 | + return returnedFn; | ||
585 | + }, | ||
586 | + | ||
587 | + generateSource: function () { | ||
588 | + var opts = this.opts; | ||
589 | + | ||
590 | + if (opts.rmWhitespace) { | ||
591 | + // Have to use two separate replace here as `^` and `$` operators don't | ||
592 | + // work well with `\r`. | ||
593 | + this.templateText = | ||
594 | + this.templateText.replace(/\r/g, '').replace(/^\s+|\s+$/gm, ''); | ||
595 | + } | ||
596 | + | ||
597 | + // Slurp spaces and tabs before <%_ and after _%> | ||
598 | + this.templateText = | ||
599 | + this.templateText.replace(/[ \t]*<%_/gm, '<%_').replace(/_%>[ \t]*/gm, '_%>'); | ||
600 | + | ||
601 | + var self = this; | ||
602 | + var matches = this.parseTemplateText(); | ||
603 | + var d = this.opts.delimiter; | ||
604 | + | ||
605 | + if (matches && matches.length) { | ||
606 | + matches.forEach(function (line, index) { | ||
607 | + var opening; | ||
608 | + var closing; | ||
609 | + var include; | ||
610 | + var includeOpts; | ||
611 | + var includeObj; | ||
612 | + var includeSrc; | ||
613 | + // If this is an opening tag, check for closing tags | ||
614 | + // FIXME: May end up with some false positives here | ||
615 | + // Better to store modes as k/v with '<' + delimiter as key | ||
616 | + // Then this can simply check against the map | ||
617 | + if ( line.indexOf('<' + d) === 0 // If it is a tag | ||
618 | + && line.indexOf('<' + d + d) !== 0) { // and is not escaped | ||
619 | + closing = matches[index + 2]; | ||
620 | + if (!(closing == d + '>' || closing == '-' + d + '>' || closing == '_' + d + '>')) { | ||
621 | + throw new Error('Could not find matching close tag for "' + line + '".'); | ||
622 | + } | ||
623 | + } | ||
624 | + // HACK: backward-compat `include` preprocessor directives | ||
625 | + if ((include = line.match(/^\s*include\s+(\S+)/))) { | ||
626 | + opening = matches[index - 1]; | ||
627 | + // Must be in EVAL or RAW mode | ||
628 | + if (opening && (opening == '<' + d || opening == '<' + d + '-' || opening == '<' + d + '_')) { | ||
629 | + includeOpts = utils.shallowCopy({}, self.opts); | ||
630 | + includeObj = includeSource(include[1], includeOpts); | ||
631 | + if (self.opts.compileDebug) { | ||
632 | + includeSrc = | ||
633 | + ' ; (function(){' + '\n' | ||
634 | + + ' var __line = 1' + '\n' | ||
635 | + + ' , __lines = ' + JSON.stringify(includeObj.template) + '\n' | ||
636 | + + ' , __filename = ' + JSON.stringify(includeObj.filename) + ';' + '\n' | ||
637 | + + ' try {' + '\n' | ||
638 | + + includeObj.source | ||
639 | + + ' } catch (e) {' + '\n' | ||
640 | + + ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\n' | ||
641 | + + ' }' + '\n' | ||
642 | + + ' ; }).call(this)' + '\n'; | ||
643 | + }else{ | ||
644 | + includeSrc = ' ; (function(){' + '\n' + includeObj.source + | ||
645 | + ' ; }).call(this)' + '\n'; | ||
646 | + } | ||
647 | + self.source += includeSrc; | ||
648 | + self.dependencies.push(exports.resolveInclude(include[1], | ||
649 | + includeOpts.filename)); | ||
650 | + return; | ||
651 | + } | ||
652 | + } | ||
653 | + self.scanLine(line); | ||
654 | + }); | ||
655 | + } | ||
656 | + | ||
657 | + }, | ||
658 | + | ||
659 | + parseTemplateText: function () { | ||
660 | + var str = this.templateText; | ||
661 | + var pat = this.regex; | ||
662 | + var result = pat.exec(str); | ||
663 | + var arr = []; | ||
664 | + var firstPos; | ||
665 | + | ||
666 | + while (result) { | ||
667 | + firstPos = result.index; | ||
668 | + | ||
669 | + if (firstPos !== 0) { | ||
670 | + arr.push(str.substring(0, firstPos)); | ||
671 | + str = str.slice(firstPos); | ||
672 | + } | ||
673 | + | ||
674 | + arr.push(result[0]); | ||
675 | + str = str.slice(result[0].length); | ||
676 | + result = pat.exec(str); | ||
677 | + } | ||
678 | + | ||
679 | + if (str) { | ||
680 | + arr.push(str); | ||
681 | + } | ||
682 | + | ||
683 | + return arr; | ||
684 | + }, | ||
685 | + | ||
686 | + _addOutput: function (line) { | ||
687 | + if (this.truncate) { | ||
688 | + // Only replace single leading linebreak in the line after | ||
689 | + // -%> tag -- this is the single, trailing linebreak | ||
690 | + // after the tag that the truncation mode replaces | ||
691 | + // Handle Win / Unix / old Mac linebreaks -- do the \r\n | ||
692 | + // combo first in the regex-or | ||
693 | + line = line.replace(/^(?:\r\n|\r|\n)/, ''); | ||
694 | + this.truncate = false; | ||
695 | + } | ||
696 | + else if (this.opts.rmWhitespace) { | ||
697 | + // rmWhitespace has already removed trailing spaces, just need | ||
698 | + // to remove linebreaks | ||
699 | + line = line.replace(/^\n/, ''); | ||
700 | + } | ||
701 | + if (!line) { | ||
702 | + return line; | ||
703 | + } | ||
704 | + | ||
705 | + // Preserve literal slashes | ||
706 | + line = line.replace(/\\/g, '\\\\'); | ||
707 | + | ||
708 | + // Convert linebreaks | ||
709 | + line = line.replace(/\n/g, '\\n'); | ||
710 | + line = line.replace(/\r/g, '\\r'); | ||
711 | + | ||
712 | + // Escape double-quotes | ||
713 | + // - this will be the delimiter during execution | ||
714 | + line = line.replace(/"/g, '\\"'); | ||
715 | + this.source += ' ; __append("' + line + '")' + '\n'; | ||
716 | + }, | ||
717 | + | ||
718 | + scanLine: function (line) { | ||
719 | + var self = this; | ||
720 | + var d = this.opts.delimiter; | ||
721 | + var newLineCount = 0; | ||
722 | + | ||
723 | + newLineCount = (line.split('\n').length - 1); | ||
724 | + | ||
725 | + switch (line) { | ||
726 | + case '<' + d: | ||
727 | + case '<' + d + '_': | ||
728 | + this.mode = Template.modes.EVAL; | ||
729 | + break; | ||
730 | + case '<' + d + '=': | ||
731 | + this.mode = Template.modes.ESCAPED; | ||
732 | + break; | ||
733 | + case '<' + d + '-': | ||
734 | + this.mode = Template.modes.RAW; | ||
735 | + break; | ||
736 | + case '<' + d + '#': | ||
737 | + this.mode = Template.modes.COMMENT; | ||
738 | + break; | ||
739 | + case '<' + d + d: | ||
740 | + this.mode = Template.modes.LITERAL; | ||
741 | + this.source += ' ; __append("' + line.replace('<' + d + d, '<' + d) + '")' + '\n'; | ||
742 | + break; | ||
743 | + case d + d + '>': | ||
744 | + this.mode = Template.modes.LITERAL; | ||
745 | + this.source += ' ; __append("' + line.replace(d + d + '>', d + '>') + '")' + '\n'; | ||
746 | + break; | ||
747 | + case d + '>': | ||
748 | + case '-' + d + '>': | ||
749 | + case '_' + d + '>': | ||
750 | + if (this.mode == Template.modes.LITERAL) { | ||
751 | + this._addOutput(line); | ||
752 | + } | ||
753 | + | ||
754 | + this.mode = null; | ||
755 | + this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0; | ||
756 | + break; | ||
757 | + default: | ||
758 | + // In script mode, depends on type of tag | ||
759 | + if (this.mode) { | ||
760 | + // If '//' is found without a line break, add a line break. | ||
761 | + switch (this.mode) { | ||
762 | + case Template.modes.EVAL: | ||
763 | + case Template.modes.ESCAPED: | ||
764 | + case Template.modes.RAW: | ||
765 | + if (line.lastIndexOf('//') > line.lastIndexOf('\n')) { | ||
766 | + line += '\n'; | ||
767 | + } | ||
768 | + } | ||
769 | + switch (this.mode) { | ||
770 | + // Just executing code | ||
771 | + case Template.modes.EVAL: | ||
772 | + this.source += ' ; ' + line + '\n'; | ||
773 | + break; | ||
774 | + // Exec, esc, and output | ||
775 | + case Template.modes.ESCAPED: | ||
776 | + this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\n'; | ||
777 | + break; | ||
778 | + // Exec and output | ||
779 | + case Template.modes.RAW: | ||
780 | + this.source += ' ; __append(' + stripSemi(line) + ')' + '\n'; | ||
781 | + break; | ||
782 | + case Template.modes.COMMENT: | ||
783 | + // Do nothing | ||
784 | + break; | ||
785 | + // Literal <%% mode, append as raw output | ||
786 | + case Template.modes.LITERAL: | ||
787 | + this._addOutput(line); | ||
788 | + break; | ||
789 | + } | ||
790 | + } | ||
791 | + // In string mode, just add the output | ||
792 | + else { | ||
793 | + this._addOutput(line); | ||
794 | + } | ||
795 | + } | ||
796 | + | ||
797 | + if (self.opts.compileDebug && newLineCount) { | ||
798 | + this.currentLine += newLineCount; | ||
799 | + this.source += ' ; __line = ' + this.currentLine + '\n'; | ||
800 | + } | ||
801 | + } | ||
802 | +}; | ||
803 | + | ||
804 | +/** | ||
805 | + * Escape characters reserved in XML. | ||
806 | + * | ||
807 | + * This is simply an export of {@link module:utils.escapeXML}. | ||
808 | + * | ||
809 | + * If `markup` is `undefined` or `null`, the empty string is returned. | ||
810 | + * | ||
811 | + * @param {String} markup Input string | ||
812 | + * @return {String} Escaped string | ||
813 | + * @public | ||
814 | + * @func | ||
815 | + * */ | ||
816 | +exports.escapeXML = utils.escapeXML; | ||
817 | + | ||
818 | +/** | ||
819 | + * Express.js support. | ||
820 | + * | ||
821 | + * This is an alias for {@link module:ejs.renderFile}, in order to support | ||
822 | + * Express.js out-of-the-box. | ||
823 | + * | ||
824 | + * @func | ||
825 | + */ | ||
826 | + | ||
827 | +exports.__express = exports.renderFile; | ||
828 | + | ||
829 | +// Add require support | ||
830 | +/* istanbul ignore else */ | ||
831 | +if (require.extensions) { | ||
832 | + require.extensions['.ejs'] = function (module, flnm) { | ||
833 | + var filename = flnm || /* istanbul ignore next */ module.filename; | ||
834 | + var options = { | ||
835 | + filename: filename, | ||
836 | + client: true | ||
837 | + }; | ||
838 | + var template = fileLoader(filename).toString(); | ||
839 | + var fn = exports.compile(template, options); | ||
840 | + module._compile('module.exports = ' + fn.toString() + ';', filename); | ||
841 | + }; | ||
842 | +} | ||
843 | + | ||
844 | +/** | ||
845 | + * Version of EJS. | ||
846 | + * | ||
847 | + * @readonly | ||
848 | + * @type {String} | ||
849 | + * @public | ||
850 | + */ | ||
851 | + | ||
852 | +exports.VERSION = _VERSION_STRING; | ||
853 | + | ||
854 | +/** | ||
855 | + * Name for detection of EJS. | ||
856 | + * | ||
857 | + * @readonly | ||
858 | + * @type {String} | ||
859 | + * @public | ||
860 | + */ | ||
861 | + | ||
862 | +exports.name = _NAME; | ||
863 | + | ||
864 | +/* istanbul ignore if */ | ||
865 | +if (typeof window != 'undefined') { | ||
866 | + window.ejs = exports; | ||
867 | +} | ||
868 | + | ||
869 | +},{"../package.json":6,"./utils":2,"fs":3,"path":4}],2:[function(require,module,exports){ | ||
870 | +/* | ||
871 | + * EJS Embedded JavaScript templates | ||
872 | + * Copyright 2112 Matthew Eernisse (mde@fleegix.org) | ||
873 | + * | ||
874 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
875 | + * you may not use this file except in compliance with the License. | ||
876 | + * You may obtain a copy of the License at | ||
877 | + * | ||
878 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
879 | + * | ||
880 | + * Unless required by applicable law or agreed to in writing, software | ||
881 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
882 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
883 | + * See the License for the specific language governing permissions and | ||
884 | + * limitations under the License. | ||
885 | + * | ||
886 | +*/ | ||
887 | + | ||
888 | +/** | ||
889 | + * Private utility functions | ||
890 | + * @module utils | ||
891 | + * @private | ||
892 | + */ | ||
893 | + | ||
894 | +'use strict'; | ||
895 | + | ||
896 | +var regExpChars = /[|\\{}()[\]^$+*?.]/g; | ||
897 | + | ||
898 | +/** | ||
899 | + * Escape characters reserved in regular expressions. | ||
900 | + * | ||
901 | + * If `string` is `undefined` or `null`, the empty string is returned. | ||
902 | + * | ||
903 | + * @param {String} string Input string | ||
904 | + * @return {String} Escaped string | ||
905 | + * @static | ||
906 | + * @private | ||
907 | + */ | ||
908 | +exports.escapeRegExpChars = function (string) { | ||
909 | + // istanbul ignore if | ||
910 | + if (!string) { | ||
911 | + return ''; | ||
912 | + } | ||
913 | + return String(string).replace(regExpChars, '\\$&'); | ||
914 | +}; | ||
915 | + | ||
916 | +var _ENCODE_HTML_RULES = { | ||
917 | + '&': '&', | ||
918 | + '<': '<', | ||
919 | + '>': '>', | ||
920 | + '"': '"', | ||
921 | + "'": ''' | ||
922 | +}; | ||
923 | +var _MATCH_HTML = /[&<>\'"]/g; | ||
924 | + | ||
925 | +function encode_char(c) { | ||
926 | + return _ENCODE_HTML_RULES[c] || c; | ||
927 | +} | ||
928 | + | ||
929 | +/** | ||
930 | + * Stringified version of constants used by {@link module:utils.escapeXML}. | ||
931 | + * | ||
932 | + * It is used in the process of generating {@link ClientFunction}s. | ||
933 | + * | ||
934 | + * @readonly | ||
935 | + * @type {String} | ||
936 | + */ | ||
937 | + | ||
938 | +var escapeFuncStr = | ||
939 | + 'var _ENCODE_HTML_RULES = {\n' | ||
940 | ++ ' "&": "&"\n' | ||
941 | ++ ' , "<": "<"\n' | ||
942 | ++ ' , ">": ">"\n' | ||
943 | ++ ' , \'"\': """\n' | ||
944 | ++ ' , "\'": "'"\n' | ||
945 | ++ ' }\n' | ||
946 | ++ ' , _MATCH_HTML = /[&<>\'"]/g;\n' | ||
947 | ++ 'function encode_char(c) {\n' | ||
948 | ++ ' return _ENCODE_HTML_RULES[c] || c;\n' | ||
949 | ++ '};\n'; | ||
950 | + | ||
951 | +/** | ||
952 | + * Escape characters reserved in XML. | ||
953 | + * | ||
954 | + * If `markup` is `undefined` or `null`, the empty string is returned. | ||
955 | + * | ||
956 | + * @implements {EscapeCallback} | ||
957 | + * @param {String} markup Input string | ||
958 | + * @return {String} Escaped string | ||
959 | + * @static | ||
960 | + * @private | ||
961 | + */ | ||
962 | + | ||
963 | +exports.escapeXML = function (markup) { | ||
964 | + return markup == undefined | ||
965 | + ? '' | ||
966 | + : String(markup) | ||
967 | + .replace(_MATCH_HTML, encode_char); | ||
968 | +}; | ||
969 | +exports.escapeXML.toString = function () { | ||
970 | + return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr; | ||
971 | +}; | ||
972 | + | ||
973 | +/** | ||
974 | + * Naive copy of properties from one object to another. | ||
975 | + * Does not recurse into non-scalar properties | ||
976 | + * Does not check to see if the property has a value before copying | ||
977 | + * | ||
978 | + * @param {Object} to Destination object | ||
979 | + * @param {Object} from Source object | ||
980 | + * @return {Object} Destination object | ||
981 | + * @static | ||
982 | + * @private | ||
983 | + */ | ||
984 | +exports.shallowCopy = function (to, from) { | ||
985 | + from = from || {}; | ||
986 | + for (var p in from) { | ||
987 | + to[p] = from[p]; | ||
988 | + } | ||
989 | + return to; | ||
990 | +}; | ||
991 | + | ||
992 | +/** | ||
993 | + * Naive copy of a list of key names, from one object to another. | ||
994 | + * Only copies property if it is actually defined | ||
995 | + * Does not recurse into non-scalar properties | ||
996 | + * | ||
997 | + * @param {Object} to Destination object | ||
998 | + * @param {Object} from Source object | ||
999 | + * @param {Array} list List of properties to copy | ||
1000 | + * @return {Object} Destination object | ||
1001 | + * @static | ||
1002 | + * @private | ||
1003 | + */ | ||
1004 | +exports.shallowCopyFromList = function (to, from, list) { | ||
1005 | + for (var i = 0; i < list.length; i++) { | ||
1006 | + var p = list[i]; | ||
1007 | + if (typeof from[p] != 'undefined') { | ||
1008 | + to[p] = from[p]; | ||
1009 | + } | ||
1010 | + } | ||
1011 | + return to; | ||
1012 | +}; | ||
1013 | + | ||
1014 | +/** | ||
1015 | + * Simple in-process cache implementation. Does not implement limits of any | ||
1016 | + * sort. | ||
1017 | + * | ||
1018 | + * @implements Cache | ||
1019 | + * @static | ||
1020 | + * @private | ||
1021 | + */ | ||
1022 | +exports.cache = { | ||
1023 | + _data: {}, | ||
1024 | + set: function (key, val) { | ||
1025 | + this._data[key] = val; | ||
1026 | + }, | ||
1027 | + get: function (key) { | ||
1028 | + return this._data[key]; | ||
1029 | + }, | ||
1030 | + reset: function () { | ||
1031 | + this._data = {}; | ||
1032 | + } | ||
1033 | +}; | ||
1034 | + | ||
1035 | +},{}],3:[function(require,module,exports){ | ||
1036 | + | ||
1037 | +},{}],4:[function(require,module,exports){ | ||
1038 | +(function (process){ | ||
1039 | +// Copyright Joyent, Inc. and other Node contributors. | ||
1040 | +// | ||
1041 | +// Permission is hereby granted, free of charge, to any person obtaining a | ||
1042 | +// copy of this software and associated documentation files (the | ||
1043 | +// "Software"), to deal in the Software without restriction, including | ||
1044 | +// without limitation the rights to use, copy, modify, merge, publish, | ||
1045 | +// distribute, sublicense, and/or sell copies of the Software, and to permit | ||
1046 | +// persons to whom the Software is furnished to do so, subject to the | ||
1047 | +// following conditions: | ||
1048 | +// | ||
1049 | +// The above copyright notice and this permission notice shall be included | ||
1050 | +// in all copies or substantial portions of the Software. | ||
1051 | +// | ||
1052 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
1053 | +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
1054 | +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN | ||
1055 | +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | ||
1056 | +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
1057 | +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
1058 | +// USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
1059 | + | ||
1060 | +// resolves . and .. elements in a path array with directory names there | ||
1061 | +// must be no slashes, empty elements, or device names (c:\) in the array | ||
1062 | +// (so also no leading and trailing slashes - it does not distinguish | ||
1063 | +// relative and absolute paths) | ||
1064 | +function normalizeArray(parts, allowAboveRoot) { | ||
1065 | + // if the path tries to go above the root, `up` ends up > 0 | ||
1066 | + var up = 0; | ||
1067 | + for (var i = parts.length - 1; i >= 0; i--) { | ||
1068 | + var last = parts[i]; | ||
1069 | + if (last === '.') { | ||
1070 | + parts.splice(i, 1); | ||
1071 | + } else if (last === '..') { | ||
1072 | + parts.splice(i, 1); | ||
1073 | + up++; | ||
1074 | + } else if (up) { | ||
1075 | + parts.splice(i, 1); | ||
1076 | + up--; | ||
1077 | + } | ||
1078 | + } | ||
1079 | + | ||
1080 | + // if the path is allowed to go above the root, restore leading ..s | ||
1081 | + if (allowAboveRoot) { | ||
1082 | + for (; up--; up) { | ||
1083 | + parts.unshift('..'); | ||
1084 | + } | ||
1085 | + } | ||
1086 | + | ||
1087 | + return parts; | ||
1088 | +} | ||
1089 | + | ||
1090 | +// Split a filename into [root, dir, basename, ext], unix version | ||
1091 | +// 'root' is just a slash, or nothing. | ||
1092 | +var splitPathRe = | ||
1093 | + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; | ||
1094 | +var splitPath = function(filename) { | ||
1095 | + return splitPathRe.exec(filename).slice(1); | ||
1096 | +}; | ||
1097 | + | ||
1098 | +// path.resolve([from ...], to) | ||
1099 | +// posix version | ||
1100 | +exports.resolve = function() { | ||
1101 | + var resolvedPath = '', | ||
1102 | + resolvedAbsolute = false; | ||
1103 | + | ||
1104 | + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { | ||
1105 | + var path = (i >= 0) ? arguments[i] : process.cwd(); | ||
1106 | + | ||
1107 | + // Skip empty and invalid entries | ||
1108 | + if (typeof path !== 'string') { | ||
1109 | + throw new TypeError('Arguments to path.resolve must be strings'); | ||
1110 | + } else if (!path) { | ||
1111 | + continue; | ||
1112 | + } | ||
1113 | + | ||
1114 | + resolvedPath = path + '/' + resolvedPath; | ||
1115 | + resolvedAbsolute = path.charAt(0) === '/'; | ||
1116 | + } | ||
1117 | + | ||
1118 | + // At this point the path should be resolved to a full absolute path, but | ||
1119 | + // handle relative paths to be safe (might happen when process.cwd() fails) | ||
1120 | + | ||
1121 | + // Normalize the path | ||
1122 | + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { | ||
1123 | + return !!p; | ||
1124 | + }), !resolvedAbsolute).join('/'); | ||
1125 | + | ||
1126 | + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; | ||
1127 | +}; | ||
1128 | + | ||
1129 | +// path.normalize(path) | ||
1130 | +// posix version | ||
1131 | +exports.normalize = function(path) { | ||
1132 | + var isAbsolute = exports.isAbsolute(path), | ||
1133 | + trailingSlash = substr(path, -1) === '/'; | ||
1134 | + | ||
1135 | + // Normalize the path | ||
1136 | + path = normalizeArray(filter(path.split('/'), function(p) { | ||
1137 | + return !!p; | ||
1138 | + }), !isAbsolute).join('/'); | ||
1139 | + | ||
1140 | + if (!path && !isAbsolute) { | ||
1141 | + path = '.'; | ||
1142 | + } | ||
1143 | + if (path && trailingSlash) { | ||
1144 | + path += '/'; | ||
1145 | + } | ||
1146 | + | ||
1147 | + return (isAbsolute ? '/' : '') + path; | ||
1148 | +}; | ||
1149 | + | ||
1150 | +// posix version | ||
1151 | +exports.isAbsolute = function(path) { | ||
1152 | + return path.charAt(0) === '/'; | ||
1153 | +}; | ||
1154 | + | ||
1155 | +// posix version | ||
1156 | +exports.join = function() { | ||
1157 | + var paths = Array.prototype.slice.call(arguments, 0); | ||
1158 | + return exports.normalize(filter(paths, function(p, index) { | ||
1159 | + if (typeof p !== 'string') { | ||
1160 | + throw new TypeError('Arguments to path.join must be strings'); | ||
1161 | + } | ||
1162 | + return p; | ||
1163 | + }).join('/')); | ||
1164 | +}; | ||
1165 | + | ||
1166 | + | ||
1167 | +// path.relative(from, to) | ||
1168 | +// posix version | ||
1169 | +exports.relative = function(from, to) { | ||
1170 | + from = exports.resolve(from).substr(1); | ||
1171 | + to = exports.resolve(to).substr(1); | ||
1172 | + | ||
1173 | + function trim(arr) { | ||
1174 | + var start = 0; | ||
1175 | + for (; start < arr.length; start++) { | ||
1176 | + if (arr[start] !== '') break; | ||
1177 | + } | ||
1178 | + | ||
1179 | + var end = arr.length - 1; | ||
1180 | + for (; end >= 0; end--) { | ||
1181 | + if (arr[end] !== '') break; | ||
1182 | + } | ||
1183 | + | ||
1184 | + if (start > end) return []; | ||
1185 | + return arr.slice(start, end - start + 1); | ||
1186 | + } | ||
1187 | + | ||
1188 | + var fromParts = trim(from.split('/')); | ||
1189 | + var toParts = trim(to.split('/')); | ||
1190 | + | ||
1191 | + var length = Math.min(fromParts.length, toParts.length); | ||
1192 | + var samePartsLength = length; | ||
1193 | + for (var i = 0; i < length; i++) { | ||
1194 | + if (fromParts[i] !== toParts[i]) { | ||
1195 | + samePartsLength = i; | ||
1196 | + break; | ||
1197 | + } | ||
1198 | + } | ||
1199 | + | ||
1200 | + var outputParts = []; | ||
1201 | + for (var i = samePartsLength; i < fromParts.length; i++) { | ||
1202 | + outputParts.push('..'); | ||
1203 | + } | ||
1204 | + | ||
1205 | + outputParts = outputParts.concat(toParts.slice(samePartsLength)); | ||
1206 | + | ||
1207 | + return outputParts.join('/'); | ||
1208 | +}; | ||
1209 | + | ||
1210 | +exports.sep = '/'; | ||
1211 | +exports.delimiter = ':'; | ||
1212 | + | ||
1213 | +exports.dirname = function(path) { | ||
1214 | + var result = splitPath(path), | ||
1215 | + root = result[0], | ||
1216 | + dir = result[1]; | ||
1217 | + | ||
1218 | + if (!root && !dir) { | ||
1219 | + // No dirname whatsoever | ||
1220 | + return '.'; | ||
1221 | + } | ||
1222 | + | ||
1223 | + if (dir) { | ||
1224 | + // It has a dirname, strip trailing slash | ||
1225 | + dir = dir.substr(0, dir.length - 1); | ||
1226 | + } | ||
1227 | + | ||
1228 | + return root + dir; | ||
1229 | +}; | ||
1230 | + | ||
1231 | + | ||
1232 | +exports.basename = function(path, ext) { | ||
1233 | + var f = splitPath(path)[2]; | ||
1234 | + // TODO: make this comparison case-insensitive on windows? | ||
1235 | + if (ext && f.substr(-1 * ext.length) === ext) { | ||
1236 | + f = f.substr(0, f.length - ext.length); | ||
1237 | + } | ||
1238 | + return f; | ||
1239 | +}; | ||
1240 | + | ||
1241 | + | ||
1242 | +exports.extname = function(path) { | ||
1243 | + return splitPath(path)[3]; | ||
1244 | +}; | ||
1245 | + | ||
1246 | +function filter (xs, f) { | ||
1247 | + if (xs.filter) return xs.filter(f); | ||
1248 | + var res = []; | ||
1249 | + for (var i = 0; i < xs.length; i++) { | ||
1250 | + if (f(xs[i], i, xs)) res.push(xs[i]); | ||
1251 | + } | ||
1252 | + return res; | ||
1253 | +} | ||
1254 | + | ||
1255 | +// String.prototype.substr - negative index don't work in IE8 | ||
1256 | +var substr = 'ab'.substr(-1) === 'b' | ||
1257 | + ? function (str, start, len) { return str.substr(start, len) } | ||
1258 | + : function (str, start, len) { | ||
1259 | + if (start < 0) start = str.length + start; | ||
1260 | + return str.substr(start, len); | ||
1261 | + } | ||
1262 | +; | ||
1263 | + | ||
1264 | +}).call(this,require('_process')) | ||
1265 | +},{"_process":5}],5:[function(require,module,exports){ | ||
1266 | +// shim for using process in browser | ||
1267 | +var process = module.exports = {}; | ||
1268 | + | ||
1269 | +// cached from whatever global is present so that test runners that stub it | ||
1270 | +// don't break things. But we need to wrap it in a try catch in case it is | ||
1271 | +// wrapped in strict mode code which doesn't define any globals. It's inside a | ||
1272 | +// function because try/catches deoptimize in certain engines. | ||
1273 | + | ||
1274 | +var cachedSetTimeout; | ||
1275 | +var cachedClearTimeout; | ||
1276 | + | ||
1277 | +function defaultSetTimout() { | ||
1278 | + throw new Error('setTimeout has not been defined'); | ||
1279 | +} | ||
1280 | +function defaultClearTimeout () { | ||
1281 | + throw new Error('clearTimeout has not been defined'); | ||
1282 | +} | ||
1283 | +(function () { | ||
1284 | + try { | ||
1285 | + if (typeof setTimeout === 'function') { | ||
1286 | + cachedSetTimeout = setTimeout; | ||
1287 | + } else { | ||
1288 | + cachedSetTimeout = defaultSetTimout; | ||
1289 | + } | ||
1290 | + } catch (e) { | ||
1291 | + cachedSetTimeout = defaultSetTimout; | ||
1292 | + } | ||
1293 | + try { | ||
1294 | + if (typeof clearTimeout === 'function') { | ||
1295 | + cachedClearTimeout = clearTimeout; | ||
1296 | + } else { | ||
1297 | + cachedClearTimeout = defaultClearTimeout; | ||
1298 | + } | ||
1299 | + } catch (e) { | ||
1300 | + cachedClearTimeout = defaultClearTimeout; | ||
1301 | + } | ||
1302 | +} ()) | ||
1303 | +function runTimeout(fun) { | ||
1304 | + if (cachedSetTimeout === setTimeout) { | ||
1305 | + //normal enviroments in sane situations | ||
1306 | + return setTimeout(fun, 0); | ||
1307 | + } | ||
1308 | + // if setTimeout wasn't available but was latter defined | ||
1309 | + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { | ||
1310 | + cachedSetTimeout = setTimeout; | ||
1311 | + return setTimeout(fun, 0); | ||
1312 | + } | ||
1313 | + try { | ||
1314 | + // when when somebody has screwed with setTimeout but no I.E. maddness | ||
1315 | + return cachedSetTimeout(fun, 0); | ||
1316 | + } catch(e){ | ||
1317 | + try { | ||
1318 | + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally | ||
1319 | + return cachedSetTimeout.call(null, fun, 0); | ||
1320 | + } catch(e){ | ||
1321 | + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error | ||
1322 | + return cachedSetTimeout.call(this, fun, 0); | ||
1323 | + } | ||
1324 | + } | ||
1325 | + | ||
1326 | + | ||
1327 | +} | ||
1328 | +function runClearTimeout(marker) { | ||
1329 | + if (cachedClearTimeout === clearTimeout) { | ||
1330 | + //normal enviroments in sane situations | ||
1331 | + return clearTimeout(marker); | ||
1332 | + } | ||
1333 | + // if clearTimeout wasn't available but was latter defined | ||
1334 | + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { | ||
1335 | + cachedClearTimeout = clearTimeout; | ||
1336 | + return clearTimeout(marker); | ||
1337 | + } | ||
1338 | + try { | ||
1339 | + // when when somebody has screwed with setTimeout but no I.E. maddness | ||
1340 | + return cachedClearTimeout(marker); | ||
1341 | + } catch (e){ | ||
1342 | + try { | ||
1343 | + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally | ||
1344 | + return cachedClearTimeout.call(null, marker); | ||
1345 | + } catch (e){ | ||
1346 | + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. | ||
1347 | + // Some versions of I.E. have different rules for clearTimeout vs setTimeout | ||
1348 | + return cachedClearTimeout.call(this, marker); | ||
1349 | + } | ||
1350 | + } | ||
1351 | + | ||
1352 | + | ||
1353 | + | ||
1354 | +} | ||
1355 | +var queue = []; | ||
1356 | +var draining = false; | ||
1357 | +var currentQueue; | ||
1358 | +var queueIndex = -1; | ||
1359 | + | ||
1360 | +function cleanUpNextTick() { | ||
1361 | + if (!draining || !currentQueue) { | ||
1362 | + return; | ||
1363 | + } | ||
1364 | + draining = false; | ||
1365 | + if (currentQueue.length) { | ||
1366 | + queue = currentQueue.concat(queue); | ||
1367 | + } else { | ||
1368 | + queueIndex = -1; | ||
1369 | + } | ||
1370 | + if (queue.length) { | ||
1371 | + drainQueue(); | ||
1372 | + } | ||
1373 | +} | ||
1374 | + | ||
1375 | +function drainQueue() { | ||
1376 | + if (draining) { | ||
1377 | + return; | ||
1378 | + } | ||
1379 | + var timeout = runTimeout(cleanUpNextTick); | ||
1380 | + draining = true; | ||
1381 | + | ||
1382 | + var len = queue.length; | ||
1383 | + while(len) { | ||
1384 | + currentQueue = queue; | ||
1385 | + queue = []; | ||
1386 | + while (++queueIndex < len) { | ||
1387 | + if (currentQueue) { | ||
1388 | + currentQueue[queueIndex].run(); | ||
1389 | + } | ||
1390 | + } | ||
1391 | + queueIndex = -1; | ||
1392 | + len = queue.length; | ||
1393 | + } | ||
1394 | + currentQueue = null; | ||
1395 | + draining = false; | ||
1396 | + runClearTimeout(timeout); | ||
1397 | +} | ||
1398 | + | ||
1399 | +process.nextTick = function (fun) { | ||
1400 | + var args = new Array(arguments.length - 1); | ||
1401 | + if (arguments.length > 1) { | ||
1402 | + for (var i = 1; i < arguments.length; i++) { | ||
1403 | + args[i - 1] = arguments[i]; | ||
1404 | + } | ||
1405 | + } | ||
1406 | + queue.push(new Item(fun, args)); | ||
1407 | + if (queue.length === 1 && !draining) { | ||
1408 | + runTimeout(drainQueue); | ||
1409 | + } | ||
1410 | +}; | ||
1411 | + | ||
1412 | +// v8 likes predictible objects | ||
1413 | +function Item(fun, array) { | ||
1414 | + this.fun = fun; | ||
1415 | + this.array = array; | ||
1416 | +} | ||
1417 | +Item.prototype.run = function () { | ||
1418 | + this.fun.apply(null, this.array); | ||
1419 | +}; | ||
1420 | +process.title = 'browser'; | ||
1421 | +process.browser = true; | ||
1422 | +process.env = {}; | ||
1423 | +process.argv = []; | ||
1424 | +process.version = ''; // empty string to avoid regexp issues | ||
1425 | +process.versions = {}; | ||
1426 | + | ||
1427 | +function noop() {} | ||
1428 | + | ||
1429 | +process.on = noop; | ||
1430 | +process.addListener = noop; | ||
1431 | +process.once = noop; | ||
1432 | +process.off = noop; | ||
1433 | +process.removeListener = noop; | ||
1434 | +process.removeAllListeners = noop; | ||
1435 | +process.emit = noop; | ||
1436 | + | ||
1437 | +process.binding = function (name) { | ||
1438 | + throw new Error('process.binding is not supported'); | ||
1439 | +}; | ||
1440 | + | ||
1441 | +process.cwd = function () { return '/' }; | ||
1442 | +process.chdir = function (dir) { | ||
1443 | + throw new Error('process.chdir is not supported'); | ||
1444 | +}; | ||
1445 | +process.umask = function() { return 0; }; | ||
1446 | + | ||
1447 | +},{}],6:[function(require,module,exports){ | ||
1448 | +module.exports={ | ||
1449 | + "name": "ejs", | ||
1450 | + "description": "Embedded JavaScript templates", | ||
1451 | + "keywords": [ | ||
1452 | + "template", | ||
1453 | + "engine", | ||
1454 | + "ejs" | ||
1455 | + ], | ||
1456 | + "version": "2.5.6", | ||
1457 | + "author": "Matthew Eernisse <mde@fleegix.org> (http://fleegix.org)", | ||
1458 | + "contributors": [ | ||
1459 | + "Timothy Gu <timothygu99@gmail.com> (https://timothygu.github.io)" | ||
1460 | + ], | ||
1461 | + "license": "Apache-2.0", | ||
1462 | + "main": "./lib/ejs.js", | ||
1463 | + "repository": { | ||
1464 | + "type": "git", | ||
1465 | + "url": "git://github.com/mde/ejs.git" | ||
1466 | + }, | ||
1467 | + "bugs": "https://github.com/mde/ejs/issues", | ||
1468 | + "homepage": "https://github.com/mde/ejs", | ||
1469 | + "dependencies": {}, | ||
1470 | + "devDependencies": { | ||
1471 | + "browserify": "^13.0.1", | ||
1472 | + "eslint": "^3.0.0", | ||
1473 | + "git-directory-deploy": "^1.5.1", | ||
1474 | + "istanbul": "~0.4.3", | ||
1475 | + "jake": "^8.0.0", | ||
1476 | + "jsdoc": "^3.4.0", | ||
1477 | + "lru-cache": "^4.0.1", | ||
1478 | + "mocha": "^3.0.2", | ||
1479 | + "uglify-js": "^2.6.2" | ||
1480 | + }, | ||
1481 | + "engines": { | ||
1482 | + "node": ">=0.10.0" | ||
1483 | + }, | ||
1484 | + "scripts": { | ||
1485 | + "test": "jake test", | ||
1486 | + "lint": "eslint \"**/*.js\" Jakefile", | ||
1487 | + "coverage": "istanbul cover node_modules/mocha/bin/_mocha", | ||
1488 | + "doc": "jake doc", | ||
1489 | + "devdoc": "jake doc[dev]" | ||
1490 | + } | ||
1491 | +} | ||
1492 | + | ||
1493 | +},{}]},{},[1])(1) | ||
1494 | +}); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
node_modules/ejs/ejs.min.js
0 → 100644
1 | +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ejs=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){"use strict";var fs=require("fs");var path=require("path");var utils=require("./utils");var scopeOptionWarned=false;var _VERSION_STRING=require("../package.json").version;var _DEFAULT_DELIMITER="%";var _DEFAULT_LOCALS_NAME="locals";var _NAME="ejs";var _REGEX_STRING="(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)";var _OPTS=["delimiter","scope","context","debug","compileDebug","client","_with","rmWhitespace","strict","filename"];var _OPTS_EXPRESS=_OPTS.concat("cache");var _BOM=/^\uFEFF/;exports.cache=utils.cache;exports.fileLoader=fs.readFileSync;exports.localsName=_DEFAULT_LOCALS_NAME;exports.resolveInclude=function(name,filename,isDir){var dirname=path.dirname;var extname=path.extname;var resolve=path.resolve;var includePath=resolve(isDir?filename:dirname(filename),name);var ext=extname(name);if(!ext){includePath+=".ejs"}return includePath};function getIncludePath(path,options){var includePath;var filePath;var views=options.views;if(path.charAt(0)=="/"){includePath=exports.resolveInclude(path.replace(/^\/*/,""),options.root||"/",true)}else{if(options.filename){filePath=exports.resolveInclude(path,options.filename);if(fs.existsSync(filePath)){includePath=filePath}}if(!includePath){if(Array.isArray(views)&&views.some(function(v){filePath=exports.resolveInclude(path,v,true);return fs.existsSync(filePath)})){includePath=filePath}}if(!includePath){throw new Error("Could not find include include file.")}}return includePath}function handleCache(options,template){var func;var filename=options.filename;var hasTemplate=arguments.length>1;if(options.cache){if(!filename){throw new Error("cache option requires a filename")}func=exports.cache.get(filename);if(func){return func}if(!hasTemplate){template=fileLoader(filename).toString().replace(_BOM,"")}}else if(!hasTemplate){if(!filename){throw new Error("Internal EJS error: no file name or template "+"provided")}template=fileLoader(filename).toString().replace(_BOM,"")}func=exports.compile(template,options);if(options.cache){exports.cache.set(filename,func)}return func}function tryHandleCache(options,data,cb){var result;try{result=handleCache(options)(data)}catch(err){return cb(err)}return cb(null,result)}function fileLoader(filePath){return exports.fileLoader(filePath)}function includeFile(path,options){var opts=utils.shallowCopy({},options);opts.filename=getIncludePath(path,opts);return handleCache(opts)}function includeSource(path,options){var opts=utils.shallowCopy({},options);var includePath;var template;includePath=getIncludePath(path,opts);template=fileLoader(includePath).toString().replace(_BOM,"");opts.filename=includePath;var templ=new Template(template,opts);templ.generateSource();return{source:templ.source,filename:includePath,template:template}}function rethrow(err,str,flnm,lineno,esc){var lines=str.split("\n");var start=Math.max(lineno-3,0);var end=Math.min(lines.length,lineno+3);var filename=esc(flnm);var context=lines.slice(start,end).map(function(line,i){var curr=i+start+1;return(curr==lineno?" >> ":" ")+curr+"| "+line}).join("\n");err.path=filename;err.message=(filename||"ejs")+":"+lineno+"\n"+context+"\n\n"+err.message;throw err}function stripSemi(str){return str.replace(/;(\s*$)/,"$1")}exports.compile=function compile(template,opts){var templ;if(opts&&opts.scope){if(!scopeOptionWarned){console.warn("`scope` option is deprecated and will be removed in EJS 3");scopeOptionWarned=true}if(!opts.context){opts.context=opts.scope}delete opts.scope}templ=new Template(template,opts);return templ.compile()};exports.render=function(template,d,o){var data=d||{};var opts=o||{};if(arguments.length==2){utils.shallowCopyFromList(opts,data,_OPTS)}return handleCache(opts,template)(data)};exports.renderFile=function(){var filename=arguments[0];var cb=arguments[arguments.length-1];var opts={filename:filename};var data;if(arguments.length>2){data=arguments[1];if(arguments.length===3){if(data.settings){if(data.settings["view options"]){utils.shallowCopyFromList(opts,data.settings["view options"],_OPTS_EXPRESS)}if(data.settings.views){opts.views=data.settings.views}}else{utils.shallowCopyFromList(opts,data,_OPTS_EXPRESS)}}else{utils.shallowCopy(opts,arguments[2])}opts.filename=filename}else{data={}}return tryHandleCache(opts,data,cb)};exports.clearCache=function(){exports.cache.reset()};function Template(text,opts){opts=opts||{};var options={};this.templateText=text;this.mode=null;this.truncate=false;this.currentLine=1;this.source="";this.dependencies=[];options.client=opts.client||false;options.escapeFunction=opts.escape||utils.escapeXML;options.compileDebug=opts.compileDebug!==false;options.debug=!!opts.debug;options.filename=opts.filename;options.delimiter=opts.delimiter||exports.delimiter||_DEFAULT_DELIMITER;options.strict=opts.strict||false;options.context=opts.context;options.cache=opts.cache||false;options.rmWhitespace=opts.rmWhitespace;options.root=opts.root;options.localsName=opts.localsName||exports.localsName||_DEFAULT_LOCALS_NAME;options.views=opts.views;if(options.strict){options._with=false}else{options._with=typeof opts._with!="undefined"?opts._with:true}this.opts=options;this.regex=this.createRegex()}Template.modes={EVAL:"eval",ESCAPED:"escaped",RAW:"raw",COMMENT:"comment",LITERAL:"literal"};Template.prototype={createRegex:function(){var str=_REGEX_STRING;var delim=utils.escapeRegExpChars(this.opts.delimiter);str=str.replace(/%/g,delim);return new RegExp(str)},compile:function(){var src;var fn;var opts=this.opts;var prepended="";var appended="";var escapeFn=opts.escapeFunction;if(!this.source){this.generateSource();prepended+=" var __output = [], __append = __output.push.bind(__output);"+"\n";if(opts._with!==false){prepended+=" with ("+opts.localsName+" || {}) {"+"\n";appended+=" }"+"\n"}appended+=' return __output.join("");'+"\n";this.source=prepended+this.source+appended}if(opts.compileDebug){src="var __line = 1"+"\n"+" , __lines = "+JSON.stringify(this.templateText)+"\n"+" , __filename = "+(opts.filename?JSON.stringify(opts.filename):"undefined")+";"+"\n"+"try {"+"\n"+this.source+"} catch (e) {"+"\n"+" rethrow(e, __lines, __filename, __line, escapeFn);"+"\n"+"}"+"\n"}else{src=this.source}if(opts.client){src="escapeFn = escapeFn || "+escapeFn.toString()+";"+"\n"+src;if(opts.compileDebug){src="rethrow = rethrow || "+rethrow.toString()+";"+"\n"+src}}if(opts.strict){src='"use strict";\n'+src}if(opts.debug){console.log(src)}try{fn=new Function(opts.localsName+", escapeFn, include, rethrow",src)}catch(e){if(e instanceof SyntaxError){if(opts.filename){e.message+=" in "+opts.filename}e.message+=" while compiling ejs\n\n";e.message+="If the above error is not helpful, you may want to try EJS-Lint:\n";e.message+="https://github.com/RyanZim/EJS-Lint"}throw e}if(opts.client){fn.dependencies=this.dependencies;return fn}var returnedFn=function(data){var include=function(path,includeData){var d=utils.shallowCopy({},data);if(includeData){d=utils.shallowCopy(d,includeData)}return includeFile(path,opts)(d)};return fn.apply(opts.context,[data||{},escapeFn,include,rethrow])};returnedFn.dependencies=this.dependencies;return returnedFn},generateSource:function(){var opts=this.opts;if(opts.rmWhitespace){this.templateText=this.templateText.replace(/\r/g,"").replace(/^\s+|\s+$/gm,"")}this.templateText=this.templateText.replace(/[ \t]*<%_/gm,"<%_").replace(/_%>[ \t]*/gm,"_%>");var self=this;var matches=this.parseTemplateText();var d=this.opts.delimiter;if(matches&&matches.length){matches.forEach(function(line,index){var opening;var closing;var include;var includeOpts;var includeObj;var includeSrc;if(line.indexOf("<"+d)===0&&line.indexOf("<"+d+d)!==0){closing=matches[index+2];if(!(closing==d+">"||closing=="-"+d+">"||closing=="_"+d+">")){throw new Error('Could not find matching close tag for "'+line+'".')}}if(include=line.match(/^\s*include\s+(\S+)/)){opening=matches[index-1];if(opening&&(opening=="<"+d||opening=="<"+d+"-"||opening=="<"+d+"_")){includeOpts=utils.shallowCopy({},self.opts);includeObj=includeSource(include[1],includeOpts);if(self.opts.compileDebug){includeSrc=" ; (function(){"+"\n"+" var __line = 1"+"\n"+" , __lines = "+JSON.stringify(includeObj.template)+"\n"+" , __filename = "+JSON.stringify(includeObj.filename)+";"+"\n"+" try {"+"\n"+includeObj.source+" } catch (e) {"+"\n"+" rethrow(e, __lines, __filename, __line, escapeFn);"+"\n"+" }"+"\n"+" ; }).call(this)"+"\n"}else{includeSrc=" ; (function(){"+"\n"+includeObj.source+" ; }).call(this)"+"\n"}self.source+=includeSrc;self.dependencies.push(exports.resolveInclude(include[1],includeOpts.filename));return}}self.scanLine(line)})}},parseTemplateText:function(){var str=this.templateText;var pat=this.regex;var result=pat.exec(str);var arr=[];var firstPos;while(result){firstPos=result.index;if(firstPos!==0){arr.push(str.substring(0,firstPos));str=str.slice(firstPos)}arr.push(result[0]);str=str.slice(result[0].length);result=pat.exec(str)}if(str){arr.push(str)}return arr},_addOutput:function(line){if(this.truncate){line=line.replace(/^(?:\r\n|\r|\n)/,"");this.truncate=false}else if(this.opts.rmWhitespace){line=line.replace(/^\n/,"")}if(!line){return line}line=line.replace(/\\/g,"\\\\");line=line.replace(/\n/g,"\\n");line=line.replace(/\r/g,"\\r");line=line.replace(/"/g,'\\"');this.source+=' ; __append("'+line+'")'+"\n"},scanLine:function(line){var self=this;var d=this.opts.delimiter;var newLineCount=0;newLineCount=line.split("\n").length-1;switch(line){case"<"+d:case"<"+d+"_":this.mode=Template.modes.EVAL;break;case"<"+d+"=":this.mode=Template.modes.ESCAPED;break;case"<"+d+"-":this.mode=Template.modes.RAW;break;case"<"+d+"#":this.mode=Template.modes.COMMENT;break;case"<"+d+d:this.mode=Template.modes.LITERAL;this.source+=' ; __append("'+line.replace("<"+d+d,"<"+d)+'")'+"\n";break;case d+d+">":this.mode=Template.modes.LITERAL;this.source+=' ; __append("'+line.replace(d+d+">",d+">")+'")'+"\n";break;case d+">":case"-"+d+">":case"_"+d+">":if(this.mode==Template.modes.LITERAL){this._addOutput(line)}this.mode=null;this.truncate=line.indexOf("-")===0||line.indexOf("_")===0;break;default:if(this.mode){switch(this.mode){case Template.modes.EVAL:case Template.modes.ESCAPED:case Template.modes.RAW:if(line.lastIndexOf("//")>line.lastIndexOf("\n")){line+="\n"}}switch(this.mode){case Template.modes.EVAL:this.source+=" ; "+line+"\n";break;case Template.modes.ESCAPED:this.source+=" ; __append(escapeFn("+stripSemi(line)+"))"+"\n";break;case Template.modes.RAW:this.source+=" ; __append("+stripSemi(line)+")"+"\n";break;case Template.modes.COMMENT:break;case Template.modes.LITERAL:this._addOutput(line);break}}else{this._addOutput(line)}}if(self.opts.compileDebug&&newLineCount){this.currentLine+=newLineCount;this.source+=" ; __line = "+this.currentLine+"\n"}}};exports.escapeXML=utils.escapeXML;exports.__express=exports.renderFile;if(require.extensions){require.extensions[".ejs"]=function(module,flnm){var filename=flnm||module.filename;var options={filename:filename,client:true};var template=fileLoader(filename).toString();var fn=exports.compile(template,options);module._compile("module.exports = "+fn.toString()+";",filename)}}exports.VERSION=_VERSION_STRING;exports.name=_NAME;if(typeof window!="undefined"){window.ejs=exports}},{"../package.json":6,"./utils":2,fs:3,path:4}],2:[function(require,module,exports){"use strict";var regExpChars=/[|\\{}()[\]^$+*?.]/g;exports.escapeRegExpChars=function(string){if(!string){return""}return String(string).replace(regExpChars,"\\$&")};var _ENCODE_HTML_RULES={"&":"&","<":"<",">":">",'"':""","'":"'"};var _MATCH_HTML=/[&<>\'"]/g;function encode_char(c){return _ENCODE_HTML_RULES[c]||c}var escapeFuncStr="var _ENCODE_HTML_RULES = {\n"+' "&": "&"\n'+' , "<": "<"\n'+' , ">": ">"\n'+' , \'"\': """\n'+' , "\'": "'"\n'+" }\n"+" , _MATCH_HTML = /[&<>'\"]/g;\n"+"function encode_char(c) {\n"+" return _ENCODE_HTML_RULES[c] || c;\n"+"};\n";exports.escapeXML=function(markup){return markup==undefined?"":String(markup).replace(_MATCH_HTML,encode_char)};exports.escapeXML.toString=function(){return Function.prototype.toString.call(this)+";\n"+escapeFuncStr};exports.shallowCopy=function(to,from){from=from||{};for(var p in from){to[p]=from[p]}return to};exports.shallowCopyFromList=function(to,from,list){for(var i=0;i<list.length;i++){var p=list[i];if(typeof from[p]!="undefined"){to[p]=from[p]}}return to};exports.cache={_data:{},set:function(key,val){this._data[key]=val},get:function(key){return this._data[key]},reset:function(){this._data={}}}},{}],3:[function(require,module,exports){},{}],4:[function(require,module,exports){(function(process){function normalizeArray(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up--;up){parts.unshift("..")}}return parts}var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;var splitPath=function(filename){return splitPathRe.exec(filename).slice(1)};exports.resolve=function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:process.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){continue}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=normalizeArray(filter(resolvedPath.split("/"),function(p){return!!p}),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."};exports.normalize=function(path){var isAbsolute=exports.isAbsolute(path),trailingSlash=substr(path,-1)==="/";path=normalizeArray(filter(path.split("/"),function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path};exports.isAbsolute=function(path){return path.charAt(0)==="/"};exports.join=function(){var paths=Array.prototype.slice.call(arguments,0);return exports.normalize(filter(paths,function(p,index){if(typeof p!=="string"){throw new TypeError("Arguments to path.join must be strings")}return p}).join("/"))};exports.relative=function(from,to){from=exports.resolve(from).substr(1);to=exports.resolve(to).substr(1);function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[start]!=="")break}var end=arr.length-1;for(;end>=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i<length;i++){if(fromParts[i]!==toParts[i]){samePartsLength=i;break}}var outputParts=[];for(var i=samePartsLength;i<fromParts.length;i++){outputParts.push("..")}outputParts=outputParts.concat(toParts.slice(samePartsLength));return outputParts.join("/")};exports.sep="/";exports.delimiter=":";exports.dirname=function(path){var result=splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir};exports.basename=function(path,ext){var f=splitPath(path)[2];if(ext&&f.substr(-1*ext.length)===ext){f=f.substr(0,f.length-ext.length)}return f};exports.extname=function(path){return splitPath(path)[3]};function filter(xs,f){if(xs.filter)return xs.filter(f);var res=[];for(var i=0;i<xs.length;i++){if(f(xs[i],i,xs))res.push(xs[i])}return res}var substr="ab".substr(-1)==="b"?function(str,start,len){return str.substr(start,len)}:function(str,start,len){if(start<0)start=str.length+start;return str.substr(start,len)}}).call(this,require("_process"))},{_process:5}],5:[function(require,module,exports){var process=module.exports={};var cachedSetTimeout;var cachedClearTimeout;function defaultSetTimout(){throw new Error("setTimeout has not been defined")}function defaultClearTimeout(){throw new Error("clearTimeout has not been defined")}(function(){try{if(typeof setTimeout==="function"){cachedSetTimeout=setTimeout}else{cachedSetTimeout=defaultSetTimout}}catch(e){cachedSetTimeout=defaultSetTimout}try{if(typeof clearTimeout==="function"){cachedClearTimeout=clearTimeout}else{cachedClearTimeout=defaultClearTimeout}}catch(e){cachedClearTimeout=defaultClearTimeout}})();function runTimeout(fun){if(cachedSetTimeout===setTimeout){return setTimeout(fun,0)}if((cachedSetTimeout===defaultSetTimout||!cachedSetTimeout)&&setTimeout){cachedSetTimeout=setTimeout;return setTimeout(fun,0)}try{return cachedSetTimeout(fun,0)}catch(e){try{return cachedSetTimeout.call(null,fun,0)}catch(e){return cachedSetTimeout.call(this,fun,0)}}}function runClearTimeout(marker){if(cachedClearTimeout===clearTimeout){return clearTimeout(marker)}if((cachedClearTimeout===defaultClearTimeout||!cachedClearTimeout)&&clearTimeout){cachedClearTimeout=clearTimeout;return clearTimeout(marker)}try{return cachedClearTimeout(marker)}catch(e){try{return cachedClearTimeout.call(null,marker)}catch(e){return cachedClearTimeout.call(this,marker)}}}var queue=[];var draining=false;var currentQueue;var queueIndex=-1;function cleanUpNextTick(){if(!draining||!currentQueue){return}draining=false;if(currentQueue.length){queue=currentQueue.concat(queue)}else{queueIndex=-1}if(queue.length){drainQueue()}}function drainQueue(){if(draining){return}var timeout=runTimeout(cleanUpNextTick);draining=true;var len=queue.length;while(len){currentQueue=queue;queue=[];while(++queueIndex<len){if(currentQueue){currentQueue[queueIndex].run()}}queueIndex=-1;len=queue.length}currentQueue=null;draining=false;runClearTimeout(timeout)}process.nextTick=function(fun){var args=new Array(arguments.length-1);if(arguments.length>1){for(var i=1;i<arguments.length;i++){args[i-1]=arguments[i]}}queue.push(new Item(fun,args));if(queue.length===1&&!draining){runTimeout(drainQueue)}};function Item(fun,array){this.fun=fun;this.array=array}Item.prototype.run=function(){this.fun.apply(null,this.array)};process.title="browser";process.browser=true;process.env={};process.argv=[];process.version="";process.versions={};function noop(){}process.on=noop;process.addListener=noop;process.once=noop;process.off=noop;process.removeListener=noop;process.removeAllListeners=noop;process.emit=noop;process.binding=function(name){throw new Error("process.binding is not supported")};process.cwd=function(){return"/"};process.chdir=function(dir){throw new Error("process.chdir is not supported")};process.umask=function(){return 0}},{}],6:[function(require,module,exports){module.exports={name:"ejs",description:"Embedded JavaScript templates",keywords:["template","engine","ejs"],version:"2.5.6",author:"Matthew Eernisse <mde@fleegix.org> (http://fleegix.org)",contributors:["Timothy Gu <timothygu99@gmail.com> (https://timothygu.github.io)"],license:"Apache-2.0",main:"./lib/ejs.js",repository:{type:"git",url:"git://github.com/mde/ejs.git"},bugs:"https://github.com/mde/ejs/issues",homepage:"https://github.com/mde/ejs",dependencies:{},devDependencies:{browserify:"^13.0.1",eslint:"^3.0.0","git-directory-deploy":"^1.5.1",istanbul:"~0.4.3",jake:"^8.0.0",jsdoc:"^3.4.0","lru-cache":"^4.0.1",mocha:"^3.0.2","uglify-js":"^2.6.2"},engines:{node:">=0.10.0"},scripts:{test:"jake test",lint:'eslint "**/*.js" Jakefile',coverage:"istanbul cover node_modules/mocha/bin/_mocha",doc:"jake doc",devdoc:"jake doc[dev]"}}},{}]},{},[1])(1)}); |
node_modules/ejs/lib/ejs.js
0 → 100644
1 | +/* | ||
2 | + * EJS Embedded JavaScript templates | ||
3 | + * Copyright 2112 Matthew Eernisse (mde@fleegix.org) | ||
4 | + * | ||
5 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + * you may not use this file except in compliance with the License. | ||
7 | + * You may obtain a copy of the License at | ||
8 | + * | ||
9 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + * | ||
11 | + * Unless required by applicable law or agreed to in writing, software | ||
12 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + * See the License for the specific language governing permissions and | ||
15 | + * limitations under the License. | ||
16 | + * | ||
17 | +*/ | ||
18 | + | ||
19 | +'use strict'; | ||
20 | + | ||
21 | +/** | ||
22 | + * @file Embedded JavaScript templating engine. {@link http://ejs.co} | ||
23 | + * @author Matthew Eernisse <mde@fleegix.org> | ||
24 | + * @author Tiancheng "Timothy" Gu <timothygu99@gmail.com> | ||
25 | + * @project EJS | ||
26 | + * @license {@link http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0} | ||
27 | + */ | ||
28 | + | ||
29 | +/** | ||
30 | + * EJS internal functions. | ||
31 | + * | ||
32 | + * Technically this "module" lies in the same file as {@link module:ejs}, for | ||
33 | + * the sake of organization all the private functions re grouped into this | ||
34 | + * module. | ||
35 | + * | ||
36 | + * @module ejs-internal | ||
37 | + * @private | ||
38 | + */ | ||
39 | + | ||
40 | +/** | ||
41 | + * Embedded JavaScript templating engine. | ||
42 | + * | ||
43 | + * @module ejs | ||
44 | + * @public | ||
45 | + */ | ||
46 | + | ||
47 | +var fs = require('fs'); | ||
48 | +var path = require('path'); | ||
49 | +var utils = require('./utils'); | ||
50 | + | ||
51 | +var scopeOptionWarned = false; | ||
52 | +var _VERSION_STRING = require('../package.json').version; | ||
53 | +var _DEFAULT_DELIMITER = '%'; | ||
54 | +var _DEFAULT_LOCALS_NAME = 'locals'; | ||
55 | +var _NAME = 'ejs'; | ||
56 | +var _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)'; | ||
57 | +var _OPTS = ['delimiter', 'scope', 'context', 'debug', 'compileDebug', | ||
58 | + 'client', '_with', 'rmWhitespace', 'strict', 'filename']; | ||
59 | +// We don't allow 'cache' option to be passed in the data obj | ||
60 | +// for the normal `render` call, but this is where Express puts it | ||
61 | +// so we make an exception for `renderFile` | ||
62 | +var _OPTS_EXPRESS = _OPTS.concat('cache'); | ||
63 | +var _BOM = /^\uFEFF/; | ||
64 | + | ||
65 | +/** | ||
66 | + * EJS template function cache. This can be a LRU object from lru-cache NPM | ||
67 | + * module. By default, it is {@link module:utils.cache}, a simple in-process | ||
68 | + * cache that grows continuously. | ||
69 | + * | ||
70 | + * @type {Cache} | ||
71 | + */ | ||
72 | + | ||
73 | +exports.cache = utils.cache; | ||
74 | + | ||
75 | +/** | ||
76 | + * Custom file loader. Useful for template preprocessing or restricting access | ||
77 | + * to a certain part of the filesystem. | ||
78 | + * | ||
79 | + * @type {fileLoader} | ||
80 | + */ | ||
81 | + | ||
82 | +exports.fileLoader = fs.readFileSync; | ||
83 | + | ||
84 | +/** | ||
85 | + * Name of the object containing the locals. | ||
86 | + * | ||
87 | + * This variable is overridden by {@link Options}`.localsName` if it is not | ||
88 | + * `undefined`. | ||
89 | + * | ||
90 | + * @type {String} | ||
91 | + * @public | ||
92 | + */ | ||
93 | + | ||
94 | +exports.localsName = _DEFAULT_LOCALS_NAME; | ||
95 | + | ||
96 | +/** | ||
97 | + * Get the path to the included file from the parent file path and the | ||
98 | + * specified path. | ||
99 | + * | ||
100 | + * @param {String} name specified path | ||
101 | + * @param {String} filename parent file path | ||
102 | + * @param {Boolean} isDir parent file path whether is directory | ||
103 | + * @return {String} | ||
104 | + */ | ||
105 | +exports.resolveInclude = function(name, filename, isDir) { | ||
106 | + var dirname = path.dirname; | ||
107 | + var extname = path.extname; | ||
108 | + var resolve = path.resolve; | ||
109 | + var includePath = resolve(isDir ? filename : dirname(filename), name); | ||
110 | + var ext = extname(name); | ||
111 | + if (!ext) { | ||
112 | + includePath += '.ejs'; | ||
113 | + } | ||
114 | + return includePath; | ||
115 | +}; | ||
116 | + | ||
117 | +/** | ||
118 | + * Get the path to the included file by Options | ||
119 | + * | ||
120 | + * @param {String} path specified path | ||
121 | + * @param {Options} options compilation options | ||
122 | + * @return {String} | ||
123 | + */ | ||
124 | +function getIncludePath(path, options) { | ||
125 | + var includePath; | ||
126 | + var filePath; | ||
127 | + var views = options.views; | ||
128 | + | ||
129 | + // Abs path | ||
130 | + if (path.charAt(0) == '/') { | ||
131 | + includePath = exports.resolveInclude(path.replace(/^\/*/,''), options.root || '/', true); | ||
132 | + } | ||
133 | + // Relative paths | ||
134 | + else { | ||
135 | + // Look relative to a passed filename first | ||
136 | + if (options.filename) { | ||
137 | + filePath = exports.resolveInclude(path, options.filename); | ||
138 | + if (fs.existsSync(filePath)) { | ||
139 | + includePath = filePath; | ||
140 | + } | ||
141 | + } | ||
142 | + // Then look in any views directories | ||
143 | + if (!includePath) { | ||
144 | + if (Array.isArray(views) && views.some(function (v) { | ||
145 | + filePath = exports.resolveInclude(path, v, true); | ||
146 | + return fs.existsSync(filePath); | ||
147 | + })) { | ||
148 | + includePath = filePath; | ||
149 | + } | ||
150 | + } | ||
151 | + if (!includePath) { | ||
152 | + throw new Error('Could not find include include file.'); | ||
153 | + } | ||
154 | + } | ||
155 | + return includePath; | ||
156 | +} | ||
157 | + | ||
158 | +/** | ||
159 | + * Get the template from a string or a file, either compiled on-the-fly or | ||
160 | + * read from cache (if enabled), and cache the template if needed. | ||
161 | + * | ||
162 | + * If `template` is not set, the file specified in `options.filename` will be | ||
163 | + * read. | ||
164 | + * | ||
165 | + * If `options.cache` is true, this function reads the file from | ||
166 | + * `options.filename` so it must be set prior to calling this function. | ||
167 | + * | ||
168 | + * @memberof module:ejs-internal | ||
169 | + * @param {Options} options compilation options | ||
170 | + * @param {String} [template] template source | ||
171 | + * @return {(TemplateFunction|ClientFunction)} | ||
172 | + * Depending on the value of `options.client`, either type might be returned. | ||
173 | + * @static | ||
174 | + */ | ||
175 | + | ||
176 | +function handleCache(options, template) { | ||
177 | + var func; | ||
178 | + var filename = options.filename; | ||
179 | + var hasTemplate = arguments.length > 1; | ||
180 | + | ||
181 | + if (options.cache) { | ||
182 | + if (!filename) { | ||
183 | + throw new Error('cache option requires a filename'); | ||
184 | + } | ||
185 | + func = exports.cache.get(filename); | ||
186 | + if (func) { | ||
187 | + return func; | ||
188 | + } | ||
189 | + if (!hasTemplate) { | ||
190 | + template = fileLoader(filename).toString().replace(_BOM, ''); | ||
191 | + } | ||
192 | + } | ||
193 | + else if (!hasTemplate) { | ||
194 | + // istanbul ignore if: should not happen at all | ||
195 | + if (!filename) { | ||
196 | + throw new Error('Internal EJS error: no file name or template ' | ||
197 | + + 'provided'); | ||
198 | + } | ||
199 | + template = fileLoader(filename).toString().replace(_BOM, ''); | ||
200 | + } | ||
201 | + func = exports.compile(template, options); | ||
202 | + if (options.cache) { | ||
203 | + exports.cache.set(filename, func); | ||
204 | + } | ||
205 | + return func; | ||
206 | +} | ||
207 | + | ||
208 | +/** | ||
209 | + * Try calling handleCache with the given options and data and call the | ||
210 | + * callback with the result. If an error occurs, call the callback with | ||
211 | + * the error. Used by renderFile(). | ||
212 | + * | ||
213 | + * @memberof module:ejs-internal | ||
214 | + * @param {Options} options compilation options | ||
215 | + * @param {Object} data template data | ||
216 | + * @param {RenderFileCallback} cb callback | ||
217 | + * @static | ||
218 | + */ | ||
219 | + | ||
220 | +function tryHandleCache(options, data, cb) { | ||
221 | + var result; | ||
222 | + try { | ||
223 | + result = handleCache(options)(data); | ||
224 | + } | ||
225 | + catch (err) { | ||
226 | + return cb(err); | ||
227 | + } | ||
228 | + return cb(null, result); | ||
229 | +} | ||
230 | + | ||
231 | +/** | ||
232 | + * fileLoader is independent | ||
233 | + * | ||
234 | + * @param {String} filePath ejs file path. | ||
235 | + * @return {String} The contents of the specified file. | ||
236 | + * @static | ||
237 | + */ | ||
238 | + | ||
239 | +function fileLoader(filePath){ | ||
240 | + return exports.fileLoader(filePath); | ||
241 | +} | ||
242 | + | ||
243 | +/** | ||
244 | + * Get the template function. | ||
245 | + * | ||
246 | + * If `options.cache` is `true`, then the template is cached. | ||
247 | + * | ||
248 | + * @memberof module:ejs-internal | ||
249 | + * @param {String} path path for the specified file | ||
250 | + * @param {Options} options compilation options | ||
251 | + * @return {(TemplateFunction|ClientFunction)} | ||
252 | + * Depending on the value of `options.client`, either type might be returned | ||
253 | + * @static | ||
254 | + */ | ||
255 | + | ||
256 | +function includeFile(path, options) { | ||
257 | + var opts = utils.shallowCopy({}, options); | ||
258 | + opts.filename = getIncludePath(path, opts); | ||
259 | + return handleCache(opts); | ||
260 | +} | ||
261 | + | ||
262 | +/** | ||
263 | + * Get the JavaScript source of an included file. | ||
264 | + * | ||
265 | + * @memberof module:ejs-internal | ||
266 | + * @param {String} path path for the specified file | ||
267 | + * @param {Options} options compilation options | ||
268 | + * @return {Object} | ||
269 | + * @static | ||
270 | + */ | ||
271 | + | ||
272 | +function includeSource(path, options) { | ||
273 | + var opts = utils.shallowCopy({}, options); | ||
274 | + var includePath; | ||
275 | + var template; | ||
276 | + includePath = getIncludePath(path, opts); | ||
277 | + template = fileLoader(includePath).toString().replace(_BOM, ''); | ||
278 | + opts.filename = includePath; | ||
279 | + var templ = new Template(template, opts); | ||
280 | + templ.generateSource(); | ||
281 | + return { | ||
282 | + source: templ.source, | ||
283 | + filename: includePath, | ||
284 | + template: template | ||
285 | + }; | ||
286 | +} | ||
287 | + | ||
288 | +/** | ||
289 | + * Re-throw the given `err` in context to the `str` of ejs, `filename`, and | ||
290 | + * `lineno`. | ||
291 | + * | ||
292 | + * @implements RethrowCallback | ||
293 | + * @memberof module:ejs-internal | ||
294 | + * @param {Error} err Error object | ||
295 | + * @param {String} str EJS source | ||
296 | + * @param {String} filename file name of the EJS file | ||
297 | + * @param {String} lineno line number of the error | ||
298 | + * @static | ||
299 | + */ | ||
300 | + | ||
301 | +function rethrow(err, str, flnm, lineno, esc){ | ||
302 | + var lines = str.split('\n'); | ||
303 | + var start = Math.max(lineno - 3, 0); | ||
304 | + var end = Math.min(lines.length, lineno + 3); | ||
305 | + var filename = esc(flnm); // eslint-disable-line | ||
306 | + // Error context | ||
307 | + var context = lines.slice(start, end).map(function (line, i){ | ||
308 | + var curr = i + start + 1; | ||
309 | + return (curr == lineno ? ' >> ' : ' ') | ||
310 | + + curr | ||
311 | + + '| ' | ||
312 | + + line; | ||
313 | + }).join('\n'); | ||
314 | + | ||
315 | + // Alter exception message | ||
316 | + err.path = filename; | ||
317 | + err.message = (filename || 'ejs') + ':' | ||
318 | + + lineno + '\n' | ||
319 | + + context + '\n\n' | ||
320 | + + err.message; | ||
321 | + | ||
322 | + throw err; | ||
323 | +} | ||
324 | + | ||
325 | +function stripSemi(str){ | ||
326 | + return str.replace(/;(\s*$)/, '$1'); | ||
327 | +} | ||
328 | + | ||
329 | +/** | ||
330 | + * Compile the given `str` of ejs into a template function. | ||
331 | + * | ||
332 | + * @param {String} template EJS template | ||
333 | + * | ||
334 | + * @param {Options} opts compilation options | ||
335 | + * | ||
336 | + * @return {(TemplateFunction|ClientFunction)} | ||
337 | + * Depending on the value of `opts.client`, either type might be returned. | ||
338 | + * @public | ||
339 | + */ | ||
340 | + | ||
341 | +exports.compile = function compile(template, opts) { | ||
342 | + var templ; | ||
343 | + | ||
344 | + // v1 compat | ||
345 | + // 'scope' is 'context' | ||
346 | + // FIXME: Remove this in a future version | ||
347 | + if (opts && opts.scope) { | ||
348 | + if (!scopeOptionWarned){ | ||
349 | + console.warn('`scope` option is deprecated and will be removed in EJS 3'); | ||
350 | + scopeOptionWarned = true; | ||
351 | + } | ||
352 | + if (!opts.context) { | ||
353 | + opts.context = opts.scope; | ||
354 | + } | ||
355 | + delete opts.scope; | ||
356 | + } | ||
357 | + templ = new Template(template, opts); | ||
358 | + return templ.compile(); | ||
359 | +}; | ||
360 | + | ||
361 | +/** | ||
362 | + * Render the given `template` of ejs. | ||
363 | + * | ||
364 | + * If you would like to include options but not data, you need to explicitly | ||
365 | + * call this function with `data` being an empty object or `null`. | ||
366 | + * | ||
367 | + * @param {String} template EJS template | ||
368 | + * @param {Object} [data={}] template data | ||
369 | + * @param {Options} [opts={}] compilation and rendering options | ||
370 | + * @return {String} | ||
371 | + * @public | ||
372 | + */ | ||
373 | + | ||
374 | +exports.render = function (template, d, o) { | ||
375 | + var data = d || {}; | ||
376 | + var opts = o || {}; | ||
377 | + | ||
378 | + // No options object -- if there are optiony names | ||
379 | + // in the data, copy them to options | ||
380 | + if (arguments.length == 2) { | ||
381 | + utils.shallowCopyFromList(opts, data, _OPTS); | ||
382 | + } | ||
383 | + | ||
384 | + return handleCache(opts, template)(data); | ||
385 | +}; | ||
386 | + | ||
387 | +/** | ||
388 | + * Render an EJS file at the given `path` and callback `cb(err, str)`. | ||
389 | + * | ||
390 | + * If you would like to include options but not data, you need to explicitly | ||
391 | + * call this function with `data` being an empty object or `null`. | ||
392 | + * | ||
393 | + * @param {String} path path to the EJS file | ||
394 | + * @param {Object} [data={}] template data | ||
395 | + * @param {Options} [opts={}] compilation and rendering options | ||
396 | + * @param {RenderFileCallback} cb callback | ||
397 | + * @public | ||
398 | + */ | ||
399 | + | ||
400 | +exports.renderFile = function () { | ||
401 | + var filename = arguments[0]; | ||
402 | + var cb = arguments[arguments.length - 1]; | ||
403 | + var opts = {filename: filename}; | ||
404 | + var data; | ||
405 | + | ||
406 | + if (arguments.length > 2) { | ||
407 | + data = arguments[1]; | ||
408 | + | ||
409 | + // No options object -- if there are optiony names | ||
410 | + // in the data, copy them to options | ||
411 | + if (arguments.length === 3) { | ||
412 | + // Express 4 | ||
413 | + if (data.settings) { | ||
414 | + if (data.settings['view options']) { | ||
415 | + utils.shallowCopyFromList(opts, data.settings['view options'], _OPTS_EXPRESS); | ||
416 | + } | ||
417 | + if (data.settings.views) { | ||
418 | + opts.views = data.settings.views; | ||
419 | + } | ||
420 | + } | ||
421 | + // Express 3 and lower | ||
422 | + else { | ||
423 | + utils.shallowCopyFromList(opts, data, _OPTS_EXPRESS); | ||
424 | + } | ||
425 | + } | ||
426 | + else { | ||
427 | + // Use shallowCopy so we don't pollute passed in opts obj with new vals | ||
428 | + utils.shallowCopy(opts, arguments[2]); | ||
429 | + } | ||
430 | + | ||
431 | + opts.filename = filename; | ||
432 | + } | ||
433 | + else { | ||
434 | + data = {}; | ||
435 | + } | ||
436 | + | ||
437 | + return tryHandleCache(opts, data, cb); | ||
438 | +}; | ||
439 | + | ||
440 | +/** | ||
441 | + * Clear intermediate JavaScript cache. Calls {@link Cache#reset}. | ||
442 | + * @public | ||
443 | + */ | ||
444 | + | ||
445 | +exports.clearCache = function () { | ||
446 | + exports.cache.reset(); | ||
447 | +}; | ||
448 | + | ||
449 | +function Template(text, opts) { | ||
450 | + opts = opts || {}; | ||
451 | + var options = {}; | ||
452 | + this.templateText = text; | ||
453 | + this.mode = null; | ||
454 | + this.truncate = false; | ||
455 | + this.currentLine = 1; | ||
456 | + this.source = ''; | ||
457 | + this.dependencies = []; | ||
458 | + options.client = opts.client || false; | ||
459 | + options.escapeFunction = opts.escape || utils.escapeXML; | ||
460 | + options.compileDebug = opts.compileDebug !== false; | ||
461 | + options.debug = !!opts.debug; | ||
462 | + options.filename = opts.filename; | ||
463 | + options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER; | ||
464 | + options.strict = opts.strict || false; | ||
465 | + options.context = opts.context; | ||
466 | + options.cache = opts.cache || false; | ||
467 | + options.rmWhitespace = opts.rmWhitespace; | ||
468 | + options.root = opts.root; | ||
469 | + options.localsName = opts.localsName || exports.localsName || _DEFAULT_LOCALS_NAME; | ||
470 | + options.views = opts.views; | ||
471 | + | ||
472 | + if (options.strict) { | ||
473 | + options._with = false; | ||
474 | + } | ||
475 | + else { | ||
476 | + options._with = typeof opts._with != 'undefined' ? opts._with : true; | ||
477 | + } | ||
478 | + | ||
479 | + this.opts = options; | ||
480 | + | ||
481 | + this.regex = this.createRegex(); | ||
482 | +} | ||
483 | + | ||
484 | +Template.modes = { | ||
485 | + EVAL: 'eval', | ||
486 | + ESCAPED: 'escaped', | ||
487 | + RAW: 'raw', | ||
488 | + COMMENT: 'comment', | ||
489 | + LITERAL: 'literal' | ||
490 | +}; | ||
491 | + | ||
492 | +Template.prototype = { | ||
493 | + createRegex: function () { | ||
494 | + var str = _REGEX_STRING; | ||
495 | + var delim = utils.escapeRegExpChars(this.opts.delimiter); | ||
496 | + str = str.replace(/%/g, delim); | ||
497 | + return new RegExp(str); | ||
498 | + }, | ||
499 | + | ||
500 | + compile: function () { | ||
501 | + var src; | ||
502 | + var fn; | ||
503 | + var opts = this.opts; | ||
504 | + var prepended = ''; | ||
505 | + var appended = ''; | ||
506 | + var escapeFn = opts.escapeFunction; | ||
507 | + | ||
508 | + if (!this.source) { | ||
509 | + this.generateSource(); | ||
510 | + prepended += ' var __output = [], __append = __output.push.bind(__output);' + '\n'; | ||
511 | + if (opts._with !== false) { | ||
512 | + prepended += ' with (' + opts.localsName + ' || {}) {' + '\n'; | ||
513 | + appended += ' }' + '\n'; | ||
514 | + } | ||
515 | + appended += ' return __output.join("");' + '\n'; | ||
516 | + this.source = prepended + this.source + appended; | ||
517 | + } | ||
518 | + | ||
519 | + if (opts.compileDebug) { | ||
520 | + src = 'var __line = 1' + '\n' | ||
521 | + + ' , __lines = ' + JSON.stringify(this.templateText) + '\n' | ||
522 | + + ' , __filename = ' + (opts.filename ? | ||
523 | + JSON.stringify(opts.filename) : 'undefined') + ';' + '\n' | ||
524 | + + 'try {' + '\n' | ||
525 | + + this.source | ||
526 | + + '} catch (e) {' + '\n' | ||
527 | + + ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\n' | ||
528 | + + '}' + '\n'; | ||
529 | + } | ||
530 | + else { | ||
531 | + src = this.source; | ||
532 | + } | ||
533 | + | ||
534 | + if (opts.client) { | ||
535 | + src = 'escapeFn = escapeFn || ' + escapeFn.toString() + ';' + '\n' + src; | ||
536 | + if (opts.compileDebug) { | ||
537 | + src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\n' + src; | ||
538 | + } | ||
539 | + } | ||
540 | + | ||
541 | + if (opts.strict) { | ||
542 | + src = '"use strict";\n' + src; | ||
543 | + } | ||
544 | + if (opts.debug) { | ||
545 | + console.log(src); | ||
546 | + } | ||
547 | + | ||
548 | + try { | ||
549 | + fn = new Function(opts.localsName + ', escapeFn, include, rethrow', src); | ||
550 | + } | ||
551 | + catch(e) { | ||
552 | + // istanbul ignore else | ||
553 | + if (e instanceof SyntaxError) { | ||
554 | + if (opts.filename) { | ||
555 | + e.message += ' in ' + opts.filename; | ||
556 | + } | ||
557 | + e.message += ' while compiling ejs\n\n'; | ||
558 | + e.message += 'If the above error is not helpful, you may want to try EJS-Lint:\n'; | ||
559 | + e.message += 'https://github.com/RyanZim/EJS-Lint'; | ||
560 | + } | ||
561 | + throw e; | ||
562 | + } | ||
563 | + | ||
564 | + if (opts.client) { | ||
565 | + fn.dependencies = this.dependencies; | ||
566 | + return fn; | ||
567 | + } | ||
568 | + | ||
569 | + // Return a callable function which will execute the function | ||
570 | + // created by the source-code, with the passed data as locals | ||
571 | + // Adds a local `include` function which allows full recursive include | ||
572 | + var returnedFn = function (data) { | ||
573 | + var include = function (path, includeData) { | ||
574 | + var d = utils.shallowCopy({}, data); | ||
575 | + if (includeData) { | ||
576 | + d = utils.shallowCopy(d, includeData); | ||
577 | + } | ||
578 | + return includeFile(path, opts)(d); | ||
579 | + }; | ||
580 | + return fn.apply(opts.context, [data || {}, escapeFn, include, rethrow]); | ||
581 | + }; | ||
582 | + returnedFn.dependencies = this.dependencies; | ||
583 | + return returnedFn; | ||
584 | + }, | ||
585 | + | ||
586 | + generateSource: function () { | ||
587 | + var opts = this.opts; | ||
588 | + | ||
589 | + if (opts.rmWhitespace) { | ||
590 | + // Have to use two separate replace here as `^` and `$` operators don't | ||
591 | + // work well with `\r`. | ||
592 | + this.templateText = | ||
593 | + this.templateText.replace(/\r/g, '').replace(/^\s+|\s+$/gm, ''); | ||
594 | + } | ||
595 | + | ||
596 | + // Slurp spaces and tabs before <%_ and after _%> | ||
597 | + this.templateText = | ||
598 | + this.templateText.replace(/[ \t]*<%_/gm, '<%_').replace(/_%>[ \t]*/gm, '_%>'); | ||
599 | + | ||
600 | + var self = this; | ||
601 | + var matches = this.parseTemplateText(); | ||
602 | + var d = this.opts.delimiter; | ||
603 | + | ||
604 | + if (matches && matches.length) { | ||
605 | + matches.forEach(function (line, index) { | ||
606 | + var opening; | ||
607 | + var closing; | ||
608 | + var include; | ||
609 | + var includeOpts; | ||
610 | + var includeObj; | ||
611 | + var includeSrc; | ||
612 | + // If this is an opening tag, check for closing tags | ||
613 | + // FIXME: May end up with some false positives here | ||
614 | + // Better to store modes as k/v with '<' + delimiter as key | ||
615 | + // Then this can simply check against the map | ||
616 | + if ( line.indexOf('<' + d) === 0 // If it is a tag | ||
617 | + && line.indexOf('<' + d + d) !== 0) { // and is not escaped | ||
618 | + closing = matches[index + 2]; | ||
619 | + if (!(closing == d + '>' || closing == '-' + d + '>' || closing == '_' + d + '>')) { | ||
620 | + throw new Error('Could not find matching close tag for "' + line + '".'); | ||
621 | + } | ||
622 | + } | ||
623 | + // HACK: backward-compat `include` preprocessor directives | ||
624 | + if ((include = line.match(/^\s*include\s+(\S+)/))) { | ||
625 | + opening = matches[index - 1]; | ||
626 | + // Must be in EVAL or RAW mode | ||
627 | + if (opening && (opening == '<' + d || opening == '<' + d + '-' || opening == '<' + d + '_')) { | ||
628 | + includeOpts = utils.shallowCopy({}, self.opts); | ||
629 | + includeObj = includeSource(include[1], includeOpts); | ||
630 | + if (self.opts.compileDebug) { | ||
631 | + includeSrc = | ||
632 | + ' ; (function(){' + '\n' | ||
633 | + + ' var __line = 1' + '\n' | ||
634 | + + ' , __lines = ' + JSON.stringify(includeObj.template) + '\n' | ||
635 | + + ' , __filename = ' + JSON.stringify(includeObj.filename) + ';' + '\n' | ||
636 | + + ' try {' + '\n' | ||
637 | + + includeObj.source | ||
638 | + + ' } catch (e) {' + '\n' | ||
639 | + + ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\n' | ||
640 | + + ' }' + '\n' | ||
641 | + + ' ; }).call(this)' + '\n'; | ||
642 | + }else{ | ||
643 | + includeSrc = ' ; (function(){' + '\n' + includeObj.source + | ||
644 | + ' ; }).call(this)' + '\n'; | ||
645 | + } | ||
646 | + self.source += includeSrc; | ||
647 | + self.dependencies.push(exports.resolveInclude(include[1], | ||
648 | + includeOpts.filename)); | ||
649 | + return; | ||
650 | + } | ||
651 | + } | ||
652 | + self.scanLine(line); | ||
653 | + }); | ||
654 | + } | ||
655 | + | ||
656 | + }, | ||
657 | + | ||
658 | + parseTemplateText: function () { | ||
659 | + var str = this.templateText; | ||
660 | + var pat = this.regex; | ||
661 | + var result = pat.exec(str); | ||
662 | + var arr = []; | ||
663 | + var firstPos; | ||
664 | + | ||
665 | + while (result) { | ||
666 | + firstPos = result.index; | ||
667 | + | ||
668 | + if (firstPos !== 0) { | ||
669 | + arr.push(str.substring(0, firstPos)); | ||
670 | + str = str.slice(firstPos); | ||
671 | + } | ||
672 | + | ||
673 | + arr.push(result[0]); | ||
674 | + str = str.slice(result[0].length); | ||
675 | + result = pat.exec(str); | ||
676 | + } | ||
677 | + | ||
678 | + if (str) { | ||
679 | + arr.push(str); | ||
680 | + } | ||
681 | + | ||
682 | + return arr; | ||
683 | + }, | ||
684 | + | ||
685 | + _addOutput: function (line) { | ||
686 | + if (this.truncate) { | ||
687 | + // Only replace single leading linebreak in the line after | ||
688 | + // -%> tag -- this is the single, trailing linebreak | ||
689 | + // after the tag that the truncation mode replaces | ||
690 | + // Handle Win / Unix / old Mac linebreaks -- do the \r\n | ||
691 | + // combo first in the regex-or | ||
692 | + line = line.replace(/^(?:\r\n|\r|\n)/, ''); | ||
693 | + this.truncate = false; | ||
694 | + } | ||
695 | + else if (this.opts.rmWhitespace) { | ||
696 | + // rmWhitespace has already removed trailing spaces, just need | ||
697 | + // to remove linebreaks | ||
698 | + line = line.replace(/^\n/, ''); | ||
699 | + } | ||
700 | + if (!line) { | ||
701 | + return line; | ||
702 | + } | ||
703 | + | ||
704 | + // Preserve literal slashes | ||
705 | + line = line.replace(/\\/g, '\\\\'); | ||
706 | + | ||
707 | + // Convert linebreaks | ||
708 | + line = line.replace(/\n/g, '\\n'); | ||
709 | + line = line.replace(/\r/g, '\\r'); | ||
710 | + | ||
711 | + // Escape double-quotes | ||
712 | + // - this will be the delimiter during execution | ||
713 | + line = line.replace(/"/g, '\\"'); | ||
714 | + this.source += ' ; __append("' + line + '")' + '\n'; | ||
715 | + }, | ||
716 | + | ||
717 | + scanLine: function (line) { | ||
718 | + var self = this; | ||
719 | + var d = this.opts.delimiter; | ||
720 | + var newLineCount = 0; | ||
721 | + | ||
722 | + newLineCount = (line.split('\n').length - 1); | ||
723 | + | ||
724 | + switch (line) { | ||
725 | + case '<' + d: | ||
726 | + case '<' + d + '_': | ||
727 | + this.mode = Template.modes.EVAL; | ||
728 | + break; | ||
729 | + case '<' + d + '=': | ||
730 | + this.mode = Template.modes.ESCAPED; | ||
731 | + break; | ||
732 | + case '<' + d + '-': | ||
733 | + this.mode = Template.modes.RAW; | ||
734 | + break; | ||
735 | + case '<' + d + '#': | ||
736 | + this.mode = Template.modes.COMMENT; | ||
737 | + break; | ||
738 | + case '<' + d + d: | ||
739 | + this.mode = Template.modes.LITERAL; | ||
740 | + this.source += ' ; __append("' + line.replace('<' + d + d, '<' + d) + '")' + '\n'; | ||
741 | + break; | ||
742 | + case d + d + '>': | ||
743 | + this.mode = Template.modes.LITERAL; | ||
744 | + this.source += ' ; __append("' + line.replace(d + d + '>', d + '>') + '")' + '\n'; | ||
745 | + break; | ||
746 | + case d + '>': | ||
747 | + case '-' + d + '>': | ||
748 | + case '_' + d + '>': | ||
749 | + if (this.mode == Template.modes.LITERAL) { | ||
750 | + this._addOutput(line); | ||
751 | + } | ||
752 | + | ||
753 | + this.mode = null; | ||
754 | + this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0; | ||
755 | + break; | ||
756 | + default: | ||
757 | + // In script mode, depends on type of tag | ||
758 | + if (this.mode) { | ||
759 | + // If '//' is found without a line break, add a line break. | ||
760 | + switch (this.mode) { | ||
761 | + case Template.modes.EVAL: | ||
762 | + case Template.modes.ESCAPED: | ||
763 | + case Template.modes.RAW: | ||
764 | + if (line.lastIndexOf('//') > line.lastIndexOf('\n')) { | ||
765 | + line += '\n'; | ||
766 | + } | ||
767 | + } | ||
768 | + switch (this.mode) { | ||
769 | + // Just executing code | ||
770 | + case Template.modes.EVAL: | ||
771 | + this.source += ' ; ' + line + '\n'; | ||
772 | + break; | ||
773 | + // Exec, esc, and output | ||
774 | + case Template.modes.ESCAPED: | ||
775 | + this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\n'; | ||
776 | + break; | ||
777 | + // Exec and output | ||
778 | + case Template.modes.RAW: | ||
779 | + this.source += ' ; __append(' + stripSemi(line) + ')' + '\n'; | ||
780 | + break; | ||
781 | + case Template.modes.COMMENT: | ||
782 | + // Do nothing | ||
783 | + break; | ||
784 | + // Literal <%% mode, append as raw output | ||
785 | + case Template.modes.LITERAL: | ||
786 | + this._addOutput(line); | ||
787 | + break; | ||
788 | + } | ||
789 | + } | ||
790 | + // In string mode, just add the output | ||
791 | + else { | ||
792 | + this._addOutput(line); | ||
793 | + } | ||
794 | + } | ||
795 | + | ||
796 | + if (self.opts.compileDebug && newLineCount) { | ||
797 | + this.currentLine += newLineCount; | ||
798 | + this.source += ' ; __line = ' + this.currentLine + '\n'; | ||
799 | + } | ||
800 | + } | ||
801 | +}; | ||
802 | + | ||
803 | +/** | ||
804 | + * Escape characters reserved in XML. | ||
805 | + * | ||
806 | + * This is simply an export of {@link module:utils.escapeXML}. | ||
807 | + * | ||
808 | + * If `markup` is `undefined` or `null`, the empty string is returned. | ||
809 | + * | ||
810 | + * @param {String} markup Input string | ||
811 | + * @return {String} Escaped string | ||
812 | + * @public | ||
813 | + * @func | ||
814 | + * */ | ||
815 | +exports.escapeXML = utils.escapeXML; | ||
816 | + | ||
817 | +/** | ||
818 | + * Express.js support. | ||
819 | + * | ||
820 | + * This is an alias for {@link module:ejs.renderFile}, in order to support | ||
821 | + * Express.js out-of-the-box. | ||
822 | + * | ||
823 | + * @func | ||
824 | + */ | ||
825 | + | ||
826 | +exports.__express = exports.renderFile; | ||
827 | + | ||
828 | +// Add require support | ||
829 | +/* istanbul ignore else */ | ||
830 | +if (require.extensions) { | ||
831 | + require.extensions['.ejs'] = function (module, flnm) { | ||
832 | + var filename = flnm || /* istanbul ignore next */ module.filename; | ||
833 | + var options = { | ||
834 | + filename: filename, | ||
835 | + client: true | ||
836 | + }; | ||
837 | + var template = fileLoader(filename).toString(); | ||
838 | + var fn = exports.compile(template, options); | ||
839 | + module._compile('module.exports = ' + fn.toString() + ';', filename); | ||
840 | + }; | ||
841 | +} | ||
842 | + | ||
843 | +/** | ||
844 | + * Version of EJS. | ||
845 | + * | ||
846 | + * @readonly | ||
847 | + * @type {String} | ||
848 | + * @public | ||
849 | + */ | ||
850 | + | ||
851 | +exports.VERSION = _VERSION_STRING; | ||
852 | + | ||
853 | +/** | ||
854 | + * Name for detection of EJS. | ||
855 | + * | ||
856 | + * @readonly | ||
857 | + * @type {String} | ||
858 | + * @public | ||
859 | + */ | ||
860 | + | ||
861 | +exports.name = _NAME; | ||
862 | + | ||
863 | +/* istanbul ignore if */ | ||
864 | +if (typeof window != 'undefined') { | ||
865 | + window.ejs = exports; | ||
866 | +} |
node_modules/ejs/lib/utils.js
0 → 100644
1 | +/* | ||
2 | + * EJS Embedded JavaScript templates | ||
3 | + * Copyright 2112 Matthew Eernisse (mde@fleegix.org) | ||
4 | + * | ||
5 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + * you may not use this file except in compliance with the License. | ||
7 | + * You may obtain a copy of the License at | ||
8 | + * | ||
9 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + * | ||
11 | + * Unless required by applicable law or agreed to in writing, software | ||
12 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + * See the License for the specific language governing permissions and | ||
15 | + * limitations under the License. | ||
16 | + * | ||
17 | +*/ | ||
18 | + | ||
19 | +/** | ||
20 | + * Private utility functions | ||
21 | + * @module utils | ||
22 | + * @private | ||
23 | + */ | ||
24 | + | ||
25 | +'use strict'; | ||
26 | + | ||
27 | +var regExpChars = /[|\\{}()[\]^$+*?.]/g; | ||
28 | + | ||
29 | +/** | ||
30 | + * Escape characters reserved in regular expressions. | ||
31 | + * | ||
32 | + * If `string` is `undefined` or `null`, the empty string is returned. | ||
33 | + * | ||
34 | + * @param {String} string Input string | ||
35 | + * @return {String} Escaped string | ||
36 | + * @static | ||
37 | + * @private | ||
38 | + */ | ||
39 | +exports.escapeRegExpChars = function (string) { | ||
40 | + // istanbul ignore if | ||
41 | + if (!string) { | ||
42 | + return ''; | ||
43 | + } | ||
44 | + return String(string).replace(regExpChars, '\\$&'); | ||
45 | +}; | ||
46 | + | ||
47 | +var _ENCODE_HTML_RULES = { | ||
48 | + '&': '&', | ||
49 | + '<': '<', | ||
50 | + '>': '>', | ||
51 | + '"': '"', | ||
52 | + "'": ''' | ||
53 | +}; | ||
54 | +var _MATCH_HTML = /[&<>\'"]/g; | ||
55 | + | ||
56 | +function encode_char(c) { | ||
57 | + return _ENCODE_HTML_RULES[c] || c; | ||
58 | +} | ||
59 | + | ||
60 | +/** | ||
61 | + * Stringified version of constants used by {@link module:utils.escapeXML}. | ||
62 | + * | ||
63 | + * It is used in the process of generating {@link ClientFunction}s. | ||
64 | + * | ||
65 | + * @readonly | ||
66 | + * @type {String} | ||
67 | + */ | ||
68 | + | ||
69 | +var escapeFuncStr = | ||
70 | + 'var _ENCODE_HTML_RULES = {\n' | ||
71 | ++ ' "&": "&"\n' | ||
72 | ++ ' , "<": "<"\n' | ||
73 | ++ ' , ">": ">"\n' | ||
74 | ++ ' , \'"\': """\n' | ||
75 | ++ ' , "\'": "'"\n' | ||
76 | ++ ' }\n' | ||
77 | ++ ' , _MATCH_HTML = /[&<>\'"]/g;\n' | ||
78 | ++ 'function encode_char(c) {\n' | ||
79 | ++ ' return _ENCODE_HTML_RULES[c] || c;\n' | ||
80 | ++ '};\n'; | ||
81 | + | ||
82 | +/** | ||
83 | + * Escape characters reserved in XML. | ||
84 | + * | ||
85 | + * If `markup` is `undefined` or `null`, the empty string is returned. | ||
86 | + * | ||
87 | + * @implements {EscapeCallback} | ||
88 | + * @param {String} markup Input string | ||
89 | + * @return {String} Escaped string | ||
90 | + * @static | ||
91 | + * @private | ||
92 | + */ | ||
93 | + | ||
94 | +exports.escapeXML = function (markup) { | ||
95 | + return markup == undefined | ||
96 | + ? '' | ||
97 | + : String(markup) | ||
98 | + .replace(_MATCH_HTML, encode_char); | ||
99 | +}; | ||
100 | +exports.escapeXML.toString = function () { | ||
101 | + return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr; | ||
102 | +}; | ||
103 | + | ||
104 | +/** | ||
105 | + * Naive copy of properties from one object to another. | ||
106 | + * Does not recurse into non-scalar properties | ||
107 | + * Does not check to see if the property has a value before copying | ||
108 | + * | ||
109 | + * @param {Object} to Destination object | ||
110 | + * @param {Object} from Source object | ||
111 | + * @return {Object} Destination object | ||
112 | + * @static | ||
113 | + * @private | ||
114 | + */ | ||
115 | +exports.shallowCopy = function (to, from) { | ||
116 | + from = from || {}; | ||
117 | + for (var p in from) { | ||
118 | + to[p] = from[p]; | ||
119 | + } | ||
120 | + return to; | ||
121 | +}; | ||
122 | + | ||
123 | +/** | ||
124 | + * Naive copy of a list of key names, from one object to another. | ||
125 | + * Only copies property if it is actually defined | ||
126 | + * Does not recurse into non-scalar properties | ||
127 | + * | ||
128 | + * @param {Object} to Destination object | ||
129 | + * @param {Object} from Source object | ||
130 | + * @param {Array} list List of properties to copy | ||
131 | + * @return {Object} Destination object | ||
132 | + * @static | ||
133 | + * @private | ||
134 | + */ | ||
135 | +exports.shallowCopyFromList = function (to, from, list) { | ||
136 | + for (var i = 0; i < list.length; i++) { | ||
137 | + var p = list[i]; | ||
138 | + if (typeof from[p] != 'undefined') { | ||
139 | + to[p] = from[p]; | ||
140 | + } | ||
141 | + } | ||
142 | + return to; | ||
143 | +}; | ||
144 | + | ||
145 | +/** | ||
146 | + * Simple in-process cache implementation. Does not implement limits of any | ||
147 | + * sort. | ||
148 | + * | ||
149 | + * @implements Cache | ||
150 | + * @static | ||
151 | + * @private | ||
152 | + */ | ||
153 | +exports.cache = { | ||
154 | + _data: {}, | ||
155 | + set: function (key, val) { | ||
156 | + this._data[key] = val; | ||
157 | + }, | ||
158 | + get: function (key) { | ||
159 | + return this._data[key]; | ||
160 | + }, | ||
161 | + reset: function () { | ||
162 | + this._data = {}; | ||
163 | + } | ||
164 | +}; |
node_modules/ejs/package.json
0 → 100644
1 | +{ | ||
2 | + "_from": "ejs@~2.5.7", | ||
3 | + "_id": "ejs@2.5.7", | ||
4 | + "_inBundle": false, | ||
5 | + "_integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", | ||
6 | + "_location": "/ejs", | ||
7 | + "_phantomChildren": {}, | ||
8 | + "_requested": { | ||
9 | + "type": "range", | ||
10 | + "registry": true, | ||
11 | + "raw": "ejs@~2.5.7", | ||
12 | + "name": "ejs", | ||
13 | + "escapedName": "ejs", | ||
14 | + "rawSpec": "~2.5.7", | ||
15 | + "saveSpec": null, | ||
16 | + "fetchSpec": "~2.5.7" | ||
17 | + }, | ||
18 | + "_requiredBy": [ | ||
19 | + "/" | ||
20 | + ], | ||
21 | + "_resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", | ||
22 | + "_shasum": "cc872c168880ae3c7189762fd5ffc00896c9518a", | ||
23 | + "_spec": "ejs@~2.5.7", | ||
24 | + "_where": "/home/ubuntu/OpenSource_Project", | ||
25 | + "author": { | ||
26 | + "name": "Matthew Eernisse", | ||
27 | + "email": "mde@fleegix.org", | ||
28 | + "url": "http://fleegix.org" | ||
29 | + }, | ||
30 | + "bugs": { | ||
31 | + "url": "https://github.com/mde/ejs/issues" | ||
32 | + }, | ||
33 | + "bundleDependencies": false, | ||
34 | + "contributors": [ | ||
35 | + { | ||
36 | + "name": "Timothy Gu", | ||
37 | + "email": "timothygu99@gmail.com", | ||
38 | + "url": "https://timothygu.github.io" | ||
39 | + } | ||
40 | + ], | ||
41 | + "dependencies": {}, | ||
42 | + "deprecated": false, | ||
43 | + "description": "Embedded JavaScript templates", | ||
44 | + "devDependencies": { | ||
45 | + "browserify": "^13.0.1", | ||
46 | + "eslint": "^3.0.0", | ||
47 | + "git-directory-deploy": "^1.5.1", | ||
48 | + "istanbul": "~0.4.3", | ||
49 | + "jake": "^8.0.0", | ||
50 | + "jsdoc": "^3.4.0", | ||
51 | + "lru-cache": "^4.0.1", | ||
52 | + "mocha": "^3.0.2", | ||
53 | + "uglify-js": "^2.6.2" | ||
54 | + }, | ||
55 | + "engines": { | ||
56 | + "node": ">=0.10.0" | ||
57 | + }, | ||
58 | + "homepage": "https://github.com/mde/ejs", | ||
59 | + "keywords": [ | ||
60 | + "template", | ||
61 | + "engine", | ||
62 | + "ejs" | ||
63 | + ], | ||
64 | + "license": "Apache-2.0", | ||
65 | + "main": "./lib/ejs.js", | ||
66 | + "name": "ejs", | ||
67 | + "repository": { | ||
68 | + "type": "git", | ||
69 | + "url": "git://github.com/mde/ejs.git" | ||
70 | + }, | ||
71 | + "scripts": { | ||
72 | + "coverage": "istanbul cover node_modules/mocha/bin/_mocha", | ||
73 | + "devdoc": "jake doc[dev]", | ||
74 | + "doc": "jake doc", | ||
75 | + "lint": "eslint \"**/*.js\" Jakefile", | ||
76 | + "test": "jake test" | ||
77 | + }, | ||
78 | + "version": "2.5.7" | ||
79 | +} |
node_modules/morgan/HISTORY.md
0 → 100644
1 | +1.9.0 / 2017-09-26 | ||
2 | +================== | ||
3 | + | ||
4 | + * Use `res.headersSent` when available | ||
5 | + * deps: basic-auth@~2.0.0 | ||
6 | + - Use `safe-buffer` for improved Buffer API | ||
7 | + * deps: debug@2.6.9 | ||
8 | + * deps: depd@~1.1.1 | ||
9 | + - Remove unnecessary `Buffer` loading | ||
10 | + | ||
11 | +1.8.2 / 2017-05-23 | ||
12 | +================== | ||
13 | + | ||
14 | + * deps: debug@2.6.8 | ||
15 | + - Fix `DEBUG_MAX_ARRAY_LENGTH` | ||
16 | + - deps: ms@2.0.0 | ||
17 | + | ||
18 | +1.8.1 / 2017-02-04 | ||
19 | +================== | ||
20 | + | ||
21 | + * deps: debug@2.6.1 | ||
22 | + - Fix deprecation messages in WebStorm and other editors | ||
23 | + - Undeprecate `DEBUG_FD` set to `1` or `2` | ||
24 | + | ||
25 | +1.8.0 / 2017-02-04 | ||
26 | +================== | ||
27 | + | ||
28 | + * Fix sending unnecessary `undefined` argument to token functions | ||
29 | + * deps: basic-auth@~1.1.0 | ||
30 | + * deps: debug@2.6.0 | ||
31 | + - Allow colors in workers | ||
32 | + - Deprecated `DEBUG_FD` environment variable | ||
33 | + - Fix error when running under React Native | ||
34 | + - Use same color for same namespace | ||
35 | + - deps: ms@0.7.2 | ||
36 | + * perf: enable strict mode in compiled functions | ||
37 | + | ||
38 | +1.7.0 / 2016-02-18 | ||
39 | +================== | ||
40 | + | ||
41 | + * Add `digits` argument to `response-time` token | ||
42 | + * deps: depd@~1.1.0 | ||
43 | + - Enable strict mode in more places | ||
44 | + - Support web browser loading | ||
45 | + * deps: on-headers@~1.0.1 | ||
46 | + - perf: enable strict mode | ||
47 | + | ||
48 | +1.6.1 / 2015-07-03 | ||
49 | +================== | ||
50 | + | ||
51 | + * deps: basic-auth@~1.0.3 | ||
52 | + | ||
53 | +1.6.0 / 2015-06-12 | ||
54 | +================== | ||
55 | + | ||
56 | + * Add `morgan.compile(format)` export | ||
57 | + * Do not color 1xx status codes in `dev` format | ||
58 | + * Fix `response-time` token to not include response latency | ||
59 | + * Fix `status` token incorrectly displaying before response in `dev` format | ||
60 | + * Fix token return values to be `undefined` or a string | ||
61 | + * Improve representation of multiple headers in `req` and `res` tokens | ||
62 | + * Use `res.getHeader` in `res` token | ||
63 | + * deps: basic-auth@~1.0.2 | ||
64 | + - perf: enable strict mode | ||
65 | + - perf: hoist regular expression | ||
66 | + - perf: parse with regular expressions | ||
67 | + - perf: remove argument reassignment | ||
68 | + * deps: on-finished@~2.3.0 | ||
69 | + - Add defined behavior for HTTP `CONNECT` requests | ||
70 | + - Add defined behavior for HTTP `Upgrade` requests | ||
71 | + - deps: ee-first@1.1.1 | ||
72 | + * pref: enable strict mode | ||
73 | + * pref: reduce function closure scopes | ||
74 | + * pref: remove dynamic compile on every request for `dev` format | ||
75 | + * pref: remove an argument reassignment | ||
76 | + * pref: skip function call without `skip` option | ||
77 | + | ||
78 | +1.5.3 / 2015-05-10 | ||
79 | +================== | ||
80 | + | ||
81 | + * deps: basic-auth@~1.0.1 | ||
82 | + * deps: debug@~2.2.0 | ||
83 | + - deps: ms@0.7.1 | ||
84 | + * deps: depd@~1.0.1 | ||
85 | + * deps: on-finished@~2.2.1 | ||
86 | + - Fix `isFinished(req)` when data buffered | ||
87 | + | ||
88 | +1.5.2 / 2015-03-15 | ||
89 | +================== | ||
90 | + | ||
91 | + * deps: debug@~2.1.3 | ||
92 | + - Fix high intensity foreground color for bold | ||
93 | + - deps: ms@0.7.0 | ||
94 | + | ||
95 | +1.5.1 / 2014-12-31 | ||
96 | +================== | ||
97 | + | ||
98 | + * deps: debug@~2.1.1 | ||
99 | + * deps: on-finished@~2.2.0 | ||
100 | + | ||
101 | +1.5.0 / 2014-11-06 | ||
102 | +================== | ||
103 | + | ||
104 | + * Add multiple date formats | ||
105 | + - `clf` for the common log format | ||
106 | + - `iso` for the common ISO 8601 date time format | ||
107 | + - `web` for the common RFC 1123 date time format | ||
108 | + * Deprecate `buffer` option | ||
109 | + * Fix date format in `common` and `combined` formats | ||
110 | + * Fix token arguments to accept values with `"` | ||
111 | + | ||
112 | +1.4.1 / 2014-10-22 | ||
113 | +================== | ||
114 | + | ||
115 | + * deps: on-finished@~2.1.1 | ||
116 | + - Fix handling of pipelined requests | ||
117 | + | ||
118 | +1.4.0 / 2014-10-16 | ||
119 | +================== | ||
120 | + | ||
121 | + * Add `debug` messages | ||
122 | + * deps: depd@~1.0.0 | ||
123 | + | ||
124 | +1.3.2 / 2014-09-27 | ||
125 | +================== | ||
126 | + | ||
127 | + * Fix `req.ip` integration when `immediate: false` | ||
128 | + | ||
129 | +1.3.1 / 2014-09-14 | ||
130 | +================== | ||
131 | + | ||
132 | + * Remove un-used `bytes` dependency | ||
133 | + * deps: depd@0.4.5 | ||
134 | + | ||
135 | +1.3.0 / 2014-09-01 | ||
136 | +================== | ||
137 | + | ||
138 | + * Assert if `format` is not a function or string | ||
139 | + | ||
140 | +1.2.3 / 2014-08-16 | ||
141 | +================== | ||
142 | + | ||
143 | + * deps: on-finished@2.1.0 | ||
144 | + | ||
145 | +1.2.2 / 2014-07-27 | ||
146 | +================== | ||
147 | + | ||
148 | + * deps: depd@0.4.4 | ||
149 | + - Work-around v8 generating empty stack traces | ||
150 | + | ||
151 | +1.2.1 / 2014-07-26 | ||
152 | +================== | ||
153 | + | ||
154 | + * deps: depd@0.4.3 | ||
155 | + - Fix exception when global `Error.stackTraceLimit` is too low | ||
156 | + | ||
157 | +1.2.0 / 2014-07-19 | ||
158 | +================== | ||
159 | + | ||
160 | + * Add `:remote-user` token | ||
161 | + * Add `combined` log format | ||
162 | + * Add `common` log format | ||
163 | + * Add `morgan(format, options)` function signature | ||
164 | + * Deprecate `default` format -- use `combined` format instead | ||
165 | + * Deprecate not providing a format | ||
166 | + * Remove non-standard grey color from `dev` format | ||
167 | + | ||
168 | +1.1.1 / 2014-05-20 | ||
169 | +================== | ||
170 | + | ||
171 | + * simplify method to get remote address | ||
172 | + | ||
173 | +1.1.0 / 2014-05-18 | ||
174 | +================== | ||
175 | + | ||
176 | + * "dev" format will use same tokens as other formats | ||
177 | + * `:response-time` token is now empty when immediate used | ||
178 | + * `:response-time` token is now monotonic | ||
179 | + * `:response-time` token has precision to 1 μs | ||
180 | + * fix `:status` + immediate output in node.js 0.8 | ||
181 | + * improve `buffer` option to prevent indefinite event loop holding | ||
182 | + * deps: bytes@1.0.0 | ||
183 | + - add negative support | ||
184 | + | ||
185 | +1.0.1 / 2014-05-04 | ||
186 | +================== | ||
187 | + | ||
188 | + * Make buffer unique per morgan instance | ||
189 | + * deps: bytes@0.3.0 | ||
190 | + * added terabyte support | ||
191 | + | ||
192 | +1.0.0 / 2014-02-08 | ||
193 | +================== | ||
194 | + | ||
195 | + * Initial release |
node_modules/morgan/LICENSE
0 → 100644
1 | +(The MIT License) | ||
2 | + | ||
3 | +Copyright (c) 2014 Jonathan Ong <me@jongleberry.com> | ||
4 | +Copyright (c) 2014-2017 Douglas Christopher Wilson <doug@somethingdoug.com> | ||
5 | + | ||
6 | +Permission is hereby granted, free of charge, to any person obtaining | ||
7 | +a copy of this software and associated documentation files (the | ||
8 | +'Software'), to deal in the Software without restriction, including | ||
9 | +without limitation the rights to use, copy, modify, merge, publish, | ||
10 | +distribute, sublicense, and/or sell copies of the Software, and to | ||
11 | +permit persons to whom the Software is furnished to do so, subject to | ||
12 | +the following conditions: | ||
13 | + | ||
14 | +The above copyright notice and this permission notice shall be | ||
15 | +included in all copies or substantial portions of the Software. | ||
16 | + | ||
17 | +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||
18 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
19 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
20 | +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
21 | +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
22 | +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
23 | +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
node_modules/morgan/README.md
0 → 100644
1 | +# morgan | ||
2 | + | ||
3 | +[![NPM Version][npm-image]][npm-url] | ||
4 | +[![NPM Downloads][downloads-image]][downloads-url] | ||
5 | +[![Build Status][travis-image]][travis-url] | ||
6 | +[![Test Coverage][coveralls-image]][coveralls-url] | ||
7 | +[![Gratipay][gratipay-image]][gratipay-url] | ||
8 | + | ||
9 | +HTTP request logger middleware for node.js | ||
10 | + | ||
11 | +> Named after [Dexter](http://en.wikipedia.org/wiki/Dexter_Morgan), a show you should not watch until completion. | ||
12 | + | ||
13 | +## API | ||
14 | + | ||
15 | +<!-- eslint-disable no-unused-vars --> | ||
16 | + | ||
17 | +```js | ||
18 | +var morgan = require('morgan') | ||
19 | +``` | ||
20 | + | ||
21 | +### morgan(format, options) | ||
22 | + | ||
23 | +Create a new morgan logger middleware function using the given `format` and `options`. | ||
24 | +The `format` argument may be a string of a predefined name (see below for the names), | ||
25 | +a string of a format string, or a function that will produce a log entry. | ||
26 | + | ||
27 | +The `format` function will be called with three arguments `tokens`, `req`, and `res`, | ||
28 | +where `tokens` is an object with all defined tokens, `req` is the HTTP request and `res` | ||
29 | +is the HTTP response. The function is expected to return a string that will be the log | ||
30 | +line, or `undefined` / `null` to skip logging. | ||
31 | + | ||
32 | +#### Using a predefined format string | ||
33 | + | ||
34 | +<!-- eslint-disable no-undef --> | ||
35 | + | ||
36 | +```js | ||
37 | +morgan('tiny') | ||
38 | +``` | ||
39 | + | ||
40 | +#### Using format string of predefined tokens | ||
41 | + | ||
42 | +<!-- eslint-disable no-undef --> | ||
43 | + | ||
44 | +```js | ||
45 | +morgan(':method :url :status :res[content-length] - :response-time ms') | ||
46 | +``` | ||
47 | + | ||
48 | +#### Using a custom format function | ||
49 | + | ||
50 | +<!-- eslint-disable no-undef --> | ||
51 | + | ||
52 | +``` js | ||
53 | +morgan(function (tokens, req, res) { | ||
54 | + return [ | ||
55 | + tokens.method(req, res), | ||
56 | + tokens.url(req, res), | ||
57 | + tokens.status(req, res), | ||
58 | + tokens.res(req, res, 'content-length'), '-', | ||
59 | + tokens['response-time'](req, res), 'ms' | ||
60 | + ].join(' ') | ||
61 | +}) | ||
62 | +``` | ||
63 | + | ||
64 | +#### Options | ||
65 | + | ||
66 | +Morgan accepts these properties in the options object. | ||
67 | + | ||
68 | +##### immediate | ||
69 | + | ||
70 | +Write log line on request instead of response. This means that a requests will | ||
71 | +be logged even if the server crashes, _but data from the response (like the | ||
72 | +response code, content length, etc.) cannot be logged_. | ||
73 | + | ||
74 | +##### skip | ||
75 | + | ||
76 | +Function to determine if logging is skipped, defaults to `false`. This function | ||
77 | +will be called as `skip(req, res)`. | ||
78 | + | ||
79 | +<!-- eslint-disable no-undef --> | ||
80 | + | ||
81 | +```js | ||
82 | +// EXAMPLE: only log error responses | ||
83 | +morgan('combined', { | ||
84 | + skip: function (req, res) { return res.statusCode < 400 } | ||
85 | +}) | ||
86 | +``` | ||
87 | + | ||
88 | +##### stream | ||
89 | + | ||
90 | +Output stream for writing log lines, defaults to `process.stdout`. | ||
91 | + | ||
92 | +#### Predefined Formats | ||
93 | + | ||
94 | +There are various pre-defined formats provided: | ||
95 | + | ||
96 | +##### combined | ||
97 | + | ||
98 | +Standard Apache combined log output. | ||
99 | + | ||
100 | +``` | ||
101 | +:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent" | ||
102 | +``` | ||
103 | + | ||
104 | +##### common | ||
105 | + | ||
106 | +Standard Apache common log output. | ||
107 | + | ||
108 | +``` | ||
109 | +:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] | ||
110 | +``` | ||
111 | + | ||
112 | +##### dev | ||
113 | + | ||
114 | +Concise output colored by response status for development use. The `:status` | ||
115 | +token will be colored red for server error codes, yellow for client error | ||
116 | +codes, cyan for redirection codes, and uncolored for all other codes. | ||
117 | + | ||
118 | +``` | ||
119 | +:method :url :status :response-time ms - :res[content-length] | ||
120 | +``` | ||
121 | + | ||
122 | +##### short | ||
123 | + | ||
124 | +Shorter than default, also including response time. | ||
125 | + | ||
126 | +``` | ||
127 | +:remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms | ||
128 | +``` | ||
129 | + | ||
130 | +##### tiny | ||
131 | + | ||
132 | +The minimal output. | ||
133 | + | ||
134 | +``` | ||
135 | +:method :url :status :res[content-length] - :response-time ms | ||
136 | +``` | ||
137 | + | ||
138 | +#### Tokens | ||
139 | + | ||
140 | +##### Creating new tokens | ||
141 | + | ||
142 | +To define a token, simply invoke `morgan.token()` with the name and a callback function. | ||
143 | +This callback function is expected to return a string value. The value returned is then | ||
144 | +available as ":type" in this case: | ||
145 | + | ||
146 | +<!-- eslint-disable no-undef --> | ||
147 | + | ||
148 | +```js | ||
149 | +morgan.token('type', function (req, res) { return req.headers['content-type'] }) | ||
150 | +``` | ||
151 | + | ||
152 | +Calling `morgan.token()` using the same name as an existing token will overwrite that | ||
153 | +token definition. | ||
154 | + | ||
155 | +The token function is expected to be called with the arguments `req` and `res`, representing | ||
156 | +the HTTP request and HTTP response. Additionally, the token can accept further arguments of | ||
157 | +it's choosing to customize behavior. | ||
158 | + | ||
159 | +##### :date[format] | ||
160 | + | ||
161 | +The current date and time in UTC. The available formats are: | ||
162 | + | ||
163 | + - `clf` for the common log format (`"10/Oct/2000:13:55:36 +0000"`) | ||
164 | + - `iso` for the common ISO 8601 date time format (`2000-10-10T13:55:36.000Z`) | ||
165 | + - `web` for the common RFC 1123 date time format (`Tue, 10 Oct 2000 13:55:36 GMT`) | ||
166 | + | ||
167 | +If no format is given, then the default is `web`. | ||
168 | + | ||
169 | +##### :http-version | ||
170 | + | ||
171 | +The HTTP version of the request. | ||
172 | + | ||
173 | +##### :method | ||
174 | + | ||
175 | +The HTTP method of the request. | ||
176 | + | ||
177 | +##### :referrer | ||
178 | + | ||
179 | +The Referrer header of the request. This will use the standard mis-spelled Referer header if exists, otherwise Referrer. | ||
180 | + | ||
181 | +##### :remote-addr | ||
182 | + | ||
183 | +The remote address of the request. This will use `req.ip`, otherwise the standard `req.connection.remoteAddress` value (socket address). | ||
184 | + | ||
185 | +##### :remote-user | ||
186 | + | ||
187 | +The user authenticated as part of Basic auth for the request. | ||
188 | + | ||
189 | +##### :req[header] | ||
190 | + | ||
191 | +The given `header` of the request. | ||
192 | + | ||
193 | +##### :res[header] | ||
194 | + | ||
195 | +The given `header` of the response. | ||
196 | + | ||
197 | +##### :response-time[digits] | ||
198 | + | ||
199 | +The time between the request coming into `morgan` and when the response | ||
200 | +headers are written, in milliseconds. | ||
201 | + | ||
202 | +The `digits` argument is a number that specifies the number of digits to | ||
203 | +include on the number, defaulting to `3`, which provides microsecond precision. | ||
204 | + | ||
205 | +##### :status | ||
206 | + | ||
207 | +The status code of the response. | ||
208 | + | ||
209 | +If the request/response cycle completes before a response was sent to the | ||
210 | +client (for example, the TCP socket closed prematurely by a client aborting | ||
211 | +the request), then the status will be empty (displayed as `"-"` in the log). | ||
212 | + | ||
213 | +##### :url | ||
214 | + | ||
215 | +The URL of the request. This will use `req.originalUrl` if exists, otherwise `req.url`. | ||
216 | + | ||
217 | +##### :user-agent | ||
218 | + | ||
219 | +The contents of the User-Agent header of the request. | ||
220 | + | ||
221 | +### morgan.compile(format) | ||
222 | + | ||
223 | +Compile a format string into a `format` function for use by `morgan`. A format string | ||
224 | +is a string that represents a single log line and can utilize token syntax. | ||
225 | +Tokens are references by `:token-name`. If tokens accept arguments, they can | ||
226 | +be passed using `[]`, for example: `:token-name[pretty]` would pass the string | ||
227 | +`'pretty'` as an argument to the token `token-name`. | ||
228 | + | ||
229 | +The function returned from `morgan.compile` takes three arguments `tokens`, `req`, and | ||
230 | +`res`, where `tokens` is object with all defined tokens, `req` is the HTTP request and | ||
231 | +`res` is the HTTP response. The function will return a string that will be the log line, | ||
232 | +or `undefined` / `null` to skip logging. | ||
233 | + | ||
234 | +Normally formats are defined using `morgan.format(name, format)`, but for certain | ||
235 | +advanced uses, this compile function is directly available. | ||
236 | + | ||
237 | +## Examples | ||
238 | + | ||
239 | +### express/connect | ||
240 | + | ||
241 | +Simple app that will log all request in the Apache combined format to STDOUT | ||
242 | + | ||
243 | +```js | ||
244 | +var express = require('express') | ||
245 | +var morgan = require('morgan') | ||
246 | + | ||
247 | +var app = express() | ||
248 | + | ||
249 | +app.use(morgan('combined')) | ||
250 | + | ||
251 | +app.get('/', function (req, res) { | ||
252 | + res.send('hello, world!') | ||
253 | +}) | ||
254 | +``` | ||
255 | + | ||
256 | +### vanilla http server | ||
257 | + | ||
258 | +Simple app that will log all request in the Apache combined format to STDOUT | ||
259 | + | ||
260 | +```js | ||
261 | +var finalhandler = require('finalhandler') | ||
262 | +var http = require('http') | ||
263 | +var morgan = require('morgan') | ||
264 | + | ||
265 | +// create "middleware" | ||
266 | +var logger = morgan('combined') | ||
267 | + | ||
268 | +http.createServer(function (req, res) { | ||
269 | + var done = finalhandler(req, res) | ||
270 | + logger(req, res, function (err) { | ||
271 | + if (err) return done(err) | ||
272 | + | ||
273 | + // respond to request | ||
274 | + res.setHeader('content-type', 'text/plain') | ||
275 | + res.end('hello, world!') | ||
276 | + }) | ||
277 | +}) | ||
278 | +``` | ||
279 | + | ||
280 | +### write logs to a file | ||
281 | + | ||
282 | +#### single file | ||
283 | + | ||
284 | +Simple app that will log all requests in the Apache combined format to the file | ||
285 | +`access.log`. | ||
286 | + | ||
287 | +```js | ||
288 | +var express = require('express') | ||
289 | +var fs = require('fs') | ||
290 | +var morgan = require('morgan') | ||
291 | +var path = require('path') | ||
292 | + | ||
293 | +var app = express() | ||
294 | + | ||
295 | +// create a write stream (in append mode) | ||
296 | +var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), {flags: 'a'}) | ||
297 | + | ||
298 | +// setup the logger | ||
299 | +app.use(morgan('combined', {stream: accessLogStream})) | ||
300 | + | ||
301 | +app.get('/', function (req, res) { | ||
302 | + res.send('hello, world!') | ||
303 | +}) | ||
304 | +``` | ||
305 | + | ||
306 | +#### log file rotation | ||
307 | + | ||
308 | +Simple app that will log all requests in the Apache combined format to one log | ||
309 | +file per day in the `log/` directory using the | ||
310 | +[rotating-file-stream module](https://www.npmjs.com/package/rotating-file-stream). | ||
311 | + | ||
312 | +```js | ||
313 | +var express = require('express') | ||
314 | +var fs = require('fs') | ||
315 | +var morgan = require('morgan') | ||
316 | +var path = require('path') | ||
317 | +var rfs = require('rotating-file-stream') | ||
318 | + | ||
319 | +var app = express() | ||
320 | +var logDirectory = path.join(__dirname, 'log') | ||
321 | + | ||
322 | +// ensure log directory exists | ||
323 | +fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory) | ||
324 | + | ||
325 | +// create a rotating write stream | ||
326 | +var accessLogStream = rfs('access.log', { | ||
327 | + interval: '1d', // rotate daily | ||
328 | + path: logDirectory | ||
329 | +}) | ||
330 | + | ||
331 | +// setup the logger | ||
332 | +app.use(morgan('combined', {stream: accessLogStream})) | ||
333 | + | ||
334 | +app.get('/', function (req, res) { | ||
335 | + res.send('hello, world!') | ||
336 | +}) | ||
337 | +``` | ||
338 | + | ||
339 | +### split / dual logging | ||
340 | + | ||
341 | +The `morgan` middleware can be used as many times as needed, enabling | ||
342 | +combinations like: | ||
343 | + | ||
344 | + * Log entry on request and one on response | ||
345 | + * Log all requests to file, but errors to console | ||
346 | + * ... and more! | ||
347 | + | ||
348 | +Sample app that will log all requests to a file using Apache format, but | ||
349 | +error responses are logged to the console: | ||
350 | + | ||
351 | +```js | ||
352 | +var express = require('express') | ||
353 | +var fs = require('fs') | ||
354 | +var morgan = require('morgan') | ||
355 | +var path = require('path') | ||
356 | + | ||
357 | +var app = express() | ||
358 | + | ||
359 | +// log only 4xx and 5xx responses to console | ||
360 | +app.use(morgan('dev', { | ||
361 | + skip: function (req, res) { return res.statusCode < 400 } | ||
362 | +})) | ||
363 | + | ||
364 | +// log all requests to access.log | ||
365 | +app.use(morgan('common', { | ||
366 | + stream: fs.createWriteStream(path.join(__dirname, 'access.log'), {flags: 'a'}) | ||
367 | +})) | ||
368 | + | ||
369 | +app.get('/', function (req, res) { | ||
370 | + res.send('hello, world!') | ||
371 | +}) | ||
372 | +``` | ||
373 | + | ||
374 | +### use custom token formats | ||
375 | + | ||
376 | +Sample app that will use custom token formats. This adds an ID to all requests and displays it using the `:id` token. | ||
377 | + | ||
378 | +```js | ||
379 | +var express = require('express') | ||
380 | +var morgan = require('morgan') | ||
381 | +var uuid = require('node-uuid') | ||
382 | + | ||
383 | +morgan.token('id', function getId (req) { | ||
384 | + return req.id | ||
385 | +}) | ||
386 | + | ||
387 | +var app = express() | ||
388 | + | ||
389 | +app.use(assignId) | ||
390 | +app.use(morgan(':id :method :url :response-time')) | ||
391 | + | ||
392 | +app.get('/', function (req, res) { | ||
393 | + res.send('hello, world!') | ||
394 | +}) | ||
395 | + | ||
396 | +function assignId (req, res, next) { | ||
397 | + req.id = uuid.v4() | ||
398 | + next() | ||
399 | +} | ||
400 | +``` | ||
401 | + | ||
402 | +## License | ||
403 | + | ||
404 | +[MIT](LICENSE) | ||
405 | + | ||
406 | +[npm-image]: https://img.shields.io/npm/v/morgan.svg | ||
407 | +[npm-url]: https://npmjs.org/package/morgan | ||
408 | +[travis-image]: https://img.shields.io/travis/expressjs/morgan/master.svg | ||
409 | +[travis-url]: https://travis-ci.org/expressjs/morgan | ||
410 | +[coveralls-image]: https://img.shields.io/coveralls/expressjs/morgan/master.svg | ||
411 | +[coveralls-url]: https://coveralls.io/r/expressjs/morgan?branch=master | ||
412 | +[downloads-image]: https://img.shields.io/npm/dm/morgan.svg | ||
413 | +[downloads-url]: https://npmjs.org/package/morgan | ||
414 | +[gratipay-image]: https://img.shields.io/gratipay/dougwilson.svg | ||
415 | +[gratipay-url]: https://www.gratipay.com/dougwilson/ |
node_modules/morgan/index.js
0 → 100644
1 | +/*! | ||
2 | + * morgan | ||
3 | + * Copyright(c) 2010 Sencha Inc. | ||
4 | + * Copyright(c) 2011 TJ Holowaychuk | ||
5 | + * Copyright(c) 2014 Jonathan Ong | ||
6 | + * Copyright(c) 2014-2017 Douglas Christopher Wilson | ||
7 | + * MIT Licensed | ||
8 | + */ | ||
9 | + | ||
10 | +'use strict' | ||
11 | + | ||
12 | +/** | ||
13 | + * Module exports. | ||
14 | + * @public | ||
15 | + */ | ||
16 | + | ||
17 | +module.exports = morgan | ||
18 | +module.exports.compile = compile | ||
19 | +module.exports.format = format | ||
20 | +module.exports.token = token | ||
21 | + | ||
22 | +/** | ||
23 | + * Module dependencies. | ||
24 | + * @private | ||
25 | + */ | ||
26 | + | ||
27 | +var auth = require('basic-auth') | ||
28 | +var debug = require('debug')('morgan') | ||
29 | +var deprecate = require('depd')('morgan') | ||
30 | +var onFinished = require('on-finished') | ||
31 | +var onHeaders = require('on-headers') | ||
32 | + | ||
33 | +/** | ||
34 | + * Array of CLF month names. | ||
35 | + * @private | ||
36 | + */ | ||
37 | + | ||
38 | +var CLF_MONTH = [ | ||
39 | + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', | ||
40 | + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' | ||
41 | +] | ||
42 | + | ||
43 | +/** | ||
44 | + * Default log buffer duration. | ||
45 | + * @private | ||
46 | + */ | ||
47 | + | ||
48 | +var DEFAULT_BUFFER_DURATION = 1000 | ||
49 | + | ||
50 | +/** | ||
51 | + * Create a logger middleware. | ||
52 | + * | ||
53 | + * @public | ||
54 | + * @param {String|Function} format | ||
55 | + * @param {Object} [options] | ||
56 | + * @return {Function} middleware | ||
57 | + */ | ||
58 | + | ||
59 | +function morgan (format, options) { | ||
60 | + var fmt = format | ||
61 | + var opts = options || {} | ||
62 | + | ||
63 | + if (format && typeof format === 'object') { | ||
64 | + opts = format | ||
65 | + fmt = opts.format || 'default' | ||
66 | + | ||
67 | + // smart deprecation message | ||
68 | + deprecate('morgan(options): use morgan(' + (typeof fmt === 'string' ? JSON.stringify(fmt) : 'format') + ', options) instead') | ||
69 | + } | ||
70 | + | ||
71 | + if (fmt === undefined) { | ||
72 | + deprecate('undefined format: specify a format') | ||
73 | + } | ||
74 | + | ||
75 | + // output on request instead of response | ||
76 | + var immediate = opts.immediate | ||
77 | + | ||
78 | + // check if log entry should be skipped | ||
79 | + var skip = opts.skip || false | ||
80 | + | ||
81 | + // format function | ||
82 | + var formatLine = typeof fmt !== 'function' | ||
83 | + ? getFormatFunction(fmt) | ||
84 | + : fmt | ||
85 | + | ||
86 | + // stream | ||
87 | + var buffer = opts.buffer | ||
88 | + var stream = opts.stream || process.stdout | ||
89 | + | ||
90 | + // buffering support | ||
91 | + if (buffer) { | ||
92 | + deprecate('buffer option') | ||
93 | + | ||
94 | + // flush interval | ||
95 | + var interval = typeof buffer !== 'number' | ||
96 | + ? DEFAULT_BUFFER_DURATION | ||
97 | + : buffer | ||
98 | + | ||
99 | + // swap the stream | ||
100 | + stream = createBufferStream(stream, interval) | ||
101 | + } | ||
102 | + | ||
103 | + return function logger (req, res, next) { | ||
104 | + // request data | ||
105 | + req._startAt = undefined | ||
106 | + req._startTime = undefined | ||
107 | + req._remoteAddress = getip(req) | ||
108 | + | ||
109 | + // response data | ||
110 | + res._startAt = undefined | ||
111 | + res._startTime = undefined | ||
112 | + | ||
113 | + // record request start | ||
114 | + recordStartTime.call(req) | ||
115 | + | ||
116 | + function logRequest () { | ||
117 | + if (skip !== false && skip(req, res)) { | ||
118 | + debug('skip request') | ||
119 | + return | ||
120 | + } | ||
121 | + | ||
122 | + var line = formatLine(morgan, req, res) | ||
123 | + | ||
124 | + if (line == null) { | ||
125 | + debug('skip line') | ||
126 | + return | ||
127 | + } | ||
128 | + | ||
129 | + debug('log request') | ||
130 | + stream.write(line + '\n') | ||
131 | + }; | ||
132 | + | ||
133 | + if (immediate) { | ||
134 | + // immediate log | ||
135 | + logRequest() | ||
136 | + } else { | ||
137 | + // record response start | ||
138 | + onHeaders(res, recordStartTime) | ||
139 | + | ||
140 | + // log when response finished | ||
141 | + onFinished(res, logRequest) | ||
142 | + } | ||
143 | + | ||
144 | + next() | ||
145 | + } | ||
146 | +} | ||
147 | + | ||
148 | +/** | ||
149 | + * Apache combined log format. | ||
150 | + */ | ||
151 | + | ||
152 | +morgan.format('combined', ':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"') | ||
153 | + | ||
154 | +/** | ||
155 | + * Apache common log format. | ||
156 | + */ | ||
157 | + | ||
158 | +morgan.format('common', ':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length]') | ||
159 | + | ||
160 | +/** | ||
161 | + * Default format. | ||
162 | + */ | ||
163 | + | ||
164 | +morgan.format('default', ':remote-addr - :remote-user [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"') | ||
165 | +deprecate.property(morgan, 'default', 'default format: use combined format') | ||
166 | + | ||
167 | +/** | ||
168 | + * Short format. | ||
169 | + */ | ||
170 | + | ||
171 | +morgan.format('short', ':remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms') | ||
172 | + | ||
173 | +/** | ||
174 | + * Tiny format. | ||
175 | + */ | ||
176 | + | ||
177 | +morgan.format('tiny', ':method :url :status :res[content-length] - :response-time ms') | ||
178 | + | ||
179 | +/** | ||
180 | + * dev (colored) | ||
181 | + */ | ||
182 | + | ||
183 | +morgan.format('dev', function developmentFormatLine (tokens, req, res) { | ||
184 | + // get the status code if response written | ||
185 | + var status = headersSent(res) | ||
186 | + ? res.statusCode | ||
187 | + : undefined | ||
188 | + | ||
189 | + // get status color | ||
190 | + var color = status >= 500 ? 31 // red | ||
191 | + : status >= 400 ? 33 // yellow | ||
192 | + : status >= 300 ? 36 // cyan | ||
193 | + : status >= 200 ? 32 // green | ||
194 | + : 0 // no color | ||
195 | + | ||
196 | + // get colored function | ||
197 | + var fn = developmentFormatLine[color] | ||
198 | + | ||
199 | + if (!fn) { | ||
200 | + // compile | ||
201 | + fn = developmentFormatLine[color] = compile('\x1b[0m:method :url \x1b[' + | ||
202 | + color + 'm:status \x1b[0m:response-time ms - :res[content-length]\x1b[0m') | ||
203 | + } | ||
204 | + | ||
205 | + return fn(tokens, req, res) | ||
206 | +}) | ||
207 | + | ||
208 | +/** | ||
209 | + * request url | ||
210 | + */ | ||
211 | + | ||
212 | +morgan.token('url', function getUrlToken (req) { | ||
213 | + return req.originalUrl || req.url | ||
214 | +}) | ||
215 | + | ||
216 | +/** | ||
217 | + * request method | ||
218 | + */ | ||
219 | + | ||
220 | +morgan.token('method', function getMethodToken (req) { | ||
221 | + return req.method | ||
222 | +}) | ||
223 | + | ||
224 | +/** | ||
225 | + * response time in milliseconds | ||
226 | + */ | ||
227 | + | ||
228 | +morgan.token('response-time', function getResponseTimeToken (req, res, digits) { | ||
229 | + if (!req._startAt || !res._startAt) { | ||
230 | + // missing request and/or response start time | ||
231 | + return | ||
232 | + } | ||
233 | + | ||
234 | + // calculate diff | ||
235 | + var ms = (res._startAt[0] - req._startAt[0]) * 1e3 + | ||
236 | + (res._startAt[1] - req._startAt[1]) * 1e-6 | ||
237 | + | ||
238 | + // return truncated value | ||
239 | + return ms.toFixed(digits === undefined ? 3 : digits) | ||
240 | +}) | ||
241 | + | ||
242 | +/** | ||
243 | + * current date | ||
244 | + */ | ||
245 | + | ||
246 | +morgan.token('date', function getDateToken (req, res, format) { | ||
247 | + var date = new Date() | ||
248 | + | ||
249 | + switch (format || 'web') { | ||
250 | + case 'clf': | ||
251 | + return clfdate(date) | ||
252 | + case 'iso': | ||
253 | + return date.toISOString() | ||
254 | + case 'web': | ||
255 | + return date.toUTCString() | ||
256 | + } | ||
257 | +}) | ||
258 | + | ||
259 | +/** | ||
260 | + * response status code | ||
261 | + */ | ||
262 | + | ||
263 | +morgan.token('status', function getStatusToken (req, res) { | ||
264 | + return headersSent(res) | ||
265 | + ? String(res.statusCode) | ||
266 | + : undefined | ||
267 | +}) | ||
268 | + | ||
269 | +/** | ||
270 | + * normalized referrer | ||
271 | + */ | ||
272 | + | ||
273 | +morgan.token('referrer', function getReferrerToken (req) { | ||
274 | + return req.headers['referer'] || req.headers['referrer'] | ||
275 | +}) | ||
276 | + | ||
277 | +/** | ||
278 | + * remote address | ||
279 | + */ | ||
280 | + | ||
281 | +morgan.token('remote-addr', getip) | ||
282 | + | ||
283 | +/** | ||
284 | + * remote user | ||
285 | + */ | ||
286 | + | ||
287 | +morgan.token('remote-user', function getRemoteUserToken (req) { | ||
288 | + // parse basic credentials | ||
289 | + var credentials = auth(req) | ||
290 | + | ||
291 | + // return username | ||
292 | + return credentials | ||
293 | + ? credentials.name | ||
294 | + : undefined | ||
295 | +}) | ||
296 | + | ||
297 | +/** | ||
298 | + * HTTP version | ||
299 | + */ | ||
300 | + | ||
301 | +morgan.token('http-version', function getHttpVersionToken (req) { | ||
302 | + return req.httpVersionMajor + '.' + req.httpVersionMinor | ||
303 | +}) | ||
304 | + | ||
305 | +/** | ||
306 | + * UA string | ||
307 | + */ | ||
308 | + | ||
309 | +morgan.token('user-agent', function getUserAgentToken (req) { | ||
310 | + return req.headers['user-agent'] | ||
311 | +}) | ||
312 | + | ||
313 | +/** | ||
314 | + * request header | ||
315 | + */ | ||
316 | + | ||
317 | +morgan.token('req', function getRequestToken (req, res, field) { | ||
318 | + // get header | ||
319 | + var header = req.headers[field.toLowerCase()] | ||
320 | + | ||
321 | + return Array.isArray(header) | ||
322 | + ? header.join(', ') | ||
323 | + : header | ||
324 | +}) | ||
325 | + | ||
326 | +/** | ||
327 | + * response header | ||
328 | + */ | ||
329 | + | ||
330 | +morgan.token('res', function getResponseHeader (req, res, field) { | ||
331 | + if (!headersSent(res)) { | ||
332 | + return undefined | ||
333 | + } | ||
334 | + | ||
335 | + // get header | ||
336 | + var header = res.getHeader(field) | ||
337 | + | ||
338 | + return Array.isArray(header) | ||
339 | + ? header.join(', ') | ||
340 | + : header | ||
341 | +}) | ||
342 | + | ||
343 | +/** | ||
344 | + * Format a Date in the common log format. | ||
345 | + * | ||
346 | + * @private | ||
347 | + * @param {Date} dateTime | ||
348 | + * @return {string} | ||
349 | + */ | ||
350 | + | ||
351 | +function clfdate (dateTime) { | ||
352 | + var date = dateTime.getUTCDate() | ||
353 | + var hour = dateTime.getUTCHours() | ||
354 | + var mins = dateTime.getUTCMinutes() | ||
355 | + var secs = dateTime.getUTCSeconds() | ||
356 | + var year = dateTime.getUTCFullYear() | ||
357 | + | ||
358 | + var month = CLF_MONTH[dateTime.getUTCMonth()] | ||
359 | + | ||
360 | + return pad2(date) + '/' + month + '/' + year + | ||
361 | + ':' + pad2(hour) + ':' + pad2(mins) + ':' + pad2(secs) + | ||
362 | + ' +0000' | ||
363 | +} | ||
364 | + | ||
365 | +/** | ||
366 | + * Compile a format string into a function. | ||
367 | + * | ||
368 | + * @param {string} format | ||
369 | + * @return {function} | ||
370 | + * @public | ||
371 | + */ | ||
372 | + | ||
373 | +function compile (format) { | ||
374 | + if (typeof format !== 'string') { | ||
375 | + throw new TypeError('argument format must be a string') | ||
376 | + } | ||
377 | + | ||
378 | + var fmt = format.replace(/"/g, '\\"') | ||
379 | + var js = ' "use strict"\n return "' + fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, function (_, name, arg) { | ||
380 | + var tokenArguments = 'req, res' | ||
381 | + var tokenFunction = 'tokens[' + String(JSON.stringify(name)) + ']' | ||
382 | + | ||
383 | + if (arg !== undefined) { | ||
384 | + tokenArguments += ', ' + String(JSON.stringify(arg)) | ||
385 | + } | ||
386 | + | ||
387 | + return '" +\n (' + tokenFunction + '(' + tokenArguments + ') || "-") + "' | ||
388 | + }) + '"' | ||
389 | + | ||
390 | + // eslint-disable-next-line no-new-func | ||
391 | + return new Function('tokens, req, res', js) | ||
392 | +} | ||
393 | + | ||
394 | +/** | ||
395 | + * Create a basic buffering stream. | ||
396 | + * | ||
397 | + * @param {object} stream | ||
398 | + * @param {number} interval | ||
399 | + * @public | ||
400 | + */ | ||
401 | + | ||
402 | +function createBufferStream (stream, interval) { | ||
403 | + var buf = [] | ||
404 | + var timer = null | ||
405 | + | ||
406 | + // flush function | ||
407 | + function flush () { | ||
408 | + timer = null | ||
409 | + stream.write(buf.join('')) | ||
410 | + buf.length = 0 | ||
411 | + } | ||
412 | + | ||
413 | + // write function | ||
414 | + function write (str) { | ||
415 | + if (timer === null) { | ||
416 | + timer = setTimeout(flush, interval) | ||
417 | + } | ||
418 | + | ||
419 | + buf.push(str) | ||
420 | + } | ||
421 | + | ||
422 | + // return a minimal "stream" | ||
423 | + return { write: write } | ||
424 | +} | ||
425 | + | ||
426 | +/** | ||
427 | + * Define a format with the given name. | ||
428 | + * | ||
429 | + * @param {string} name | ||
430 | + * @param {string|function} fmt | ||
431 | + * @public | ||
432 | + */ | ||
433 | + | ||
434 | +function format (name, fmt) { | ||
435 | + morgan[name] = fmt | ||
436 | + return this | ||
437 | +} | ||
438 | + | ||
439 | +/** | ||
440 | + * Lookup and compile a named format function. | ||
441 | + * | ||
442 | + * @param {string} name | ||
443 | + * @return {function} | ||
444 | + * @public | ||
445 | + */ | ||
446 | + | ||
447 | +function getFormatFunction (name) { | ||
448 | + // lookup format | ||
449 | + var fmt = morgan[name] || name || morgan.default | ||
450 | + | ||
451 | + // return compiled format | ||
452 | + return typeof fmt !== 'function' | ||
453 | + ? compile(fmt) | ||
454 | + : fmt | ||
455 | +} | ||
456 | + | ||
457 | +/** | ||
458 | + * Get request IP address. | ||
459 | + * | ||
460 | + * @private | ||
461 | + * @param {IncomingMessage} req | ||
462 | + * @return {string} | ||
463 | + */ | ||
464 | + | ||
465 | +function getip (req) { | ||
466 | + return req.ip || | ||
467 | + req._remoteAddress || | ||
468 | + (req.connection && req.connection.remoteAddress) || | ||
469 | + undefined | ||
470 | +} | ||
471 | + | ||
472 | +/** | ||
473 | + * Determine if the response headers have been sent. | ||
474 | + * | ||
475 | + * @param {object} res | ||
476 | + * @returns {boolean} | ||
477 | + * @private | ||
478 | + */ | ||
479 | + | ||
480 | +function headersSent (res) { | ||
481 | + return typeof res.headersSent !== 'boolean' | ||
482 | + ? Boolean(res._header) | ||
483 | + : res.headersSent | ||
484 | +} | ||
485 | + | ||
486 | +/** | ||
487 | + * Pad number to two digits. | ||
488 | + * | ||
489 | + * @private | ||
490 | + * @param {number} num | ||
491 | + * @return {string} | ||
492 | + */ | ||
493 | + | ||
494 | +function pad2 (num) { | ||
495 | + var str = String(num) | ||
496 | + | ||
497 | + return (str.length === 1 ? '0' : '') + str | ||
498 | +} | ||
499 | + | ||
500 | +/** | ||
501 | + * Record the start time. | ||
502 | + * @private | ||
503 | + */ | ||
504 | + | ||
505 | +function recordStartTime () { | ||
506 | + this._startAt = process.hrtime() | ||
507 | + this._startTime = new Date() | ||
508 | +} | ||
509 | + | ||
510 | +/** | ||
511 | + * Define a token function with the given name, | ||
512 | + * and callback fn(req, res). | ||
513 | + * | ||
514 | + * @param {string} name | ||
515 | + * @param {function} fn | ||
516 | + * @public | ||
517 | + */ | ||
518 | + | ||
519 | +function token (name, fn) { | ||
520 | + morgan[name] = fn | ||
521 | + return this | ||
522 | +} |
node_modules/morgan/package.json
0 → 100644
1 | +{ | ||
2 | + "_from": "morgan@~1.9.0", | ||
3 | + "_id": "morgan@1.9.0", | ||
4 | + "_inBundle": false, | ||
5 | + "_integrity": "sha1-0B+mxlhZt2/PMbPLU6OCGjEdgFE=", | ||
6 | + "_location": "/morgan", | ||
7 | + "_phantomChildren": {}, | ||
8 | + "_requested": { | ||
9 | + "type": "range", | ||
10 | + "registry": true, | ||
11 | + "raw": "morgan@~1.9.0", | ||
12 | + "name": "morgan", | ||
13 | + "escapedName": "morgan", | ||
14 | + "rawSpec": "~1.9.0", | ||
15 | + "saveSpec": null, | ||
16 | + "fetchSpec": "~1.9.0" | ||
17 | + }, | ||
18 | + "_requiredBy": [ | ||
19 | + "/" | ||
20 | + ], | ||
21 | + "_resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz", | ||
22 | + "_shasum": "d01fa6c65859b76fcf31b3cb53a3821a311d8051", | ||
23 | + "_spec": "morgan@~1.9.0", | ||
24 | + "_where": "/home/ubuntu/OpenSource_Project", | ||
25 | + "bugs": { | ||
26 | + "url": "https://github.com/expressjs/morgan/issues" | ||
27 | + }, | ||
28 | + "bundleDependencies": false, | ||
29 | + "contributors": [ | ||
30 | + { | ||
31 | + "name": "Douglas Christopher Wilson", | ||
32 | + "email": "doug@somethingdoug.com" | ||
33 | + }, | ||
34 | + { | ||
35 | + "name": "Jonathan Ong", | ||
36 | + "email": "me@jongleberry.com", | ||
37 | + "url": "http://jongleberry.com" | ||
38 | + } | ||
39 | + ], | ||
40 | + "dependencies": { | ||
41 | + "basic-auth": "~2.0.0", | ||
42 | + "debug": "2.6.9", | ||
43 | + "depd": "~1.1.1", | ||
44 | + "on-finished": "~2.3.0", | ||
45 | + "on-headers": "~1.0.1" | ||
46 | + }, | ||
47 | + "deprecated": false, | ||
48 | + "description": "HTTP request logger middleware for node.js", | ||
49 | + "devDependencies": { | ||
50 | + "eslint": "3.19.0", | ||
51 | + "eslint-config-standard": "10.2.1", | ||
52 | + "eslint-plugin-import": "2.7.0", | ||
53 | + "eslint-plugin-markdown": "1.0.0-beta.6", | ||
54 | + "eslint-plugin-node": "5.1.1", | ||
55 | + "eslint-plugin-promise": "3.5.0", | ||
56 | + "eslint-plugin-standard": "3.0.1", | ||
57 | + "istanbul": "0.4.5", | ||
58 | + "mocha": "2.5.3", | ||
59 | + "split": "1.0.1", | ||
60 | + "supertest": "1.1.0" | ||
61 | + }, | ||
62 | + "engines": { | ||
63 | + "node": ">= 0.8.0" | ||
64 | + }, | ||
65 | + "files": [ | ||
66 | + "LICENSE", | ||
67 | + "HISTORY.md", | ||
68 | + "README.md", | ||
69 | + "index.js" | ||
70 | + ], | ||
71 | + "homepage": "https://github.com/expressjs/morgan#readme", | ||
72 | + "keywords": [ | ||
73 | + "express", | ||
74 | + "http", | ||
75 | + "logger", | ||
76 | + "middleware" | ||
77 | + ], | ||
78 | + "license": "MIT", | ||
79 | + "name": "morgan", | ||
80 | + "repository": { | ||
81 | + "type": "git", | ||
82 | + "url": "git+https://github.com/expressjs/morgan.git" | ||
83 | + }, | ||
84 | + "scripts": { | ||
85 | + "lint": "eslint --plugin markdown --ext js,md .", | ||
86 | + "test": "mocha --check-leaks --reporter spec --bail", | ||
87 | + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --check-leaks --reporter dot", | ||
88 | + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --check-leaks --reporter spec" | ||
89 | + }, | ||
90 | + "version": "1.9.0" | ||
91 | +} |
node_modules/on-headers/HISTORY.md
0 → 100644
1 | +1.0.1 / 2015-09-29 | ||
2 | +================== | ||
3 | + | ||
4 | + * perf: enable strict mode | ||
5 | + | ||
6 | +1.0.0 / 2014-08-10 | ||
7 | +================== | ||
8 | + | ||
9 | + * Honor `res.statusCode` change in `listener` | ||
10 | + * Move to `jshttp` orgainzation | ||
11 | + * Prevent `arguments`-related de-opt | ||
12 | + | ||
13 | +0.0.0 / 2014-05-13 | ||
14 | +================== | ||
15 | + | ||
16 | + * Initial implementation |
node_modules/on-headers/LICENSE
0 → 100644
1 | +(The MIT License) | ||
2 | + | ||
3 | +Copyright (c) 2014 Douglas Christopher Wilson | ||
4 | + | ||
5 | +Permission is hereby granted, free of charge, to any person obtaining | ||
6 | +a copy of this software and associated documentation files (the | ||
7 | +'Software'), to deal in the Software without restriction, including | ||
8 | +without limitation the rights to use, copy, modify, merge, publish, | ||
9 | +distribute, sublicense, and/or sell copies of the Software, and to | ||
10 | +permit persons to whom the Software is furnished to do so, subject to | ||
11 | +the following conditions: | ||
12 | + | ||
13 | +The above copyright notice and this permission notice shall be | ||
14 | +included in all copies or substantial portions of the Software. | ||
15 | + | ||
16 | +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||
17 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
18 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
19 | +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
20 | +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
21 | +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
22 | +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
node_modules/on-headers/README.md
0 → 100644
1 | +# on-headers | ||
2 | + | ||
3 | +[![NPM Version][npm-image]][npm-url] | ||
4 | +[![NPM Downloads][downloads-image]][downloads-url] | ||
5 | +[![Node.js Version][node-version-image]][node-version-url] | ||
6 | +[![Build Status][travis-image]][travis-url] | ||
7 | +[![Test Coverage][coveralls-image]][coveralls-url] | ||
8 | + | ||
9 | +Execute a listener when a response is about to write headers. | ||
10 | + | ||
11 | +## Installation | ||
12 | + | ||
13 | +```sh | ||
14 | +$ npm install on-headers | ||
15 | +``` | ||
16 | + | ||
17 | +## API | ||
18 | + | ||
19 | +```js | ||
20 | +var onHeaders = require('on-headers') | ||
21 | +``` | ||
22 | + | ||
23 | +### onHeaders(res, listener) | ||
24 | + | ||
25 | +This will add the listener `listener` to fire when headers are emitted for `res`. | ||
26 | +The listener is passed the `response` object as it's context (`this`). Headers are | ||
27 | +considered to be emitted only once, right before they are sent to the client. | ||
28 | + | ||
29 | +When this is called multiple times on the same `res`, the `listener`s are fired | ||
30 | +in the reverse order they were added. | ||
31 | + | ||
32 | +## Examples | ||
33 | + | ||
34 | +```js | ||
35 | +var http = require('http') | ||
36 | +var onHeaders = require('on-headers') | ||
37 | + | ||
38 | +http | ||
39 | +.createServer(onRequest) | ||
40 | +.listen(3000) | ||
41 | + | ||
42 | +function addPoweredBy() { | ||
43 | + // set if not set by end of request | ||
44 | + if (!this.getHeader('X-Powered-By')) { | ||
45 | + this.setHeader('X-Powered-By', 'Node.js') | ||
46 | + } | ||
47 | +} | ||
48 | + | ||
49 | +function onRequest(req, res) { | ||
50 | + onHeaders(res, addPoweredBy) | ||
51 | + | ||
52 | + res.setHeader('Content-Type', 'text/plain') | ||
53 | + res.end('hello!') | ||
54 | +} | ||
55 | +``` | ||
56 | + | ||
57 | +## Testing | ||
58 | + | ||
59 | +```sh | ||
60 | +$ npm test | ||
61 | +``` | ||
62 | + | ||
63 | +## License | ||
64 | + | ||
65 | +[MIT](LICENSE) | ||
66 | + | ||
67 | +[npm-image]: https://img.shields.io/npm/v/on-headers.svg | ||
68 | +[npm-url]: https://npmjs.org/package/on-headers | ||
69 | +[node-version-image]: https://img.shields.io/node/v/on-headers.svg | ||
70 | +[node-version-url]: http://nodejs.org/download/ | ||
71 | +[travis-image]: https://img.shields.io/travis/jshttp/on-headers/master.svg | ||
72 | +[travis-url]: https://travis-ci.org/jshttp/on-headers | ||
73 | +[coveralls-image]: https://img.shields.io/coveralls/jshttp/on-headers/master.svg | ||
74 | +[coveralls-url]: https://coveralls.io/r/jshttp/on-headers?branch=master | ||
75 | +[downloads-image]: https://img.shields.io/npm/dm/on-headers.svg | ||
76 | +[downloads-url]: https://npmjs.org/package/on-headers |
node_modules/on-headers/index.js
0 → 100644
1 | +/*! | ||
2 | + * on-headers | ||
3 | + * Copyright(c) 2014 Douglas Christopher Wilson | ||
4 | + * MIT Licensed | ||
5 | + */ | ||
6 | + | ||
7 | +'use strict' | ||
8 | + | ||
9 | +/** | ||
10 | + * Reference to Array slice. | ||
11 | + */ | ||
12 | + | ||
13 | +var slice = Array.prototype.slice | ||
14 | + | ||
15 | +/** | ||
16 | + * Execute a listener when a response is about to write headers. | ||
17 | + * | ||
18 | + * @param {Object} res | ||
19 | + * @return {Function} listener | ||
20 | + * @api public | ||
21 | + */ | ||
22 | + | ||
23 | +module.exports = function onHeaders(res, listener) { | ||
24 | + if (!res) { | ||
25 | + throw new TypeError('argument res is required') | ||
26 | + } | ||
27 | + | ||
28 | + if (typeof listener !== 'function') { | ||
29 | + throw new TypeError('argument listener must be a function') | ||
30 | + } | ||
31 | + | ||
32 | + res.writeHead = createWriteHead(res.writeHead, listener) | ||
33 | +} | ||
34 | + | ||
35 | +function createWriteHead(prevWriteHead, listener) { | ||
36 | + var fired = false; | ||
37 | + | ||
38 | + // return function with core name and argument list | ||
39 | + return function writeHead(statusCode) { | ||
40 | + // set headers from arguments | ||
41 | + var args = setWriteHeadHeaders.apply(this, arguments); | ||
42 | + | ||
43 | + // fire listener | ||
44 | + if (!fired) { | ||
45 | + fired = true | ||
46 | + listener.call(this) | ||
47 | + | ||
48 | + // pass-along an updated status code | ||
49 | + if (typeof args[0] === 'number' && this.statusCode !== args[0]) { | ||
50 | + args[0] = this.statusCode | ||
51 | + args.length = 1 | ||
52 | + } | ||
53 | + } | ||
54 | + | ||
55 | + prevWriteHead.apply(this, args); | ||
56 | + } | ||
57 | +} | ||
58 | + | ||
59 | +function setWriteHeadHeaders(statusCode) { | ||
60 | + var length = arguments.length | ||
61 | + var headerIndex = length > 1 && typeof arguments[1] === 'string' | ||
62 | + ? 2 | ||
63 | + : 1 | ||
64 | + | ||
65 | + var headers = length >= headerIndex + 1 | ||
66 | + ? arguments[headerIndex] | ||
67 | + : undefined | ||
68 | + | ||
69 | + this.statusCode = statusCode | ||
70 | + | ||
71 | + // the following block is from node.js core | ||
72 | + if (Array.isArray(headers)) { | ||
73 | + // handle array case | ||
74 | + for (var i = 0, len = headers.length; i < len; ++i) { | ||
75 | + this.setHeader(headers[i][0], headers[i][1]) | ||
76 | + } | ||
77 | + } else if (headers) { | ||
78 | + // handle object case | ||
79 | + var keys = Object.keys(headers) | ||
80 | + for (var i = 0; i < keys.length; i++) { | ||
81 | + var k = keys[i] | ||
82 | + if (k) this.setHeader(k, headers[k]) | ||
83 | + } | ||
84 | + } | ||
85 | + | ||
86 | + // copy leading arguments | ||
87 | + var args = new Array(Math.min(length, headerIndex)) | ||
88 | + for (var i = 0; i < args.length; i++) { | ||
89 | + args[i] = arguments[i] | ||
90 | + } | ||
91 | + | ||
92 | + return args | ||
93 | +} |
node_modules/on-headers/package.json
0 → 100644
1 | +{ | ||
2 | + "_from": "on-headers@~1.0.1", | ||
3 | + "_id": "on-headers@1.0.1", | ||
4 | + "_inBundle": false, | ||
5 | + "_integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", | ||
6 | + "_location": "/on-headers", | ||
7 | + "_phantomChildren": {}, | ||
8 | + "_requested": { | ||
9 | + "type": "range", | ||
10 | + "registry": true, | ||
11 | + "raw": "on-headers@~1.0.1", | ||
12 | + "name": "on-headers", | ||
13 | + "escapedName": "on-headers", | ||
14 | + "rawSpec": "~1.0.1", | ||
15 | + "saveSpec": null, | ||
16 | + "fetchSpec": "~1.0.1" | ||
17 | + }, | ||
18 | + "_requiredBy": [ | ||
19 | + "/morgan" | ||
20 | + ], | ||
21 | + "_resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", | ||
22 | + "_shasum": "928f5d0f470d49342651ea6794b0857c100693f7", | ||
23 | + "_spec": "on-headers@~1.0.1", | ||
24 | + "_where": "/home/ubuntu/OpenSource_Project/node_modules/morgan", | ||
25 | + "author": { | ||
26 | + "name": "Douglas Christopher Wilson", | ||
27 | + "email": "doug@somethingdoug.com" | ||
28 | + }, | ||
29 | + "bugs": { | ||
30 | + "url": "https://github.com/jshttp/on-headers/issues" | ||
31 | + }, | ||
32 | + "bundleDependencies": false, | ||
33 | + "dependencies": {}, | ||
34 | + "deprecated": false, | ||
35 | + "description": "Execute a listener when a response is about to write headers", | ||
36 | + "devDependencies": { | ||
37 | + "istanbul": "0.3.21", | ||
38 | + "mocha": "2.3.3", | ||
39 | + "supertest": "1.1.0" | ||
40 | + }, | ||
41 | + "engines": { | ||
42 | + "node": ">= 0.8" | ||
43 | + }, | ||
44 | + "files": [ | ||
45 | + "LICENSE", | ||
46 | + "HISTORY.md", | ||
47 | + "README.md", | ||
48 | + "index.js" | ||
49 | + ], | ||
50 | + "homepage": "https://github.com/jshttp/on-headers#readme", | ||
51 | + "keywords": [ | ||
52 | + "event", | ||
53 | + "headers", | ||
54 | + "http", | ||
55 | + "onheaders" | ||
56 | + ], | ||
57 | + "license": "MIT", | ||
58 | + "name": "on-headers", | ||
59 | + "repository": { | ||
60 | + "type": "git", | ||
61 | + "url": "git+https://github.com/jshttp/on-headers.git" | ||
62 | + }, | ||
63 | + "scripts": { | ||
64 | + "test": "mocha --reporter spec --bail --check-leaks test/", | ||
65 | + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", | ||
66 | + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" | ||
67 | + }, | ||
68 | + "version": "1.0.1" | ||
69 | +} |
node_modules/serve-favicon/HISTORY.md
0 → 100644
1 | +2.4.5 / 2017-09-26 | ||
2 | +================== | ||
3 | + | ||
4 | + * deps: etag@~1.8.1 | ||
5 | + - perf: replace regular expression with substring | ||
6 | + * deps: fresh@0.5.2 | ||
7 | + - Fix regression matching multiple ETags in `If-None-Match` | ||
8 | + - perf: improve `If-None-Match` token parsing | ||
9 | + | ||
10 | +2.4.4 / 2017-09-11 | ||
11 | +================== | ||
12 | + | ||
13 | + * deps: fresh@0.5.1 | ||
14 | + - Fix handling of modified headers with invalid dates | ||
15 | + - perf: improve ETag match loop | ||
16 | + * deps: parseurl@~1.3.2 | ||
17 | + - perf: reduce overhead for full URLs | ||
18 | + - perf: unroll the "fast-path" `RegExp` | ||
19 | + * deps: safe-buffer@5.1.1 | ||
20 | + | ||
21 | +2.4.3 / 2017-05-16 | ||
22 | +================== | ||
23 | + | ||
24 | + * Use `safe-buffer` for improved Buffer API | ||
25 | + * deps: ms@2.0.0 | ||
26 | + | ||
27 | +2.4.2 / 2017-03-24 | ||
28 | +================== | ||
29 | + | ||
30 | + * deps: ms@1.0.0 | ||
31 | + | ||
32 | +2.4.1 / 2017-02-27 | ||
33 | +================== | ||
34 | + | ||
35 | + * Remove usage of `res._headers` private field | ||
36 | + * deps: fresh@0.5.0 | ||
37 | + - Fix incorrect result when `If-None-Match` has both `*` and ETags | ||
38 | + - Fix weak `ETag` matching to match spec | ||
39 | + - perf: skip checking modified time if ETag check failed | ||
40 | + - perf: skip parsing `If-None-Match` when no `ETag` header | ||
41 | + - perf: use `Date.parse` instead of `new Date` | ||
42 | + | ||
43 | +2.4.0 / 2017-02-19 | ||
44 | +================== | ||
45 | + | ||
46 | + * deps: etag@~1.8.0 | ||
47 | + - Use SHA1 instead of MD5 for ETag hashing | ||
48 | + - Works with FIPS 140-2 OpenSSL configuration | ||
49 | + * deps: fresh@0.4.0 | ||
50 | + - Fix false detection of `no-cache` request directive | ||
51 | + - perf: enable strict mode | ||
52 | + - perf: hoist regular expressions | ||
53 | + - perf: remove duplicate conditional | ||
54 | + - perf: remove unnecessary boolean coercions | ||
55 | + * perf: simplify initial argument checking | ||
56 | + | ||
57 | +2.3.2 / 2016-11-16 | ||
58 | +================== | ||
59 | + | ||
60 | + * deps: ms@0.7.2 | ||
61 | + | ||
62 | +2.3.1 / 2016-01-23 | ||
63 | +================== | ||
64 | + | ||
65 | + * deps: parseurl@~1.3.1 | ||
66 | + - perf: enable strict mode | ||
67 | + | ||
68 | +2.3.0 / 2015-06-13 | ||
69 | +================== | ||
70 | + | ||
71 | + * Send non-chunked response for `OPTIONS` | ||
72 | + * deps: etag@~1.7.0 | ||
73 | + - Always include entity length in ETags for hash length extensions | ||
74 | + - Generate non-Stats ETags using MD5 only (no longer CRC32) | ||
75 | + - Remove base64 padding in ETags to shorten | ||
76 | + * deps: fresh@0.3.0 | ||
77 | + - Add weak `ETag` matching support | ||
78 | + * perf: enable strict mode | ||
79 | + * perf: remove argument reassignment | ||
80 | + * perf: remove bitwise operations | ||
81 | + | ||
82 | +2.2.1 / 2015-05-14 | ||
83 | +================== | ||
84 | + | ||
85 | + * deps: etag@~1.6.0 | ||
86 | + - Improve support for JXcore | ||
87 | + - Support "fake" stats objects in environments without `fs` | ||
88 | + * deps: ms@0.7.1 | ||
89 | + - Prevent extraordinarily long inputs | ||
90 | + | ||
91 | +2.2.0 / 2014-12-18 | ||
92 | +================== | ||
93 | + | ||
94 | + * Support query string in the URL | ||
95 | + * deps: etag@~1.5.1 | ||
96 | + - deps: crc@3.2.1 | ||
97 | + * deps: ms@0.7.0 | ||
98 | + - Add `milliseconds` | ||
99 | + - Add `msecs` | ||
100 | + - Add `secs` | ||
101 | + - Add `mins` | ||
102 | + - Add `hrs` | ||
103 | + - Add `yrs` | ||
104 | + | ||
105 | +2.1.7 / 2014-11-19 | ||
106 | +================== | ||
107 | + | ||
108 | + * Avoid errors from enumerables on `Object.prototype` | ||
109 | + | ||
110 | +2.1.6 / 2014-10-16 | ||
111 | +================== | ||
112 | + | ||
113 | + * deps: etag@~1.5.0 | ||
114 | + | ||
115 | +2.1.5 / 2014-09-24 | ||
116 | +================== | ||
117 | + | ||
118 | + * deps: etag@~1.4.0 | ||
119 | + | ||
120 | +2.1.4 / 2014-09-15 | ||
121 | +================== | ||
122 | + | ||
123 | + * Fix content headers being sent in 304 response | ||
124 | + * deps: etag@~1.3.1 | ||
125 | + - Improve ETag generation speed | ||
126 | + | ||
127 | +2.1.3 / 2014-09-07 | ||
128 | +================== | ||
129 | + | ||
130 | + * deps: fresh@0.2.4 | ||
131 | + | ||
132 | +2.1.2 / 2014-09-05 | ||
133 | +================== | ||
134 | + | ||
135 | + * deps: etag@~1.3.0 | ||
136 | + - Improve ETag generation speed | ||
137 | + | ||
138 | +2.1.1 / 2014-08-25 | ||
139 | +================== | ||
140 | + | ||
141 | + * Fix `ms` to be listed as a dependency | ||
142 | + | ||
143 | +2.1.0 / 2014-08-24 | ||
144 | +================== | ||
145 | + | ||
146 | + * Accept string for `maxAge` (converted by `ms`) | ||
147 | + * Use `etag` to generate `ETag` header | ||
148 | + | ||
149 | +2.0.1 / 2014-06-05 | ||
150 | +================== | ||
151 | + | ||
152 | + * Reduce byte size of `ETag` header | ||
153 | + | ||
154 | +2.0.0 / 2014-05-02 | ||
155 | +================== | ||
156 | + | ||
157 | + * `path` argument is required; there is no default icon. | ||
158 | + * Accept `Buffer` of icon as first argument. | ||
159 | + * Non-GET and HEAD requests are denied. | ||
160 | + * Send valid max-age value | ||
161 | + * Support conditional requests | ||
162 | + * Support max-age=0 | ||
163 | + * Support OPTIONS method | ||
164 | + * Throw if `path` argument is directory. | ||
165 | + | ||
166 | +1.0.2 / 2014-03-16 | ||
167 | +================== | ||
168 | + | ||
169 | + * Fixed content of default icon. | ||
170 | + | ||
171 | +1.0.1 / 2014-03-11 | ||
172 | +================== | ||
173 | + | ||
174 | + * Fixed path to default icon. | ||
175 | + | ||
176 | +1.0.0 / 2014-02-15 | ||
177 | +================== | ||
178 | + | ||
179 | + * Initial release |
node_modules/serve-favicon/LICENSE
0 → 100644
1 | +(The MIT License) | ||
2 | + | ||
3 | +Copyright (c) 2010 Sencha Inc. | ||
4 | +Copyright (c) 2011 LearnBoost | ||
5 | +Copyright (c) 2011 TJ Holowaychuk | ||
6 | +Copyright (c) 2014-2017 Douglas Christopher Wilson | ||
7 | + | ||
8 | +Permission is hereby granted, free of charge, to any person obtaining | ||
9 | +a copy of this software and associated documentation files (the | ||
10 | +'Software'), to deal in the Software without restriction, including | ||
11 | +without limitation the rights to use, copy, modify, merge, publish, | ||
12 | +distribute, sublicense, and/or sell copies of the Software, and to | ||
13 | +permit persons to whom the Software is furnished to do so, subject to | ||
14 | +the following conditions: | ||
15 | + | ||
16 | +The above copyright notice and this permission notice shall be | ||
17 | +included in all copies or substantial portions of the Software. | ||
18 | + | ||
19 | +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||
20 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
21 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
22 | +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
23 | +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
24 | +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
25 | +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
node_modules/serve-favicon/README.md
0 → 100644
1 | +# serve-favicon | ||
2 | + | ||
3 | +[![NPM Version][npm-image]][npm-url] | ||
4 | +[![NPM Downloads][downloads-image]][downloads-url] | ||
5 | +[![Linux Build][travis-image]][travis-url] | ||
6 | +[![Windows Build][appveyor-image]][appveyor-url] | ||
7 | +[![Test Coverage][coveralls-image]][coveralls-url] | ||
8 | +[![Gratipay][gratipay-image]][gratipay-url] | ||
9 | + | ||
10 | +Node.js middleware for serving a favicon. | ||
11 | + | ||
12 | +A favicon is a visual cue that client software, like browsers, use to identify | ||
13 | +a site. For an example and more information, please visit | ||
14 | +[the Wikipedia article on favicons](https://en.wikipedia.org/wiki/Favicon). | ||
15 | + | ||
16 | +Why use this module? | ||
17 | + | ||
18 | + - User agents request `favicon.ico` frequently and indiscriminately, so you | ||
19 | + may wish to exclude these requests from your logs by using this middleware | ||
20 | + before your logger middleware. | ||
21 | + - This module caches the icon in memory to improve performance by skipping | ||
22 | + disk access. | ||
23 | + - This module provides an `ETag` based on the contents of the icon, rather | ||
24 | + than file system properties. | ||
25 | + - This module will serve with the most compatible `Content-Type`. | ||
26 | + | ||
27 | +**Note** This module is exclusively for serving the "default, implicit favicon", | ||
28 | +which is `GET /favicon.ico`. For additional vendor-specific icons that require | ||
29 | +HTML markup, additional middleware is required to serve the relevant files, for | ||
30 | +example [serve-static](https://npmjs.org/package/serve-static). | ||
31 | + | ||
32 | +## Install | ||
33 | + | ||
34 | +This is a [Node.js](https://nodejs.org/en/) module available through the | ||
35 | +[npm registry](https://www.npmjs.com/). Installation is done using the | ||
36 | +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): | ||
37 | + | ||
38 | +```sh | ||
39 | +$ npm install serve-favicon | ||
40 | +``` | ||
41 | + | ||
42 | +## API | ||
43 | + | ||
44 | +### favicon(path, options) | ||
45 | + | ||
46 | +Create new middleware to serve a favicon from the given `path` to a favicon file. | ||
47 | +`path` may also be a `Buffer` of the icon to serve. | ||
48 | + | ||
49 | +#### Options | ||
50 | + | ||
51 | +Serve favicon accepts these properties in the options object. | ||
52 | + | ||
53 | +##### maxAge | ||
54 | + | ||
55 | +The `cache-control` `max-age` directive in `ms`, defaulting to 1 year. This can | ||
56 | +also be a string accepted by the [ms](https://www.npmjs.org/package/ms#readme) | ||
57 | +module. | ||
58 | + | ||
59 | +## Examples | ||
60 | + | ||
61 | +Typically this middleware will come very early in your stack (maybe even first) | ||
62 | +to avoid processing any other middleware if we already know the request is for | ||
63 | +`/favicon.ico`. | ||
64 | + | ||
65 | +### express | ||
66 | + | ||
67 | +```javascript | ||
68 | +var express = require('express') | ||
69 | +var favicon = require('serve-favicon') | ||
70 | +var path = require('path') | ||
71 | + | ||
72 | +var app = express() | ||
73 | +app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))) | ||
74 | + | ||
75 | +// Add your routes here, etc. | ||
76 | + | ||
77 | +app.listen(3000) | ||
78 | +``` | ||
79 | + | ||
80 | +### connect | ||
81 | + | ||
82 | +```javascript | ||
83 | +var connect = require('connect') | ||
84 | +var favicon = require('serve-favicon') | ||
85 | +var path = require('path') | ||
86 | + | ||
87 | +var app = connect() | ||
88 | +app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))) | ||
89 | + | ||
90 | +// Add your middleware here, etc. | ||
91 | + | ||
92 | +app.listen(3000) | ||
93 | +``` | ||
94 | + | ||
95 | +### vanilla http server | ||
96 | + | ||
97 | +This middleware can be used anywhere, even outside express/connect. It takes | ||
98 | +`req`, `res`, and `callback`. | ||
99 | + | ||
100 | +```javascript | ||
101 | +var http = require('http') | ||
102 | +var favicon = require('serve-favicon') | ||
103 | +var finalhandler = require('finalhandler') | ||
104 | +var path = require('path') | ||
105 | + | ||
106 | +var _favicon = favicon(path.join(__dirname, 'public', 'favicon.ico')) | ||
107 | + | ||
108 | +var server = http.createServer(function onRequest (req, res) { | ||
109 | + var done = finalhandler(req, res) | ||
110 | + | ||
111 | + _favicon(req, res, function onNext (err) { | ||
112 | + if (err) return done(err) | ||
113 | + | ||
114 | + // continue to process the request here, etc. | ||
115 | + | ||
116 | + res.statusCode = 404 | ||
117 | + res.end('oops') | ||
118 | + }) | ||
119 | +}) | ||
120 | + | ||
121 | +server.listen(3000) | ||
122 | +``` | ||
123 | + | ||
124 | +## License | ||
125 | + | ||
126 | +[MIT](LICENSE) | ||
127 | + | ||
128 | +[npm-image]: https://img.shields.io/npm/v/serve-favicon.svg | ||
129 | +[npm-url]: https://npmjs.org/package/serve-favicon | ||
130 | +[travis-image]: https://img.shields.io/travis/expressjs/serve-favicon/master.svg?label=linux | ||
131 | +[travis-url]: https://travis-ci.org/expressjs/serve-favicon | ||
132 | +[appveyor-image]: https://img.shields.io/appveyor/ci/dougwilson/serve-favicon/master.svg?label=windows | ||
133 | +[appveyor-url]: https://ci.appveyor.com/project/dougwilson/serve-favicon | ||
134 | +[coveralls-image]: https://img.shields.io/coveralls/expressjs/serve-favicon.svg | ||
135 | +[coveralls-url]: https://coveralls.io/r/expressjs/serve-favicon?branch=master | ||
136 | +[downloads-image]: https://img.shields.io/npm/dm/serve-favicon.svg | ||
137 | +[downloads-url]: https://npmjs.org/package/serve-favicon | ||
138 | +[gratipay-image]: https://img.shields.io/gratipay/dougwilson.svg | ||
139 | +[gratipay-url]: https://www.gratipay.com/dougwilson/ |
node_modules/serve-favicon/index.js
0 → 100644
1 | +/*! | ||
2 | + * serve-favicon | ||
3 | + * Copyright(c) 2010 Sencha Inc. | ||
4 | + * Copyright(c) 2011 TJ Holowaychuk | ||
5 | + * Copyright(c) 2014-2017 Douglas Christopher Wilson | ||
6 | + * MIT Licensed | ||
7 | + */ | ||
8 | + | ||
9 | +'use strict' | ||
10 | + | ||
11 | +/** | ||
12 | + * Module dependencies. | ||
13 | + * @private | ||
14 | + */ | ||
15 | + | ||
16 | +var Buffer = require('safe-buffer').Buffer | ||
17 | +var etag = require('etag') | ||
18 | +var fresh = require('fresh') | ||
19 | +var fs = require('fs') | ||
20 | +var ms = require('ms') | ||
21 | +var parseUrl = require('parseurl') | ||
22 | +var path = require('path') | ||
23 | +var resolve = path.resolve | ||
24 | + | ||
25 | +/** | ||
26 | + * Module exports. | ||
27 | + * @public | ||
28 | + */ | ||
29 | + | ||
30 | +module.exports = favicon | ||
31 | + | ||
32 | +/** | ||
33 | + * Module variables. | ||
34 | + * @private | ||
35 | + */ | ||
36 | + | ||
37 | +var ONE_YEAR_MS = 60 * 60 * 24 * 365 * 1000 // 1 year | ||
38 | + | ||
39 | +/** | ||
40 | + * Serves the favicon located by the given `path`. | ||
41 | + * | ||
42 | + * @public | ||
43 | + * @param {String|Buffer} path | ||
44 | + * @param {Object} [options] | ||
45 | + * @return {Function} middleware | ||
46 | + */ | ||
47 | + | ||
48 | +function favicon (path, options) { | ||
49 | + var opts = options || {} | ||
50 | + | ||
51 | + var icon // favicon cache | ||
52 | + var maxAge = calcMaxAge(opts.maxAge) | ||
53 | + | ||
54 | + if (!path) { | ||
55 | + throw new TypeError('path to favicon.ico is required') | ||
56 | + } | ||
57 | + | ||
58 | + if (Buffer.isBuffer(path)) { | ||
59 | + icon = createIcon(Buffer.from(path), maxAge) | ||
60 | + } else if (typeof path === 'string') { | ||
61 | + path = resolveSync(path) | ||
62 | + } else { | ||
63 | + throw new TypeError('path to favicon.ico must be string or buffer') | ||
64 | + } | ||
65 | + | ||
66 | + return function favicon (req, res, next) { | ||
67 | + if (parseUrl(req).pathname !== '/favicon.ico') { | ||
68 | + next() | ||
69 | + return | ||
70 | + } | ||
71 | + | ||
72 | + if (req.method !== 'GET' && req.method !== 'HEAD') { | ||
73 | + res.statusCode = req.method === 'OPTIONS' ? 200 : 405 | ||
74 | + res.setHeader('Allow', 'GET, HEAD, OPTIONS') | ||
75 | + res.setHeader('Content-Length', '0') | ||
76 | + res.end() | ||
77 | + return | ||
78 | + } | ||
79 | + | ||
80 | + if (icon) { | ||
81 | + send(req, res, icon) | ||
82 | + return | ||
83 | + } | ||
84 | + | ||
85 | + fs.readFile(path, function (err, buf) { | ||
86 | + if (err) return next(err) | ||
87 | + icon = createIcon(buf, maxAge) | ||
88 | + send(req, res, icon) | ||
89 | + }) | ||
90 | + } | ||
91 | +} | ||
92 | + | ||
93 | +/** | ||
94 | + * Calculate the max-age from a configured value. | ||
95 | + * | ||
96 | + * @private | ||
97 | + * @param {string|number} val | ||
98 | + * @return {number} | ||
99 | + */ | ||
100 | + | ||
101 | +function calcMaxAge (val) { | ||
102 | + var num = typeof val === 'string' | ||
103 | + ? ms(val) | ||
104 | + : val | ||
105 | + | ||
106 | + return num != null | ||
107 | + ? Math.min(Math.max(0, num), ONE_YEAR_MS) | ||
108 | + : ONE_YEAR_MS | ||
109 | +} | ||
110 | + | ||
111 | +/** | ||
112 | + * Create icon data from Buffer and max-age. | ||
113 | + * | ||
114 | + * @private | ||
115 | + * @param {Buffer} buf | ||
116 | + * @param {number} maxAge | ||
117 | + * @return {object} | ||
118 | + */ | ||
119 | + | ||
120 | +function createIcon (buf, maxAge) { | ||
121 | + return { | ||
122 | + body: buf, | ||
123 | + headers: { | ||
124 | + 'Cache-Control': 'public, max-age=' + Math.floor(maxAge / 1000), | ||
125 | + 'ETag': etag(buf) | ||
126 | + } | ||
127 | + } | ||
128 | +} | ||
129 | + | ||
130 | +/** | ||
131 | + * Create EISDIR error. | ||
132 | + * | ||
133 | + * @private | ||
134 | + * @param {string} path | ||
135 | + * @return {Error} | ||
136 | + */ | ||
137 | + | ||
138 | +function createIsDirError (path) { | ||
139 | + var error = new Error('EISDIR, illegal operation on directory \'' + path + '\'') | ||
140 | + error.code = 'EISDIR' | ||
141 | + error.errno = 28 | ||
142 | + error.path = path | ||
143 | + error.syscall = 'open' | ||
144 | + return error | ||
145 | +} | ||
146 | + | ||
147 | +/** | ||
148 | + * Determine if the cached representation is fresh. | ||
149 | + * | ||
150 | + * @param {object} req | ||
151 | + * @param {object} res | ||
152 | + * @return {boolean} | ||
153 | + * @private | ||
154 | + */ | ||
155 | + | ||
156 | +function isFresh (req, res) { | ||
157 | + return fresh(req.headers, { | ||
158 | + 'etag': res.getHeader('ETag'), | ||
159 | + 'last-modified': res.getHeader('Last-Modified') | ||
160 | + }) | ||
161 | +} | ||
162 | + | ||
163 | +/** | ||
164 | + * Resolve the path to icon. | ||
165 | + * | ||
166 | + * @param {string} iconPath | ||
167 | + * @private | ||
168 | + */ | ||
169 | + | ||
170 | +function resolveSync (iconPath) { | ||
171 | + var path = resolve(iconPath) | ||
172 | + var stat = fs.statSync(path) | ||
173 | + | ||
174 | + if (stat.isDirectory()) { | ||
175 | + throw createIsDirError(path) | ||
176 | + } | ||
177 | + | ||
178 | + return path | ||
179 | +} | ||
180 | + | ||
181 | +/** | ||
182 | + * Send icon data in response to a request. | ||
183 | + * | ||
184 | + * @private | ||
185 | + * @param {IncomingMessage} req | ||
186 | + * @param {OutgoingMessage} res | ||
187 | + * @param {object} icon | ||
188 | + */ | ||
189 | + | ||
190 | +function send (req, res, icon) { | ||
191 | + // Set headers | ||
192 | + var headers = icon.headers | ||
193 | + var keys = Object.keys(headers) | ||
194 | + for (var i = 0; i < keys.length; i++) { | ||
195 | + var key = keys[i] | ||
196 | + res.setHeader(key, headers[key]) | ||
197 | + } | ||
198 | + | ||
199 | + // Validate freshness | ||
200 | + if (isFresh(req, res)) { | ||
201 | + res.statusCode = 304 | ||
202 | + res.end() | ||
203 | + return | ||
204 | + } | ||
205 | + | ||
206 | + // Send icon | ||
207 | + res.statusCode = 200 | ||
208 | + res.setHeader('Content-Length', icon.body.length) | ||
209 | + res.setHeader('Content-Type', 'image/x-icon') | ||
210 | + res.end(icon.body) | ||
211 | +} |
node_modules/serve-favicon/package.json
0 → 100644
1 | +{ | ||
2 | + "_from": "serve-favicon@~2.4.5", | ||
3 | + "_id": "serve-favicon@2.4.5", | ||
4 | + "_inBundle": false, | ||
5 | + "_integrity": "sha512-s7F8h2NrslMkG50KxvlGdj+ApSwaLex0vexuJ9iFf3GLTIp1ph/l1qZvRe9T9TJEYZgmq72ZwJ2VYiAEtChknw==", | ||
6 | + "_location": "/serve-favicon", | ||
7 | + "_phantomChildren": {}, | ||
8 | + "_requested": { | ||
9 | + "type": "range", | ||
10 | + "registry": true, | ||
11 | + "raw": "serve-favicon@~2.4.5", | ||
12 | + "name": "serve-favicon", | ||
13 | + "escapedName": "serve-favicon", | ||
14 | + "rawSpec": "~2.4.5", | ||
15 | + "saveSpec": null, | ||
16 | + "fetchSpec": "~2.4.5" | ||
17 | + }, | ||
18 | + "_requiredBy": [ | ||
19 | + "/" | ||
20 | + ], | ||
21 | + "_resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.4.5.tgz", | ||
22 | + "_shasum": "49d9a46863153a9240691c893d2b0e7d85d6d436", | ||
23 | + "_spec": "serve-favicon@~2.4.5", | ||
24 | + "_where": "/home/ubuntu/OpenSource_Project", | ||
25 | + "author": { | ||
26 | + "name": "Douglas Christopher Wilson", | ||
27 | + "email": "doug@somethingdoug.com" | ||
28 | + }, | ||
29 | + "bugs": { | ||
30 | + "url": "https://github.com/expressjs/serve-favicon/issues" | ||
31 | + }, | ||
32 | + "bundleDependencies": false, | ||
33 | + "dependencies": { | ||
34 | + "etag": "~1.8.1", | ||
35 | + "fresh": "0.5.2", | ||
36 | + "ms": "2.0.0", | ||
37 | + "parseurl": "~1.3.2", | ||
38 | + "safe-buffer": "5.1.1" | ||
39 | + }, | ||
40 | + "deprecated": false, | ||
41 | + "description": "favicon serving middleware with caching", | ||
42 | + "devDependencies": { | ||
43 | + "eslint": "3.19.0", | ||
44 | + "eslint-config-standard": "10.2.1", | ||
45 | + "eslint-plugin-import": "2.7.0", | ||
46 | + "eslint-plugin-markdown": "1.0.0-beta.6", | ||
47 | + "eslint-plugin-node": "5.1.1", | ||
48 | + "eslint-plugin-promise": "3.5.0", | ||
49 | + "eslint-plugin-standard": "3.0.1", | ||
50 | + "istanbul": "0.4.5", | ||
51 | + "mocha": "2.5.3", | ||
52 | + "supertest": "1.1.0", | ||
53 | + "temp-path": "1.0.0" | ||
54 | + }, | ||
55 | + "engines": { | ||
56 | + "node": ">= 0.8.0" | ||
57 | + }, | ||
58 | + "files": [ | ||
59 | + "LICENSE", | ||
60 | + "HISTORY.md", | ||
61 | + "index.js" | ||
62 | + ], | ||
63 | + "homepage": "https://github.com/expressjs/serve-favicon#readme", | ||
64 | + "keywords": [ | ||
65 | + "express", | ||
66 | + "favicon", | ||
67 | + "middleware" | ||
68 | + ], | ||
69 | + "license": "MIT", | ||
70 | + "name": "serve-favicon", | ||
71 | + "repository": { | ||
72 | + "type": "git", | ||
73 | + "url": "git+https://github.com/expressjs/serve-favicon.git" | ||
74 | + }, | ||
75 | + "scripts": { | ||
76 | + "lint": "eslint --plugin markdown --ext js,md .", | ||
77 | + "test": "mocha --reporter spec --bail --check-leaks test/", | ||
78 | + "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/", | ||
79 | + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/" | ||
80 | + }, | ||
81 | + "version": "2.4.5" | ||
82 | +} |
1 | { | 1 | { |
2 | - "requires": true, | 2 | + "name": "project", |
3 | + "version": "0.0.0", | ||
3 | "lockfileVersion": 1, | 4 | "lockfileVersion": 1, |
5 | + "requires": true, | ||
4 | "dependencies": { | 6 | "dependencies": { |
5 | "accepts": { | 7 | "accepts": { |
6 | "version": "1.3.4", | 8 | "version": "1.3.4", |
... | @@ -52,6 +54,14 @@ | ... | @@ -52,6 +54,14 @@ |
52 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", | 54 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", |
53 | "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" | 55 | "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" |
54 | }, | 56 | }, |
57 | + "basic-auth": { | ||
58 | + "version": "2.0.0", | ||
59 | + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.0.tgz", | ||
60 | + "integrity": "sha1-AV2z81PgLlY3d1X5YnQuiYHnu7o=", | ||
61 | + "requires": { | ||
62 | + "safe-buffer": "5.1.1" | ||
63 | + } | ||
64 | + }, | ||
55 | "bcrypt-pbkdf": { | 65 | "bcrypt-pbkdf": { |
56 | "version": "1.0.1", | 66 | "version": "1.0.1", |
57 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", | 67 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", |
... | @@ -124,6 +134,15 @@ | ... | @@ -124,6 +134,15 @@ |
124 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", | 134 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", |
125 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" | 135 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" |
126 | }, | 136 | }, |
137 | + "cookie-parser": { | ||
138 | + "version": "1.4.3", | ||
139 | + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.3.tgz", | ||
140 | + "integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=", | ||
141 | + "requires": { | ||
142 | + "cookie": "0.3.1", | ||
143 | + "cookie-signature": "1.0.6" | ||
144 | + } | ||
145 | + }, | ||
127 | "cookie-signature": { | 146 | "cookie-signature": { |
128 | "version": "1.0.6", | 147 | "version": "1.0.6", |
129 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", | 148 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", |
... | @@ -197,6 +216,11 @@ | ... | @@ -197,6 +216,11 @@ |
197 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", | 216 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", |
198 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" | 217 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" |
199 | }, | 218 | }, |
219 | + "ejs": { | ||
220 | + "version": "2.5.7", | ||
221 | + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", | ||
222 | + "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=" | ||
223 | + }, | ||
200 | "encodeurl": { | 224 | "encodeurl": { |
201 | "version": "1.0.1", | 225 | "version": "1.0.1", |
202 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", | 226 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", |
... | @@ -464,6 +488,18 @@ | ... | @@ -464,6 +488,18 @@ |
464 | "mime-db": "1.30.0" | 488 | "mime-db": "1.30.0" |
465 | } | 489 | } |
466 | }, | 490 | }, |
491 | + "morgan": { | ||
492 | + "version": "1.9.0", | ||
493 | + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz", | ||
494 | + "integrity": "sha1-0B+mxlhZt2/PMbPLU6OCGjEdgFE=", | ||
495 | + "requires": { | ||
496 | + "basic-auth": "2.0.0", | ||
497 | + "debug": "2.6.9", | ||
498 | + "depd": "1.1.1", | ||
499 | + "on-finished": "2.3.0", | ||
500 | + "on-headers": "1.0.1" | ||
501 | + } | ||
502 | + }, | ||
467 | "ms": { | 503 | "ms": { |
468 | "version": "2.0.0", | 504 | "version": "2.0.0", |
469 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | 505 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", |
... | @@ -487,6 +523,11 @@ | ... | @@ -487,6 +523,11 @@ |
487 | "ee-first": "1.1.1" | 523 | "ee-first": "1.1.1" |
488 | } | 524 | } |
489 | }, | 525 | }, |
526 | + "on-headers": { | ||
527 | + "version": "1.0.1", | ||
528 | + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", | ||
529 | + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" | ||
530 | + }, | ||
490 | "parseurl": { | 531 | "parseurl": { |
491 | "version": "1.3.2", | 532 | "version": "1.3.2", |
492 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", | 533 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", |
... | @@ -591,6 +632,18 @@ | ... | @@ -591,6 +632,18 @@ |
591 | "statuses": "1.3.1" | 632 | "statuses": "1.3.1" |
592 | } | 633 | } |
593 | }, | 634 | }, |
635 | + "serve-favicon": { | ||
636 | + "version": "2.4.5", | ||
637 | + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.4.5.tgz", | ||
638 | + "integrity": "sha512-s7F8h2NrslMkG50KxvlGdj+ApSwaLex0vexuJ9iFf3GLTIp1ph/l1qZvRe9T9TJEYZgmq72ZwJ2VYiAEtChknw==", | ||
639 | + "requires": { | ||
640 | + "etag": "1.8.1", | ||
641 | + "fresh": "0.5.2", | ||
642 | + "ms": "2.0.0", | ||
643 | + "parseurl": "1.3.2", | ||
644 | + "safe-buffer": "5.1.1" | ||
645 | + } | ||
646 | + }, | ||
594 | "serve-static": { | 647 | "serve-static": { |
595 | "version": "1.13.1", | 648 | "version": "1.13.1", |
596 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", | 649 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", | ... | ... |
package.json
0 → 100644
1 | +{ | ||
2 | + "name": "project", | ||
3 | + "version": "0.0.0", | ||
4 | + "private": true, | ||
5 | + "scripts": { | ||
6 | + "start": "node ./bin/www" | ||
7 | + }, | ||
8 | + "dependencies": { | ||
9 | + "body-parser": "~1.18.2", | ||
10 | + "cookie-parser": "~1.4.3", | ||
11 | + "debug": "~2.6.9", | ||
12 | + "ejs": "~2.5.7", | ||
13 | + "express": "^4.16.2", | ||
14 | + "morgan": "~1.9.0", | ||
15 | + "request": "^2.83.0", | ||
16 | + "serve-favicon": "~2.4.5" | ||
17 | + }, | ||
18 | + "main": "app.js", | ||
19 | + "devDependencies": {}, | ||
20 | + "author": "", | ||
21 | + "license": "ISC", | ||
22 | + "description": "" | ||
23 | +} |
routes/keyboard.js
0 → 100644
1 | +var express = require('express'); | ||
2 | +var app = express.Router(); | ||
3 | + | ||
4 | +// Kakao Keyboard API | ||
5 | +app.get('/', function(req, res) { | ||
6 | + const menu = { | ||
7 | + "type": 'buttons', | ||
8 | + "buttons": ["/설정", "/시작"]}; | ||
9 | + | ||
10 | + res.status(200).set({ | ||
11 | + 'content-type': 'application/json' | ||
12 | + }).send(JSON.stringify(menu)); | ||
13 | +}); | ||
14 | + | ||
15 | + | ||
16 | +module.exports = app; | ||
17 | + |
routes/message.js
0 → 100644
1 | +var express = require('express'); | ||
2 | +var request = require('request'); | ||
3 | +var app = express.Router(); | ||
4 | + | ||
5 | +// Naver Auth Key | ||
6 | +var client_id = '86rKmat0DijccSxKa01P'; | ||
7 | +var client_secret = 'rMapNjB8DP'; | ||
8 | + | ||
9 | +// Naver API URL | ||
10 | +var api_url = 'https://openapi.naver.com/v1/papago/n2mt'; | ||
11 | + | ||
12 | +// Kakao Message API | ||
13 | +app.post('/', function(req, res) { | ||
14 | + const _obj = { | ||
15 | + user_key: req.body.user_key, | ||
16 | + type: req.body.type, | ||
17 | + content: req.body.content | ||
18 | + }; | ||
19 | + | ||
20 | + console.log(_obj.content) | ||
21 | + | ||
22 | + if(_obj.content == '/시작'){ | ||
23 | + res.set('content-type', 'application/json'); | ||
24 | + res.json({ | ||
25 | + "message": { | ||
26 | + "text": "언어를 설정하고 싶으면 /설정 이라고 타이핑 해주세요" | ||
27 | + }, | ||
28 | + "keyboard": { | ||
29 | + "type": "text" | ||
30 | + } | ||
31 | + }); | ||
32 | + } | ||
33 | +else{ | ||
34 | + // Naver Papago Translate | ||
35 | + var options = { | ||
36 | + url: api_url, | ||
37 | + // 한국어(source : ko), 영어(target: en), 카톡에서 받는 메시지(text) | ||
38 | + form: {'source':'ko', 'target':'en', 'text':req.body.content}, | ||
39 | + headers: {'X-Naver-Client-Id': client_id, 'X-Naver-Client-Secret': client_secret} | ||
40 | + }; | ||
41 | +console.log('aa'); | ||
42 | + // Naver Post API | ||
43 | + request.post(options, function(error, response, body){ | ||
44 | + // Translate API Sucess | ||
45 | + if(!error && response.statusCode == 200){ | ||
46 | + // JSON | ||
47 | + var objBody = JSON.parse(response.body); | ||
48 | + // Message 잘 찍히는지 확인 | ||
49 | + console.log(objBody.message.result.translatedText); | ||
50 | + | ||
51 | + // Kakao Message API | ||
52 | + let massage = { | ||
53 | + "message": { | ||
54 | + // Naver API Translate 결과를 Kakao Message | ||
55 | + "text": objBody.message.result.translatedText | ||
56 | + }, | ||
57 | + }; | ||
58 | + | ||
59 | + // Kakao Message API 전송 | ||
60 | + res.set({ | ||
61 | + 'content-type': 'application/json' | ||
62 | + }).send(JSON.stringify(massage)); | ||
63 | + }else{ | ||
64 | + // Naver Message Error 발생 | ||
65 | + res.status(response.statusCode).end(); | ||
66 | + console.log('error = ' + response.statusCode); | ||
67 | + | ||
68 | + let massage = { | ||
69 | + "message": { | ||
70 | + "text": response.statusCode | ||
71 | + }, | ||
72 | + }; | ||
73 | + | ||
74 | + // Kakao에 Error Message | ||
75 | + res.set({ | ||
76 | + 'content-type': 'application/json' | ||
77 | + }).send(JSON.stringify(massage)); | ||
78 | + } | ||
79 | + }); | ||
80 | +} | ||
81 | +}); | ||
82 | + | ||
83 | +module.exports = app; | ||
84 | + |
-
Please register or login to post a comment