From d04fcb720a3d5fb7c4adeb250e9d9339384bb550 Mon Sep 17 00:00:00 2001 From: John Boehr Date: Thu, 30 Apr 2020 19:10:11 -0700 Subject: [PATCH] Update to handlebars v4.7.6 Currently using using my fork: https://github.com/jbboehr/handlebars.js/tree/remove-equals-4.x Awaiting PR: https://github.com/handlebars-lang/handlebars.js/pull/1683 * Rewrote everything in TypeScript * Switched the license to `AGPL-3.0-or-later`. The specification data is still licensed under the `MIT` license, as it is extracted from `handlebars.js` * `description` now includes all `describe($description, ...)` from the handlebars test suite * `exception` can now be either `true`, a string, or a regex. * `message` used to be the exception message, but will now be any extra message noted in the handlebars.js test suite * `options` was renamed to `runtimeOptions` to differentiate from `compileOptions` * Using a new version format `104.7.6` which is: `(myMajor * 100 + handlebarsMajor) + '.' + (myMinor * 100 + handlebarsMinor) + '.' + (myPatch * 100 + handlebarsPatch)` * `number` is now included in tests (besides the first implied `00`) that have multiple cases * `compat` is removed in favor of `compileOptions.compat` * `globalPartials`, `globalDecorators`, and `globalHelpers` are now removed and merged into `partials`, `decorators`, and `helpers` instead Closes #7 --- .editorconfig | 8 + .eslintignore | 5 + .eslintrc.json | 65 + .gitattributes | 6 + .gitignore | 1 + .gitmodules | 2 +- .jshintrc | 22 - .travis.yml | 25 +- CHANGELOG.md | 26 + LICENSE.md | 800 ++++++++-- Makefile | 47 +- README.md | 5 +- bin/eval.js | 17 - bin/export.js | 107 -- bin/index.js | 652 -------- bin/lint.php | 28 +- bin/runner.js | 337 ----- bin/stubs.php | 34 +- ci.nix | 39 + composer.json | 4 +- default.nix | 15 + derivation.nix | 23 +- handlebars.js | 2 +- package-lock.json | 2387 ++++++++++++++++++++++++++++++ package.json | 65 +- patch/_functions.hjson | 2359 +++++++++++++++++++++++++++++ patch/basic.json | 153 +- patch/bench.json | 26 - patch/blocks.json | 112 +- patch/builtins.json | 151 +- patch/data.json | 145 +- patch/helpers.json | 864 +---------- patch/parser.json | 22 +- patch/partials.json | 43 +- patch/regressions.json | 57 +- patch/strict.json | 106 +- patch/string-params.json | 121 +- patch/subexpressions.json | 200 +-- patch/tokenizer.json | 3 - patch/track-ids.json | 191 --- patch/whitespace-control.json | 3 - shell.nix | 32 + src/cli.ts | 37 + src/commands/export.ts | 116 ++ src/commands/extractFunctions.ts | 100 ++ src/commands/generate.ts | 119 ++ src/commands/testRunner.ts | 367 +++++ src/eval.ts | 43 + src/expectTemplate.ts | 140 ++ src/globalContext.ts | 32 + src/mockGlobals.ts | 365 +++++ src/testContext.ts | 50 + src/types.d.ts | 93 ++ src/utils.ts | 290 ++++ tsconfig.json | 23 + 55 files changed, 7606 insertions(+), 3479 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.json create mode 100644 .gitattributes delete mode 100644 .jshintrc create mode 100644 CHANGELOG.md delete mode 100644 bin/eval.js delete mode 100644 bin/export.js delete mode 100755 bin/index.js delete mode 100755 bin/runner.js create mode 100644 ci.nix create mode 100644 package-lock.json create mode 100644 patch/_functions.hjson delete mode 100644 patch/bench.json delete mode 100644 patch/tokenizer.json delete mode 100644 patch/track-ids.json delete mode 100644 patch/whitespace-control.json create mode 100644 shell.nix create mode 100644 src/cli.ts create mode 100644 src/commands/export.ts create mode 100644 src/commands/extractFunctions.ts create mode 100644 src/commands/generate.ts create mode 100644 src/commands/testRunner.ts create mode 100644 src/eval.ts create mode 100644 src/expectTemplate.ts create mode 100644 src/globalContext.ts create mode 100644 src/mockGlobals.ts create mode 100644 src/testContext.ts create mode 100644 src/types.d.ts create mode 100644 src/utils.ts create mode 100644 tsconfig.json diff --git a/.editorconfig b/.editorconfig index 3b790b0..1c06093 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,5 +8,13 @@ indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true +[Makefile] +indent_style = tab +indent_size = 4 + [*.json] indent_style = tab +indent_size = 4 + +[*.ts] +indent_size = 4 diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..49423bd --- /dev/null +++ b/.eslintignore @@ -0,0 +1,5 @@ +node_modules +/dist/ +/handlebars.js/ +/patch/ +/spec/ diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..b63ef4d --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,65 @@ +{ + "root": true, + "env": { + "node": true, + "es6": true + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", + "plugin:import/errors", + "plugin:import/warnings", + "plugin:import/typescript" + ], + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "module", + "ecmaFeatures": { + "modules": true + } + }, + "plugins": [ + "@typescript-eslint", + "import" + ], + "rules": { + "indent": [ + "error", + 4 + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "single" + ], + "semi": [ + "error", + "always" + ], + + "import/extensions": [ + "error", + "ignorePackages", + { + "js": "never", + "mjs": "never", + "jsx": "never", + "ts": "never", + "tsx": "never" + } + ], + "@typescript-eslint/no-explicit-any": "off", + "no-prototype-builtins": "off", + "no-use-before-define": "off", + "@typescript-eslint/no-use-before-define": "off" + } +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..4ee5d5d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +* text=auto eol=lf +.gitattributes export-ignore +.gitignore export-ignore +.gitmodules export-ignore +.travis.yml export-ignore +dist linguist-generated=true diff --git a/.gitignore b/.gitignore index 523db4d..7053c9a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *~ /node_modules/ /tmp/ +/vendor/ diff --git a/.gitmodules b/.gitmodules index 941fba4..7db7f2c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "handlebars.js"] path = handlebars.js - url = https://github.com/wycats/handlebars.js.git + url = https://github.com/jbboehr/handlebars.js.git diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 951d6bd..0000000 --- a/.jshintrc +++ /dev/null @@ -1,22 +0,0 @@ -{ - "bitwise": true, - "camelcase": true, - "curly": true, - "eqeqeq": true, - "eqnull": true, - "forin": true, - "freeze": true, - "funcscope": false, - "immed": true, - "latedef": "nofunc", - "newcap": true, - "noarg": true, - "node": true, - "noempty": false, - "nonbsp": true, - "notypeof": true, - "singleGroups": true, - "strict": true, - "undef": true, - "unused": true -} diff --git a/.travis.yml b/.travis.yml index c97b7d1..a778a23 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,28 +3,31 @@ language: php php: - 7.2 + - 7.3 + - 7.4 + - master -before_script: +before_install: + - export PATH="./node_modules/.bin:$PATH" + +install: - npm install - make script: - - make check_changes - - make test + - make test_changes + - make test_eslint + - make test_node + - make test_php branches: only: - master - travis -env: - global: - - secure: "ZjGYCdnJbnuXx+CTiIIr50cZxEaGXF8JIY3QMgfOJ2ll4X6wVZ5FsYaOyuaaDI86lb767/fKPZ4hgFqMVAYS50XHjjr23Smavd9HHsVRPQmOifrYIYVFSDkEiKVo6JIiJPBI0NM+5vrowuORMm3YFGZMv6RGOEAa5cvjSte1wVSwvgeIK6QKlXL65L/29/p7ynT6PPhZ3kuc+lY3v2N4WGxMj7eynjGajsymAEKCqKDjRu7RRGbhcw7KdPbeMo2l+qkQBS/aEikiUgTW2CBb7cirXHODnEru15OQOTWw29ntrI7uteA6vK5w9ygTtguTEVhVDDAySGU6VYK/5VO2nnye0VLkTRKPpzeEuQNjbw85MveFoxXDPgfpUUe0tiG1ho37p73aFbZM6im1M5oQCL8gcqi+rUCshRn5MpjscZ8vMN7GFF1Sva1RQ9f/ho93gmIP0+5TStVTYgd3QTri3F14lT79P0Ujbxk4ltWX15Zj52Kcan0ipWmcz9ENGH3kqMOH9q2KvWI+vPL3laL9sBQ5L5VUWeF8XrmrSYX9MOILaJWaCPQT31oBbGUlgJZGslGqpctLBHsF5K7t7LObADU5XheMWvC0iDO/0WqVDyG37D4UTfXoaFrXIlhNSX6ouZjq+WwJaOyxLm/498N0Wk/XUpMSJ4XFKiw/mSe/6XA=" - matrix: include: - language: nix - before_script: - script: nix-build --argstr handlebarsSpecVersion $TRAVIS_BRANCH | tee result.txt - after_success: cat result.txt | cachix push jbboehr-ci - + before_install: + install: + script: nix-build --argstr handlebarsSpecVersion $TRAVIS_BRANCH diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..2713cc8 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,26 @@ +# Changelog + +All Notable changes to `handlebars-spec` will be documented in this file. + +Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [Unreleased] + +### Changed +- Rewrote everything in TypeScript +- Switched the license to `AGPL-3.0-or-later`. The specification data is still licensed under the `MIT` license, as it is extracted from `handlebars.js` +- `description` now includes all `describe($description, ...)` from the handlebars test suite +- `exception` can now be either `true`, a string, or a regex. +- `message` used to be the exception message, but will now be any extra message noted in the handlebars.js test suite +- `options` was renamed to `runtimeOptions` to differentiate from `compileOptions` +- Using a new version format `104.7.6` which is: `(myMajor * 100 + handlebarsMajor) + '.' + (myMinor * 100 + handlebarsMinor) + '.' + (myPatch * 100 + handlebarsPatch)` + +### Added +- `number` is now included in tests (besides the first implied `00`) that have multiple cases + +### Removed +- `compat` is removed in favor of `compileOptions.compat` +- `globalPartials`, `globalDecorators`, and `globalHelpers` are now removed and merged into + `partials`, `decorators`, and `helpers` instead + +[Unreleased]: https://github.com/jbboehr/handlebars.c/compare/v4.0.5-p1...HEAD diff --git a/LICENSE.md b/LICENSE.md index eac7dad..4ef32f0 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,163 +1,651 @@ -GNU Lesser General Public License +GNU Affero General Public License ================================= -_Version 3, 29 June 2007_ +_Version 3, 19 November 2007_ _Copyright © 2007 Free Software Foundation, Inc. <>_ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - -This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - -### 0. Additional Definitions - -As used herein, “this License” refers to version 3 of the GNU Lesser -General Public License, and the “GNU GPL” refers to version 3 of the GNU -General Public License. - -“The Library” refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - -An “Application” is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - -A “Combined Work” is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the “Linked -Version”. - -The “Minimal Corresponding Source” for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - -The “Corresponding Application Code” for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - -### 1. Exception to Section 3 of the GNU GPL - -You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - -### 2. Conveying Modified Versions - -If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - -* **a)** under this License, provided that you make a good faith effort to -ensure that, in the event an Application does not supply the -function or data, the facility still operates, and performs -whatever part of its purpose remains meaningful, or - -* **b)** under the GNU GPL, with none of the additional permissions of -this License applicable to that copy. - -### 3. Object Code Incorporating Material from Library Header Files - -The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - -* **a)** Give prominent notice with each copy of the object code that the -Library is used in it and that the Library and its use are -covered by this License. -* **b)** Accompany the object code with a copy of the GNU GPL and this license -document. - -### 4. Combined Works - -You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - -* **a)** Give prominent notice with each copy of the Combined Work that -the Library is used in it and that the Library and its use are -covered by this License. - -* **b)** Accompany the Combined Work with a copy of the GNU GPL and this license -document. - -* **c)** For a Combined Work that displays copyright notices during -execution, include the copyright notice for the Library among -these notices, as well as a reference directing the user to the -copies of the GNU GPL and this license document. - -* **d)** Do one of the following: - - **0)** Convey the Minimal Corresponding Source under the terms of this -License, and the Corresponding Application Code in a form -suitable for, and under terms that permit, the user to -recombine or relink the Application with a modified version of -the Linked Version to produce a modified Combined Work, in the -manner specified by section 6 of the GNU GPL for conveying -Corresponding Source. - - **1)** Use a suitable shared library mechanism for linking with the -Library. A suitable mechanism is one that **(a)** uses at run time -a copy of the Library already present on the user's computer -system, and **(b)** will operate properly with a modified version -of the Library that is interface-compatible with the Linked -Version. - -* **e)** Provide Installation Information, but only if you would otherwise -be required to provide such information under section 6 of the -GNU GPL, and only to the extent that such information is -necessary to install and execute a modified version of the -Combined Work produced by recombining or relinking the -Application with a modified version of the Linked Version. (If -you use option **4d0**, the Installation Information must accompany -the Minimal Corresponding Source and Corresponding Application -Code. If you use option **4d1**, you must provide the Installation -Information in the manner specified by section 6 of the GNU GPL -for conveying Corresponding Source.) - -### 5. Combined Libraries - -You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - -* **a)** Accompany the combined library with a copy of the same work based -on the Library, uncombined with any other library facilities, -conveyed under the terms of this License. -* **b)** Give prominent notice with the combined library that part of it -is a work based on the Library, and explaining where to find the -accompanying uncombined form of the same work. - -### 6. Revised Versions of the GNU Lesser General Public License - -The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License “or any later version” -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - -If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. \ No newline at end of file +## Preamble + +The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +Developers that use our General Public Licenses protect your rights +with two steps: **(1)** assert copyright on the software, and **(2)** offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + +A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + +The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + +An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + +The precise terms and conditions for copying, distribution and +modification follow. + +## TERMS AND CONDITIONS + +### 0. Definitions + +“This License” refers to version 3 of the GNU Affero General Public License. + +“Copyright” also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +“The Program” refers to any copyrightable work licensed under this +License. Each licensee is addressed as “you”. “Licensees” and +“recipients” may be individuals or organizations. + +To “modify” a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a “modified version” of the +earlier work or a work “based on” the earlier work. + +A “covered work” means either the unmodified Program or a work based +on the Program. + +To “propagate” a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To “convey” a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays “Appropriate Legal Notices” +to the extent that it includes a convenient and prominently visible +feature that **(1)** displays an appropriate copyright notice, and **(2)** +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +### 1. Source Code + +The “source code” for a work means the preferred form of the work +for making modifications to it. “Object code” means any non-source +form of a work. + +A “Standard Interface” means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The “System Libraries” of an executable work include anything, other +than the work as a whole, that **(a)** is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and **(b)** serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +“Major Component”, in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The “Corresponding Source” for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +The Corresponding Source for a work in source code form is that +same work. + +### 2. Basic Permissions + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + +### 3. Protecting Users' Legal Rights From Anti-Circumvention Law + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +### 4. Conveying Verbatim Copies + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +### 5. Conveying Modified Source Versions + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + +* **a)** The work must carry prominent notices stating that you modified +it, and giving a relevant date. +* **b)** The work must carry prominent notices stating that it is +released under this License and any conditions added under section 7. +This requirement modifies the requirement in section 4 to +“keep intact all notices”. +* **c)** You must license the entire work, as a whole, under this +License to anyone who comes into possession of a copy. This +License will therefore apply, along with any applicable section 7 +additional terms, to the whole of the work, and all its parts, +regardless of how they are packaged. This License gives no +permission to license the work in any other way, but it does not +invalidate such permission if you have separately received it. +* **d)** If the work has interactive user interfaces, each must display +Appropriate Legal Notices; however, if the Program has interactive +interfaces that do not display Appropriate Legal Notices, your +work need not make them do so. + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +“aggregate” if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +### 6. Conveying Non-Source Forms + +You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + +* **a)** Convey the object code in, or embodied in, a physical product +(including a physical distribution medium), accompanied by the +Corresponding Source fixed on a durable physical medium +customarily used for software interchange. +* **b)** Convey the object code in, or embodied in, a physical product +(including a physical distribution medium), accompanied by a +written offer, valid for at least three years and valid for as +long as you offer spare parts or customer support for that product +model, to give anyone who possesses the object code either **(1)** a +copy of the Corresponding Source for all the software in the +product that is covered by this License, on a durable physical +medium customarily used for software interchange, for a price no +more than your reasonable cost of physically performing this +conveying of source, or **(2)** access to copy the +Corresponding Source from a network server at no charge. +* **c)** Convey individual copies of the object code with a copy of the +written offer to provide the Corresponding Source. This +alternative is allowed only occasionally and noncommercially, and +only if you received the object code with such an offer, in accord +with subsection 6b. +* **d)** Convey the object code by offering access from a designated +place (gratis or for a charge), and offer equivalent access to the +Corresponding Source in the same way through the same place at no +further charge. You need not require recipients to copy the +Corresponding Source along with the object code. If the place to +copy the object code is a network server, the Corresponding Source +may be on a different server (operated by you or a third party) +that supports equivalent copying facilities, provided you maintain +clear directions next to the object code saying where to find the +Corresponding Source. Regardless of what server hosts the +Corresponding Source, you remain obligated to ensure that it is +available for as long as needed to satisfy these requirements. +* **e)** Convey the object code using peer-to-peer transmission, provided +you inform other peers where the object code and Corresponding +Source of the work are being offered to the general public at no +charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A “User Product” is either **(1)** a “consumer product”, which means any +tangible personal property which is normally used for personal, family, +or household purposes, or **(2)** anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, “normally used” refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +“Installation Information” for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +### 7. Additional Terms + +“Additional permissions” are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + +* **a)** Disclaiming warranty or limiting liability differently from the +terms of sections 15 and 16 of this License; or +* **b)** Requiring preservation of specified reasonable legal notices or +author attributions in that material or in the Appropriate Legal +Notices displayed by works containing it; or +* **c)** Prohibiting misrepresentation of the origin of that material, or +requiring that modified versions of such material be marked in +reasonable ways as different from the original version; or +* **d)** Limiting the use for publicity purposes of names of licensors or +authors of the material; or +* **e)** Declining to grant rights under trademark law for use of some +trade names, trademarks, or service marks; or +* **f)** Requiring indemnification of licensors and authors of that +material by anyone who conveys the material (or modified versions of +it) with contractual assumptions of liability to the recipient, for +any liability that these contractual assumptions directly impose on +those licensors and authors. + +All other non-permissive additional terms are considered “further +restrictions” within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +### 8. Termination + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated **(a)** +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and **(b)** permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +### 9. Acceptance Not Required for Having Copies + +You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +### 10. Automatic Licensing of Downstream Recipients + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An “entity transaction” is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +### 11. Patents + +A “contributor” is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's “contributor version”. + +A contributor's “essential patent claims” are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, “control” includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a “patent license” is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To “grant” such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either **(1)** cause the Corresponding Source to be so +available, or **(2)** arrange to deprive yourself of the benefit of the +patent license for this particular work, or **(3)** arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. “Knowingly relying” means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is “discriminatory” if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license **(a)** in connection with copies of the covered work +conveyed by you (or copies made from those copies), or **(b)** primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +### 12. No Surrender of Others' Freedom + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +### 13. Remote Network Interaction; Use with the GNU General Public License + +Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + +### 14. Revised Versions of this License + +The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License “or any later version” applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +### 15. Disclaimer of Warranty + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +### 16. Limitation of Liability + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + +### 17. Interpretation of Sections 15 and 16 + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +_END OF TERMS AND CONDITIONS_ + +## How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the “copyright” line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a “Source” link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a “copyright disclaimer” for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +<>. diff --git a/Makefile b/Makefile index ca5ac71..1c1e1f0 100644 --- a/Makefile +++ b/Makefile @@ -1,39 +1,40 @@ -BASIC_SPECS := basic blocks builtins data helpers partials regressions \ - string-params subexpressions strict track-ids \ +SPECS := basic blocks builtins data helpers parser partials regressions \ + string-params subexpressions strict tokenizer track-ids \ whitespace-control -SPECS := $(BASIC_SPECS) parser tokenizer all: spec export -spec: node_modules - node bin handlebars.js/bench/templates/index.js -o spec/bench.json - $(foreach var, $(SPECS), node bin handlebars.js/spec/$(var).js -o spec/$(var).json;) +dist: node_modules src tsconfig.json + tsc -export: node_modules - node bin/export spec/bench.json -o export/bench.json - $(foreach var, $(BASIC_SPECS), node bin/export spec/$(var).json -o export/$(var).json;) +node_modules: package.json + npm install -check_changes: - @git status --porcelain | grep 'spec/' && return 1 || return 0 +spec: dist + $(foreach var, $(SPECS), node dist/cli.js generate -o spec/$(var).json handlebars.js/spec/$(var).js;) + +export: dist + $(foreach var, $(SPECS), node dist/cli.js export -o export/$(var).json spec/$(var).json;) -stubs: - $(foreach var, $(SPECS), php bin/stubs.php spec/$(var).json patch/$(var).json;) -test: jshint test_node test_php +test: test_changes test_eslint test_node test_php +check: test -test_node: - @echo ---------- Testing spec against handlebars.js ---------- - node bin/runner.js +test_changes: + @git status --porcelain | grep 'spec/' && return 1 || return 0 + +test_node: dist + @echo ---------- Testing spec against handlebars.js ---------- + node dist/cli.js testRunner test_php: - @echo ---------- Linting PHP code ---------- + @echo ---------- Linting PHP code ---------- php bin/lint.php $(foreach var,$(SPECS),spec/$(var).json) -jshint: node_modules - ./node_modules/.bin/jshint bin/*.js +test_eslint: node_modules + eslint --ext .js,.ts . -node_modules: - npm install -.PHONY: all spec export check_changes test test_node test_php +.PHONY: all spec export test test_changes test_eslint test_node test_php +.DEFAULT_GOAL: all diff --git a/README.md b/README.md index 819fa5a..3ad59bc 100644 --- a/README.md +++ b/README.md @@ -9,5 +9,6 @@ This project was [originally developed](https://github.com/kasperisager/handleba ## License -This project is licensed under the [LGPLv3](http://www.gnu.org/licenses/lgpl-3.0.txt). The specification data is part -of [handlebars.js](https://github.com/wycats/handlebars.js) and is licensed under the [MIT license](http://opensource.org/licenses/MIT). +This project is licensed under the [AGPL-3.0-or-later](http://www.gnu.org/licenses/agpl-3.0.txt). +*HOWEVER*, the specification data is part of [handlebars.js](https://github.com/handlebars-lang/handlebars.js) +and is licensed under the [MIT license](http://opensource.org/licenses/MIT). diff --git a/bin/eval.js b/bin/eval.js deleted file mode 100644 index 2b63603..0000000 --- a/bin/eval.js +++ /dev/null @@ -1,17 +0,0 @@ - -/*jshint strict: false, unused: false */ - -var _utils = require('handlebars').Utils; - -function safeEval(templateSpec) { - try { - /* jshint ignore:start */ - return eval('(' + templateSpec + ')'); - /* jshint ignore:end */ - } catch (err) { - console.error("SPEC:" + templateSpec); - throw err; - } -} - -module.exports = safeEval; diff --git a/bin/export.js b/bin/export.js deleted file mode 100644 index c87ebf3..0000000 --- a/bin/export.js +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env node - -"use strict"; - -var program = require('commander'); -var fs = require('fs'); -var path = require('path'); -var Handlebars = require('handlebars'); -var pkg = require('../package.json'); - -program - .version(pkg.version) - .usage('[options] ') - .option('-o, --output [file]', 'write JSON output to a file') - .option('-v, --verbose', 'verbose') - .parse(process.argv); - -var input = path.resolve(program.args[0]); -//var suite = path.basename(input).replace(/\.js$/, ''); -var exists = fs.existsSync(input); - -if( !exists ) { - console.error('The input file does not exist'); - return process.exit(66); -} - -function compile(input, options) { - var env = Handlebars; - - options = options || {}; - if (!('data' in options)) { // jshint ignore:line - options.data = true; - } - if (options.compat) { - options.useDepths = true; - } - - var ast = env.parse(input); - var astCopy = JSON.parse(JSON.stringify(ast)); - var opcodes = new env.Compiler().compile(ast, options); - return { - ast: astCopy, - opcodes: opcodes - }; - //return new env.JavaScriptCompiler().compile(environment, options); -} - -var inputTests = require(input); -var tests = []; - -Object.keys(inputTests).forEach(function(x) { - var test = inputTests[x]; - try { - var res = compile(test.template, test.compileOptions); - test.ast = res.ast; - test.opcodes = res.opcodes; - if( test.partials ) { - var partialAsts = {}; - var partialOpcodes = {}; - Object.keys(test.partials).forEach(function(y) { - var res = compile(test.partials[y], test.compileOptions); - partialAsts[y] = res.ast; - partialOpcodes[y] = res.opcodes; - }); - test.partialAsts = partialAsts; - test.partialOpcodes = partialOpcodes; - } - if( test.globalPartials ) { - var globalPartialAsts = {}; - var globalPartialOpcodes = {}; - Object.keys(test.globalPartials).forEach(function(y) { - var res = compile(test.globalPartials[y], test.compileOptions); - globalPartialAsts[y] = res.ast; - globalPartialOpcodes[y] = res.opcodes; - }); - test.globalPartialAsts = globalPartialAsts; - test.globalPartialOpcodes = globalPartialOpcodes; - } - tests.push(test); - } catch(e) { - if( !test.exception ) { - console.log('Caught exception, skipping test ', - test.description, '-', test.it, program.verbose ? e.stack : e); - } - } -}); - -try { - var output = JSON.stringify(tests, null, '\t'); -} catch(e) { - console.log('Failed converting to JSON: ' + input + ' (' + e + ')'); - return process.exit(70); -} - -if (!program.output) { - return console.log(output); -} - -var outputFile = path.resolve(program.output); - -try { - fs.writeFileSync(outputFile, output); - console.log('JSON saved to ' + program.output); -} catch(e) { - console.log(e); - return process.exit(73); -} diff --git a/bin/index.js b/bin/index.js deleted file mode 100755 index 5fe56c7..0000000 --- a/bin/index.js +++ /dev/null @@ -1,652 +0,0 @@ -#!/usr/bin/env node - -"use strict"; - -var program = require('commander'); -var fs = require('fs'); -var path = require('path'); -var util = require('util'); -var extend = require('extend'); -var Handlebars = require('handlebars'); -var pkg = require('../package.json'); - -program - .version(pkg.version) - .usage('[options] ') - .option('-o, --output [file]', 'write JSON output to a file') - .parse(process.argv); - -var input = path.resolve(program.args[0]); -var suite = path.basename(input).replace(/\.js$/, ''); -var exists = fs.existsSync(input); - -if( !exists ) { - console.error('The input file does not exist'); - return process.exit(66); -} - -var tests = []; // Array containg the actual specs -var indices = []; // Temp array for auto-incrementing test indices -var context = {}; // Current test context -var afterFns = []; // Functions to execute after a test -var beforeFns = []; // Functions to execute before a test -var unusedPatches = null; - - -// Utils - -function addTest(spec) { - if (!spec || !spec.template) { - return; - } - - var key = (spec.description + '-' + spec.it).toLowerCase(); - var name = (function() { - for (var i = 0; i < 99; i++) { - var name = key + '-' + ('0' + i).slice(-2); - if (indices.indexOf(name) === -1) { - return name; - } - } - throw new Error('Failed to acquire test index'); - })(); - - indices.push(name); - - var patchFile = path.resolve('./patch/') + '/' + suite + '.json'; - if (fs.existsSync(path.resolve(patchFile))) { - var patch = require(patchFile); - - if (patch.hasOwnProperty(name)) { - if( patch[name] === null ) { - // Note: setting to null means to skip the test. These will most - // likely be implementation-dependant. Note that it still has to be - // added to the indices array - spec = null; - } else { - spec = extend(true, spec, patch[name]); - // Using nulls in patches to unset things - stripNulls(spec); - } - - // Track unused patches - if( unusedPatches === null ) { - unusedPatches = extend({}, patch); - } - delete unusedPatches[name]; - } - } - - if( spec !== null ) { - tests.push(spec); - } -} - -function clone(v) { - return v === undefined ? undefined : JSON.parse(JSON.stringify(v)); -} - -function detectGlobalHelpers() { - var builtins = ['helperMissing', 'blockHelperMissing', 'each', 'if', - 'unless', 'with', 'log', 'lookup']; - var globalHelpers; - Object.keys(global.handlebarsEnv.helpers).forEach(function(x) { - if( builtins.indexOf(x) !== -1 ) { - return; - } - if( !globalHelpers ) { - globalHelpers = {}; - } - globalHelpers[x] = global.handlebarsEnv.helpers[x]; - }); - if( globalHelpers ) { - context.globalHelpers = globalHelpers; - } else { - delete context.globalHelpers; - } -} - -function detectGlobalDecorators() { - var builtins = ['inline']; - var globalDecorators; - Object.keys(global.handlebarsEnv.decorators).forEach(function(x) { - if( builtins.indexOf(x) !== -1 ) { - return; - } - if( !globalDecorators ) { - globalDecorators = {}; - } - globalDecorators[x] = global.handlebarsEnv.decorators[x]; - }); - if( globalDecorators ) { - context.globalDecorators = globalDecorators; - } else { - delete context.globalDecorators; - } -} - -function detectGlobalPartials() { - // This should never be null, but it is in one case - if( !global.handlebarsEnv ) { - return; - } - var globalPartials; - Object.keys(global.handlebarsEnv.partials).forEach(function(x) { - if( !globalPartials ) { - globalPartials = {}; - } - globalPartials[x] = global.handlebarsEnv.partials[x]; - }); - if( globalPartials ) { - context.globalPartials = globalPartials; - } else { - delete context.globalPartials; - } -} - -function extractHelpers(data) { - var helpers = {}; - - if (!data || typeof data !== 'object') { - return false; - } - - Object.keys(data).forEach(function (el) { - if (isFunction(data[el])) { - helpers[el] = { "!code" : true, javascript: '' + data[el] }; - } - }); - - return isEmptyObject(helpers) ? false : helpers; -} - -function isFunction(object) { - return Boolean(object && object.constructor && object.call && object.apply); -} - -function isEmptyObject(object) { - return !Object.keys(object).length; -} - - -function removeCircularReferences(data, prev) { - if( typeof data !== 'object' ) { - return; - } - prev = prev || []; - prev.push(data); - function checkCircularRef(v) { - for( var y in prev ) { - if( v === prev[y] ) { - return true; - } - } - return false; - } - for( var x in data ) { - if( checkCircularRef(data[x]) ) { - delete data[x]; - } else if( typeof data[x] === 'object' ) { - removeCircularReferences(data[x]); - } - } -} - -function resetContext() { - delete context.template; - delete context.data; - delete context.options; - delete context.compileOptions; - delete context.helpers; - delete context.globalHelpers; - delete context.partials; - delete context.globalPartials; - delete context.decorators; - delete context.globalDecorators; - delete context.exception; -} - -function stringifyLambdas(data) { - if( typeof data !== 'object' ) { - return; - } - for( var x in data ) { - if( data[x] instanceof Array ) { - stringifyLambdas(data[x]); - } else if( typeof data[x] === 'function' || data[x] instanceof Function ) { - data[x] = { - '!code' : true, - 'javascript' : data[x].toString() - }; - } else if( typeof data[x] === 'object' ) { - stringifyLambdas(data[x]); - } - } -} - -function stripNulls(data) { - if( typeof data === 'object' ) { - for( var x in data ) { - if( data[x] === null ) { - if( data['!keepnull'] ) { - delete data['!keepnull']; - } else { - delete data[x]; - } - } else if( typeof data === 'object' ) { - stripNulls(data[x]); - } - } - } -} - - - -// Globals - -global.Handlebars = Handlebars; -global.handlebarsEnv = Handlebars.create(); - -global.afterEach = function afterEach(fn) { - afterFns.push(fn); -}; - -global.beforeEach = function beforeEach(fn) { - beforeFns.push(fn); -}; - -global.CompilerContext = { - compile: function CompilerContextCompile(template, options) { - // Push template unto context - context.template = template; - context.compileOptions = clone(options); - - var compiledTemplate = Handlebars.compile(template, options); - - return function (data, options) { - // Note: merging data in the options causes tests to fail, possibly - // a separate type of data? - if (options && options.hasOwnProperty('data')) { - //data = extend(true, data, options.data); - context.options = context.options || {}; - context.options.data = options.data; - } - - // Push template data unto context - context.data = data; - - if (options && options.hasOwnProperty('helpers')) { - // Push helpers unto context - context.helpers = options.helpers; - } - - if (options && options.hasOwnProperty('decorators')) { - // Push decorators unto context - context.decorators = options.decorators; - } - - return compiledTemplate(data, options); - }; - }, - compileWithPartial: function CompilerContextCompileWithPartial(template, options) { - // Push template unto context - context.template = template; - context.compileOptions = clone(options); - return Handlebars.compile(template, options); - } -}; - -global.describe = function describe(description, next) { - // Push suite description unto context - context.description = description; - next(); - delete context.description; -}; - -global.it = function it(description, next) { - // Call before fns - beforeFns.forEach(function(fn) { - fn(); - }); - // Push test spec unto context - context.it = description; - // Test - next(); - // Remove test spec from context - delete context.it; - // Call after fns - afterFns.forEach(function(fn) { - fn(); - }); -}; - -global.equal = global.equals = function equals(actual, expected, message) { - var spec = { - description : context.description || context.it, - it : context.it, - template : context.template, - data : context.data, - expected : expected, - }; - - // Remove circular references in data - removeCircularReferences(spec.data); - - // Get message - if (message) { - spec.message = message; - } - - // Get options - if( context.options ) { - spec.options = context.options; - if( spec.options.data ) { - stringifyLambdas(spec.options.data); - } - } - - // Get compiler options - if (context.compileOptions) { - spec.compileOptions = context.compileOptions; - } - - // Get helpers - if (context.helpers) { - spec.helpers = extractHelpers(context.helpers); - } - - // Get global helpers - if (context.globalHelpers) { - spec.globalHelpers = extractHelpers(context.globalHelpers); - } - - // Get decorators - if (context.decorators) { - spec.decorators = extractHelpers(context.decorators); - } - - // Get global decorators - if (context.globalDecorators) { - spec.globalDecorators = extractHelpers(context.globalDecorators); - } - - // If a template is found in the lexer, use it for the spec. This is true in - // the case of the tokenizer. - if (!spec.template && Handlebars.Parser.lexer.matched) { - spec.template = Handlebars.Parser.lexer.matched; - } - - // Convert lambdas to object/strings - stringifyLambdas(spec.data); - - // Add test - addTest(spec); - - // Reset the context - resetContext(); -}; - -global.tokenize = function tokenize(template) { - context.template = template; - return global.originalTokenize(template); -}; - -global.shouldMatchTokens = function shouldMatchTokens(result /*, tokens*/) { - var spec = { - description : context.description || context.it, - it : context.it, - template : context.template, - expected : result, - }; - - // Add the test - addTest(spec); - - // Reset the context - resetContext(); -}; - -global.shouldBeToken = function shouldBeToken() { - -}; - -global.shouldCompileTo = function shouldCompileTo(string, hashOrArray, expected) { - global.shouldCompileToWithPartials(string, hashOrArray, false, expected); -}; - -global.shouldCompileToWithPartials = function shouldCompileToWithPartials(string, hashOrArray, partials, expected, message) { - detectGlobalHelpers(); - detectGlobalPartials(); - detectGlobalDecorators(); - global.compileWithPartials(string, hashOrArray, partials, expected, message); -}; - -global.compileWithPartials = function compileWithPartials(string, hashOrArray, partials, expected, message) { - var helpers; - var decorators; - var data; - var compat; - var compileOptions = extend({}, context.compileOptions); - - if (util.isArray(hashOrArray)) { - data = hashOrArray[0]; - helpers = extractHelpers(hashOrArray[1]); - partials = hashOrArray[2]; - if( hashOrArray[3] ) { - if( typeof hashOrArray[3] === 'boolean' ) { - compileOptions.compat = compat = true; - } else if( typeof hashOrArray[3] === 'object' ) { - extend(compileOptions, hashOrArray[3]); - } - } - /* if (hashOrArray[4] != null) { - options.data = !!hashOrArray[4]; - ary[1].data = hashOrArray[4]; - } */ - } else { - data = hashOrArray; - if( typeof data === 'object' ) { - data = hashOrArray.hash || hashOrArray; - helpers = extractHelpers(hashOrArray.helpers || context.helpers); - partials = hashOrArray.partials || context.partials; - decorators = extractHelpers(hashOrArray.decorators || context.decorators); - delete data.helpers; - delete data.partials; - delete data.decorators; - } - } - - var spec = { - description : context.description || context.it, - it : context.it, - template : string, - data : data, - expected : expected - }; - - // Remove circular references in data - removeCircularReferences(data); - - // Check for exception - if( context.exception ) { - spec.exception = true; - } - - if (partials) { - spec.partials = partials; - } - if (helpers) { - spec.helpers = helpers; - } - if (decorators) { - spec.decorators = decorators; - } - if (message) { - spec.message = '' + message; - } - if (compat) { - spec.compat = true; - } - - // Get options - if( context.options ) { - spec.options = context.options; - if( spec.options.data ) { - stringifyLambdas(spec.options.data); - } - } - - // Get compiler options - if( compileOptions ) { - spec.compileOptions = compileOptions; - } - - // Get global partials - if( context.globalPartials ) { - spec.globalPartials = context.globalPartials; - } - - // Get global helpers - if( context.globalHelpers ) { - spec.globalHelpers = extractHelpers(context.globalHelpers); - } - - // Get global decorators - if( context.globalDecorators ) { - spec.globalDecorators = extractHelpers(context.globalDecorators); - } - - // Convert lambdas to object/strings - stringifyLambdas(spec.data); - stringifyLambdas(spec.partials); - - // Add the test - addTest(spec); - - // Reset the context - resetContext(); -}; - -global.shouldThrow = function shouldThrow(callback, error, message) { - context.exception = true; - - try { - callback(); - } catch (err) {} - - delete context.exception; - - var spec = { - description : context.description || context.it, - it : context.it, - template : context.template, - exception : true, - }; - - // Add the message - if (message) { - spec.message = '' + message; - } - - // If a template is found in the lexer, use it for the spec. This is true in - // the case of the tokenizer. - if (!spec.template) { - spec.template = Handlebars.Parser.lexer.matched + - Handlebars.Parser.lexer._input; - } - - // Add the test - addTest(spec); - - // Reset the context - resetContext(); -}; - - - -// Main - -// Need to patch out some global functions for the tokenizer -if( input.match(/tokenizer\.js$/) ) { - var tokenizerData = ('' + fs.readFileSync(input)) - .replace(/function shouldMatchTokens/, 'function REMshouldMatchTokens') - .replace(/function shouldBeToken/, 'function REMshouldBeToken') - .replace(/function tokenize/, 'global.originalTokenize = function'); - input = input.replace(/\.js$/, '.tmp.js'); - fs.writeFileSync(input, tokenizerData); - process.on('exit', function() { - fs.unlinkSync(input); - }); -} - -if( input.match(/bench\/templates/) ) { - suite = 'bench'; - var benches = require(input); - Object.keys(benches).forEach(function(x) { - var data = benches[x]; - var expected = Handlebars.compile(data.handlebars)(data.context, { - helpers: data.helpers, - partials: data.partials && data.partials.handlebars, - decorators: data.decorators - }); - stringifyLambdas(data.context); - var test = { - description: 'Benchmarks', - it: x, - template: data.handlebars, - data: data.context, - expected: expected, - compileOptions: { - data: false - } - }; - if( data.helpers ) { - test.helpers = extractHelpers(data.helpers); - } - if( data.partials && data.partials.handlebars ) { - test.partials = data.partials.handlebars; - } - if( data.decorators ) { - test.decorators = extractHelpers(data.decorators); - } - addTest(test); - - if( test.mustache ) { - test = clone(test); - test.it = x + ' compat'; - test.template = data.mustache; - test.compileOptions.compat = true; - addTest(test); - } - }); -} else { - require(input); -} - -try { - var output = JSON.stringify(tests, null, '\t'); -} catch(e) { - console.log('Failed converting to JSON: ' + input + ' (' + e + ')'); - return process.exit(70); -} - -if (!program.output) { - return console.log(output); -} - -var outputFile = path.resolve(program.output); - -try { - fs.writeFileSync(outputFile, output); - console.log('JSON saved to ' + program.output); - if( unusedPatches !== null ) { - unusedPatches = Object.keys(unusedPatches); - if( unusedPatches.length ) { - console.log("Unused patches: " + unusedPatches); - } - } -} catch(e) { - console.log(e); - return process.exit(73); -} - diff --git a/bin/lint.php b/bin/lint.php index ced4770..a7edad9 100644 --- a/bin/lint.php +++ b/bin/lint.php @@ -1,4 +1,20 @@ . + */ // Cleanup temp files @@ -75,28 +91,28 @@ function searchForCode($data, &$codes, $path = array()) { foreach( $inputFiles as $inputFile ) { $indices[$inputFile] = array(); - + if( !file_exists($inputFile) ) { echo "Input file does not exist\n"; exit(66); } - + $tests = json_decode(file_get_contents($inputFile), true); if( !$tests ) { echo "Failed to decode JSON\n"; exit(65); } - + foreach( $tests as $test ) { $prefix = $inputFile . ' - ' . $test['description'] . ' - ' . $test['it']; $codes = null; $index = 0; searchForCode($test, $codes); - + if( empty($codes) ) { continue; } - + foreach( $codes as $key => $code ) { echo $prefix, ' ', '#', ++$index, " [", $key, "] ... "; try { @@ -117,7 +133,7 @@ function searchForCode($data, &$codes, $path = array()) { $skipped[] = $prefix; } } - + unset($codes); } } diff --git a/bin/runner.js b/bin/runner.js deleted file mode 100755 index c015205..0000000 --- a/bin/runner.js +++ /dev/null @@ -1,337 +0,0 @@ -#!/usr/bin/env node - -"use strict"; - -var fs = require('fs'); -var path = require('path'); -var util = require('util'); -var assert = require('assert'); -var Handlebars = require('handlebars'); -var safeEval = require('./eval'); - - - -// Utils - -function astFor(template) { // borrowed from spec/parser.js - var ast = Handlebars.parse(template); - return Handlebars.print(ast); -} - -function clone(v) { - return v === undefined ? undefined : JSON.parse(JSON.stringify(v)); -} - -function tokenize(template) { // borrowed from spec/tokenizer.js - var parser = Handlebars.Parser, - lexer = parser.lexer; - - lexer.setInput(template); - var out = []; - - for (;;) { - var token = lexer.lex(); - if( !token ) { - break; - } - var result = parser.terminals_[token] || token; - if (!result || result === 'EOF' || result === 'INVALID') { - break; - } - out.push({name: result, text: lexer.yytext}); - } - - return out; -} - -function unstringifyHelpers(helpers) { - if( !helpers || helpers === null ) { - return; - } - var ret = {}; - Object.keys(helpers).forEach(function(x) { - ret[x] = safeEval(helpers[x].javascript); - }); - return ret; -} - -function unstringifyLambdas(data) { - if( !data || data === null ) { - return data; - } - for( var x in data ) { - if( util.isArray(data[x]) ) { - unstringifyLambdas(data[x]); - } else if( typeof data[x] === 'object' && data[x] !== null ) { - if( '!code' in data[x] ) { - data[x] = safeEval(data[x].javascript); - } else { - unstringifyLambdas(data[x]); - } - } - } - return data; -} - -function fixSparseArray(data) { - if( !data || typeof data !== 'object' ) { - return data; - } - - var x, i; - - if( '!sparsearray' in data ) { - var newData = []; - for( x in data ) { - if( data.hasOwnProperty(x) ) { - if( !isNaN(i = parseInt(x)) ) { - newData[i] = data[x]; - } - } - } - data = newData; - } else { - for( x in data ) { - if( data.hasOwnProperty(x) ) { - data[x] = fixSparseArray(data[x]); - } - } - } - - return data; -} - - - -// Test utils - -function checkResult(test, e) { - var shouldExcept = test.exception === true; - var didExcept = e !== undefined; - if( shouldExcept === didExcept ) { - console.log(test.prefix + 'OK'); - return true; - } else { - var msg = e || 'Error: should have thrown, did not'; - console.log(test.prefix + msg); - if( e ) { - console.error(e.stack); - } - console.error('Test Data: ', test); - return false; - } -} - -function makePrefix(test) { - return '(' + test.suite + ' - ' + test.it + ' - ' + test.description + '): '; -} - -function prepareTestGeneric(test) { - var spec = {}; - // Output prefix - spec.prefix = makePrefix(test); - // Template - spec.template = test.template; - // Expected - spec.expected = test.expected; - // Exception - spec.exception = test.exception ? true : false; - // Data - spec.data = fixSparseArray(clone(test.data)); - unstringifyLambdas(spec.data); - // Helpers - spec.helpers = unstringifyHelpers(test.helpers); - spec.globalHelpers = test.globalHelpers || undefined; - // Partials - spec.partials = test.partials; - unstringifyLambdas(spec.partials); - spec.globalPartials = test.globalPartials || undefined; - // Decorators - spec.decorators = unstringifyHelpers(test.decorators); - spec.globalDecorators = test.globalDecorators || undefined; - // Options - spec.options = clone(test.options); - spec.compileOptions = clone(test.compileOptions); - if( spec.options && typeof spec.options.data === 'object' ) { - unstringifyLambdas(spec.options.data); - } - // Compat - spec.compat = Boolean(test.compat); - return spec; -} - -function prepareTestParser(test) { - var spec = {}; - // Output prefix - spec.prefix = makePrefix(test); - // Template - spec.template = test.template; - // Expected - spec.expected = clone(test.expected); - // Exception - spec.exception = test.exception ? true : false; - // Message - spec.message = test.message; - return spec; -} - -function prepareTestTokenizer(test) { - var spec = {}; - // Output prefix - spec.prefix = makePrefix(test); - // Template - spec.template = test.template; - // Expected - spec.expected = clone(test.expected); - return spec; -} - -function runTest(test) { - var result = null; - switch( test.suite ) { - case 'basic': - case 'bench': - case 'blocks': - case 'builtins': - case 'data': - case 'helpers': - case 'partials': - case 'regressions': - case 'strict': - case 'string-params': - case 'subexpressions': - case 'track-ids': - case 'whitespace-control': - result = runTestGeneric(prepareTestGeneric(test)); - break; - case 'parser': - result = runTestParser(prepareTestParser(test)); - break; - case 'tokenizer': - result = runTestTokenizer(prepareTestTokenizer(test)); - break; - } - return result; -} - -function runTestGeneric(test) { - try { - // Register global partials - global.handlebarsEnv.partials = {}; - Object.keys(test.globalPartials || {}).forEach(function(x) { - global.handlebarsEnv.registerPartial(x, test.globalPartials[x]); - }); - - // Register global helpers - Object.keys(test.globalHelpers || {}).forEach(function(x) { - global.handlebarsEnv.registerHelper(x, safeEval(test.globalHelpers[x].javascript)); - }); - - // Register global decorators - Object.keys(test.globalDecorators || {}).forEach(function(x) { - global.handlebarsEnv.registerDecorator(x, safeEval(test.globalDecorators[x].javascript)); - }); - - // Execute - var hasPartials = typeof test.partials === 'object' && Object.keys(test.partials).length > 0; - var template = global.CompilerContext[hasPartials ? 'compileWithPartial' : 'compile'](test.template, clone(test.compileOptions)); - var opts = test.options || {}; - //opts.data = typeof test.data === 'string' ? [test.data] : test.data; // le sigh - if( test.helpers ) { - opts.helpers = test.helpers; - } - if( test.partials ) { - opts.partials = test.partials; - } - if( test.decorators ) { - opts.decorators = test.decorators; - } - test.opts = opts; - - var actual = template(test.data, test.opts); - global.equals(actual, test.expected); - - return checkResult(test); - } catch(e) { - return checkResult(test, e); - } -} - -function runTestParser(test) { - try { - var actual = astFor(test.template); - assert.equal(actual, test.expected); - return checkResult(test); - } catch(e) { - return checkResult(test, e); - } -} - -function runTestTokenizer(test) { - try { - var actual = tokenize(test.template); - assert.deepEqual(actual, test.expected); - return checkResult(test); - } catch(e) { - return checkResult(test, e); - } -} - - - -// Globals - -global.Handlebars = Handlebars; -global.handlebarsEnv = Handlebars; - -global.CompilerContext = { // borrowed from spec/env/node.js - compile: function(template, options) { - var templateSpec = global.handlebarsEnv.precompile(template, options); - return global.handlebarsEnv.template(safeEval(templateSpec)); - }, - compileWithPartial: function(template, options) { - return global.handlebarsEnv.compile(template, options); - } -}; -require('../handlebars.js/spec/env/common.js'); - -// Sigh - not sure why this isn't working right (for builtins #each) -Handlebars.registerHelper('detectDataInsideEach', function(options) { - return options.data && options.data.exclaim; -}); - - - -// Main - -var dir = path.resolve('./spec/'); -var specs = fs.readdirSync(dir); -var successes = []; -var failures = []; -var skipped = []; - -Object.keys(specs).forEach(function(x) { - var suite = specs[x].replace(/\.json$/, ''); - var data = require(dir + '/' + specs[x]); - Object.keys(data).forEach(function(y) { - data[y].suite = suite; - var result = runTest(data[y]); - if( result === null ) { - skipped.push(data[y]); - } else if( result === true ) { - successes.push(data[y]); - } else { - failures.push(data[y]); - } - }); -}); - - -// Results - -console.log('Summary'); -console.log('Success: ' + successes.length); -console.log('Failed: ' + failures.length); -console.log('Skipped: ' + skipped.length); - -process.exit(failures.length ? 2 : 0); diff --git a/bin/stubs.php b/bin/stubs.php index 048e53e..0f64c23 100644 --- a/bin/stubs.php +++ b/bin/stubs.php @@ -1,4 +1,20 @@ . + */ if( $argc <= 1 ) { echo "Generates stubs for php code from javascript functions\n"; @@ -12,13 +28,13 @@ function createPatchStub($name, $test, $key, $inputFile) { global $patches; - + $patchData = &$patches; - + if( !isset($patchData[$name]) ) { $patchData[$name] = array(); } - + // Get ref via key $ref = &$patchData[$name]; $ref2 = &$test; @@ -31,12 +47,12 @@ function createPatchStub($name, $test, $key, $inputFile) { $ref = &$ref[$k]; $ref2 = &$ref2[$k]; } - + if( isset($ref[$final]['php']) ) { // Sanity check return; } - + $ref[$final]['phpstub'] = $ref2[$final]['javascript']; } @@ -48,7 +64,7 @@ function searchForCode($data, &$codes, $path = array()) { if( !is_array($v) ) { continue; } - + $tmp = $path; $tmp[] = is_int($k) ? sprintf('%d', $k) : $k; if( !empty($v['!code']) ) { @@ -97,15 +113,15 @@ function searchForCode($data, &$codes, $path = array()) { throw new \Exception('Failed to generate index for test: ' . $key); } $indices[] = $name; - + $codes = null; $index = 0; searchForCode($test, $codes); - + if( empty($codes) ) { continue; } - + foreach( $codes as $key => $code ) { createPatchStub($name, $test, $key, $inputFile); } diff --git a/ci.nix b/ci.nix new file mode 100644 index 0000000..745cf1c --- /dev/null +++ b/ci.nix @@ -0,0 +1,39 @@ +# Copyright (C) 2020 John Boehr +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +builtins.mapAttrs (k: _v: + let + path = builtins.fetchTarball { + url = https://github.com/NixOS/nixpkgs/archive/release-19.09.tar.gz; + name = "nixpkgs-19.09"; + }; + pkgs = import (path) { system = k; }; + in + pkgs.recurseIntoAttrs { + n1909 = pkgs.callPackage ./default.nix {}; + + n2003 = let + path = builtins.fetchTarball { + url = https://github.com/NixOS/nixpkgs/archive/release-20.03.tar.gz; + name = "nixpkgs-20.03"; + }; + pkgs = import (path) { system = k; }; + in pkgs.callPackage ./default.nix {}; + } +) { + x86_64-linux = {}; + # Uncomment to test build on macOS too + # x86_64-darwin = {}; +} diff --git a/composer.json b/composer.json index 6148ae4..d0a21f3 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,6 @@ "handlebars", "mustache" ], - "license": "LGPLv3", + "license": "AGPL-3.0-or-later", "type" : "library" -} \ No newline at end of file +} diff --git a/default.nix b/default.nix index e41a92e..74b3090 100644 --- a/default.nix +++ b/default.nix @@ -1,3 +1,18 @@ +# Copyright (C) 2020 John Boehr +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + { pkgs ? import {}, handlebarsSpecVersion ? null, diff --git a/derivation.nix b/derivation.nix index 3220539..892a17c 100644 --- a/derivation.nix +++ b/derivation.nix @@ -1,3 +1,18 @@ +# Copyright (C) 2020 John Boehr +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + { lib, stdenv, @@ -8,7 +23,7 @@ handlebarsSpecSha256 ? null }: -let +let orDefault = x: y: (if (!isNull x) then x else y); in @@ -22,16 +37,16 @@ stdenv.mkDerivation rec { builder = writeText "builder.sh" '' source $stdenv/setup - + buildPhase() { echo do nothing } - + installPhase() { mkdir -p $out/share/handlebars-spec cp -prvd spec export $out/share/handlebars-spec/ } - + genericBuild ''; diff --git a/handlebars.js b/handlebars.js index 205c61c..0cc64fd 160000 --- a/handlebars.js +++ b/handlebars.js @@ -1 +1 @@ -Subproject commit 205c61cfb1acdb599bbdfcf2d356641254e09e5c +Subproject commit 0cc64fde2ef5d3029f845f4591bdfdd4d186adbd diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..62c7e46 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2387 @@ +{ + "name": "handlebars-spec", + "version": "104.6.4", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", + "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", + "dev": true + }, + "@babel/highlight": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", + "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.9.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/runtime": { + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", + "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@sinonjs/commons": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.2.tgz", + "integrity": "sha512-+DUO6pnp3udV/v2VfUWgaY5BIE1IfT7lLfeDzPVeMT1XKkaAp9LgSI9x5RtrFQoZ9Oi0PgXQQHPaoKu7dCjVxw==", + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@sinonjs/formatio": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", + "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^5.0.2" + } + }, + "@sinonjs/samsam": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.0.3.tgz", + "integrity": "sha512-QucHkc2uMJ0pFGjJUDP3F9dq5dx8QIaqISl9QgwLOh6P9yv877uONPGXh/OH/0zmM3tW1JjuJltAZV2l7zU+uQ==", + "requires": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha512-mMUu4nWHLBlHtxXY17Fg6+ucS/MnndyOWyOe7MmwkoMYxvfQU2ajtRaEvqSUv+aVkMqH/C0NCI8UoVfRNQ10yg==", + "dev": true + }, + "@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", + "dev": true + }, + "@types/extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/extend/-/extend-3.0.1.tgz", + "integrity": "sha512-R1g/VyKFFI2HLC1QGAeTtCBWCo6n75l41OnsVYNbmKG+kempOESaodf6BeJyUM3Q0rKa/NQcTHbB2+66lNnxLw==", + "dev": true + }, + "@types/hjson": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/hjson/-/hjson-2.4.1.tgz", + "integrity": "sha512-yXq/C73UHM8GQc6RYJnUXUgxudr2Q9227Iawhkp03YCnfJJTc+6LJnnVLx+UR/Dvw6imO5Q3vpGNmR9IRBI0JQ==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", + "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", + "dev": true + }, + "@types/node": { + "version": "13.13.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.4.tgz", + "integrity": "sha512-x26ur3dSXgv5AwKS0lNfbjpCakGIduWU1DU91Zz58ONRWrIKGunmZBNv4P7N+e27sJkiGDsw/3fT4AtsqQBrBA==", + "dev": true + }, + "@types/sinon": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-9.0.0.tgz", + "integrity": "sha512-v2TkYHkts4VXshMkcmot/H+ERZ2SevKa10saGaJPGCJ8vh3lKrC4u663zYEeRZxep+VbG6YRDtQ6gVqw9dYzPA==", + "dev": true, + "requires": { + "@types/sinonjs__fake-timers": "*" + } + }, + "@types/sinonjs__fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.1.tgz", + "integrity": "sha512-yYezQwGWty8ziyYLdZjwxyMb0CZR49h8JALHGrxjQHWlqGgc8kLdHEgWrgL0uZ29DMvEVBDnHU2Wg36zKSIUtA==", + "dev": true + }, + "@types/uglify-js": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.9.0.tgz", + "integrity": "sha512-3ZcoyPYHVOCcLpnfZwD47KFLr8W/mpUcgjpf1M4Q78TMJIw7KMAHSjiCLJp1z3ZrBR9pTLbe191O0TldFK5zcw==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@typescript-eslint/eslint-plugin": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.30.0.tgz", + "integrity": "sha512-PGejii0qIZ9Q40RB2jIHyUpRWs1GJuHP1pkoCiaeicfwO9z7Fx03NQzupuyzAmv+q9/gFNHu7lo1ByMXe8PNyg==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "2.30.0", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.0.0", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.30.0.tgz", + "integrity": "sha512-L3/tS9t+hAHksy8xuorhOzhdefN0ERPDWmR9CclsIGOUqGKy6tqc/P+SoXeJRye5gazkuPO0cK9MQRnolykzkA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "2.30.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.30.0.tgz", + "integrity": "sha512-9kDOxzp0K85UnpmPJqUzdWaCNorYYgk1yZmf4IKzpeTlSAclnFsrLjfwD9mQExctLoLoGAUXq1co+fbr+3HeFw==", + "dev": true, + "requires": { + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "2.30.0", + "@typescript-eslint/typescript-estree": "2.30.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "@typescript-eslint/typescript-estree": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.30.0.tgz", + "integrity": "sha512-nI5WOechrA0qAhnr+DzqwmqHsx7Ulr/+0H7bWCcClDhhWkSyZR5BmTvnBEyONwJCTWHfc5PAQExX24VD26IAVw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^6.3.0", + "tsutils": "^3.17.1" + } + }, + "acorn": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", + "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", + "dev": true + }, + "acorn-jsx": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", + "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", + "dev": true + }, + "ajv": { + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", + "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "requires": { + "type-fest": "^0.11.0" + }, + "dependencies": { + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + } + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=" + }, + "array-includes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + } + }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "ast-metadata-inferer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.1.1.tgz", + "integrity": "sha512-hc9w8Qrgg9Lf9iFcZVhNjUnhrd2BBpTlyCnegPVvCe6O0yMrF57a6Cmh7k+xUsfUOMh9wajOL5AsGOBNEyTCcw==", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "available-typed-arrays": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz", + "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==", + "requires": { + "array-filter": "^1.0.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browserslist": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz", + "integrity": "sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001043", + "electron-to-chromium": "^1.3.413", + "node-releases": "^1.1.53", + "pkg-up": "^2.0.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "caniuse-db": { + "version": "1.0.30001048", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30001048.tgz", + "integrity": "sha512-HqYsBIZlVARU5GDXPziXSFwFVpGx9KqCznr62iaey7bT2sqpx7/jI4B3PvbKguKi8kGeEannJ7WEPB5H71rjFQ==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001048", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001048.tgz", + "integrity": "sha512-g1iSHKVxornw0K8LG9LLdf+Fxnv7T1Z+mMsf0/YYLclQX4Cd522Ap0Lrw6NFqHgezit78dtyWxzlV2Xfc7vgRg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "clime": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/clime/-/clime-0.5.10.tgz", + "integrity": "sha512-FpqeE23ukoEzsS7IkRNWf5ssg1BoiKBr55ra8fxrMXZuaHhsRY+gCJwMOUIrQrVEuIYAaUxzBd/2Q6kek6ecRg==", + "requires": { + "chalk": "^2.1.0", + "extendable-error": "^0.1.5", + "hyphenate": "^0.2.1", + "parse-messy-time": "^2.1.0", + "reflect-metadata": "^0.1.10", + "strip-ansi": "^4.0.0", + "villa": "^0.2.11" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-equal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.3.tgz", + "integrity": "sha512-Spqdl4H+ky45I9ByyJtXteOm9CaIrPmnIPmOhrkKGNYWeDgCvJ8jNYVCTjChxW4FqGuZnLHADc8EKRMX6+CgvA==", + "requires": { + "es-abstract": "^1.17.5", + "es-get-iterator": "^1.1.0", + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.2", + "is-regex": "^1.0.5", + "isarray": "^2.0.5", + "object-is": "^1.1.2", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.2", + "which-boxed-primitive": "^1.0.1", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.2" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + } + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "electron-to-chromium": { + "version": "1.3.422", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.422.tgz", + "integrity": "sha512-8HXl8Mje9nkNjZdFsRcoFkM7hXzQ3cMSxF+lx85CUg5j9lQvuYsKh5Ku5WnduxUvweZToMviOrplOQ9vzkdz2w==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-get-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", + "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", + "requires": { + "es-abstract": "^1.17.4", + "has-symbols": "^1.0.1", + "is-arguments": "^1.0.4", + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "eslint": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "eslint-import-resolver-node": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz", + "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-compat": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-3.5.1.tgz", + "integrity": "sha512-dhfW12vZxxKLEVhrPoblmEopgwpYU2Sd4GdXj5OSfbQ+as9+1aY+S5pqnJYJvXXNWFFJ6aspLkCyk4NMQ/pgtA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.7", + "ast-metadata-inferer": "^0.1.1", + "browserslist": "^4.8.2", + "caniuse-db": "^1.0.30001017", + "lodash.memoize": "4.1.2", + "mdn-browser-compat-data": "^1.0.3", + "semver": "^6.3.0" + } + }, + "eslint-plugin-es": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.0.tgz", + "integrity": "sha512-6/Jb/J/ZvSebydwbBJO1R9E5ky7YeElfK56Veh7e4QGFHCXoIXGH9HhVz+ibJLM3XJ1XjP+T7rKBLUa/Y7eIng==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + } + }, + "eslint-plugin-import": { + "version": "2.20.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.2.tgz", + "integrity": "sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.1", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.12.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, + "requires": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + } + } + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", + "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "espree": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", + "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extendable-error": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.5.tgz", + "integrity": "sha1-EiMIpwl7yJomOyxPvwiceBQOO20=" + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "handlebars": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + }, + "hjson": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/hjson/-/hjson-3.2.1.tgz", + "integrity": "sha512-OhhrFMeC7dVuA1xvxuXGTv/yTdhTvbe8hz+3LgVNsfi9+vgz0sF/RrkuX8eegpKaMc9cwYwydImBH6iePoJtdQ==" + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "hyphenate": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/hyphenate/-/hyphenate-0.2.4.tgz", + "integrity": "sha512-COZPA5RLSvGJDlWrbMcKF16tKcfCaNNh63yA7QldGz6i/BVJAeYCXPQAiXUzS0y2pxY7c8VId0CPvxm2Rbisqw==" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "inquirer": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", + "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^3.0.0", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.5.3", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.0.tgz", + "integrity": "sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g==" + }, + "is-boolean-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.1.tgz", + "integrity": "sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==" + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==" + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", + "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==" + }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==" + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "requires": { + "has": "^1.0.3" + } + }, + "is-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", + "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==" + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==" + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typed-array": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.3.tgz", + "integrity": "sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ==", + "requires": { + "available-typed-arrays": "^1.0.0", + "es-abstract": "^1.17.4", + "foreach": "^2.0.5", + "has-symbols": "^1.0.1" + } + }, + "is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==" + }, + "is-weakset": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz", + "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw==" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "just-extend": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.0.tgz", + "integrity": "sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA==" + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "mdn-browser-compat-data": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/mdn-browser-compat-data/-/mdn-browser-compat-data-1.0.18.tgz", + "integrity": "sha512-6N7UzsgyXMsJvN/LxfqZqH7A4Sq69erz/o/6Ao10sJ8Dc6g2aWvjkTAjmchXK2Q/2UIC3GzldzzNqujesXak9A==", + "dev": true, + "requires": { + "extend": "3.0.2" + }, + "dependencies": { + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + } + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "nise": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.3.tgz", + "integrity": "sha512-EGlhjm7/4KvmmE6B/UFsKh7eHykRl9VH+au8dduHLCyWUO/hr7+N+WtTvDUwc9zHuM1IaIJs/0lQ6Ag1jDkQSg==", + "requires": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node-releases": { + "version": "1.1.53", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.53.tgz", + "integrity": "sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" + }, + "object-is": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", + "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-messy-time": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-messy-time/-/parse-messy-time-2.1.0.tgz", + "integrity": "sha1-ehTOehxPZbXt4kM5nMBW2GvVetU=" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", + "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", + "dev": true + }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "rxjs": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", + "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "sha1": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", + "integrity": "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=", + "requires": { + "charenc": ">= 0.0.1", + "crypt": ">= 0.0.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "side-channel": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz", + "integrity": "sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==", + "requires": { + "es-abstract": "^1.17.0-next.1", + "object-inspect": "^1.7.0" + } + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "sinon": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.0.2.tgz", + "integrity": "sha512-0uF8Q/QHkizNUmbK3LRFqx5cpTttEVXudywY9Uwzy8bTfZUhljZ7ARzSxnRHWYWtVTeh4Cw+tTb3iU21FQVO9A==", + "requires": { + "@sinonjs/commons": "^1.7.2", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/formatio": "^5.0.1", + "@sinonjs/samsam": "^5.0.3", + "diff": "^4.0.2", + "nise": "^4.0.1", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimleft": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", + "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimstart": "^1.0.0" + } + }, + "string.prototype.trimright": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", + "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimend": "^1.0.0" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", + "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "ts-node": { + "version": "8.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.9.1.tgz", + "integrity": "sha512-yrq6ODsxEFTLz0R3BX2myf0WBCSQh9A+py8PBo1dCzWIOcvisbyH6akNKqDHMgXePF2kir5mm5JXJTH3OUJYOQ==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + } + }, + "tslib": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", + "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", + "dev": true + }, + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "typescript": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", + "dev": true + }, + "uglify-js": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.1.tgz", + "integrity": "sha512-JUPoL1jHsc9fOjVFHdQIhqEEJsQvfKDjlubcCilu8U26uZ73qOg8VsN8O1jbuei44ZPlwL7kmbAdM4tzaUvqnA==", + "requires": { + "commander": "~2.20.3" + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "villa": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/villa/-/villa-0.2.11.tgz", + "integrity": "sha1-qZocCsAQJbcxG7VQwfp/jmVwaSo=" + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz", + "integrity": "sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ==", + "requires": { + "is-bigint": "^1.0.0", + "is-boolean-object": "^1.0.0", + "is-number-object": "^1.0.3", + "is-string": "^1.0.4", + "is-symbol": "^1.0.2" + } + }, + "which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, + "which-typed-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.2.tgz", + "integrity": "sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ==", + "requires": { + "available-typed-arrays": "^1.0.2", + "es-abstract": "^1.17.5", + "foreach": "^2.0.5", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.1", + "is-typed-array": "^1.1.3" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + } + } +} diff --git a/package.json b/package.json index aa62812..bc45fcf 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,49 @@ { - "name": "handlebars-spec", - "version": "4.0.5", - "description": "", - "main": "bin/index.js", - "scripts": { - "test": "bin/runner.js" - }, - "author": "John Boehr ", - "contributors": [ - "Kasper Isager " - ], - "license": "MIT", - "dependencies": { - "commander": "^2.2.x", - "extend": "^1.2.x", - "handlebars": "4.0.5", - "jshint": "2.5.x" - } + "name": "handlebars-spec", + "version": "104.6.4", + "description": "", + "author": "John Boehr ", + "contributors": [ + "Kasper Isager " + ], + "license": "AGPL-3.0-or-later", + "repository": "https://github.com/jbboehr/handlebars-spec.git", + "dependencies": { + "clime": "^0.5.10", + "deep-equal": "^2.0.3", + "extend": "^3.0.2", + "handlebars": "4.7.6", + "hjson": "^3.2.1", + "sha1": "^1.1.1", + "sinon": "^9.0.2", + "uglify-js": "^3.9.1" + }, + "devDependencies": { + "@types/deep-equal": "^1.0.1", + "@types/extend": "^3.0.1", + "@types/hjson": "^2.4.1", + "@types/node": "^13.13.4", + "@types/sinon": "^9.0.0", + "@types/uglify-js": "^3.9.0", + "@typescript-eslint/eslint-plugin": "^2.30.0", + "@typescript-eslint/parser": "^2.30.0", + "eslint": "^6.8.0", + "eslint-plugin-compat": "^3.5.1", + "eslint-plugin-import": "^2.20.2", + "eslint-plugin-node": "^11.1.0", + "source-map": "^0.7.3", + "ts-node": "^8.9.1", + "typescript": "^3.8.3" + }, + "scripts": { + "build": "tsc", + "extractFunctions": "ts-node --files src/cli.ts extractFunctions", + "format": "eslint --ext .js,.ts --fix .", + "lint": "eslint --ext .js,.ts .", + "generate": "ts-node --files src/cli.ts generate", + "testRunner": "ts-node --files src/cli.ts testRunner" + }, + "engines": { + "node": ">=12.0.0" + } } diff --git a/patch/_functions.hjson b/patch/_functions.hjson new file mode 100644 index 0000000..2d13e9c --- /dev/null +++ b/patch/_functions.hjson @@ -0,0 +1,2359 @@ +{ + "function(_undefined,_null,options){return(_undefined===undefined)+\" \"+(_null===null)+\" \"+typeof options};": { + !code: true + javascript: + ''' + function (_undefined, _null, options) { + return (_undefined === undefined) + ' ' + (_null === null) + ' ' + (typeof options); + } + ''' + php: + ''' + function ($_undefined, $_null, $options) { + return ($_undefined === null ? 'true' : 'false') . ' ' . ($_null === null ? 'true' : 'false') . ' ' . gettype($options); + } + ''' + } + "function(){return\"undefined!\"};": { + !code: true + javascript: + ''' + function () { + return 'undefined!'; + } + ''' + php: + ''' + function() { + return 'undefined!'; + } + ''' + } + "function(){return\"null!\"};": { + !code: true + javascript: + ''' + function () { + return 'null!'; + } + ''' + php: + ''' + function() { + return 'null!'; + } + ''' + } + "function(){return new Handlebars.SafeString(\"&'\\\\<>\")};": { + !code: true + javascript: function () { return new Handlebars.SafeString('&\'\\<>'); } + php: function () { return new SafeString('&\'\\<>'); } + } + "function(){return\"Awesome\"};": { + !code: true + javascript: function () { return 'Awesome'; } + php: function () { return "Awesome"; } + } + "function(){return this.more};": { + !code: true + javascript: function () { return this.more; } + php: function($options) { return $options->scope['more']; } + } + "function(context){return context};": { + !code: true + javascript: function (context) { return context; } + php: function($context) { return $context; } + } + "function(context,options){return options.fn(context)};": { + !code: true + javascript: function (context, options) { return options.fn(context); } + php: function($context, $options) { return $options->fn($context); } + } + "function(options){return options.fn(this)};": { + !code: true + javascript: + ''' + function (options) { + return options.fn(this); + } + ''' + php: + ''' + function($options) { + return $options->fn($options->scope); + } + ''' + } + "function(){return this};": { + !code: true + javascript: function () { return this; } + php: function($context) { return $context; } + } + "function(value){return\"bar \"+value};": { + !code: true + javascript: + ''' + function (value) { + return 'bar ' + value; + } + ''' + php: function($value) { return 'bar ' . $value; } + } + "function(value){return value};": { + !code: true + javascript: function (value) { return value; } + php: function($value) { return $value; } + } + "function(arg){return\"bar\"+arg};": { + !code: true + javascript: function (arg) { return 'bar' + arg; } + php: function($arg) { return 'bar' . $arg; } + } + "function(){return\"bar\"};": { + !code: true + javascript: function () { return 'bar'; } + php: function() { return 'bar'; } + } + "function(arg){return arg};": { + !code: true + javascript: function (arg) { return arg; } + php: function($arg) { return $arg; } + } + "function(options){return options.fn.run};": { + !code: true + javascript: + ''' + function (options) { + return options.fn.run; + } + ''' + php: + ''' + function($options) { + return $options->fn->run; + } + ''' + } + "function(fn){fn.run=\"success\";return fn};": { + !code: true + javascript: + ''' + function (fn) { + fn.run = 'success'; + return fn; + } + ''' + php: + ''' + function($fn) { + $fn->run = 'success'; + return $fn; + } + ''' + } + "function(options){return options.fn()+options.fn.run};": { + !code: true + javascript: + ''' + function (options) { + return options.fn() + options.fn.run; + } + ''' + php: + ''' + function($options) { + return $options->fn() . $options->fn->run; + } + ''' + } + "function(fn){fn.run=\"cess\"};": { + !code: true + javascript: + ''' + function (fn) { + fn.run = 'cess'; + } + ''' + php: + ''' + function($fn) { + $fn->run = 'cess'; + } + ''' + } + "function(fn,props,container,options){fn.run=options.fn();return fn};": { + !code: true + javascript: + ''' + function (fn, props, container, options) { + fn.run = options.fn(); + return fn; + } + ''' + php: + ''' + function($fn, $props, $container, $options) { + $fn->run = $options->fn(); + return $fn; + } + ''' + } + "function(fn,props,container,options){fn.run=options.fn.nested+options.fn();return fn};": { + !code: true + javascript: + ''' + function (fn, props, container, options) { + fn.run = options.fn.nested + options.fn(); + return fn; + } + ''' + php: + ''' + function($fn, $props, $container, $options) { + $fn->run = $options->fn->nested . $options->fn(); + return $fn; + } + ''' + } + "function(fn,props,container,options){props.nested=options.fn()};": { + !code: true + javascript: + ''' + function (fn, props, container, options) { + props.nested = options.fn(); + } + ''' + php: + ''' + function($fn, $props, $container, $options) { + $props->nested = $options->fn(); + } + ''' + } + "function(fn,props,container,options){fn.run=(fn.run||\"\")+options.fn();return fn};": { + !code: true + javascript: + ''' + function (fn, props, container, options) { + fn.run = (fn.run || '') + options.fn(); + return fn; + } + ''' + php: + ''' + function($fn, $props, $container, $options) { + $fn->run = (isset($fn->run) ? $fn->run : '') . $options->fn(); + return $fn; + } + ''' + } + "function(fn,props,container,options){fn.run=options.args;return fn};": { + !code: true + javascript: + ''' + function (fn, props, container, options) { + fn.run = options.args; + return fn; + } + ''' + php: + ''' + function($fn, $props, $container, $options) { + $fn->run = $options->args; + return $fn; + } + ''' + } + "function(fn,props,container,options){equals(options.args[0],\"success\");run=true;return fn};": { + !code: true + javascript: + ''' + function (fn, props, container, options) { + equals(options.args[0], 'success'); + run = true; + return fn; + } + ''' + php: + ''' + function($fn, $props, $container, $options) { + assert('$options->args[0] === "success"'); + return $fn; + } + ''' + } + "function(fn,props,container,options){equals(options.args[0],undefined);global.run=true;return fn};": { + !code: true + javascript: + ''' + function (fn, props, container, options) { + equals(options.args[0], undefined); + global.run = true; + return fn; + } + ''' + } + "function(){return true};": { + !code: true + javascript: + ''' + function () { + return true; + } + ''' + php: + ''' + function() { + return true; + } + ''' + } + "function(){return this.world};": { + !code: true + javascript: function () {return this.world; } + php: function($scope) { return $scope['world']; } + } + "function(){return false};": { + !code: true + javascript: function () { return false; } + php: function() { return false; } + } + "function(){return this.foo};": { + !code: true + javascript: function () {return this.foo; } + php: function($scope) { return isset($scope['foo']) ? $scope['foo'] : null; } + } + "function(){return{first:\"Alan\",last:\"Johnson\"}};": { + !code: true + javascript: function () { return {first: 'Alan', last: 'Johnson'}; } + php: function() { return array("first" => "Alan", "last" => "Johnson"); } + } + "function(options){return options.data&&options.data.exclaim};": { + !code: true + javascript: function(options) { return options.data && options.data.exclaim; } + php: function($options) { return isset($options['data']['exclaim'])? $options['data']['exclaim'] : ''; } + } + "function(){return[{text:\"goodbye\"},{text:\"Goodbye\"},{text:\"GOODBYE\"}]};": { + !code: true + javascript: function () { return [{text: 'goodbye'}, {text: 'Goodbye'}, {text: 'GOODBYE'}]; } + php: function() { return array(array("text" => "goodbye"), array("text" => "Goodbye"), array("text" => "GOODBYE")); } + } + "function(options){return options.data.adjective+\" \"+this.noun};": { + !code: true + javascript: + ''' + function (options) { + return options.data.adjective + ' ' + this.noun; + } + ''' + php: + ''' + function($options) { + return $options['data']['adjective'] . " " . $options->scope['noun']; + } + ''' + } + "function(options){var frame=Handlebars.createFrame(options.data);for(var prop in options.hash){if(prop in options.hash){frame[prop]=options.hash[prop]}}return options.fn(this,{data:frame})};": { + !code: true + javascript: + ''' + function (options) { + var frame = Handlebars.createFrame(options.data); + for (var prop in options.hash) { + if (prop in options.hash) { + frame[prop] = options.hash[prop]; + } + } + return options.fn(this, {data: frame}); + } + ''' + php: + ''' + function($options) { + $frame = Utils::createFrame($options['data']); + foreach( $options['hash'] as $prop => $v ) { + $frame[$prop] = $options['hash'][$prop]; + } + return $options->fn($options->scope, array("data" => $frame)); + } + ''' + } + "function(noun){return\"Hello \"+noun};": { + !code: true + javascript: + ''' + function (noun) { + return 'Hello ' + noun; + } + ''' + php: function($noun) { return "Hello " . ($noun === null ? 'undefined' : $noun); } + } + "function(options){return\"Hello \"+options.hash.noun};": { + !code: true + javascript: + ''' + function (options) { + return 'Hello ' + options.hash.noun; + } + ''' + php: function($options) { return "Hello " . $options['hash']['noun']; } + } + "function(){return\"hello\"};": { + !code: true + javascript: function () { return 'hello'; } + php: function() { return 'hello'; } + } + "function(noun,options){return options.data.adjective+\" \"+noun+(this.exclaim?\"!\":\"\")};": { + !code: true + javascript: + ''' + function (noun, options) { + return options.data.adjective + ' ' + noun + (this.exclaim ? '!' : ''); + } + ''' + php: + ''' + function($noun, $options) { + return $options['data']['adjective'] . " " . $noun . ($options->scope['exclaim'] ? "!" : ""); + } + ''' + } + "function(options){return options.data.adjective+\" world\"+(this.exclaim?\"!\":\"\")};": { + !code: true + javascript: + ''' + function (options) { + return options.data.adjective + ' world' + (this.exclaim ? '!' : ''); + } + ''' + php: + ''' + function($options) { + return $options['data']['adjective'] . " world" . ($options->scope['exclaim'] ? "!" : ""); + } + ''' + } + "function(options){return options.fn({exclaim:\"?\"})};": { + !code: true + javascript: + ''' + function (options) { + return options.fn({exclaim: '?'}); + } + ''' + php: + ''' + function($options) { + return $options->fn(array("exclaim" => "?")); + } + ''' + } + "function(thing,options){return options.data.adjective+\" \"+thing+(this.exclaim||\"\")};": { + !code: true + javascript: + ''' + function (thing, options) { + return options.data.adjective + ' ' + thing + (this.exclaim || ''); + } + ''' + php: + ''' + function($thing, $options) { + return $options['data']['adjective'] . " " . $thing . ($options->scope['exclaim'] ?: ""); + } + ''' + } + "function(options){return options.data.accessData+\" \"+options.fn({exclaim:\"?\"})};": { + !code: true + javascript: + ''' + function (options) { + return options.data.accessData + ' ' + options.fn({exclaim: '?'}); + } + ''' + php: + ''' + function($options) { + return $options['data']['accessData'] . " " . $options->fn(array("exclaim" => "?")); + } + ''' + } + "function(options){return options.fn({exclaim:\"?\",zomg:\"world\"},{data:{adjective:\"sad\"}})};": { + !code: true + javascript: + ''' + function (options) { + return options.fn({exclaim: '?', zomg: 'world'}, { data: {adjective: 'sad'} }); + } + ''' + php: + ''' + function($options) { + return $options->fn(array("exclaim" => "?", "zomg" => "world"), array("data" => array("adjective" => "sad"))); + } + ''' + } + "function(options){return options.fn({exclaim:\"?\"},{data:{adjective:\"sad\"}})};": { + !code: true + javascript: + ''' + function (options) { + return options.fn({exclaim: '?'}, { data: {adjective: 'sad'} }); + } + ''' + php: + ''' + function($options) { + return $options->fn(array("exclaim" => "?"), array("data" => array("adjective" => "sad"))); + } + ''' + } + "function(options){var frame=Handlebars.createFrame(options.data);frame.depth=options.data.depth+1;return options.fn(this,{data:frame})};": { + !code: true + javascript: + ''' + function (options) { + var frame = Handlebars.createFrame(options.data); + frame.depth = options.data.depth + 1; + return options.fn(this, {data: frame}); + } + ''' + php: + ''' + function($options) { + $frame = Utils::createFrame($options['data']); + $frame['depth'] = $options['data']['depth'] + 1; + return $options->fn($options->scope, array("data" => $frame)); + } + ''' + } + "function(prefix){return''+this.text+\"\"};": { + !code: true + javascript: + ''' + function (prefix) { + return '' + this.text + ''; + } + ''' + php: function($prefix, $options) { return '' . $options->scope['text'] . ''; } + } + "function(options){return options.fn()};": { + !code: true + javascript: + ''' + function (options) { + return options.fn(); + } + ''' + php: + ''' + function($options) { + return $options->fn(); + } + ''' + } + "function(a,b,c,options){return options.fn()+a+b+c};": { + !code: true + javascript: + ''' + function (a, b, c, options) { + return options.fn() + a + b + c; + } + ''' + php: + ''' + function($a, $b, $c, $options) { + return $options->fn() . $a . $b . $c; + } + ''' + } + "function(options){var out=\"\";var byes=[\"Goodbye\",\"goodbye\",\"GOODBYE\"];for(var i=0,j=byes.length;ifn($options->scope) . '! '; + } + return $out; + } + ''' + } + "function(options){var out=\"\";var byes=[\"Goodbye\",\"goodbye\",\"GOODBYE\"];for(var i=0,j=byes.length;ifn(); + $out .= '! '; + } + return $out; + } + ''' + } + "function(prefix,options){return''+options.fn(this)+\"\"};": { + !code: true + javascript: + ''' + function (prefix, options) { + return '' + options.fn(this) + ''; + } + ''' + php: function($prefix, $options) { $out = ''; $out .= $options->fn($options->scope); return $out . ''; } + } + "function(){};": { + !code: true + javascript: function () {} + php: function() {} + } + "function(options){return options.fn({text:\"GOODBYE\"})};": { + !code: true + javascript: function (options) { return options.fn({text: 'GOODBYE'}); } + php: function($options) { return $options->fn(array('text' => 'GOODBYE')); } + } + "function(options){return\"
\"+options.fn(this)+\"
\"};": { + !code: true + javascript: function (options) { return '
' + options.fn(this) + '
'; } + php: function($options) { $out = '
'; $out .= $options->fn($options->scope); return $out . '
'; } + } + "function link(options){return''+options.fn(this)+\"\"};": { + !code: true + javascript: + ''' + function link(options) { + return '' + options.fn(this) + ''; + } + ''' + php: + ''' + function($options) { + return '' . $options->fn($options->scope) . ''; + } + ''' + } + "function(context,options){return\"
\"+options.fn(context)+\"
\"};": { + !code: true + javascript: function (context, options) { return '
' + options.fn(context) + '
'; } + php: + ''' + function($context, $options) { + $out = '
'; + $out .= $options->fn($context); + return $out . '
'; + } + ''' + } + "function(options){return''+options.fn(this)+\"\"};": { + !code: true + javascript: function (options) { return '' + options.fn(this) + ''; } + php: + ''' + function($options) { + $out = ''; + $out .= $options->fn($options->scope); + return $out . ''; + } + ''' + } + "function list(context,options){if(context.length>0){var out=\"
    \";for(var i=0,j=context.length;i\";out+=options.fn(context[i]);out+=\"\"}out+=\"
\";return out}else{return\"

\"+options.inverse(this)+\"

\"}};": { + !code: true + javascript: + ''' + function list(context, options) { + if (context.length > 0) { + var out = '
    '; + for (var i = 0, j = context.length; i < j; i++) { + out += '
  • '; + out += options.fn(context[i]); + out += '
  • '; + } + out += '
'; + return out; + } else { + return '

' + options.inverse(this) + '

'; + } + } + ''' + php: + ''' + function($context, $options) { + $out = ''; + if (count($context) > 0) { + $out .= '
    '; + foreach ($context as $row) { + $out .= '
  • '; + $out .= $options->fn($row); + $out .= '
  • '; + } + $out .= '
'; + } elseif (isset($options->inverse)) { + $out .= '

'; + $out .= $options->inverse($options->scope); + $out .= '

'; + } + return $out; + } + ''' + } + "function(){return\"winning\"};": { + !code: true + javascript: + ''' + function () { + return 'winning'; + } + ''' + php: + ''' + function() { + return 'winning'; + } + ''' + } + "function(){return\"fail\"};": { + !code: true + javascript: function () { return 'fail'; } + php: function() { return 'fail'; } + } + "function(){return\"world\"};": { + !code: true + javascript: function () { return 'world'; } + php: function() { return 'world'; } + } + "function(){return\"helpers\"};": { + !code: true + javascript: function () { return 'helpers'; } + php: function() { return 'helpers'; } + } + "function(){return\"helper\"};": { + !code: true + javascript: function () { return 'helper'; } + php: function() { return 'helper'; } + } + "function(){return\"found it!\"};": { + !code: true + javascript: function () { return 'found it!'; } + php: function() { return 'found it!'; } + } + "function(){return\"world!\"};": { + !code: true + javascript: function () { return 'world!'; } + php: function() { return 'world!'; } + } + "function(times,times2){if(typeof times!==\"number\"){times=\"NaN\"}if(typeof times2!==\"number\"){times2=\"NaN\"}return\"Hello \"+times+\" \"+times2+\" times\"};": { + !code: true + javascript: + ''' + function (times, times2) { + if (typeof times !== 'number') { times = 'NaN'; } + if (typeof times2 !== 'number') { times2 = 'NaN'; } + return 'Hello ' + times + ' ' + times2 + ' times'; + } + ''' + php: + ''' + function($times, $times2) { + if (!is_numeric($times)) { + $times = 'NaN'; + } + if (!is_numeric($times2)) { + $times2 = "NaN"; + } + return "Hello $times $times2 times"; + } + ''' + } + "function(times){if(typeof times!==\"number\"){times=\"NaN\"}return\"Hello \"+times+\" times\"};": { + !code: true + javascript: + ''' + function (times) { + if (typeof times !== 'number') { times = 'NaN'; } + return 'Hello ' + times + ' times'; + } + ''' + php: + ''' + function($times) { + if(!is_numeric($times)) { + $times = "NaN"; + } + return "Hello $times times"; + } + ''' + } + "function(param,times,bool1,bool2){if(typeof times!==\"number\"){times=\"NaN\"}if(typeof bool1!==\"boolean\"){bool1=\"NaB\"}if(typeof bool2!==\"boolean\"){bool2=\"NaB\"}return\"Hello \"+param+\" \"+times+\" times: \"+bool1+\" \"+bool2};": { + !code: true + javascript: + ''' + function (param, times, bool1, bool2) { + if (typeof times !== 'number') { times = 'NaN'; } + if (typeof bool1 !== 'boolean') { bool1 = 'NaB'; } + if (typeof bool2 !== 'boolean') { bool2 = 'NaB'; } + return 'Hello ' + param + ' ' + times + ' times: ' + bool1 + ' ' + bool2; + } + ''' + php: + ''' + function($param, $times, $bool1, $bool2) { + if(!is_numeric($times)) { $times = "NaN"; } + if(!is_bool($bool1)) { + $bool1 = "NaB"; + } else { + $bool1 = ($bool1 ? 'true' : 'false'); + } + if(!is_bool($bool2)) { + $bool2 = "NaB"; + } else { + $bool2 = ($bool2 ? 'true' : 'false'); + } + + return "Hello $param $times times: $bool1 $bool2"; + } + ''' + } + "function(param){return\"Hello \"+param};": { + !code: true + javascript: function (param) { return 'Hello ' + param; } + php: function($param) { return "Hello " . $param; } + } + "function(cruel,world){return\"Goodbye \"+cruel+\" \"+world};": { + !code: true + javascript: function (cruel, world) { return 'Goodbye ' + cruel + ' ' + world; } + php: function($cruel, $world) { return 'Goodbye ' . $cruel . ' ' . $world; } + } + "function(cruel,world,options){return options.fn({greeting:\"Goodbye\",adj:cruel,noun:world})};": { + !code: true + javascript: + ''' + function (cruel, world, options) { + return options.fn({greeting: 'Goodbye', adj: cruel, noun: world}); + } + ''' + php: + ''' + function($cruel, $world, $options) { + return $options->fn(array('greeting' => 'Goodbye', 'adj' => 'cruel', 'noun' => 'world')); + } + ''' + } + "function(options){return\"GOODBYE \"+options.hash.cruel+\" \"+options.hash.world+\" \"+options.hash.times+\" TIMES\"};": { + !code: true + javascript: + ''' + function (options) { + return 'GOODBYE ' + options.hash.cruel + ' ' + options.hash.world + ' ' + options.hash.times + ' TIMES'; + } + ''' + php: + ''' + function($options) { + $r = 'GOODBYE '; + $r .= $options['hash']['cruel'].' '; + $r .= $options['hash']['world'].' '; + $r .= $options['hash']['times'].' TIMES'; + + return $r; + } + ''' + } + "function goodbye(options){if(options.hash.print===true){return\"GOODBYE \"+options.hash.cruel+\" \"+options.hash.world}else if(options.hash.print===false){return\"NOT PRINTING\"}else{return\"THIS SHOULD NOT HAPPEN\"}};": { + !code: true + javascript: + ''' + function goodbye(options) { + if (options.hash.print === true) { + return 'GOODBYE ' + options.hash.cruel + ' ' + options.hash.world; + } else if (options.hash.print === false) { + return 'NOT PRINTING'; + } else { + return 'THIS SHOULD NOT HAPPEN'; + } + } + ''' + php: + ''' + function ($options) { + if ($options['hash']['print'] === true) { + return 'GOODBYE ' . $options['hash']['cruel'] . ' ' . $options['hash']['world']; + } else if ($options['hash']['print'] === false) { + return 'NOT PRINTING'; + } else { + return 'THIS SHOULD NOT HAPPEN'; + } + } + ''' + } + "function(options){return\"GOODBYE \"+options.hash.cruel+\" \"+options.fn(this)+\" \"+options.hash.times+\" TIMES\"};": { + !code: true + javascript: + ''' + function (options) { + return 'GOODBYE ' + options.hash.cruel + ' ' + options.fn(this) + ' ' + options.hash.times + ' TIMES'; + } + ''' + php: + ''' + function($options) { + return "GOODBYE {$options['hash']['cruel']} " . $options->fn($options->scope) . " {$options['hash']['times']} TIMES"; + } + ''' + } + "function goodbye(options){if(options.hash.print===true){return\"GOODBYE \"+options.hash.cruel+\" \"+options.fn(this)}else if(options.hash.print===false){return\"NOT PRINTING\"}else{return\"THIS SHOULD NOT HAPPEN\"}};": { + !code: true + javascript: + ''' + function goodbye(options) { + if (options.hash.print === true) { + return 'GOODBYE ' + options.hash.cruel + ' ' + options.fn(this); + } else if (options.hash.print === false) { + return 'NOT PRINTING'; + } else { + return 'THIS SHOULD NOT HAPPEN'; + } + } + ''' + php: + ''' + function ($options) { + if ($options['hash']['print'] === true) { + return 'GOODBYE ' . $options['hash']['cruel'] . ' ' . $options->fn($options->scope); + } else if ($options['hash']['print'] === false) { + return 'NOT PRINTING'; + } else { + return 'THIS SHOULD NOT HAPPEN'; + } + } + ''' + } + "function(mesg,options){if(options.name===\"link_to\"){return new Handlebars.SafeString(\"\"+mesg+\"\")}};": { + !code: true + javascript: + ''' + function (mesg, options) { + if (options.name === 'link_to') { + return new Handlebars.SafeString('' + mesg + ''); + } + } + ''' + php: + ''' + function($mesg, $options = null) { + if($options && $options['name'] === "link_to") { + return new SafeString("" . $mesg . ""); + } + } + ''' + } + "function(options){if(options.name===\"link_to\"){return new Handlebars.SafeString(\"winning\")}};": { + !code: true + javascript: + ''' + function (options) { + if (options.name === 'link_to') { + return new Handlebars.SafeString('winning'); + } + } + ''' + php: + ''' + function($options) { + if($options['name'] === "link_to") { + return new SafeString("winning"); + } + } + ''' + } + "function(){return\"foo\"};": { + !code: true + javascript: + ''' + function () { + return 'foo'; + } + ''' + php: + ''' + function() { + return 'foo'; + } + ''' + } + "function(arg){return typeof arg};": { + !code: true + javascript: function (arg) { return typeof arg; } + php: function($arg) { return $arg === null ? 'undefined' : gettype($arg); } + } + "function(){return this.bar};": { + !code: true + javascript: function () { return this.bar; } + php: function($context) { return $context['bar']; } + } + "function(){return this.truthiness()};": { + !code: true + javascript: function () { return this.truthiness(); } + php: function($options) { return $options->scope['truthiness'](); } + } + "function(){return\"missing: \"+arguments[arguments.length-1].name};": { + !code: true + javascript: + ''' + function () { + return 'missing: ' + arguments[arguments.length - 1].name; + } + ''' + php: + ''' + function() { + $arguments = func_get_args(); + return 'missing: ' . $arguments[count($arguments)-1]['name']; + } + ''' + } + "function(){return\"helper missing: \"+arguments[arguments.length-1].name};": { + !code: true + javascript: + ''' + function () { + return 'helper missing: ' + arguments[arguments.length - 1].name; + } + ''' + php: + ''' + function() { + $arguments = func_get_args(); + return 'helper missing: ' . $arguments[count($arguments)-1]['name']; + } + ''' + } + "function(){return\"ran: \"+arguments[arguments.length-1].name};": { + !code: true + javascript: + ''' + function () { + return 'ran: ' + arguments[arguments.length - 1].name; + } + ''' + php: + ''' + function() { + $arguments = func_get_args(); + return 'ran: ' . $arguments[count($arguments)-1]['name']; + } + ''' + } + "function(){return this.goodbye.toUpperCase()};": { + !code: true + javascript: + ''' + function () { + return this.goodbye.toUpperCase(); + } + ''' + php: + ''' + function($options) { + return strtoupper($options->scope['goodbye']); + } + ''' + } + "function(world){return\"cruel \"+world.toUpperCase()};": { + !code: true + javascript: + ''' + function (world) { + return 'cruel ' + world.toUpperCase(); + } + ''' + php: + ''' + function($world) { + return "cruel " . strtoupper($world); + } + ''' + } + "function(options){return this.goodbye.toUpperCase()+options.fn(this)};": { + !code: true + javascript: + ''' + function (options) { + return this.goodbye.toUpperCase() + options.fn(this); + } + ''' + php: + ''' + function($options) { + return strtoupper($options->scope['goodbye']) . $options->fn($options->scope); + } + ''' + } + "function(options){equals(options.fn.blockParams,1);return options.fn({value:\"bar\"},{blockParams:[1,2]})};": { + !code: true + javascript: + ''' + function (options) { + equals(options.fn.blockParams, 1); + return options.fn({value: 'bar'}, {blockParams: [1, 2]}); + } + ''' + php: + ''' + function($options) { + return $options->fn(array('value' => 'bar'), array('blockParams' => array(1, 2))); + } + ''' + } + "function(options){equals(options.fn.blockParams,1);return options.fn({},{blockParams:[1,2]})};": { + !code: true + javascript: + ''' + function (options) { + equals(options.fn.blockParams, 1); + return options.fn({}, {blockParams: [1, 2]}); + } + ''' + php: + ''' + function($options) { + return $options->fn(array(), array('blockParams' => array(1, 2))); + } + ''' + } + "function(options){equals(options.fn.blockParams,1);return options.fn(this,{blockParams:[1,2]})};": { + !code: true + javascript: + ''' + function (options) { + equals(options.fn.blockParams, 1); + return options.fn(this, {blockParams: [1, 2]}); + } + ''' + php: + ''' + function($options) { + return $options->fn($options->scope, array('blockParams' => array(1, 2))); + } + ''' + } + "function(options){if(typeof value===\"undefined\"){value=1}return options.fn({value:\"bar\"},{blockParams:options.fn.blockParams===1?[global.value++,global.value++]:undefined})};": { + !code: true + javascript: + ''' + function (options) { + if( typeof value === 'undefined' ) { value = 1; } return options.fn({value: 'bar'}, {blockParams: options.fn.blockParams === 1 ? [global.value++, global.value++] : undefined}); + } + ''' + } + "function testHelper(options){return options.lookupProperty(this,\"testProperty\")};": { + !code: true + javascript: + ''' + function testHelper(options) { + return options.lookupProperty(this, 'testProperty'); + } + ''' + php: + ''' + function ($options) { + return $options->lookupProperty($options->scope, 'testProperty'); + } + ''' + } + "function(){return\"dude\"};": { + !code: true + javascript: + ''' + function () { + return 'dude'; + } + ''' + php: + ''' + function() { + return 'dude'; + } + ''' + } + "function(){return\"missing\"};": { + !code: true + javascript: + ''' + function () { + return 'missing'; + } + ''' + php: + ''' + function() { + return 'missing'; + } + ''' + } + "function partial(context){return context.name+\" (\"+context.url+\") \"};": { + !code: true + javascript: + ''' + function partial(context) { + return context.name + ' (' + context.url + ') '; + } + ''' + php: + ''' + function($context) { + return $context['name'] . ' (' . $context['url'] . ') '; + } + ''' + } + "function(){return\"blah\"};": { + !code: true + javascript: + ''' + function () { + return 'blah'; + } + ''' + php: + ''' + function() { + return "blah"; + } + ''' + } + "function(block){return block.fn(\"\")};": { + !code: true + javascript: function (block) { return block.fn(''); } + php: function($block) { return $block/*['fn']*/->fn(''); } + } + "function(block){return block.inverse(\"\")};": { + !code: true + javascript: function (block) { return block.inverse(''); } + php: function($block) { return $block/*['inverse']*/->inverse(''); } + } + "function(value){return value+\"\"};": { + !code: true + javascript: function (value) { return value + ''; } + php: function($value) { return $value === null ? 'undefined' : (string) $value; } + } + "function(options){return new Handlebars.SafeString(options.fn())};": { + !code: true + javascript: + ''' + function (options) { + return new Handlebars.SafeString(options.fn()); + } + ''' + php: + ''' + function($options) { + return new \Handlebars\SafeString($options->fn()); + } + ''' + } + "function(){for(var name in this){if(Object.prototype.hasOwnProperty.call(this,name)){return\"found\"}}return this===\"bat\"?\"found\":\"not\"};": { + !code: true + javascript: + ''' + function() { + // It's valid to execute a block against an undefined context, but + // helpers can not do so, so we expect to have an empty object here; + for (var name in this) { + if (Object.prototype.hasOwnProperty.call(this, name)) { + return 'found'; + } + } + // And to make IE happy, check for the known string as length is not enumerated. + return this === 'bat' ? 'found' : 'not'; + } + ''' + php: + ''' + function() { + return 'found'; + } + ''' + } + "function(conditional,options){if(conditional){return options.fn(this)}else{return options.inverse(this)}};": { + !code: true + javascript: + ''' + function(conditional, options) { + if (conditional) { + return options.fn(this); + } else { + return options.inverse(this); + } + } + ''' + php: + ''' + function($conditional, $options) { + if ($conditional) { + return $options->fn($options->scope); + } else { + return $options->inverse($options->scope); + } + } + ''' + } + "function(options){return options.hash.length};": { + !code: true + javascript: + ''' + function(options) { + return options.hash.length; + } + ''' + php: + ''' + function($options) { + return $options['hash']['length']; + } + ''' + } + "function(options){equals(\"value\"in options.hash,true);equals(options.hash.value,undefined);return\"success\"};": { + !code: true + javascript: + ''' + function (options) { + equals('value' in options.hash, true); + equals(options.hash.value, undefined); + return 'success'; + } + ''' + php: + ''' + function () { + return 'success'; + } + ''' + } + "function(passiveVoice,noun){return\"HELP ME MY BOSS \"+passiveVoice+\" \"+noun};": { + !code: true + javascript: + ''' + function (passiveVoice, noun) { + return 'HELP ME MY BOSS ' + passiveVoice + ' ' + noun; + } + ''' + php: + ''' + function($passiveVoice, $noun) { + return "HELP ME MY BOSS " . $passiveVoice . ' ' . $noun; + } + ''' + } + "function(passiveVoice,noun,options){return\"HELP ME MY BOSS \"+passiveVoice+\" \"+noun+\": \"+options.fn(this)};": { + !code: true + javascript: + ''' + function (passiveVoice, noun, options) { + return 'HELP ME MY BOSS ' + passiveVoice + ' ' + + noun + ': ' + options.fn(this); + } + ''' + php: + ''' + function($passiveVoice, $noun, $options) { + return "HELP ME MY BOSS " . $passiveVoice . ' ' . + $noun . ': ' . $options->fn($options->scope); + } + ''' + } + "function(desire,noun,options){return\"STOP ME FROM READING HACKER NEWS I \"+options.contexts[0][desire]+\" \"+noun};": { + !code: true + javascript: + ''' + function (desire, noun, options) { + return 'STOP ME FROM READING HACKER NEWS I ' + + options.contexts[0][desire] + ' ' + noun; + } + ''' + php: + ''' + function($desire, $noun, $options) { + return "STOP ME FROM READING HACKER NEWS I " . + $options['contexts'][0][$desire] . " " . $noun; + } + ''' + } + "function(context,options){return options.fn(options.contexts[0][context])};": { + !code: true + javascript: + ''' + function (context, options) { + return options.fn(options.contexts[0][context]); + } + ''' + php: + ''' + function($context, $options) { + return $options->fn($options['contexts'][0][$context]); + } + ''' + } + "function(desire,noun,trueBool,falseBool,options){equal(options.types[0],\"StringLiteral\",\"the string type is passed\");equal(options.types[1],\"PathExpression\",\"the expression type is passed\");equal(options.types[2],\"BooleanLiteral\",\"the expression type is passed\");equal(desire,\"need\",\"the string form is passed for strings\");equal(noun,\"dad.joke\",\"the string form is passed for expressions\");equal(trueBool,true,\"raw booleans are passed through\");equal(falseBool,false,\"raw booleans are passed through\");return\"Helper called\"};": { + !code: true + javascript: + ''' + function(desire, noun, trueBool, falseBool, options) { + equal(options.types[0], 'StringLiteral', 'the string type is passed'); + equal( + options.types[1], + 'PathExpression', + 'the expression type is passed' + ); + equal( + options.types[2], + 'BooleanLiteral', + 'the expression type is passed' + ); + equal(desire, 'need', 'the string form is passed for strings'); + equal(noun, 'dad.joke', 'the string form is passed for expressions'); + equal(trueBool, true, 'raw booleans are passed through'); + equal(falseBool, false, 'raw booleans are passed through'); + return 'Helper called'; + } + ''' + } + "function(exclamation,options){equal(exclamation,\"he.says\");equal(options.types[0],\"PathExpression\");equal(options.hashTypes.desire,\"StringLiteral\");equal(options.hashTypes.noun,\"PathExpression\");equal(options.hashTypes.bool,\"BooleanLiteral\");equal(options.hash.desire,\"need\");equal(options.hash.noun,\"dad.joke\");equal(options.hash.bool,true);return\"Helper called\"};": { + !code: true + javascript: + ''' + function(exclamation, options) { + equal(exclamation, 'he.says'); + equal(options.types[0], 'PathExpression'); + + equal(options.hashTypes.desire, 'StringLiteral'); + equal(options.hashTypes.noun, 'PathExpression'); + equal(options.hashTypes.bool, 'BooleanLiteral'); + equal(options.hash.desire, 'need'); + equal(options.hash.noun, 'dad.joke'); + equal(options.hash.bool, true); + return 'Helper called'; + } + ''' + } + "function(desire,noun,options){return\"STOP ME FROM READING HACKER NEWS I \"+options.contexts[0][desire]+\" \"+noun+\" \"+options.fn(this)};": { + !code: true + javascript: + ''' + function (desire, noun, options) { + return 'STOP ME FROM READING HACKER NEWS I ' + + options.contexts[0][desire] + ' ' + noun + ' ' + + options.fn(this); + } + ''' + php: + ''' + function($desire, $noun, $options) { + return "STOP ME FROM READING HACKER NEWS I " . + $options['contexts'][0][$desire] . " " . $noun . " " . + $options->fn($options->scope); + } + ''' + } + "function(){return\"WITH\"};": { + !code: true + javascript: + ''' + function () { + return 'WITH'; + } + ''' + php: + ''' + function($options) { + return "WITH"; + } + ''' + } + "function(){return\"VIEW\"};": { + !code: true + javascript: + ''' + function () { + return 'VIEW'; + } + ''' + php: + ''' + function() { + return "VIEW"; + } + ''' + } + "function(bar,options){equal(bar,\"@bar\");equal(options.types[0],\"PathExpression\");return\"Foo!\"};": { + !code: true + javascript: + ''' + function (bar, options) { + equal(bar, '@bar'); + equal(options.types[0], 'PathExpression'); + return 'Foo!'; + } + ''' + php: + ''' + function($bar, $options) { + return 'Foo!'; + } + ''' + } + "function(val){return val+val};": { + !code: true + javascript: + ''' + function (val) { + return val + val; + } + ''' + php: + ''' + function($val) { + return $val . $val; + } + ''' + } + "function(){return\"LOL\"};": { + !code: true + javascript: + ''' + function () { + return 'LOL'; + } + ''' + php: + ''' + function() { + return "LOL"; + } + ''' + } + "function(val){return\"val is \"+val};": { + !code: true + javascript: + ''' + function (val) { + return 'val is ' + val; + } + ''' + php: + ''' + function($val) { + return "val is " . (is_bool($val) ? ($val ? 'true' : 'false') : $val); + } + ''' + } + "function(x,y){return x===y};": { + !code: true + javascript: + ''' + function (x, y) { + return x === y; + } + ''' + php: + ''' + function($x, $y) { + return $x === $y; + } + ''' + } + "function(val,that,theOther){return\"val is \"+val+\", \"+that+\" and \"+theOther};": { + !code: true + javascript: + ''' + function (val, that, theOther) { + return 'val is ' + val + ', ' + that + ' and ' + theOther; + } + ''' + php: + ''' + function($val, $that, $theOther) { + return "val is " . $val . ', ' . (is_bool($that) ? ($that ? 'true' : 'false') : $that) . ' and ' . $theOther; + } + ''' + } + "function(a,b){return a+\"-\"+b};": { + !code: true + javascript: + ''' + function (a, b) { + return a + '-' + b; + } + ''' + php: + ''' + function($a, $b) { + return $a . "-" . $b; + } + ''' + } + "function(a,b){return a+b};": { + !code: true + javascript: + ''' + function (a, b) { + return a + b; + } + ''' + php: + ''' + function($a, $b) { + return $a . $b; + } + ''' + } + "function(x,y,options){if(!options||options===global.lastOptions){throw new Error(\"options hash was reused\")}global.lastOptions=options;return x===y};": { + !code: true + javascript: + ''' + function(x, y, options) { + if (!options || options === global.lastOptions) { + throw new Error('options hash was reused'); + } + global.lastOptions = options; + return x === y; + } + ''' + } + "function(options){return\"val is \"+options.hash.fun};": { + !code: true + javascript: + ''' + function (options) { + return "val is " + options.hash.fun; + } + ''' + php: + ''' + function($options) { + return "val is " . (is_bool($tmp = $options['hash']['fun']) ? ($tmp ? 'true' : 'false') : $tmp); + } + ''' + } + "function(options){var hash=options.hash;var ariaLabel=Handlebars.Utils.escapeExpression(hash[\"aria-label\"]);var placeholder=Handlebars.Utils.escapeExpression(hash.placeholder);return new Handlebars.SafeString('')};": { + !code: true + javascript: + ''' + function (options) { + var hash = options.hash; + var ariaLabel = Handlebars.Utils.escapeExpression(hash['aria-label']); + var placeholder = Handlebars.Utils.escapeExpression(hash.placeholder); + return new Handlebars.SafeString(''); + } + ''' + php: + ''' + function($options) { + $hash = $options['hash']; + $ariaLabel = (string) ($hash['aria-label'] instanceof SafeString ? $hash['aria-label'] : htmlspecialchars($hash['aria-label'])); + $placeholder = (string) ($hash['placeholder'] instanceof SafeString ? $hash['placeholder'] : htmlspecialchars($hash['placeholder'])); + return new SafeString(''); + } + ''' + } + "function(defaultString){return new Handlebars.SafeString(defaultString)};": { + !code: true + javascript: + ''' + function (defaultString) { + return new Handlebars.SafeString(defaultString); + } + ''' + php: + ''' + function($defaultString) { + return new SafeString($defaultString); + } + ''' + } + "function(a,b,options){equals(a,\"foo\");equals(options.types.length,2,\"string params for outer helper processed correctly\");equals(options.types[0],\"SubExpression\",\"string params for outer helper processed correctly\");equals(options.types[1],\"PathExpression\",\"string params for outer helper processed correctly\");return a+b};": { + !code: true + javascript: + ''' + function (a, b, options) { + equals(a, 'foo'); + equals(options.types.length, 2, 'string params for outer helper processed correctly'); + equals(options.types[0], 'SubExpression', 'string params for outer helper processed correctly'); + equals(options.types[1], 'PathExpression', 'string params for outer helper processed correctly'); + return a + b; + } + ''' + php: + ''' + function($a, $b, $options) { + return $a . $b; + } + ''' + } + "function(a,options){equals(options.types.length,1,\"string params for inner helper processed correctly\");equals(options.types[0],\"PathExpression\",\"string params for inner helper processed correctly\");return a};": { + !code: true + javascript: + ''' + function (a, options) { + equals(options.types.length, 1, 'string params for inner helper processed correctly'); + equals(options.types[0], 'PathExpression', 'string params for inner helper processed correctly'); + return a; + } + ''' + php: + ''' + function($a, $options) { + return $a; + } + ''' + } + "function(options){equals(options.hashTypes.fun,\"SubExpression\");return\"val is \"+options.hash.fun};": { + !code: true + javascript: + ''' + function(options) { + equals(options.hashTypes.fun, 'SubExpression'); + return 'val is ' + options.hash.fun; + } + ''' + } + "function(){return\"BORK\"};": { + !code: true + javascript: + ''' + function () { + return 'BORK'; + } + ''' + php: + ''' + function() { + return "BORK"; + } + ''' + } + "function(passiveVoice,noun,options){equal(options.ids,undefined);equal(options.hashIds,undefined);return\"success\"};": { + !code: true + javascript: + ''' + function (passiveVoice, noun, options) { + equal(options.ids, undefined); + equal(options.hashIds, undefined); + + return 'success'; + } + ''' + php: + ''' + function($passiveVoice, $noun, $options) { + return 'success'; + } + ''' + } + "function(passiveVoice,noun,options){equal(options.ids[0],\"is.a\");equal(options.ids[1],\"slave.driver\");return\"HELP ME MY BOSS \"+options.ids[0]+\":\"+passiveVoice+\" \"+options.ids[1]+\":\"+noun};": { + !code: true + javascript: + ''' + function (passiveVoice, noun, options) { + equal(options.ids[0], 'is.a'); + equal(options.ids[1], 'slave.driver'); + + return 'HELP ME MY BOSS ' + options.ids[0] + ':' + passiveVoice + ' ' + options.ids[1] + ':' + noun; + } + ''' + php: + ''' + function($passiveVoice, $noun, $options) { + return "HELP ME MY BOSS " . $options['ids'][0] . ':' . $passiveVoice . ' ' . $options['ids'][1] . ':' . $noun; + } + ''' + } + "function(options){equal(options.hashIds.bat,\"is.a\");equal(options.hashIds.baz,\"slave.driver\");return\"HELP ME MY BOSS \"+options.hashIds.bat+\":\"+options.hash.bat+\" \"+options.hashIds.baz+\":\"+options.hash.baz};": { + !code: true + javascript: + ''' + function (options) { + equal(options.hashIds.bat, 'is.a'); + equal(options.hashIds.baz, 'slave.driver'); + + return 'HELP ME MY BOSS ' + options.hashIds.bat + ':' + options.hash.bat + ' ' + options.hashIds.baz + ':' + options.hash.baz; + } + ''' + php: + ''' + function($options) { + return "HELP ME MY BOSS " . $options['hashIds']['bat'] . ':' . $options['hash']['bat'] . ' ' . $options['hashIds']['baz'] . ':' . $options['hash']['baz']; + } + ''' + } + "function(passiveVoice,noun,thiz,thiz2,options){equal(options.ids[0],\"is.a\");equal(options.ids[1],\"../slave.driver\");equal(options.ids[2],\"is.a\");equal(options.ids[3],\"\");return\"HELP ME MY BOSS \"+options.ids[0]+\":\"+passiveVoice+\" \"+options.ids[1]+\":\"+noun};": { + !code: true + javascript: + ''' + function (passiveVoice, noun, thiz, thiz2, options) { + equal(options.ids[0], 'is.a'); + equal(options.ids[1], '../slave.driver'); + equal(options.ids[2], 'is.a'); + equal(options.ids[3], ''); + + return 'HELP ME MY BOSS ' + options.ids[0] + ':' + passiveVoice + ' ' + options.ids[1] + ':' + noun; + } + ''' + php: + ''' + function($passiveVoice, $noun, $thiz, $thiz2, $options) { + return "HELP ME MY BOSS " . $options['ids'][0] . ':' . $passiveVoice . ' ' . $options['ids'][1] . ':' . ($noun === null ? 'undefined' : $noun); + } + ''' + } + "function(passiveVoice,noun,options){equal(options.ids[0],\"@is.a\");equal(options.ids[1],\"@slave.driver\");return\"HELP ME MY BOSS \"+options.ids[0]+\":\"+passiveVoice+\" \"+options.ids[1]+\":\"+noun};": { + !code: true + javascript: + ''' + function (passiveVoice, noun, options) { + equal(options.ids[0], '@is.a'); + equal(options.ids[1], '@slave.driver'); + + return 'HELP ME MY BOSS ' + options.ids[0] + ':' + passiveVoice + ' ' + options.ids[1] + ':' + noun; + } + ''' + php: + ''' + function($passiveVoice, $noun, $options) { + return "HELP ME MY BOSS " . $options['ids'][0] . ':' . $passiveVoice . ' ' . $options['ids'][1] . ':' . $noun; + } + ''' + } + "function(passiveVoice,noun,options){equal(options.ids[0],null);equal(options.ids[1],null);equal(options.hashIds.key,null);return\"HELP ME MY BOSS \"+passiveVoice+\" \"+noun+\" \"+options.hash.key};": { + !code: true + javascript: + ''' + function (passiveVoice, noun, options) { + equal(options.ids[0], null); + equal(options.ids[1], null); + equal(options.hashIds.key, null); + + return 'HELP ME MY BOSS ' + passiveVoice + ' ' + noun + ' ' + options.hash.key; + } + ''' + php: + ''' + function($passiveVoice, $noun, $options) { + return "HELP ME MY BOSS " . $passiveVoice . ' ' . $noun . ' ' . ($options['hash']['key'] === false ? 'false' : $options['hash']['key']); + } + ''' + } + "function(){return 1};": { + !code: true + javascript: function () { return 1; } + php: function() { return 1; } + } + "function(passiveVoice,options){equal(options.ids[0],true);return\"HELP ME MY BOSS \"+passiveVoice};": { + !code: true + javascript: + ''' + function (passiveVoice, options) { + equal(options.ids[0], true); + + return 'HELP ME MY BOSS ' + passiveVoice; + } + ''' + php: + ''' + function($passiveVoice, $options) { + return "HELP ME MY BOSS " . $passiveVoice; + } + ''' + } + "function(options){var blockParams=[this.is];blockParams.path=[\"zomg\"];return options.fn(this,{blockParams:blockParams})};": { + !code: true + javascript: + ''' + function (options) { + var blockParams = [this.is]; + blockParams.path = ['zomg']; + return options.fn(this, {blockParams: blockParams}); + } + ''' + php: + ''' + function($options) { + $blockParams = array($options->scope['is']); + $blockParams['path'] = array('zomg'); + return $options->fn($options->scope, array('blockParams' => $blockParams)); + } + ''' + } + "function(passiveVoice,noun,blah,options){equal(options.ids[0],\"zomg.a\");equal(options.ids[1],\"slave.driver\");equal(options.ids[2],\"zomg\");return\"HELP ME MY BOSS \"+options.ids[0]+\":\"+passiveVoice+\" \"+options.ids[1]+\":\"+noun};": { + !code: true + javascript: + ''' + function (passiveVoice, noun, blah, options) { + equal(options.ids[0], 'zomg.a'); + equal(options.ids[1], 'slave.driver'); + equal(options.ids[2], 'zomg'); + + return 'HELP ME MY BOSS ' + options.ids[0] + ':' + passiveVoice + ' ' + options.ids[1] + ':' + noun; + } + ''' + php: + ''' + function($passiveVoice, $noun, $blah, $options) { + return 'HELP ME MY BOSS ' . $options->ids[0] . ':' . $passiveVoice . ' ' . $options->ids[1] . ':' . $noun; + } + ''' + } + "function(name,options){return name+\":\"+options.ids[0]+\"\\n\"};": { + !code: true + javascript: + ''' + function (name, options) { + return name + ':' + options.ids[0] + '\n'; + } + ''' + php: + ''' + function($name, $options) { + return $name . ':' . $options->ids[0] . "\n"; + } + ''' + } + "function(name,options){return name+\":\"+options.data.contextPath+\"\\n\"};": { + !code: true + javascript: + ''' + function (name, options) { + return name + ':' + options.data.contextPath + '\n'; + } + ''' + php: + ''' + function($name, $options) { + return $name . ':' . $options['data']['contextPath'] . "\n"; + } + ''' + } + "function(fn,props,container,options){equals(options.args[0],undefined);run=true;return fn};": { + !code: true + javascript: + ''' + function(fn, props, container, options) { + equals(options.args[0], undefined); + run = true; + return fn; + } + ''' + } + "function(context,options){var inverse=options.inverse,fn=options.fn;if(context===true){return fn(this)}else if(context===false||context==null){return inverse(this)}else if(_utils.isArray(context)){if(context.length>0){if(options.ids){options.ids=[options.name]}return instance.helpers.each(context,options)}else{return inverse(this)}}else{if(options.data&&options.ids){var data=_utils.createFrame(options.data);data.contextPath=_utils.appendContextPath(options.data.contextPath,options.name);options={data:data}}return fn(context,options)}};": { + !code: true + javascript: + ''' + function (context, options) { + var inverse = options.inverse, + fn = options.fn; + + if (context === true) { + return fn(this); + } else if (context === false || context == null) { + return inverse(this); + } else if (_utils.isArray(context)) { + if (context.length > 0) { + if (options.ids) { + options.ids = [options.name]; + } + + return instance.helpers.each(context, options); + } else { + return inverse(this); + } + } else { + if (options.data && options.ids) { + var data = _utils.createFrame(options.data); + data.contextPath = _utils.appendContextPath(options.data.contextPath, options.name); + options = { data: data }; + } + + return fn(context, options); + } + } + ''' + } + "function(context,options){if(!options){throw new _exception2[\"default\"](\"Must pass iterator to #each\")}var fn=options.fn,inverse=options.inverse,i=0,ret=\"\",data=undefined,contextPath=undefined;if(options.data&&options.ids){contextPath=_utils.appendContextPath(options.data.contextPath,options.ids[0])+\".\"}if(_utils.isFunction(context)){context=context.call(this)}if(options.data){data=_utils.createFrame(options.data)}function execIteration(field,index,last){if(data){data.key=field;data.index=index;data.first=index===0;data.last=!!last;if(contextPath){data.contextPath=contextPath+field}}ret=ret+fn(context[field],{data:data,blockParams:_utils.blockParams([context[field],field],[contextPath+field,null])})}if(context&&typeof context===\"object\"){if(_utils.isArray(context)){for(var j=context.length;ilookupProperty($obj, $field); + } + ''' + } + "function(context,options){if(arguments.length!=2){throw new _exception2[\"default\"](\"#with requires exactly one argument\")}if(_utils.isFunction(context)){context=context.call(this)}var fn=options.fn;if(!_utils.isEmpty(context)){var data=options.data;if(options.data&&options.ids){data=_utils.createFrame(options.data);data.contextPath=_utils.appendContextPath(options.data.contextPath,options.ids[0])}return fn(context,{data:data,blockParams:_utils.blockParams([context],[data&&data.contextPath])})}else{return options.inverse(this)}};": { + !code: true + javascript: + ''' + function (context, options) { + if (arguments.length != 2) { + throw new _exception2['default']('#with requires exactly one argument'); + } + if (_utils.isFunction(context)) { + context = context.call(this); + } + + var fn = options.fn; + + if (!_utils.isEmpty(context)) { + var data = options.data; + if (options.data && options.ids) { + data = _utils.createFrame(options.data); + data.contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]); + } + + return fn(context, { + data: data, + blockParams: _utils.blockParams([context], [data && data.contextPath]) + }); + } else { + return options.inverse(this); + } + } + ''' + } + "function ret(context){var options=arguments.length<=1||arguments[1]===undefined?{}:arguments[1];var data=options.data;ret._setup(options);if(!options.partial&&templateSpec.useData){data=initData(context,data)}var depths=undefined,blockParams=templateSpec.useBlockParams?[]:undefined;if(templateSpec.useDepths){if(options.depths){depths=context!=options.depths[0]?[context].concat(options.depths):options.depths}else{depths=[context]}}function main(context){return\"\"+templateSpec.main(container,context,container.helpers,container.partials,data,blockParams,depths)}main=executeDecorators(templateSpec.main,main,container,options.depths||[],data,blockParams);return main(context,options)};": { + !code: true + javascript: + ''' + function ret(context) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var data = options.data; + + ret._setup(options); + if (!options.partial && templateSpec.useData) { + data = initData(context, data); + } + var depths = undefined, + blockParams = templateSpec.useBlockParams ? [] : undefined; + if (templateSpec.useDepths) { + if (options.depths) { + depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths; + } else { + depths = [context]; + } + } + + function main(context /*, options*/) { + return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths); + } + + main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams); + return main(context, options); + } + ''' + } + "function(options){return options.fn({value:\"bar\"},{blockParams:options.fn.blockParams===1?[value++,value++]:undefined})};": { + !code: true + javascript: + ''' + function(options) { + return options.fn( + { value: 'bar' }, + { + blockParams: + options.fn.blockParams === 1 ? [value++, value++] : undefined + } + ); + } + ''' + php: + ''' + function($options) { + static $value = 0; + return $options->fn( + [ "value" => 'bar' ], + [ + // blockParams probably wrong + "blockParams" => $options->blockParams === 1 ? [$value++, $value++] : null + ] + ); + } + ''' + } + "function(exclamation,options){equal(exclamation,\"he.says\");equal(options.types[0],\"PathExpression\");equal(options.contexts.length,1);equal(options.hashContexts.noun,context);equal(options.hash.desire,\"need\");equal(options.hash.noun,\"dad.joke\");equal(options.hash.bool,true);return\"Helper called\"};": { + !code: true + javascript: + ''' + function(exclamation, options) { + equal(exclamation, 'he.says'); + equal(options.types[0], 'PathExpression'); + + equal(options.contexts.length, 1); + equal(options.hashContexts.noun, context); + equal(options.hash.desire, 'need'); + equal(options.hash.noun, 'dad.joke'); + equal(options.hash.bool, true); + return 'Helper called'; + } + ''' + php: + ''' + function($exclamation, $options) { + assert($exclamation == 'he.says'); + assert($options->types[0] === 'PathExpression'); + + assert(count(options->contexts), 1); + //assert($options->hashContexts["noun"], $context); + assert($options->hash["desire"], 'need'); + assert($options->hash["noun"], 'dad.joke'); + assert($options->hash["bool"], true); + return 'Helper called'; + } + ''' + } + "function(withContext,options){return options.fn(options.contexts[0][withContext])};": { + !code: true + javascript: + ''' + function(withContext, options) { + return options.fn(options.contexts[0][withContext]); + } + ''' + php: + ''' + function($withContext, $options) { + return $options->fn($options->contexts[0][$withContext]); + } + ''' + } + "function(x,y,options){if(!options||options===lastOptions){throw new Error(\"options hash was reused\")}lastOptions=options;return x===y};": { + !code: true + javascript: + ''' + function(x, y, options) { + if (!options || options === lastOptions) { + throw new Error('options hash was reused'); + } + lastOptions = options; + return x === y; + } + ''' + php: + ''' + function($x, $y, $options) { + static $lastOptions = null; + if (!$options || $options === $lastOptions) { + throw new Exception('options hash was reused'); + } + $lastOptions = $options; + return $x === $y; + } + ''' + } +} diff --git a/patch/basic.json b/patch/basic.json index 8e8d7fe..a4d9cd2 100644 --- a/patch/basic.json +++ b/patch/basic.json @@ -1,19 +1,5 @@ { - "basic context-block functions with context argument-00": { - "data": { - "awesome": { - "php": "function($context, $options) { return $options->fn($context); }" - } - } - }, - "basic context-block functions without context argument-00": { - "data": { - "awesome": { - "php": "function($options) { return $options->fn($options->scope); }" - } - } - }, - "basic context-compiling with a string context-00": { + "basic context - compiling with a string context - 00": { "note": "PHP strings do not have properties", "helpers": { "length": { @@ -21,140 +7,5 @@ "php": "function($options) { return strlen($options->scope); }" } } - }, - "basic context-depthed block functions with context argument-00": { - "data": { - "awesome": { - "php": "function($context, $options) { return $options->fn($context); }" - } - } - }, - "basic context-depthed block functions without context argument-00": { - "data": { - "awesome": { - "php": "function($context) { return $context; }" - } - } - }, - "basic context-depthed functions with context argument-00": { - "data": { - "awesome": { - "php": "function($context) { return $context; }" - } - } - }, - "basic context-functions returning safestrings shouldn't be escaped-00": { - "data": { - "awesome": { - "php": "function () { return new SafeString('&\\'\\\\<>'); }" - } - } - }, - "basic context-functions with context argument-00": { - "data": { - "awesome": { - "php": "function($context) { return $context; }" - } - } - }, - "basic context-functions-00": { - "data": { - "awesome": { - "php": "function () { return \"Awesome\"; }" - } - } - }, - "basic context-functions-01": { - "data": { - "awesome": { - "php": "function($options) { return $options->scope['more']; }" - } - } - }, - "basic context-pass number literals-04": { - "data": { - "12.34": { - "php": "function($arg) { return 'bar' . $arg; }" - } - } - }, - "basic context-pathed block functions without context argument-00": { - "data": { - "foo": { - "awesome": { - "php": "function($scope) { return $scope; }" - } - } - } - }, - "basic context-pathed functions with context argument-00": { - "data": { - "bar": { - "awesome": { - "php": "function($context) { return $context; }" - } - } - } - }, - "basic context-should handle literals in subexpression-00": { - "data": { - "false": { - "php": "function() { return 'bar'; }" - } - }, - "helpers": { - "foo": { - "php": "function($arg) {\n return $arg;\n }" - } - } - }, - "basic context-should handle undefined and null-00": { - "data": { - "awesome": { - "php": "function ($_undefined, $_null, $options) {\n return ($_undefined === null ? 'true' : 'false') . ' ' . ($_null === null ? 'true' : 'false') . ' ' . gettype($options);\n }" - } - } - }, - "basic context-should handle undefined and null-01": { - "data": { - "undefined": { - "php": "function() {\n return 'undefined!';\n }" - } - } - }, - "basic context-should handle undefined and null-02": { - "data": { - "null": { - "php": "function() {\n return 'null!';\n }" - } - } - }, - "basic context-this keyword in helpers-00": { - "helpers": { - "foo": { - "php": "function($value) { return 'bar ' . $value; }" - } - } - }, - "basic context-this keyword in helpers-01": { - "helpers": { - "foo": { - "php": "function($value) { return 'bar ' . $value; }" - } - } - }, - "basic context-this keyword nested inside helpers param-01": { - "data": { - "foo": { - "php": "function($value) { return $value; }" - } - } - }, - "basic context-this keyword nested inside helpers param-02": { - "data": { - "foo": { - "php": "function($value) { return $value; }" - } - } } -} \ No newline at end of file +} diff --git a/patch/bench.json b/patch/bench.json deleted file mode 100644 index 8e497ae..0000000 --- a/patch/bench.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "benchmarks-arguments-00": { - "helpers": { - "foo": { - "php": "function() {\n return '';\n }" - } - } - }, - "benchmarks-complex-00": { - "data": { - "header": { - "php": "function () {\n return \"Colors\";\n }" - } - } - }, - "benchmarks-subexpression-00": { - "data": { - "echo": { - "php": "function($value) {\n return 'foo ' . $value;\n }" - }, - "header": { - "php": "function() {\n return \"Colors\";\n }" - } - } - } -} \ No newline at end of file diff --git a/patch/blocks.json b/patch/blocks.json index c4416f2..2d7cb05 100644 --- a/patch/blocks.json +++ b/patch/blocks.json @@ -1,104 +1,10 @@ { - "decorators-should access parent variables-00": { - "helpers": { - "helper": { - "php": "function($options) {\n return $options->fn->run;\n }" - } - }, - "decorators": { - "decorator": { - "php": "function($fn, $props, $container, $options) {\n $fn->run = $options->args;\n return $fn;\n }" - } - } - }, - "decorators-should apply allow undefined return-00": { - "helpers": { - "helper": { - "php": "function($options) {\n return $options->fn() . $options->fn->run;\n }" - } - }, - "decorators": { - "decorator": { - "php": "function($fn) {\n $fn->run = 'cess';\n }" - } - } - }, - "decorators-should apply block decorators-00": { - "helpers": { - "helper": { - "php": "function($options) {\n return $options->fn->run;\n }" - } - }, - "decorators": { - "decorator": { - "php": "function($fn, $props, $container, $options) {\n $fn->run = $options->fn();\n return $fn;\n }" - } - } - }, - "decorators-should apply multiple decorators-00": { - "helpers": { - "helper": { - "php": "function($options) {\n return $options->fn->run;\n }" - } - }, - "decorators": { - "decorator": { - "php": "function($fn, $props, $container, $options) {\n $fn->run = (isset($fn->run) ? $fn->run : '') . $options->fn();\n return $fn;\n }" - } - } - }, - "decorators-should apply mustache decorators-00": { - "helpers": { - "helper": { - "php": "function($options) {\n return $options->fn->run;\n }" - } - }, - "decorators": { - "decorator": { - "php": "function($fn) {\n $fn->run = 'success';\n return $fn;\n }" - } - } - }, - "decorators-should fail when accessing variables from root-00": { - "decorators": { - "decorator": { - "php": "function($fn, $props, $container, $options) {\n assert('$options->args[0] === null');\n return $fn;\n }" - } - } - }, - "decorators-should fail when accessing variables from root-01": null, - "decorators-should support nested decorators-00": { - "helpers": { - "helper": { - "php": "function($options) {\n return $options->fn->run;\n }" - } - }, - "decorators": { - "decorator": { - "php": "function($fn, $props, $container, $options) {\n $fn->run = $options->fn->nested . $options->fn();\n return $fn;\n }" - }, - "nested": { - "php": "function($fn, $props, $container, $options) {\n $props->nested = $options->fn();\n }" - } - } - }, - "decorators-should work with root program-00": { - "decorators": { - "decorator": { - "php": "function($fn, $props, $container, $options) {\n assert('$options->args[0] === \"success\"');\n return $fn;\n }" - } - } - }, - "decorators-should work with root program-01": null, - "inverted sections-chained inverted sections with mismatch-00": { - "expected": null - }, - "inverted sections-chained inverted sections with mismatch-01": null, - "registration-allows multiple globals-00": null, - "registration-allows multiple globals-01": null, - "registration-allows multiple globals-02": null, - "registration-allows multiple globals-03": null, - "registration-fails with multiple and args-00": null, - "registration-unregisters-00": null, - "registration-unregisters-01": null -} \ No newline at end of file + "blocks - decorators - registration - fails with multiple and args - 00": null, + "blocks - decorators - should fail when accessing variables from root - 00": { + "decorators": { + "decorator": { + "javascript": "function (fn, props, container, options) {\n equals(options.args[0], undefined);\n global.run = true;\n return fn;\n }" + } + } + } +} diff --git a/patch/builtins.json b/patch/builtins.json index 1175658..cf32221 100644 --- a/patch/builtins.json +++ b/patch/builtins.json @@ -1,138 +1,15 @@ { - "#each-data passed to helpers-00": { - "helpers": { - "detectDataInsideEach": { - "!code": true, - "javascript": "function(options) { return options.data && options.data.exclaim; }", - "php": "function($options) { return isset($options['data']['exclaim'])? $options['data']['exclaim'] : ''; }" - } - } - }, - "#each-each with an object and @key-00": { - "expected": "2. GOODBYE! <b>#1<\/b>. goodbye! cruel world!", - "globalHelpers": { - "detectDataInsideEach": { - "php": "function($options) {\n return $options['data'] && $options['data']['exclaim'];\n }" - } - } - }, - "#each-each with an object and @key-01": null, - "#each-each with an object and @key-02": { - "globalHelpers": { - "detectDataInsideEach": { - "php": "function($options) {\n return $options['data'] && $options['data']['exclaim'];\n }" - } - } - }, - "#each-each with function argument-00": { - "data": { - "goodbyes": { - "php": "function() { return array(array(\"text\" => \"goodbye\"), array(\"text\" => \"Goodbye\"), array(\"text\" => \"GOODBYE\")); }" - } - }, - "globalHelpers": { - "detectDataInsideEach": { - "php": "function($options) {\n return $options['data'] && $options['data']['exclaim'];\n }" - } - } - }, - "#each-each with function argument-01": { - "globalHelpers": { - "detectDataInsideEach": { - "php": "function($options) {\n return $options['data'] && $options['data']['exclaim'];\n }" - } - } - }, - "#each-each without context-00": { - "globalHelpers": { - "detectDataInsideEach": { - "php": "function($options) {\n return $options['data'] && $options['data']['exclaim'];\n }" - } - } - }, - "#each-each without data-00": { - "globalHelpers": { - "detectDataInsideEach": { - "php": "function($options) {\n return $options['data'] && $options['data']['exclaim'];\n }" - } - } - }, - "#each-each without data-01": { - "globalHelpers": { - "detectDataInsideEach": { - "php": "function($options) {\n return $options['data'] && $options['data']['exclaim'];\n }" - } - } - }, - "#each-each-00": { - "globalHelpers": { - "detectDataInsideEach": { - "php": "function($options) {\n return $options['data'] && $options['data']['exclaim'];\n }" - } - } - }, - "#each-each-01": { - "globalHelpers": { - "detectDataInsideEach": { - "php": "function($options) {\n return $options['data'] && $options['data']['exclaim'];\n }" - } - } - }, - "#if-if with function argument-00": { - "data": { - "goodbye": { - "php": "function() { return true; }" - } - } - }, - "#if-if with function argument-01": { - "data": { - "goodbye": { - "php": "function($scope) { return $scope['world']; }" - } - } - }, - "#if-if with function argument-02": { - "data": { - "goodbye": { - "php": "function() { return false; }" - } - } - }, - "#if-if with function argument-03": { - "data": { - "goodbye": { - "php": "function($scope) { return isset($scope['foo']) ? $scope['foo'] : null; }" - } - } - }, - "#log-should call logger at data level-00": null, - "#log-should call logger at data level-01": null, - "#log-should call logger at data level-02": null, - "#log-should call logger at default level-00": null, - "#log-should call logger at default level-01": null, - "#log-should call logger at default level-02": null, - "#log-should handle hash log levels-00": null, - "#log-should handle hash log levels-01": null, - "#log-should handle hash log levels-02": null, - "#log-should handle hash log levels-03": null, - "#log-should handle missing logger-00": null, - "#log-should handle missing logger-01": null, - "#log-should handle string log levels-00": null, - "#log-should handle string log levels-01": null, - "#log-should handle string log levels-02": null, - "#log-should handle string log levels-03": null, - "#log-should log at data level-00": null, - "#log-should log at data level-01": null, - "#log-should output to info-00": null, - "#log-should output to info-01": null, - "#log-should pass multiple log arguments-00": null, - "#log-should pass multiple log arguments-01": null, - "#with-with with function argument-00": { - "data": { - "person": { - "php": "function() { return array(\"first\" => \"Alan\", \"last\" => \"Johnson\"); }" - } - } - } -} \ No newline at end of file + "builtin helpers - #each - each on iterable - 00": null, + "builtin helpers - #each - each on iterable - 01": null, + "builtin helpers - #log - should call logger at default level - 00": null, + "builtin helpers - #log - should call logger at data level - 00": null, + "builtin helpers - #log - should output to info - 00": null, + "builtin helpers - #log - should log at data level - 00": null, + "builtin helpers - #log - should handle missing logger - 00": null, + "builtin helpers - #log - should handle string log levels - 00": null, + "builtin helpers - #log - should handle string log levels - 01": null, + "builtin helpers - #log - should handle hash log levels - 00": null, + "builtin helpers - #log - should handle hash log levels - 01": null, + "builtin helpers - #log - should pass multiple log arguments - 00": null, + "builtin helpers - #log - should pass zero log arguments - 00": null +} diff --git a/patch/data.json b/patch/data.json index 11599ed..4f9975c 100644 --- a/patch/data.json +++ b/patch/data.json @@ -1,30 +1,5 @@ { - "data-data can be functions with params-00": { - "options": { - "data": { - "hello": { - "php": "function() { return 'hello'; }" - } - } - } - }, - "data-data can be functions-00": { - "options": { - "data": { - "hello": { - "php": "function() { return 'hello'; }" - } - } - } - }, - "data-data is inherited downstream-00": { - "helpers": { - "let": { - "php": "function($options) {\n $frame = Utils::createFrame($options['data']);\n foreach( $options['hash'] as $prop => $v ) {\n $frame[$prop] = $options['hash'][$prop];\n }\n return $options->fn($options->scope, array(\"data\" => $frame));\n }" - } - } - }, - "data-deep @foo triggers automatic top-level data-00": { + "data - deep @foo triggers automatic top-level data - 00": { "helpers": { "helperMissing": null, "blockHelperMissing": null, @@ -34,78 +9,10 @@ "with": null, "log": null, "lookup": null, - "let": { - "javascript": "function (options) {\n var frame = Handlebars.createFrame(options.data);\n\n for (var prop in options.hash) {\n frame[prop] = options.hash[prop];\n }\n return options.fn(this, { data: frame });\n }", - "php": "function($options) {\n $frame = Utils::createFrame($options['data']);\n foreach( $options['hash'] as $prop => $v ) {\n $frame[$prop] = $options['hash'][$prop];\n }\n return $options->fn($options->scope, array(\"data\" => $frame));\n }" - } - } - }, - "data-hash values can be looked up via @foo-00": { - "helpers": { - "hello": { - "php": "function($options) { return \"Hello \" . $options['hash']['noun']; }" - } - } - }, - "data-nested parameter data can be looked up via @foo.bar-00": { - "helpers": { - "hello": { - "php": "function($noun) { return \"Hello \" . $noun; }" - } - } - }, - "data-nested parameter data does not fail with @world.bar-00": { - "helpers": { - "hello": { - "php": "function($noun) { return \"Hello \" . ($noun === null ? 'undefined' : $noun); }" - } - } - }, - "data-parameter data can be looked up via @foo-00": { - "helpers": { - "hello": { - "php": "function($noun) { return \"Hello \" . $noun; }" - } - } - }, - "data-passing in data to a compiled function that expects data - data is passed to with block helpers where children use ..-00": { - "helpers": { - "hello": { - "php": "function($options) {\n return $options['data']['accessData'] . \" \" . $options->fn(array(\"exclaim\" => \"?\"));\n }" - }, - "world": { - "php": "function($thing, $options) {\n return $options['data']['adjective'] . \" \" . $thing . ($options->scope['exclaim'] ?: \"\");\n }" - } + "_parent": null } }, - "data-passing in data to a compiled function that expects data - works with block helpers that use ..-00": { - "helpers": { - "hello": { - "php": "function($options) {\n return $options->fn(array(\"exclaim\" => \"?\"));\n }" - }, - "world": { - "php": "function($thing, $options) {\n return $options['data']['adjective'] . \" \" . $thing . ($options->scope['exclaim'] ?: \"\");\n }" - } - } - }, - "data-passing in data to a compiled function that expects data - works with block helpers-00": { - "helpers": { - "hello": { - "php": "function($options) {\n return $options->fn($options->scope);\n }" - }, - "world": { - "php": "function($options) {\n return $options['data']['adjective'] . \" world\" . ($options->scope['exclaim'] ? \"!\" : \"\");\n }" - } - } - }, - "data-passing in data to a compiled function that expects data - works with helpers and parameters-00": { - "helpers": { - "hello": { - "php": "function($noun, $options) {\n return $options['data']['adjective'] . \" \" . $noun . ($options->scope['exclaim'] ? \"!\" : \"\");\n }" - } - } - }, - "data-passing in data to a compiled function that expects data - works with helpers in partials-00": { + "data - passing in data to a compiled function that expects data - works with helpers in partials - 00": { "helpers": { "helperMissing": null, "blockHelperMissing": null, @@ -114,45 +21,11 @@ "unless": null, "with": null, "log": null, - "lookup": null, - "hello": { - "php": "function($options) {\n return $options['data']['adjective'] . \" \" . $options->scope['noun'];\n }" - } + "lookup": null }, - "decorators": null - }, - "data-passing in data to a compiled function that expects data - works with helpers-00": { - "helpers": { - "hello": { - "php": "function($options) {\n return $options['data']['adjective'] . \" \" . $options->scope['noun'];\n }" - } - } - }, - "data-you can override inherited data when invoking a helper with depth-00": { - "helpers": { - "hello": { - "php": "function($options) {\n return $options->fn(array(\"exclaim\" => \"?\"), array(\"data\" => array(\"adjective\" => \"sad\")));\n }" - }, - "world": { - "php": "function($thing, $options) {\n return $options['data']['adjective'] . \" \" . $thing . ($options->scope['exclaim'] ?: \"\");\n }" - } - } - }, - "data-you can override inherited data when invoking a helper-00": { - "helpers": { - "hello": { - "php": "function($options) {\n return $options->fn(array(\"exclaim\" => \"?\", \"zomg\" => \"world\"), array(\"data\" => array(\"adjective\" => \"sad\")));\n }" - }, - "world": { - "php": "function($thing, $options) {\n return $options['data']['adjective'] . \" \" . $thing . ($options->scope['exclaim'] ?: \"\");\n }" - } - } - }, - "nesting-the root context can be looked up via @root-00": { - "helpers": { - "helper": { - "php": "function($options) {\n $frame = Utils::createFrame($options['data']);\n $frame['depth'] = $options['data']['depth'] + 1;\n return $options->fn($options->scope, array(\"data\" => $frame));\n }" - } - } + "decorators": null, + "partials": { + "myPartial": "{{hello}}" + } } -} \ No newline at end of file +} diff --git a/patch/helpers.json b/patch/helpers.json index fe0a203..95e5dd9 100644 --- a/patch/helpers.json +++ b/patch/helpers.json @@ -1,846 +1,20 @@ { - "block params-should allow block params on chained helpers-00": { - "helpers": { - "goodbyes": { - "php": "function($options) {\n return $options->fn(array('value' => 'bar'), array('blockParams' => array(1, 2)));\n }" - } - }, - "globalHelpers": { - "world": { - "php": "function() { return 'world!'; }" - }, - "testHelper": { - "php": "function() { return 'found it!'; }" - } - } - }, - "block params-should not take presedence over pathed values-00": { - "helpers": { - "value": { - "php": "function() {\n return 'foo';\n }" - }, - "goodbyes": { - "php": "function($options) {\n return $options->fn($options->scope, array('blockParams' => array(1, 2)));\n }" - } - }, - "globalHelpers": { - "world": { - "php": "function() { return 'world!'; }" - }, - "testHelper": { - "php": "function() { return 'found it!'; }" - } - } - }, - "block params-should take presedence over context values-00": { - "helpers": { - "goodbyes": { - "php": "function($options) {\n return $options->fn(array('value' => 'bar'), array('blockParams' => array(1, 2)));\n }" - } - }, - "globalHelpers": { - "world": { - "php": "function() { return 'world!'; }" - }, - "testHelper": { - "php": "function() { return 'found it!'; }" - } - } - }, - "block params-should take presedence over helper values-00": { - "helpers": { - "value": { - "php": "function() {\n return 'foo';\n }" - }, - "goodbyes": { - "php": "function($options) {\n return $options->fn(array(), array('blockParams' => array(1, 2)));\n }" - } - }, - "globalHelpers": { - "world": { - "php": "function() { return 'world!'; }" - }, - "testHelper": { - "php": "function() { return 'found it!'; }" - } - } - }, - "block params-should take presednece over parent block params-00": { - "helpers": { - "goodbyes": { - "javascript": "function (options) {\n if( typeof value === 'undefined' ) { value = 1; } return options.fn({value: 'bar'}, {blockParams: options.fn.blockParams === 1 ? [value++, value++] : undefined});\n }", - "php": "function($options) {\n static $value;\n if( $value === null ) { $value = 1; } return $options->fn(array('value' => 'bar'), array('blockParams' => array($value++, $value++)));\n }" - } - }, - "globalHelpers": { - "world": { - "php": "function() { return 'world!'; }" - }, - "testHelper": { - "php": "function() { return 'found it!'; }" - } - } - }, - "blockhelpermissing-lambdas are resolved by blockhelpermissing, not handlebars proper-00": { - "data": { - "truthy": { - "php": "function() { return true; }" - } - }, - "globalHelpers": { - "world": { - "php": "function() { return \"world!\"; }" - }, - "test_helper": { - "php": "function() { return 'found it!'; }" - }, - "testHelper": { - "php": "function() { return 'found it!'; }" - } - } - }, - "blockhelpermissing-lambdas resolved by blockhelpermissing are bound to the context-00": { - "data": { - "truthy": { - "php": "function($options) { return $options->scope['truthiness'](); }" - }, - "truthiness": { - "php": "function() { return false; }" - } - }, - "globalHelpers": { - "world": { - "php": "function() { return \"world!\"; }" - }, - "test_helper": { - "php": "function() { return 'found it!'; }" - }, - "testHelper": { - "php": "function() { return 'found it!'; }" - } - }, - "note": "Check original spec. Needs other tests, possibly implementation dependant." - }, - "decimal number literals work-decimal number literals work-00": { - "helpers": { - "hello": { - "php": "function($times, $times2) {\n if (!is_numeric($times)) {\n $times = 'NaN';\n }\n if (!is_numeric($times2)) {\n $times2 = \"NaN\";\n }\n return \"Hello $times $times2 times\";\n}" - } - }, - "globalHelpers": { - "world": { - "php": "function() { return \"world!\"; }" - }, - "test_helper": { - "php": "function() { return 'found it!'; }" - }, - "testHelper": { - "php": "function() { return 'found it!'; }" - } - } - }, - "hash-block helpers can take an optional hash with booleans-00": { - "helpers": { - "goodbye": { - "php": "function($options) {\n if ($options['hash']['print'] === true) {\n return \"GOODBYE {$options['hash']['cruel']} \" . $options->fn($options->scope) . @$options['hash']['world'];\n } elseif ($options['hash']['print'] === false) {\n return \"NOT PRINTING\";\n } else {\n return \"THIS SHOULD NOT HAPPEN\";\n }\n}" - } - } - }, - "hash-block helpers can take an optional hash with booleans-01": { - "helpers": { - "goodbye": { - "php": "function($options) {\n if ($options['hash']['print'] === true) {\n return \"GOODBYE {$options['hash']['cruel']} \" . $options->fn($options->scope) . @$options['hash']['world'];\n } elseif ($options['hash']['print'] === false) {\n return \"NOT PRINTING\";\n } else {\n return \"THIS SHOULD NOT HAPPEN\";\n }\n}" - } - } - }, - "hash-block helpers can take an optional hash with single quoted stings-00": { - "helpers": { - "goodbye": { - "php": "function($options) {\n return \"GOODBYE {$options['hash']['cruel']} \" . $options->fn($options->scope) . \" {$options['hash']['times']} TIMES\";\n}" - } - } - }, - "hash-block helpers can take an optional hash-00": { - "helpers": { - "goodbye": { - "php": "function($options) {\n return \"GOODBYE {$options['hash']['cruel']} \" . $options->fn($options->scope) . \" {$options['hash']['times']} TIMES\";\n}" - } - } - }, - "hash-helpers can take an optional hash with booleans-00": { - "helpers": { - "goodbye": { - "php": "function($options) {\n if ($options['hash']['print'] === true) {\n return \"GOODBYE {$options['hash']['cruel']} \" . $options['hash']['world'];\n } elseif ($options['hash']['print'] === false) {\n return \"NOT PRINTING\";\n } else {\n return \"THIS SHOULD NOT HAPPEN\";\n }\n}" - } - } - }, - "hash-helpers can take an optional hash with booleans-01": { - "helpers": { - "goodbye": { - "php": "function($options) {\n if ($options['hash']['print'] === true) {\n return \"GOODBYE {$options['hash']['cruel']} \" . $options['hash']['world'];\n } elseif ($options['hash']['print'] === false) {\n return \"NOT PRINTING\";\n } else {\n return \"THIS SHOULD NOT HAPPEN\";\n }\n}" - } - } - }, - "hash-helpers can take an optional hash-00": { - "helpers": { - "goodbye": { - "php": "function($options) {\n $r = 'GOODBYE ';\n $r .= $options['hash']['cruel'].' ';\n $r .= $options['hash']['world'].' ';\n $r .= $options['hash']['times'].' TIMES';\n\n return $r;\n}" - } - } - }, - "helpermissing-if a context is not found, custom helpermissing is used-00": { - "helpers": { - "helperMissing": { - "php": "function($mesg, $options = null) {\n if($options && $options['name'] === \"link_to\") {\n return new SafeString(\"\" . $mesg . \"<\/a>\");\n }\n }" - } - }, - "globalHelpers": { - "world": { - "php": "function() { return \"world!\"; }" - }, - "test_helper": { - "php": "function() { return 'found it!'; }" - }, - "testHelper": { - "php": "function() { return 'found it!'; }" - } - } - }, - "helpermissing-if a value is not found, custom helpermissing is used-00": { - "helpers": { - "helperMissing": { - "php": "function($options) {\n if($options['name'] === \"link_to\") {\n return new SafeString(\"winning<\/a>\");\n }\n }" - } - }, - "globalHelpers": { - "world": { - "php": "function() { return \"world!\"; }" - }, - "test_helper": { - "php": "function() { return 'found it!'; }" - }, - "testHelper": { - "php": "function() { return 'found it!'; }" - } - } - }, - "helpers hash-in cases of conflict, helpers win-00": { - "helpers": { - "lookup": { - "php": "function() { return 'helpers'; }" - } - } - }, - "helpers hash-in cases of conflict, helpers win-01": { - "helpers": { - "lookup": { - "php": "function() { return 'helpers'; }" - } - } - }, - "helpers hash-providing a helpers hash-00": { - "helpers": { - "world": { - "php": "function() { return 'world'; }" - } - } - }, - "helpers hash-providing a helpers hash-01": { - "helpers": { - "world": { - "php": "function() { return 'world'; }" - } - } - }, - "helpers hash-the helper hash should augment the global hash-00": { - "helpers": { - "test_helper": { - "!code": true, - "javascript": "function() { return 'found it!'; }", - "php": "function() { return 'found it!'; }" - }, - "world": { - "php": "function() { return 'world!'; }" - } - }, - "globalHelpers": { - "world": { - "php": "function() { return \"world!\"; }" - }, - "test_helper": { - "php": "function() { return 'found it!'; }" - } - } - }, - "helpers hash-the helpers hash is available is nested contexts-00": { - "helpers": { - "helper": { - "php": "function() { return 'helper'; }" - } - } - }, - "helpers-block helper inverted sections-00": { - "helpers": { - "list": { - "php": "function($context, $options) {\n $out = '';\n if (count($context) > 0) {\n $out .= '