chore: disable delete confirmation in VS Code explorer
Disable the confirmation dialog when deleting files in the VS Code explorer to streamline the development workflow and reduce friction during file management operations.
This commit is contained in:
202
website/node_modules/ejs/LICENSE
generated
vendored
Normal file
202
website/node_modules/ejs/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
374
website/node_modules/ejs/README.md
generated
vendored
Normal file
374
website/node_modules/ejs/README.md
generated
vendored
Normal file
@@ -0,0 +1,374 @@
|
||||
Embedded JavaScript templates<br/>
|
||||
[](https://snyk.io/test/npm/ejs)
|
||||
=============================
|
||||
|
||||
## Security
|
||||
|
||||
Security professionals, before reporting any security issues, please reference the
|
||||
<a href="https://github.com/mde/ejs/blob/main/SECURITY.md">SECURITY.md</a>
|
||||
in this project, in particular, the following: "EJS is effectively a JavaScript runtime.
|
||||
Its entire job is to execute JavaScript. If you run the EJS render method without
|
||||
checking the inputs yourself, you are responsible for the results."
|
||||
|
||||
In short, DO NOT submit 'vulnerabilities' that include this snippet of code:
|
||||
|
||||
```javascript
|
||||
app.get('/', (req, res) => {
|
||||
res.render('index', req.query);
|
||||
});
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
$ npm install ejs
|
||||
```
|
||||
|
||||
### Import or require
|
||||
|
||||
Supports both CommonJS and ES Modules.
|
||||
|
||||
```javascript
|
||||
import ejs from 'ejs';
|
||||
// Or
|
||||
const ejs = require('ejs');
|
||||
```
|
||||
|
||||
### Compatibility
|
||||
|
||||
Server: CommonJS approach (`require`) supports Node versions at least
|
||||
back to v0.12, likely older versions too. ES Modules approach (`import`)
|
||||
requires a Node version that supports ESM.
|
||||
|
||||
CLI: Requires Node v8 or newer.
|
||||
|
||||
Browser: EJS supports all modern browsers, but is very likely to work even
|
||||
in very, very old browsers. Your mileage may vary.
|
||||
|
||||
## Features
|
||||
|
||||
* Control flow with `<% %>`
|
||||
* Escaped output with `<%= %>` (escape function configurable)
|
||||
* Unescaped raw output with `<%- %>`
|
||||
* Newline-trim mode ('newline slurping') with `-%>` ending tag
|
||||
* Whitespace-trim mode (slurp all whitespace) for control flow with `<%_ _%>`
|
||||
* Custom delimiters (e.g. `[? ?]` instead of `<% %>`)
|
||||
* Includes
|
||||
* Client-side support
|
||||
* Static caching of intermediate JavaScript
|
||||
* Static caching of templates
|
||||
* Complies with the [Express](http://expressjs.com) view system
|
||||
|
||||
## Example
|
||||
|
||||
```ejs
|
||||
<% if (user) { %>
|
||||
<h2><%= user.name %></h2>
|
||||
<% } %>
|
||||
```
|
||||
|
||||
## Basic usage
|
||||
|
||||
```javascript
|
||||
const template = ejs.compile(str, options);
|
||||
template(data);
|
||||
// => Rendered HTML string
|
||||
|
||||
ejs.render(str, data, options);
|
||||
// => Rendered HTML string
|
||||
|
||||
ejs.renderFile(filename, data, options, function(err, str){
|
||||
// str => Rendered HTML string
|
||||
});
|
||||
```
|
||||
|
||||
It is also possible to use `ejs.render(dataAndOptions);` where you pass
|
||||
everything in a single object. In that case, you'll end up with local variables
|
||||
for all the passed options. However, be aware that your code could break if we
|
||||
add an option with the same name as one of your data object's properties.
|
||||
Therefore, we do not recommend using this shortcut.
|
||||
|
||||
### Important
|
||||
You should never give end-users unfettered access to the EJS render method, If you do so you are using EJS in an inherently un-secure way.
|
||||
|
||||
### Options
|
||||
|
||||
- `cache` Compiled functions are cached, requires `filename`
|
||||
- `filename` The name of the file being rendered. Not required if you
|
||||
are using `renderFile()`. Used by `cache` to key caches, and for includes.
|
||||
- `root` Set template root(s) for includes with an absolute path (e.g, /file.ejs).
|
||||
Can be array to try to resolve include from multiple directories.
|
||||
- `views` An array of paths to use when resolving includes with relative paths.
|
||||
- `context` Function execution context
|
||||
- `compileDebug` When `false` no debug instrumentation is compiled
|
||||
- `delimiter` Character to use for inner delimiter, by default '%'
|
||||
- `openDelimiter` Character to use for opening delimiter, by default '<'
|
||||
- `closeDelimiter` Character to use for closing delimiter, by default '>'
|
||||
- `debug` Outputs generated function body
|
||||
- `strict` When set to `true`, generated function is in strict mode
|
||||
- `_with` Whether or not to use `with() {}` constructs. If `false`
|
||||
then the locals will be stored in the `locals` object. Set to `false` in strict mode.
|
||||
- `destructuredLocals` An array of local variables that are always destructured from
|
||||
the locals object, available even in strict mode.
|
||||
- `localsName` Name to use for the object storing local variables when not using
|
||||
`with` Defaults to `locals`
|
||||
- `rmWhitespace` Remove all safe-to-remove whitespace, including leading
|
||||
and trailing whitespace. It also enables a safer version of `-%>` line
|
||||
slurping for all scriptlet tags (it does not strip new lines of tags in
|
||||
the middle of a line).
|
||||
- `escape` The escaping function used with `<%=` construct.
|
||||
(By default escapes XML).
|
||||
- `outputFunctionName` Set to a string (e.g., 'echo' or 'print') for a function to print
|
||||
output inside scriptlet tags.
|
||||
- `async` When `true`, EJS will use an async function for rendering. (Depends
|
||||
on async/await support in the JS runtime).
|
||||
- `includer` Custom function to handle EJS includes, receives `(originalPath, parsedPath)`
|
||||
parameters, where `originalPath` is the path in include as-is and `parsedPath` is the
|
||||
previously resolved path. Should return an object `{ filename, template }`,
|
||||
you may return only one of the properties, where `filename` is the final parsed path and `template`
|
||||
is the included content.
|
||||
|
||||
This project uses [JSDoc](https://jsdoc.app/). For the full public API
|
||||
documentation, clone the repository and run `jake doc`. This will run JSDoc
|
||||
with the proper options and output the documentation to `out/`. If you want
|
||||
the both the public & private API docs, run `jake devdoc` instead.
|
||||
|
||||
### Tags
|
||||
|
||||
- `<%` 'Scriptlet' tag, for control-flow, no output
|
||||
- `<%_` 'Whitespace Slurping' Scriptlet tag, strips all whitespace before it
|
||||
- `<%=` Outputs the value into the template (escaped)
|
||||
- `<%-` Outputs the unescaped value into the template
|
||||
- `<%#` Comment tag, no execution, no output
|
||||
- `<%%` Outputs a literal '<%'
|
||||
- `%%>` Outputs a literal '%>'
|
||||
- `%>` Plain ending tag
|
||||
- `-%>` Trim-mode ('newline slurp') tag, trims following newline
|
||||
- `_%>` 'Whitespace Slurping' ending tag, removes all whitespace after it
|
||||
|
||||
For the full syntax documentation, please see [docs/syntax.md](https://github.com/mde/ejs/blob/master/docs/syntax.md).
|
||||
|
||||
### Includes
|
||||
|
||||
Includes either have to be an absolute path, or, if not, are assumed as
|
||||
relative to the template with the `include` call. For example if you are
|
||||
including `./views/user/show.ejs` from `./views/users.ejs` you would
|
||||
use `<%- include('user/show') %>`.
|
||||
|
||||
You must specify the `filename` option for the template with the `include`
|
||||
call unless you are using `renderFile()`.
|
||||
|
||||
You'll likely want to use the raw output tag (`<%-`) with your include to avoid
|
||||
double-escaping the HTML output.
|
||||
|
||||
```ejs
|
||||
<ul>
|
||||
<% users.forEach(function(user){ %>
|
||||
<%- include('user/show', {user: user}) %>
|
||||
<% }); %>
|
||||
</ul>
|
||||
```
|
||||
|
||||
Includes are inserted at runtime, so you can use variables for the path in the
|
||||
`include` call (for example `<%- include(somePath) %>`). Variables in your
|
||||
top-level data object are available to all your includes, but local variables
|
||||
need to be passed down.
|
||||
|
||||
NOTE: Include preprocessor directives (`<% include user/show %>`) are
|
||||
not supported in v3.0+.
|
||||
|
||||
## Custom delimiters
|
||||
|
||||
Custom delimiters can be applied on a per-template basis, or globally:
|
||||
|
||||
```javascript
|
||||
import ejs from 'ejs';
|
||||
const users = ['geddy', 'neil', 'alex'];
|
||||
|
||||
// Just one template
|
||||
ejs.render('<p>[?= users.join(" | "); ?]</p>', {users: users}, {delimiter: '?', openDelimiter: '[', closeDelimiter: ']'});
|
||||
// => '<p>geddy | neil | alex</p>'
|
||||
|
||||
// Or globally
|
||||
ejs.delimiter = '?';
|
||||
ejs.openDelimiter = '[';
|
||||
ejs.closeDelimiter = ']';
|
||||
ejs.render('<p>[?= users.join(" | "); ?]</p>', {users: users});
|
||||
// => '<p>geddy | neil | alex</p>'
|
||||
```
|
||||
|
||||
### Caching
|
||||
|
||||
EJS ships with a basic in-process cache for caching the intermediate JavaScript
|
||||
functions used to render templates. It's easy to plug in LRU caching using
|
||||
Node's `lru-cache` library:
|
||||
|
||||
```javascript
|
||||
import ejs from 'ejs';
|
||||
import { LRUCache } from 'lru-cache';
|
||||
|
||||
ejs.cache = LRUCache({max: 100}); // LRU cache with 100-item limit
|
||||
```
|
||||
|
||||
If you want to clear the EJS cache, call `ejs.clearCache`. If you're using the
|
||||
LRU cache and need a different limit, simple reset `ejs.cache` to a new instance
|
||||
of the LRU.
|
||||
|
||||
### Custom file loader
|
||||
|
||||
The default file loader is `fs.readFileSync`, if you want to customize it, you can set ejs.fileLoader.
|
||||
|
||||
```javascript
|
||||
import ejs from 'ejs';
|
||||
|
||||
const myFileLoad = function (filePath) {
|
||||
return 'myFileLoad: ' + fs.readFileSync(filePath);
|
||||
};
|
||||
|
||||
ejs.fileLoader = myFileLoad;
|
||||
```
|
||||
|
||||
With this feature, you can preprocess the template before reading it.
|
||||
|
||||
### Layouts
|
||||
|
||||
EJS does not specifically support blocks, but layouts can be implemented by
|
||||
including headers and footers, like so:
|
||||
|
||||
```ejs
|
||||
<%- include('header') -%>
|
||||
<h1>
|
||||
Title
|
||||
</h1>
|
||||
<p>
|
||||
My page
|
||||
</p>
|
||||
<%- include('footer') -%>
|
||||
```
|
||||
|
||||
## Client-side support
|
||||
|
||||
Go to the [Latest Release](https://github.com/mde/ejs/releases/latest), download
|
||||
`./ejs.js` or `./ejs.min.js`. Alternately, you can compile it yourself by cloning
|
||||
the repository and running `jake build` (or `npx jake build` if jake is
|
||||
not installed globally).
|
||||
|
||||
Include one of these files on your page, and `ejs` should be available globally.
|
||||
|
||||
### Example
|
||||
|
||||
```html
|
||||
<div id="output"></div>
|
||||
<script src="ejs.min.js"></script>
|
||||
<script>
|
||||
let people = ['geddy', 'neil', 'alex'],
|
||||
html = ejs.render('<%= people.join(", "); %>', {people: people});
|
||||
// With jQuery:
|
||||
$('#output').html(html);
|
||||
// Vanilla JS:
|
||||
document.getElementById('output').innerHTML = html;
|
||||
</script>
|
||||
```
|
||||
|
||||
### Caveats
|
||||
|
||||
Most of EJS will work as expected; however, there are a few things to note:
|
||||
|
||||
1. Obviously, since you do not have access to the filesystem, `ejs.renderFile()` won't work.
|
||||
2. For the same reason, `include`s do not work unless you use an `include callback`. Here is an example:
|
||||
```javascript
|
||||
let str = "Hello <%= include('file', {person: 'John'}); %>",
|
||||
fn = ejs.compile(str);
|
||||
|
||||
fn(data, null, function(path, d){ // include callback
|
||||
// path -> 'file'
|
||||
// d -> {person: 'John'}
|
||||
// Put your code here
|
||||
// Return the contents of file as a string
|
||||
}); // returns rendered string
|
||||
```
|
||||
|
||||
See the [examples folder](https://github.com/mde/ejs/tree/master/examples) for more details.
|
||||
|
||||
## CLI
|
||||
|
||||
EJS ships with a full-featured CLI. Options are similar to those used in JavaScript code:
|
||||
|
||||
- `-o / --output-file FILE` Write the rendered output to FILE rather than stdout.
|
||||
- `-f / --data-file FILE` Must be JSON-formatted. Use parsed input from FILE as data for rendering.
|
||||
- `-i / --data-input STRING` Must be JSON-formatted and URI-encoded. Use parsed input from STRING as data for rendering.
|
||||
- `-m / --delimiter CHARACTER` Use CHARACTER with angle brackets for open/close (defaults to %).
|
||||
- `-p / --open-delimiter CHARACTER` Use CHARACTER instead of left angle bracket to open.
|
||||
- `-c / --close-delimiter CHARACTER` Use CHARACTER instead of right angle bracket to close.
|
||||
- `-s / --strict` When set to `true`, generated function is in strict mode
|
||||
- `-n / --no-with` Use 'locals' object for vars rather than using `with` (implies --strict).
|
||||
- `-l / --locals-name` Name to use for the object storing local variables when not using `with`.
|
||||
- `-w / --rm-whitespace` Remove all safe-to-remove whitespace, including leading and trailing whitespace.
|
||||
- `-d / --debug` Outputs generated function body
|
||||
- `-h / --help` Display this help message.
|
||||
- `-V/v / --version` Display the EJS version.
|
||||
|
||||
Here are some examples of usage:
|
||||
|
||||
```shell
|
||||
$ ejs -p [ -c ] ./template_file.ejs -o ./output.html
|
||||
$ ejs ./test/fixtures/user.ejs name=Lerxst
|
||||
$ ejs -n -l _ ./some_template.ejs -f ./data_file.json
|
||||
```
|
||||
|
||||
### Data input
|
||||
|
||||
There is a variety of ways to pass the CLI data for rendering.
|
||||
|
||||
Stdin:
|
||||
|
||||
```shell
|
||||
$ ./test/fixtures/user_data.json | ejs ./test/fixtures/user.ejs
|
||||
$ ejs ./test/fixtures/user.ejs < test/fixtures/user_data.json
|
||||
```
|
||||
|
||||
A data file:
|
||||
|
||||
```shell
|
||||
$ ejs ./test/fixtures/user.ejs -f ./user_data.json
|
||||
```
|
||||
|
||||
A command-line option (must be URI-encoded):
|
||||
|
||||
```shell
|
||||
./bin/cli.js -i %7B%22name%22%3A%20%22foo%22%7D ./test/fixtures/user.ejs
|
||||
```
|
||||
|
||||
Or, passing values directly at the end of the invocation:
|
||||
|
||||
```shell
|
||||
./bin/cli.js -m $ ./test/fixtures/user.ejs name=foo
|
||||
```
|
||||
|
||||
### Output
|
||||
|
||||
The CLI by default send output to stdout, but you can use the `-o` or `--output-file`
|
||||
flag to specify a target file to send the output to.
|
||||
|
||||
## IDE Integration with Syntax Highlighting
|
||||
|
||||
VSCode:Javascript EJS by *DigitalBrainstem*
|
||||
|
||||
## Related projects
|
||||
|
||||
There are a number of implementations of EJS:
|
||||
|
||||
* TJ's implementation, the v1 of this library: https://github.com/tj/ejs
|
||||
* EJS Embedded JavaScript Framework on Google Code: https://code.google.com/p/embeddedjavascript/
|
||||
* Sam Stephenson's Ruby implementation: https://rubygems.org/gems/ejs
|
||||
* Erubis, an ERB implementation which also runs JavaScript: http://www.kuwata-lab.com/erubis/users-guide.04.html#lang-javascript
|
||||
* DigitalBrainstem EJS Language support: https://github.com/Digitalbrainstem/ejs-grammar
|
||||
|
||||
## License
|
||||
|
||||
Licensed under the Apache License, Version 2.0
|
||||
(<http://www.apache.org/licenses/LICENSE-2.0>)
|
||||
|
||||
- - -
|
||||
EJS Embedded JavaScript templates copyright 2112
|
||||
mde@fleegix.org.
|
||||
218
website/node_modules/ejs/bin/cli.js
generated
vendored
Normal file
218
website/node_modules/ejs/bin/cli.js
generated
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
* EJS Embedded JavaScript templates
|
||||
* Copyright 2112 Matthew Eernisse (mde@fleegix.org)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
let path = require('path');
|
||||
|
||||
let { Parser } = require('../lib/cjs/parseargs');
|
||||
|
||||
let ejs = require('../lib/cjs/ejs');
|
||||
let { hyphenToCamel } = require('../lib/cjs/utils');
|
||||
let fs = require('fs');
|
||||
let args = process.argv.slice(2);
|
||||
let usage = fs.readFileSync(`${__dirname}/../usage.txt`).toString();
|
||||
|
||||
function die(msg) {
|
||||
console.log(msg);
|
||||
process.stdout.write('', function () {
|
||||
process.stderr.write('', function () {
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const CLI_OPTS = [
|
||||
{ full: 'output-file',
|
||||
abbr: 'o',
|
||||
expectValue: true,
|
||||
},
|
||||
{ full: 'data-file',
|
||||
abbr: 'f',
|
||||
expectValue: true,
|
||||
},
|
||||
{ full: 'data-input',
|
||||
abbr: 'i',
|
||||
expectValue: true,
|
||||
},
|
||||
{ full: 'delimiter',
|
||||
abbr: 'm',
|
||||
expectValue: true,
|
||||
passThrough: true,
|
||||
},
|
||||
{ full: 'open-delimiter',
|
||||
abbr: 'p',
|
||||
expectValue: true,
|
||||
passThrough: true,
|
||||
},
|
||||
{ full: 'close-delimiter',
|
||||
abbr: 'c',
|
||||
expectValue: true,
|
||||
passThrough: true,
|
||||
},
|
||||
{ full: 'strict',
|
||||
abbr: 's',
|
||||
expectValue: false,
|
||||
allowValue: false,
|
||||
passThrough: true,
|
||||
},
|
||||
{ full: 'no-with',
|
||||
abbr: 'n',
|
||||
expectValue: false,
|
||||
allowValue: false,
|
||||
},
|
||||
{ full: 'locals-name',
|
||||
abbr: 'l',
|
||||
expectValue: true,
|
||||
passThrough: true,
|
||||
},
|
||||
{ full: 'rm-whitespace',
|
||||
abbr: 'w',
|
||||
expectValue: false,
|
||||
allowValue: false,
|
||||
passThrough: true,
|
||||
},
|
||||
{ full: 'debug',
|
||||
abbr: 'd',
|
||||
expectValue: false,
|
||||
allowValue: false,
|
||||
passThrough: true,
|
||||
},
|
||||
{ full: 'help',
|
||||
abbr: 'h',
|
||||
passThrough: true,
|
||||
},
|
||||
{ full: 'version',
|
||||
abbr: 'V',
|
||||
passThrough: true,
|
||||
},
|
||||
// Alias lowercase v
|
||||
{ full: 'version',
|
||||
abbr: 'v',
|
||||
passThrough: true,
|
||||
},
|
||||
];
|
||||
|
||||
let preempts = {
|
||||
version: function () {
|
||||
die(ejs.VERSION);
|
||||
},
|
||||
help: function () {
|
||||
die(usage);
|
||||
}
|
||||
};
|
||||
|
||||
let stdin = '';
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('readable', () => {
|
||||
let chunk;
|
||||
while ((chunk = process.stdin.read()) !== null) {
|
||||
stdin += chunk;
|
||||
}
|
||||
});
|
||||
|
||||
function run() {
|
||||
|
||||
let parser = new Parser(CLI_OPTS);
|
||||
let result = parser.parse(args);
|
||||
|
||||
let templatePath = result.taskNames[0];
|
||||
let pVals = result.envVars;
|
||||
let pOpts = {};
|
||||
|
||||
for (let p in result.opts) {
|
||||
let name = hyphenToCamel(p);
|
||||
pOpts[name] = result.opts[p];
|
||||
}
|
||||
|
||||
let opts = {};
|
||||
let vals = {};
|
||||
|
||||
// Same-named 'passthrough' opts
|
||||
CLI_OPTS.forEach((opt) => {
|
||||
let optName = hyphenToCamel(opt.full);
|
||||
if (opt.passThrough && typeof pOpts[optName] != 'undefined') {
|
||||
opts[optName] = pOpts[optName];
|
||||
}
|
||||
});
|
||||
|
||||
// Bail out for help/version
|
||||
for (let p in opts) {
|
||||
if (preempts[p]) {
|
||||
return preempts[p]();
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure there's a template to render
|
||||
if (!templatePath) {
|
||||
throw new Error('Please provide a template path. (Run ejs -h for help)');
|
||||
}
|
||||
|
||||
if (opts.strict) {
|
||||
pOpts.noWith = true;
|
||||
}
|
||||
if (pOpts.noWith) {
|
||||
opts._with = false;
|
||||
}
|
||||
|
||||
// Grab and parse any input data, in order of precedence:
|
||||
// 1. Stdin
|
||||
// 2. CLI arg via -i
|
||||
// 3. Data file via -f
|
||||
// Any individual vals passed at the end (e.g., foo=bar) will override
|
||||
// any vals previously set
|
||||
let input;
|
||||
let err = new Error('Please do not pass data multiple ways. Pick one of stdin, -f, or -i.');
|
||||
if (stdin) {
|
||||
input = stdin;
|
||||
}
|
||||
else if (pOpts.dataInput) {
|
||||
if (input) {
|
||||
throw err;
|
||||
}
|
||||
input = decodeURIComponent(pOpts.dataInput);
|
||||
}
|
||||
else if (pOpts.dataFile) {
|
||||
if (input) {
|
||||
throw err;
|
||||
}
|
||||
input = fs.readFileSync(pOpts.dataFile).toString();
|
||||
}
|
||||
|
||||
if (input) {
|
||||
vals = JSON.parse(input);
|
||||
}
|
||||
|
||||
// Override / set any individual values passed from the command line
|
||||
for (let p in pVals) {
|
||||
vals[p] = pVals[p];
|
||||
}
|
||||
|
||||
opts.filename = path.resolve(process.cwd(), templatePath);
|
||||
let template = fs.readFileSync(opts.filename).toString();
|
||||
let output = ejs.render(template, vals, opts);
|
||||
if (pOpts.outputFile) {
|
||||
fs.writeFileSync(pOpts.outputFile, output);
|
||||
}
|
||||
else {
|
||||
process.stdout.write(output);
|
||||
}
|
||||
process.exit();
|
||||
}
|
||||
|
||||
// Defer execution so that stdin can be read if necessary
|
||||
setImmediate(run);
|
||||
1817
website/node_modules/ejs/ejs.js
generated
vendored
Normal file
1817
website/node_modules/ejs/ejs.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
website/node_modules/ejs/ejs.min.js
generated
vendored
Normal file
1
website/node_modules/ejs/ejs.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
132
website/node_modules/ejs/jakefile.js
generated
vendored
Normal file
132
website/node_modules/ejs/jakefile.js
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
let fs = require('fs');
|
||||
let path = require('path');
|
||||
let execSync = require('child_process').execSync;
|
||||
let exec = function (cmd) {
|
||||
execSync(cmd, {stdio: 'inherit'});
|
||||
};
|
||||
|
||||
/* global jake, task, desc, publishTask */
|
||||
|
||||
const BUILT_EJS_FILES = [
|
||||
'ejs.js',
|
||||
'ejs.min.js',
|
||||
'lib/esm/ejs.js',
|
||||
'lib/cjs/ejs.js',
|
||||
];
|
||||
|
||||
// Hook into some of the publish lifecycle events
|
||||
jake.on('finished', function (ev) {
|
||||
|
||||
switch (ev.name) {
|
||||
case 'publish':
|
||||
console.log('Updating hosted docs...');
|
||||
console.log('If this fails, run jake docPublish to re-try.');
|
||||
jake.Task.docPublish.invoke();
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
desc('Builds the EJS library');
|
||||
task('build', ['lint', 'clean', 'compile', 'browserify', 'minify']);
|
||||
|
||||
desc('Compiles ESM to CJS source files');
|
||||
task('compile', function () {
|
||||
// Compile CJS version
|
||||
exec('npx tsc');
|
||||
let source = fs.readFileSync('lib/cjs/ejs.js', 'utf8').toString();
|
||||
// Browerify chokes on the 'node:' prefix in require statements
|
||||
// Added the 'node:' prefix to ESM for Deno compat
|
||||
['fs', 'path', 'url'].forEach((mod) => {
|
||||
source = source.replace(`require("node:${mod}")`, `require("${mod}")`);
|
||||
source = source.replace(new RegExp(`node_${mod}_1`, 'g'), `${mod}_1`);
|
||||
});
|
||||
// replace `let` in code-generation strings
|
||||
source = source.replace(
|
||||
"var DECLARATION_KEYWORD = 'let';",
|
||||
"var DECLARATION_KEYWORD = 'var';"
|
||||
);
|
||||
fs.writeFileSync('lib/cjs/ejs.js', source);
|
||||
fs.writeFileSync('lib/cjs/package.json', '{"type":"commonjs"}');
|
||||
});
|
||||
|
||||
desc('Cleans browerified/minified files and package files');
|
||||
task('clean', ['clobber'], function () {
|
||||
jake.rmRf('./ejs.js');
|
||||
jake.rmRf('./ejs.min.js');
|
||||
jake.rmRf('./lib/cjs');
|
||||
console.log('Cleaned up compiled files.');
|
||||
});
|
||||
|
||||
desc('Lints the source code');
|
||||
task('lint', ['clean'], function () {
|
||||
let epath = path.join('./node_modules/.bin/eslint');
|
||||
// Handle both ESM and CJS files in project
|
||||
exec(epath+' --config ./eslint.config_esm.mjs "lib/esm/*.js"');
|
||||
exec(epath+' --config ./eslint.config_cjs.mjs "test/*.js" "bin/cli.js" "jakefile.js"');
|
||||
console.log('Linting completed.');
|
||||
});
|
||||
|
||||
task('browserify', function () {
|
||||
const currentDir = process.cwd();
|
||||
process.chdir('./lib/cjs');
|
||||
let epath = path.join('../../node_modules/browserify/bin/cmd.js');
|
||||
exec(epath+' --standalone ejs ejs.js > ../../ejs.js');
|
||||
process.chdir(currentDir);
|
||||
console.log('Browserification completed.');
|
||||
});
|
||||
|
||||
task('minify', function () {
|
||||
let epath = path.join('./node_modules/uglify-js/bin/uglifyjs');
|
||||
exec(epath+' ./ejs.js > ejs.min.js');
|
||||
console.log('Minification completed.');
|
||||
});
|
||||
|
||||
desc('Generates the EJS API docs for the public API');
|
||||
task('doc', function () {
|
||||
jake.rmRf('out');
|
||||
let epath = path.join('./node_modules/.bin/jsdoc');
|
||||
exec(epath+' --verbose -c jsdoc.json lib/esm/* docs/jsdoc/*');
|
||||
console.log('Documentation generated in ./out.');
|
||||
});
|
||||
|
||||
desc('Generates the EJS API docs for the public and private API');
|
||||
task('devdoc', function () {
|
||||
jake.rmRf('out');
|
||||
let epath = path.join('./node_modules/.bin/jsdoc');
|
||||
exec(epath+' --verbose -p -c jsdoc.json lib/esm/* docs/jsdoc/*');
|
||||
console.log('Documentation generated in ./out.');
|
||||
});
|
||||
|
||||
desc('Publishes the EJS API docs');
|
||||
task('docPublish', ['doc'], function () {
|
||||
fs.writeFileSync('out/CNAME', 'api.ejs.co');
|
||||
console.log('Pushing docs to gh-pages...');
|
||||
let epath = path.join('./node_modules/.bin/git-directory-deploy');
|
||||
exec(epath+' --directory out/');
|
||||
console.log('Docs published to gh-pages.');
|
||||
});
|
||||
|
||||
desc('Runs the EJS test suite');
|
||||
task('test', ['build', 'testOnly'], function () {});
|
||||
|
||||
task('testOnly', function () {
|
||||
exec(path.join('./node_modules/.bin/mocha --u tdd'));
|
||||
});
|
||||
|
||||
publishTask('ejs', ['build'], function () {
|
||||
this.packageFiles.include([
|
||||
'jakefile.js',
|
||||
'README.md',
|
||||
'LICENSE',
|
||||
'package.json',
|
||||
'ejs.js',
|
||||
'ejs.min.js',
|
||||
'lib/**',
|
||||
'bin/**',
|
||||
'usage.txt'
|
||||
]);
|
||||
});
|
||||
|
||||
845
website/node_modules/ejs/lib/cjs/ejs.js
generated
vendored
Normal file
845
website/node_modules/ejs/lib/cjs/ejs.js
generated
vendored
Normal file
@@ -0,0 +1,845 @@
|
||||
/*
|
||||
* EJS Embedded JavaScript templates
|
||||
* Copyright 2112 Matthew Eernisse (mde@fleegix.org)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
'use strict';
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var fs_1 = __importDefault(require("fs"));
|
||||
var path_1 = __importDefault(require("path"));
|
||||
var utils_js_1 = __importDefault(require("./utils.js"));
|
||||
/**
|
||||
* @file Embedded JavaScript templating engine. {@link http://ejs.co}
|
||||
* @author Matthew Eernisse <mde@fleegix.org>
|
||||
* @project EJS
|
||||
* @license {@link http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0}
|
||||
*/
|
||||
/**
|
||||
* EJS internal functions.
|
||||
*
|
||||
* Technically this "module" lies in the same file as {@link module:ejs}, for
|
||||
* the sake of organization all the private functions re grouped into this
|
||||
* module.
|
||||
*
|
||||
* @module ejs-internal
|
||||
* @private
|
||||
*/
|
||||
/**
|
||||
* Embedded JavaScript templating engine.
|
||||
*
|
||||
* @module ejs
|
||||
* @public
|
||||
*/
|
||||
// Keyword used in code generation -- updated to 'var' in CJS build
|
||||
var DECLARATION_KEYWORD = 'var';
|
||||
var ejs = {};
|
||||
/** @type {string} */
|
||||
var _DEFAULT_OPEN_DELIMITER = '<';
|
||||
var _DEFAULT_CLOSE_DELIMITER = '>';
|
||||
var _DEFAULT_DELIMITER = '%';
|
||||
var _DEFAULT_LOCALS_NAME = 'locals';
|
||||
var _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)';
|
||||
var _OPTS_PASSABLE_WITH_DATA = ['delimiter', 'scope', 'context', 'debug', 'compileDebug',
|
||||
'_with', 'rmWhitespace', 'strict', 'filename', 'async'];
|
||||
// We don't allow 'cache' option to be passed in the data obj for
|
||||
// the normal `render` call, but this is where Express 2 & 3 put it
|
||||
// so we make an exception for `renderFile`
|
||||
var _OPTS_PASSABLE_WITH_DATA_EXPRESS = _OPTS_PASSABLE_WITH_DATA.concat('cache');
|
||||
var _BOM = /^\uFEFF/;
|
||||
var _JS_IDENTIFIER = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;
|
||||
/**
|
||||
* EJS template function cache. This can be a LRU object from lru-cache NPM
|
||||
* module. By default, it is {@link module:utils.cache}, a simple in-process
|
||||
* cache that grows continuously.
|
||||
*
|
||||
* @type {Cache}
|
||||
*/
|
||||
ejs.cache = utils_js_1.default.cache;
|
||||
/**
|
||||
* Custom file loader. Useful for template preprocessing or restricting access
|
||||
* to a certain part of the filesystem.
|
||||
*
|
||||
* @type {fileLoader}
|
||||
*/
|
||||
ejs.fileLoader = fs_1.default.readFileSync;
|
||||
/**
|
||||
* Name of the object containing the locals.
|
||||
*
|
||||
* This variable is overridden by {@link Options}`.localsName` if it is not
|
||||
* `undefined`.
|
||||
*
|
||||
* @type {String}
|
||||
* @public
|
||||
*/
|
||||
ejs.localsName = _DEFAULT_LOCALS_NAME;
|
||||
/**
|
||||
* Promise implementation -- defaults to the native implementation if available
|
||||
* This is mostly just for testability
|
||||
*
|
||||
* @type {PromiseConstructorLike}
|
||||
* @public
|
||||
*/
|
||||
ejs.promiseImpl = (new Function('return this;'))().Promise;
|
||||
/**
|
||||
* Get the path to the included file from the parent file path and the
|
||||
* specified path.
|
||||
*
|
||||
* @param {String} name specified path
|
||||
* @param {String} filename parent file path
|
||||
* @param {Boolean} [isDir=false] whether the parent file path is a directory
|
||||
* @return {String}
|
||||
*/
|
||||
ejs.resolveInclude = function (name, filename, isDir) {
|
||||
var dirname = path_1.default.dirname;
|
||||
var extname = path_1.default.extname;
|
||||
var resolve = path_1.default.resolve;
|
||||
var includePath = resolve(isDir ? filename : dirname(filename), name);
|
||||
var ext = extname(name);
|
||||
if (!ext) {
|
||||
includePath += '.ejs';
|
||||
}
|
||||
return includePath;
|
||||
};
|
||||
/**
|
||||
* Try to resolve file path on multiple directories
|
||||
*
|
||||
* @param {String} name specified path
|
||||
* @param {Array<String>} paths list of possible parent directory paths
|
||||
* @return {String}
|
||||
*/
|
||||
function resolvePaths(name, paths) {
|
||||
var filePath;
|
||||
if (paths.some(function (v) {
|
||||
filePath = ejs.resolveInclude(name, v, true);
|
||||
return fs_1.default.existsSync(filePath);
|
||||
})) {
|
||||
return filePath;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get the path to the included file by Options
|
||||
*
|
||||
* @param {String} path specified path
|
||||
* @param {Options} options compilation options
|
||||
* @return {String}
|
||||
*/
|
||||
function getIncludePath(path, options) {
|
||||
var includePath;
|
||||
var filePath;
|
||||
var views = options.views;
|
||||
var match = /^[A-Za-z]+:\\|^\//.exec(path);
|
||||
// Abs path
|
||||
if (match && match.length) {
|
||||
path = path.replace(/^\/*/, '');
|
||||
if (Array.isArray(options.root)) {
|
||||
includePath = resolvePaths(path, options.root);
|
||||
}
|
||||
else {
|
||||
includePath = ejs.resolveInclude(path, options.root || '/', true);
|
||||
}
|
||||
}
|
||||
// Relative paths
|
||||
else {
|
||||
// Look relative to a passed filename first
|
||||
if (options.filename) {
|
||||
filePath = ejs.resolveInclude(path, options.filename);
|
||||
if (fs_1.default.existsSync(filePath)) {
|
||||
includePath = filePath;
|
||||
}
|
||||
}
|
||||
// Then look in any views directories
|
||||
if (!includePath && Array.isArray(views)) {
|
||||
includePath = resolvePaths(path, views);
|
||||
}
|
||||
if (!includePath && typeof options.includer !== 'function') {
|
||||
throw new Error('Could not find the include file "' +
|
||||
options.escapeFunction(path) + '"');
|
||||
}
|
||||
}
|
||||
return includePath;
|
||||
}
|
||||
/**
|
||||
* Get the template from a string or a file, either compiled on-the-fly or
|
||||
* read from cache (if enabled), and cache the template if needed.
|
||||
*
|
||||
* If `template` is not set, the file specified in `options.filename` will be
|
||||
* read.
|
||||
*
|
||||
* If `options.cache` is true, this function reads the file from
|
||||
* `options.filename` so it must be set prior to calling this function.
|
||||
*
|
||||
* @memberof module:ejs-internal
|
||||
* @param {Options} options compilation options
|
||||
* @param {String} [template] template source
|
||||
* @return {TemplateFunction}
|
||||
* @static
|
||||
*/
|
||||
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 = ejs.cache.get(filename);
|
||||
if (func) {
|
||||
return func;
|
||||
}
|
||||
if (!hasTemplate) {
|
||||
template = fileLoader(filename).toString().replace(_BOM, '');
|
||||
}
|
||||
}
|
||||
else if (!hasTemplate) {
|
||||
// istanbul ignore if: should not happen at all
|
||||
if (!filename) {
|
||||
throw new Error('Internal EJS error: no file name or template '
|
||||
+ 'provided');
|
||||
}
|
||||
template = fileLoader(filename).toString().replace(_BOM, '');
|
||||
}
|
||||
func = ejs.compile(template, options);
|
||||
if (options.cache) {
|
||||
ejs.cache.set(filename, func);
|
||||
}
|
||||
return func;
|
||||
}
|
||||
/**
|
||||
* Try calling handleCache with the given options and data and call the
|
||||
* callback with the result. If an error occurs, call the callback with
|
||||
* the error. Used by renderFile().
|
||||
*
|
||||
* @memberof module:ejs-internal
|
||||
* @param {Options} options compilation options
|
||||
* @param {Object} data template data
|
||||
* @param {RenderFileCallback} cb callback
|
||||
* @static
|
||||
*/
|
||||
function tryHandleCache(options, data, cb) {
|
||||
var result;
|
||||
if (!cb) {
|
||||
if (typeof ejs.promiseImpl == 'function') {
|
||||
return new ejs.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);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* fileLoader is independent
|
||||
*
|
||||
* @param {String} filePath ejs file path.
|
||||
* @return {String} The contents of the specified file.
|
||||
* @static
|
||||
*/
|
||||
function fileLoader(filePath) {
|
||||
return ejs.fileLoader(filePath);
|
||||
}
|
||||
/**
|
||||
* Get the template function.
|
||||
*
|
||||
* If `options.cache` is `true`, then the template is cached.
|
||||
*
|
||||
* @memberof module:ejs-internal
|
||||
* @param {String} path path for the specified file
|
||||
* @param {Options} options compilation options
|
||||
* @return {TemplateFunction}
|
||||
* @static
|
||||
*/
|
||||
function includeFile(path, options) {
|
||||
var opts = utils_js_1.default.shallowCopy(utils_js_1.default.createNullProtoObjWherePossible(), options);
|
||||
opts.filename = getIncludePath(path, opts);
|
||||
if (typeof options.includer === 'function') {
|
||||
var includerResult = options.includer(path, opts.filename);
|
||||
if (includerResult) {
|
||||
if (includerResult.filename) {
|
||||
opts.filename = includerResult.filename;
|
||||
}
|
||||
if (includerResult.template) {
|
||||
return handleCache(opts, includerResult.template);
|
||||
}
|
||||
}
|
||||
}
|
||||
return handleCache(opts);
|
||||
}
|
||||
/**
|
||||
* Re-throw the given `err` in context to the `str` of ejs, `filename`, and
|
||||
* `lineno`.
|
||||
*
|
||||
* @implements {RethrowCallback}
|
||||
* @memberof module:ejs-internal
|
||||
* @param {Error} err Error object
|
||||
* @param {String} str EJS source
|
||||
* @param {String} flnm file name of the EJS file
|
||||
* @param {Number} lineno line number of the error
|
||||
* @param {EscapeCallback} esc
|
||||
* @static
|
||||
*/
|
||||
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);
|
||||
// Error context
|
||||
var context = lines.slice(start, end).map(function (line, i) {
|
||||
var curr = i + start + 1;
|
||||
return (curr == lineno ? ' >> ' : ' ')
|
||||
+ curr
|
||||
+ '| '
|
||||
+ line;
|
||||
}).join('\n');
|
||||
// Alter exception message
|
||||
err.path = filename;
|
||||
err.message = (filename || 'ejs') + ':'
|
||||
+ lineno + '\n'
|
||||
+ context + '\n\n'
|
||||
+ err.message;
|
||||
throw err;
|
||||
}
|
||||
function stripSemi(str) {
|
||||
return str.replace(/;(\s*$)/, '$1');
|
||||
}
|
||||
/**
|
||||
* Compile the given `str` of ejs into a template function.
|
||||
*
|
||||
* @param {String} template EJS template
|
||||
*
|
||||
* @param {Options} [opts] compilation options
|
||||
*
|
||||
* @return {TemplateFunction}
|
||||
* Note that the return type of the function depends on the value of `opts.async`.
|
||||
* @public
|
||||
*/
|
||||
ejs.compile = function compile(template, opts) {
|
||||
var templ;
|
||||
// v1 compat
|
||||
// 'scope' is 'context'
|
||||
// FIXME: Remove this in a future version
|
||||
if (opts && opts.scope) {
|
||||
console.warn('`scope` option is deprecated and will be removed in future EJS');
|
||||
if (!opts.context) {
|
||||
opts.context = opts.scope;
|
||||
}
|
||||
delete opts.scope;
|
||||
}
|
||||
templ = new Template(template, opts);
|
||||
return templ.compile();
|
||||
};
|
||||
/**
|
||||
* Render the given `template` of ejs.
|
||||
*
|
||||
* If you would like to include options but not data, you need to explicitly
|
||||
* call this function with `data` being an empty object or `null`.
|
||||
*
|
||||
* @param {String} template EJS template
|
||||
* @param {Object} [data={}] template data
|
||||
* @param {Options} [opts={}] compilation and rendering options
|
||||
* @return {(String|Promise<String>)}
|
||||
* Return value type depends on `opts.async`.
|
||||
* @public
|
||||
*/
|
||||
ejs.render = function (template, d, o) {
|
||||
var data = d || utils_js_1.default.createNullProtoObjWherePossible();
|
||||
var opts = o || utils_js_1.default.createNullProtoObjWherePossible();
|
||||
// No options object -- if there are optiony names
|
||||
// in the data, copy them to options
|
||||
if (arguments.length == 2) {
|
||||
utils_js_1.default.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA);
|
||||
}
|
||||
return handleCache(opts, template)(data);
|
||||
};
|
||||
/**
|
||||
* Render an EJS file at the given `path` and callback `cb(err, str)`.
|
||||
*
|
||||
* If you would like to include options but not data, you need to explicitly
|
||||
* call this function with `data` being an empty object or `null`.
|
||||
*
|
||||
* @param {String} path path to the EJS file
|
||||
* @param {Object} [data={}] template data
|
||||
* @param {Options} [opts={}] compilation and rendering options
|
||||
* @param {RenderFileCallback} cb callback
|
||||
* @public
|
||||
*/
|
||||
ejs.renderFile = function () {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var filename = args.shift();
|
||||
var cb;
|
||||
var opts = { filename: filename };
|
||||
var data;
|
||||
var viewOpts;
|
||||
// Do we have a callback?
|
||||
if (typeof arguments[arguments.length - 1] == 'function') {
|
||||
cb = args.pop();
|
||||
}
|
||||
// Do we have data/opts?
|
||||
if (args.length) {
|
||||
// Should always have data obj
|
||||
data = args.shift();
|
||||
// Normal passed opts (data obj + opts obj)
|
||||
if (args.length) {
|
||||
// Use shallowCopy so we don't pollute passed in opts obj with new vals
|
||||
utils_js_1.default.shallowCopy(opts, args.pop());
|
||||
}
|
||||
// Special casing for Express (settings + opts-in-data)
|
||||
else {
|
||||
// Express 3 and 4
|
||||
if (utils_js_1.default.hasOwn(data, 'settings') && data.settings) {
|
||||
// Pull a few things from known locations
|
||||
if (data.settings.views) {
|
||||
opts.views = data.settings.views;
|
||||
}
|
||||
if (data.settings['view cache']) {
|
||||
opts.cache = true;
|
||||
}
|
||||
// Undocumented after Express 2, but still usable, esp. for
|
||||
// items that are unsafe to be passed along with data, like `root`
|
||||
viewOpts = data.settings['view options'];
|
||||
if (viewOpts) {
|
||||
utils_js_1.default.shallowCopy(opts, viewOpts);
|
||||
}
|
||||
}
|
||||
// Express 2 and lower, values set in app.locals, or people who just
|
||||
// want to pass options in their data. NOTE: These values will override
|
||||
// anything previously set in settings or settings['view options']
|
||||
utils_js_1.default.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA_EXPRESS);
|
||||
}
|
||||
opts.filename = filename;
|
||||
}
|
||||
else {
|
||||
data = utils_js_1.default.createNullProtoObjWherePossible();
|
||||
}
|
||||
return tryHandleCache(opts, data, cb);
|
||||
};
|
||||
/**
|
||||
* Clear intermediate JavaScript cache. Calls {@link Cache#reset}.
|
||||
* @public
|
||||
*/
|
||||
/**
|
||||
* EJS template class
|
||||
* @public
|
||||
*/
|
||||
ejs.Template = Template;
|
||||
ejs.clearCache = function () {
|
||||
ejs.cache.reset();
|
||||
};
|
||||
function Template(text, optsParam) {
|
||||
var opts = utils_js_1.default.hasOwnOnlyObject(optsParam);
|
||||
var options = utils_js_1.default.createNullProtoObjWherePossible();
|
||||
this.templateText = text;
|
||||
/** @type {string | null} */
|
||||
this.mode = null;
|
||||
this.truncate = false;
|
||||
this.currentLine = 1;
|
||||
this.source = '';
|
||||
options.escapeFunction = opts.escape || opts.escapeFunction || utils_js_1.default.escapeXML;
|
||||
options.compileDebug = opts.compileDebug !== false;
|
||||
options.debug = !!opts.debug;
|
||||
options.filename = opts.filename;
|
||||
options.openDelimiter = opts.openDelimiter || ejs.openDelimiter || _DEFAULT_OPEN_DELIMITER;
|
||||
options.closeDelimiter = opts.closeDelimiter || ejs.closeDelimiter || _DEFAULT_CLOSE_DELIMITER;
|
||||
options.delimiter = opts.delimiter || ejs.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.includer = opts.includer;
|
||||
options.outputFunctionName = opts.outputFunctionName;
|
||||
options.localsName = opts.localsName || ejs.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_js_1.default.escapeRegExpChars(this.opts.delimiter);
|
||||
var open = utils_js_1.default.escapeRegExpChars(this.opts.openDelimiter);
|
||||
var close = utils_js_1.default.escapeRegExpChars(this.opts.closeDelimiter);
|
||||
str = str.replace(/%/g, delim)
|
||||
.replace(/</g, open)
|
||||
.replace(/>/g, close);
|
||||
return new RegExp(str);
|
||||
},
|
||||
compile: function () {
|
||||
/** @type {string} */
|
||||
var src;
|
||||
var fn;
|
||||
var opts = this.opts;
|
||||
var prepended = '';
|
||||
var appended = '';
|
||||
/** @type {EscapeCallback} */
|
||||
var escapeFn = opts.escapeFunction;
|
||||
/** @type {FunctionConstructor} */
|
||||
var ctor;
|
||||
/** @type {string} */
|
||||
var sanitizedFilename = opts.filename ? JSON.stringify(opts.filename) : 'undefined';
|
||||
if (!this.source) {
|
||||
this.generateSource();
|
||||
prepended +=
|
||||
" ".concat(DECLARATION_KEYWORD, " __output = \"\";\n") +
|
||||
' function __append(s) { if (s !== undefined && s !== null) __output += s }\n';
|
||||
if (opts.outputFunctionName) {
|
||||
if (!_JS_IDENTIFIER.test(opts.outputFunctionName)) {
|
||||
throw new Error('outputFunctionName is not a valid JS identifier.');
|
||||
}
|
||||
prepended += " ".concat(DECLARATION_KEYWORD, " ") + opts.outputFunctionName + ' = __append;' + '\n';
|
||||
}
|
||||
if (opts.localsName && !_JS_IDENTIFIER.test(opts.localsName)) {
|
||||
throw new Error('localsName is not a valid JS identifier.');
|
||||
}
|
||||
if (opts.destructuredLocals && opts.destructuredLocals.length) {
|
||||
var destructuring = " ".concat(DECLARATION_KEYWORD, " __locals = (") + opts.localsName + ' || {}),\n';
|
||||
for (var i = 0; i < opts.destructuredLocals.length; i++) {
|
||||
var name_1 = opts.destructuredLocals[i];
|
||||
if (!_JS_IDENTIFIER.test(name_1)) {
|
||||
throw new Error('destructuredLocals[' + i + '] is not a valid JS identifier.');
|
||||
}
|
||||
if (i > 0) {
|
||||
destructuring += ',\n ';
|
||||
}
|
||||
destructuring += name_1 + ' = __locals.' + name_1;
|
||||
}
|
||||
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 = "".concat(DECLARATION_KEYWORD, " __line = 1") + '\n'
|
||||
+ ' , __lines = ' + JSON.stringify(this.templateText) + '\n'
|
||||
+ ' , __filename = ' + sanitizedFilename + ';' + '\n'
|
||||
+ 'try {' + '\n'
|
||||
+ this.source
|
||||
+ '} catch (e) {' + '\n'
|
||||
+ ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\n'
|
||||
+ '}' + '\n';
|
||||
}
|
||||
else {
|
||||
src = this.source;
|
||||
}
|
||||
if (opts.strict) {
|
||||
src = '"use strict";\n' + src;
|
||||
}
|
||||
if (opts.debug) {
|
||||
console.log(src);
|
||||
}
|
||||
if (opts.compileDebug && opts.filename) {
|
||||
src = src + '\n'
|
||||
+ '//# sourceURL=' + sanitizedFilename + '\n';
|
||||
}
|
||||
try {
|
||||
if (opts.async) {
|
||||
// Have to use generated function for this, since in envs without support,
|
||||
// it breaks in parsing
|
||||
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) {
|
||||
// istanbul ignore else
|
||||
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;
|
||||
}
|
||||
// Return a callable function which will execute the function
|
||||
// created by the source-code, with the passed data as locals
|
||||
// Adds a local `include` function which allows full recursive include
|
||||
var returnedFn = function anonymous(data) {
|
||||
var include = function (path, includeData) {
|
||||
var d = utils_js_1.default.shallowCopy(utils_js_1.default.createNullProtoObjWherePossible(), data);
|
||||
if (includeData) {
|
||||
d = utils_js_1.default.shallowCopy(d, includeData);
|
||||
}
|
||||
return includeFile(path, opts)(d);
|
||||
};
|
||||
return fn.apply(opts.context, [data || utils_js_1.default.createNullProtoObjWherePossible(), escapeFn, include, rethrow]);
|
||||
};
|
||||
if (opts.filename && typeof Object.defineProperty === 'function') {
|
||||
var filename = opts.filename;
|
||||
var basename = path_1.default.basename(filename, path_1.default.extname(filename));
|
||||
try {
|
||||
Object.defineProperty(returnedFn, 'name', {
|
||||
value: basename,
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
catch (e) { /* ignore */ }
|
||||
}
|
||||
return returnedFn;
|
||||
},
|
||||
generateSource: function () {
|
||||
var opts = this.opts;
|
||||
if (opts.rmWhitespace) {
|
||||
// Have to use two separate replace here as `^` and `$` operators don't
|
||||
// work well with `\r` and empty lines don't work well with the `m` flag.
|
||||
this.templateText =
|
||||
this.templateText.replace(/[\r\n]+/g, '\n').replace(/^\s+|\s+$/gm, '');
|
||||
}
|
||||
var self = this;
|
||||
var d = this.opts.delimiter;
|
||||
var o = this.opts.openDelimiter;
|
||||
var c = this.opts.closeDelimiter;
|
||||
// Slurp spaces and tabs before opening whitespace slurp tag and after closing whitespace slurp tag
|
||||
// Build the tags using custom delimiters: openDelimiter + delimiter + '_' and '_' + delimiter + closeDelimiter
|
||||
var openWhitespaceSlurpTag = utils_js_1.default.escapeRegExpChars(o + d + '_');
|
||||
var closeWhitespaceSlurpTag = utils_js_1.default.escapeRegExpChars('_' + d + c);
|
||||
var openWhitespaceSlurpReplacement = o + d + '_';
|
||||
var closeWhitespaceSlurpReplacement = '_' + d + c;
|
||||
this.templateText =
|
||||
this.templateText.replace(new RegExp('[ \\t]*' + openWhitespaceSlurpTag, 'gm'), openWhitespaceSlurpReplacement)
|
||||
.replace(new RegExp(closeWhitespaceSlurpTag + '[ \\t]*', 'gm'), closeWhitespaceSlurpReplacement);
|
||||
var matches = this.parseTemplateText();
|
||||
if (matches && matches.length) {
|
||||
matches.forEach(function (line, index) {
|
||||
var closing;
|
||||
// If this is an opening tag, check for closing tags
|
||||
// FIXME: May end up with some false positives here
|
||||
// Better to store modes as k/v with openDelimiter + delimiter as key
|
||||
// Then this can simply check against the map
|
||||
if (line.indexOf(o + d) === 0 // If it is a tag
|
||||
&& line.indexOf(o + d + d) !== 0) { // and is not escaped
|
||||
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) {
|
||||
// Only replace single leading linebreak in the line after
|
||||
// -%> tag -- this is the single, trailing linebreak
|
||||
// after the tag that the truncation mode replaces
|
||||
// Handle Win / Unix / old Mac linebreaks -- do the \r\n
|
||||
// combo first in the regex-or
|
||||
line = line.replace(/^(?:\r\n|\r|\n)/, '');
|
||||
this.truncate = false;
|
||||
}
|
||||
if (!line) {
|
||||
return line;
|
||||
}
|
||||
// Preserve literal slashes
|
||||
line = line.replace(/\\/g, '\\\\');
|
||||
// Convert linebreaks
|
||||
line = line.replace(/\n/g, '\\n');
|
||||
line = line.replace(/\r/g, '\\r');
|
||||
// Escape double-quotes
|
||||
// - this will be the delimiter during execution
|
||||
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:
|
||||
// In script mode, depends on type of tag
|
||||
if (this.mode) {
|
||||
// If '//' is found without a line break, add a line break.
|
||||
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) {
|
||||
// Just executing code
|
||||
case Template.modes.EVAL:
|
||||
this.source += ' ; ' + line + '\n';
|
||||
break;
|
||||
// Exec, esc, and output
|
||||
case Template.modes.ESCAPED:
|
||||
this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\n';
|
||||
break;
|
||||
// Exec and output
|
||||
case Template.modes.RAW:
|
||||
this.source += ' ; __append(' + stripSemi(line) + ')' + '\n';
|
||||
break;
|
||||
case Template.modes.COMMENT:
|
||||
// Do nothing
|
||||
break;
|
||||
// Literal <%% mode, append as raw output
|
||||
case Template.modes.LITERAL:
|
||||
this._addOutput(line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// In string mode, just add the output
|
||||
else {
|
||||
this._addOutput(line);
|
||||
}
|
||||
}
|
||||
if (self.opts.compileDebug && newLineCount) {
|
||||
this.currentLine += newLineCount;
|
||||
this.source += ' ; __line = ' + this.currentLine + '\n';
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Escape characters reserved in XML.
|
||||
*
|
||||
* This is simply an export of {@link module:utils.escapeXML}.
|
||||
*
|
||||
* If `markup` is `undefined` or `null`, the empty string is returned.
|
||||
*
|
||||
* @param {String} markup Input string
|
||||
* @return {String} Escaped string
|
||||
* @public
|
||||
* @func
|
||||
* */
|
||||
ejs.escapeXML = utils_js_1.default.escapeXML;
|
||||
/**
|
||||
* Express.js support.
|
||||
*
|
||||
* This is an alias for {@link module:ejs.renderFile}, in order to support
|
||||
* Express.js out-of-the-box.
|
||||
*
|
||||
* @func
|
||||
*/
|
||||
ejs.__express = ejs.renderFile;
|
||||
/* istanbul ignore if */
|
||||
if (typeof window != 'undefined') {
|
||||
window.ejs = ejs;
|
||||
}
|
||||
if (typeof module != 'undefined') {
|
||||
module.exports = ejs;
|
||||
}
|
||||
exports.default = ejs;
|
||||
1
website/node_modules/ejs/lib/cjs/package.json
generated
vendored
Normal file
1
website/node_modules/ejs/lib/cjs/package.json
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"type":"commonjs"}
|
||||
125
website/node_modules/ejs/lib/cjs/parseargs.js
generated
vendored
Normal file
125
website/node_modules/ejs/lib/cjs/parseargs.js
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* EJS Embedded JavaScript templates
|
||||
* Copyright 2112 Matthew Eernisse (mde@fleegix.org)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var parseargs = {};
|
||||
var isOpt = function (arg) { return arg.indexOf('-') === 0; };
|
||||
var removeOptPrefix = function (opt) { return opt.replace(/^--/, '').replace(/^-/, ''); };
|
||||
/**
|
||||
* @constructor
|
||||
* Parses a list of command-line args into a key/value object of
|
||||
* options and an array of positional commands.
|
||||
* @param {Array} opts A list of options in the following format:
|
||||
* [{full: 'foo', abbr: 'f'}, {full: 'bar', abbr: 'b'}]]
|
||||
*/
|
||||
parseargs.Parser = function (opts) {
|
||||
// A key/value object of matching options parsed out of the args
|
||||
this.opts = {};
|
||||
this.taskNames = null;
|
||||
this.envVars = null;
|
||||
// Data structures used for parsing
|
||||
this.reg = opts;
|
||||
this.shortOpts = {};
|
||||
this.longOpts = {};
|
||||
var self = this;
|
||||
[].forEach.call(opts, function (item) {
|
||||
self.shortOpts[item.abbr] = item;
|
||||
self.longOpts[item.full] = item;
|
||||
});
|
||||
};
|
||||
parseargs.Parser.prototype = new function () {
|
||||
var _trueOrNextVal = function (argParts, args) {
|
||||
if (argParts[1]) {
|
||||
return argParts[1];
|
||||
}
|
||||
else {
|
||||
return (!args[0] || isOpt(args[0])) ?
|
||||
true : args.shift();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Parses an array of arguments into options and positional commands
|
||||
* @param {Array} args The command-line args to parse
|
||||
*/
|
||||
this.parse = function (args) {
|
||||
var cmds = [];
|
||||
var cmd;
|
||||
var envVars = {};
|
||||
var opts = {};
|
||||
var arg;
|
||||
var argItem;
|
||||
var argParts;
|
||||
var cmdItems;
|
||||
var taskNames = [];
|
||||
var preempt;
|
||||
while (args.length) {
|
||||
arg = args.shift();
|
||||
if (isOpt(arg)) {
|
||||
arg = removeOptPrefix(arg);
|
||||
argParts = arg.split('=');
|
||||
argItem = this.longOpts[argParts[0]] || this.shortOpts[argParts[0]];
|
||||
if (argItem) {
|
||||
// First-encountered preemptive opt takes precedence -- no further opts
|
||||
// or possibility of ambiguity, so just look for a value, or set to
|
||||
// true and then bail
|
||||
if (argItem.preempts) {
|
||||
opts[argItem.full] = _trueOrNextVal(argParts, args);
|
||||
preempt = true;
|
||||
break;
|
||||
}
|
||||
// If the opt requires a value, see if we can get a value from the
|
||||
// next arg, or infer true from no-arg -- if it's followed by another
|
||||
// opt, throw an error
|
||||
if (argItem.expectValue || argItem.allowValue) {
|
||||
opts[argItem.full] = _trueOrNextVal(argParts, args);
|
||||
if (argItem.expectValue && !opts[argItem.full]) {
|
||||
throw new Error(argItem.full + ' option expects a value.');
|
||||
}
|
||||
}
|
||||
else {
|
||||
opts[argItem.full] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
cmds.unshift(arg);
|
||||
}
|
||||
}
|
||||
if (!preempt) {
|
||||
// Parse out any env-vars and task-name
|
||||
while ((cmd = cmds.pop())) {
|
||||
cmdItems = cmd.split('=');
|
||||
if (cmdItems.length > 1) {
|
||||
envVars[cmdItems[0]] = cmdItems[1];
|
||||
}
|
||||
else {
|
||||
taskNames.push(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
opts: opts,
|
||||
envVars: envVars,
|
||||
taskNames: taskNames
|
||||
};
|
||||
};
|
||||
};
|
||||
if (typeof exports != 'undefined') {
|
||||
module.exports = parseargs;
|
||||
}
|
||||
exports.default = parseargs;
|
||||
245
website/node_modules/ejs/lib/cjs/utils.js
generated
vendored
Normal file
245
website/node_modules/ejs/lib/cjs/utils.js
generated
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* EJS Embedded JavaScript templates
|
||||
* Copyright 2112 Matthew Eernisse (mde@fleegix.org)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* Private utility functions
|
||||
* @module utils
|
||||
* @private
|
||||
*/
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var utils = {};
|
||||
var regExpChars = /[|\\{}()[\]^$+*?.]/g;
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
var hasOwn = function (obj, key) { return hasOwnProperty.apply(obj, [key]); };
|
||||
utils.hasOwn = hasOwn;
|
||||
/**
|
||||
* Escape characters reserved in regular expressions.
|
||||
*
|
||||
* If `string` is `undefined` or `null`, the empty string is returned.
|
||||
*
|
||||
* @param {String} string Input string
|
||||
* @return {String} Escaped string
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
utils.escapeRegExpChars = function (string) {
|
||||
// istanbul ignore if
|
||||
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;
|
||||
}
|
||||
/**
|
||||
* Stringified version of constants used by {@link module:utils.escapeXML}.
|
||||
*
|
||||
* @readonly
|
||||
* @type {String}
|
||||
*/
|
||||
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';
|
||||
/**
|
||||
* Escape characters reserved in XML.
|
||||
*
|
||||
* If `markup` is `undefined` or `null`, the empty string is returned.
|
||||
*
|
||||
* @implements {EscapeCallback}
|
||||
* @param {String} markup Input string
|
||||
* @return {String} Escaped string
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
utils.escapeXML = function (markup) {
|
||||
return markup == undefined
|
||||
? ''
|
||||
: String(markup)
|
||||
.replace(_MATCH_HTML, encode_char);
|
||||
};
|
||||
function escapeXMLToString() {
|
||||
return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr;
|
||||
}
|
||||
try {
|
||||
if (typeof Object.defineProperty === 'function') {
|
||||
// If the Function prototype is frozen, the "toString" property is non-writable. This means that any objects which inherit this property
|
||||
// cannot have the property changed using an assignment. If using strict mode, attempting that will cause an error. If not using strict
|
||||
// mode, attempting that will be silently ignored.
|
||||
// However, we can still explicitly shadow the prototype's "toString" property by defining a new "toString" property on this object.
|
||||
Object.defineProperty(utils.escapeXML, 'toString', { value: escapeXMLToString });
|
||||
}
|
||||
else {
|
||||
// If Object.defineProperty() doesn't exist, attempt to shadow this property using the assignment operator.
|
||||
utils.escapeXML.toString = escapeXMLToString;
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
console.warn('Unable to set escapeXML.toString (is the Function prototype frozen?)');
|
||||
}
|
||||
/**
|
||||
* Naive copy of properties from one object to another.
|
||||
* Does not recurse into non-scalar properties
|
||||
* Does not check to see if the property has a value before copying
|
||||
*
|
||||
* @param {Object} to Destination object
|
||||
* @param {Object} from Source object
|
||||
* @return {Object} Destination object
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
utils.shallowCopy = function (to, from) {
|
||||
from = from || {};
|
||||
if ((to !== null) && (to !== undefined)) {
|
||||
for (var p in from) {
|
||||
if (!hasOwn(from, p)) {
|
||||
continue;
|
||||
}
|
||||
if (p === '__proto__' || p === 'constructor') {
|
||||
continue;
|
||||
}
|
||||
to[p] = from[p];
|
||||
}
|
||||
}
|
||||
return to;
|
||||
};
|
||||
/**
|
||||
* Naive copy of a list of key names, from one object to another.
|
||||
* Only copies property if it is actually defined
|
||||
* Does not recurse into non-scalar properties
|
||||
*
|
||||
* @param {Object} to Destination object
|
||||
* @param {Object} from Source object
|
||||
* @param {Array} list List of properties to copy
|
||||
* @return {Object} Destination object
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
utils.shallowCopyFromList = function (to, from, list) {
|
||||
list = list || [];
|
||||
from = from || {};
|
||||
if ((to !== null) && (to !== undefined)) {
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var p = list[i];
|
||||
if (typeof from[p] != 'undefined') {
|
||||
if (!hasOwn(from, p)) {
|
||||
continue;
|
||||
}
|
||||
if (p === '__proto__' || p === 'constructor') {
|
||||
continue;
|
||||
}
|
||||
to[p] = from[p];
|
||||
}
|
||||
}
|
||||
}
|
||||
return to;
|
||||
};
|
||||
/**
|
||||
* Simple in-process cache implementation. Does not implement limits of any
|
||||
* sort.
|
||||
*
|
||||
* @implements {Cache}
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
utils.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 = {};
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Transforms hyphen case variable into camel case.
|
||||
*
|
||||
* @param {String} string Hyphen case string
|
||||
* @return {String} Camel case string
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
utils.hyphenToCamel = function (str) {
|
||||
return str.replace(/-[a-z]/g, function (match) { return match[1].toUpperCase(); });
|
||||
};
|
||||
/**
|
||||
* Returns a null-prototype object in runtimes that support it
|
||||
*
|
||||
* @return {Object} Object, prototype will be set to null where possible
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
utils.createNullProtoObjWherePossible = (function () {
|
||||
if (typeof Object.create == 'function') {
|
||||
return function () {
|
||||
return Object.create(null);
|
||||
};
|
||||
}
|
||||
if (!({ __proto__: null } instanceof Object)) {
|
||||
return function () {
|
||||
return { __proto__: null };
|
||||
};
|
||||
}
|
||||
// Not possible, just pass through
|
||||
return function () {
|
||||
return {};
|
||||
};
|
||||
})();
|
||||
/**
|
||||
* Copies own-properties from one object to a null-prototype object for basic
|
||||
* protection against prototype pollution
|
||||
*
|
||||
* @return {Object} Object with own-properties of input object
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
utils.hasOwnOnlyObject = function (obj) {
|
||||
var o = utils.createNullProtoObjWherePossible();
|
||||
for (var p in obj) {
|
||||
if (hasOwn(obj, p)) {
|
||||
o[p] = obj[p];
|
||||
}
|
||||
}
|
||||
return o;
|
||||
};
|
||||
if (typeof exports != 'undefined') {
|
||||
module.exports = utils;
|
||||
}
|
||||
exports.default = utils;
|
||||
928
website/node_modules/ejs/lib/esm/ejs.js
generated
vendored
Normal file
928
website/node_modules/ejs/lib/esm/ejs.js
generated
vendored
Normal file
@@ -0,0 +1,928 @@
|
||||
/*
|
||||
* EJS Embedded JavaScript templates
|
||||
* Copyright 2112 Matthew Eernisse (mde@fleegix.org)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import utils from './utils.js';
|
||||
|
||||
/**
|
||||
* @file Embedded JavaScript templating engine. {@link http://ejs.co}
|
||||
* @author Matthew Eernisse <mde@fleegix.org>
|
||||
* @project EJS
|
||||
* @license {@link http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0}
|
||||
*/
|
||||
|
||||
/**
|
||||
* EJS internal functions.
|
||||
*
|
||||
* Technically this "module" lies in the same file as {@link module:ejs}, for
|
||||
* the sake of organization all the private functions re grouped into this
|
||||
* module.
|
||||
*
|
||||
* @module ejs-internal
|
||||
* @private
|
||||
*/
|
||||
|
||||
/**
|
||||
* Embedded JavaScript templating engine.
|
||||
*
|
||||
* @module ejs
|
||||
* @public
|
||||
*/
|
||||
|
||||
// Keyword used in code generation -- updated to 'var' in CJS build
|
||||
const DECLARATION_KEYWORD = 'let';
|
||||
|
||||
const ejs = {};
|
||||
|
||||
/** @type {string} */
|
||||
let _DEFAULT_OPEN_DELIMITER = '<';
|
||||
let _DEFAULT_CLOSE_DELIMITER = '>';
|
||||
let _DEFAULT_DELIMITER = '%';
|
||||
let _DEFAULT_LOCALS_NAME = 'locals';
|
||||
let _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)';
|
||||
let _OPTS_PASSABLE_WITH_DATA = ['delimiter', 'scope', 'context', 'debug', 'compileDebug',
|
||||
'_with', 'rmWhitespace', 'strict', 'filename', 'async'];
|
||||
// We don't allow 'cache' option to be passed in the data obj for
|
||||
// the normal `render` call, but this is where Express 2 & 3 put it
|
||||
// so we make an exception for `renderFile`
|
||||
let _OPTS_PASSABLE_WITH_DATA_EXPRESS = _OPTS_PASSABLE_WITH_DATA.concat('cache');
|
||||
let _BOM = /^\uFEFF/;
|
||||
let _JS_IDENTIFIER = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;
|
||||
|
||||
/**
|
||||
* EJS template function cache. This can be a LRU object from lru-cache NPM
|
||||
* module. By default, it is {@link module:utils.cache}, a simple in-process
|
||||
* cache that grows continuously.
|
||||
*
|
||||
* @type {Cache}
|
||||
*/
|
||||
|
||||
ejs.cache = utils.cache;
|
||||
|
||||
/**
|
||||
* Custom file loader. Useful for template preprocessing or restricting access
|
||||
* to a certain part of the filesystem.
|
||||
*
|
||||
* @type {fileLoader}
|
||||
*/
|
||||
|
||||
ejs.fileLoader = fs.readFileSync;
|
||||
|
||||
/**
|
||||
* Name of the object containing the locals.
|
||||
*
|
||||
* This variable is overridden by {@link Options}`.localsName` if it is not
|
||||
* `undefined`.
|
||||
*
|
||||
* @type {String}
|
||||
* @public
|
||||
*/
|
||||
|
||||
ejs.localsName = _DEFAULT_LOCALS_NAME;
|
||||
|
||||
/**
|
||||
* Promise implementation -- defaults to the native implementation if available
|
||||
* This is mostly just for testability
|
||||
*
|
||||
* @type {PromiseConstructorLike}
|
||||
* @public
|
||||
*/
|
||||
|
||||
ejs.promiseImpl = (new Function('return this;'))().Promise;
|
||||
|
||||
/**
|
||||
* Get the path to the included file from the parent file path and the
|
||||
* specified path.
|
||||
*
|
||||
* @param {String} name specified path
|
||||
* @param {String} filename parent file path
|
||||
* @param {Boolean} [isDir=false] whether the parent file path is a directory
|
||||
* @return {String}
|
||||
*/
|
||||
ejs.resolveInclude = function(name, filename, isDir) {
|
||||
let dirname = path.dirname;
|
||||
let extname = path.extname;
|
||||
let resolve = path.resolve;
|
||||
let includePath = resolve(isDir ? filename : dirname(filename), name);
|
||||
let ext = extname(name);
|
||||
if (!ext) {
|
||||
includePath += '.ejs';
|
||||
}
|
||||
return includePath;
|
||||
};
|
||||
|
||||
/**
|
||||
* Try to resolve file path on multiple directories
|
||||
*
|
||||
* @param {String} name specified path
|
||||
* @param {Array<String>} paths list of possible parent directory paths
|
||||
* @return {String}
|
||||
*/
|
||||
function resolvePaths(name, paths) {
|
||||
let filePath;
|
||||
if (paths.some(function (v) {
|
||||
filePath = ejs.resolveInclude(name, v, true);
|
||||
return fs.existsSync(filePath);
|
||||
})) {
|
||||
return filePath;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to the included file by Options
|
||||
*
|
||||
* @param {String} path specified path
|
||||
* @param {Options} options compilation options
|
||||
* @return {String}
|
||||
*/
|
||||
function getIncludePath(path, options) {
|
||||
let includePath;
|
||||
let filePath;
|
||||
let views = options.views;
|
||||
let match = /^[A-Za-z]+:\\|^\//.exec(path);
|
||||
|
||||
// Abs path
|
||||
if (match && match.length) {
|
||||
path = path.replace(/^\/*/, '');
|
||||
if (Array.isArray(options.root)) {
|
||||
includePath = resolvePaths(path, options.root);
|
||||
} else {
|
||||
includePath = ejs.resolveInclude(path, options.root || '/', true);
|
||||
}
|
||||
}
|
||||
// Relative paths
|
||||
else {
|
||||
// Look relative to a passed filename first
|
||||
if (options.filename) {
|
||||
filePath = ejs.resolveInclude(path, options.filename);
|
||||
if (fs.existsSync(filePath)) {
|
||||
includePath = filePath;
|
||||
}
|
||||
}
|
||||
// Then look in any views directories
|
||||
if (!includePath && Array.isArray(views)) {
|
||||
includePath = resolvePaths(path, views);
|
||||
}
|
||||
if (!includePath && typeof options.includer !== 'function') {
|
||||
throw new Error('Could not find the include file "' +
|
||||
options.escapeFunction(path) + '"');
|
||||
}
|
||||
}
|
||||
return includePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the template from a string or a file, either compiled on-the-fly or
|
||||
* read from cache (if enabled), and cache the template if needed.
|
||||
*
|
||||
* If `template` is not set, the file specified in `options.filename` will be
|
||||
* read.
|
||||
*
|
||||
* If `options.cache` is true, this function reads the file from
|
||||
* `options.filename` so it must be set prior to calling this function.
|
||||
*
|
||||
* @memberof module:ejs-internal
|
||||
* @param {Options} options compilation options
|
||||
* @param {String} [template] template source
|
||||
* @return {TemplateFunction}
|
||||
* @static
|
||||
*/
|
||||
|
||||
function handleCache(options, template) {
|
||||
let func;
|
||||
let filename = options.filename;
|
||||
let hasTemplate = arguments.length > 1;
|
||||
|
||||
if (options.cache) {
|
||||
if (!filename) {
|
||||
throw new Error('cache option requires a filename');
|
||||
}
|
||||
func = ejs.cache.get(filename);
|
||||
if (func) {
|
||||
return func;
|
||||
}
|
||||
if (!hasTemplate) {
|
||||
template = fileLoader(filename).toString().replace(_BOM, '');
|
||||
}
|
||||
}
|
||||
else if (!hasTemplate) {
|
||||
// istanbul ignore if: should not happen at all
|
||||
if (!filename) {
|
||||
throw new Error('Internal EJS error: no file name or template '
|
||||
+ 'provided');
|
||||
}
|
||||
template = fileLoader(filename).toString().replace(_BOM, '');
|
||||
}
|
||||
func = ejs.compile(template, options);
|
||||
if (options.cache) {
|
||||
ejs.cache.set(filename, func);
|
||||
}
|
||||
return func;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try calling handleCache with the given options and data and call the
|
||||
* callback with the result. If an error occurs, call the callback with
|
||||
* the error. Used by renderFile().
|
||||
*
|
||||
* @memberof module:ejs-internal
|
||||
* @param {Options} options compilation options
|
||||
* @param {Object} data template data
|
||||
* @param {RenderFileCallback} cb callback
|
||||
* @static
|
||||
*/
|
||||
|
||||
function tryHandleCache(options, data, cb) {
|
||||
let result;
|
||||
if (!cb) {
|
||||
if (typeof ejs.promiseImpl == 'function') {
|
||||
return new ejs.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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fileLoader is independent
|
||||
*
|
||||
* @param {String} filePath ejs file path.
|
||||
* @return {String} The contents of the specified file.
|
||||
* @static
|
||||
*/
|
||||
|
||||
function fileLoader(filePath){
|
||||
return ejs.fileLoader(filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the template function.
|
||||
*
|
||||
* If `options.cache` is `true`, then the template is cached.
|
||||
*
|
||||
* @memberof module:ejs-internal
|
||||
* @param {String} path path for the specified file
|
||||
* @param {Options} options compilation options
|
||||
* @return {TemplateFunction}
|
||||
* @static
|
||||
*/
|
||||
|
||||
function includeFile(path, options) {
|
||||
let opts = utils.shallowCopy(utils.createNullProtoObjWherePossible(), options);
|
||||
opts.filename = getIncludePath(path, opts);
|
||||
if (typeof options.includer === 'function') {
|
||||
let includerResult = options.includer(path, opts.filename);
|
||||
if (includerResult) {
|
||||
if (includerResult.filename) {
|
||||
opts.filename = includerResult.filename;
|
||||
}
|
||||
if (includerResult.template) {
|
||||
return handleCache(opts, includerResult.template);
|
||||
}
|
||||
}
|
||||
}
|
||||
return handleCache(opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-throw the given `err` in context to the `str` of ejs, `filename`, and
|
||||
* `lineno`.
|
||||
*
|
||||
* @implements {RethrowCallback}
|
||||
* @memberof module:ejs-internal
|
||||
* @param {Error} err Error object
|
||||
* @param {String} str EJS source
|
||||
* @param {String} flnm file name of the EJS file
|
||||
* @param {Number} lineno line number of the error
|
||||
* @param {EscapeCallback} esc
|
||||
* @static
|
||||
*/
|
||||
|
||||
function rethrow(err, str, flnm, lineno, esc) {
|
||||
let lines = str.split('\n');
|
||||
let start = Math.max(lineno - 3, 0);
|
||||
let end = Math.min(lines.length, lineno + 3);
|
||||
let filename = esc(flnm);
|
||||
// Error context
|
||||
let context = lines.slice(start, end).map(function (line, i){
|
||||
let curr = i + start + 1;
|
||||
return (curr == lineno ? ' >> ' : ' ')
|
||||
+ curr
|
||||
+ '| '
|
||||
+ line;
|
||||
}).join('\n');
|
||||
|
||||
// Alter exception message
|
||||
err.path = filename;
|
||||
err.message = (filename || 'ejs') + ':'
|
||||
+ lineno + '\n'
|
||||
+ context + '\n\n'
|
||||
+ err.message;
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
function stripSemi(str){
|
||||
return str.replace(/;(\s*$)/, '$1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the given `str` of ejs into a template function.
|
||||
*
|
||||
* @param {String} template EJS template
|
||||
*
|
||||
* @param {Options} [opts] compilation options
|
||||
*
|
||||
* @return {TemplateFunction}
|
||||
* Note that the return type of the function depends on the value of `opts.async`.
|
||||
* @public
|
||||
*/
|
||||
|
||||
ejs.compile = function compile(template, opts) {
|
||||
let templ;
|
||||
|
||||
// v1 compat
|
||||
// 'scope' is 'context'
|
||||
// FIXME: Remove this in a future version
|
||||
if (opts && opts.scope) {
|
||||
console.warn('`scope` option is deprecated and will be removed in future EJS');
|
||||
if (!opts.context) {
|
||||
opts.context = opts.scope;
|
||||
}
|
||||
delete opts.scope;
|
||||
}
|
||||
templ = new Template(template, opts);
|
||||
return templ.compile();
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the given `template` of ejs.
|
||||
*
|
||||
* If you would like to include options but not data, you need to explicitly
|
||||
* call this function with `data` being an empty object or `null`.
|
||||
*
|
||||
* @param {String} template EJS template
|
||||
* @param {Object} [data={}] template data
|
||||
* @param {Options} [opts={}] compilation and rendering options
|
||||
* @return {(String|Promise<String>)}
|
||||
* Return value type depends on `opts.async`.
|
||||
* @public
|
||||
*/
|
||||
|
||||
ejs.render = function (template, d, o) {
|
||||
let data = d || utils.createNullProtoObjWherePossible();
|
||||
let opts = o || utils.createNullProtoObjWherePossible();
|
||||
|
||||
// No options object -- if there are optiony names
|
||||
// in the data, copy them to options
|
||||
if (arguments.length == 2) {
|
||||
utils.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA);
|
||||
}
|
||||
|
||||
return handleCache(opts, template)(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Render an EJS file at the given `path` and callback `cb(err, str)`.
|
||||
*
|
||||
* If you would like to include options but not data, you need to explicitly
|
||||
* call this function with `data` being an empty object or `null`.
|
||||
*
|
||||
* @param {String} path path to the EJS file
|
||||
* @param {Object} [data={}] template data
|
||||
* @param {Options} [opts={}] compilation and rendering options
|
||||
* @param {RenderFileCallback} cb callback
|
||||
* @public
|
||||
*/
|
||||
|
||||
ejs.renderFile = function () {
|
||||
let args = Array.prototype.slice.call(arguments);
|
||||
let filename = args.shift();
|
||||
let cb;
|
||||
let opts = {filename: filename};
|
||||
let data;
|
||||
let viewOpts;
|
||||
|
||||
// Do we have a callback?
|
||||
if (typeof arguments[arguments.length - 1] == 'function') {
|
||||
cb = args.pop();
|
||||
}
|
||||
// Do we have data/opts?
|
||||
if (args.length) {
|
||||
// Should always have data obj
|
||||
data = args.shift();
|
||||
// Normal passed opts (data obj + opts obj)
|
||||
if (args.length) {
|
||||
// Use shallowCopy so we don't pollute passed in opts obj with new vals
|
||||
utils.shallowCopy(opts, args.pop());
|
||||
}
|
||||
// Special casing for Express (settings + opts-in-data)
|
||||
else {
|
||||
// Express 3 and 4
|
||||
if (utils.hasOwn(data, 'settings') && data.settings) {
|
||||
// Pull a few things from known locations
|
||||
if (data.settings.views) {
|
||||
opts.views = data.settings.views;
|
||||
}
|
||||
if (data.settings['view cache']) {
|
||||
opts.cache = true;
|
||||
}
|
||||
// Undocumented after Express 2, but still usable, esp. for
|
||||
// items that are unsafe to be passed along with data, like `root`
|
||||
viewOpts = data.settings['view options'];
|
||||
if (viewOpts) {
|
||||
utils.shallowCopy(opts, viewOpts);
|
||||
}
|
||||
}
|
||||
// Express 2 and lower, values set in app.locals, or people who just
|
||||
// want to pass options in their data. NOTE: These values will override
|
||||
// anything previously set in settings or settings['view options']
|
||||
utils.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA_EXPRESS);
|
||||
}
|
||||
opts.filename = filename;
|
||||
}
|
||||
else {
|
||||
data = utils.createNullProtoObjWherePossible();
|
||||
}
|
||||
|
||||
return tryHandleCache(opts, data, cb);
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear intermediate JavaScript cache. Calls {@link Cache#reset}.
|
||||
* @public
|
||||
*/
|
||||
|
||||
/**
|
||||
* EJS template class
|
||||
* @public
|
||||
*/
|
||||
ejs.Template = Template;
|
||||
|
||||
ejs.clearCache = function () {
|
||||
ejs.cache.reset();
|
||||
};
|
||||
|
||||
function Template(text, optsParam) {
|
||||
let opts = utils.hasOwnOnlyObject(optsParam);
|
||||
let options = utils.createNullProtoObjWherePossible();
|
||||
this.templateText = text;
|
||||
/** @type {string | null} */
|
||||
this.mode = null;
|
||||
this.truncate = false;
|
||||
this.currentLine = 1;
|
||||
this.source = '';
|
||||
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 || ejs.openDelimiter || _DEFAULT_OPEN_DELIMITER;
|
||||
options.closeDelimiter = opts.closeDelimiter || ejs.closeDelimiter || _DEFAULT_CLOSE_DELIMITER;
|
||||
options.delimiter = opts.delimiter || ejs.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.includer = opts.includer;
|
||||
options.outputFunctionName = opts.outputFunctionName;
|
||||
options.localsName = opts.localsName || ejs.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 () {
|
||||
let str = _REGEX_STRING;
|
||||
let delim = utils.escapeRegExpChars(this.opts.delimiter);
|
||||
let open = utils.escapeRegExpChars(this.opts.openDelimiter);
|
||||
let close = utils.escapeRegExpChars(this.opts.closeDelimiter);
|
||||
str = str.replace(/%/g, delim)
|
||||
.replace(/</g, open)
|
||||
.replace(/>/g, close);
|
||||
return new RegExp(str);
|
||||
},
|
||||
|
||||
compile: function () {
|
||||
/** @type {string} */
|
||||
let src;
|
||||
let fn;
|
||||
let opts = this.opts;
|
||||
let prepended = '';
|
||||
let appended = '';
|
||||
/** @type {EscapeCallback} */
|
||||
let escapeFn = opts.escapeFunction;
|
||||
/** @type {FunctionConstructor} */
|
||||
let ctor;
|
||||
/** @type {string} */
|
||||
let sanitizedFilename = opts.filename ? JSON.stringify(opts.filename) : 'undefined';
|
||||
|
||||
if (!this.source) {
|
||||
this.generateSource();
|
||||
prepended +=
|
||||
` ${DECLARATION_KEYWORD} __output = "";\n` +
|
||||
' function __append(s) { if (s !== undefined && s !== null) __output += s }\n';
|
||||
if (opts.outputFunctionName) {
|
||||
if (!_JS_IDENTIFIER.test(opts.outputFunctionName)) {
|
||||
throw new Error('outputFunctionName is not a valid JS identifier.');
|
||||
}
|
||||
prepended += ` ${DECLARATION_KEYWORD} ` + opts.outputFunctionName + ' = __append;' + '\n';
|
||||
}
|
||||
if (opts.localsName && !_JS_IDENTIFIER.test(opts.localsName)) {
|
||||
throw new Error('localsName is not a valid JS identifier.');
|
||||
}
|
||||
if (opts.destructuredLocals && opts.destructuredLocals.length) {
|
||||
let destructuring = ` ${DECLARATION_KEYWORD} __locals = (` + opts.localsName + ' || {}),\n';
|
||||
for (let i = 0; i < opts.destructuredLocals.length; i++) {
|
||||
let name = opts.destructuredLocals[i];
|
||||
if (!_JS_IDENTIFIER.test(name)) {
|
||||
throw new Error('destructuredLocals[' + i + '] is not a valid JS identifier.');
|
||||
}
|
||||
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 = `${DECLARATION_KEYWORD} __line = 1` + '\n'
|
||||
+ ' , __lines = ' + JSON.stringify(this.templateText) + '\n'
|
||||
+ ' , __filename = ' + sanitizedFilename + ';' + '\n'
|
||||
+ 'try {' + '\n'
|
||||
+ this.source
|
||||
+ '} catch (e) {' + '\n'
|
||||
+ ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\n'
|
||||
+ '}' + '\n';
|
||||
}
|
||||
else {
|
||||
src = this.source;
|
||||
}
|
||||
|
||||
if (opts.strict) {
|
||||
src = '"use strict";\n' + src;
|
||||
}
|
||||
if (opts.debug) {
|
||||
console.log(src);
|
||||
}
|
||||
if (opts.compileDebug && opts.filename) {
|
||||
src = src + '\n'
|
||||
+ '//# sourceURL=' + sanitizedFilename + '\n';
|
||||
}
|
||||
|
||||
try {
|
||||
if (opts.async) {
|
||||
// Have to use generated function for this, since in envs without support,
|
||||
// it breaks in parsing
|
||||
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) {
|
||||
// istanbul ignore else
|
||||
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;
|
||||
}
|
||||
|
||||
// Return a callable function which will execute the function
|
||||
// created by the source-code, with the passed data as locals
|
||||
// Adds a local `include` function which allows full recursive include
|
||||
let returnedFn = function anonymous(data) {
|
||||
let include = function (path, includeData) {
|
||||
let d = utils.shallowCopy(utils.createNullProtoObjWherePossible(), data);
|
||||
if (includeData) {
|
||||
d = utils.shallowCopy(d, includeData);
|
||||
}
|
||||
return includeFile(path, opts)(d);
|
||||
};
|
||||
return fn.apply(opts.context,
|
||||
[data || utils.createNullProtoObjWherePossible(), escapeFn, include, rethrow]);
|
||||
};
|
||||
if (opts.filename && typeof Object.defineProperty === 'function') {
|
||||
let filename = opts.filename;
|
||||
let basename = path.basename(filename, path.extname(filename));
|
||||
try {
|
||||
Object.defineProperty(returnedFn, 'name', {
|
||||
value: basename,
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
} catch (e) {/* ignore */}
|
||||
}
|
||||
return returnedFn;
|
||||
},
|
||||
|
||||
generateSource: function () {
|
||||
let opts = this.opts;
|
||||
|
||||
if (opts.rmWhitespace) {
|
||||
// Have to use two separate replace here as `^` and `$` operators don't
|
||||
// work well with `\r` and empty lines don't work well with the `m` flag.
|
||||
this.templateText =
|
||||
this.templateText.replace(/[\r\n]+/g, '\n').replace(/^\s+|\s+$/gm, '');
|
||||
}
|
||||
|
||||
let self = this;
|
||||
let d = this.opts.delimiter;
|
||||
let o = this.opts.openDelimiter;
|
||||
let c = this.opts.closeDelimiter;
|
||||
|
||||
// Slurp spaces and tabs before opening whitespace slurp tag and after closing whitespace slurp tag
|
||||
// Build the tags using custom delimiters: openDelimiter + delimiter + '_' and '_' + delimiter + closeDelimiter
|
||||
let openWhitespaceSlurpTag = utils.escapeRegExpChars(o + d + '_');
|
||||
let closeWhitespaceSlurpTag = utils.escapeRegExpChars('_' + d + c);
|
||||
let openWhitespaceSlurpReplacement = o + d + '_';
|
||||
let closeWhitespaceSlurpReplacement = '_' + d + c;
|
||||
this.templateText =
|
||||
this.templateText.replace(new RegExp('[ \\t]*' + openWhitespaceSlurpTag, 'gm'), openWhitespaceSlurpReplacement)
|
||||
.replace(new RegExp(closeWhitespaceSlurpTag + '[ \\t]*', 'gm'), closeWhitespaceSlurpReplacement);
|
||||
|
||||
let matches = this.parseTemplateText();
|
||||
|
||||
if (matches && matches.length) {
|
||||
matches.forEach(function (line, index) {
|
||||
let closing;
|
||||
// If this is an opening tag, check for closing tags
|
||||
// FIXME: May end up with some false positives here
|
||||
// Better to store modes as k/v with openDelimiter + delimiter as key
|
||||
// Then this can simply check against the map
|
||||
if ( line.indexOf(o + d) === 0 // If it is a tag
|
||||
&& line.indexOf(o + d + d) !== 0) { // and is not escaped
|
||||
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 () {
|
||||
let str = this.templateText;
|
||||
let pat = this.regex;
|
||||
let result = pat.exec(str);
|
||||
let arr = [];
|
||||
let 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) {
|
||||
// Only replace single leading linebreak in the line after
|
||||
// -%> tag -- this is the single, trailing linebreak
|
||||
// after the tag that the truncation mode replaces
|
||||
// Handle Win / Unix / old Mac linebreaks -- do the \r\n
|
||||
// combo first in the regex-or
|
||||
line = line.replace(/^(?:\r\n|\r|\n)/, '');
|
||||
this.truncate = false;
|
||||
}
|
||||
if (!line) {
|
||||
return line;
|
||||
}
|
||||
|
||||
// Preserve literal slashes
|
||||
line = line.replace(/\\/g, '\\\\');
|
||||
|
||||
// Convert linebreaks
|
||||
line = line.replace(/\n/g, '\\n');
|
||||
line = line.replace(/\r/g, '\\r');
|
||||
|
||||
// Escape double-quotes
|
||||
// - this will be the delimiter during execution
|
||||
line = line.replace(/"/g, '\\"');
|
||||
this.source += ' ; __append("' + line + '")' + '\n';
|
||||
},
|
||||
|
||||
scanLine: function (line) {
|
||||
let self = this;
|
||||
let d = this.opts.delimiter;
|
||||
let o = this.opts.openDelimiter;
|
||||
let c = this.opts.closeDelimiter;
|
||||
let 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:
|
||||
// In script mode, depends on type of tag
|
||||
if (this.mode) {
|
||||
// If '//' is found without a line break, add a line break.
|
||||
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) {
|
||||
// Just executing code
|
||||
case Template.modes.EVAL:
|
||||
this.source += ' ; ' + line + '\n';
|
||||
break;
|
||||
// Exec, esc, and output
|
||||
case Template.modes.ESCAPED:
|
||||
this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\n';
|
||||
break;
|
||||
// Exec and output
|
||||
case Template.modes.RAW:
|
||||
this.source += ' ; __append(' + stripSemi(line) + ')' + '\n';
|
||||
break;
|
||||
case Template.modes.COMMENT:
|
||||
// Do nothing
|
||||
break;
|
||||
// Literal <%% mode, append as raw output
|
||||
case Template.modes.LITERAL:
|
||||
this._addOutput(line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// In string mode, just add the output
|
||||
else {
|
||||
this._addOutput(line);
|
||||
}
|
||||
}
|
||||
|
||||
if (self.opts.compileDebug && newLineCount) {
|
||||
this.currentLine += newLineCount;
|
||||
this.source += ' ; __line = ' + this.currentLine + '\n';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Escape characters reserved in XML.
|
||||
*
|
||||
* This is simply an export of {@link module:utils.escapeXML}.
|
||||
*
|
||||
* If `markup` is `undefined` or `null`, the empty string is returned.
|
||||
*
|
||||
* @param {String} markup Input string
|
||||
* @return {String} Escaped string
|
||||
* @public
|
||||
* @func
|
||||
* */
|
||||
ejs.escapeXML = utils.escapeXML;
|
||||
|
||||
/**
|
||||
* Express.js support.
|
||||
*
|
||||
* This is an alias for {@link module:ejs.renderFile}, in order to support
|
||||
* Express.js out-of-the-box.
|
||||
*
|
||||
* @func
|
||||
*/
|
||||
|
||||
ejs.__express = ejs.renderFile;
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (typeof window != 'undefined') {
|
||||
window.ejs = ejs;
|
||||
}
|
||||
|
||||
if (typeof module != 'undefined') {
|
||||
module.exports = ejs;
|
||||
}
|
||||
export default ejs;
|
||||
3
website/node_modules/ejs/lib/esm/package.json
generated
vendored
Normal file
3
website/node_modules/ejs/lib/esm/package.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
139
website/node_modules/ejs/lib/esm/parseargs.js
generated
vendored
Normal file
139
website/node_modules/ejs/lib/esm/parseargs.js
generated
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* EJS Embedded JavaScript templates
|
||||
* Copyright 2112 Matthew Eernisse (mde@fleegix.org)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
let parseargs = {};
|
||||
let isOpt = function (arg) { return arg.indexOf('-') === 0; };
|
||||
let removeOptPrefix = function (opt) { return opt.replace(/^--/, '').replace(/^-/, ''); };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* Parses a list of command-line args into a key/value object of
|
||||
* options and an array of positional commands.
|
||||
* @param {Array} opts A list of options in the following format:
|
||||
* [{full: 'foo', abbr: 'f'}, {full: 'bar', abbr: 'b'}]]
|
||||
*/
|
||||
parseargs.Parser = function (opts) {
|
||||
// A key/value object of matching options parsed out of the args
|
||||
this.opts = {};
|
||||
this.taskNames = null;
|
||||
this.envVars = null;
|
||||
|
||||
// Data structures used for parsing
|
||||
this.reg = opts;
|
||||
this.shortOpts = {};
|
||||
this.longOpts = {};
|
||||
|
||||
let self = this;
|
||||
[].forEach.call(opts, function (item) {
|
||||
self.shortOpts[item.abbr] = item;
|
||||
self.longOpts[item.full] = item;
|
||||
});
|
||||
};
|
||||
|
||||
parseargs.Parser.prototype = new function () {
|
||||
|
||||
let _trueOrNextVal = function (argParts, args) {
|
||||
if (argParts[1]) {
|
||||
return argParts[1];
|
||||
}
|
||||
else {
|
||||
return (!args[0] || isOpt(args[0])) ?
|
||||
true : args.shift();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses an array of arguments into options and positional commands
|
||||
* @param {Array} args The command-line args to parse
|
||||
*/
|
||||
this.parse = function (args) {
|
||||
let cmds = [];
|
||||
let cmd;
|
||||
let envVars = {};
|
||||
let opts = {};
|
||||
let arg;
|
||||
let argItem;
|
||||
let argParts;
|
||||
let cmdItems;
|
||||
let taskNames = [];
|
||||
let preempt;
|
||||
|
||||
while (args.length) {
|
||||
arg = args.shift();
|
||||
|
||||
if (isOpt(arg)) {
|
||||
arg = removeOptPrefix(arg);
|
||||
argParts = arg.split('=');
|
||||
argItem = this.longOpts[argParts[0]] || this.shortOpts[argParts[0]];
|
||||
if (argItem) {
|
||||
// First-encountered preemptive opt takes precedence -- no further opts
|
||||
// or possibility of ambiguity, so just look for a value, or set to
|
||||
// true and then bail
|
||||
if (argItem.preempts) {
|
||||
opts[argItem.full] = _trueOrNextVal(argParts, args);
|
||||
preempt = true;
|
||||
break;
|
||||
}
|
||||
// If the opt requires a value, see if we can get a value from the
|
||||
// next arg, or infer true from no-arg -- if it's followed by another
|
||||
// opt, throw an error
|
||||
if (argItem.expectValue || argItem.allowValue) {
|
||||
opts[argItem.full] = _trueOrNextVal(argParts, args);
|
||||
if (argItem.expectValue && !opts[argItem.full]) {
|
||||
throw new Error(argItem.full + ' option expects a value.');
|
||||
}
|
||||
}
|
||||
else {
|
||||
opts[argItem.full] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
cmds.unshift(arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (!preempt) {
|
||||
// Parse out any env-vars and task-name
|
||||
while ((cmd = cmds.pop())) {
|
||||
cmdItems = cmd.split('=');
|
||||
if (cmdItems.length > 1) {
|
||||
envVars[cmdItems[0]] = cmdItems[1];
|
||||
}
|
||||
else {
|
||||
taskNames.push(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
opts: opts,
|
||||
envVars: envVars,
|
||||
taskNames: taskNames
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
if (typeof exports != 'undefined') {
|
||||
module.exports = parseargs;
|
||||
}
|
||||
export default parseargs;
|
||||
262
website/node_modules/ejs/lib/esm/utils.js
generated
vendored
Normal file
262
website/node_modules/ejs/lib/esm/utils.js
generated
vendored
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* EJS Embedded JavaScript templates
|
||||
* Copyright 2112 Matthew Eernisse (mde@fleegix.org)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Private utility functions
|
||||
* @module utils
|
||||
* @private
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const utils = {};
|
||||
var regExpChars = /[|\\{}()[\]^$+*?.]/g;
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
var hasOwn = function (obj, key) { return hasOwnProperty.apply(obj, [key]); };
|
||||
utils.hasOwn = hasOwn;
|
||||
|
||||
/**
|
||||
* Escape characters reserved in regular expressions.
|
||||
*
|
||||
* If `string` is `undefined` or `null`, the empty string is returned.
|
||||
*
|
||||
* @param {String} string Input string
|
||||
* @return {String} Escaped string
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
utils.escapeRegExpChars = function (string) {
|
||||
// istanbul ignore if
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stringified version of constants used by {@link module:utils.escapeXML}.
|
||||
*
|
||||
* @readonly
|
||||
* @type {String}
|
||||
*/
|
||||
|
||||
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';
|
||||
|
||||
/**
|
||||
* Escape characters reserved in XML.
|
||||
*
|
||||
* If `markup` is `undefined` or `null`, the empty string is returned.
|
||||
*
|
||||
* @implements {EscapeCallback}
|
||||
* @param {String} markup Input string
|
||||
* @return {String} Escaped string
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
|
||||
utils.escapeXML = function (markup) {
|
||||
return markup == undefined
|
||||
? ''
|
||||
: String(markup)
|
||||
.replace(_MATCH_HTML, encode_char);
|
||||
};
|
||||
|
||||
function escapeXMLToString() {
|
||||
return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr;
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof Object.defineProperty === 'function') {
|
||||
// If the Function prototype is frozen, the "toString" property is non-writable. This means that any objects which inherit this property
|
||||
// cannot have the property changed using an assignment. If using strict mode, attempting that will cause an error. If not using strict
|
||||
// mode, attempting that will be silently ignored.
|
||||
// However, we can still explicitly shadow the prototype's "toString" property by defining a new "toString" property on this object.
|
||||
Object.defineProperty(utils.escapeXML, 'toString', { value: escapeXMLToString });
|
||||
} else {
|
||||
// If Object.defineProperty() doesn't exist, attempt to shadow this property using the assignment operator.
|
||||
utils.escapeXML.toString = escapeXMLToString;
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('Unable to set escapeXML.toString (is the Function prototype frozen?)');
|
||||
}
|
||||
|
||||
/**
|
||||
* Naive copy of properties from one object to another.
|
||||
* Does not recurse into non-scalar properties
|
||||
* Does not check to see if the property has a value before copying
|
||||
*
|
||||
* @param {Object} to Destination object
|
||||
* @param {Object} from Source object
|
||||
* @return {Object} Destination object
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
utils.shallowCopy = function (to, from) {
|
||||
from = from || {};
|
||||
if ((to !== null) && (to !== undefined)) {
|
||||
for (var p in from) {
|
||||
if (!hasOwn(from, p)) {
|
||||
continue;
|
||||
}
|
||||
if (p === '__proto__' || p === 'constructor') {
|
||||
continue;
|
||||
}
|
||||
to[p] = from[p];
|
||||
}
|
||||
}
|
||||
return to;
|
||||
};
|
||||
|
||||
/**
|
||||
* Naive copy of a list of key names, from one object to another.
|
||||
* Only copies property if it is actually defined
|
||||
* Does not recurse into non-scalar properties
|
||||
*
|
||||
* @param {Object} to Destination object
|
||||
* @param {Object} from Source object
|
||||
* @param {Array} list List of properties to copy
|
||||
* @return {Object} Destination object
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
utils.shallowCopyFromList = function (to, from, list) {
|
||||
list = list || [];
|
||||
from = from || {};
|
||||
if ((to !== null) && (to !== undefined)) {
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var p = list[i];
|
||||
if (typeof from[p] != 'undefined') {
|
||||
if (!hasOwn(from, p)) {
|
||||
continue;
|
||||
}
|
||||
if (p === '__proto__' || p === 'constructor') {
|
||||
continue;
|
||||
}
|
||||
to[p] = from[p];
|
||||
}
|
||||
}
|
||||
}
|
||||
return to;
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple in-process cache implementation. Does not implement limits of any
|
||||
* sort.
|
||||
*
|
||||
* @implements {Cache}
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
utils.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 = {};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms hyphen case variable into camel case.
|
||||
*
|
||||
* @param {String} string Hyphen case string
|
||||
* @return {String} Camel case string
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
utils.hyphenToCamel = function (str) {
|
||||
return str.replace(/-[a-z]/g, function (match) { return match[1].toUpperCase(); });
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a null-prototype object in runtimes that support it
|
||||
*
|
||||
* @return {Object} Object, prototype will be set to null where possible
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
utils.createNullProtoObjWherePossible = (function () {
|
||||
if (typeof Object.create == 'function') {
|
||||
return function () {
|
||||
return Object.create(null);
|
||||
};
|
||||
}
|
||||
if (!({__proto__: null} instanceof Object)) {
|
||||
return function () {
|
||||
return {__proto__: null};
|
||||
};
|
||||
}
|
||||
// Not possible, just pass through
|
||||
return function () {
|
||||
return {};
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Copies own-properties from one object to a null-prototype object for basic
|
||||
* protection against prototype pollution
|
||||
*
|
||||
* @return {Object} Object with own-properties of input object
|
||||
* @static
|
||||
* @private
|
||||
*/
|
||||
utils.hasOwnOnlyObject = function (obj) {
|
||||
var o = utils.createNullProtoObjWherePossible();
|
||||
for (var p in obj) {
|
||||
if (hasOwn(obj, p)) {
|
||||
o[p] = obj[p];
|
||||
}
|
||||
}
|
||||
return o;
|
||||
};
|
||||
|
||||
if (typeof exports != 'undefined') {
|
||||
module.exports = utils;
|
||||
}
|
||||
export default utils;
|
||||
49
website/node_modules/ejs/package.json
generated
vendored
Normal file
49
website/node_modules/ejs/package.json
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "ejs",
|
||||
"description": "Embedded JavaScript templates",
|
||||
"keywords": [
|
||||
"template",
|
||||
"templating",
|
||||
"engine",
|
||||
"ejs"
|
||||
],
|
||||
"version": "5.0.2",
|
||||
"author": "Matthew Eernisse <matthew.eernisse@gmail.com>",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"ejs": "./bin/cli.js"
|
||||
},
|
||||
"main": "./lib/cjs/ejs.js",
|
||||
"module": "./lib/esm/ejs.js",
|
||||
"browser": "./ejs.min.js",
|
||||
"exports": {
|
||||
"import": "./lib/esm/ejs.js",
|
||||
"require": "./lib/cjs/ejs.js"
|
||||
},
|
||||
"jsdelivr": "ejs.min.js",
|
||||
"unpkg": "ejs.min.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/mde/ejs.git"
|
||||
},
|
||||
"bugs": "https://github.com/mde/ejs/issues",
|
||||
"homepage": "https://github.com/mde/ejs",
|
||||
"devDependencies": {
|
||||
"jake": "^10.9.1",
|
||||
"typescript": "^5.4.5",
|
||||
"@babel/eslint-parser": "^7.24.5",
|
||||
"browserify": "^17.0.0",
|
||||
"eslint": "^9.1.1",
|
||||
"git-directory-deploy": "^1.5.1",
|
||||
"jsdoc": "^4.0.2",
|
||||
"lru-cache": "^4.0.1",
|
||||
"mocha": "^10.2.0",
|
||||
"uglify-js": "^3.3.16"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.12.18"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "npx jake test"
|
||||
}
|
||||
}
|
||||
24
website/node_modules/ejs/usage.txt
generated
vendored
Normal file
24
website/node_modules/ejs/usage.txt
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
EJS Embedded JavaScript templates
|
||||
{Usage}: ejs [options ...] template-file [data variables ...]
|
||||
|
||||
{Options}:
|
||||
-o, --output-file FILE Write the rendered output to FILE rather than stdout.
|
||||
-f, --data-file FILE Must be JSON-formatted. Use parsed input from FILE as data for rendering.
|
||||
-i, --data-input STRING Must be JSON-formatted and URI-encoded. Use parsed input from STRING as data for rendering.
|
||||
-m, --delimiter CHARACTER Use CHARACTER with angle brackets for open/close (defaults to %).
|
||||
-p, --open-delimiter CHARACTER Use CHARACTER instead of left angle bracket to open.
|
||||
-c, --close-delimiter CHARACTER Use CHARACTER instead of right angle bracket to close.
|
||||
-s, --strict When set to `true`, generated function is in strict mode
|
||||
-n --no-with Use 'locals' object for vars rather than using `with` (implies --strict).
|
||||
-l --locals-name Name to use for the object storing local variables when not using `with`.
|
||||
-w --rm-whitespace Remove all safe-to-remove whitespace, including leading and trailing whitespace.
|
||||
-d --debug Outputs generated function body
|
||||
-h, --help Display this help message.
|
||||
-V/v, --version Display the EJS version.
|
||||
|
||||
{Examples}:
|
||||
ejs -m $ ./test/fixtures/user.ejs -f ./user_data.json
|
||||
ejs -m $ ./test/fixtures/user.ejs name=Lerxst
|
||||
ejs -p [ -c ] ./template_file.ejs -o ./output.html
|
||||
ejs -n -l _ ./some_template.ejs -f ./data_file.json
|
||||
ejs -w ./template_with_whitspace.ejs -o ./output_file.html
|
||||
Reference in New Issue
Block a user