Showing
17 changed files
with
3261 additions
and
20 deletions
... | @@ -9,9 +9,9 @@ var usersRouter = require('./routes/users'); | ... | @@ -9,9 +9,9 @@ var usersRouter = require('./routes/users'); |
9 | 9 | ||
10 | var app = express(); | 10 | var app = express(); |
11 | 11 | ||
12 | -// view engine setup | 12 | +// view engine setup (뷰 폴더 경로 설정) |
13 | app.set('views', path.join(__dirname, 'views')); | 13 | app.set('views', path.join(__dirname, 'views')); |
14 | -app.set('view engine', 'jade'); | 14 | +app.set('view engine', 'ejs'); |
15 | 15 | ||
16 | app.use(logger('dev')); | 16 | app.use(logger('dev')); |
17 | app.use(express.json()); | 17 | app.use(express.json()); | ... | ... |
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)](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 | +```ejs | ||
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 | +let 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` | ||
75 | + then the locals will be stored in the `locals` object. Set to `false` in strict mode. | ||
76 | + - `destructuredLocals` An array of local variables that are always destructured from | ||
77 | + the locals object, available even in strict mode. | ||
78 | + - `localsName` Name to use for the object storing local variables when not using | ||
79 | + `with` Defaults to `locals` | ||
80 | + - `rmWhitespace` Remove all safe-to-remove whitespace, including leading | ||
81 | + and trailing whitespace. It also enables a safer version of `-%>` line | ||
82 | + slurping for all scriptlet tags (it does not strip new lines of tags in | ||
83 | + the middle of a line). | ||
84 | + - `escape` The escaping function used with `<%=` construct. It is | ||
85 | + used in rendering and is `.toString()`ed in the generation of client functions. | ||
86 | + (By default escapes XML). | ||
87 | + - `outputFunctionName` Set to a string (e.g., 'echo' or 'print') for a function to print | ||
88 | + output inside scriptlet tags. | ||
89 | + - `async` When `true`, EJS will use an async function for rendering. (Depends | ||
90 | + on async/await support in the JS runtime. | ||
91 | + | ||
92 | +This project uses [JSDoc](http://usejsdoc.org/). For the full public API | ||
93 | +documentation, clone the repository and run `npm run doc`. This will run JSDoc | ||
94 | +with the proper options and output the documentation to `out/`. If you want | ||
95 | +the both the public & private API docs, run `npm run devdoc` instead. | ||
96 | + | ||
97 | +## Tags | ||
98 | + | ||
99 | + - `<%` 'Scriptlet' tag, for control-flow, no output | ||
100 | + - `<%_` 'Whitespace Slurping' Scriptlet tag, strips all whitespace before it | ||
101 | + - `<%=` Outputs the value into the template (escaped) | ||
102 | + - `<%-` Outputs the unescaped value into the template | ||
103 | + - `<%#` Comment tag, no execution, no output | ||
104 | + - `<%%` Outputs a literal '<%' | ||
105 | + - `%%>` Outputs a literal '%>' | ||
106 | + - `%>` Plain ending tag | ||
107 | + - `-%>` Trim-mode ('newline slurp') tag, trims following newline | ||
108 | + - `_%>` 'Whitespace Slurping' ending tag, removes all whitespace after it | ||
109 | + | ||
110 | +For the full syntax documentation, please see [docs/syntax.md](https://github.com/mde/ejs/blob/master/docs/syntax.md). | ||
111 | + | ||
112 | +## Includes | ||
113 | + | ||
114 | +Includes either have to be an absolute path, or, if not, are assumed as | ||
115 | +relative to the template with the `include` call. For example if you are | ||
116 | +including `./views/user/show.ejs` from `./views/users.ejs` you would | ||
117 | +use `<%- include('user/show') %>`. | ||
118 | + | ||
119 | +You must specify the `filename` option for the template with the `include` | ||
120 | +call unless you are using `renderFile()`. | ||
121 | + | ||
122 | +You'll likely want to use the raw output tag (`<%-`) with your include to avoid | ||
123 | +double-escaping the HTML output. | ||
124 | + | ||
125 | +```ejs | ||
126 | +<ul> | ||
127 | + <% users.forEach(function(user){ %> | ||
128 | + <%- include('user/show', {user: user}) %> | ||
129 | + <% }); %> | ||
130 | +</ul> | ||
131 | +``` | ||
132 | + | ||
133 | +Includes are inserted at runtime, so you can use variables for the path in the | ||
134 | +`include` call (for example `<%- include(somePath) %>`). Variables in your | ||
135 | +top-level data object are available to all your includes, but local variables | ||
136 | +need to be passed down. | ||
137 | + | ||
138 | +NOTE: Include preprocessor directives (`<% include user/show %>`) are | ||
139 | +still supported. | ||
140 | + | ||
141 | +## Custom delimiters | ||
142 | + | ||
143 | +Custom delimiters can be applied on a per-template basis, or globally: | ||
144 | + | ||
145 | +```javascript | ||
146 | +let ejs = require('ejs'), | ||
147 | + users = ['geddy', 'neil', 'alex']; | ||
148 | + | ||
149 | +// Just one template | ||
150 | +ejs.render('<?= users.join(" | "); ?>', {users: users}, {delimiter: '?'}); | ||
151 | +// => 'geddy | neil | alex' | ||
152 | + | ||
153 | +// Or globally | ||
154 | +ejs.delimiter = '$'; | ||
155 | +ejs.render('<$= users.join(" | "); $>', {users: users}); | ||
156 | +// => 'geddy | neil | alex' | ||
157 | +``` | ||
158 | + | ||
159 | +## Caching | ||
160 | + | ||
161 | +EJS ships with a basic in-process cache for caching the intermediate JavaScript | ||
162 | +functions used to render templates. It's easy to plug in LRU caching using | ||
163 | +Node's `lru-cache` library: | ||
164 | + | ||
165 | +```javascript | ||
166 | +let ejs = require('ejs'), | ||
167 | + LRU = require('lru-cache'); | ||
168 | +ejs.cache = LRU(100); // LRU cache with 100-item limit | ||
169 | +``` | ||
170 | + | ||
171 | +If you want to clear the EJS cache, call `ejs.clearCache`. If you're using the | ||
172 | +LRU cache and need a different limit, simple reset `ejs.cache` to a new instance | ||
173 | +of the LRU. | ||
174 | + | ||
175 | +## Custom file loader | ||
176 | + | ||
177 | +The default file loader is `fs.readFileSync`, if you want to customize it, you can set ejs.fileLoader. | ||
178 | + | ||
179 | +```javascript | ||
180 | +let ejs = require('ejs'); | ||
181 | +let myFileLoad = function (filePath) { | ||
182 | + return 'myFileLoad: ' + fs.readFileSync(filePath); | ||
183 | +}; | ||
184 | + | ||
185 | +ejs.fileLoader = myFileLoad; | ||
186 | +``` | ||
187 | + | ||
188 | +With this feature, you can preprocess the template before reading it. | ||
189 | + | ||
190 | +## Layouts | ||
191 | + | ||
192 | +EJS does not specifically support blocks, but layouts can be implemented by | ||
193 | +including headers and footers, like so: | ||
194 | + | ||
195 | + | ||
196 | +```ejs | ||
197 | +<%- include('header') -%> | ||
198 | +<h1> | ||
199 | + Title | ||
200 | +</h1> | ||
201 | +<p> | ||
202 | + My page | ||
203 | +</p> | ||
204 | +<%- include('footer') -%> | ||
205 | +``` | ||
206 | + | ||
207 | +## Client-side support | ||
208 | + | ||
209 | +Go to the [Latest Release](https://github.com/mde/ejs/releases/latest), download | ||
210 | +`./ejs.js` or `./ejs.min.js`. Alternately, you can compile it yourself by cloning | ||
211 | +the repository and running `jake build` (or `$(npm bin)/jake build` if jake is | ||
212 | +not installed globally). | ||
213 | + | ||
214 | +Include one of these files on your page, and `ejs` should be available globally. | ||
215 | + | ||
216 | +### Example | ||
217 | + | ||
218 | +```html | ||
219 | +<div id="output"></div> | ||
220 | +<script src="ejs.min.js"></script> | ||
221 | +<script> | ||
222 | + let people = ['geddy', 'neil', 'alex'], | ||
223 | + html = ejs.render('<%= people.join(", "); %>', {people: people}); | ||
224 | + // With jQuery: | ||
225 | + $('#output').html(html); | ||
226 | + // Vanilla JS: | ||
227 | + document.getElementById('output').innerHTML = html; | ||
228 | +</script> | ||
229 | +``` | ||
230 | + | ||
231 | +### Caveats | ||
232 | + | ||
233 | +Most of EJS will work as expected; however, there are a few things to note: | ||
234 | + | ||
235 | +1. Obviously, since you do not have access to the filesystem, `ejs.renderFile()` won't work. | ||
236 | +2. For the same reason, `include`s do not work unless you use an `include callback`. Here is an example: | ||
237 | + ```javascript | ||
238 | + let str = "Hello <%= include('file', {person: 'John'}); %>", | ||
239 | + fn = ejs.compile(str, {client: true}); | ||
240 | + | ||
241 | + fn(data, null, function(path, d){ // include callback | ||
242 | + // path -> 'file' | ||
243 | + // d -> {person: 'John'} | ||
244 | + // Put your code here | ||
245 | + // Return the contents of file as a string | ||
246 | + }); // returns rendered string | ||
247 | + ``` | ||
248 | + | ||
249 | +See the [examples folder](https://github.com/mde/ejs/tree/master/examples) for more details. | ||
250 | + | ||
251 | +### IDE Integration with Syntax Highlighting | ||
252 | + | ||
253 | +VSCode:Javascript EJS by *DigitalBrainstem* | ||
254 | + | ||
255 | +## Related projects | ||
256 | + | ||
257 | +There are a number of implementations of EJS: | ||
258 | + | ||
259 | + * TJ's implementation, the v1 of this library: https://github.com/tj/ejs | ||
260 | + * Jupiter Consulting's EJS: http://www.embeddedjs.com/ | ||
261 | + * EJS Embedded JavaScript Framework on Google Code: https://code.google.com/p/embeddedjavascript/ | ||
262 | + * Sam Stephenson's Ruby implementation: https://rubygems.org/gems/ejs | ||
263 | + * Erubis, an ERB implementation which also runs JavaScript: http://www.kuwata-lab.com/erubis/users-guide.04.html#lang-javascript | ||
264 | + * DigitalBrainstem EJS Language support: https://github.com/Digitalbrainstem/ejs-grammar | ||
265 | + | ||
266 | +## License | ||
267 | + | ||
268 | +Licensed under the Apache License, Version 2.0 | ||
269 | +(<http://www.apache.org/licenses/LICENSE-2.0>) | ||
270 | + | ||
271 | +- - - | ||
272 | +EJS Embedded JavaScript templates copyright 2112 | ||
273 | +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(){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}return e})()({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_OPEN_DELIMITER = '<'; | ||
55 | +var _DEFAULT_CLOSE_DELIMITER = '>'; | ||
56 | +var _DEFAULT_DELIMITER = '%'; | ||
57 | +var _DEFAULT_LOCALS_NAME = 'locals'; | ||
58 | +var _NAME = 'ejs'; | ||
59 | +var _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)'; | ||
60 | +var _OPTS_PASSABLE_WITH_DATA = ['delimiter', 'scope', 'context', 'debug', 'compileDebug', | ||
61 | + 'client', '_with', 'rmWhitespace', 'strict', 'filename', 'async']; | ||
62 | +// We don't allow 'cache' option to be passed in the data obj for | ||
63 | +// the normal `render` call, but this is where Express 2 & 3 put it | ||
64 | +// so we make an exception for `renderFile` | ||
65 | +var _OPTS_PASSABLE_WITH_DATA_EXPRESS = _OPTS_PASSABLE_WITH_DATA.concat('cache'); | ||
66 | +var _BOM = /^\uFEFF/; | ||
67 | + | ||
68 | +/** | ||
69 | + * EJS template function cache. This can be a LRU object from lru-cache NPM | ||
70 | + * module. By default, it is {@link module:utils.cache}, a simple in-process | ||
71 | + * cache that grows continuously. | ||
72 | + * | ||
73 | + * @type {Cache} | ||
74 | + */ | ||
75 | + | ||
76 | +exports.cache = utils.cache; | ||
77 | + | ||
78 | +/** | ||
79 | + * Custom file loader. Useful for template preprocessing or restricting access | ||
80 | + * to a certain part of the filesystem. | ||
81 | + * | ||
82 | + * @type {fileLoader} | ||
83 | + */ | ||
84 | + | ||
85 | +exports.fileLoader = fs.readFileSync; | ||
86 | + | ||
87 | +/** | ||
88 | + * Name of the object containing the locals. | ||
89 | + * | ||
90 | + * This variable is overridden by {@link Options}`.localsName` if it is not | ||
91 | + * `undefined`. | ||
92 | + * | ||
93 | + * @type {String} | ||
94 | + * @public | ||
95 | + */ | ||
96 | + | ||
97 | +exports.localsName = _DEFAULT_LOCALS_NAME; | ||
98 | + | ||
99 | +/** | ||
100 | + * Promise implementation -- defaults to the native implementation if available | ||
101 | + * This is mostly just for testability | ||
102 | + * | ||
103 | + * @type {Function} | ||
104 | + * @public | ||
105 | + */ | ||
106 | + | ||
107 | +exports.promiseImpl = (new Function('return this;'))().Promise; | ||
108 | + | ||
109 | +/** | ||
110 | + * Get the path to the included file from the parent file path and the | ||
111 | + * specified path. | ||
112 | + * | ||
113 | + * @param {String} name specified path | ||
114 | + * @param {String} filename parent file path | ||
115 | + * @param {Boolean} isDir parent file path whether is directory | ||
116 | + * @return {String} | ||
117 | + */ | ||
118 | +exports.resolveInclude = function(name, filename, isDir) { | ||
119 | + var dirname = path.dirname; | ||
120 | + var extname = path.extname; | ||
121 | + var resolve = path.resolve; | ||
122 | + var includePath = resolve(isDir ? filename : dirname(filename), name); | ||
123 | + var ext = extname(name); | ||
124 | + if (!ext) { | ||
125 | + includePath += '.ejs'; | ||
126 | + } | ||
127 | + return includePath; | ||
128 | +}; | ||
129 | + | ||
130 | +/** | ||
131 | + * Get the path to the included file by Options | ||
132 | + * | ||
133 | + * @param {String} path specified path | ||
134 | + * @param {Options} options compilation options | ||
135 | + * @return {String} | ||
136 | + */ | ||
137 | +function getIncludePath(path, options) { | ||
138 | + var includePath; | ||
139 | + var filePath; | ||
140 | + var views = options.views; | ||
141 | + var match = /^[A-Za-z]+:\\|^\//.exec(path); | ||
142 | + | ||
143 | + // Abs path | ||
144 | + if (match && match.length) { | ||
145 | + includePath = exports.resolveInclude(path.replace(/^\/*/,''), options.root || '/', true); | ||
146 | + } | ||
147 | + // Relative paths | ||
148 | + else { | ||
149 | + // Look relative to a passed filename first | ||
150 | + if (options.filename) { | ||
151 | + filePath = exports.resolveInclude(path, options.filename); | ||
152 | + if (fs.existsSync(filePath)) { | ||
153 | + includePath = filePath; | ||
154 | + } | ||
155 | + } | ||
156 | + // Then look in any views directories | ||
157 | + if (!includePath) { | ||
158 | + if (Array.isArray(views) && views.some(function (v) { | ||
159 | + filePath = exports.resolveInclude(path, v, true); | ||
160 | + return fs.existsSync(filePath); | ||
161 | + })) { | ||
162 | + includePath = filePath; | ||
163 | + } | ||
164 | + } | ||
165 | + if (!includePath) { | ||
166 | + throw new Error('Could not find the include file "' + | ||
167 | + options.escapeFunction(path) + '"'); | ||
168 | + } | ||
169 | + } | ||
170 | + return includePath; | ||
171 | +} | ||
172 | + | ||
173 | +/** | ||
174 | + * Get the template from a string or a file, either compiled on-the-fly or | ||
175 | + * read from cache (if enabled), and cache the template if needed. | ||
176 | + * | ||
177 | + * If `template` is not set, the file specified in `options.filename` will be | ||
178 | + * read. | ||
179 | + * | ||
180 | + * If `options.cache` is true, this function reads the file from | ||
181 | + * `options.filename` so it must be set prior to calling this function. | ||
182 | + * | ||
183 | + * @memberof module:ejs-internal | ||
184 | + * @param {Options} options compilation options | ||
185 | + * @param {String} [template] template source | ||
186 | + * @return {(TemplateFunction|ClientFunction)} | ||
187 | + * Depending on the value of `options.client`, either type might be returned. | ||
188 | + * @static | ||
189 | + */ | ||
190 | + | ||
191 | +function handleCache(options, template) { | ||
192 | + var func; | ||
193 | + var filename = options.filename; | ||
194 | + var hasTemplate = arguments.length > 1; | ||
195 | + | ||
196 | + if (options.cache) { | ||
197 | + if (!filename) { | ||
198 | + throw new Error('cache option requires a filename'); | ||
199 | + } | ||
200 | + func = exports.cache.get(filename); | ||
201 | + if (func) { | ||
202 | + return func; | ||
203 | + } | ||
204 | + if (!hasTemplate) { | ||
205 | + template = fileLoader(filename).toString().replace(_BOM, ''); | ||
206 | + } | ||
207 | + } | ||
208 | + else if (!hasTemplate) { | ||
209 | + // istanbul ignore if: should not happen at all | ||
210 | + if (!filename) { | ||
211 | + throw new Error('Internal EJS error: no file name or template ' | ||
212 | + + 'provided'); | ||
213 | + } | ||
214 | + template = fileLoader(filename).toString().replace(_BOM, ''); | ||
215 | + } | ||
216 | + func = exports.compile(template, options); | ||
217 | + if (options.cache) { | ||
218 | + exports.cache.set(filename, func); | ||
219 | + } | ||
220 | + return func; | ||
221 | +} | ||
222 | + | ||
223 | +/** | ||
224 | + * Try calling handleCache with the given options and data and call the | ||
225 | + * callback with the result. If an error occurs, call the callback with | ||
226 | + * the error. Used by renderFile(). | ||
227 | + * | ||
228 | + * @memberof module:ejs-internal | ||
229 | + * @param {Options} options compilation options | ||
230 | + * @param {Object} data template data | ||
231 | + * @param {RenderFileCallback} cb callback | ||
232 | + * @static | ||
233 | + */ | ||
234 | + | ||
235 | +function tryHandleCache(options, data, cb) { | ||
236 | + var result; | ||
237 | + if (!cb) { | ||
238 | + if (typeof exports.promiseImpl == 'function') { | ||
239 | + return new exports.promiseImpl(function (resolve, reject) { | ||
240 | + try { | ||
241 | + result = handleCache(options)(data); | ||
242 | + resolve(result); | ||
243 | + } | ||
244 | + catch (err) { | ||
245 | + reject(err); | ||
246 | + } | ||
247 | + }); | ||
248 | + } | ||
249 | + else { | ||
250 | + throw new Error('Please provide a callback function'); | ||
251 | + } | ||
252 | + } | ||
253 | + else { | ||
254 | + try { | ||
255 | + result = handleCache(options)(data); | ||
256 | + } | ||
257 | + catch (err) { | ||
258 | + return cb(err); | ||
259 | + } | ||
260 | + | ||
261 | + cb(null, result); | ||
262 | + } | ||
263 | +} | ||
264 | + | ||
265 | +/** | ||
266 | + * fileLoader is independent | ||
267 | + * | ||
268 | + * @param {String} filePath ejs file path. | ||
269 | + * @return {String} The contents of the specified file. | ||
270 | + * @static | ||
271 | + */ | ||
272 | + | ||
273 | +function fileLoader(filePath){ | ||
274 | + return exports.fileLoader(filePath); | ||
275 | +} | ||
276 | + | ||
277 | +/** | ||
278 | + * Get the template function. | ||
279 | + * | ||
280 | + * If `options.cache` is `true`, then the template is cached. | ||
281 | + * | ||
282 | + * @memberof module:ejs-internal | ||
283 | + * @param {String} path path for the specified file | ||
284 | + * @param {Options} options compilation options | ||
285 | + * @return {(TemplateFunction|ClientFunction)} | ||
286 | + * Depending on the value of `options.client`, either type might be returned | ||
287 | + * @static | ||
288 | + */ | ||
289 | + | ||
290 | +function includeFile(path, options) { | ||
291 | + var opts = utils.shallowCopy({}, options); | ||
292 | + opts.filename = getIncludePath(path, opts); | ||
293 | + return handleCache(opts); | ||
294 | +} | ||
295 | + | ||
296 | +/** | ||
297 | + * Re-throw the given `err` in context to the `str` of ejs, `filename`, and | ||
298 | + * `lineno`. | ||
299 | + * | ||
300 | + * @implements RethrowCallback | ||
301 | + * @memberof module:ejs-internal | ||
302 | + * @param {Error} err Error object | ||
303 | + * @param {String} str EJS source | ||
304 | + * @param {String} filename file name of the EJS file | ||
305 | + * @param {String} lineno line number of the error | ||
306 | + * @static | ||
307 | + */ | ||
308 | + | ||
309 | +function rethrow(err, str, flnm, lineno, esc){ | ||
310 | + var lines = str.split('\n'); | ||
311 | + var start = Math.max(lineno - 3, 0); | ||
312 | + var end = Math.min(lines.length, lineno + 3); | ||
313 | + var filename = esc(flnm); // eslint-disable-line | ||
314 | + // Error context | ||
315 | + var context = lines.slice(start, end).map(function (line, i){ | ||
316 | + var curr = i + start + 1; | ||
317 | + return (curr == lineno ? ' >> ' : ' ') | ||
318 | + + curr | ||
319 | + + '| ' | ||
320 | + + line; | ||
321 | + }).join('\n'); | ||
322 | + | ||
323 | + // Alter exception message | ||
324 | + err.path = filename; | ||
325 | + err.message = (filename || 'ejs') + ':' | ||
326 | + + lineno + '\n' | ||
327 | + + context + '\n\n' | ||
328 | + + err.message; | ||
329 | + | ||
330 | + throw err; | ||
331 | +} | ||
332 | + | ||
333 | +function stripSemi(str){ | ||
334 | + return str.replace(/;(\s*$)/, '$1'); | ||
335 | +} | ||
336 | + | ||
337 | +/** | ||
338 | + * Compile the given `str` of ejs into a template function. | ||
339 | + * | ||
340 | + * @param {String} template EJS template | ||
341 | + * | ||
342 | + * @param {Options} opts compilation options | ||
343 | + * | ||
344 | + * @return {(TemplateFunction|ClientFunction)} | ||
345 | + * Depending on the value of `opts.client`, either type might be returned. | ||
346 | + * Note that the return type of the function also depends on the value of `opts.async`. | ||
347 | + * @public | ||
348 | + */ | ||
349 | + | ||
350 | +exports.compile = function compile(template, opts) { | ||
351 | + var templ; | ||
352 | + | ||
353 | + // v1 compat | ||
354 | + // 'scope' is 'context' | ||
355 | + // FIXME: Remove this in a future version | ||
356 | + if (opts && opts.scope) { | ||
357 | + if (!scopeOptionWarned){ | ||
358 | + console.warn('`scope` option is deprecated and will be removed in EJS 3'); | ||
359 | + scopeOptionWarned = true; | ||
360 | + } | ||
361 | + if (!opts.context) { | ||
362 | + opts.context = opts.scope; | ||
363 | + } | ||
364 | + delete opts.scope; | ||
365 | + } | ||
366 | + templ = new Template(template, opts); | ||
367 | + return templ.compile(); | ||
368 | +}; | ||
369 | + | ||
370 | +/** | ||
371 | + * Render the given `template` of ejs. | ||
372 | + * | ||
373 | + * If you would like to include options but not data, you need to explicitly | ||
374 | + * call this function with `data` being an empty object or `null`. | ||
375 | + * | ||
376 | + * @param {String} template EJS template | ||
377 | + * @param {Object} [data={}] template data | ||
378 | + * @param {Options} [opts={}] compilation and rendering options | ||
379 | + * @return {(String|Promise<String>)} | ||
380 | + * Return value type depends on `opts.async`. | ||
381 | + * @public | ||
382 | + */ | ||
383 | + | ||
384 | +exports.render = function (template, d, o) { | ||
385 | + var data = d || {}; | ||
386 | + var opts = o || {}; | ||
387 | + | ||
388 | + // No options object -- if there are optiony names | ||
389 | + // in the data, copy them to options | ||
390 | + if (arguments.length == 2) { | ||
391 | + utils.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA); | ||
392 | + } | ||
393 | + | ||
394 | + return handleCache(opts, template)(data); | ||
395 | +}; | ||
396 | + | ||
397 | +/** | ||
398 | + * Render an EJS file at the given `path` and callback `cb(err, str)`. | ||
399 | + * | ||
400 | + * If you would like to include options but not data, you need to explicitly | ||
401 | + * call this function with `data` being an empty object or `null`. | ||
402 | + * | ||
403 | + * @param {String} path path to the EJS file | ||
404 | + * @param {Object} [data={}] template data | ||
405 | + * @param {Options} [opts={}] compilation and rendering options | ||
406 | + * @param {RenderFileCallback} cb callback | ||
407 | + * @public | ||
408 | + */ | ||
409 | + | ||
410 | +exports.renderFile = function () { | ||
411 | + var args = Array.prototype.slice.call(arguments); | ||
412 | + var filename = args.shift(); | ||
413 | + var cb; | ||
414 | + var opts = {filename: filename}; | ||
415 | + var data; | ||
416 | + var viewOpts; | ||
417 | + | ||
418 | + // Do we have a callback? | ||
419 | + if (typeof arguments[arguments.length - 1] == 'function') { | ||
420 | + cb = args.pop(); | ||
421 | + } | ||
422 | + // Do we have data/opts? | ||
423 | + if (args.length) { | ||
424 | + // Should always have data obj | ||
425 | + data = args.shift(); | ||
426 | + // Normal passed opts (data obj + opts obj) | ||
427 | + if (args.length) { | ||
428 | + // Use shallowCopy so we don't pollute passed in opts obj with new vals | ||
429 | + utils.shallowCopy(opts, args.pop()); | ||
430 | + } | ||
431 | + // Special casing for Express (settings + opts-in-data) | ||
432 | + else { | ||
433 | + // Express 3 and 4 | ||
434 | + if (data.settings) { | ||
435 | + // Pull a few things from known locations | ||
436 | + if (data.settings.views) { | ||
437 | + opts.views = data.settings.views; | ||
438 | + } | ||
439 | + if (data.settings['view cache']) { | ||
440 | + opts.cache = true; | ||
441 | + } | ||
442 | + // Undocumented after Express 2, but still usable, esp. for | ||
443 | + // items that are unsafe to be passed along with data, like `root` | ||
444 | + viewOpts = data.settings['view options']; | ||
445 | + if (viewOpts) { | ||
446 | + utils.shallowCopy(opts, viewOpts); | ||
447 | + } | ||
448 | + } | ||
449 | + // Express 2 and lower, values set in app.locals, or people who just | ||
450 | + // want to pass options in their data. NOTE: These values will override | ||
451 | + // anything previously set in settings or settings['view options'] | ||
452 | + utils.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA_EXPRESS); | ||
453 | + } | ||
454 | + opts.filename = filename; | ||
455 | + } | ||
456 | + else { | ||
457 | + data = {}; | ||
458 | + } | ||
459 | + | ||
460 | + return tryHandleCache(opts, data, cb); | ||
461 | +}; | ||
462 | + | ||
463 | +/** | ||
464 | + * Clear intermediate JavaScript cache. Calls {@link Cache#reset}. | ||
465 | + * @public | ||
466 | + */ | ||
467 | + | ||
468 | +/** | ||
469 | + * EJS template class | ||
470 | + * @public | ||
471 | + */ | ||
472 | +exports.Template = Template; | ||
473 | + | ||
474 | +exports.clearCache = function () { | ||
475 | + exports.cache.reset(); | ||
476 | +}; | ||
477 | + | ||
478 | +function Template(text, opts) { | ||
479 | + opts = opts || {}; | ||
480 | + var options = {}; | ||
481 | + this.templateText = text; | ||
482 | + this.mode = null; | ||
483 | + this.truncate = false; | ||
484 | + this.currentLine = 1; | ||
485 | + this.source = ''; | ||
486 | + this.dependencies = []; | ||
487 | + options.client = opts.client || false; | ||
488 | + options.escapeFunction = opts.escape || opts.escapeFunction || utils.escapeXML; | ||
489 | + options.compileDebug = opts.compileDebug !== false; | ||
490 | + options.debug = !!opts.debug; | ||
491 | + options.filename = opts.filename; | ||
492 | + options.openDelimiter = opts.openDelimiter || exports.openDelimiter || _DEFAULT_OPEN_DELIMITER; | ||
493 | + options.closeDelimiter = opts.closeDelimiter || exports.closeDelimiter || _DEFAULT_CLOSE_DELIMITER; | ||
494 | + options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER; | ||
495 | + options.strict = opts.strict || false; | ||
496 | + options.context = opts.context; | ||
497 | + options.cache = opts.cache || false; | ||
498 | + options.rmWhitespace = opts.rmWhitespace; | ||
499 | + options.root = opts.root; | ||
500 | + options.outputFunctionName = opts.outputFunctionName; | ||
501 | + options.localsName = opts.localsName || exports.localsName || _DEFAULT_LOCALS_NAME; | ||
502 | + options.views = opts.views; | ||
503 | + options.async = opts.async; | ||
504 | + options.destructuredLocals = opts.destructuredLocals; | ||
505 | + options.legacyInclude = typeof opts.legacyInclude != 'undefined' ? !!opts.legacyInclude : true; | ||
506 | + | ||
507 | + if (options.strict) { | ||
508 | + options._with = false; | ||
509 | + } | ||
510 | + else { | ||
511 | + options._with = typeof opts._with != 'undefined' ? opts._with : true; | ||
512 | + } | ||
513 | + | ||
514 | + this.opts = options; | ||
515 | + | ||
516 | + this.regex = this.createRegex(); | ||
517 | +} | ||
518 | + | ||
519 | +Template.modes = { | ||
520 | + EVAL: 'eval', | ||
521 | + ESCAPED: 'escaped', | ||
522 | + RAW: 'raw', | ||
523 | + COMMENT: 'comment', | ||
524 | + LITERAL: 'literal' | ||
525 | +}; | ||
526 | + | ||
527 | +Template.prototype = { | ||
528 | + createRegex: function () { | ||
529 | + var str = _REGEX_STRING; | ||
530 | + var delim = utils.escapeRegExpChars(this.opts.delimiter); | ||
531 | + var open = utils.escapeRegExpChars(this.opts.openDelimiter); | ||
532 | + var close = utils.escapeRegExpChars(this.opts.closeDelimiter); | ||
533 | + str = str.replace(/%/g, delim) | ||
534 | + .replace(/</g, open) | ||
535 | + .replace(/>/g, close); | ||
536 | + return new RegExp(str); | ||
537 | + }, | ||
538 | + | ||
539 | + compile: function () { | ||
540 | + var src; | ||
541 | + var fn; | ||
542 | + var opts = this.opts; | ||
543 | + var prepended = ''; | ||
544 | + var appended = ''; | ||
545 | + var escapeFn = opts.escapeFunction; | ||
546 | + var ctor; | ||
547 | + | ||
548 | + if (!this.source) { | ||
549 | + this.generateSource(); | ||
550 | + prepended += | ||
551 | + ' var __output = "";\n' + | ||
552 | + ' function __append(s) { if (s !== undefined && s !== null) __output += s }\n'; | ||
553 | + if (opts.outputFunctionName) { | ||
554 | + prepended += ' var ' + opts.outputFunctionName + ' = __append;' + '\n'; | ||
555 | + } | ||
556 | + if (opts.destructuredLocals && opts.destructuredLocals.length) { | ||
557 | + var destructuring = ' var __locals = (' + opts.localsName + ' || {}),\n'; | ||
558 | + for (var i = 0; i < opts.destructuredLocals.length; i++) { | ||
559 | + var name = opts.destructuredLocals[i]; | ||
560 | + if (i > 0) { | ||
561 | + destructuring += ',\n '; | ||
562 | + } | ||
563 | + destructuring += name + ' = __locals.' + name; | ||
564 | + } | ||
565 | + prepended += destructuring + ';\n'; | ||
566 | + } | ||
567 | + if (opts._with !== false) { | ||
568 | + prepended += ' with (' + opts.localsName + ' || {}) {' + '\n'; | ||
569 | + appended += ' }' + '\n'; | ||
570 | + } | ||
571 | + appended += ' return __output;' + '\n'; | ||
572 | + this.source = prepended + this.source + appended; | ||
573 | + } | ||
574 | + | ||
575 | + if (opts.compileDebug) { | ||
576 | + src = 'var __line = 1' + '\n' | ||
577 | + + ' , __lines = ' + JSON.stringify(this.templateText) + '\n' | ||
578 | + + ' , __filename = ' + (opts.filename ? | ||
579 | + JSON.stringify(opts.filename) : 'undefined') + ';' + '\n' | ||
580 | + + 'try {' + '\n' | ||
581 | + + this.source | ||
582 | + + '} catch (e) {' + '\n' | ||
583 | + + ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\n' | ||
584 | + + '}' + '\n'; | ||
585 | + } | ||
586 | + else { | ||
587 | + src = this.source; | ||
588 | + } | ||
589 | + | ||
590 | + if (opts.client) { | ||
591 | + src = 'escapeFn = escapeFn || ' + escapeFn.toString() + ';' + '\n' + src; | ||
592 | + if (opts.compileDebug) { | ||
593 | + src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\n' + src; | ||
594 | + } | ||
595 | + } | ||
596 | + | ||
597 | + if (opts.strict) { | ||
598 | + src = '"use strict";\n' + src; | ||
599 | + } | ||
600 | + if (opts.debug) { | ||
601 | + console.log(src); | ||
602 | + } | ||
603 | + if (opts.compileDebug && opts.filename) { | ||
604 | + src = src + '\n' | ||
605 | + + '//# sourceURL=' + opts.filename + '\n'; | ||
606 | + } | ||
607 | + | ||
608 | + try { | ||
609 | + if (opts.async) { | ||
610 | + // Have to use generated function for this, since in envs without support, | ||
611 | + // it breaks in parsing | ||
612 | + try { | ||
613 | + ctor = (new Function('return (async function(){}).constructor;'))(); | ||
614 | + } | ||
615 | + catch(e) { | ||
616 | + if (e instanceof SyntaxError) { | ||
617 | + throw new Error('This environment does not support async/await'); | ||
618 | + } | ||
619 | + else { | ||
620 | + throw e; | ||
621 | + } | ||
622 | + } | ||
623 | + } | ||
624 | + else { | ||
625 | + ctor = Function; | ||
626 | + } | ||
627 | + fn = new ctor(opts.localsName + ', escapeFn, include, rethrow', src); | ||
628 | + } | ||
629 | + catch(e) { | ||
630 | + // istanbul ignore else | ||
631 | + if (e instanceof SyntaxError) { | ||
632 | + if (opts.filename) { | ||
633 | + e.message += ' in ' + opts.filename; | ||
634 | + } | ||
635 | + e.message += ' while compiling ejs\n\n'; | ||
636 | + e.message += 'If the above error is not helpful, you may want to try EJS-Lint:\n'; | ||
637 | + e.message += 'https://github.com/RyanZim/EJS-Lint'; | ||
638 | + if (!opts.async) { | ||
639 | + e.message += '\n'; | ||
640 | + e.message += 'Or, if you meant to create an async function, pass `async: true` as an option.'; | ||
641 | + } | ||
642 | + } | ||
643 | + throw e; | ||
644 | + } | ||
645 | + | ||
646 | + // Return a callable function which will execute the function | ||
647 | + // created by the source-code, with the passed data as locals | ||
648 | + // Adds a local `include` function which allows full recursive include | ||
649 | + var returnedFn = opts.client ? fn : function anonymous(data) { | ||
650 | + var include = function (path, includeData) { | ||
651 | + var d = utils.shallowCopy({}, data); | ||
652 | + if (includeData) { | ||
653 | + d = utils.shallowCopy(d, includeData); | ||
654 | + } | ||
655 | + return includeFile(path, opts)(d); | ||
656 | + }; | ||
657 | + return fn.apply(opts.context, [data || {}, escapeFn, include, rethrow]); | ||
658 | + }; | ||
659 | + returnedFn.dependencies = this.dependencies; | ||
660 | + if (opts.filename && typeof Object.defineProperty === 'function') { | ||
661 | + var filename = opts.filename; | ||
662 | + var basename = path.basename(filename, path.extname(filename)); | ||
663 | + try { | ||
664 | + Object.defineProperty(returnedFn, 'name', { | ||
665 | + value: basename, | ||
666 | + writable: false, | ||
667 | + enumerable: false, | ||
668 | + configurable: true | ||
669 | + }); | ||
670 | + } catch (e) {/* ignore */} | ||
671 | + } | ||
672 | + return returnedFn; | ||
673 | + }, | ||
674 | + | ||
675 | + generateSource: function () { | ||
676 | + var opts = this.opts; | ||
677 | + | ||
678 | + if (opts.rmWhitespace) { | ||
679 | + // Have to use two separate replace here as `^` and `$` operators don't | ||
680 | + // work well with `\r` and empty lines don't work well with the `m` flag. | ||
681 | + this.templateText = | ||
682 | + this.templateText.replace(/[\r\n]+/g, '\n').replace(/^\s+|\s+$/gm, ''); | ||
683 | + } | ||
684 | + | ||
685 | + // Slurp spaces and tabs before <%_ and after _%> | ||
686 | + this.templateText = | ||
687 | + this.templateText.replace(/[ \t]*<%_/gm, '<%_').replace(/_%>[ \t]*/gm, '_%>'); | ||
688 | + | ||
689 | + var self = this; | ||
690 | + var matches = this.parseTemplateText(); | ||
691 | + var d = this.opts.delimiter; | ||
692 | + var o = this.opts.openDelimiter; | ||
693 | + var c = this.opts.closeDelimiter; | ||
694 | + | ||
695 | + if (matches && matches.length) { | ||
696 | + matches.forEach(function (line, index) { | ||
697 | + var closing; | ||
698 | + // If this is an opening tag, check for closing tags | ||
699 | + // FIXME: May end up with some false positives here | ||
700 | + // Better to store modes as k/v with openDelimiter + delimiter as key | ||
701 | + // Then this can simply check against the map | ||
702 | + if ( line.indexOf(o + d) === 0 // If it is a tag | ||
703 | + && line.indexOf(o + d + d) !== 0) { // and is not escaped | ||
704 | + closing = matches[index + 2]; | ||
705 | + if (!(closing == d + c || closing == '-' + d + c || closing == '_' + d + c)) { | ||
706 | + throw new Error('Could not find matching close tag for "' + line + '".'); | ||
707 | + } | ||
708 | + } | ||
709 | + self.scanLine(line); | ||
710 | + }); | ||
711 | + } | ||
712 | + | ||
713 | + }, | ||
714 | + | ||
715 | + parseTemplateText: function () { | ||
716 | + var str = this.templateText; | ||
717 | + var pat = this.regex; | ||
718 | + var result = pat.exec(str); | ||
719 | + var arr = []; | ||
720 | + var firstPos; | ||
721 | + | ||
722 | + while (result) { | ||
723 | + firstPos = result.index; | ||
724 | + | ||
725 | + if (firstPos !== 0) { | ||
726 | + arr.push(str.substring(0, firstPos)); | ||
727 | + str = str.slice(firstPos); | ||
728 | + } | ||
729 | + | ||
730 | + arr.push(result[0]); | ||
731 | + str = str.slice(result[0].length); | ||
732 | + result = pat.exec(str); | ||
733 | + } | ||
734 | + | ||
735 | + if (str) { | ||
736 | + arr.push(str); | ||
737 | + } | ||
738 | + | ||
739 | + return arr; | ||
740 | + }, | ||
741 | + | ||
742 | + _addOutput: function (line) { | ||
743 | + if (this.truncate) { | ||
744 | + // Only replace single leading linebreak in the line after | ||
745 | + // -%> tag -- this is the single, trailing linebreak | ||
746 | + // after the tag that the truncation mode replaces | ||
747 | + // Handle Win / Unix / old Mac linebreaks -- do the \r\n | ||
748 | + // combo first in the regex-or | ||
749 | + line = line.replace(/^(?:\r\n|\r|\n)/, ''); | ||
750 | + this.truncate = false; | ||
751 | + } | ||
752 | + if (!line) { | ||
753 | + return line; | ||
754 | + } | ||
755 | + | ||
756 | + // Preserve literal slashes | ||
757 | + line = line.replace(/\\/g, '\\\\'); | ||
758 | + | ||
759 | + // Convert linebreaks | ||
760 | + line = line.replace(/\n/g, '\\n'); | ||
761 | + line = line.replace(/\r/g, '\\r'); | ||
762 | + | ||
763 | + // Escape double-quotes | ||
764 | + // - this will be the delimiter during execution | ||
765 | + line = line.replace(/"/g, '\\"'); | ||
766 | + this.source += ' ; __append("' + line + '")' + '\n'; | ||
767 | + }, | ||
768 | + | ||
769 | + scanLine: function (line) { | ||
770 | + var self = this; | ||
771 | + var d = this.opts.delimiter; | ||
772 | + var o = this.opts.openDelimiter; | ||
773 | + var c = this.opts.closeDelimiter; | ||
774 | + var newLineCount = 0; | ||
775 | + | ||
776 | + newLineCount = (line.split('\n').length - 1); | ||
777 | + | ||
778 | + switch (line) { | ||
779 | + case o + d: | ||
780 | + case o + d + '_': | ||
781 | + this.mode = Template.modes.EVAL; | ||
782 | + break; | ||
783 | + case o + d + '=': | ||
784 | + this.mode = Template.modes.ESCAPED; | ||
785 | + break; | ||
786 | + case o + d + '-': | ||
787 | + this.mode = Template.modes.RAW; | ||
788 | + break; | ||
789 | + case o + d + '#': | ||
790 | + this.mode = Template.modes.COMMENT; | ||
791 | + break; | ||
792 | + case o + d + d: | ||
793 | + this.mode = Template.modes.LITERAL; | ||
794 | + this.source += ' ; __append("' + line.replace(o + d + d, o + d) + '")' + '\n'; | ||
795 | + break; | ||
796 | + case d + d + c: | ||
797 | + this.mode = Template.modes.LITERAL; | ||
798 | + this.source += ' ; __append("' + line.replace(d + d + c, d + c) + '")' + '\n'; | ||
799 | + break; | ||
800 | + case d + c: | ||
801 | + case '-' + d + c: | ||
802 | + case '_' + d + c: | ||
803 | + if (this.mode == Template.modes.LITERAL) { | ||
804 | + this._addOutput(line); | ||
805 | + } | ||
806 | + | ||
807 | + this.mode = null; | ||
808 | + this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0; | ||
809 | + break; | ||
810 | + default: | ||
811 | + // In script mode, depends on type of tag | ||
812 | + if (this.mode) { | ||
813 | + // If '//' is found without a line break, add a line break. | ||
814 | + switch (this.mode) { | ||
815 | + case Template.modes.EVAL: | ||
816 | + case Template.modes.ESCAPED: | ||
817 | + case Template.modes.RAW: | ||
818 | + if (line.lastIndexOf('//') > line.lastIndexOf('\n')) { | ||
819 | + line += '\n'; | ||
820 | + } | ||
821 | + } | ||
822 | + switch (this.mode) { | ||
823 | + // Just executing code | ||
824 | + case Template.modes.EVAL: | ||
825 | + this.source += ' ; ' + line + '\n'; | ||
826 | + break; | ||
827 | + // Exec, esc, and output | ||
828 | + case Template.modes.ESCAPED: | ||
829 | + this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\n'; | ||
830 | + break; | ||
831 | + // Exec and output | ||
832 | + case Template.modes.RAW: | ||
833 | + this.source += ' ; __append(' + stripSemi(line) + ')' + '\n'; | ||
834 | + break; | ||
835 | + case Template.modes.COMMENT: | ||
836 | + // Do nothing | ||
837 | + break; | ||
838 | + // Literal <%% mode, append as raw output | ||
839 | + case Template.modes.LITERAL: | ||
840 | + this._addOutput(line); | ||
841 | + break; | ||
842 | + } | ||
843 | + } | ||
844 | + // In string mode, just add the output | ||
845 | + else { | ||
846 | + this._addOutput(line); | ||
847 | + } | ||
848 | + } | ||
849 | + | ||
850 | + if (self.opts.compileDebug && newLineCount) { | ||
851 | + this.currentLine += newLineCount; | ||
852 | + this.source += ' ; __line = ' + this.currentLine + '\n'; | ||
853 | + } | ||
854 | + } | ||
855 | +}; | ||
856 | + | ||
857 | +/** | ||
858 | + * Escape characters reserved in XML. | ||
859 | + * | ||
860 | + * This is simply an export of {@link module:utils.escapeXML}. | ||
861 | + * | ||
862 | + * If `markup` is `undefined` or `null`, the empty string is returned. | ||
863 | + * | ||
864 | + * @param {String} markup Input string | ||
865 | + * @return {String} Escaped string | ||
866 | + * @public | ||
867 | + * @func | ||
868 | + * */ | ||
869 | +exports.escapeXML = utils.escapeXML; | ||
870 | + | ||
871 | +/** | ||
872 | + * Express.js support. | ||
873 | + * | ||
874 | + * This is an alias for {@link module:ejs.renderFile}, in order to support | ||
875 | + * Express.js out-of-the-box. | ||
876 | + * | ||
877 | + * @func | ||
878 | + */ | ||
879 | + | ||
880 | +exports.__express = exports.renderFile; | ||
881 | + | ||
882 | +/** | ||
883 | + * Version of EJS. | ||
884 | + * | ||
885 | + * @readonly | ||
886 | + * @type {String} | ||
887 | + * @public | ||
888 | + */ | ||
889 | + | ||
890 | +exports.VERSION = _VERSION_STRING; | ||
891 | + | ||
892 | +/** | ||
893 | + * Name for detection of EJS. | ||
894 | + * | ||
895 | + * @readonly | ||
896 | + * @type {String} | ||
897 | + * @public | ||
898 | + */ | ||
899 | + | ||
900 | +exports.name = _NAME; | ||
901 | + | ||
902 | +/* istanbul ignore if */ | ||
903 | +if (typeof window != 'undefined') { | ||
904 | + window.ejs = exports; | ||
905 | +} | ||
906 | + | ||
907 | +},{"../package.json":6,"./utils":2,"fs":3,"path":4}],2:[function(require,module,exports){ | ||
908 | +/* | ||
909 | + * EJS Embedded JavaScript templates | ||
910 | + * Copyright 2112 Matthew Eernisse (mde@fleegix.org) | ||
911 | + * | ||
912 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
913 | + * you may not use this file except in compliance with the License. | ||
914 | + * You may obtain a copy of the License at | ||
915 | + * | ||
916 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
917 | + * | ||
918 | + * Unless required by applicable law or agreed to in writing, software | ||
919 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
920 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
921 | + * See the License for the specific language governing permissions and | ||
922 | + * limitations under the License. | ||
923 | + * | ||
924 | +*/ | ||
925 | + | ||
926 | +/** | ||
927 | + * Private utility functions | ||
928 | + * @module utils | ||
929 | + * @private | ||
930 | + */ | ||
931 | + | ||
932 | +'use strict'; | ||
933 | + | ||
934 | +var regExpChars = /[|\\{}()[\]^$+*?.]/g; | ||
935 | + | ||
936 | +/** | ||
937 | + * Escape characters reserved in regular expressions. | ||
938 | + * | ||
939 | + * If `string` is `undefined` or `null`, the empty string is returned. | ||
940 | + * | ||
941 | + * @param {String} string Input string | ||
942 | + * @return {String} Escaped string | ||
943 | + * @static | ||
944 | + * @private | ||
945 | + */ | ||
946 | +exports.escapeRegExpChars = function (string) { | ||
947 | + // istanbul ignore if | ||
948 | + if (!string) { | ||
949 | + return ''; | ||
950 | + } | ||
951 | + return String(string).replace(regExpChars, '\\$&'); | ||
952 | +}; | ||
953 | + | ||
954 | +var _ENCODE_HTML_RULES = { | ||
955 | + '&': '&', | ||
956 | + '<': '<', | ||
957 | + '>': '>', | ||
958 | + '"': '"', | ||
959 | + "'": ''' | ||
960 | +}; | ||
961 | +var _MATCH_HTML = /[&<>'"]/g; | ||
962 | + | ||
963 | +function encode_char(c) { | ||
964 | + return _ENCODE_HTML_RULES[c] || c; | ||
965 | +} | ||
966 | + | ||
967 | +/** | ||
968 | + * Stringified version of constants used by {@link module:utils.escapeXML}. | ||
969 | + * | ||
970 | + * It is used in the process of generating {@link ClientFunction}s. | ||
971 | + * | ||
972 | + * @readonly | ||
973 | + * @type {String} | ||
974 | + */ | ||
975 | + | ||
976 | +var escapeFuncStr = | ||
977 | + 'var _ENCODE_HTML_RULES = {\n' | ||
978 | ++ ' "&": "&"\n' | ||
979 | ++ ' , "<": "<"\n' | ||
980 | ++ ' , ">": ">"\n' | ||
981 | ++ ' , \'"\': """\n' | ||
982 | ++ ' , "\'": "'"\n' | ||
983 | ++ ' }\n' | ||
984 | ++ ' , _MATCH_HTML = /[&<>\'"]/g;\n' | ||
985 | ++ 'function encode_char(c) {\n' | ||
986 | ++ ' return _ENCODE_HTML_RULES[c] || c;\n' | ||
987 | ++ '};\n'; | ||
988 | + | ||
989 | +/** | ||
990 | + * Escape characters reserved in XML. | ||
991 | + * | ||
992 | + * If `markup` is `undefined` or `null`, the empty string is returned. | ||
993 | + * | ||
994 | + * @implements {EscapeCallback} | ||
995 | + * @param {String} markup Input string | ||
996 | + * @return {String} Escaped string | ||
997 | + * @static | ||
998 | + * @private | ||
999 | + */ | ||
1000 | + | ||
1001 | +exports.escapeXML = function (markup) { | ||
1002 | + return markup == undefined | ||
1003 | + ? '' | ||
1004 | + : String(markup) | ||
1005 | + .replace(_MATCH_HTML, encode_char); | ||
1006 | +}; | ||
1007 | +exports.escapeXML.toString = function () { | ||
1008 | + return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr; | ||
1009 | +}; | ||
1010 | + | ||
1011 | +/** | ||
1012 | + * Naive copy of properties from one object to another. | ||
1013 | + * Does not recurse into non-scalar properties | ||
1014 | + * Does not check to see if the property has a value before copying | ||
1015 | + * | ||
1016 | + * @param {Object} to Destination object | ||
1017 | + * @param {Object} from Source object | ||
1018 | + * @return {Object} Destination object | ||
1019 | + * @static | ||
1020 | + * @private | ||
1021 | + */ | ||
1022 | +exports.shallowCopy = function (to, from) { | ||
1023 | + from = from || {}; | ||
1024 | + for (var p in from) { | ||
1025 | + to[p] = from[p]; | ||
1026 | + } | ||
1027 | + return to; | ||
1028 | +}; | ||
1029 | + | ||
1030 | +/** | ||
1031 | + * Naive copy of a list of key names, from one object to another. | ||
1032 | + * Only copies property if it is actually defined | ||
1033 | + * Does not recurse into non-scalar properties | ||
1034 | + * | ||
1035 | + * @param {Object} to Destination object | ||
1036 | + * @param {Object} from Source object | ||
1037 | + * @param {Array} list List of properties to copy | ||
1038 | + * @return {Object} Destination object | ||
1039 | + * @static | ||
1040 | + * @private | ||
1041 | + */ | ||
1042 | +exports.shallowCopyFromList = function (to, from, list) { | ||
1043 | + for (var i = 0; i < list.length; i++) { | ||
1044 | + var p = list[i]; | ||
1045 | + if (typeof from[p] != 'undefined') { | ||
1046 | + to[p] = from[p]; | ||
1047 | + } | ||
1048 | + } | ||
1049 | + return to; | ||
1050 | +}; | ||
1051 | + | ||
1052 | +/** | ||
1053 | + * Simple in-process cache implementation. Does not implement limits of any | ||
1054 | + * sort. | ||
1055 | + * | ||
1056 | + * @implements Cache | ||
1057 | + * @static | ||
1058 | + * @private | ||
1059 | + */ | ||
1060 | +exports.cache = { | ||
1061 | + _data: {}, | ||
1062 | + set: function (key, val) { | ||
1063 | + this._data[key] = val; | ||
1064 | + }, | ||
1065 | + get: function (key) { | ||
1066 | + return this._data[key]; | ||
1067 | + }, | ||
1068 | + remove: function (key) { | ||
1069 | + delete this._data[key]; | ||
1070 | + }, | ||
1071 | + reset: function () { | ||
1072 | + this._data = {}; | ||
1073 | + } | ||
1074 | +}; | ||
1075 | + | ||
1076 | +},{}],3:[function(require,module,exports){ | ||
1077 | + | ||
1078 | +},{}],4:[function(require,module,exports){ | ||
1079 | +(function (process){ | ||
1080 | +// Copyright Joyent, Inc. and other Node contributors. | ||
1081 | +// | ||
1082 | +// Permission is hereby granted, free of charge, to any person obtaining a | ||
1083 | +// copy of this software and associated documentation files (the | ||
1084 | +// "Software"), to deal in the Software without restriction, including | ||
1085 | +// without limitation the rights to use, copy, modify, merge, publish, | ||
1086 | +// distribute, sublicense, and/or sell copies of the Software, and to permit | ||
1087 | +// persons to whom the Software is furnished to do so, subject to the | ||
1088 | +// following conditions: | ||
1089 | +// | ||
1090 | +// The above copyright notice and this permission notice shall be included | ||
1091 | +// in all copies or substantial portions of the Software. | ||
1092 | +// | ||
1093 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
1094 | +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
1095 | +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN | ||
1096 | +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | ||
1097 | +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
1098 | +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
1099 | +// USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
1100 | + | ||
1101 | +// resolves . and .. elements in a path array with directory names there | ||
1102 | +// must be no slashes, empty elements, or device names (c:\) in the array | ||
1103 | +// (so also no leading and trailing slashes - it does not distinguish | ||
1104 | +// relative and absolute paths) | ||
1105 | +function normalizeArray(parts, allowAboveRoot) { | ||
1106 | + // if the path tries to go above the root, `up` ends up > 0 | ||
1107 | + var up = 0; | ||
1108 | + for (var i = parts.length - 1; i >= 0; i--) { | ||
1109 | + var last = parts[i]; | ||
1110 | + if (last === '.') { | ||
1111 | + parts.splice(i, 1); | ||
1112 | + } else if (last === '..') { | ||
1113 | + parts.splice(i, 1); | ||
1114 | + up++; | ||
1115 | + } else if (up) { | ||
1116 | + parts.splice(i, 1); | ||
1117 | + up--; | ||
1118 | + } | ||
1119 | + } | ||
1120 | + | ||
1121 | + // if the path is allowed to go above the root, restore leading ..s | ||
1122 | + if (allowAboveRoot) { | ||
1123 | + for (; up--; up) { | ||
1124 | + parts.unshift('..'); | ||
1125 | + } | ||
1126 | + } | ||
1127 | + | ||
1128 | + return parts; | ||
1129 | +} | ||
1130 | + | ||
1131 | +// Split a filename into [root, dir, basename, ext], unix version | ||
1132 | +// 'root' is just a slash, or nothing. | ||
1133 | +var splitPathRe = | ||
1134 | + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; | ||
1135 | +var splitPath = function(filename) { | ||
1136 | + return splitPathRe.exec(filename).slice(1); | ||
1137 | +}; | ||
1138 | + | ||
1139 | +// path.resolve([from ...], to) | ||
1140 | +// posix version | ||
1141 | +exports.resolve = function() { | ||
1142 | + var resolvedPath = '', | ||
1143 | + resolvedAbsolute = false; | ||
1144 | + | ||
1145 | + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { | ||
1146 | + var path = (i >= 0) ? arguments[i] : process.cwd(); | ||
1147 | + | ||
1148 | + // Skip empty and invalid entries | ||
1149 | + if (typeof path !== 'string') { | ||
1150 | + throw new TypeError('Arguments to path.resolve must be strings'); | ||
1151 | + } else if (!path) { | ||
1152 | + continue; | ||
1153 | + } | ||
1154 | + | ||
1155 | + resolvedPath = path + '/' + resolvedPath; | ||
1156 | + resolvedAbsolute = path.charAt(0) === '/'; | ||
1157 | + } | ||
1158 | + | ||
1159 | + // At this point the path should be resolved to a full absolute path, but | ||
1160 | + // handle relative paths to be safe (might happen when process.cwd() fails) | ||
1161 | + | ||
1162 | + // Normalize the path | ||
1163 | + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { | ||
1164 | + return !!p; | ||
1165 | + }), !resolvedAbsolute).join('/'); | ||
1166 | + | ||
1167 | + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; | ||
1168 | +}; | ||
1169 | + | ||
1170 | +// path.normalize(path) | ||
1171 | +// posix version | ||
1172 | +exports.normalize = function(path) { | ||
1173 | + var isAbsolute = exports.isAbsolute(path), | ||
1174 | + trailingSlash = substr(path, -1) === '/'; | ||
1175 | + | ||
1176 | + // Normalize the path | ||
1177 | + path = normalizeArray(filter(path.split('/'), function(p) { | ||
1178 | + return !!p; | ||
1179 | + }), !isAbsolute).join('/'); | ||
1180 | + | ||
1181 | + if (!path && !isAbsolute) { | ||
1182 | + path = '.'; | ||
1183 | + } | ||
1184 | + if (path && trailingSlash) { | ||
1185 | + path += '/'; | ||
1186 | + } | ||
1187 | + | ||
1188 | + return (isAbsolute ? '/' : '') + path; | ||
1189 | +}; | ||
1190 | + | ||
1191 | +// posix version | ||
1192 | +exports.isAbsolute = function(path) { | ||
1193 | + return path.charAt(0) === '/'; | ||
1194 | +}; | ||
1195 | + | ||
1196 | +// posix version | ||
1197 | +exports.join = function() { | ||
1198 | + var paths = Array.prototype.slice.call(arguments, 0); | ||
1199 | + return exports.normalize(filter(paths, function(p, index) { | ||
1200 | + if (typeof p !== 'string') { | ||
1201 | + throw new TypeError('Arguments to path.join must be strings'); | ||
1202 | + } | ||
1203 | + return p; | ||
1204 | + }).join('/')); | ||
1205 | +}; | ||
1206 | + | ||
1207 | + | ||
1208 | +// path.relative(from, to) | ||
1209 | +// posix version | ||
1210 | +exports.relative = function(from, to) { | ||
1211 | + from = exports.resolve(from).substr(1); | ||
1212 | + to = exports.resolve(to).substr(1); | ||
1213 | + | ||
1214 | + function trim(arr) { | ||
1215 | + var start = 0; | ||
1216 | + for (; start < arr.length; start++) { | ||
1217 | + if (arr[start] !== '') break; | ||
1218 | + } | ||
1219 | + | ||
1220 | + var end = arr.length - 1; | ||
1221 | + for (; end >= 0; end--) { | ||
1222 | + if (arr[end] !== '') break; | ||
1223 | + } | ||
1224 | + | ||
1225 | + if (start > end) return []; | ||
1226 | + return arr.slice(start, end - start + 1); | ||
1227 | + } | ||
1228 | + | ||
1229 | + var fromParts = trim(from.split('/')); | ||
1230 | + var toParts = trim(to.split('/')); | ||
1231 | + | ||
1232 | + var length = Math.min(fromParts.length, toParts.length); | ||
1233 | + var samePartsLength = length; | ||
1234 | + for (var i = 0; i < length; i++) { | ||
1235 | + if (fromParts[i] !== toParts[i]) { | ||
1236 | + samePartsLength = i; | ||
1237 | + break; | ||
1238 | + } | ||
1239 | + } | ||
1240 | + | ||
1241 | + var outputParts = []; | ||
1242 | + for (var i = samePartsLength; i < fromParts.length; i++) { | ||
1243 | + outputParts.push('..'); | ||
1244 | + } | ||
1245 | + | ||
1246 | + outputParts = outputParts.concat(toParts.slice(samePartsLength)); | ||
1247 | + | ||
1248 | + return outputParts.join('/'); | ||
1249 | +}; | ||
1250 | + | ||
1251 | +exports.sep = '/'; | ||
1252 | +exports.delimiter = ':'; | ||
1253 | + | ||
1254 | +exports.dirname = function(path) { | ||
1255 | + var result = splitPath(path), | ||
1256 | + root = result[0], | ||
1257 | + dir = result[1]; | ||
1258 | + | ||
1259 | + if (!root && !dir) { | ||
1260 | + // No dirname whatsoever | ||
1261 | + return '.'; | ||
1262 | + } | ||
1263 | + | ||
1264 | + if (dir) { | ||
1265 | + // It has a dirname, strip trailing slash | ||
1266 | + dir = dir.substr(0, dir.length - 1); | ||
1267 | + } | ||
1268 | + | ||
1269 | + return root + dir; | ||
1270 | +}; | ||
1271 | + | ||
1272 | + | ||
1273 | +exports.basename = function(path, ext) { | ||
1274 | + var f = splitPath(path)[2]; | ||
1275 | + // TODO: make this comparison case-insensitive on windows? | ||
1276 | + if (ext && f.substr(-1 * ext.length) === ext) { | ||
1277 | + f = f.substr(0, f.length - ext.length); | ||
1278 | + } | ||
1279 | + return f; | ||
1280 | +}; | ||
1281 | + | ||
1282 | + | ||
1283 | +exports.extname = function(path) { | ||
1284 | + return splitPath(path)[3]; | ||
1285 | +}; | ||
1286 | + | ||
1287 | +function filter (xs, f) { | ||
1288 | + if (xs.filter) return xs.filter(f); | ||
1289 | + var res = []; | ||
1290 | + for (var i = 0; i < xs.length; i++) { | ||
1291 | + if (f(xs[i], i, xs)) res.push(xs[i]); | ||
1292 | + } | ||
1293 | + return res; | ||
1294 | +} | ||
1295 | + | ||
1296 | +// String.prototype.substr - negative index don't work in IE8 | ||
1297 | +var substr = 'ab'.substr(-1) === 'b' | ||
1298 | + ? function (str, start, len) { return str.substr(start, len) } | ||
1299 | + : function (str, start, len) { | ||
1300 | + if (start < 0) start = str.length + start; | ||
1301 | + return str.substr(start, len); | ||
1302 | + } | ||
1303 | +; | ||
1304 | + | ||
1305 | +}).call(this,require('_process')) | ||
1306 | +},{"_process":5}],5:[function(require,module,exports){ | ||
1307 | +// shim for using process in browser | ||
1308 | +var process = module.exports = {}; | ||
1309 | + | ||
1310 | +// cached from whatever global is present so that test runners that stub it | ||
1311 | +// don't break things. But we need to wrap it in a try catch in case it is | ||
1312 | +// wrapped in strict mode code which doesn't define any globals. It's inside a | ||
1313 | +// function because try/catches deoptimize in certain engines. | ||
1314 | + | ||
1315 | +var cachedSetTimeout; | ||
1316 | +var cachedClearTimeout; | ||
1317 | + | ||
1318 | +function defaultSetTimout() { | ||
1319 | + throw new Error('setTimeout has not been defined'); | ||
1320 | +} | ||
1321 | +function defaultClearTimeout () { | ||
1322 | + throw new Error('clearTimeout has not been defined'); | ||
1323 | +} | ||
1324 | +(function () { | ||
1325 | + try { | ||
1326 | + if (typeof setTimeout === 'function') { | ||
1327 | + cachedSetTimeout = setTimeout; | ||
1328 | + } else { | ||
1329 | + cachedSetTimeout = defaultSetTimout; | ||
1330 | + } | ||
1331 | + } catch (e) { | ||
1332 | + cachedSetTimeout = defaultSetTimout; | ||
1333 | + } | ||
1334 | + try { | ||
1335 | + if (typeof clearTimeout === 'function') { | ||
1336 | + cachedClearTimeout = clearTimeout; | ||
1337 | + } else { | ||
1338 | + cachedClearTimeout = defaultClearTimeout; | ||
1339 | + } | ||
1340 | + } catch (e) { | ||
1341 | + cachedClearTimeout = defaultClearTimeout; | ||
1342 | + } | ||
1343 | +} ()) | ||
1344 | +function runTimeout(fun) { | ||
1345 | + if (cachedSetTimeout === setTimeout) { | ||
1346 | + //normal enviroments in sane situations | ||
1347 | + return setTimeout(fun, 0); | ||
1348 | + } | ||
1349 | + // if setTimeout wasn't available but was latter defined | ||
1350 | + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { | ||
1351 | + cachedSetTimeout = setTimeout; | ||
1352 | + return setTimeout(fun, 0); | ||
1353 | + } | ||
1354 | + try { | ||
1355 | + // when when somebody has screwed with setTimeout but no I.E. maddness | ||
1356 | + return cachedSetTimeout(fun, 0); | ||
1357 | + } catch(e){ | ||
1358 | + try { | ||
1359 | + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally | ||
1360 | + return cachedSetTimeout.call(null, fun, 0); | ||
1361 | + } catch(e){ | ||
1362 | + // 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 | ||
1363 | + return cachedSetTimeout.call(this, fun, 0); | ||
1364 | + } | ||
1365 | + } | ||
1366 | + | ||
1367 | + | ||
1368 | +} | ||
1369 | +function runClearTimeout(marker) { | ||
1370 | + if (cachedClearTimeout === clearTimeout) { | ||
1371 | + //normal enviroments in sane situations | ||
1372 | + return clearTimeout(marker); | ||
1373 | + } | ||
1374 | + // if clearTimeout wasn't available but was latter defined | ||
1375 | + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { | ||
1376 | + cachedClearTimeout = clearTimeout; | ||
1377 | + return clearTimeout(marker); | ||
1378 | + } | ||
1379 | + try { | ||
1380 | + // when when somebody has screwed with setTimeout but no I.E. maddness | ||
1381 | + return cachedClearTimeout(marker); | ||
1382 | + } catch (e){ | ||
1383 | + try { | ||
1384 | + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally | ||
1385 | + return cachedClearTimeout.call(null, marker); | ||
1386 | + } catch (e){ | ||
1387 | + // 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. | ||
1388 | + // Some versions of I.E. have different rules for clearTimeout vs setTimeout | ||
1389 | + return cachedClearTimeout.call(this, marker); | ||
1390 | + } | ||
1391 | + } | ||
1392 | + | ||
1393 | + | ||
1394 | + | ||
1395 | +} | ||
1396 | +var queue = []; | ||
1397 | +var draining = false; | ||
1398 | +var currentQueue; | ||
1399 | +var queueIndex = -1; | ||
1400 | + | ||
1401 | +function cleanUpNextTick() { | ||
1402 | + if (!draining || !currentQueue) { | ||
1403 | + return; | ||
1404 | + } | ||
1405 | + draining = false; | ||
1406 | + if (currentQueue.length) { | ||
1407 | + queue = currentQueue.concat(queue); | ||
1408 | + } else { | ||
1409 | + queueIndex = -1; | ||
1410 | + } | ||
1411 | + if (queue.length) { | ||
1412 | + drainQueue(); | ||
1413 | + } | ||
1414 | +} | ||
1415 | + | ||
1416 | +function drainQueue() { | ||
1417 | + if (draining) { | ||
1418 | + return; | ||
1419 | + } | ||
1420 | + var timeout = runTimeout(cleanUpNextTick); | ||
1421 | + draining = true; | ||
1422 | + | ||
1423 | + var len = queue.length; | ||
1424 | + while(len) { | ||
1425 | + currentQueue = queue; | ||
1426 | + queue = []; | ||
1427 | + while (++queueIndex < len) { | ||
1428 | + if (currentQueue) { | ||
1429 | + currentQueue[queueIndex].run(); | ||
1430 | + } | ||
1431 | + } | ||
1432 | + queueIndex = -1; | ||
1433 | + len = queue.length; | ||
1434 | + } | ||
1435 | + currentQueue = null; | ||
1436 | + draining = false; | ||
1437 | + runClearTimeout(timeout); | ||
1438 | +} | ||
1439 | + | ||
1440 | +process.nextTick = function (fun) { | ||
1441 | + var args = new Array(arguments.length - 1); | ||
1442 | + if (arguments.length > 1) { | ||
1443 | + for (var i = 1; i < arguments.length; i++) { | ||
1444 | + args[i - 1] = arguments[i]; | ||
1445 | + } | ||
1446 | + } | ||
1447 | + queue.push(new Item(fun, args)); | ||
1448 | + if (queue.length === 1 && !draining) { | ||
1449 | + runTimeout(drainQueue); | ||
1450 | + } | ||
1451 | +}; | ||
1452 | + | ||
1453 | +// v8 likes predictible objects | ||
1454 | +function Item(fun, array) { | ||
1455 | + this.fun = fun; | ||
1456 | + this.array = array; | ||
1457 | +} | ||
1458 | +Item.prototype.run = function () { | ||
1459 | + this.fun.apply(null, this.array); | ||
1460 | +}; | ||
1461 | +process.title = 'browser'; | ||
1462 | +process.browser = true; | ||
1463 | +process.env = {}; | ||
1464 | +process.argv = []; | ||
1465 | +process.version = ''; // empty string to avoid regexp issues | ||
1466 | +process.versions = {}; | ||
1467 | + | ||
1468 | +function noop() {} | ||
1469 | + | ||
1470 | +process.on = noop; | ||
1471 | +process.addListener = noop; | ||
1472 | +process.once = noop; | ||
1473 | +process.off = noop; | ||
1474 | +process.removeListener = noop; | ||
1475 | +process.removeAllListeners = noop; | ||
1476 | +process.emit = noop; | ||
1477 | +process.prependListener = noop; | ||
1478 | +process.prependOnceListener = noop; | ||
1479 | + | ||
1480 | +process.listeners = function (name) { return [] } | ||
1481 | + | ||
1482 | +process.binding = function (name) { | ||
1483 | + throw new Error('process.binding is not supported'); | ||
1484 | +}; | ||
1485 | + | ||
1486 | +process.cwd = function () { return '/' }; | ||
1487 | +process.chdir = function (dir) { | ||
1488 | + throw new Error('process.chdir is not supported'); | ||
1489 | +}; | ||
1490 | +process.umask = function() { return 0; }; | ||
1491 | + | ||
1492 | +},{}],6:[function(require,module,exports){ | ||
1493 | +module.exports={ | ||
1494 | + "name": "ejs", | ||
1495 | + "description": "Embedded JavaScript templates", | ||
1496 | + "keywords": [ | ||
1497 | + "template", | ||
1498 | + "engine", | ||
1499 | + "ejs" | ||
1500 | + ], | ||
1501 | + "version": "3.0.1", | ||
1502 | + "author": "Matthew Eernisse <mde@fleegix.org> (http://fleegix.org)", | ||
1503 | + "license": "Apache-2.0", | ||
1504 | + "main": "./lib/ejs.js", | ||
1505 | + "repository": { | ||
1506 | + "type": "git", | ||
1507 | + "url": "git://github.com/mde/ejs.git" | ||
1508 | + }, | ||
1509 | + "bugs": "https://github.com/mde/ejs/issues", | ||
1510 | + "homepage": "https://github.com/mde/ejs", | ||
1511 | + "dependencies": {}, | ||
1512 | + "devDependencies": { | ||
1513 | + "browserify": "^13.1.1", | ||
1514 | + "eslint": "^4.14.0", | ||
1515 | + "git-directory-deploy": "^1.5.1", | ||
1516 | + "jake": "^10.3.1", | ||
1517 | + "jsdoc": "^3.4.0", | ||
1518 | + "lru-cache": "^4.0.1", | ||
1519 | + "mocha": "^5.0.5", | ||
1520 | + "uglify-js": "^3.3.16" | ||
1521 | + }, | ||
1522 | + "engines": { | ||
1523 | + "node": ">=0.10.0" | ||
1524 | + }, | ||
1525 | + "scripts": { | ||
1526 | + "test": "mocha", | ||
1527 | + "postinstall": "node ./postinstall.js" | ||
1528 | + } | ||
1529 | +} | ||
1530 | + | ||
1531 | +},{}]},{},[1])(1) | ||
1532 | +}); |
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(){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}return e}()({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_OPEN_DELIMITER="<";var _DEFAULT_CLOSE_DELIMITER=">";var _DEFAULT_DELIMITER="%";var _DEFAULT_LOCALS_NAME="locals";var _NAME="ejs";var _REGEX_STRING="(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)";var _OPTS_PASSABLE_WITH_DATA=["delimiter","scope","context","debug","compileDebug","client","_with","rmWhitespace","strict","filename","async"];var _OPTS_PASSABLE_WITH_DATA_EXPRESS=_OPTS_PASSABLE_WITH_DATA.concat("cache");var _BOM=/^\uFEFF/;exports.cache=utils.cache;exports.fileLoader=fs.readFileSync;exports.localsName=_DEFAULT_LOCALS_NAME;exports.promiseImpl=new Function("return this;")().Promise;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;var match=/^[A-Za-z]+:\\|^\//.exec(path);if(match&&match.length){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 the include file "'+options.escapeFunction(path)+'"')}}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;if(!cb){if(typeof exports.promiseImpl=="function"){return new exports.promiseImpl(function(resolve,reject){try{result=handleCache(options)(data);resolve(result)}catch(err){reject(err)}})}else{throw new Error("Please provide a callback function")}}else{try{result=handleCache(options)(data)}catch(err){return cb(err)}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 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_PASSABLE_WITH_DATA)}return handleCache(opts,template)(data)};exports.renderFile=function(){var args=Array.prototype.slice.call(arguments);var filename=args.shift();var cb;var opts={filename:filename};var data;var viewOpts;if(typeof arguments[arguments.length-1]=="function"){cb=args.pop()}if(args.length){data=args.shift();if(args.length){utils.shallowCopy(opts,args.pop())}else{if(data.settings){if(data.settings.views){opts.views=data.settings.views}if(data.settings["view cache"]){opts.cache=true}viewOpts=data.settings["view options"];if(viewOpts){utils.shallowCopy(opts,viewOpts)}}utils.shallowCopyFromList(opts,data,_OPTS_PASSABLE_WITH_DATA_EXPRESS)}opts.filename=filename}else{data={}}return tryHandleCache(opts,data,cb)};exports.Template=Template;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||opts.escapeFunction||utils.escapeXML;options.compileDebug=opts.compileDebug!==false;options.debug=!!opts.debug;options.filename=opts.filename;options.openDelimiter=opts.openDelimiter||exports.openDelimiter||_DEFAULT_OPEN_DELIMITER;options.closeDelimiter=opts.closeDelimiter||exports.closeDelimiter||_DEFAULT_CLOSE_DELIMITER;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.outputFunctionName=opts.outputFunctionName;options.localsName=opts.localsName||exports.localsName||_DEFAULT_LOCALS_NAME;options.views=opts.views;options.async=opts.async;options.destructuredLocals=opts.destructuredLocals;options.legacyInclude=typeof opts.legacyInclude!="undefined"?!!opts.legacyInclude:true;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);var open=utils.escapeRegExpChars(this.opts.openDelimiter);var close=utils.escapeRegExpChars(this.opts.closeDelimiter);str=str.replace(/%/g,delim).replace(/</g,open).replace(/>/g,close);return new RegExp(str)},compile:function(){var src;var fn;var opts=this.opts;var prepended="";var appended="";var escapeFn=opts.escapeFunction;var ctor;if(!this.source){this.generateSource();prepended+=' var __output = "";\n'+" function __append(s) { if (s !== undefined && s !== null) __output += s }\n";if(opts.outputFunctionName){prepended+=" var "+opts.outputFunctionName+" = __append;"+"\n"}if(opts.destructuredLocals&&opts.destructuredLocals.length){var destructuring=" var __locals = ("+opts.localsName+" || {}),\n";for(var i=0;i<opts.destructuredLocals.length;i++){var name=opts.destructuredLocals[i];if(i>0){destructuring+=",\n "}destructuring+=name+" = __locals."+name}prepended+=destructuring+";\n"}if(opts._with!==false){prepended+=" with ("+opts.localsName+" || {}) {"+"\n";appended+=" }"+"\n"}appended+=" return __output;"+"\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)}if(opts.compileDebug&&opts.filename){src=src+"\n"+"//# sourceURL="+opts.filename+"\n"}try{if(opts.async){try{ctor=new Function("return (async function(){}).constructor;")()}catch(e){if(e instanceof SyntaxError){throw new Error("This environment does not support async/await")}else{throw e}}}else{ctor=Function}fn=new ctor(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";if(!opts.async){e.message+="\n";e.message+="Or, if you meant to create an async function, pass `async: true` as an option."}}throw e}var returnedFn=opts.client?fn:function anonymous(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;if(opts.filename&&typeof Object.defineProperty==="function"){var filename=opts.filename;var basename=path.basename(filename,path.extname(filename));try{Object.defineProperty(returnedFn,"name",{value:basename,writable:false,enumerable:false,configurable:true})}catch(e){}}return returnedFn},generateSource:function(){var opts=this.opts;if(opts.rmWhitespace){this.templateText=this.templateText.replace(/[\r\n]+/g,"\n").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;var o=this.opts.openDelimiter;var c=this.opts.closeDelimiter;if(matches&&matches.length){matches.forEach(function(line,index){var closing;if(line.indexOf(o+d)===0&&line.indexOf(o+d+d)!==0){closing=matches[index+2];if(!(closing==d+c||closing=="-"+d+c||closing=="_"+d+c)){throw new Error('Could not find matching close tag for "'+line+'".')}}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}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 o=this.opts.openDelimiter;var c=this.opts.closeDelimiter;var newLineCount=0;newLineCount=line.split("\n").length-1;switch(line){case o+d:case o+d+"_":this.mode=Template.modes.EVAL;break;case o+d+"=":this.mode=Template.modes.ESCAPED;break;case o+d+"-":this.mode=Template.modes.RAW;break;case o+d+"#":this.mode=Template.modes.COMMENT;break;case o+d+d:this.mode=Template.modes.LITERAL;this.source+=' ; __append("'+line.replace(o+d+d,o+d)+'")'+"\n";break;case d+d+c:this.mode=Template.modes.LITERAL;this.source+=' ; __append("'+line.replace(d+d+c,d+c)+'")'+"\n";break;case d+c:case"-"+d+c:case"_"+d+c: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;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]},remove:function(key){delete 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.prependListener=noop;process.prependOnceListener=noop;process.listeners=function(name){return[]};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:"3.0.1",author:"Matthew Eernisse <mde@fleegix.org> (http://fleegix.org)",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.1.1",eslint:"^4.14.0","git-directory-deploy":"^1.5.1",jake:"^10.3.1",jsdoc:"^3.4.0","lru-cache":"^4.0.1",mocha:"^5.0.5","uglify-js":"^3.3.16"},engines:{node:">=0.10.0"},scripts:{test:"mocha",postinstall:"node ./postinstall.js"}}},{}]},{},[1])(1)}); |
node_modules/ejs/jakefile.js
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', ['clean'], function () { | ||
22 | + exec('./node_modules/.bin/eslint "**/*.js"'); | ||
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 | +desc('Generates the EJS API docs'); | ||
37 | +task('doc', function (dev) { | ||
38 | + jake.rmRf('out'); | ||
39 | + var p = dev ? '-p' : ''; | ||
40 | + exec('./node_modules/.bin/jsdoc ' + p + ' -c jsdoc.json lib/* docs/jsdoc/*'); | ||
41 | + console.log('Documentation generated.'); | ||
42 | +}); | ||
43 | + | ||
44 | +desc('Publishes the EJS API docs'); | ||
45 | +task('docPublish', ['doc'], function () { | ||
46 | + fs.writeFileSync('out/CNAME', 'api.ejs.co'); | ||
47 | + console.log('Pushing docs to gh-pages...'); | ||
48 | + exec('./node_modules/.bin/git-directory-deploy --directory out/'); | ||
49 | + console.log('Docs published to gh-pages.'); | ||
50 | +}); | ||
51 | + | ||
52 | +desc('Runs the EJS test suite'); | ||
53 | +task('test', ['lint'], function () { | ||
54 | + exec('./node_modules/.bin/mocha'); | ||
55 | +}); | ||
56 | + | ||
57 | +publishTask('ejs', ['build'], function () { | ||
58 | + this.packageFiles.include([ | ||
59 | + 'jakefile.js', | ||
60 | + 'README.md', | ||
61 | + 'LICENSE', | ||
62 | + 'package.json', | ||
63 | + 'postinstall.js', | ||
64 | + 'ejs.js', | ||
65 | + 'ejs.min.js', | ||
66 | + 'lib/**' | ||
67 | + ]); | ||
68 | +}); | ||
69 | + | ||
70 | +jake.Task.publish.on('complete', function () { | ||
71 | + console.log('Updating hosted docs...'); | ||
72 | + console.log('If this fails, run jake docPublish to re-try.'); | ||
73 | + jake.Task.docPublish.invoke(); | ||
74 | +}); |
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_OPEN_DELIMITER = '<'; | ||
54 | +var _DEFAULT_CLOSE_DELIMITER = '>'; | ||
55 | +var _DEFAULT_DELIMITER = '%'; | ||
56 | +var _DEFAULT_LOCALS_NAME = 'locals'; | ||
57 | +var _NAME = 'ejs'; | ||
58 | +var _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)'; | ||
59 | +var _OPTS_PASSABLE_WITH_DATA = ['delimiter', 'scope', 'context', 'debug', 'compileDebug', | ||
60 | + 'client', '_with', 'rmWhitespace', 'strict', 'filename', 'async']; | ||
61 | +// We don't allow 'cache' option to be passed in the data obj for | ||
62 | +// the normal `render` call, but this is where Express 2 & 3 put it | ||
63 | +// so we make an exception for `renderFile` | ||
64 | +var _OPTS_PASSABLE_WITH_DATA_EXPRESS = _OPTS_PASSABLE_WITH_DATA.concat('cache'); | ||
65 | +var _BOM = /^\uFEFF/; | ||
66 | + | ||
67 | +/** | ||
68 | + * EJS template function cache. This can be a LRU object from lru-cache NPM | ||
69 | + * module. By default, it is {@link module:utils.cache}, a simple in-process | ||
70 | + * cache that grows continuously. | ||
71 | + * | ||
72 | + * @type {Cache} | ||
73 | + */ | ||
74 | + | ||
75 | +exports.cache = utils.cache; | ||
76 | + | ||
77 | +/** | ||
78 | + * Custom file loader. Useful for template preprocessing or restricting access | ||
79 | + * to a certain part of the filesystem. | ||
80 | + * | ||
81 | + * @type {fileLoader} | ||
82 | + */ | ||
83 | + | ||
84 | +exports.fileLoader = fs.readFileSync; | ||
85 | + | ||
86 | +/** | ||
87 | + * Name of the object containing the locals. | ||
88 | + * | ||
89 | + * This variable is overridden by {@link Options}`.localsName` if it is not | ||
90 | + * `undefined`. | ||
91 | + * | ||
92 | + * @type {String} | ||
93 | + * @public | ||
94 | + */ | ||
95 | + | ||
96 | +exports.localsName = _DEFAULT_LOCALS_NAME; | ||
97 | + | ||
98 | +/** | ||
99 | + * Promise implementation -- defaults to the native implementation if available | ||
100 | + * This is mostly just for testability | ||
101 | + * | ||
102 | + * @type {Function} | ||
103 | + * @public | ||
104 | + */ | ||
105 | + | ||
106 | +exports.promiseImpl = (new Function('return this;'))().Promise; | ||
107 | + | ||
108 | +/** | ||
109 | + * Get the path to the included file from the parent file path and the | ||
110 | + * specified path. | ||
111 | + * | ||
112 | + * @param {String} name specified path | ||
113 | + * @param {String} filename parent file path | ||
114 | + * @param {Boolean} isDir parent file path whether is directory | ||
115 | + * @return {String} | ||
116 | + */ | ||
117 | +exports.resolveInclude = function(name, filename, isDir) { | ||
118 | + var dirname = path.dirname; | ||
119 | + var extname = path.extname; | ||
120 | + var resolve = path.resolve; | ||
121 | + var includePath = resolve(isDir ? filename : dirname(filename), name); | ||
122 | + var ext = extname(name); | ||
123 | + if (!ext) { | ||
124 | + includePath += '.ejs'; | ||
125 | + } | ||
126 | + return includePath; | ||
127 | +}; | ||
128 | + | ||
129 | +/** | ||
130 | + * Get the path to the included file by Options | ||
131 | + * | ||
132 | + * @param {String} path specified path | ||
133 | + * @param {Options} options compilation options | ||
134 | + * @return {String} | ||
135 | + */ | ||
136 | +function getIncludePath(path, options) { | ||
137 | + var includePath; | ||
138 | + var filePath; | ||
139 | + var views = options.views; | ||
140 | + var match = /^[A-Za-z]+:\\|^\//.exec(path); | ||
141 | + | ||
142 | + // Abs path | ||
143 | + if (match && match.length) { | ||
144 | + includePath = exports.resolveInclude(path.replace(/^\/*/,''), options.root || '/', true); | ||
145 | + } | ||
146 | + // Relative paths | ||
147 | + else { | ||
148 | + // Look relative to a passed filename first | ||
149 | + if (options.filename) { | ||
150 | + filePath = exports.resolveInclude(path, options.filename); | ||
151 | + if (fs.existsSync(filePath)) { | ||
152 | + includePath = filePath; | ||
153 | + } | ||
154 | + } | ||
155 | + // Then look in any views directories | ||
156 | + if (!includePath) { | ||
157 | + if (Array.isArray(views) && views.some(function (v) { | ||
158 | + filePath = exports.resolveInclude(path, v, true); | ||
159 | + return fs.existsSync(filePath); | ||
160 | + })) { | ||
161 | + includePath = filePath; | ||
162 | + } | ||
163 | + } | ||
164 | + if (!includePath) { | ||
165 | + throw new Error('Could not find the include file "' + | ||
166 | + options.escapeFunction(path) + '"'); | ||
167 | + } | ||
168 | + } | ||
169 | + return includePath; | ||
170 | +} | ||
171 | + | ||
172 | +/** | ||
173 | + * Get the template from a string or a file, either compiled on-the-fly or | ||
174 | + * read from cache (if enabled), and cache the template if needed. | ||
175 | + * | ||
176 | + * If `template` is not set, the file specified in `options.filename` will be | ||
177 | + * read. | ||
178 | + * | ||
179 | + * If `options.cache` is true, this function reads the file from | ||
180 | + * `options.filename` so it must be set prior to calling this function. | ||
181 | + * | ||
182 | + * @memberof module:ejs-internal | ||
183 | + * @param {Options} options compilation options | ||
184 | + * @param {String} [template] template source | ||
185 | + * @return {(TemplateFunction|ClientFunction)} | ||
186 | + * Depending on the value of `options.client`, either type might be returned. | ||
187 | + * @static | ||
188 | + */ | ||
189 | + | ||
190 | +function handleCache(options, template) { | ||
191 | + var func; | ||
192 | + var filename = options.filename; | ||
193 | + var hasTemplate = arguments.length > 1; | ||
194 | + | ||
195 | + if (options.cache) { | ||
196 | + if (!filename) { | ||
197 | + throw new Error('cache option requires a filename'); | ||
198 | + } | ||
199 | + func = exports.cache.get(filename); | ||
200 | + if (func) { | ||
201 | + return func; | ||
202 | + } | ||
203 | + if (!hasTemplate) { | ||
204 | + template = fileLoader(filename).toString().replace(_BOM, ''); | ||
205 | + } | ||
206 | + } | ||
207 | + else if (!hasTemplate) { | ||
208 | + // istanbul ignore if: should not happen at all | ||
209 | + if (!filename) { | ||
210 | + throw new Error('Internal EJS error: no file name or template ' | ||
211 | + + 'provided'); | ||
212 | + } | ||
213 | + template = fileLoader(filename).toString().replace(_BOM, ''); | ||
214 | + } | ||
215 | + func = exports.compile(template, options); | ||
216 | + if (options.cache) { | ||
217 | + exports.cache.set(filename, func); | ||
218 | + } | ||
219 | + return func; | ||
220 | +} | ||
221 | + | ||
222 | +/** | ||
223 | + * Try calling handleCache with the given options and data and call the | ||
224 | + * callback with the result. If an error occurs, call the callback with | ||
225 | + * the error. Used by renderFile(). | ||
226 | + * | ||
227 | + * @memberof module:ejs-internal | ||
228 | + * @param {Options} options compilation options | ||
229 | + * @param {Object} data template data | ||
230 | + * @param {RenderFileCallback} cb callback | ||
231 | + * @static | ||
232 | + */ | ||
233 | + | ||
234 | +function tryHandleCache(options, data, cb) { | ||
235 | + var result; | ||
236 | + if (!cb) { | ||
237 | + if (typeof exports.promiseImpl == 'function') { | ||
238 | + return new exports.promiseImpl(function (resolve, reject) { | ||
239 | + try { | ||
240 | + result = handleCache(options)(data); | ||
241 | + resolve(result); | ||
242 | + } | ||
243 | + catch (err) { | ||
244 | + reject(err); | ||
245 | + } | ||
246 | + }); | ||
247 | + } | ||
248 | + else { | ||
249 | + throw new Error('Please provide a callback function'); | ||
250 | + } | ||
251 | + } | ||
252 | + else { | ||
253 | + try { | ||
254 | + result = handleCache(options)(data); | ||
255 | + } | ||
256 | + catch (err) { | ||
257 | + return cb(err); | ||
258 | + } | ||
259 | + | ||
260 | + cb(null, result); | ||
261 | + } | ||
262 | +} | ||
263 | + | ||
264 | +/** | ||
265 | + * fileLoader is independent | ||
266 | + * | ||
267 | + * @param {String} filePath ejs file path. | ||
268 | + * @return {String} The contents of the specified file. | ||
269 | + * @static | ||
270 | + */ | ||
271 | + | ||
272 | +function fileLoader(filePath){ | ||
273 | + return exports.fileLoader(filePath); | ||
274 | +} | ||
275 | + | ||
276 | +/** | ||
277 | + * Get the template function. | ||
278 | + * | ||
279 | + * If `options.cache` is `true`, then the template is cached. | ||
280 | + * | ||
281 | + * @memberof module:ejs-internal | ||
282 | + * @param {String} path path for the specified file | ||
283 | + * @param {Options} options compilation options | ||
284 | + * @return {(TemplateFunction|ClientFunction)} | ||
285 | + * Depending on the value of `options.client`, either type might be returned | ||
286 | + * @static | ||
287 | + */ | ||
288 | + | ||
289 | +function includeFile(path, options) { | ||
290 | + var opts = utils.shallowCopy({}, options); | ||
291 | + opts.filename = getIncludePath(path, opts); | ||
292 | + return handleCache(opts); | ||
293 | +} | ||
294 | + | ||
295 | +/** | ||
296 | + * Re-throw the given `err` in context to the `str` of ejs, `filename`, and | ||
297 | + * `lineno`. | ||
298 | + * | ||
299 | + * @implements RethrowCallback | ||
300 | + * @memberof module:ejs-internal | ||
301 | + * @param {Error} err Error object | ||
302 | + * @param {String} str EJS source | ||
303 | + * @param {String} filename file name of the EJS file | ||
304 | + * @param {String} lineno line number of the error | ||
305 | + * @static | ||
306 | + */ | ||
307 | + | ||
308 | +function rethrow(err, str, flnm, lineno, esc){ | ||
309 | + var lines = str.split('\n'); | ||
310 | + var start = Math.max(lineno - 3, 0); | ||
311 | + var end = Math.min(lines.length, lineno + 3); | ||
312 | + var filename = esc(flnm); // eslint-disable-line | ||
313 | + // Error context | ||
314 | + var context = lines.slice(start, end).map(function (line, i){ | ||
315 | + var curr = i + start + 1; | ||
316 | + return (curr == lineno ? ' >> ' : ' ') | ||
317 | + + curr | ||
318 | + + '| ' | ||
319 | + + line; | ||
320 | + }).join('\n'); | ||
321 | + | ||
322 | + // Alter exception message | ||
323 | + err.path = filename; | ||
324 | + err.message = (filename || 'ejs') + ':' | ||
325 | + + lineno + '\n' | ||
326 | + + context + '\n\n' | ||
327 | + + err.message; | ||
328 | + | ||
329 | + throw err; | ||
330 | +} | ||
331 | + | ||
332 | +function stripSemi(str){ | ||
333 | + return str.replace(/;(\s*$)/, '$1'); | ||
334 | +} | ||
335 | + | ||
336 | +/** | ||
337 | + * Compile the given `str` of ejs into a template function. | ||
338 | + * | ||
339 | + * @param {String} template EJS template | ||
340 | + * | ||
341 | + * @param {Options} opts compilation options | ||
342 | + * | ||
343 | + * @return {(TemplateFunction|ClientFunction)} | ||
344 | + * Depending on the value of `opts.client`, either type might be returned. | ||
345 | + * Note that the return type of the function also depends on the value of `opts.async`. | ||
346 | + * @public | ||
347 | + */ | ||
348 | + | ||
349 | +exports.compile = function compile(template, opts) { | ||
350 | + var templ; | ||
351 | + | ||
352 | + // v1 compat | ||
353 | + // 'scope' is 'context' | ||
354 | + // FIXME: Remove this in a future version | ||
355 | + if (opts && opts.scope) { | ||
356 | + if (!scopeOptionWarned){ | ||
357 | + console.warn('`scope` option is deprecated and will be removed in EJS 3'); | ||
358 | + scopeOptionWarned = true; | ||
359 | + } | ||
360 | + if (!opts.context) { | ||
361 | + opts.context = opts.scope; | ||
362 | + } | ||
363 | + delete opts.scope; | ||
364 | + } | ||
365 | + templ = new Template(template, opts); | ||
366 | + return templ.compile(); | ||
367 | +}; | ||
368 | + | ||
369 | +/** | ||
370 | + * Render the given `template` of ejs. | ||
371 | + * | ||
372 | + * If you would like to include options but not data, you need to explicitly | ||
373 | + * call this function with `data` being an empty object or `null`. | ||
374 | + * | ||
375 | + * @param {String} template EJS template | ||
376 | + * @param {Object} [data={}] template data | ||
377 | + * @param {Options} [opts={}] compilation and rendering options | ||
378 | + * @return {(String|Promise<String>)} | ||
379 | + * Return value type depends on `opts.async`. | ||
380 | + * @public | ||
381 | + */ | ||
382 | + | ||
383 | +exports.render = function (template, d, o) { | ||
384 | + var data = d || {}; | ||
385 | + var opts = o || {}; | ||
386 | + | ||
387 | + // No options object -- if there are optiony names | ||
388 | + // in the data, copy them to options | ||
389 | + if (arguments.length == 2) { | ||
390 | + utils.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA); | ||
391 | + } | ||
392 | + | ||
393 | + return handleCache(opts, template)(data); | ||
394 | +}; | ||
395 | + | ||
396 | +/** | ||
397 | + * Render an EJS file at the given `path` and callback `cb(err, str)`. | ||
398 | + * | ||
399 | + * If you would like to include options but not data, you need to explicitly | ||
400 | + * call this function with `data` being an empty object or `null`. | ||
401 | + * | ||
402 | + * @param {String} path path to the EJS file | ||
403 | + * @param {Object} [data={}] template data | ||
404 | + * @param {Options} [opts={}] compilation and rendering options | ||
405 | + * @param {RenderFileCallback} cb callback | ||
406 | + * @public | ||
407 | + */ | ||
408 | + | ||
409 | +exports.renderFile = function () { | ||
410 | + var args = Array.prototype.slice.call(arguments); | ||
411 | + var filename = args.shift(); | ||
412 | + var cb; | ||
413 | + var opts = {filename: filename}; | ||
414 | + var data; | ||
415 | + var viewOpts; | ||
416 | + | ||
417 | + // Do we have a callback? | ||
418 | + if (typeof arguments[arguments.length - 1] == 'function') { | ||
419 | + cb = args.pop(); | ||
420 | + } | ||
421 | + // Do we have data/opts? | ||
422 | + if (args.length) { | ||
423 | + // Should always have data obj | ||
424 | + data = args.shift(); | ||
425 | + // Normal passed opts (data obj + opts obj) | ||
426 | + if (args.length) { | ||
427 | + // Use shallowCopy so we don't pollute passed in opts obj with new vals | ||
428 | + utils.shallowCopy(opts, args.pop()); | ||
429 | + } | ||
430 | + // Special casing for Express (settings + opts-in-data) | ||
431 | + else { | ||
432 | + // Express 3 and 4 | ||
433 | + if (data.settings) { | ||
434 | + // Pull a few things from known locations | ||
435 | + if (data.settings.views) { | ||
436 | + opts.views = data.settings.views; | ||
437 | + } | ||
438 | + if (data.settings['view cache']) { | ||
439 | + opts.cache = true; | ||
440 | + } | ||
441 | + // Undocumented after Express 2, but still usable, esp. for | ||
442 | + // items that are unsafe to be passed along with data, like `root` | ||
443 | + viewOpts = data.settings['view options']; | ||
444 | + if (viewOpts) { | ||
445 | + utils.shallowCopy(opts, viewOpts); | ||
446 | + } | ||
447 | + } | ||
448 | + // Express 2 and lower, values set in app.locals, or people who just | ||
449 | + // want to pass options in their data. NOTE: These values will override | ||
450 | + // anything previously set in settings or settings['view options'] | ||
451 | + utils.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA_EXPRESS); | ||
452 | + } | ||
453 | + opts.filename = filename; | ||
454 | + } | ||
455 | + else { | ||
456 | + data = {}; | ||
457 | + } | ||
458 | + | ||
459 | + return tryHandleCache(opts, data, cb); | ||
460 | +}; | ||
461 | + | ||
462 | +/** | ||
463 | + * Clear intermediate JavaScript cache. Calls {@link Cache#reset}. | ||
464 | + * @public | ||
465 | + */ | ||
466 | + | ||
467 | +/** | ||
468 | + * EJS template class | ||
469 | + * @public | ||
470 | + */ | ||
471 | +exports.Template = Template; | ||
472 | + | ||
473 | +exports.clearCache = function () { | ||
474 | + exports.cache.reset(); | ||
475 | +}; | ||
476 | + | ||
477 | +function Template(text, opts) { | ||
478 | + opts = opts || {}; | ||
479 | + var options = {}; | ||
480 | + this.templateText = text; | ||
481 | + this.mode = null; | ||
482 | + this.truncate = false; | ||
483 | + this.currentLine = 1; | ||
484 | + this.source = ''; | ||
485 | + this.dependencies = []; | ||
486 | + options.client = opts.client || false; | ||
487 | + options.escapeFunction = opts.escape || opts.escapeFunction || utils.escapeXML; | ||
488 | + options.compileDebug = opts.compileDebug !== false; | ||
489 | + options.debug = !!opts.debug; | ||
490 | + options.filename = opts.filename; | ||
491 | + options.openDelimiter = opts.openDelimiter || exports.openDelimiter || _DEFAULT_OPEN_DELIMITER; | ||
492 | + options.closeDelimiter = opts.closeDelimiter || exports.closeDelimiter || _DEFAULT_CLOSE_DELIMITER; | ||
493 | + options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER; | ||
494 | + options.strict = opts.strict || false; | ||
495 | + options.context = opts.context; | ||
496 | + options.cache = opts.cache || false; | ||
497 | + options.rmWhitespace = opts.rmWhitespace; | ||
498 | + options.root = opts.root; | ||
499 | + options.outputFunctionName = opts.outputFunctionName; | ||
500 | + options.localsName = opts.localsName || exports.localsName || _DEFAULT_LOCALS_NAME; | ||
501 | + options.views = opts.views; | ||
502 | + options.async = opts.async; | ||
503 | + options.destructuredLocals = opts.destructuredLocals; | ||
504 | + options.legacyInclude = typeof opts.legacyInclude != 'undefined' ? !!opts.legacyInclude : true; | ||
505 | + | ||
506 | + if (options.strict) { | ||
507 | + options._with = false; | ||
508 | + } | ||
509 | + else { | ||
510 | + options._with = typeof opts._with != 'undefined' ? opts._with : true; | ||
511 | + } | ||
512 | + | ||
513 | + this.opts = options; | ||
514 | + | ||
515 | + this.regex = this.createRegex(); | ||
516 | +} | ||
517 | + | ||
518 | +Template.modes = { | ||
519 | + EVAL: 'eval', | ||
520 | + ESCAPED: 'escaped', | ||
521 | + RAW: 'raw', | ||
522 | + COMMENT: 'comment', | ||
523 | + LITERAL: 'literal' | ||
524 | +}; | ||
525 | + | ||
526 | +Template.prototype = { | ||
527 | + createRegex: function () { | ||
528 | + var str = _REGEX_STRING; | ||
529 | + var delim = utils.escapeRegExpChars(this.opts.delimiter); | ||
530 | + var open = utils.escapeRegExpChars(this.opts.openDelimiter); | ||
531 | + var close = utils.escapeRegExpChars(this.opts.closeDelimiter); | ||
532 | + str = str.replace(/%/g, delim) | ||
533 | + .replace(/</g, open) | ||
534 | + .replace(/>/g, close); | ||
535 | + return new RegExp(str); | ||
536 | + }, | ||
537 | + | ||
538 | + compile: function () { | ||
539 | + var src; | ||
540 | + var fn; | ||
541 | + var opts = this.opts; | ||
542 | + var prepended = ''; | ||
543 | + var appended = ''; | ||
544 | + var escapeFn = opts.escapeFunction; | ||
545 | + var ctor; | ||
546 | + | ||
547 | + if (!this.source) { | ||
548 | + this.generateSource(); | ||
549 | + prepended += | ||
550 | + ' var __output = "";\n' + | ||
551 | + ' function __append(s) { if (s !== undefined && s !== null) __output += s }\n'; | ||
552 | + if (opts.outputFunctionName) { | ||
553 | + prepended += ' var ' + opts.outputFunctionName + ' = __append;' + '\n'; | ||
554 | + } | ||
555 | + if (opts.destructuredLocals && opts.destructuredLocals.length) { | ||
556 | + var destructuring = ' var __locals = (' + opts.localsName + ' || {}),\n'; | ||
557 | + for (var i = 0; i < opts.destructuredLocals.length; i++) { | ||
558 | + var name = opts.destructuredLocals[i]; | ||
559 | + if (i > 0) { | ||
560 | + destructuring += ',\n '; | ||
561 | + } | ||
562 | + destructuring += name + ' = __locals.' + name; | ||
563 | + } | ||
564 | + prepended += destructuring + ';\n'; | ||
565 | + } | ||
566 | + if (opts._with !== false) { | ||
567 | + prepended += ' with (' + opts.localsName + ' || {}) {' + '\n'; | ||
568 | + appended += ' }' + '\n'; | ||
569 | + } | ||
570 | + appended += ' return __output;' + '\n'; | ||
571 | + this.source = prepended + this.source + appended; | ||
572 | + } | ||
573 | + | ||
574 | + if (opts.compileDebug) { | ||
575 | + src = 'var __line = 1' + '\n' | ||
576 | + + ' , __lines = ' + JSON.stringify(this.templateText) + '\n' | ||
577 | + + ' , __filename = ' + (opts.filename ? | ||
578 | + JSON.stringify(opts.filename) : 'undefined') + ';' + '\n' | ||
579 | + + 'try {' + '\n' | ||
580 | + + this.source | ||
581 | + + '} catch (e) {' + '\n' | ||
582 | + + ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\n' | ||
583 | + + '}' + '\n'; | ||
584 | + } | ||
585 | + else { | ||
586 | + src = this.source; | ||
587 | + } | ||
588 | + | ||
589 | + if (opts.client) { | ||
590 | + src = 'escapeFn = escapeFn || ' + escapeFn.toString() + ';' + '\n' + src; | ||
591 | + if (opts.compileDebug) { | ||
592 | + src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\n' + src; | ||
593 | + } | ||
594 | + } | ||
595 | + | ||
596 | + if (opts.strict) { | ||
597 | + src = '"use strict";\n' + src; | ||
598 | + } | ||
599 | + if (opts.debug) { | ||
600 | + console.log(src); | ||
601 | + } | ||
602 | + if (opts.compileDebug && opts.filename) { | ||
603 | + src = src + '\n' | ||
604 | + + '//# sourceURL=' + opts.filename + '\n'; | ||
605 | + } | ||
606 | + | ||
607 | + try { | ||
608 | + if (opts.async) { | ||
609 | + // Have to use generated function for this, since in envs without support, | ||
610 | + // it breaks in parsing | ||
611 | + try { | ||
612 | + ctor = (new Function('return (async function(){}).constructor;'))(); | ||
613 | + } | ||
614 | + catch(e) { | ||
615 | + if (e instanceof SyntaxError) { | ||
616 | + throw new Error('This environment does not support async/await'); | ||
617 | + } | ||
618 | + else { | ||
619 | + throw e; | ||
620 | + } | ||
621 | + } | ||
622 | + } | ||
623 | + else { | ||
624 | + ctor = Function; | ||
625 | + } | ||
626 | + fn = new ctor(opts.localsName + ', escapeFn, include, rethrow', src); | ||
627 | + } | ||
628 | + catch(e) { | ||
629 | + // istanbul ignore else | ||
630 | + if (e instanceof SyntaxError) { | ||
631 | + if (opts.filename) { | ||
632 | + e.message += ' in ' + opts.filename; | ||
633 | + } | ||
634 | + e.message += ' while compiling ejs\n\n'; | ||
635 | + e.message += 'If the above error is not helpful, you may want to try EJS-Lint:\n'; | ||
636 | + e.message += 'https://github.com/RyanZim/EJS-Lint'; | ||
637 | + if (!opts.async) { | ||
638 | + e.message += '\n'; | ||
639 | + e.message += 'Or, if you meant to create an async function, pass `async: true` as an option.'; | ||
640 | + } | ||
641 | + } | ||
642 | + throw e; | ||
643 | + } | ||
644 | + | ||
645 | + // Return a callable function which will execute the function | ||
646 | + // created by the source-code, with the passed data as locals | ||
647 | + // Adds a local `include` function which allows full recursive include | ||
648 | + var returnedFn = opts.client ? fn : function anonymous(data) { | ||
649 | + var include = function (path, includeData) { | ||
650 | + var d = utils.shallowCopy({}, data); | ||
651 | + if (includeData) { | ||
652 | + d = utils.shallowCopy(d, includeData); | ||
653 | + } | ||
654 | + return includeFile(path, opts)(d); | ||
655 | + }; | ||
656 | + return fn.apply(opts.context, [data || {}, escapeFn, include, rethrow]); | ||
657 | + }; | ||
658 | + returnedFn.dependencies = this.dependencies; | ||
659 | + if (opts.filename && typeof Object.defineProperty === 'function') { | ||
660 | + var filename = opts.filename; | ||
661 | + var basename = path.basename(filename, path.extname(filename)); | ||
662 | + try { | ||
663 | + Object.defineProperty(returnedFn, 'name', { | ||
664 | + value: basename, | ||
665 | + writable: false, | ||
666 | + enumerable: false, | ||
667 | + configurable: true | ||
668 | + }); | ||
669 | + } catch (e) {/* ignore */} | ||
670 | + } | ||
671 | + return returnedFn; | ||
672 | + }, | ||
673 | + | ||
674 | + generateSource: function () { | ||
675 | + var opts = this.opts; | ||
676 | + | ||
677 | + if (opts.rmWhitespace) { | ||
678 | + // Have to use two separate replace here as `^` and `$` operators don't | ||
679 | + // work well with `\r` and empty lines don't work well with the `m` flag. | ||
680 | + this.templateText = | ||
681 | + this.templateText.replace(/[\r\n]+/g, '\n').replace(/^\s+|\s+$/gm, ''); | ||
682 | + } | ||
683 | + | ||
684 | + // Slurp spaces and tabs before <%_ and after _%> | ||
685 | + this.templateText = | ||
686 | + this.templateText.replace(/[ \t]*<%_/gm, '<%_').replace(/_%>[ \t]*/gm, '_%>'); | ||
687 | + | ||
688 | + var self = this; | ||
689 | + var matches = this.parseTemplateText(); | ||
690 | + var d = this.opts.delimiter; | ||
691 | + var o = this.opts.openDelimiter; | ||
692 | + var c = this.opts.closeDelimiter; | ||
693 | + | ||
694 | + if (matches && matches.length) { | ||
695 | + matches.forEach(function (line, index) { | ||
696 | + var closing; | ||
697 | + // If this is an opening tag, check for closing tags | ||
698 | + // FIXME: May end up with some false positives here | ||
699 | + // Better to store modes as k/v with openDelimiter + delimiter as key | ||
700 | + // Then this can simply check against the map | ||
701 | + if ( line.indexOf(o + d) === 0 // If it is a tag | ||
702 | + && line.indexOf(o + d + d) !== 0) { // and is not escaped | ||
703 | + closing = matches[index + 2]; | ||
704 | + if (!(closing == d + c || closing == '-' + d + c || closing == '_' + d + c)) { | ||
705 | + throw new Error('Could not find matching close tag for "' + line + '".'); | ||
706 | + } | ||
707 | + } | ||
708 | + self.scanLine(line); | ||
709 | + }); | ||
710 | + } | ||
711 | + | ||
712 | + }, | ||
713 | + | ||
714 | + parseTemplateText: function () { | ||
715 | + var str = this.templateText; | ||
716 | + var pat = this.regex; | ||
717 | + var result = pat.exec(str); | ||
718 | + var arr = []; | ||
719 | + var firstPos; | ||
720 | + | ||
721 | + while (result) { | ||
722 | + firstPos = result.index; | ||
723 | + | ||
724 | + if (firstPos !== 0) { | ||
725 | + arr.push(str.substring(0, firstPos)); | ||
726 | + str = str.slice(firstPos); | ||
727 | + } | ||
728 | + | ||
729 | + arr.push(result[0]); | ||
730 | + str = str.slice(result[0].length); | ||
731 | + result = pat.exec(str); | ||
732 | + } | ||
733 | + | ||
734 | + if (str) { | ||
735 | + arr.push(str); | ||
736 | + } | ||
737 | + | ||
738 | + return arr; | ||
739 | + }, | ||
740 | + | ||
741 | + _addOutput: function (line) { | ||
742 | + if (this.truncate) { | ||
743 | + // Only replace single leading linebreak in the line after | ||
744 | + // -%> tag -- this is the single, trailing linebreak | ||
745 | + // after the tag that the truncation mode replaces | ||
746 | + // Handle Win / Unix / old Mac linebreaks -- do the \r\n | ||
747 | + // combo first in the regex-or | ||
748 | + line = line.replace(/^(?:\r\n|\r|\n)/, ''); | ||
749 | + this.truncate = false; | ||
750 | + } | ||
751 | + if (!line) { | ||
752 | + return line; | ||
753 | + } | ||
754 | + | ||
755 | + // Preserve literal slashes | ||
756 | + line = line.replace(/\\/g, '\\\\'); | ||
757 | + | ||
758 | + // Convert linebreaks | ||
759 | + line = line.replace(/\n/g, '\\n'); | ||
760 | + line = line.replace(/\r/g, '\\r'); | ||
761 | + | ||
762 | + // Escape double-quotes | ||
763 | + // - this will be the delimiter during execution | ||
764 | + line = line.replace(/"/g, '\\"'); | ||
765 | + this.source += ' ; __append("' + line + '")' + '\n'; | ||
766 | + }, | ||
767 | + | ||
768 | + scanLine: function (line) { | ||
769 | + var self = this; | ||
770 | + var d = this.opts.delimiter; | ||
771 | + var o = this.opts.openDelimiter; | ||
772 | + var c = this.opts.closeDelimiter; | ||
773 | + var newLineCount = 0; | ||
774 | + | ||
775 | + newLineCount = (line.split('\n').length - 1); | ||
776 | + | ||
777 | + switch (line) { | ||
778 | + case o + d: | ||
779 | + case o + d + '_': | ||
780 | + this.mode = Template.modes.EVAL; | ||
781 | + break; | ||
782 | + case o + d + '=': | ||
783 | + this.mode = Template.modes.ESCAPED; | ||
784 | + break; | ||
785 | + case o + d + '-': | ||
786 | + this.mode = Template.modes.RAW; | ||
787 | + break; | ||
788 | + case o + d + '#': | ||
789 | + this.mode = Template.modes.COMMENT; | ||
790 | + break; | ||
791 | + case o + d + d: | ||
792 | + this.mode = Template.modes.LITERAL; | ||
793 | + this.source += ' ; __append("' + line.replace(o + d + d, o + d) + '")' + '\n'; | ||
794 | + break; | ||
795 | + case d + d + c: | ||
796 | + this.mode = Template.modes.LITERAL; | ||
797 | + this.source += ' ; __append("' + line.replace(d + d + c, d + c) + '")' + '\n'; | ||
798 | + break; | ||
799 | + case d + c: | ||
800 | + case '-' + d + c: | ||
801 | + case '_' + d + c: | ||
802 | + if (this.mode == Template.modes.LITERAL) { | ||
803 | + this._addOutput(line); | ||
804 | + } | ||
805 | + | ||
806 | + this.mode = null; | ||
807 | + this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0; | ||
808 | + break; | ||
809 | + default: | ||
810 | + // In script mode, depends on type of tag | ||
811 | + if (this.mode) { | ||
812 | + // If '//' is found without a line break, add a line break. | ||
813 | + switch (this.mode) { | ||
814 | + case Template.modes.EVAL: | ||
815 | + case Template.modes.ESCAPED: | ||
816 | + case Template.modes.RAW: | ||
817 | + if (line.lastIndexOf('//') > line.lastIndexOf('\n')) { | ||
818 | + line += '\n'; | ||
819 | + } | ||
820 | + } | ||
821 | + switch (this.mode) { | ||
822 | + // Just executing code | ||
823 | + case Template.modes.EVAL: | ||
824 | + this.source += ' ; ' + line + '\n'; | ||
825 | + break; | ||
826 | + // Exec, esc, and output | ||
827 | + case Template.modes.ESCAPED: | ||
828 | + this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\n'; | ||
829 | + break; | ||
830 | + // Exec and output | ||
831 | + case Template.modes.RAW: | ||
832 | + this.source += ' ; __append(' + stripSemi(line) + ')' + '\n'; | ||
833 | + break; | ||
834 | + case Template.modes.COMMENT: | ||
835 | + // Do nothing | ||
836 | + break; | ||
837 | + // Literal <%% mode, append as raw output | ||
838 | + case Template.modes.LITERAL: | ||
839 | + this._addOutput(line); | ||
840 | + break; | ||
841 | + } | ||
842 | + } | ||
843 | + // In string mode, just add the output | ||
844 | + else { | ||
845 | + this._addOutput(line); | ||
846 | + } | ||
847 | + } | ||
848 | + | ||
849 | + if (self.opts.compileDebug && newLineCount) { | ||
850 | + this.currentLine += newLineCount; | ||
851 | + this.source += ' ; __line = ' + this.currentLine + '\n'; | ||
852 | + } | ||
853 | + } | ||
854 | +}; | ||
855 | + | ||
856 | +/** | ||
857 | + * Escape characters reserved in XML. | ||
858 | + * | ||
859 | + * This is simply an export of {@link module:utils.escapeXML}. | ||
860 | + * | ||
861 | + * If `markup` is `undefined` or `null`, the empty string is returned. | ||
862 | + * | ||
863 | + * @param {String} markup Input string | ||
864 | + * @return {String} Escaped string | ||
865 | + * @public | ||
866 | + * @func | ||
867 | + * */ | ||
868 | +exports.escapeXML = utils.escapeXML; | ||
869 | + | ||
870 | +/** | ||
871 | + * Express.js support. | ||
872 | + * | ||
873 | + * This is an alias for {@link module:ejs.renderFile}, in order to support | ||
874 | + * Express.js out-of-the-box. | ||
875 | + * | ||
876 | + * @func | ||
877 | + */ | ||
878 | + | ||
879 | +exports.__express = exports.renderFile; | ||
880 | + | ||
881 | +/** | ||
882 | + * Version of EJS. | ||
883 | + * | ||
884 | + * @readonly | ||
885 | + * @type {String} | ||
886 | + * @public | ||
887 | + */ | ||
888 | + | ||
889 | +exports.VERSION = _VERSION_STRING; | ||
890 | + | ||
891 | +/** | ||
892 | + * Name for detection of EJS. | ||
893 | + * | ||
894 | + * @readonly | ||
895 | + * @type {String} | ||
896 | + * @public | ||
897 | + */ | ||
898 | + | ||
899 | +exports.name = _NAME; | ||
900 | + | ||
901 | +/* istanbul ignore if */ | ||
902 | +if (typeof window != 'undefined') { | ||
903 | + window.ejs = exports; | ||
904 | +} |
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 | + remove: function (key) { | ||
162 | + delete this._data[key]; | ||
163 | + }, | ||
164 | + reset: function () { | ||
165 | + this._data = {}; | ||
166 | + } | ||
167 | +}; |
node_modules/ejs/package.json
0 → 100644
1 | +{ | ||
2 | + "_from": "ejs", | ||
3 | + "_id": "ejs@3.0.1", | ||
4 | + "_inBundle": false, | ||
5 | + "_integrity": "sha512-cuIMtJwxvzumSAkqaaoGY/L6Fc/t6YvoP9/VIaK0V/CyqKLEQ8sqODmYfy/cjXEdZ9+OOL8TecbJu+1RsofGDw==", | ||
6 | + "_location": "/ejs", | ||
7 | + "_phantomChildren": {}, | ||
8 | + "_requested": { | ||
9 | + "type": "tag", | ||
10 | + "registry": true, | ||
11 | + "raw": "ejs", | ||
12 | + "name": "ejs", | ||
13 | + "escapedName": "ejs", | ||
14 | + "rawSpec": "", | ||
15 | + "saveSpec": null, | ||
16 | + "fetchSpec": "latest" | ||
17 | + }, | ||
18 | + "_requiredBy": [ | ||
19 | + "#USER", | ||
20 | + "/" | ||
21 | + ], | ||
22 | + "_resolved": "https://registry.npmjs.org/ejs/-/ejs-3.0.1.tgz", | ||
23 | + "_shasum": "30c8f6ee9948502cc32e85c37a3f8b39b5a614a5", | ||
24 | + "_spec": "ejs", | ||
25 | + "_where": "C:\\Users\\LG\\Desktop\\4-1\\Reminder-Talk", | ||
26 | + "author": { | ||
27 | + "name": "Matthew Eernisse", | ||
28 | + "email": "mde@fleegix.org", | ||
29 | + "url": "http://fleegix.org" | ||
30 | + }, | ||
31 | + "bugs": { | ||
32 | + "url": "https://github.com/mde/ejs/issues" | ||
33 | + }, | ||
34 | + "bundleDependencies": false, | ||
35 | + "dependencies": {}, | ||
36 | + "deprecated": false, | ||
37 | + "description": "Embedded JavaScript templates", | ||
38 | + "devDependencies": { | ||
39 | + "browserify": "^13.1.1", | ||
40 | + "eslint": "^4.14.0", | ||
41 | + "git-directory-deploy": "^1.5.1", | ||
42 | + "jake": "^10.3.1", | ||
43 | + "jsdoc": "^3.4.0", | ||
44 | + "lru-cache": "^4.0.1", | ||
45 | + "mocha": "^5.0.5", | ||
46 | + "uglify-js": "^3.3.16" | ||
47 | + }, | ||
48 | + "engines": { | ||
49 | + "node": ">=0.10.0" | ||
50 | + }, | ||
51 | + "homepage": "https://github.com/mde/ejs", | ||
52 | + "keywords": [ | ||
53 | + "template", | ||
54 | + "engine", | ||
55 | + "ejs" | ||
56 | + ], | ||
57 | + "license": "Apache-2.0", | ||
58 | + "main": "./lib/ejs.js", | ||
59 | + "name": "ejs", | ||
60 | + "repository": { | ||
61 | + "type": "git", | ||
62 | + "url": "git://github.com/mde/ejs.git" | ||
63 | + }, | ||
64 | + "scripts": { | ||
65 | + "postinstall": "node ./postinstall.js", | ||
66 | + "test": "mocha" | ||
67 | + }, | ||
68 | + "version": "3.0.1" | ||
69 | +} |
node_modules/ejs/postinstall.js
0 → 100644
1 | +#!/usr/bin/env node | ||
2 | + | ||
3 | +'use strict'; | ||
4 | + | ||
5 | +function isTrue(value) { | ||
6 | + return !!value && value !== '0' && value !== 'false'; | ||
7 | +} | ||
8 | + | ||
9 | +let envDisable = isTrue(process.env.DISABLE_OPENCOLLECTIVE) || isTrue(process.env.CI); | ||
10 | +let logLevel = process.env.npm_config_loglevel; | ||
11 | +let logLevelDisplay = ['silent', 'error', 'warn'].indexOf(logLevel) > -1; | ||
12 | + | ||
13 | +if (!envDisable && !logLevelDisplay) { | ||
14 | + console.log('Thank you for installing \u001b[35mEJS\u001b[0m: built with the \u001b[32mJake\u001b[0m JavaScript build tool (\u001b[32mhttps://jakejs.com/\u001b[0m)\n'); | ||
15 | +} | ||
16 | + | ||
17 | + |
... | @@ -225,6 +225,11 @@ | ... | @@ -225,6 +225,11 @@ |
225 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", | 225 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", |
226 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" | 226 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" |
227 | }, | 227 | }, |
228 | + "ejs": { | ||
229 | + "version": "3.0.1", | ||
230 | + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.0.1.tgz", | ||
231 | + "integrity": "sha512-cuIMtJwxvzumSAkqaaoGY/L6Fc/t6YvoP9/VIaK0V/CyqKLEQ8sqODmYfy/cjXEdZ9+OOL8TecbJu+1RsofGDw==" | ||
232 | + }, | ||
228 | "encodeurl": { | 233 | "encodeurl": { |
229 | "version": "1.0.2", | 234 | "version": "1.0.2", |
230 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", | 235 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", | ... | ... |
... | @@ -8,6 +8,7 @@ | ... | @@ -8,6 +8,7 @@ |
8 | "dependencies": { | 8 | "dependencies": { |
9 | "cookie-parser": "~1.4.4", | 9 | "cookie-parser": "~1.4.4", |
10 | "debug": "~2.6.9", | 10 | "debug": "~2.6.9", |
11 | + "ejs": "^3.0.1", | ||
11 | "express": "~4.16.1", | 12 | "express": "~4.16.1", |
12 | "http-errors": "~1.6.3", | 13 | "http-errors": "~1.6.3", |
13 | "jade": "~1.11.0", | 14 | "jade": "~1.11.0", | ... | ... |
views/error.ejs
0 → 100644
views/error.jade
deleted
100644 → 0
views/index.ejs
0 → 100644
1 | +<!DOCTYPE html> | ||
2 | +<html> | ||
3 | + <head> | ||
4 | + <title><%= title %></title> | ||
5 | + <link rel='stylesheet' href='/stylesheets/style.css' /> | ||
6 | + </head> | ||
7 | + <body> | ||
8 | + <h1><%= title %></h1> | ||
9 | + <p>Welcome to <%= title %></p> | ||
10 | + </body> | ||
11 | +</html> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
views/index.jade
deleted
100644 → 0
-
Please register or login to post a comment