From 0773f5159d594a9f3ee3628d1d79640157bad49e Mon Sep 17 00:00:00 2001 From: mgerb42 Date: Tue, 28 Jul 2015 12:49:32 -0500 Subject: [PATCH] added blogpost and switched to ejs --- {views/blogposts => Jade}/7-21-15.jade | 0 {views => Jade}/error.jade | 0 {views => Jade}/index.jade | 5 +- {views => Jade}/layout.jade | 0 {views => Jade}/success.jade | 0 app.js | 6 +- node_modules/ejs/Jakefile | 45 + node_modules/ejs/README.md | 178 + node_modules/ejs/ejs.js | 1224 ++ node_modules/ejs/ejs.min.js | 1 + node_modules/ejs/lib/ejs.js | 717 + node_modules/ejs/lib/utils.js | 141 + node_modules/ejs/package.json | 77 + node_modules/ejs/test/ejs.js | 859 + node_modules/ejs/test/fixtures/backslash.ejs | 1 + node_modules/ejs/test/fixtures/backslash.html | 1 + node_modules/ejs/test/fixtures/comments.ejs | 7 + node_modules/ejs/test/fixtures/comments.html | 6 + .../ejs/test/fixtures/consecutive-tags.ejs | 1 + .../ejs/test/fixtures/consecutive-tags.html | 1 + .../ejs/test/fixtures/double-quote.ejs | 1 + .../ejs/test/fixtures/double-quote.html | 1 + node_modules/ejs/test/fixtures/error.ejs | 5 + node_modules/ejs/test/fixtures/error.out | 8 + node_modules/ejs/test/fixtures/fail.ejs | 1 + .../ejs/test/fixtures/hello-world.ejs | 1 + .../ejs/test/fixtures/include-abspath.ejs | 5 + .../ejs/test/fixtures/include-simple.ejs | 3 + .../ejs/test/fixtures/include-simple.html | 4 + .../ejs/test/fixtures/include.css.ejs | 1 + .../ejs/test/fixtures/include.css.html | 4 + node_modules/ejs/test/fixtures/include.ejs | 5 + node_modules/ejs/test/fixtures/include.html | 12 + .../ejs/test/fixtures/include_cache.ejs | 1 + .../ejs/test/fixtures/include_cache.html | 1 + .../fixtures/include_preprocessor.css.ejs | 1 + .../fixtures/include_preprocessor.css.html | 4 + .../test/fixtures/include_preprocessor.ejs | 5 + .../test/fixtures/include_preprocessor.html | 12 + .../fixtures/include_preprocessor_cache.ejs | 1 + .../fixtures/include_preprocessor_cache.html | 1 + .../ejs/test/fixtures/includes/bom.ejs | 1 + .../ejs/test/fixtures/includes/menu-item.ejs | 1 + .../ejs/test/fixtures/includes/menu/item.ejs | 1 + node_modules/ejs/test/fixtures/literal.ejs | 3 + node_modules/ejs/test/fixtures/literal.html | 3 + node_modules/ejs/test/fixtures/menu.ejs | 15 + node_modules/ejs/test/fixtures/menu.html | 9 + .../ejs/test/fixtures/menu_preprocessor.ejs | 11 + .../ejs/test/fixtures/menu_preprocessor.html | 8 + node_modules/ejs/test/fixtures/menu_var.ejs | 15 + node_modules/ejs/test/fixtures/messed.ejs | 1 + node_modules/ejs/test/fixtures/messed.html | 1 + node_modules/ejs/test/fixtures/newlines.ejs | 5 + node_modules/ejs/test/fixtures/newlines.html | 9 + .../ejs/test/fixtures/newlines.mixed.ejs | 6 + .../ejs/test/fixtures/newlines.mixed.html | 4 + .../ejs/test/fixtures/no.newlines.ejs | 5 + .../ejs/test/fixtures/no.newlines.error.ejs | 5 + .../ejs/test/fixtures/no.newlines.html | 5 + .../ejs/test/fixtures/no.semicolons.ejs | 8 + .../ejs/test/fixtures/no.semicolons.html | 3 + node_modules/ejs/test/fixtures/para.ejs | 1 + node_modules/ejs/test/fixtures/pet.ejs | 1 + .../ejs/test/fixtures/rmWhitespace.ejs | 14 + .../ejs/test/fixtures/rmWhitespace.html | 8 + .../ejs/test/fixtures/single-quote.ejs | 1 + .../ejs/test/fixtures/single-quote.html | 1 + node_modules/ejs/test/fixtures/style.css | 3 + .../ejs/test/fixtures/user-no-with.ejs | 1 + node_modules/ejs/test/fixtures/user.ejs | 1 + .../ejs/test/fixtures/with-context.ejs | 1 + node_modules/ejs/test/mocha.opts | 3 + node_modules/ejs/test/tmp/include.ejs | 1 + .../ejs/test/tmp/include_preprocessor.ejs | 1 + node_modules/ejs/test/tmp/renderFile.ejs | 1 + npm-debug.log | 37 - public/javascripts/custom.js | 13 +- public/jquery-1.11.3.min.js | 5 + public/jquery-timepicker/.gitignore | 4 - public/jquery-timepicker/GruntFile.js | 29 - public/jquery-timepicker/README.md | 279 - public/jquery-timepicker/bower.json | 16 - public/jquery-timepicker/index.html | 392 - .../jquery-timepicker/jquery.timepicker.css | 72 - public/jquery-timepicker/jquery.timepicker.js | 1195 -- .../jquery.timepicker.min.js | 7 - .../jt.timepicker.jquery.json | 27 - .../lib/bootstrap-datepicker.css | 512 - .../lib/bootstrap-datepicker.js | 1671 -- .../lib/glyphicons-halflings.png | Bin 13826 -> 0 bytes public/jquery-timepicker/lib/screenshot.png | Bin 4756 -> 0 bytes public/jquery-timepicker/lib/site.css | 195 - public/jquery-timepicker/lib/site.js | 10 - public/jquery-timepicker/package.json | 31 - .../external/jquery/jquery.js | 0 .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 212 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 208 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 335 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 207 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 262 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 262 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 332 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 280 bytes .../images/ui-icons_222222_256x240.png | Bin 6922 -> 6922 bytes .../images/ui-icons_2e83ff_256x240.png} | Bin 4549 -> 4549 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 6992 bytes .../images/ui-icons_888888_256x240.png | Bin 0 -> 6999 bytes .../images/ui-icons_cd0a0a_256x240.png} | Bin 4549 -> 4549 bytes .../index.html | 0 .../jquery-ui.css | 270 +- .../jquery-ui.js | 14822 ++++++++-------- .../jquery-ui-1.11.4.custom/jquery-ui.min.css | 7 + .../jquery-ui-1.11.4.custom/jquery-ui.min.js | 13 + .../jquery-ui.structure.css | 174 +- .../jquery-ui.structure.min.css | 5 + .../jquery-ui.theme.css | 92 +- .../jquery-ui.theme.min.css | 5 + .../ui-bg_diagonals-thick_18_b81900_40x40.png | Bin 418 -> 0 bytes .../ui-bg_diagonals-thick_20_666666_40x40.png | Bin 312 -> 0 bytes .../images/ui-bg_flat_10_000000_40x100.png | Bin 205 -> 0 bytes .../images/ui-bg_glass_100_f6f6f6_1x400.png | Bin 262 -> 0 bytes .../images/ui-bg_glass_100_fdf5ce_1x400.png | Bin 348 -> 0 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 207 -> 0 bytes .../ui-bg_gloss-wave_35_f6a828_500x100.png | Bin 5815 -> 0 bytes .../ui-bg_highlight-soft_100_eeeeee_1x100.png | Bin 278 -> 0 bytes .../ui-bg_highlight-soft_75_ffe45c_1x100.png | Bin 328 -> 0 bytes .../images/ui-icons_228ef1_256x240.png | Bin 4549 -> 0 bytes .../images/ui-icons_ffffff_256x240.png | Bin 6299 -> 0 bytes public/jquery-ui-1.11.4/jquery-ui.min.css | 7 - public/jquery-ui-1.11.4/jquery-ui.min.js | 13 - .../jquery-ui.structure.min.css | 5 - .../jquery-ui-1.11.4/jquery-ui.theme.min.css | 5 - public/stylesheets/style.css | 2 +- routes/index.js | 11 +- views/blogposts/7-21-15.ejs | 47 + views/blogposts/7-28-15.ejs | 88 + views/error.ejs | 11 + views/index.ejs | 162 + views/layout.ejs | 13 + views/layoutBottom.ejs | 9 + views/success.ejs | 24 + 142 files changed, 11585 insertions(+), 12199 deletions(-) rename {views/blogposts => Jade}/7-21-15.jade (100%) rename {views => Jade}/error.jade (100%) rename {views => Jade}/index.jade (94%) rename {views => Jade}/layout.jade (100%) rename {views => Jade}/success.jade (100%) create mode 100644 node_modules/ejs/Jakefile create mode 100644 node_modules/ejs/README.md create mode 100644 node_modules/ejs/ejs.js create mode 100644 node_modules/ejs/ejs.min.js create mode 100644 node_modules/ejs/lib/ejs.js create mode 100644 node_modules/ejs/lib/utils.js create mode 100644 node_modules/ejs/package.json create mode 100644 node_modules/ejs/test/ejs.js create mode 100644 node_modules/ejs/test/fixtures/backslash.ejs create mode 100644 node_modules/ejs/test/fixtures/backslash.html create mode 100644 node_modules/ejs/test/fixtures/comments.ejs create mode 100644 node_modules/ejs/test/fixtures/comments.html create mode 100644 node_modules/ejs/test/fixtures/consecutive-tags.ejs create mode 100644 node_modules/ejs/test/fixtures/consecutive-tags.html create mode 100644 node_modules/ejs/test/fixtures/double-quote.ejs create mode 100644 node_modules/ejs/test/fixtures/double-quote.html create mode 100644 node_modules/ejs/test/fixtures/error.ejs create mode 100644 node_modules/ejs/test/fixtures/error.out create mode 100644 node_modules/ejs/test/fixtures/fail.ejs create mode 100644 node_modules/ejs/test/fixtures/hello-world.ejs create mode 100644 node_modules/ejs/test/fixtures/include-abspath.ejs create mode 100644 node_modules/ejs/test/fixtures/include-simple.ejs create mode 100644 node_modules/ejs/test/fixtures/include-simple.html create mode 100644 node_modules/ejs/test/fixtures/include.css.ejs create mode 100644 node_modules/ejs/test/fixtures/include.css.html create mode 100644 node_modules/ejs/test/fixtures/include.ejs create mode 100644 node_modules/ejs/test/fixtures/include.html create mode 100644 node_modules/ejs/test/fixtures/include_cache.ejs create mode 100644 node_modules/ejs/test/fixtures/include_cache.html create mode 100644 node_modules/ejs/test/fixtures/include_preprocessor.css.ejs create mode 100644 node_modules/ejs/test/fixtures/include_preprocessor.css.html create mode 100644 node_modules/ejs/test/fixtures/include_preprocessor.ejs create mode 100644 node_modules/ejs/test/fixtures/include_preprocessor.html create mode 100644 node_modules/ejs/test/fixtures/include_preprocessor_cache.ejs create mode 100644 node_modules/ejs/test/fixtures/include_preprocessor_cache.html create mode 100644 node_modules/ejs/test/fixtures/includes/bom.ejs create mode 100644 node_modules/ejs/test/fixtures/includes/menu-item.ejs create mode 100644 node_modules/ejs/test/fixtures/includes/menu/item.ejs create mode 100644 node_modules/ejs/test/fixtures/literal.ejs create mode 100644 node_modules/ejs/test/fixtures/literal.html create mode 100644 node_modules/ejs/test/fixtures/menu.ejs create mode 100644 node_modules/ejs/test/fixtures/menu.html create mode 100644 node_modules/ejs/test/fixtures/menu_preprocessor.ejs create mode 100644 node_modules/ejs/test/fixtures/menu_preprocessor.html create mode 100644 node_modules/ejs/test/fixtures/menu_var.ejs create mode 100644 node_modules/ejs/test/fixtures/messed.ejs create mode 100644 node_modules/ejs/test/fixtures/messed.html create mode 100644 node_modules/ejs/test/fixtures/newlines.ejs create mode 100644 node_modules/ejs/test/fixtures/newlines.html create mode 100644 node_modules/ejs/test/fixtures/newlines.mixed.ejs create mode 100644 node_modules/ejs/test/fixtures/newlines.mixed.html create mode 100644 node_modules/ejs/test/fixtures/no.newlines.ejs create mode 100644 node_modules/ejs/test/fixtures/no.newlines.error.ejs create mode 100644 node_modules/ejs/test/fixtures/no.newlines.html create mode 100644 node_modules/ejs/test/fixtures/no.semicolons.ejs create mode 100644 node_modules/ejs/test/fixtures/no.semicolons.html create mode 100644 node_modules/ejs/test/fixtures/para.ejs create mode 100644 node_modules/ejs/test/fixtures/pet.ejs create mode 100644 node_modules/ejs/test/fixtures/rmWhitespace.ejs create mode 100644 node_modules/ejs/test/fixtures/rmWhitespace.html create mode 100644 node_modules/ejs/test/fixtures/single-quote.ejs create mode 100644 node_modules/ejs/test/fixtures/single-quote.html create mode 100644 node_modules/ejs/test/fixtures/style.css create mode 100644 node_modules/ejs/test/fixtures/user-no-with.ejs create mode 100644 node_modules/ejs/test/fixtures/user.ejs create mode 100644 node_modules/ejs/test/fixtures/with-context.ejs create mode 100644 node_modules/ejs/test/mocha.opts create mode 100644 node_modules/ejs/test/tmp/include.ejs create mode 100644 node_modules/ejs/test/tmp/include_preprocessor.ejs create mode 100644 node_modules/ejs/test/tmp/renderFile.ejs delete mode 100644 npm-debug.log create mode 100644 public/jquery-1.11.3.min.js delete mode 100644 public/jquery-timepicker/.gitignore delete mode 100644 public/jquery-timepicker/GruntFile.js delete mode 100644 public/jquery-timepicker/README.md delete mode 100644 public/jquery-timepicker/bower.json delete mode 100644 public/jquery-timepicker/index.html delete mode 100755 public/jquery-timepicker/jquery.timepicker.css delete mode 100644 public/jquery-timepicker/jquery.timepicker.js delete mode 100644 public/jquery-timepicker/jquery.timepicker.min.js delete mode 100644 public/jquery-timepicker/jt.timepicker.jquery.json delete mode 100644 public/jquery-timepicker/lib/bootstrap-datepicker.css delete mode 100755 public/jquery-timepicker/lib/bootstrap-datepicker.js delete mode 100755 public/jquery-timepicker/lib/glyphicons-halflings.png delete mode 100755 public/jquery-timepicker/lib/screenshot.png delete mode 100644 public/jquery-timepicker/lib/site.css delete mode 100644 public/jquery-timepicker/lib/site.js delete mode 100644 public/jquery-timepicker/package.json rename public/{jquery-ui-1.11.4 => jquery-ui-1.11.4.custom}/external/jquery/jquery.js (100%) create mode 100644 public/jquery-ui-1.11.4.custom/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 public/jquery-ui-1.11.4.custom/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 public/jquery-ui-1.11.4.custom/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 public/jquery-ui-1.11.4.custom/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 public/jquery-ui-1.11.4.custom/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 public/jquery-ui-1.11.4.custom/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 public/jquery-ui-1.11.4.custom/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 public/jquery-ui-1.11.4.custom/images/ui-bg_highlight-soft_75_cccccc_1x100.png rename public/{jquery-ui-1.11.4 => jquery-ui-1.11.4.custom}/images/ui-icons_222222_256x240.png (98%) rename public/{jquery-ui-1.11.4/images/ui-icons_ffd27a_256x240.png => jquery-ui-1.11.4.custom/images/ui-icons_2e83ff_256x240.png} (90%) create mode 100644 public/jquery-ui-1.11.4.custom/images/ui-icons_454545_256x240.png create mode 100644 public/jquery-ui-1.11.4.custom/images/ui-icons_888888_256x240.png rename public/{jquery-ui-1.11.4/images/ui-icons_ef8c08_256x240.png => jquery-ui-1.11.4.custom/images/ui-icons_cd0a0a_256x240.png} (88%) rename public/{jquery-ui-1.11.4 => jquery-ui-1.11.4.custom}/index.html (100%) rename public/{jquery-ui-1.11.4 => jquery-ui-1.11.4.custom}/jquery-ui.css (90%) rename public/{jquery-ui-1.11.4 => jquery-ui-1.11.4.custom}/jquery-ui.js (99%) create mode 100644 public/jquery-ui-1.11.4.custom/jquery-ui.min.css create mode 100644 public/jquery-ui-1.11.4.custom/jquery-ui.min.js rename public/{jquery-ui-1.11.4 => jquery-ui-1.11.4.custom}/jquery-ui.structure.css (100%) create mode 100644 public/jquery-ui-1.11.4.custom/jquery-ui.structure.min.css rename public/{jquery-ui-1.11.4 => jquery-ui-1.11.4.custom}/jquery-ui.theme.css (81%) create mode 100644 public/jquery-ui-1.11.4.custom/jquery-ui.theme.min.css delete mode 100644 public/jquery-ui-1.11.4/images/ui-bg_diagonals-thick_18_b81900_40x40.png delete mode 100644 public/jquery-ui-1.11.4/images/ui-bg_diagonals-thick_20_666666_40x40.png delete mode 100644 public/jquery-ui-1.11.4/images/ui-bg_flat_10_000000_40x100.png delete mode 100644 public/jquery-ui-1.11.4/images/ui-bg_glass_100_f6f6f6_1x400.png delete mode 100644 public/jquery-ui-1.11.4/images/ui-bg_glass_100_fdf5ce_1x400.png delete mode 100644 public/jquery-ui-1.11.4/images/ui-bg_glass_65_ffffff_1x400.png delete mode 100644 public/jquery-ui-1.11.4/images/ui-bg_gloss-wave_35_f6a828_500x100.png delete mode 100644 public/jquery-ui-1.11.4/images/ui-bg_highlight-soft_100_eeeeee_1x100.png delete mode 100644 public/jquery-ui-1.11.4/images/ui-bg_highlight-soft_75_ffe45c_1x100.png delete mode 100644 public/jquery-ui-1.11.4/images/ui-icons_228ef1_256x240.png delete mode 100644 public/jquery-ui-1.11.4/images/ui-icons_ffffff_256x240.png delete mode 100644 public/jquery-ui-1.11.4/jquery-ui.min.css delete mode 100644 public/jquery-ui-1.11.4/jquery-ui.min.js delete mode 100644 public/jquery-ui-1.11.4/jquery-ui.structure.min.css delete mode 100644 public/jquery-ui-1.11.4/jquery-ui.theme.min.css create mode 100644 views/blogposts/7-21-15.ejs create mode 100644 views/blogposts/7-28-15.ejs create mode 100644 views/error.ejs create mode 100644 views/index.ejs create mode 100644 views/layout.ejs create mode 100644 views/layoutBottom.ejs create mode 100644 views/success.ejs diff --git a/views/blogposts/7-21-15.jade b/Jade/7-21-15.jade similarity index 100% rename from views/blogposts/7-21-15.jade rename to Jade/7-21-15.jade diff --git a/views/error.jade b/Jade/error.jade similarity index 100% rename from views/error.jade rename to Jade/error.jade diff --git a/views/index.jade b/Jade/index.jade similarity index 94% rename from views/index.jade rename to Jade/index.jade index 4234c1d..7f470d4 100644 --- a/views/index.jade +++ b/Jade/index.jade @@ -10,8 +10,7 @@ block content h1.blog-title mitchellG.me p.lead.blog-description A "blog" about computer related projects that I find interesting. div.row - div.col-lg-8.blog-main - include ./blogposts/7-21-15.jade + div.col-sm-8.blog-main @@ -22,7 +21,7 @@ block content br div.sidebar-module.sidebar-module-inset p. - I'm 22 years old and I'm currently attending Winona State University as a Computer Science major. + I'm 22 years old and currently attending Winona State University as a Computer Science major. I am graduating in Spring of 2016 and plan to pursue a career in the field of software development. a(href="https://www.linkedin.com/pub/mitchell-gerber/b3/391/125" target="_blank") i.icon-large.icon-linked-in diff --git a/views/layout.jade b/Jade/layout.jade similarity index 100% rename from views/layout.jade rename to Jade/layout.jade diff --git a/views/success.jade b/Jade/success.jade similarity index 100% rename from views/success.jade rename to Jade/success.jade diff --git a/app.js b/app.js index c3221cf..c9d6832 100644 --- a/app.js +++ b/app.js @@ -7,6 +7,7 @@ var bodyParser = require('body-parser'); var index = require('./routes/index'); var success = require('./routes/success'); + var mongoose = require('mongoose'); var mainLoop = require('./main'); @@ -22,7 +23,7 @@ db.once('open', function (callback) { // view engine setup app.set('views', path.join(__dirname, 'views')); -app.set('view engine', 'jade'); +app.set('view engine', 'ejs'); // uncomment after placing your favicon in /public app.use(favicon(__dirname + '/public/favicon.ico')); @@ -33,7 +34,8 @@ app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use('/', index); -app.use('/success', success) +app.use('/success', success); + // catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); diff --git a/node_modules/ejs/Jakefile b/node_modules/ejs/Jakefile new file mode 100644 index 0000000..0362e98 --- /dev/null +++ b/node_modules/ejs/Jakefile @@ -0,0 +1,45 @@ +var fs = require('fs') + , buildOpts = { + printStdout: true + , printStderr: true + }; + +task('build', ['browserify', 'minify'], function () { + console.log('Build completed.'); +}); + +desc('Cleans browerified/minified files and package files'); +task('clean', ['clobber'], function () { + jake.rmRf('./ejs.js'); + jake.rmRf('./ejs.min.js'); +}); + +task('browserify', {async: true}, function () { + jake.exec('./node_modules/browserify/bin/cmd.js lib/ejs.js > ejs.js', + buildOpts, function () { + console.log('Browserification completed.'); + setTimeout(complete, 0); + }); +}); + +task('minify', {async: true}, function () { + jake.exec('./node_modules/uglify-js/bin/uglifyjs ejs.js > ejs.min.js', + buildOpts, function () { + console.log('Minification completed.'); + setTimeout(complete, 0); + }); +}); + +publishTask('ejs', ['build'], function () { + this.packageFiles.include([ + 'Jakefile' + , 'README.md' + , 'package.json' + , 'ejs.js' + , 'ejs.min.js' + , 'lib/**' + , 'test/**' + ]); +}); + + diff --git a/node_modules/ejs/README.md b/node_modules/ejs/README.md new file mode 100644 index 0000000..f0bffdb --- /dev/null +++ b/node_modules/ejs/README.md @@ -0,0 +1,178 @@ +# EJS + +Embedded JavaScript templates + +[![Build Status](https://img.shields.io/travis/mde/ejs/master.svg?style=flat)](https://travis-ci.org/mde/ejs) +[![Developing Dependencies](https://img.shields.io/david/dev/mde/ejs.svg?style=flat)](https://david-dm.org/mde/ejs#info=devDependencies) + +## Installation + +```bash +$ npm install ejs +``` + +## Features + + * Control flow with `<% %>` + * Escaped output with `<%= %>` + * Unescaped raw output with `<%- %>` + * Trim-mode ('newline slurping') with `-%>` ending tag + * Custom delimiters (e.g., use '' 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 + +```html +<% if (user) { %> +

<%= user.name %>

+<% } %> +``` + +## Usage + +```javascript +var template = ejs.compile(str, options); +template(data); +// => Rendered HTML string + +ejs.render(str, data, options); +// => Rendered HTML string +``` + +You can also use the shortcut `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. + +## Options + + - `cache` Compiled functions are cached, requires `filename` + - `filename` Used by `cache` to key caches, and for includes + - `context` Function execution context + - `compileDebug` When `false` no debug instrumentation is compiled + - `client` Returns standalone compiled function + - `delimiter` Character to use with angle brackets for open/close + - `debug` Output generated function body + - `_with` Whether or not to use `with() {}` constructs. If `false` then the locals will be stored in the `locals` object. + - `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). + +## Tags + + - `<%` 'Scriptlet' tag, for control-flow, no output + - `<%=` Outputs the value into the template (HTML escaped) + - `<%-` Outputs the unescaped value into the template + - `<%#` Comment tag, no execution, no output + - `<%%` Outputs a literal '<%' + - `%>` Plain ending tag + - `-%>` Trim-mode ('newline slurp') tag, trims following newline + +## Includes + +Includes either have to be an absolute path, or, if not, are assumed as +relative to the template with the `include` call. (This requires the +`filename` option.) For example if you are including `./views/user/show.ejs` +from `./views/users.ejs` you would use `<%- include('user/show') %>`. + +You'll likely want to use the raw output tag (`<%-`) with your include to avoid +double-escaping the HTML output. + +```html + +``` + +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 +still supported. + +## Custom delimiters + +Custom delimiters can be applied on a per-template basis, or globally: + +```javascript +var ejs = require('ejs'), + users = ['geddy', 'neil', 'alex']; + +// Just one template +ejs.render('', {users: users}, {delimiter: '?'}); +// => 'geddy | neil | alex' + +// Or globally +ejs.delimiter = '$'; +ejs.render('<$= users.join(" | "); $>', {users: users}); +// => 'geddy | neil | alex' +``` + +## 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 +var ejs = require('ejs') + , LRU = require('lru-cache'); +ejs.cache = LRU(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. + +## Layouts + +EJS does not specifically support blocks, but layouts can be implemented by +including headers and footers, like so: + + +```html +<%- include('header') -%> +

+ Title +

+

+ My page +

+<%- include('footer') -%> +``` + +## Client-side support + +Go to the [Latest Release](https://github.com/mde/ejs/releases/latest), download +`./ejs.js` or `./ejs.min.js`. + +Include one of these on your page, and `ejs.render(str)`. + +## Related projects + +There are a number of implementations of EJS: + + * TJ's implementation, the v1 of this library: https://github.com/tj/ejs + * Jupiter Consulting's EJS: http://www.embeddedjs.com/ + * 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 + +## License + +Licensed under the Apache License, Version 2.0 +() + +- - - +EJS Embedded JavaScript templates copyright 2112 +mde@fleegix.org. + + diff --git a/node_modules/ejs/ejs.js b/node_modules/ejs/ejs.js new file mode 100644 index 0000000..e4e17ea --- /dev/null +++ b/node_modules/ejs/ejs.js @@ -0,0 +1,1224 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o + * @author Tiancheng "Timothy" Gu + * @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 + */ + +var fs = require('fs') + , utils = require('./utils') + , scopeOptionWarned = false + , _VERSION_STRING = require('../package.json').version + , _DEFAULT_DELIMITER = '%' + , _DEFAULT_LOCALS_NAME = 'locals' + , _REGEX_STRING = '(<%%|<%=|<%-|<%#|<%|%>|-%>)' + , _OPTS = [ 'cache', 'filename', 'delimiter', 'scope', 'context' + , 'debug', 'compileDebug', 'client', '_with' + ] + , _TRAILING_SEMCOL = /;\s*$/ + , _BOM = /^\uFEFF/; + +/** + * 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} + */ + +exports.cache = utils.cache; + +/** + * Name of the object containing the locals. + * + * This variable is overriden by {@link Options}`.localsName` if it is not + * `undefined`. + * + * @type {String} + * @public + */ + +exports.localsName = _DEFAULT_LOCALS_NAME; + +/** + * 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 + * @return {String} + */ + +exports.resolveInclude = function(name, filename) { + var path = require('path') + , dirname = path.dirname + , extname = path.extname + , resolve = path.resolve + , includePath = resolve(dirname(filename), name) + , ext = extname(name); + if (!ext) { + includePath += '.ejs'; + } + 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|ClientFunction)} + * Depending on the value of `options.client`, either type might be returned. + * @static + */ + +function handleCache(options, template) { + var fn + , path = options.filename + , hasTemplate = arguments.length > 1; + + if (options.cache) { + if (!path) { + throw new Error('cache option requires a filename'); + } + fn = exports.cache.get(path); + if (fn) { + return fn; + } + if (!hasTemplate) { + template = fs.readFileSync(path).toString().replace(_BOM, ''); + } + } + else if (!hasTemplate) { + // istanbul ignore if: should not happen at all + if (!path) { + throw new Error('Internal EJS error: no file name or template ' + + 'provided'); + } + template = fs.readFileSync(path).toString().replace(_BOM, ''); + } + fn = exports.compile(template, options); + if (options.cache) { + exports.cache.set(path, fn); + } + return fn; +} + +/** + * 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|ClientFunction)} + * Depending on the value of `options.client`, either type might be returned + * @static + */ + +function includeFile(path, options) { + var opts = utils.shallowCopy({}, options); + if (!opts.filename) { + throw new Error('`include` requires the \'filename\' option.'); + } + opts.filename = exports.resolveInclude(path, opts.filename); + return handleCache(opts); +} + +/** + * Get the JavaScript source of an included file. + * + * @memberof module:ejs-internal + * @param {String} path path for the specified file + * @param {Options} options compilation options + * @return {String} + * @static + */ + +function includeSource(path, options) { + var opts = utils.shallowCopy({}, options) + , includePath + , template; + if (!opts.filename) { + throw new Error('`include` requires the \'filename\' option.'); + } + includePath = exports.resolveInclude(path, opts.filename); + template = fs.readFileSync(includePath).toString().replace(_BOM, ''); + + opts.filename = includePath; + var templ = new Template(template, opts); + templ.generateSource(); + return templ.source; +} + +/** + * 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} filename file name of the EJS file + * @param {String} lineno line number of the error + * @static + */ + +function rethrow(err, str, filename, lineno){ + var lines = str.split('\n') + , start = Math.max(lineno - 3, 0) + , end = Math.min(lines.length, lineno + 3); + + // 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; +} + +/** + * Copy properties in data object that are recognized as options to an + * options object. + * + * This is used for compatibility with earlier versions of EJS and Express.js. + * + * @memberof module:ejs-internal + * @param {Object} data data object + * @param {Options} opts options object + * @static + */ + +function cpOptsInData(data, opts) { + _OPTS.forEach(function (p) { + if (typeof data[p] != 'undefined') { + opts[p] = data[p]; + } + }); +} + +/** + * Compile the given `str` of ejs into a template function. + * + * @param {String} template EJS template + * + * @param {Options} opts compilation options + * + * @return {(TemplateFunction|ClientFunction)} + * Depending on the value of `opts.client`, either type might be returned. + * @public + */ + +exports.compile = function compile(template, opts) { + var templ; + + // v1 compat + // 'scope' is 'context' + // FIXME: Remove this in a future version + if (opts && opts.scope) { + if (!scopeOptionWarned){ + console.warn('`scope` option is deprecated and will be removed in EJS 3'); + scopeOptionWarned = true; + } + if (!opts.context) { + opts.context = opts.scope; + } + delete opts.scope; + } + templ = new Template(template, opts); + return templ.compile(); +}; + +/** + * 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} + * @public + */ + +exports.render = function (template, data, opts) { + data = data || {}; + opts = opts || {}; + var fn; + + // No options object -- if there are optiony names + // in the data, copy them to options + if (arguments.length == 2) { + cpOptsInData(data, opts); + } + + 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 + */ + +exports.renderFile = function () { + var args = Array.prototype.slice.call(arguments) + , path = args.shift() + , cb = args.pop() + , data = args.shift() || {} + , opts = args.pop() || {} + , result; + + // Don't pollute passed in opts obj with new vals + opts = utils.shallowCopy({}, opts); + + // No options object -- if there are optiony names + // in the data, copy them to options + if (arguments.length == 3) { + cpOptsInData(data, opts); + } + opts.filename = path; + + try { + result = handleCache(opts)(data); + } + catch(err) { + return cb(err); + } + return cb(null, result); +}; + +/** + * Clear intermediate JavaScript cache. Calls {@link Cache#reset}. + * @public + */ + +exports.clearCache = function () { + exports.cache.reset(); +}; + +function Template(text, opts) { + opts = opts || {}; + var options = {}; + this.templateText = text; + this.mode = null; + this.truncate = false; + this.currentLine = 1; + this.source = ''; + this.dependencies = []; + options.client = opts.client || false; + options.escapeFunction = opts.escape || utils.escapeXML; + options.compileDebug = opts.compileDebug !== false; + options.debug = !!opts.debug; + options.filename = opts.filename; + options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER; + options._with = typeof opts._with != 'undefined' ? opts._with : true; + options.context = opts.context; + options.cache = opts.cache || false; + options.rmWhitespace = opts.rmWhitespace; + 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 + , delim = utils.escapeRegExpChars(this.opts.delimiter); + str = str.replace(/%/g, delim); + return new RegExp(str); + } + +, compile: function () { + var src + , fn + , opts = this.opts + , prepended = '' + , appended = '' + , escape = opts.escapeFunction; + + if (opts.rmWhitespace) { + // Have to use two separate replace here as `^` and `$` operators don't + // work well with `\r`. + this.templateText = + this.templateText.replace(/\r/g, '').replace(/^\s+|\s+$/gm, ''); + } + + if (!this.source) { + this.generateSource(); + prepended += ' var __output = [], __append = __output.push.bind(__output);' + '\n'; + if (opts._with !== false) { + prepended += ' with (' + exports.localsName + ' || {}) {' + '\n'; + appended += ' }' + '\n'; + } + appended += ' return __output.join("");' + '\n'; + this.source = prepended + this.source + appended; + } + + if (opts.compileDebug) { + src = 'var __line = 1' + '\n' + + ' , __lines = ' + JSON.stringify(this.templateText) + '\n' + + ' , __filename = ' + (opts.filename ? + JSON.stringify(opts.filename) : 'undefined') + ';' + '\n' + + 'try {' + '\n' + + this.source + + '} catch (e) {' + '\n' + + ' rethrow(e, __lines, __filename, __line);' + '\n' + + '}' + '\n'; + } + else { + src = this.source; + } + + if (opts.debug) { + console.log(src); + } + + if (opts.client) { + src = 'escape = escape || ' + escape.toString() + ';' + '\n' + src; + if (opts.compileDebug) { + src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\n' + src; + } + } + + try { + fn = new Function(exports.localsName + ', escape, 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'; + } + throw e; + } + + if (opts.client) { + fn.dependencies = this.dependencies; + return fn; + } + + // 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 (data) { + var include = function (path, includeData) { + var d = utils.shallowCopy({}, data); + if (includeData) { + d = utils.shallowCopy(d, includeData); + } + return includeFile(path, opts)(d); + }; + return fn.apply(opts.context, [data || {}, escape, include, rethrow]); + }; + returnedFn.dependencies = this.dependencies; + return returnedFn; + } + +, generateSource: function () { + var self = this + , matches = this.parseTemplateText() + , d = this.opts.delimiter; + + if (matches && matches.length) { + matches.forEach(function (line, index) { + var opening + , closing + , include + , includeOpts + , includeSrc; + // 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 '<' + delimiter as key + // Then this can simply check against the map + if ( line.indexOf('<' + d) === 0 // If it is a tag + && line.indexOf('<' + d + d) !== 0) { // and is not escaped + closing = matches[index + 2]; + if (!(closing == d + '>' || closing == '-' + d + '>')) { + throw new Error('Could not find matching close tag for "' + line + '".'); + } + } + // HACK: backward-compat `include` preprocessor directives + if ((include = line.match(/^\s*include\s+(\S+)/))) { + opening = matches[index - 1]; + // Must be in EVAL or RAW mode + if (opening && (opening == '<' + d || opening == '<' + d + '-')) { + includeOpts = utils.shallowCopy({}, self.opts); + includeSrc = includeSource(include[1], includeOpts); + includeSrc = ' ; (function(){' + '\n' + includeSrc + + ' ; })()' + '\n'; + self.source += includeSrc; + self.dependencies.push(exports.resolveInclude(include[1], + includeOpts.filename)); + return; + } + } + self.scanLine(line); + }); + } + + } + +, parseTemplateText: function () { + var str = this.templateText + , pat = this.regex + , result = pat.exec(str) + , arr = [] + , firstPos + , lastPos; + + while (result) { + firstPos = result.index; + lastPos = pat.lastIndex; + + 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; + } + +, scanLine: function (line) { + var self = this + , d = this.opts.delimiter + , newLineCount = 0; + + function _addOutput() { + if (self.truncate) { + line = line.replace('\n', ''); + self.truncate = false; + } + else if (self.opts.rmWhitespace) { + // Gotta me more careful here. + // .replace(/^(\s*)\n/, '$1') might be more appropriate here but as + // rmWhitespace already removes trailing spaces anyway so meh. + line = line.replace(/^\n/, ''); + } + if (!line) { + return; + } + + // 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, '\\"'); + self.source += ' ; __append("' + line + '")' + '\n'; + } + + newLineCount = (line.split('\n').length - 1); + + switch (line) { + case '<' + d: + this.mode = Template.modes.EVAL; + break; + case '<' + d + '=': + this.mode = Template.modes.ESCAPED; + break; + case '<' + d + '-': + this.mode = Template.modes.RAW; + break; + case '<' + d + '#': + this.mode = Template.modes.COMMENT; + break; + case '<' + d + d: + this.mode = Template.modes.LITERAL; + this.source += ' ; __append("' + line.replace('<' + d + d, '<' + d) + '")' + '\n'; + break; + case d + '>': + case '-' + d + '>': + if (this.mode == Template.modes.LITERAL) { + _addOutput(); + } + + this.mode = null; + this.truncate = 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(escape(' + + line.replace(_TRAILING_SEMCOL, '').trim() + '))' + '\n'; + break; + // Exec and output + case Template.modes.RAW: + this.source += ' ; __append(' + + line.replace(_TRAILING_SEMCOL, '').trim() + ')' + '\n'; + break; + case Template.modes.COMMENT: + // Do nothing + break; + // Literal <%% mode, append as raw output + case Template.modes.LITERAL: + _addOutput(); + break; + } + } + // In string mode, just add the output + else { + _addOutput(); + } + } + + if (self.opts.compileDebug && newLineCount) { + this.currentLine += newLineCount; + this.source += ' ; __line = ' + this.currentLine + '\n'; + } + } +}; + +/** + * Express.js support. + * + * This is an alias for {@link module:ejs.renderFile}, in order to support + * Express.js out-of-the-box. + * + * @func + */ + +exports.__express = exports.renderFile; + +// Add require support +/* istanbul ignore else */ +if (require.extensions) { + require.extensions['.ejs'] = function (module, filename) { + filename = filename || /* istanbul ignore next */ module.filename; + var options = { + filename: filename + , client: true + } + , template = fs.readFileSync(filename).toString() + , fn = exports.compile(template, options); + module._compile('module.exports = ' + fn.toString() + ';', filename); + }; +} + +/** + * Version of EJS. + * + * @readonly + * @type {String} + * @public + */ + +exports.VERSION = _VERSION_STRING; + +/* istanbul ignore if */ +if (typeof window != 'undefined') { + window.ejs = exports; +} + +},{"../package.json":6,"./utils":2,"fs":3,"path":4}],2:[function(require,module,exports){ +/* + * 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'; + +var regExpChars = /[|\\{}()[\]^$+*?.]/g; + +/** + * 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 + */ +exports.escapeRegExpChars = function (string) { + // istanbul ignore if + if (!string) { + return ''; + } + return String(string).replace(regExpChars, '\\$&'); +}; + +var _ENCODE_HTML_RULES = { + '&': '&' + , '<': '<' + , '>': '>' + , '"': '"' + , "'": ''' + } + , _MATCH_HTML = /[&<>\'"]/g; + +function encode_char(c) { + return _ENCODE_HTML_RULES[c] || c; +}; + +/** + * Stringified version of constants used by {@link module:utils.escapeXML}. + * + * It is used in the process of generating {@link ClientFunction}s. + * + * @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 + */ + +exports.escapeXML = function (markup) { + return markup == undefined + ? '' + : String(markup) + .replace(_MATCH_HTML, encode_char); +}; +exports.escapeXML.toString = function () { + return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr +}; + +/** + * Copy all properties from one object to another, in a shallow fashion. + * + * @param {Object} to Destination object + * @param {Object} from Source object + * @return {Object} Destination object + * @static + * @private + */ +exports.shallowCopy = function (to, from) { + from = from || {}; + for (var p in from) { + to[p] = from[p]; + } + return to; +}; + +/** + * Simple in-process cache implementation. Does not implement limits of any + * sort. + * + * @implements Cache + * @static + * @private + */ +exports.cache = { + _data: {}, + set: function (key, val) { + this._data[key] = val; + }, + get: function (key) { + return this._data[key]; + }, + reset: function () { + this._data = {}; + } +}; + + +},{}],3:[function(require,module,exports){ + +},{}],4:[function(require,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Split a filename into [root, dir, basename, ext], unix version +// 'root' is just a slash, or nothing. +var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; +var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); +}; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { + var resolvedPath = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = substr(path, -1) === '/'; + + // Normalize the path + path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + +// posix version +exports.isAbsolute = function(path) { + return path.charAt(0) === '/'; +}; + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + if (typeof p !== 'string') { + throw new TypeError('Arguments to path.join must be strings'); + } + return p; + }).join('/')); +}; + + +// path.relative(from, to) +// posix version +exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); +}; + +exports.sep = '/'; +exports.delimiter = ':'; + +exports.dirname = function(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; + + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; +}; + + +exports.basename = function(path, ext) { + var f = splitPath(path)[2]; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPath(path)[3]; +}; + +function filter (xs, f) { + if (xs.filter) return xs.filter(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + if (f(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} + +// String.prototype.substr - negative index don't work in IE8 +var substr = 'ab'.substr(-1) === 'b' + ? function (str, start, len) { return str.substr(start, len) } + : function (str, start, len) { + if (start < 0) start = str.length + start; + return str.substr(start, len); + } +; + +}).call(this,require('_process')) +},{"_process":5}],5:[function(require,module,exports){ +// shim for using process in browser + +var process = module.exports = {}; + +process.nextTick = (function () { + var canSetImmediate = typeof window !== 'undefined' + && window.setImmediate; + var canMutationObserver = typeof window !== 'undefined' + && window.MutationObserver; + var canPost = typeof window !== 'undefined' + && window.postMessage && window.addEventListener + ; + + if (canSetImmediate) { + return function (f) { return window.setImmediate(f) }; + } + + var queue = []; + + if (canMutationObserver) { + var hiddenDiv = document.createElement("div"); + var observer = new MutationObserver(function () { + var queueList = queue.slice(); + queue.length = 0; + queueList.forEach(function (fn) { + fn(); + }); + }); + + observer.observe(hiddenDiv, { attributes: true }); + + return function nextTick(fn) { + if (!queue.length) { + hiddenDiv.setAttribute('yes', 'no'); + } + queue.push(fn); + }; + } + + if (canPost) { + window.addEventListener('message', function (ev) { + var source = ev.source; + if ((source === window || source === null) && ev.data === 'process-tick') { + ev.stopPropagation(); + if (queue.length > 0) { + var fn = queue.shift(); + fn(); + } + } + }, true); + + return function nextTick(fn) { + queue.push(fn); + window.postMessage('process-tick', '*'); + }; + } + + return function nextTick(fn) { + setTimeout(fn, 0); + }; +})(); + +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +// TODO(shtylman) +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; + +},{}],6:[function(require,module,exports){ +module.exports={ + "name": "ejs", + "description": "Embedded JavaScript templates", + "keywords": [ + "template", + "engine", + "ejs" + ], + "version": "2.3.2", + "author": "Matthew Eernisse (http://fleegix.org)", + "contributors": [ + "Timothy Gu (https://timothygu.github.io)" + ], + "license": "Apache-2.0", + "main": "./lib/ejs.js", + "repository": { + "type": "git", + "url": "git://github.com/mde/ejs.git" + }, + "bugs": "https://github.com/mde/ejs/issues", + "homepage": "https://github.com/mde/ejs", + "dependencies": {}, + "devDependencies": { + "browserify": "^8.0.3", + "istanbul": "~0.3.5", + "jake": "^8.0.0", + "jsdoc": "^3.3.0-beta1", + "lru-cache": "^2.5.0", + "mocha": "^2.1.0", + "rimraf": "^2.2.8", + "uglify-js": "^2.4.16" + }, + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "test": "mocha", + "coverage": "istanbul cover node_modules/mocha/bin/_mocha", + "doc": "rimraf out && jsdoc -c jsdoc.json lib/* docs/jsdoc/*", + "devdoc": "rimraf out && jsdoc -p -c jsdoc.json lib/* docs/jsdoc/*" + } +} +},{}]},{},[1]); diff --git a/node_modules/ejs/ejs.min.js b/node_modules/ejs/ejs.min.js new file mode 100644 index 0000000..78c6abd --- /dev/null +++ b/node_modules/ejs/ejs.min.js @@ -0,0 +1 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o|-%>)",_OPTS=["cache","filename","delimiter","scope","context","debug","compileDebug","client","_with"],_TRAILING_SEMCOL=/;\s*$/,_BOM=/^\uFEFF/;exports.cache=utils.cache;exports.localsName=_DEFAULT_LOCALS_NAME;exports.resolveInclude=function(name,filename){var path=require("path"),dirname=path.dirname,extname=path.extname,resolve=path.resolve,includePath=resolve(dirname(filename),name),ext=extname(name);if(!ext){includePath+=".ejs"}return includePath};function handleCache(options,template){var fn,path=options.filename,hasTemplate=arguments.length>1;if(options.cache){if(!path){throw new Error("cache option requires a filename")}fn=exports.cache.get(path);if(fn){return fn}if(!hasTemplate){template=fs.readFileSync(path).toString().replace(_BOM,"")}}else if(!hasTemplate){if(!path){throw new Error("Internal EJS error: no file name or template "+"provided")}template=fs.readFileSync(path).toString().replace(_BOM,"")}fn=exports.compile(template,options);if(options.cache){exports.cache.set(path,fn)}return fn}function includeFile(path,options){var opts=utils.shallowCopy({},options);if(!opts.filename){throw new Error("`include` requires the 'filename' option.")}opts.filename=exports.resolveInclude(path,opts.filename);return handleCache(opts)}function includeSource(path,options){var opts=utils.shallowCopy({},options),includePath,template;if(!opts.filename){throw new Error("`include` requires the 'filename' option.")}includePath=exports.resolveInclude(path,opts.filename);template=fs.readFileSync(includePath).toString().replace(_BOM,"");opts.filename=includePath;var templ=new Template(template,opts);templ.generateSource();return templ.source}function rethrow(err,str,filename,lineno){var lines=str.split("\n"),start=Math.max(lineno-3,0),end=Math.min(lines.length,lineno+3);var context=lines.slice(start,end).map(function(line,i){var curr=i+start+1;return(curr==lineno?" >> ":" ")+curr+"| "+line}).join("\n");err.path=filename;err.message=(filename||"ejs")+":"+lineno+"\n"+context+"\n\n"+err.message;throw err}function cpOptsInData(data,opts){_OPTS.forEach(function(p){if(typeof data[p]!="undefined"){opts[p]=data[p]}})}exports.compile=function compile(template,opts){var templ;if(opts&&opts.scope){if(!scopeOptionWarned){console.warn("`scope` option is deprecated and will be removed in EJS 3");scopeOptionWarned=true}if(!opts.context){opts.context=opts.scope}delete opts.scope}templ=new Template(template,opts);return templ.compile()};exports.render=function(template,data,opts){data=data||{};opts=opts||{};var fn;if(arguments.length==2){cpOptsInData(data,opts)}return handleCache(opts,template)(data)};exports.renderFile=function(){var args=Array.prototype.slice.call(arguments),path=args.shift(),cb=args.pop(),data=args.shift()||{},opts=args.pop()||{},result;opts=utils.shallowCopy({},opts);if(arguments.length==3){cpOptsInData(data,opts)}opts.filename=path;try{result=handleCache(opts)(data)}catch(err){return cb(err)}return cb(null,result)};exports.clearCache=function(){exports.cache.reset()};function Template(text,opts){opts=opts||{};var options={};this.templateText=text;this.mode=null;this.truncate=false;this.currentLine=1;this.source="";this.dependencies=[];options.client=opts.client||false;options.escapeFunction=opts.escape||utils.escapeXML;options.compileDebug=opts.compileDebug!==false;options.debug=!!opts.debug;options.filename=opts.filename;options.delimiter=opts.delimiter||exports.delimiter||_DEFAULT_DELIMITER;options._with=typeof opts._with!="undefined"?opts._with:true;options.context=opts.context;options.cache=opts.cache||false;options.rmWhitespace=opts.rmWhitespace;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,delim=utils.escapeRegExpChars(this.opts.delimiter);str=str.replace(/%/g,delim);return new RegExp(str)},compile:function(){var src,fn,opts=this.opts,prepended="",appended="",escape=opts.escapeFunction;if(opts.rmWhitespace){this.templateText=this.templateText.replace(/\r/g,"").replace(/^\s+|\s+$/gm,"")}if(!this.source){this.generateSource();prepended+=" var __output = [], __append = __output.push.bind(__output);"+"\n";if(opts._with!==false){prepended+=" with ("+exports.localsName+" || {}) {"+"\n";appended+=" }"+"\n"}appended+=' return __output.join("");'+"\n";this.source=prepended+this.source+appended}if(opts.compileDebug){src="var __line = 1"+"\n"+" , __lines = "+JSON.stringify(this.templateText)+"\n"+" , __filename = "+(opts.filename?JSON.stringify(opts.filename):"undefined")+";"+"\n"+"try {"+"\n"+this.source+"} catch (e) {"+"\n"+" rethrow(e, __lines, __filename, __line);"+"\n"+"}"+"\n"}else{src=this.source}if(opts.debug){console.log(src)}if(opts.client){src="escape = escape || "+escape.toString()+";"+"\n"+src;if(opts.compileDebug){src="rethrow = rethrow || "+rethrow.toString()+";"+"\n"+src}}try{fn=new Function(exports.localsName+", escape, include, rethrow",src)}catch(e){if(e instanceof SyntaxError){if(opts.filename){e.message+=" in "+opts.filename}e.message+=" while compiling ejs"}throw e}if(opts.client){fn.dependencies=this.dependencies;return fn}var returnedFn=function(data){var include=function(path,includeData){var d=utils.shallowCopy({},data);if(includeData){d=utils.shallowCopy(d,includeData)}return includeFile(path,opts)(d)};return fn.apply(opts.context,[data||{},escape,include,rethrow])};returnedFn.dependencies=this.dependencies;return returnedFn},generateSource:function(){var self=this,matches=this.parseTemplateText(),d=this.opts.delimiter;if(matches&&matches.length){matches.forEach(function(line,index){var opening,closing,include,includeOpts,includeSrc;if(line.indexOf("<"+d)===0&&line.indexOf("<"+d+d)!==0){closing=matches[index+2];if(!(closing==d+">"||closing=="-"+d+">")){throw new Error('Could not find matching close tag for "'+line+'".')}}if(include=line.match(/^\s*include\s+(\S+)/)){opening=matches[index-1];if(opening&&(opening=="<"+d||opening=="<"+d+"-")){includeOpts=utils.shallowCopy({},self.opts);includeSrc=includeSource(include[1],includeOpts);includeSrc=" ; (function(){"+"\n"+includeSrc+" ; })()"+"\n";self.source+=includeSrc;self.dependencies.push(exports.resolveInclude(include[1],includeOpts.filename));return}}self.scanLine(line)})}},parseTemplateText:function(){var str=this.templateText,pat=this.regex,result=pat.exec(str),arr=[],firstPos,lastPos;while(result){firstPos=result.index;lastPos=pat.lastIndex;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},scanLine:function(line){var self=this,d=this.opts.delimiter,newLineCount=0;function _addOutput(){if(self.truncate){line=line.replace("\n","");self.truncate=false}else if(self.opts.rmWhitespace){line=line.replace(/^\n/,"")}if(!line){return}line=line.replace(/\\/g,"\\\\");line=line.replace(/\n/g,"\\n");line=line.replace(/\r/g,"\\r");line=line.replace(/"/g,'\\"');self.source+=' ; __append("'+line+'")'+"\n"}newLineCount=line.split("\n").length-1;switch(line){case"<"+d:this.mode=Template.modes.EVAL;break;case"<"+d+"=":this.mode=Template.modes.ESCAPED;break;case"<"+d+"-":this.mode=Template.modes.RAW;break;case"<"+d+"#":this.mode=Template.modes.COMMENT;break;case"<"+d+d:this.mode=Template.modes.LITERAL;this.source+=' ; __append("'+line.replace("<"+d+d,"<"+d)+'")'+"\n";break;case d+">":case"-"+d+">":if(this.mode==Template.modes.LITERAL){_addOutput()}this.mode=null;this.truncate=line.indexOf("-")===0;break;default:if(this.mode){switch(this.mode){case Template.modes.EVAL:case Template.modes.ESCAPED:case Template.modes.RAW:if(line.lastIndexOf("//")>line.lastIndexOf("\n")){line+="\n"}}switch(this.mode){case Template.modes.EVAL:this.source+=" ; "+line+"\n";break;case Template.modes.ESCAPED:this.source+=" ; __append(escape("+line.replace(_TRAILING_SEMCOL,"").trim()+"))"+"\n";break;case Template.modes.RAW:this.source+=" ; __append("+line.replace(_TRAILING_SEMCOL,"").trim()+")"+"\n";break;case Template.modes.COMMENT:break;case Template.modes.LITERAL:_addOutput();break}}else{_addOutput()}}if(self.opts.compileDebug&&newLineCount){this.currentLine+=newLineCount;this.source+=" ; __line = "+this.currentLine+"\n"}}};exports.__express=exports.renderFile;if(require.extensions){require.extensions[".ejs"]=function(module,filename){filename=filename||module.filename;var options={filename:filename,client:true},template=fs.readFileSync(filename).toString(),fn=exports.compile(template,options);module._compile("module.exports = "+fn.toString()+";",filename)}}exports.VERSION=_VERSION_STRING;if(typeof window!="undefined"){window.ejs=exports}},{"../package.json":6,"./utils":2,fs:3,path:4}],2:[function(require,module,exports){"use strict";var regExpChars=/[|\\{}()[\]^$+*?.]/g;exports.escapeRegExpChars=function(string){if(!string){return""}return String(string).replace(regExpChars,"\\$&")};var _ENCODE_HTML_RULES={"&":"&","<":"<",">":">",'"':""","'":"'"},_MATCH_HTML=/[&<>\'"]/g;function encode_char(c){return _ENCODE_HTML_RULES[c]||c}var escapeFuncStr="var _ENCODE_HTML_RULES = {\n"+' "&": "&"\n'+' , "<": "<"\n'+' , ">": ">"\n'+' , \'"\': """\n'+' , "\'": "'"\n'+" }\n"+" , _MATCH_HTML = /[&<>'\"]/g;\n"+"function encode_char(c) {\n"+" return _ENCODE_HTML_RULES[c] || c;\n"+"};\n";exports.escapeXML=function(markup){return markup==undefined?"":String(markup).replace(_MATCH_HTML,encode_char)};exports.escapeXML.toString=function(){return Function.prototype.toString.call(this)+";\n"+escapeFuncStr};exports.shallowCopy=function(to,from){from=from||{};for(var p in from){to[p]=from[p]}return to};exports.cache={_data:{},set:function(key,val){this._data[key]=val},get:function(key){return this._data[key]},reset:function(){this._data={}}}},{}],3:[function(require,module,exports){},{}],4:[function(require,module,exports){(function(process){function normalizeArray(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up--;up){parts.unshift("..")}}return parts}var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;var splitPath=function(filename){return splitPathRe.exec(filename).slice(1)};exports.resolve=function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:process.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){continue}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=normalizeArray(filter(resolvedPath.split("/"),function(p){return!!p}),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."};exports.normalize=function(path){var isAbsolute=exports.isAbsolute(path),trailingSlash=substr(path,-1)==="/";path=normalizeArray(filter(path.split("/"),function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path};exports.isAbsolute=function(path){return path.charAt(0)==="/"};exports.join=function(){var paths=Array.prototype.slice.call(arguments,0);return exports.normalize(filter(paths,function(p,index){if(typeof p!=="string"){throw new TypeError("Arguments to path.join must be strings")}return p}).join("/"))};exports.relative=function(from,to){from=exports.resolve(from).substr(1);to=exports.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i0){var fn=queue.shift();fn()}}},true);return function nextTick(fn){queue.push(fn);window.postMessage("process-tick","*")}}return function nextTick(fn){setTimeout(fn,0)}}();process.title="browser";process.browser=true;process.env={};process.argv=[];function noop(){}process.on=noop;process.addListener=noop;process.once=noop;process.off=noop;process.removeListener=noop;process.removeAllListeners=noop;process.emit=noop;process.binding=function(name){throw new Error("process.binding is not supported")};process.cwd=function(){return"/"};process.chdir=function(dir){throw new Error("process.chdir is not supported")}},{}],6:[function(require,module,exports){module.exports={name:"ejs",description:"Embedded JavaScript templates",keywords:["template","engine","ejs"],version:"2.3.2",author:"Matthew Eernisse (http://fleegix.org)",contributors:["Timothy Gu (https://timothygu.github.io)"],license:"Apache-2.0",main:"./lib/ejs.js",repository:{type:"git",url:"git://github.com/mde/ejs.git"},bugs:"https://github.com/mde/ejs/issues",homepage:"https://github.com/mde/ejs",dependencies:{},devDependencies:{browserify:"^8.0.3",istanbul:"~0.3.5",jake:"^8.0.0",jsdoc:"^3.3.0-beta1","lru-cache":"^2.5.0",mocha:"^2.1.0",rimraf:"^2.2.8","uglify-js":"^2.4.16"},engines:{node:">=0.10.0"},scripts:{test:"mocha",coverage:"istanbul cover node_modules/mocha/bin/_mocha",doc:"rimraf out && jsdoc -c jsdoc.json lib/* docs/jsdoc/*",devdoc:"rimraf out && jsdoc -p -c jsdoc.json lib/* docs/jsdoc/*"}}},{}]},{},[1]); \ No newline at end of file diff --git a/node_modules/ejs/lib/ejs.js b/node_modules/ejs/lib/ejs.js new file mode 100644 index 0000000..cfc0e85 --- /dev/null +++ b/node_modules/ejs/lib/ejs.js @@ -0,0 +1,717 @@ +/* + * 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'; + +/** + * @file Embedded JavaScript templating engine. + * @author Matthew Eernisse + * @author Tiancheng "Timothy" Gu + * @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 + */ + +var fs = require('fs') + , utils = require('./utils') + , scopeOptionWarned = false + , _VERSION_STRING = require('../package.json').version + , _DEFAULT_DELIMITER = '%' + , _DEFAULT_LOCALS_NAME = 'locals' + , _REGEX_STRING = '(<%%|<%=|<%-|<%#|<%|%>|-%>)' + , _OPTS = [ 'cache', 'filename', 'delimiter', 'scope', 'context' + , 'debug', 'compileDebug', 'client', '_with' + ] + , _TRAILING_SEMCOL = /;\s*$/ + , _BOM = /^\uFEFF/; + +/** + * 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} + */ + +exports.cache = utils.cache; + +/** + * Name of the object containing the locals. + * + * This variable is overriden by {@link Options}`.localsName` if it is not + * `undefined`. + * + * @type {String} + * @public + */ + +exports.localsName = _DEFAULT_LOCALS_NAME; + +/** + * 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 + * @return {String} + */ + +exports.resolveInclude = function(name, filename) { + var path = require('path') + , dirname = path.dirname + , extname = path.extname + , resolve = path.resolve + , includePath = resolve(dirname(filename), name) + , ext = extname(name); + if (!ext) { + includePath += '.ejs'; + } + 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|ClientFunction)} + * Depending on the value of `options.client`, either type might be returned. + * @static + */ + +function handleCache(options, template) { + var fn + , path = options.filename + , hasTemplate = arguments.length > 1; + + if (options.cache) { + if (!path) { + throw new Error('cache option requires a filename'); + } + fn = exports.cache.get(path); + if (fn) { + return fn; + } + if (!hasTemplate) { + template = fs.readFileSync(path).toString().replace(_BOM, ''); + } + } + else if (!hasTemplate) { + // istanbul ignore if: should not happen at all + if (!path) { + throw new Error('Internal EJS error: no file name or template ' + + 'provided'); + } + template = fs.readFileSync(path).toString().replace(_BOM, ''); + } + fn = exports.compile(template, options); + if (options.cache) { + exports.cache.set(path, fn); + } + return fn; +} + +/** + * 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|ClientFunction)} + * Depending on the value of `options.client`, either type might be returned + * @static + */ + +function includeFile(path, options) { + var opts = utils.shallowCopy({}, options); + if (!opts.filename) { + throw new Error('`include` requires the \'filename\' option.'); + } + opts.filename = exports.resolveInclude(path, opts.filename); + return handleCache(opts); +} + +/** + * Get the JavaScript source of an included file. + * + * @memberof module:ejs-internal + * @param {String} path path for the specified file + * @param {Options} options compilation options + * @return {String} + * @static + */ + +function includeSource(path, options) { + var opts = utils.shallowCopy({}, options) + , includePath + , template; + if (!opts.filename) { + throw new Error('`include` requires the \'filename\' option.'); + } + includePath = exports.resolveInclude(path, opts.filename); + template = fs.readFileSync(includePath).toString().replace(_BOM, ''); + + opts.filename = includePath; + var templ = new Template(template, opts); + templ.generateSource(); + return templ.source; +} + +/** + * 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} filename file name of the EJS file + * @param {String} lineno line number of the error + * @static + */ + +function rethrow(err, str, filename, lineno){ + var lines = str.split('\n') + , start = Math.max(lineno - 3, 0) + , end = Math.min(lines.length, lineno + 3); + + // 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; +} + +/** + * Copy properties in data object that are recognized as options to an + * options object. + * + * This is used for compatibility with earlier versions of EJS and Express.js. + * + * @memberof module:ejs-internal + * @param {Object} data data object + * @param {Options} opts options object + * @static + */ + +function cpOptsInData(data, opts) { + _OPTS.forEach(function (p) { + if (typeof data[p] != 'undefined') { + opts[p] = data[p]; + } + }); +} + +/** + * Compile the given `str` of ejs into a template function. + * + * @param {String} template EJS template + * + * @param {Options} opts compilation options + * + * @return {(TemplateFunction|ClientFunction)} + * Depending on the value of `opts.client`, either type might be returned. + * @public + */ + +exports.compile = function compile(template, opts) { + var templ; + + // v1 compat + // 'scope' is 'context' + // FIXME: Remove this in a future version + if (opts && opts.scope) { + if (!scopeOptionWarned){ + console.warn('`scope` option is deprecated and will be removed in EJS 3'); + scopeOptionWarned = true; + } + if (!opts.context) { + opts.context = opts.scope; + } + delete opts.scope; + } + templ = new Template(template, opts); + return templ.compile(); +}; + +/** + * 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} + * @public + */ + +exports.render = function (template, data, opts) { + data = data || {}; + opts = opts || {}; + var fn; + + // No options object -- if there are optiony names + // in the data, copy them to options + if (arguments.length == 2) { + cpOptsInData(data, opts); + } + + 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 + */ + +exports.renderFile = function () { + var args = Array.prototype.slice.call(arguments) + , path = args.shift() + , cb = args.pop() + , data = args.shift() || {} + , opts = args.pop() || {} + , result; + + // Don't pollute passed in opts obj with new vals + opts = utils.shallowCopy({}, opts); + + // No options object -- if there are optiony names + // in the data, copy them to options + if (arguments.length == 3) { + cpOptsInData(data, opts); + } + opts.filename = path; + + try { + result = handleCache(opts)(data); + } + catch(err) { + return cb(err); + } + return cb(null, result); +}; + +/** + * Clear intermediate JavaScript cache. Calls {@link Cache#reset}. + * @public + */ + +exports.clearCache = function () { + exports.cache.reset(); +}; + +function Template(text, opts) { + opts = opts || {}; + var options = {}; + this.templateText = text; + this.mode = null; + this.truncate = false; + this.currentLine = 1; + this.source = ''; + this.dependencies = []; + options.client = opts.client || false; + options.escapeFunction = opts.escape || utils.escapeXML; + options.compileDebug = opts.compileDebug !== false; + options.debug = !!opts.debug; + options.filename = opts.filename; + options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER; + options._with = typeof opts._with != 'undefined' ? opts._with : true; + options.context = opts.context; + options.cache = opts.cache || false; + options.rmWhitespace = opts.rmWhitespace; + 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 + , delim = utils.escapeRegExpChars(this.opts.delimiter); + str = str.replace(/%/g, delim); + return new RegExp(str); + } + +, compile: function () { + var src + , fn + , opts = this.opts + , prepended = '' + , appended = '' + , escape = opts.escapeFunction; + + if (opts.rmWhitespace) { + // Have to use two separate replace here as `^` and `$` operators don't + // work well with `\r`. + this.templateText = + this.templateText.replace(/\r/g, '').replace(/^\s+|\s+$/gm, ''); + } + + if (!this.source) { + this.generateSource(); + prepended += ' var __output = [], __append = __output.push.bind(__output);' + '\n'; + if (opts._with !== false) { + prepended += ' with (' + exports.localsName + ' || {}) {' + '\n'; + appended += ' }' + '\n'; + } + appended += ' return __output.join("");' + '\n'; + this.source = prepended + this.source + appended; + } + + if (opts.compileDebug) { + src = 'var __line = 1' + '\n' + + ' , __lines = ' + JSON.stringify(this.templateText) + '\n' + + ' , __filename = ' + (opts.filename ? + JSON.stringify(opts.filename) : 'undefined') + ';' + '\n' + + 'try {' + '\n' + + this.source + + '} catch (e) {' + '\n' + + ' rethrow(e, __lines, __filename, __line);' + '\n' + + '}' + '\n'; + } + else { + src = this.source; + } + + if (opts.debug) { + console.log(src); + } + + if (opts.client) { + src = 'escape = escape || ' + escape.toString() + ';' + '\n' + src; + if (opts.compileDebug) { + src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\n' + src; + } + } + + try { + fn = new Function(exports.localsName + ', escape, 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'; + } + throw e; + } + + if (opts.client) { + fn.dependencies = this.dependencies; + return fn; + } + + // 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 (data) { + var include = function (path, includeData) { + var d = utils.shallowCopy({}, data); + if (includeData) { + d = utils.shallowCopy(d, includeData); + } + return includeFile(path, opts)(d); + }; + return fn.apply(opts.context, [data || {}, escape, include, rethrow]); + }; + returnedFn.dependencies = this.dependencies; + return returnedFn; + } + +, generateSource: function () { + var self = this + , matches = this.parseTemplateText() + , d = this.opts.delimiter; + + if (matches && matches.length) { + matches.forEach(function (line, index) { + var opening + , closing + , include + , includeOpts + , includeSrc; + // 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 '<' + delimiter as key + // Then this can simply check against the map + if ( line.indexOf('<' + d) === 0 // If it is a tag + && line.indexOf('<' + d + d) !== 0) { // and is not escaped + closing = matches[index + 2]; + if (!(closing == d + '>' || closing == '-' + d + '>')) { + throw new Error('Could not find matching close tag for "' + line + '".'); + } + } + // HACK: backward-compat `include` preprocessor directives + if ((include = line.match(/^\s*include\s+(\S+)/))) { + opening = matches[index - 1]; + // Must be in EVAL or RAW mode + if (opening && (opening == '<' + d || opening == '<' + d + '-')) { + includeOpts = utils.shallowCopy({}, self.opts); + includeSrc = includeSource(include[1], includeOpts); + includeSrc = ' ; (function(){' + '\n' + includeSrc + + ' ; })()' + '\n'; + self.source += includeSrc; + self.dependencies.push(exports.resolveInclude(include[1], + includeOpts.filename)); + return; + } + } + self.scanLine(line); + }); + } + + } + +, parseTemplateText: function () { + var str = this.templateText + , pat = this.regex + , result = pat.exec(str) + , arr = [] + , firstPos + , lastPos; + + while (result) { + firstPos = result.index; + lastPos = pat.lastIndex; + + 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; + } + +, scanLine: function (line) { + var self = this + , d = this.opts.delimiter + , newLineCount = 0; + + function _addOutput() { + if (self.truncate) { + line = line.replace('\n', ''); + self.truncate = false; + } + else if (self.opts.rmWhitespace) { + // Gotta me more careful here. + // .replace(/^(\s*)\n/, '$1') might be more appropriate here but as + // rmWhitespace already removes trailing spaces anyway so meh. + line = line.replace(/^\n/, ''); + } + if (!line) { + return; + } + + // 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, '\\"'); + self.source += ' ; __append("' + line + '")' + '\n'; + } + + newLineCount = (line.split('\n').length - 1); + + switch (line) { + case '<' + d: + this.mode = Template.modes.EVAL; + break; + case '<' + d + '=': + this.mode = Template.modes.ESCAPED; + break; + case '<' + d + '-': + this.mode = Template.modes.RAW; + break; + case '<' + d + '#': + this.mode = Template.modes.COMMENT; + break; + case '<' + d + d: + this.mode = Template.modes.LITERAL; + this.source += ' ; __append("' + line.replace('<' + d + d, '<' + d) + '")' + '\n'; + break; + case d + '>': + case '-' + d + '>': + if (this.mode == Template.modes.LITERAL) { + _addOutput(); + } + + this.mode = null; + this.truncate = 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(escape(' + + line.replace(_TRAILING_SEMCOL, '').trim() + '))' + '\n'; + break; + // Exec and output + case Template.modes.RAW: + this.source += ' ; __append(' + + line.replace(_TRAILING_SEMCOL, '').trim() + ')' + '\n'; + break; + case Template.modes.COMMENT: + // Do nothing + break; + // Literal <%% mode, append as raw output + case Template.modes.LITERAL: + _addOutput(); + break; + } + } + // In string mode, just add the output + else { + _addOutput(); + } + } + + if (self.opts.compileDebug && newLineCount) { + this.currentLine += newLineCount; + this.source += ' ; __line = ' + this.currentLine + '\n'; + } + } +}; + +/** + * Express.js support. + * + * This is an alias for {@link module:ejs.renderFile}, in order to support + * Express.js out-of-the-box. + * + * @func + */ + +exports.__express = exports.renderFile; + +// Add require support +/* istanbul ignore else */ +if (require.extensions) { + require.extensions['.ejs'] = function (module, filename) { + filename = filename || /* istanbul ignore next */ module.filename; + var options = { + filename: filename + , client: true + } + , template = fs.readFileSync(filename).toString() + , fn = exports.compile(template, options); + module._compile('module.exports = ' + fn.toString() + ';', filename); + }; +} + +/** + * Version of EJS. + * + * @readonly + * @type {String} + * @public + */ + +exports.VERSION = _VERSION_STRING; + +/* istanbul ignore if */ +if (typeof window != 'undefined') { + window.ejs = exports; +} diff --git a/node_modules/ejs/lib/utils.js b/node_modules/ejs/lib/utils.js new file mode 100644 index 0000000..9e2c1d0 --- /dev/null +++ b/node_modules/ejs/lib/utils.js @@ -0,0 +1,141 @@ +/* + * 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'; + +var regExpChars = /[|\\{}()[\]^$+*?.]/g; + +/** + * 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 + */ +exports.escapeRegExpChars = function (string) { + // istanbul ignore if + if (!string) { + return ''; + } + return String(string).replace(regExpChars, '\\$&'); +}; + +var _ENCODE_HTML_RULES = { + '&': '&' + , '<': '<' + , '>': '>' + , '"': '"' + , "'": ''' + } + , _MATCH_HTML = /[&<>\'"]/g; + +function encode_char(c) { + return _ENCODE_HTML_RULES[c] || c; +}; + +/** + * Stringified version of constants used by {@link module:utils.escapeXML}. + * + * It is used in the process of generating {@link ClientFunction}s. + * + * @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 + */ + +exports.escapeXML = function (markup) { + return markup == undefined + ? '' + : String(markup) + .replace(_MATCH_HTML, encode_char); +}; +exports.escapeXML.toString = function () { + return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr +}; + +/** + * Copy all properties from one object to another, in a shallow fashion. + * + * @param {Object} to Destination object + * @param {Object} from Source object + * @return {Object} Destination object + * @static + * @private + */ +exports.shallowCopy = function (to, from) { + from = from || {}; + for (var p in from) { + to[p] = from[p]; + } + return to; +}; + +/** + * Simple in-process cache implementation. Does not implement limits of any + * sort. + * + * @implements Cache + * @static + * @private + */ +exports.cache = { + _data: {}, + set: function (key, val) { + this._data[key] = val; + }, + get: function (key) { + return this._data[key]; + }, + reset: function () { + this._data = {}; + } +}; + diff --git a/node_modules/ejs/package.json b/node_modules/ejs/package.json new file mode 100644 index 0000000..35845a7 --- /dev/null +++ b/node_modules/ejs/package.json @@ -0,0 +1,77 @@ +{ + "name": "ejs", + "description": "Embedded JavaScript templates", + "keywords": [ + "template", + "engine", + "ejs" + ], + "version": "2.3.3", + "author": { + "name": "Matthew Eernisse", + "email": "mde@fleegix.org", + "url": "http://fleegix.org" + }, + "contributors": [ + { + "name": "Timothy Gu", + "email": "timothygu99@gmail.com", + "url": "https://timothygu.github.io" + } + ], + "license": "Apache-2.0", + "main": "./lib/ejs.js", + "repository": { + "type": "git", + "url": "git://github.com/mde/ejs.git" + }, + "bugs": { + "url": "https://github.com/mde/ejs/issues" + }, + "homepage": "https://github.com/mde/ejs", + "dependencies": {}, + "devDependencies": { + "browserify": "^8.0.3", + "istanbul": "~0.3.5", + "jake": "^8.0.0", + "jsdoc": "^3.3.0-beta1", + "lru-cache": "^2.5.0", + "mocha": "^2.1.0", + "rimraf": "^2.2.8", + "uglify-js": "^2.4.16" + }, + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "test": "mocha", + "coverage": "istanbul cover node_modules/mocha/bin/_mocha", + "doc": "rimraf out && jsdoc -c jsdoc.json lib/* docs/jsdoc/*", + "devdoc": "rimraf out && jsdoc -p -c jsdoc.json lib/* docs/jsdoc/*" + }, + "_id": "ejs@2.3.3", + "_shasum": "a6babb67815d7190694af4ba82fe065e56d5f0e7", + "_resolved": "https://registry.npmjs.org/ejs/-/ejs-2.3.3.tgz", + "_from": "ejs@*", + "_npmVersion": "2.1.11", + "_nodeVersion": "0.10.33", + "_npmUser": { + "name": "mde", + "email": "mde@fleegix.org" + }, + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + { + "name": "mde", + "email": "mde@fleegix.org" + } + ], + "dist": { + "shasum": "a6babb67815d7190694af4ba82fe065e56d5f0e7", + "tarball": "http://registry.npmjs.org/ejs/-/ejs-2.3.3.tgz" + }, + "directories": {} +} diff --git a/node_modules/ejs/test/ejs.js b/node_modules/ejs/test/ejs.js new file mode 100644 index 0000000..ddea6e7 --- /dev/null +++ b/node_modules/ejs/test/ejs.js @@ -0,0 +1,859 @@ +/* jshint mocha: true */ + +/** + * Module dependencies. + */ + +var ejs = require('..') + , fs = require('fs') + , read = fs.readFileSync + , assert = require('assert') + , path = require('path') + , LRU = require('lru-cache'); + +try { + fs.mkdirSync(__dirname + '/tmp'); +} catch (ex) { + if (ex.code !== 'EEXIST') { + throw ex; + } +} + +// From https://gist.github.com/pguillory/729616 +function hook_stdio(stream, callback) { + var old_write = stream.write; + + stream.write = (function() { + return function(string, encoding, fd) { + callback(string, encoding, fd); + }; + })(stream.write); + + return function() { + stream.write = old_write; + }; +} + +/** + * Load fixture `name`. + */ + +function fixture(name) { + return read('test/fixtures/' + name, 'utf8'); +} + +/** + * User fixtures. + */ + +var users = []; +users.push({name: 'geddy'}); +users.push({name: 'neil'}); +users.push({name: 'alex'}); + +suite('ejs.compile(str, options)', function () { + test('compile to a function', function () { + var fn = ejs.compile('

yay

'); + assert.equal(fn(), '

yay

'); + }); + + test('empty input works', function () { + var fn = ejs.compile(''); + assert.equal(fn(), ''); + }); + + test('throw if there are syntax errors', function () { + try { + ejs.compile(fixture('fail.ejs')); + } + catch (err) { + assert.ok(err.message.indexOf('compiling ejs') > -1); + + try { + ejs.compile(fixture('fail.ejs'), {filename: 'fail.ejs'}); + } + catch (err) { + assert.ok(err.message.indexOf('fail.ejs') > -1); + return; + } + } + throw new Error('no error reported when there should be'); + }); + + test('allow customizing delimiter local var', function () { + var fn; + fn = ejs.compile('

', {delimiter: '?'}); + assert.equal(fn({name: 'geddy'}), '

geddy

'); + + fn = ejs.compile('

<:= name :>

', {delimiter: ':'}); + assert.equal(fn({name: 'geddy'}), '

geddy

'); + + fn = ejs.compile('

<$= name $>

', {delimiter: '$'}); + assert.equal(fn({name: 'geddy'}), '

geddy

'); + }); + + test('default to using ejs.delimiter', function () { + var fn; + ejs.delimiter = '&'; + fn = ejs.compile('

<&= name &>

'); + assert.equal(fn({name: 'geddy'}), '

geddy

'); + + fn = ejs.compile('

<|= name |>

', {delimiter: '|'}); + assert.equal(fn({name: 'geddy'}), '

geddy

'); + delete ejs.delimiter; + }); + + test('have a working client option', function () { + var fn + , str + , preFn; + fn = ejs.compile('

<%= foo %>

', {client: true}); + str = fn.toString(); + if (!process.env.running_under_istanbul) { + eval('var preFn = ' + str); + assert.equal(preFn({foo: 'bar'}), '

bar

'); + } + }); + + test('support client mode without locals', function () { + var fn + , str + , preFn; + fn = ejs.compile('

<%= "foo" %>

', {client: true}); + str = fn.toString(); + if (!process.env.running_under_istanbul) { + eval('var preFn = ' + str); + assert.equal(preFn(), '

foo

'); + } + }); + + test('not include rethrow() in client mode if compileDebug is false', function () { + var fn = ejs.compile('

<%= "foo" %>

', { + client: true + , compileDebug: false + }); + // There could be a `rethrow` in the function declaration + assert((fn.toString().match(/rethrow/g) || []).length <= 1); + }); +}); + +suite('ejs.render(str, data, opts)', function () { + test('render the template', function () { + assert.equal(ejs.render('

yay

'), '

yay

'); + }); + + test('empty input works', function () { + assert.equal(ejs.render(''), ''); + }); + + test('undefined renders nothing escaped', function () { + assert.equal(ejs.render('<%= undefined %>'), ''); + }); + + test('undefined renders nothing raw', function () { + assert.equal(ejs.render('<%- undefined %>'), ''); + }); + + test('null renders nothing escaped', function () { + assert.equal(ejs.render('<%= null %>'), ''); + }); + + test('null renders nothing raw', function () { + assert.equal(ejs.render('<%- null %>'), ''); + }); + + test('zero-value data item renders something escaped', function () { + assert.equal(ejs.render('<%= 0 %>'), '0'); + }); + + test('zero-value data object renders something raw', function () { + assert.equal(ejs.render('<%- 0 %>'), '0'); + }); + + test('accept locals', function () { + assert.equal(ejs.render('

<%= name %>

', {name: 'geddy'}), + '

geddy

'); + }); + + test('accept locals without using with() {}', function () { + assert.equal(ejs.render('

<%= locals.name %>

', {name: 'geddy'}, + {_with: false}), + '

geddy

'); + assert.throws(function() { + ejs.render('

<%= name %>

', {name: 'geddy'}, + {_with: false}); + }, /name is not defined/); + }); + + test('accept custom name for locals', function () { + ejs.localsName = 'it'; + assert.equal(ejs.render('

<%= it.name %>

', {name: 'geddy'}, + {_with: false}), + '

geddy

'); + assert.throws(function() { + ejs.render('

<%= name %>

', {name: 'geddy'}, + {_with: false}); + }, /name is not defined/); + ejs.localsName = 'locals'; + }); + + test('support caching', function () { + var file = __dirname + '/tmp/render.ejs' + , options = {cache: true, filename: file} + , out = ejs.render('

Old

', {}, options) + , expected = '

Old

'; + assert.equal(out, expected); + // Assert no change, still in cache + out = ejs.render('

New

', {}, options); + assert.equal(out, expected); + }); + + test('support LRU caching', function () { + var oldCache = ejs.cache + , file = __dirname + '/tmp/render.ejs' + , options = {cache: true, filename: file} + , out + , expected = '

Old

'; + + // Switch to LRU + ejs.cache = LRU(); + + out = ejs.render('

Old

', {}, options); + assert.equal(out, expected); + // Assert no change, still in cache + out = ejs.render('

New

', {}, options); + assert.equal(out, expected); + + // Restore system cache + ejs.cache = oldCache; + }); + + test('opts.context', function () { + var ctxt = {foo: 'FOO'} + , out = ejs.render('<%= this.foo %>', {}, {context: ctxt}); + assert.equal(out, ctxt.foo); + }); +}); + +suite('ejs.renderFile(path, [data], [options], fn)', function () { + test('render a file', function(done) { + ejs.renderFile('test/fixtures/para.ejs', function(err, html) { + if (err) { + return done(err); + } + assert.equal(html, '

hey

\n'); + done(); + }); + }); + + test('accept locals', function(done) { + var data = {name: 'fonebone'} + , options = {delimiter: '$'}; + ejs.renderFile('test/fixtures/user.ejs', data, options, function(err, html) { + if (err) { + return done(err); + } + assert.equal(html, '

fonebone

\n'); + done(); + }); + }); + + test('accept locals without using with() {}', function(done) { + var data = {name: 'fonebone'} + , options = {delimiter: '$', _with: false} + , doneCount = 0; + ejs.renderFile('test/fixtures/user-no-with.ejs', data, options, + function(err, html) { + if (err) { + if (doneCount === 2) { + return; + } + doneCount = 2; + return done(err); + } + assert.equal(html, '

fonebone

\n'); + doneCount++; + if (doneCount === 2) { + done(); + } + }); + ejs.renderFile('test/fixtures/user.ejs', data, options, function(err) { + if (!err) { + if (doneCount === 2) { + return; + } + doneCount = 2; + return done(new Error('error not thrown')); + } + doneCount++; + if (doneCount === 2) { + done(); + } + }); + }); + + test('not catch err thrown by callback', function(done) { + var data = {name: 'fonebone'} + , options = {delimiter: '$'} + , counter = 0; + + var d = require('domain').create(); + d.on('error', function (err) { + assert.equal(counter, 1); + assert.equal(err.message, 'Exception in callback'); + done(); + }); + d.run(function () { + // process.nextTick() needed to work around mochajs/mocha#513 + // + // tl;dr: mocha doesn't support synchronous exception throwing in + // domains. Have to make it async. Ticket closed because: "domains are + // deprecated :D" + process.nextTick(function () { + ejs.renderFile('test/fixtures/user.ejs', data, options, + function(err) { + counter++; + if (err) { + assert.notEqual(err.message, 'Exception in callback'); + return done(err); + } + throw new Error('Exception in callback'); + }); + }); + }); + }); + + test('support caching', function (done) { + var expected = '

Old

' + , file = __dirname + '/tmp/renderFile.ejs' + , options = {cache: true}; + fs.writeFileSync(file, '

Old

'); + + ejs.renderFile(file, {}, options, function (err, out) { + if (err) { + done(err); + } + fs.writeFileSync(file, '

New

'); + assert.equal(out, expected); + + ejs.renderFile(file, {}, options, function (err, out) { + if (err) { + done(err); + } + // Assert no change, still in cache + assert.equal(out, expected); + done(); + }); + }); + }); + + test('opts.context', function (done) { + var ctxt = {foo: 'FOO'}; + ejs.renderFile('test/fixtures/with-context.ejs', {}, + {context: ctxt}, function(err, html) { + if (err) { + return done(err); + } + assert.equal(html, ctxt.foo + '\n'); + done(); + }); + + }); +}); + +suite('cache specific', function () { + test('`clearCache` work properly', function () { + var expected = '

Old

' + , file = __dirname + '/tmp/clearCache.ejs' + , options = {cache: true, filename: file} + , out = ejs.render('

Old

', {}, options); + assert.equal(out, expected); + + ejs.clearCache(); + + expected = '

New

'; + out = ejs.render('

New

', {}, options); + assert.equal(out, expected); + }); + + test('`clearCache` work properly, LRU', function () { + var expected = '

Old

' + , oldCache = ejs.cache + , file = __dirname + '/tmp/clearCache.ejs' + , options = {cache: true, filename: file} + , out; + + ejs.cache = LRU(); + + out = ejs.render('

Old

', {}, options); + assert.equal(out, expected); + ejs.clearCache(); + expected = '

New

'; + out = ejs.render('

New

', {}, options); + assert.equal(out, expected); + + ejs.cache = oldCache; + }); + + test('LRU with cache-size 1', function () { + var oldCache = ejs.cache + , options + , out + , expected + , file; + + ejs.cache = LRU(1); + + file = __dirname + '/tmp/render1.ejs'; + options = {cache: true, filename: file}; + out = ejs.render('

File1

', {}, options); + expected = '

File1

'; + assert.equal(out, expected); + + // Same filename, different template, but output + // should be the same because cache + file = __dirname + '/tmp/render1.ejs'; + options = {cache: true, filename: file}; + out = ejs.render('

ChangedFile1

', {}, options); + expected = '

File1

'; + assert.equal(out, expected); + + // Different filiename -- output should be different, + // and previous cache-entry should be evicted + file = __dirname + '/tmp/render2.ejs'; + options = {cache: true, filename: file}; + out = ejs.render('

File2

', {}, options); + expected = '

File2

'; + assert.equal(out, expected); + + // Entry with first filename should now be out of cache, + // results should be different + file = __dirname + '/tmp/render1.ejs'; + options = {cache: true, filename: file}; + out = ejs.render('

ChangedFile1

', {}, options); + expected = '

ChangedFile1

'; + assert.equal(out, expected); + + ejs.cache = oldCache; + }); +}); + +suite('<%', function () { + test('without semicolons', function () { + assert.equal(ejs.render(fixture('no.semicolons.ejs')), + fixture('no.semicolons.html')); + }); +}); + +suite('<%=', function () { + test('escape & - - - - - - - - - - - - - -
- -

jquery.timepicker

-

- A lightweight, customizable javascript timepicker plugin for jQuery inspired by Google Calendar. -

- - -
- -
-

Use this plugin to unobtrusively add a timepicker dropdown to your forms. It's lightweight (2.7kb minified and gzipped) and easy to customize.

-
- -
-
-
-

Basic Example

-

-
- - - -
$('#basicExample').timepicker();
-
- - -
-
-

Scroll Default Example

-

Set the scroll position to local time if no value selected.

-

-
- - - -
$('#scrollDefaultExample').timepicker({ 'scrollDefault': 'now' });
-
- -
-
-

Set Time Example

-

Dynamically set the time using a Javascript Date object.

-

- - -

-
- - - -
$('#setTimeExample').timepicker();
-$('#setTimeButton').on('click', function (){
-    $('#setTimeExample').timepicker('setTime', new Date());
-});
-
- -
-
-

Duration Example

-

Set a starting time and see duration from that starting time. You can optionally set an maxTime as well.

-

-
- - - -
$('#durationExample').timepicker({
-    'minTime': '2:00pm',
-    'maxTime': '11:30pm',
-    'showDuration': true
-});
-
- -
-
-

Event Example

-

Trigger an event after selecting a value. Fires before the input onchange event.

-

- - -

-
- - - -
$('#onselectExample').timepicker();
-$('#onselectExample').on('changeTime', function() {
-    $('#onselectTarget').text($(this).val());
-});
-
- -
-
-

DisableTimeRanges Example

-

Prevent selection of certain time values.

-

-
- - - -
$('#disableTimeRangesExample').timepicker({
-    'disableTimeRanges': [
-        ['1am', '2am'],
-        ['3am', '4:01am']
-    ]
-});
-
- -
-
-

noneOption Example

-

Custom options can be added to the dropdown menu.

-

-
- - - -
-$('#noneOptionExample').timepicker({
-    'noneOption': [
-        {
-            'label': 'Foobar',
-            'className': 'shibby',
-            'value': '42'
-        },
-        'Foobar2'
-    ]
-});
-        
-
- -
-
-

timeFormat Example

-

timepicker.jquery uses the time portion of PHP's date formatting commands.

-

-
- - - -
$('#timeformatExample1').timepicker({ 'timeFormat': 'H:i:s' });
-$('#timeformatExample2').timepicker({ 'timeFormat': 'h:i A' });
-
- -
-
-

Step Example

-

Generate drop-down options with varying levels of precision.

-

-
- - - -
$('#stepExample1').timepicker({ 'step': 15 });
-$('#stepExample2').timepicker({
-    'step': function(i) {
-        return (i%2) ? 15 : 45;
-    }
-});
-
- -
-
-

forceRoundTime Example

-

jquery-timepicker allows entering times via the keyboard. Setting forceRoundTime to true will - round the entered time to the nearest option on the dropdown list.

-

-
- - - -
$('#roundTimeExample').timepicker({ 'forceRoundTime': true });
-
- -
-
-

Select Example

-

jquery-timepicker can render itself as a select element too.

-

-
- - - -
$('#selectExample').timepicker();
-$('#selectButton').click(function(e) {
-  $('#selectExample').timepicker('option', { useSelect: true });
-  $(this).hide();
-});
-
- -
-
-

Non-input Example

-

jquery-timepicker can be bound to any visibile DOM element, such as spans or divs.

-

-
- - - -
$('#spanExample').timepicker();
-    $('#openSpanExample').on('click', function(){
-    $('#spanExample').timepicker('show');
-});
-
- -
-
-

Datepair Plugin Example

- -

jquery-timepicker is designed to work with the jquery-datepair plugin. - -

- - to - - -

-
- - - - - -
-<p id="datepairExample">
-    <input type="text" class="date start" />
-    <input type="text" class="time start" /> to
-    <input type="text" class="time end" />
-    <input type="text" class="date end" />
-</p>
-
-<script type="text/javascript" src="datepair.js"></script>
-<script type="text/javascript" src="jquery.datepair.js"></script>
-<script>
-    // initialize input widgets first
-    $('#datepairExample .time').timepicker({
-        'showDuration': true,
-        'timeFormat': 'g:ia'
-    });
-
-    $('#datepairExample .date').datepicker({
-        'format': 'yyyy-m-d',
-        'autoclose': true
-    });
-
-    // initialize datepair
-    $('#datepairExample').datepair();
-</script>
- -
-
- -
-

Need Help?

-

Check the documentation or submit an issue on GitHub.

-
- - - - - - diff --git a/public/jquery-timepicker/jquery.timepicker.css b/public/jquery-timepicker/jquery.timepicker.css deleted file mode 100755 index cd75f13..0000000 --- a/public/jquery-timepicker/jquery.timepicker.css +++ /dev/null @@ -1,72 +0,0 @@ -.ui-timepicker-wrapper { - overflow-y: auto; - height: 150px; - width: 6.5em; - background: #fff; - border: 1px solid #ddd; - -webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2); - -moz-box-shadow:0 5px 10px rgba(0,0,0,0.2); - box-shadow:0 5px 10px rgba(0,0,0,0.2); - outline: none; - z-index: 10001; - margin: 0; -} - -.ui-timepicker-wrapper.ui-timepicker-with-duration { - width: 13em; -} - -.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-30, -.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-60 { - width: 11em; -} - -.ui-timepicker-list { - margin: 0; - padding: 0; - list-style: none; -} - -.ui-timepicker-duration { - margin-left: 5px; color: #888; -} - -.ui-timepicker-list:hover .ui-timepicker-duration { - color: #888; -} - -.ui-timepicker-list li { - padding: 3px 0 3px 5px; - cursor: pointer; - white-space: nowrap; - color: #000; - list-style: none; - margin: 0; -} - -.ui-timepicker-list:hover .ui-timepicker-selected { - background: #fff; color: #000; -} - -li.ui-timepicker-selected, -.ui-timepicker-list li:hover, -.ui-timepicker-list .ui-timepicker-selected:hover { - background: #1980EC; color: #fff; -} - -li.ui-timepicker-selected .ui-timepicker-duration, -.ui-timepicker-list li:hover .ui-timepicker-duration { - color: #ccc; -} - -.ui-timepicker-list li.ui-timepicker-disabled, -.ui-timepicker-list li.ui-timepicker-disabled:hover, -.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled { - color: #888; - cursor: default; -} - -.ui-timepicker-list li.ui-timepicker-disabled:hover, -.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled { - background: #f2f2f2; -} diff --git a/public/jquery-timepicker/jquery.timepicker.js b/public/jquery-timepicker/jquery.timepicker.js deleted file mode 100644 index cadde08..0000000 --- a/public/jquery-timepicker/jquery.timepicker.js +++ /dev/null @@ -1,1195 +0,0 @@ -/*! - * jquery-timepicker v1.8.0 - A jQuery timepicker plugin inspired by Google Calendar. It supports both mouse and keyboard navigation. - * Copyright (c) 2015 Jon Thornton - http://jonthornton.github.com/jquery-timepicker/ - * License: MIT - */ - - -(function (factory) { - if (typeof exports === "object" && exports && - typeof module === "object" && module && module.exports === exports) { - // Browserify. Attach to jQuery module. - factory(require("jquery")); - } else if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define(['jquery'], factory); - } else { - // Browser globals - factory(jQuery); - } -}(function ($) { - var _baseDate = _generateBaseDate(); - var _ONE_DAY = 86400; - var _lang = { - am: 'am', - pm: 'pm', - AM: 'AM', - PM: 'PM', - decimal: '.', - mins: 'mins', - hr: 'hr', - hrs: 'hrs' - }; - - var methods = { - init: function(options) - { - return this.each(function() - { - var self = $(this); - - // pick up settings from data attributes - var attributeOptions = []; - for (var key in $.fn.timepicker.defaults) { - if (self.data(key)) { - attributeOptions[key] = self.data(key); - } - } - - var settings = $.extend({}, $.fn.timepicker.defaults, attributeOptions, options); - - if (settings.lang) { - _lang = $.extend(_lang, settings.lang); - } - - settings = _parseSettings(settings); - self.data('timepicker-settings', settings); - self.addClass('ui-timepicker-input'); - - if (settings.useSelect) { - _render(self); - } else { - self.prop('autocomplete', 'off'); - self.on('click.timepicker focus.timepicker', methods.show); - self.on('change.timepicker', _formatValue); - self.on('keydown.timepicker', _keydownhandler); - self.on('keyup.timepicker', _keyuphandler); - if (settings.disableTextInput) { - self.on('keypress.timepicker', function(e) { e.preventDefault(); }); - } - - _formatValue.call(self.get(0)); - } - }); - }, - - show: function(e) - { - var self = $(this); - var settings = self.data('timepicker-settings'); - - if (e) { - if (settings.showOn !== e.type) { - return true; - } - - e.preventDefault(); - } - - if (settings.useSelect) { - self.data('timepicker-list').focus(); - return; - } - - if (_hideKeyboard(self)) { - // block the keyboard on mobile devices - self.blur(); - } - - var list = self.data('timepicker-list'); - - // check if input is readonly - if (self.prop('readonly')) { - return; - } - - // check if list needs to be rendered - if (!list || list.length === 0 || typeof settings.durationTime === 'function') { - _render(self); - list = self.data('timepicker-list'); - } - - if (_isVisible(list)) { - return; - } - - self.data('ui-timepicker-value', self.val()); - _setSelected(self, list); - - // make sure other pickers are hidden - methods.hide(); - - // position the dropdown relative to the input - list.show(); - var listOffset = {}; - - if (settings.orientation.match(/r/)) { - // right-align the dropdown - listOffset.left = self.offset().left + self.outerWidth() - list.outerWidth() + parseInt(list.css('marginLeft').replace('px', ''), 10); - } else { - // left-align the dropdown - listOffset.left = self.offset().left + parseInt(list.css('marginLeft').replace('px', ''), 10); - } - - var verticalOrientation; - if (settings.orientation.match(/t/)) { - verticalOrientation = 't'; - } else if (settings.orientation.match(/b/)) { - verticalOrientation = 'b'; - } else if ((self.offset().top + self.outerHeight(true) + list.outerHeight()) > $(window).height() + $(window).scrollTop()) { - verticalOrientation = 't'; - } else { - verticalOrientation = 'b'; - } - - if (verticalOrientation == 't') { - // position the dropdown on top - list.addClass('ui-timepicker-positioned-top'); - listOffset.top = self.offset().top - list.outerHeight() + parseInt(list.css('marginTop').replace('px', ''), 10); - } else { - // put it under the input - list.removeClass('ui-timepicker-positioned-top'); - listOffset.top = self.offset().top + self.outerHeight() + parseInt(list.css('marginTop').replace('px', ''), 10); - } - - list.offset(listOffset); - - // position scrolling - var selected = list.find('.ui-timepicker-selected'); - - if (!selected.length) { - if (_getTimeValue(self)) { - selected = _findRow(self, list, _time2int(_getTimeValue(self))); - } else if (settings.scrollDefault) { - selected = _findRow(self, list, settings.scrollDefault()); - } - } - - if (selected && selected.length) { - var topOffset = list.scrollTop() + selected.position().top - selected.outerHeight(); - list.scrollTop(topOffset); - } else { - list.scrollTop(0); - } - - // prevent scroll propagation - if(settings.stopScrollPropagation) { - $(document).on('wheel.ui-timepicker', '.ui-timepicker-wrapper', function(e){ - e.preventDefault(); - var currentScroll = $(this).scrollTop(); - $(this).scrollTop(currentScroll + e.originalEvent.deltaY); - }); - } - - // attach close handlers - $(document).on('touchstart.ui-timepicker mousedown.ui-timepicker', _closeHandler); - $(window).on('resize.ui-timepicker', _closeHandler); - if (settings.closeOnWindowScroll) { - $(document).on('scroll.ui-timepicker', _closeHandler); - } - - self.trigger('showTimepicker'); - - return this; - }, - - hide: function(e) - { - var self = $(this); - var settings = self.data('timepicker-settings'); - - if (settings && settings.useSelect) { - self.blur(); - } - - $('.ui-timepicker-wrapper').each(function() { - var list = $(this); - if (!_isVisible(list)) { - return; - } - - var self = list.data('timepicker-input'); - var settings = self.data('timepicker-settings'); - - if (settings && settings.selectOnBlur) { - _selectValue(self); - } - - list.hide(); - self.trigger('hideTimepicker'); - }); - - return this; - }, - - option: function(key, value) - { - return this.each(function(){ - var self = $(this); - var settings = self.data('timepicker-settings'); - var list = self.data('timepicker-list'); - - if (typeof key == 'object') { - settings = $.extend(settings, key); - - } else if (typeof key == 'string' && typeof value != 'undefined') { - settings[key] = value; - - } else if (typeof key == 'string') { - return settings[key]; - } - - settings = _parseSettings(settings); - - self.data('timepicker-settings', settings); - - if (list) { - list.remove(); - self.data('timepicker-list', false); - } - - if (settings.useSelect) { - _render(self); - } - }); - }, - - getSecondsFromMidnight: function() - { - return _time2int(_getTimeValue(this)); - }, - - getTime: function(relative_date) - { - var self = this; - - var time_string = _getTimeValue(self); - if (!time_string) { - return null; - } - - var offset = _time2int(time_string); - if (offset === null) { - return null; - } - - if (!relative_date) { - relative_date = new Date(); - } - - // construct a Date with today's date, and offset's time - var time = new Date(relative_date); - time.setHours(offset / 3600); - time.setMinutes(offset % 3600 / 60); - time.setSeconds(offset % 60); - time.setMilliseconds(0); - - return time; - }, - - setTime: function(value) - { - var self = this; - var settings = self.data('timepicker-settings'); - - if (settings.forceRoundTime) { - var prettyTime = _roundAndFormatTime(_time2int(value), settings) - } else { - var prettyTime = _int2time(_time2int(value), settings); - } - - if (value && prettyTime === null && settings.noneOption) { - prettyTime = value; - } - - _setTimeValue(self, prettyTime); - if (self.data('timepicker-list')) { - _setSelected(self, self.data('timepicker-list')); - } - - return this; - }, - - remove: function() - { - var self = this; - - // check if this element is a timepicker - if (!self.hasClass('ui-timepicker-input')) { - return; - } - - var settings = self.data('timepicker-settings'); - self.removeAttr('autocomplete', 'off'); - self.removeClass('ui-timepicker-input'); - self.removeData('timepicker-settings'); - self.off('.timepicker'); - - // timepicker-list won't be present unless the user has interacted with this timepicker - if (self.data('timepicker-list')) { - self.data('timepicker-list').remove(); - } - - if (settings.useSelect) { - self.show(); - } - - self.removeData('timepicker-list'); - - return this; - } - }; - - // private methods - - function _isVisible(elem) - { - var el = elem[0]; - return el.offsetWidth > 0 && el.offsetHeight > 0; - } - - function _parseSettings(settings) - { - if (settings.minTime) { - settings.minTime = _time2int(settings.minTime); - } - - if (settings.maxTime) { - settings.maxTime = _time2int(settings.maxTime); - } - - if (settings.durationTime && typeof settings.durationTime !== 'function') { - settings.durationTime = _time2int(settings.durationTime); - } - - if (settings.scrollDefault == 'now') { - settings.scrollDefault = function() { - return settings.roundingFunction(_time2int(new Date()), settings); - } - } else if (settings.scrollDefault && typeof settings.scrollDefault != 'function') { - var val = settings.scrollDefault; - settings.scrollDefault = function() { - return settings.roundingFunction(_time2int(val), settings); - } - } else if (settings.minTime) { - settings.scrollDefault = function() { - return settings.roundingFunction(settings.minTime, settings); - } - } - - if ($.type(settings.timeFormat) === "string" && settings.timeFormat.match(/[gh]/)) { - settings._twelveHourTime = true; - } - - if (settings.showOnFocus === false && settings.showOn == 'focus') { - settings.showOn = null - } - - if (settings.disableTimeRanges.length > 0) { - // convert string times to integers - for (var i in settings.disableTimeRanges) { - settings.disableTimeRanges[i] = [ - _time2int(settings.disableTimeRanges[i][0]), - _time2int(settings.disableTimeRanges[i][1]) - ]; - } - - // sort by starting time - settings.disableTimeRanges = settings.disableTimeRanges.sort(function(a, b){ - return a[0] - b[0]; - }); - - // merge any overlapping ranges - for (var i = settings.disableTimeRanges.length-1; i > 0; i--) { - if (settings.disableTimeRanges[i][0] <= settings.disableTimeRanges[i-1][1]) { - settings.disableTimeRanges[i-1] = [ - Math.min(settings.disableTimeRanges[i][0], settings.disableTimeRanges[i-1][0]), - Math.max(settings.disableTimeRanges[i][1], settings.disableTimeRanges[i-1][1]) - ]; - settings.disableTimeRanges.splice(i, 1); - } - } - } - - return settings; - } - - function _render(self) - { - var settings = self.data('timepicker-settings'); - var list = self.data('timepicker-list'); - - if (list && list.length) { - list.remove(); - self.data('timepicker-list', false); - } - - if (settings.useSelect) { - list = $('",{"class":"ui-timepicker-select"});var g=d}else{d=a("
    ",{"class":"ui-timepicker-list"});var g=a("
    ",{"class":"ui-timepicker-wrapper",tabindex:-1});g.css({display:"none",position:"absolute"}).append(d)}if(c.noneOption)if(c.noneOption===!0&&(c.noneOption=c.useSelect?"Time...":"None"),a.isArray(c.noneOption)){for(var h in c.noneOption)if(parseInt(h,10)==h){var j=e(c.noneOption[h],c.useSelect);d.append(j)}}else{var j=e(c.noneOption,c.useSelect);d.append(j)}if(c.className&&g.addClass(c.className),(null!==c.minTime||null!==c.durationTime)&&c.showDuration){{"function"==typeof c.step?"function":c.step}g.addClass("ui-timepicker-with-duration"),g.addClass("ui-timepicker-step-"+c.step)}var l=c.minTime;"function"==typeof c.durationTime?l=t(c.durationTime()):null!==c.durationTime&&(l=c.durationTime);var m=null!==c.minTime?c.minTime:0,o=null!==c.maxTime?c.maxTime:m+v-1;m>o&&(o+=v),o===v-1&&"string"===a.type(c.timeFormat)&&c.show2400&&(o=v);var p=c.disableTimeRanges,u=0,w=p.length,y=c.step;"function"!=typeof y&&(y=function(){return c.step});for(var h=m,z=0;o>=h;z++,h+=60*y(z)){var A=h,B=s(A,c);if(c.useSelect){var C=a("