updated everything
authorJesse MacFadyen <purplecabbage@gmail.com>
Sun, 26 Nov 2017 09:47:00 +0000 (01:47 -0800)
committerJesse MacFadyen <purplecabbage@gmail.com>
Sun, 26 Nov 2017 09:47:00 +0000 (01:47 -0800)
108 files changed:
.eslintignore [new file with mode: 0644]
.eslintrc.yml [new file with mode: 0644]
.gitattributes [new file with mode: 0644]
.gitignore [new file with mode: 0644]
.travis.yml [new file with mode: 0644]
LICENSE [new file with mode: 0644]
NOTICE [new file with mode: 0644]
RELEASENOTES.md [new file with mode: 0644]
VERSION [new file with mode: 0644]
appveyor.yml [new file with mode: 0644]
bin/create
bin/lib/check_reqs.js
bin/lib/create.js
bin/lib/update.js
bin/template/config.xml [new file with mode: 0644]
bin/template/cordova/Api.js [new file with mode: 0644]
bin/template/cordova/build [moved from bin/templates/project/cordova/build with 97% similarity]
bin/template/cordova/build.bat [moved from bin/templates/project/cordova/build.bat with 100% similarity]
bin/template/cordova/clean [moved from bin/templates/project/cordova/clean with 95% similarity]
bin/template/cordova/clean.bat [new file with mode: 0644]
bin/template/cordova/defaults.xml [moved from bin/templates/project/cordova/defaults.xml with 100% similarity]
bin/template/cordova/handler.js [new file with mode: 0644]
bin/template/cordova/lib/build.js [new file with mode: 0644]
bin/template/cordova/lib/clean.js [moved from bin/templates/project/cordova/lib/clean.js with 55% similarity]
bin/template/cordova/lib/run.js [moved from bin/templates/project/www/spec/helper.js with 64% similarity]
bin/template/cordova/log [moved from bin/templates/project/cordova/run with 75% similarity]
bin/template/cordova/parser.js [new file with mode: 0644]
bin/template/cordova/run [new file with mode: 0755]
bin/template/cordova/run.bat [moved from bin/templates/project/cordova/run.bat with 100% similarity]
bin/template/cordova/version [moved from bin/templates/project/cordova/version with 97% similarity]
bin/template/cordova/version.bat [moved from bin/templates/project/cordova/version.bat with 100% similarity]
bin/template/www/css/index.css [moved from bin/templates/project/www/css/index.css with 100% similarity]
bin/template/www/favicon.ico [new file with mode: 0644]
bin/template/www/img/logo.png [new file with mode: 0644]
bin/template/www/img/splash.png [new file with mode: 0644]
bin/template/www/index.html [moved from bin/templates/project/www/index.html with 92% similarity]
bin/template/www/js/index.js [moved from bin/templates/project/www/js/index.js with 93% similarity]
bin/template/www/manifest.json [new file with mode: 0644]
bin/templates/project/cordova/lib/build.js [deleted file]
bin/templates/project/cordova/lib/exec.js [deleted file]
bin/templates/project/cordova/lib/main.js [deleted file]
bin/templates/project/cordova/lib/run.js [deleted file]
bin/templates/project/www/img/logo.png [deleted file]
bin/templates/project/www/res/icon/android/icon-36-ldpi.png [deleted file]
bin/templates/project/www/res/icon/android/icon-48-mdpi.png [deleted file]
bin/templates/project/www/res/icon/android/icon-72-hdpi.png [deleted file]
bin/templates/project/www/res/icon/android/icon-96-xhdpi.png [deleted file]
bin/templates/project/www/res/icon/bada-wac/icon-48-type5.png [deleted file]
bin/templates/project/www/res/icon/bada-wac/icon-50-type3.png [deleted file]
bin/templates/project/www/res/icon/bada-wac/icon-80-type4.png [deleted file]
bin/templates/project/www/res/icon/bada/icon-128.png [deleted file]
bin/templates/project/www/res/icon/blackberry/icon-80.png [deleted file]
bin/templates/project/www/res/icon/blackberry10/icon-80.png [deleted file]
bin/templates/project/www/res/icon/ios/icon-57-2x.png [deleted file]
bin/templates/project/www/res/icon/ios/icon-57.png [deleted file]
bin/templates/project/www/res/icon/ios/icon-72-2x.png [deleted file]
bin/templates/project/www/res/icon/ios/icon-72.png [deleted file]
bin/templates/project/www/res/icon/tizen/icon-128.png [deleted file]
bin/templates/project/www/res/icon/webos/icon-64.png [deleted file]
bin/templates/project/www/res/icon/windows-phone/icon-173-tile.png [deleted file]
bin/templates/project/www/res/icon/windows-phone/icon-48.png [deleted file]
bin/templates/project/www/res/icon/windows-phone/icon-62-tile.png [deleted file]
bin/templates/project/www/res/screen/android/screen-hdpi-landscape.png [deleted file]
bin/templates/project/www/res/screen/android/screen-hdpi-portrait.png [deleted file]
bin/templates/project/www/res/screen/android/screen-ldpi-landscape.png [deleted file]
bin/templates/project/www/res/screen/android/screen-ldpi-portrait.png [deleted file]
bin/templates/project/www/res/screen/android/screen-mdpi-landscape.png [deleted file]
bin/templates/project/www/res/screen/android/screen-mdpi-portrait.png [deleted file]
bin/templates/project/www/res/screen/android/screen-xhdpi-landscape.png [deleted file]
bin/templates/project/www/res/screen/android/screen-xhdpi-portrait.png [deleted file]
bin/templates/project/www/res/screen/bada-wac/screen-type3.png [deleted file]
bin/templates/project/www/res/screen/bada-wac/screen-type4.png [deleted file]
bin/templates/project/www/res/screen/bada-wac/screen-type5.png [deleted file]
bin/templates/project/www/res/screen/bada/screen-portrait.png [deleted file]
bin/templates/project/www/res/screen/blackberry/screen-225.png [deleted file]
bin/templates/project/www/res/screen/blackberry10/splash-1280x768.png [deleted file]
bin/templates/project/www/res/screen/blackberry10/splash-720x720.png [deleted file]
bin/templates/project/www/res/screen/blackberry10/splash-768x1280.png [deleted file]
bin/templates/project/www/res/screen/ios/screen-ipad-landscape-2x.png [deleted file]
bin/templates/project/www/res/screen/ios/screen-ipad-landscape.png [deleted file]
bin/templates/project/www/res/screen/ios/screen-ipad-portrait-2x.png [deleted file]
bin/templates/project/www/res/screen/ios/screen-ipad-portrait.png [deleted file]
bin/templates/project/www/res/screen/ios/screen-iphone-landscape-2x.png [deleted file]
bin/templates/project/www/res/screen/ios/screen-iphone-landscape.png [deleted file]
bin/templates/project/www/res/screen/ios/screen-iphone-portrait-2x.png [deleted file]
bin/templates/project/www/res/screen/ios/screen-iphone-portrait-568h-2x.png [deleted file]
bin/templates/project/www/res/screen/ios/screen-iphone-portrait.png [deleted file]
bin/templates/project/www/res/screen/tizen/README.md [deleted file]
bin/templates/project/www/res/screen/webos/screen-64.png [deleted file]
bin/templates/project/www/res/screen/windows-phone/screen-portrait.jpg [deleted file]
bin/templates/project/www/spec.html [deleted file]
bin/templates/project/www/spec/index.js [deleted file]
bin/templates/project/www/spec/lib/jasmine-1.2.0/MIT.LICENSE [deleted file]
bin/templates/project/www/spec/lib/jasmine-1.2.0/jasmine-html.js [deleted file]
bin/templates/project/www/spec/lib/jasmine-1.2.0/jasmine.css [deleted file]
bin/templates/project/www/spec/lib/jasmine-1.2.0/jasmine.js [deleted file]
bin/update
cordova-js-src/confighelper.js
cordova-js-src/exec.js
cordova-js-src/platform.js
cordova-lib/cordova.js
package.json
spec/.eslintrc.yml [new file with mode: 0644]
spec/create.spec.js [new file with mode: 0644]
spec/handler.spec.js [new file with mode: 0644]
spec/manifest.spec.js [new file with mode: 0644]
spec/projectApi.spec.js [new file with mode: 0644]
spec/support/jasmine.json [new file with mode: 0644]

diff --git a/.eslintignore b/.eslintignore
new file mode 100644 (file)
index 0000000..a547141
--- /dev/null
@@ -0,0 +1 @@
+cordova-lib/cordova.js
\ No newline at end of file
diff --git a/.eslintrc.yml b/.eslintrc.yml
new file mode 100644 (file)
index 0000000..0cccb8c
--- /dev/null
@@ -0,0 +1,10 @@
+root: true
+extends: semistandard
+rules:
+  indent:
+    - error
+    - 4
+  camelcase: off
+  padded-blocks: off
+  operator-linebreak: off
+  no-throw-literal: off
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
new file mode 100644 (file)
index 0000000..f63e59a
--- /dev/null
@@ -0,0 +1,94 @@
+* text eol=lf
+
+# source code
+*.php text
+*.css text
+*.sass text
+*.scss text
+*.less text
+*.styl text
+*.js text
+*.coffee text
+*.json text
+*.htm text
+*.html text
+*.xml text
+*.svg text
+*.txt text
+*.ini text
+*.inc text
+*.pl text
+*.rb text
+*.py text
+*.scm text
+*.sql text
+*.sh text
+*.bat text
+
+# templates
+*.ejs text
+*.hbt text
+*.jade text
+*.haml text
+*.hbs text
+*.dot text
+*.tmpl text
+*.phtml text
+
+# server config
+.htaccess text
+
+# git config
+.gitattributes text
+.gitignore text
+.gitconfig text
+
+# code analysis config
+.jshintrc text
+.jscsrc text
+.jshintignore text
+.csslintrc text
+
+# misc config
+*.yaml text
+*.yml text
+.editorconfig text
+
+# build config
+*.npmignore text
+*.bowerrc text
+
+# Heroku
+Procfile text
+.slugignore text
+
+# Documentation
+*.md text
+LICENSE text
+AUTHORS text
+
+
+#
+## These files are binary and should be left untouched
+#
+
+# (binary is a macro for -text -diff)
+*.png binary
+*.jpg binary
+*.jpeg binary
+*.gif binary
+*.ico binary
+*.mov binary
+*.mp4 binary
+*.mp3 binary
+*.flv binary
+*.fla binary
+*.swf binary
+*.gz binary
+*.zip binary
+*.7z binary
+*.ttf binary
+*.eot binary
+*.woff binary
+*.pyc binary
+*.pdf binary
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..4a5098f
--- /dev/null
@@ -0,0 +1,8 @@
+
+npm-debug.log
+temp
+.DS_Store
+.gitcore
+*.jar
+.vscode
+node_modules/
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644 (file)
index 0000000..9e1ecb6
--- /dev/null
@@ -0,0 +1,12 @@
+language: node_js
+sudo: false
+node_js:
+  - "4"
+  - "6"
+  - "8"
+install:
+  - npm install
+script:
+  - node --version
+  - npm --version
+  - npm test
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..248c7b6
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,317 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ ADDITIONAL LICENSES:
+
+================================================================================
+node_modules/adm-zip
+================================================================================
+
+Copyright (c) 2012 Another-D-Mention Software and other contributors,
+http://www.another-d-mention.ro/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+================================================================================
+node_modules/shelljs
+================================================================================
+
+Copyright (c) 2012, Artur Adib <aadib@mozilla.com>
+All rights reserved.
+
+You may use this project under the terms of the New BSD license as follows:
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of Artur Adib nor the
+      names of the contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL ARTUR ADIB BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+================================================================================
+node_modules/nopt
+================================================================================
+
+Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+================================================================================
+node_modules/nopt/node_modules/abbrev
+================================================================================
+
+Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/NOTICE b/NOTICE
new file mode 100644 (file)
index 0000000..af715dc
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,5 @@
+Apache Cordova
+Copyright 2012-2017 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
new file mode 100644 (file)
index 0000000..9875c57
--- /dev/null
@@ -0,0 +1,23 @@
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+-->
+## Release Notes for Cordova Electron ##
+### 1.0.0 (Nov 25, 2017)
+* Added release notes
\ No newline at end of file
diff --git a/VERSION b/VERSION
new file mode 100644 (file)
index 0000000..835b796
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+1.0.0-dev
\ No newline at end of file
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644 (file)
index 0000000..d82cdfc
--- /dev/null
@@ -0,0 +1,39 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+# appveyor file
+# http://www.appveyor.com/docs/appveyor-yml
+
+environment:
+  matrix:
+  - nodejs_version: "4"
+  - nodejs_version: "6"
+  - nodejs_version: "8"
+
+install:
+  - ps: Install-Product node $env:nodejs_version
+  - npm install
+
+build: off
+
+test_script:
+  - node --version
+  - npm --version
+  - msbuild /version
+  - npm test
index cfcb730..45b33f3 100755 (executable)
        specific language governing permissions and limitations
        under the License.
 */
+
+/*
+ * create a Cordova project
+ *
+ * USAGE
+ *   ./create <path_to_new_project> <package_name> <project_name>
+ *
+ * EXAMPLE
+ *  ./create ~/Desktop/radness org.apache.cordova.radness Radness
+ */
+
 var path = require('path');
-var create = require('./lib/create');
-var args = process.argv;
-
-// Support basic help commands
-if(args.length < 3 || (args[2] == '--help' || args[2] == '/?' || args[2] == '-h' ||
-                    args[2] == 'help' || args[2] == '-help' || args[2] == '/help')) {
-    console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'create')) + ' <path_to_new_project> <package_name> <project_name>');
-    console.log('    <path_to_new_project>: Path to your new Cordova electron project');
-    console.log('    <package_name>: Package name, following reverse-domain style convention');
-    console.log('    <project_name>: Project name');
-    process.exit(1);
-} else {
-    create.createProject(args[2], args[3], args[4], args[5]);
+var ConfigParser = require('cordova-common').ConfigParser;
+var Api = require('./template/cordova/Api');
+
+
+var argv = require('nopt')({
+    'help' : Boolean,
+    'cli' : Boolean,
+    'shared' : Boolean, // alias for --link
+    'link' : Boolean
+}, { 'd' : '--verbose' });
+
+
+var projectPath = argv.argv.remain[0];
+
+if (argv.help || !projectPath) {
+    console.log('Usage: $0 [--link] [--cli] <path_to_new_project> <package_name> <project_name> [<project_template_dir>]');
+    console.log('   --link (optional): Link directly against the shared copy of the CordovaLib instead of a copy of it.');
+    console.log('   --cli (optional): Use the CLI-project template.');
+    console.log('   <path_to_new_project>: Path to your new Cordova iOS project');
+    console.log('   <package_name>: Package name, following reverse-domain style convention');
+    console.log('   <project_name>: Project name');
+    console.log('   <project_template_dir>: Path to project template (override).');
+    process.exit(0);
 }
+else {
+    var configPath = path.resolve(__dirname, 'template/config.xml');
+    var config = new ConfigParser(configPath);
+
+    // apply overrides (package and project names
+    if (argv.argv.remain[1]) {
+        config.setPackageName(argv.argv.remain[1]);
+    }
+    if (argv.argv.remain[2]) {
+        config.setName(argv.argv.remain[2]);
+    }
+
+    var options = {
+        cli: argv.cli,
+        link: argv.link || argv.shared,
+        customTemplate: argv.argv.remain[3],
+    };
+
+    Api.createPlatform(projectPath, config, options);
+}
+
+
index 583ad0f..172aa38 100644 (file)
@@ -19,8 +19,8 @@ specific language governing permissions and limitations
 under the License.
 */
 
-//add methods as we determine what are the requirements
+// add methods as we determine what are the requirements
 
-module.exports.run = function() {
-    return true;
-}
+module.exports.run = function () {
+    return Promise.resolve();
+};
index 98e17ca..3c6b932 100644 (file)
  * specific language governing permissions and limitations
  * under the License.
  */
-var fs = require('fs'),
-    shjs = require('shelljs'),
-    args = process.argv,
-    path = require('path'),
-    ROOT    = path.join(__dirname, '..', '..'),
-    check_reqs = require('./check_reqs');
-
-exports.createProject = function(project_path,package_name,project_name){
-    
+
+var fs = require('fs');
+var shell = require('shelljs');
+var path = require('path');
+var ROOT = path.join(__dirname, '..', '..');
+var events = require('cordova-common').events;
+var check_reqs = require('./check_reqs');
+
+// exported method to create a project, returns a promise that resolves with null
+module.exports.createProject = function (project_path, package_name, project_name) {
+/*
+    // create the dest and the standard place for our api to live
+    // platforms/platformName/cordova/Api.js
+*/
+
+    events.emit('log', 'Creating Cordova project for cordova-electron:');
+    events.emit('log', '\tPath: ' + project_path);
+    events.emit('log', '\tName: ' + project_name);
+
     // Set default values for path, package and name
-    project_path = typeof project_path !== 'undefined' ? project_path : "CordovaExample";    package_name = typeof package_name !== 'undefined' ? package_name : 'org.apache.cordova.example';
-    project_name = typeof project_name !== 'undefined' ? project_name : 'CordovaExample';
+    project_path = project_path || 'CordovaExample';
 
     // Check if project already exists
     if (fs.existsSync(project_path)) {
-        console.error('Project already exists! Delete and recreate');
-        process.exit(2);
+        events.emit('error', 'Oops, destination already exists! Delete it and try again');
     }
-    
+
     // Check that requirements are met and proper targets are installed
     if (!check_reqs.run()) {
-        console.error('Please make sure you meet the software requirements in order to build a browser cordova project');
-        process.exit(2);
+        // TODO: use events.emit
+        events.emit('error', 'Please make sure you meet the software requirements in order to build a cordova electron project');
     }
 
-    console.log('Creating Electron project. Path: ' + path.relative(process.cwd(),project_path));
+    // copy template/cordova directory ( recursive )
+    shell.cp('-r', path.join(ROOT, 'bin/template/cordova'), project_path);
 
-    //copy template directory
-    shjs.cp('-r', path.join(ROOT, 'bin', 'templates', 'project', 'www'), project_path);
+    // copy template/www directory ( recursive )
+    shell.cp('-r', path.join(ROOT, 'bin/template/www'), project_path);
 
-    //create cordova/lib if it does not exist yet
-    if (!fs.existsSync(path.join(project_path,'cordova', 'lib'))) {
-        shjs.mkdir('-p', path.join(project_path,'cordova', 'lib'));
-    }
+    // recreate our node_modules structure in the new project
+    shell.cp('-r', path.join(ROOT, 'node_modules'),
+        path.join(project_path, 'cordova'));
+
+    // copy check_reqs file
+    shell.cp(path.join(ROOT, 'bin/lib/check_reqs.js'),
+        path.join(project_path, 'cordova/lib'));
+
+    var platform_www = path.join(project_path, 'platform_www');
+
+    // copy cordova-js-src directory
+    shell.cp('-rf', path.join(ROOT, 'cordova-js-src'), platform_www);
+
+    // copy cordova js file to platform_www
+    shell.cp(path.join(ROOT, 'cordova-lib', 'cordova.js'), platform_www);
+
+    // copy favicon file to platform_www
+    shell.cp(path.join(ROOT, 'bin/template/www/favicon.ico'), platform_www);
+
+    // load manifest to write name/shortname
+    var manifest = require(path.join(ROOT, 'bin/template/www', 'manifest.json'));
+    manifest.name = project_name;
+    manifest.short_name = project_name;
+    // copy manifest file to platform_www
+    fs.writeFileSync(path.join(platform_www, 'manifest.json'),
+        JSON.stringify(manifest, null, 2), 'utf-8');
 
-    //copy required node_modules
-    shjs.cp('-r', path.join(ROOT, 'node_modules'), path.join(project_path,'cordova'));
-
-    //copy check_reqs file
-    shjs.cp( path.join(ROOT, 'bin', 'lib', 'check_reqs.js'), path.join(project_path,'cordova', 'lib'));
-    
-    //copy cordova js file
-    shjs.cp('-r', path.join(ROOT, 'cordova-lib', 'cordova.js'), path.join(project_path,'www'));
-
-    //copy cordova directory
-    shjs.cp('-r', path.join(ROOT, 'bin', 'templates', 'project', 'cordova'), project_path); 
-    [
-        'run',
-        'build',
-        'clean',
-        'version',
-    ].forEach(function(f) { 
-         shjs.chmod(755, path.join(project_path, 'cordova', f));
-    });
-}
+    return Promise.resolve();
+};
index 9367676..8c2e231 100644 (file)
        under the License.
 */
 
-var Q      = require('Q'),
-    create = require('./create'),
-    fs     = require('fs'),
-    shell = require('shelljs');
-
 module.exports.help = function () {
-    console.log("WARNING : Make sure to back up your project before updating!");
-    console.log("Usage: update PathToProject ");
-    console.log("    PathToProject : The path the project you would like to update.");
-    console.log("examples:");
-    console.log("    update C:\\Users\\anonymous\\Desktop\\MyProject");
+    console.log('WARNING : Electron does not support updating. Remove and then re-Add the platform to get the latest.');
 };
 
-module.exports.run = function (argv) {
-    var projectPath = argv[2];
-    if (!fs.existsSync(projectPath)) {
-        // if specified project path is not valid then reject promise
-        Q.reject("Browser platform does not exist here: " + projectPath);
-    }
-    return Q().then(function () {
-        console.log("Removing existing browser platform.");
-        shellfatal(shell.rm, '-rf', projectPath);
-        create.createProject(projectPath);
-    });
-}
-
-function shellfatal(shellFunc) {
-    var slicedArgs = Array.prototype.slice.call(arguments, 1);
-    try {
-        shell.config.fatal = true;
-        var returnVal = shellFunc.apply(shell, slicedArgs);
-    }   
-    finally {
-        shell.config.fatal = false;
-    }
-    return returnVal;
-}
+module.exports.run = function () {
+    return Promise.reject(new Error('Update not supported'));
+};
diff --git a/bin/template/config.xml b/bin/template/config.xml
new file mode 100644 (file)
index 0000000..a212661
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+-->
+<widget xmlns="http://www.w3.org/ns/widgets">
+
+</widget>
\ No newline at end of file
diff --git a/bin/template/cordova/Api.js b/bin/template/cordova/Api.js
new file mode 100644 (file)
index 0000000..9756ba6
--- /dev/null
@@ -0,0 +1,528 @@
+/**
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+'License'); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+/*
+    this file is found by cordova-lib when you attempt to
+    'cordova platform add PATH' where path is this repo.
+*/
+
+var shell = require('shelljs');
+var path = require('path');
+var fs = require('fs');
+
+var cdvcmn = require('cordova-common');
+var CordovaLogger = cdvcmn.CordovaLogger;
+var ConfigParser = cdvcmn.ConfigParser;
+var ActionStack = cdvcmn.ActionStack;
+var selfEvents = cdvcmn.events;
+var xmlHelpers = cdvcmn.xmlHelpers;
+var PlatformJson = cdvcmn.PlatformJson;
+var PlatformMunger = cdvcmn.ConfigChanges.PlatformMunger;
+var PluginInfoProvider = cdvcmn.PluginInfoProvider;
+
+var Parser = require('./parser');
+var PLATFORM_NAME = 'electron';
+
+function setupEvents (externalEventEmitter) {
+    if (externalEventEmitter) {
+        // This will make the platform internal events visible outside
+        selfEvents.forwardEventsTo(externalEventEmitter);
+        return externalEventEmitter;
+    }
+
+    // There is no logger if external emitter is not present,
+    // so attach a console logger
+    CordovaLogger.get().subscribe(selfEvents);
+    return selfEvents;
+}
+
+function Api (platform, platformRootDir, events) {
+
+    this.platform = platform || PLATFORM_NAME;
+
+    // MyApp/platforms/electron
+    this.root = path.resolve(__dirname, '..');
+    this.events = setupEvents(events);
+    this.parser = new Parser(this.root);
+    this.handler = require('./handler');
+
+    this.locations = {
+        platformRootDir: platformRootDir,
+        root: this.root,
+        www: path.join(this.root, 'www'),
+        res: path.join(this.root, 'res'),
+        platformWww: path.join(this.root, 'platform_www'),
+        configXml: path.join(this.root, 'config.xml'),
+        defaultConfigXml: path.join(this.root, 'cordova/defaults.xml'),
+        build: path.join(this.root, 'build'),
+        // NOTE: Due to platformApi spec we need to return relative paths here
+        cordovaJs: 'bin/templates/project/assets/www/cordova.js',
+        cordovaJsSrc: 'cordova-js-src'
+    };
+
+    this._platformJson = PlatformJson.load(this.root, platform);
+    this._pluginInfoProvider = new PluginInfoProvider();
+    this._munger = new PlatformMunger(platform, this.root, this._platformJson, this._pluginInfoProvider);
+}
+
+Api.createPlatform = function (dest, config, options, events) {
+
+    var creator = require('../../lib/create');
+    events = setupEvents(events);
+
+    var name = 'HelloCordova';
+    var id = 'io.cordova.hellocordova';
+    if (config) {
+        name = config.name();
+        id = config.packageName();
+    }
+
+    var result;
+    try {
+        // we create the project using our scripts in this platform
+        result = creator.createProject(dest, id, name, options)
+            .then(function () {
+                // after platform is created we return Api instance based on new Api.js location
+                // Api.js has been copied to the new project
+                // This is required to correctly resolve paths in the future api calls
+                var PlatformApi = require(path.resolve(dest, 'cordova/Api'));
+                return new PlatformApi('electron', dest, events);
+            });
+    } catch (e) {
+        events.emit('error', 'createPlatform is not callable from the electron project API.');
+        throw (e);
+    }
+    return result;
+};
+
+Api.updatePlatform = function (dest, options, events) {
+    // console.log("test-platform:Api:updatePlatform");
+    // todo?: create projectInstance and fulfill promise with it.
+    return Promise.resolve();
+};
+
+Api.prototype.getPlatformInfo = function () {
+    return {
+        'locations': this.locations,
+        'root': this.root,
+        'name': this.platform,
+        'version': { 'version': '1.0.0' }, // um, todo!
+        'projectConfig': this.config
+    };
+};
+
+Api.prototype.prepare = function (cordovaProject, options) {
+
+    // First cleanup current config and merge project's one into own
+    var defaultConfigPath = path.join(this.locations.platformRootDir, 'cordova',
+        'defaults.xml');
+    var ownConfigPath = this.locations.configXml;
+    var sourceCfg = cordovaProject.projectConfig;
+
+    // If defaults.xml is present, overwrite platform config.xml with it.
+    // Otherwise save whatever is there as defaults so it can be
+    // restored or copy project config into platform if none exists.
+    if (fs.existsSync(defaultConfigPath)) {
+        this.events.emit('verbose', 'Generating config.xml from defaults for platform "' + this.platform + '"');
+        shell.cp('-f', defaultConfigPath, ownConfigPath);
+    } else if (fs.existsSync(ownConfigPath)) {
+        this.events.emit('verbose', 'Generating defaults.xml from own config.xml for platform "' + this.platform + '"');
+        shell.cp('-f', ownConfigPath, defaultConfigPath);
+    } else {
+        this.events.emit('verbose', 'case 3"' + this.platform + '"');
+        shell.cp('-f', sourceCfg.path, ownConfigPath);
+    }
+
+    // merge our configs
+    this.config = new ConfigParser(ownConfigPath);
+    xmlHelpers.mergeXml(cordovaProject.projectConfig.doc.getroot(),
+        this.config.doc.getroot(),
+        this.platform, true);
+    this.config.write();
+
+    // Update own www dir with project's www assets and plugins' assets and js-files
+    this.parser.update_www(cordovaProject, options);
+
+    // Copy or Create manifest.json
+    // todo: move this to a manifest helper module
+    // output path
+    var manifestPath = path.join(this.locations.www, 'manifest.json');
+    var srcManifestPath = path.join(cordovaProject.locations.www, 'manifest.json');
+    if (fs.existsSync(srcManifestPath)) {
+        // just blindly copy it to our output/www
+        // todo: validate it? ensure all properties we expect exist?
+        this.events.emit('verbose', 'copying ' + srcManifestPath + ' => ' + manifestPath);
+        shell.cp('-f', srcManifestPath, manifestPath);
+    } else {
+        var manifestJson = {
+            'background_color': '#FFF',
+            'display': 'standalone'
+        };
+        if (this.config) {
+            if (this.config.name()) {
+                manifestJson.name = this.config.name();
+            }
+            if (this.config.shortName()) {
+                manifestJson.short_name = this.config.shortName();
+            }
+            if (this.config.packageName()) {
+                manifestJson.version = this.config.packageName();
+            }
+            if (this.config.description()) {
+                manifestJson.description = this.config.description();
+            }
+            if (this.config.author()) {
+                manifestJson.author = this.config.author();
+            }
+            // icons
+            var icons = this.config.getStaticResources('electron', 'icon');
+            var manifestIcons = icons.map(function (icon) {
+                // given a tag like this :
+                // <icon src="res/ios/icon.png" width="57" height="57" density="mdpi" />
+                /* configParser returns icons that look like this :
+                {   src: 'res/ios/icon.png',
+                    target: undefined,
+                    density: 'mdpi',
+                    platform: null,
+                    width: 57,
+                    height: 57
+                } ******/
+                /* manifest expects them to be like this :
+                {   "src": "images/touch/icon-128x128.png",
+                    "type": "image/png",
+                    "sizes": "128x128"
+                } ******/
+                // ?Is it worth looking at file extentions?
+                return {'src': icon.src,
+                    'type': 'image/png',
+                    'sizes': (icon.width + 'x' + icon.height)};
+            });
+            manifestJson.icons = manifestIcons;
+
+            // orientation
+            // <preference name="Orientation" value="landscape" />
+            var oriPref = this.config.getGlobalPreference('Orientation');
+            if (oriPref) {
+                // if it's a supported value, use it
+                if (['landscape', 'portrait'].indexOf(oriPref) > -1) {
+                    manifestJson.orientation = oriPref;
+                } else { // anything else maps to 'any'
+                    manifestJson.orientation = 'any';
+                }
+            }
+
+            // get start_url
+            var contentNode = this.config.doc.find('content') || {'attrib': {'src': 'index.html'}}; // sensible default
+            manifestJson.start_url = contentNode.attrib.src;
+
+            // now we get some values from start_url page ...
+            var startUrlPath = path.join(cordovaProject.locations.www, manifestJson.start_url);
+            if (fs.existsSync(startUrlPath)) {
+                var contents = fs.readFileSync(startUrlPath, 'utf-8');
+                // matches <meta name="theme-color" content="#FF0044">
+                var themeColorRegex = /<meta(?=[^>]*name="theme-color")\s[^>]*content="([^>]*)"/i;
+                var result = themeColorRegex.exec(contents);
+                var themeColor;
+                if (result && result.length >= 2) {
+                    themeColor = result[1];
+                } else { // see if there is a preference in config.xml
+                    // <preference name="StatusBarBackgroundColor" value="#000000" />
+                    themeColor = this.config.getGlobalPreference('StatusBarBackgroundColor');
+                }
+                if (themeColor) {
+                    manifestJson.theme_color = themeColor;
+                }
+            }
+        }
+        fs.writeFileSync(manifestPath, JSON.stringify(manifestJson, null, 2), 'utf8');
+    }
+
+    // update project according to config.xml changes.
+    return this.parser.update_project(this.config, options);
+};
+
+Api.prototype.addPlugin = function (pluginInfo, installOptions) {
+
+    // console.log(new Error().stack);
+    if (!pluginInfo) {
+        return Promise.reject(new Error('The parameter is incorrect. The first parameter ' +
+            'should be valid PluginInfo instance'));
+    }
+
+    installOptions = installOptions || {};
+    installOptions.variables = installOptions.variables || {};
+    // CB-10108 platformVersion option is required for proper plugin installation
+    installOptions.platformVersion = installOptions.platformVersion ||
+        this.getPlatformInfo().version;
+
+    var self = this;
+    var actions = new ActionStack();
+    var projectFile = this.handler.parseProjectFile && this.handler.parseProjectFile(this.root);
+
+    // gather all files needs to be handled during install
+    pluginInfo.getFilesAndFrameworks(this.platform)
+        .concat(pluginInfo.getAssets(this.platform))
+        .concat(pluginInfo.getJsModules(this.platform))
+        .forEach(function (item) {
+            actions.push(actions.createAction(
+                self._getInstaller(item.itemType),
+                [item, pluginInfo.dir, pluginInfo.id, installOptions, projectFile],
+                self._getUninstaller(item.itemType),
+                [item, pluginInfo.dir, pluginInfo.id, installOptions, projectFile]));
+        });
+
+    // run through the action stack
+    return actions.process(this.platform, this.root)
+        .then(function () {
+            if (projectFile) {
+                projectFile.write();
+            }
+
+            // Add PACKAGE_NAME variable into vars
+            if (!installOptions.variables.PACKAGE_NAME) {
+                installOptions.variables.PACKAGE_NAME = self.handler.package_name(self.root);
+            }
+
+            self._munger
+                // Ignore passed `is_top_level` option since platform itself doesn't know
+                // anything about managing dependencies - it's responsibility of caller.
+                .add_plugin_changes(pluginInfo, installOptions.variables, /* is_top_level= */true, /* should_increment= */true)
+                .save_all();
+
+            var targetDir = installOptions.usePlatformWww ?
+                self.getPlatformInfo().locations.platformWww :
+                self.getPlatformInfo().locations.www;
+
+            self._addModulesInfo(pluginInfo, targetDir);
+        });
+};
+
+Api.prototype.removePlugin = function (plugin, uninstallOptions) {
+
+    uninstallOptions = uninstallOptions || {};
+    // CB-10108 platformVersion option is required for proper plugin installation
+    uninstallOptions.platformVersion = uninstallOptions.platformVersion ||
+        this.getPlatformInfo().version;
+
+    var self = this;
+    var actions = new ActionStack();
+    var projectFile = this.handler.parseProjectFile && this.handler.parseProjectFile(this.root);
+
+    // queue up plugin files
+    plugin.getFilesAndFrameworks(this.platform)
+        .concat(plugin.getAssets(this.platform))
+        .concat(plugin.getJsModules(this.platform))
+        .forEach(function (item) {
+            actions.push(actions.createAction(
+                self._getUninstaller(item.itemType), [item, plugin.dir, plugin.id, uninstallOptions, projectFile],
+                self._getInstaller(item.itemType), [item, plugin.dir, plugin.id, uninstallOptions, projectFile]));
+        });
+
+    // run through the action stack
+    return actions.process(this.platform, this.root)
+        .then(function () {
+            if (projectFile) {
+                projectFile.write();
+            }
+
+            self._munger
+                // Ignore passed `is_top_level` option since platform itself doesn't know
+                // anything about managing dependencies - it's responsibility of caller.
+                .remove_plugin_changes(plugin, /* is_top_level= */true)
+                .save_all();
+
+            var targetDir = uninstallOptions.usePlatformWww ?
+                self.getPlatformInfo().locations.platformWww :
+                self.getPlatformInfo().locations.www;
+
+            self._removeModulesInfo(plugin, targetDir);
+            // Remove stale plugin directory
+            // TODO: this should be done by plugin files uninstaller
+            shell.rm('-rf', path.resolve(self.root, 'Plugins', plugin.id));
+        });
+};
+
+Api.prototype._getInstaller = function (type) {
+    var self = this;
+    return function (item, plugin_dir, plugin_id, options, project) {
+        var installer = self.handler[type];
+
+        if (!installer) {
+            console.log('unrecognized type ' + type);
+
+        } else {
+            var wwwDest = options.usePlatformWww ?
+                self.getPlatformInfo().locations.platformWww :
+                self.handler.www_dir(self.root);
+
+            if (type === 'asset') {
+                installer.install(item, plugin_dir, wwwDest);
+            } else if (type === 'js-module') {
+                installer.install(item, plugin_dir, plugin_id, wwwDest);
+            } else {
+                installer.install(item, plugin_dir, self.root, plugin_id, options, project);
+            }
+        }
+    };
+};
+
+Api.prototype._getUninstaller = function (type) {
+    var self = this;
+    return function (item, plugin_dir, plugin_id, options, project) {
+        var installer = self.handler[type];
+
+        if (!installer) {
+            console.log('electron plugin uninstall: unrecognized type, skipping : ' + type);
+
+        } else {
+            var wwwDest = options.usePlatformWww ?
+                self.getPlatformInfo().locations.platformWww :
+                self.handler.www_dir(self.root);
+
+            if (['asset', 'js-module'].indexOf(type) > -1) {
+                return installer.uninstall(item, wwwDest, plugin_id);
+            } else {
+                return installer.uninstall(item, self.root, plugin_id, options, project);
+            }
+
+        }
+    };
+};
+
+/**
+ * Removes the specified modules from list of installed modules and updates
+ *   platform_json and cordova_plugins.js on disk.
+ *
+ * @param   {PluginInfo}  plugin  PluginInfo instance for plugin, which modules
+ *   needs to be added.
+ * @param   {String}  targetDir  The directory, where updated cordova_plugins.js
+ *   should be written to.
+ */
+Api.prototype._addModulesInfo = function (plugin, targetDir) {
+    var installedModules = this._platformJson.root.modules || [];
+
+    var installedPaths = installedModules.map(function (installedModule) {
+        return installedModule.file;
+    });
+
+    var modulesToInstall = plugin.getJsModules(this.platform)
+        .filter(function (moduleToInstall) {
+            return installedPaths.indexOf(moduleToInstall.file) === -1;
+        }).map(function (moduleToInstall) {
+            var moduleName = plugin.id + '.' + (moduleToInstall.name || moduleToInstall.src.match(/([^\/]+)\.js/)[1]);
+            var obj = {
+                file: ['plugins', plugin.id, moduleToInstall.src].join('/'), /* eslint no-useless-escape : 0 */
+                id: moduleName,
+                pluginId: plugin.id
+            };
+            if (moduleToInstall.clobbers.length > 0) {
+                obj.clobbers = moduleToInstall.clobbers.map(function (o) { return o.target; });
+            }
+            if (moduleToInstall.merges.length > 0) {
+                obj.merges = moduleToInstall.merges.map(function (o) { return o.target; });
+            }
+            if (moduleToInstall.runs) {
+                obj.runs = true;
+            }
+
+            return obj;
+        });
+
+    this._platformJson.root.modules = installedModules.concat(modulesToInstall);
+    if (!this._platformJson.root.plugin_metadata) {
+        this._platformJson.root.plugin_metadata = {};
+    }
+    this._platformJson.root.plugin_metadata[plugin.id] = plugin.version;
+
+    this._writePluginModules(targetDir);
+    this._platformJson.save();
+};
+/**
+ * Fetches all installed modules, generates cordova_plugins contents and writes
+ *   it to file.
+ *
+ * @param   {String}  targetDir  Directory, where write cordova_plugins.js to.
+ *   Ususally it is either <platform>/www or <platform>/platform_www
+ *   directories.
+ */
+Api.prototype._writePluginModules = function (targetDir) {
+    // Write out moduleObjects as JSON wrapped in a cordova module to cordova_plugins.js
+    var final_contents = 'cordova.define(\'cordova/plugin_list\', function(require, exports, module) {\n';
+    final_contents += 'module.exports = ' + JSON.stringify(this._platformJson.root.modules, null, '    ') + ';\n';
+    final_contents += 'module.exports.metadata = \n';
+    final_contents += '// TOP OF METADATA\n';
+    final_contents += JSON.stringify(this._platformJson.root.plugin_metadata || {}, null, '    ') + '\n';
+    final_contents += '// BOTTOM OF METADATA\n';
+    final_contents += '});'; // Close cordova.define.
+
+    shell.mkdir('-p', targetDir);
+    fs.writeFileSync(path.join(targetDir, 'cordova_plugins.js'), final_contents, 'utf-8');
+};
+
+/**
+ * Removes the specified modules from list of installed modules and updates
+ *   platform_json and cordova_plugins.js on disk.
+ *
+ * @param   {PluginInfo}  plugin  PluginInfo instance for plugin, which modules
+ *   needs to be removed.
+ * @param   {String}  targetDir  The directory, where updated cordova_plugins.js
+ *   should be written to.
+ */
+Api.prototype._removeModulesInfo = function (plugin, targetDir) {
+    var installedModules = this._platformJson.root.modules || [];
+    var modulesToRemove = plugin.getJsModules(this.platform)
+        .map(function (jsModule) {
+            return ['plugins', plugin.id, jsModule.src].join('/');
+        });
+
+    var updatedModules = installedModules
+        .filter(function (installedModule) {
+            return (modulesToRemove.indexOf(installedModule.file) === -1);
+        });
+
+    this._platformJson.root.modules = updatedModules;
+    if (this._platformJson.root.plugin_metadata) {
+        delete this._platformJson.root.plugin_metadata[plugin.id];
+    }
+
+    this._writePluginModules(targetDir);
+    this._platformJson.save();
+};
+
+Api.prototype.build = function (buildOptions) {
+    var self = this;
+    return require('./lib/check_reqs').run()
+        .then(function () {
+            return require('./lib/build').run.call(self, buildOptions);
+        });
+};
+
+Api.prototype.run = function (runOptions) {
+    return require('./lib/run').run(runOptions);
+};
+
+Api.prototype.clean = function (cleanOptions) {
+    return require('./lib/clean').run(cleanOptions);
+};
+
+Api.prototype.requirements = function () {
+    return require('./lib/check_reqs').run();
+};
+
+module.exports = Api;
similarity index 97%
rename from bin/templates/project/cordova/build
rename to bin/template/cordova/build
index 64b68f4..e867ab1 100755 (executable)
@@ -29,5 +29,6 @@ if ( args[2] == '--help' || args[2] == '/?' || args[2] == '-h' || args[2] == '/h
     build.help();
     process.exit(0);
 } else {
-    build.buildProject();
+
+    build.run();
 }
similarity index 95%
rename from bin/templates/project/cordova/clean
rename to bin/template/cordova/clean
index da21bc7..1852d66 100644 (file)
@@ -22,7 +22,6 @@
 
 var path = require('path'),
     clean = require('./lib/clean'),
-    reqs  = require('./lib/check_reqs'),
     args  = process.argv;
 
 // Support basic help commands
@@ -32,6 +31,6 @@ if ( args.length > 2
     console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'clean')) );
     process.exit(0);
 } else {
-    clean.cleanProject();
+    clean.run();
 }
 
diff --git a/bin/template/cordova/clean.bat b/bin/template/cordova/clean.bat
new file mode 100644 (file)
index 0000000..5c572aa
--- /dev/null
@@ -0,0 +1,26 @@
+:: Licensed to the Apache Software Foundation (ASF) under one
+:: or more contributor license agreements.  See the NOTICE file
+:: distributed with this work for additional information
+:: regarding copyright ownership.  The ASF licenses this file
+:: to you under the Apache License, Version 2.0 (the
+:: "License"); you may not use this file except in compliance
+:: with the License.  You may obtain a copy of the License at
+::
+:: http://www.apache.org/licenses/LICENSE-2.0
+::
+:: Unless required by applicable law or agreed to in writing,
+:: software distributed under the License is distributed on an
+:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+:: KIND, either express or implied.  See the License for the
+:: specific language governing permissions and limitations
+:: under the License.
+
+@ECHO OFF
+SET script_path="%~dp0clean"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'clean' script in 'cordova' folder, aborting...>&2
+    EXIT /B 1
+)
diff --git a/bin/template/cordova/handler.js b/bin/template/cordova/handler.js
new file mode 100644 (file)
index 0000000..23c9c23
--- /dev/null
@@ -0,0 +1,131 @@
+/**
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+var path = require('path');
+var fs = require('fs');
+var shell = require('shelljs');
+var events = require('cordova-common').events;
+
+module.exports = {
+    www_dir: function (project_dir) {
+        return path.join(project_dir, 'www');
+    },
+    package_name: function (project_dir) {
+        // this method should the id from root config.xml => <widget id=xxx
+        // return common.package_name(project_dir, this.www_dir(project_dir));
+        // console.log('package_name called with ' + project_dir);
+        var pkgName = 'io.cordova.hellocordova';
+        var widget_id_regex = /(?:<widget\s+id=['"])(\S+)(?:['"])/;
+
+        var configPath = path.join(project_dir, 'config.xml');
+        if (fs.existsSync(configPath)) {
+            var configStr = fs.readFileSync(configPath, 'utf8');
+            var res = configStr.match(widget_id_regex);
+            if (res && res.length > 1) {
+                pkgName = res[1];
+            }
+        }
+        return pkgName;
+    },
+    'js-module': {
+        install: function (jsModule, plugin_dir, plugin_id, www_dir) {
+            // Copy the plugin's files into the www directory.
+            var moduleSource = path.resolve(plugin_dir, jsModule.src);
+            // Get module name based on existing 'name' attribute or filename
+            // Must use path.extname/path.basename instead of path.parse due to CB-9981
+            var moduleName = plugin_id + '.' + (jsModule.name || path.basename(jsModule.src, path.extname(jsModule.src)));
+
+            // Read in the file, prepend the cordova.define, and write it back out.
+            var scriptContent = fs.readFileSync(moduleSource, 'utf-8').replace(/^\ufeff/, ''); // Window BOM
+            if (moduleSource.match(/.*\.json$/)) {
+                scriptContent = 'module.exports = ' + scriptContent;
+            }
+            scriptContent = 'cordova.define("' + moduleName + '", function(require, exports, module) { ' + scriptContent + '\n});\n';
+
+            var moduleDestination = path.resolve(www_dir, 'plugins', plugin_id, jsModule.src);
+            shell.mkdir('-p', path.dirname(moduleDestination));
+            fs.writeFileSync(moduleDestination, scriptContent, 'utf-8');
+        },
+        uninstall: function (jsModule, www_dir, plugin_id) {
+            var pluginRelativePath = path.join('plugins', plugin_id, jsModule.src);
+            // common.removeFileAndParents(www_dir, pluginRelativePath);
+            console.log('js-module uninstall called : ' + pluginRelativePath);
+        }
+    },
+    'source-file': {
+        install: function (obj, plugin_dir, project_dir, plugin_id, options) {
+            // var dest = path.join(obj.targetDir, path.basename(obj.src));
+            // common.copyFile(plugin_dir, obj.src, project_dir, dest);
+            console.log('install called');
+        },
+        uninstall: function (obj, project_dir, plugin_id, options) {
+            // var dest = path.join(obj.targetDir, path.basename(obj.src));
+            // common.removeFile(project_dir, dest);
+            console.log('uninstall called');
+        }
+    },
+    'header-file': {
+        install: function (obj, plugin_dir, project_dir, plugin_id, options) {
+            events.emit('verbose', 'header-fileinstall is not supported for electron');
+        },
+        uninstall: function (obj, project_dir, plugin_id, options) {
+            events.emit('verbose', 'header-file.uninstall is not supported for electron');
+        }
+    },
+    'resource-file': {
+        install: function (obj, plugin_dir, project_dir, plugin_id, options) {
+            events.emit('verbose', 'resource-file.install is not supported for electron');
+        },
+        uninstall: function (obj, project_dir, plugin_id, options) {
+            events.emit('verbose', 'resource-file.uninstall is not supported for electron');
+        }
+    },
+    'framework': {
+        install: function (obj, plugin_dir, project_dir, plugin_id, options) {
+            events.emit('verbose', 'framework.install is not supported for electron');
+        },
+        uninstall: function (obj, project_dir, plugin_id, options) {
+            events.emit('verbose', 'framework.uninstall is not supported for electron');
+        }
+    },
+    'lib-file': {
+        install: function (obj, plugin_dir, project_dir, plugin_id, options) {
+            events.emit('verbose', 'lib-file.install is not supported for electron');
+        },
+        uninstall: function (obj, project_dir, plugin_id, options) {
+            events.emit('verbose', 'lib-file.uninstall is not supported for electron');
+        }
+    },
+    asset: {
+        install: function (asset, plugin_dir, wwwDest) {
+            var src = path.join(plugin_dir, asset.src);
+            var dest = path.join(wwwDest, asset.target);
+
+            if (fs.statSync(src).isDirectory()) {
+                shell.cp('-Rf', src + '/*', dest);
+            } else {
+                shell.cp('-f', src, dest);
+            }
+        },
+        uninstall: function (asset, wwwDest, plugin_id) {
+            shell.rm('-rf', path.join(wwwDest, asset.target));
+            shell.rm('-rf', path.join(wwwDest, 'plugins', plugin_id));
+        }
+    }
+};
diff --git a/bin/template/cordova/lib/build.js b/bin/template/cordova/lib/build.js
new file mode 100644 (file)
index 0000000..209cdb5
--- /dev/null
@@ -0,0 +1,37 @@
+#!/usr/bin/env node
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var path = require('path');
+var check_reqs = require('./check_reqs');
+
+/**
+ * run
+ *   Creates a zip file int platform/build folder
+ */
+module.exports.run = function () {
+    return check_reqs.run();
+};
+
+module.exports.help = function () {
+    console.log('Usage: cordova build electron');
+    var wwwPath = path.resolve(path.join(__dirname, '../../www'));
+    console.log("Build will create the packaged app in '" + wwwPath + "'.");
+};
similarity index 55%
rename from bin/templates/project/cordova/lib/clean.js
rename to bin/template/cordova/lib/clean.js
index 78c75b6..eff91b5 100644 (file)
  * specific language governing permissions and limitations
  * under the License.
  */
-var fs = require('fs'),
-    shjs = require('shelljs'),
-    path = require('path'),
-    check_reqs = require('./check_reqs'),
-    platformBuildDir = path.join('platforms', 'browser', 'build');
 
-exports.cleanProject = function(){
+var fs = require('fs');
+var shell = require('shelljs');
+var path = require('path');
+var check_reqs = require('./check_reqs');
+var platformBuildDir = path.join('platforms', 'electron', 'www');
 
-    // Check that requirements are (stil) met
+var run = function () {
+
+    // TODO: everything calls check_reqs ... why?
+    // Check that requirements are (still) met
     if (!check_reqs.run()) {
-        console.error('Please make sure you meet the software requirements in order to clean an browser cordova project');
+        console.error('Please make sure you meet the software requirements in order to clean an electron cordova project');
         process.exit(2);
     }
-    
-    console.log('Cleaning Browser project');
+
     try {
         if (fs.existsSync(platformBuildDir)) {
-            shjs.rm('-r', platformBuildDir);
+            shell.rm('-r', platformBuildDir);
         }
+    } catch (err) {
+        console.log('could not remove ' + platformBuildDir + ' : ' + err.message);
     }
-    catch(err) {
-        console.log('could not remove '+platformBuildDir+' : '+err.message);
-    }
-
-
-}
+};
 
+module.exports.run = run;
+// just on the off chance something is still calling cleanProject, we will leave this here for a while
+module.exports.cleanProject = function () {
+    console.log('lib/clean will soon only export a `run` command, please update to not call `cleanProject`.');
+    return run();
+};
similarity index 64%
rename from bin/templates/project/www/spec/helper.js
rename to bin/template/cordova/lib/run.js
index 929f776..2d4972f 100644 (file)
@@ -1,3 +1,5 @@
+#!/usr/bin/env node
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * specific language governing permissions and limitations
  * under the License.
  */
-afterEach(function() {
-    document.getElementById('stage').innerHTML = '';
-});
 
-var helper = {
-    trigger: function(obj, name) {
-        var e = document.createEvent('Event');
-        e.initEvent(name, true, true);
-        obj.dispatchEvent(e);
-    },
-    getComputedStyle: function(querySelector, property) {
-        var element = document.querySelector(querySelector);
-        return window.getComputedStyle(element).getPropertyValue(property);
-    }
+// var fs = require('fs');
+// var path = require('path');
+// var url = require('url');
+// var cordovaServe = require('cordova-serve');
+
+module.exports.run = function (args) {
+    // TODO:
 };
similarity index 75%
rename from bin/templates/project/cordova/run
rename to bin/template/cordova/log
index c83d498..bb6fb8c 100755 (executable)
@@ -8,9 +8,7 @@
        to you under the Apache License, Version 2.0 (the
        "License"); you may not use this file except in compliance
        with the License.  You may obtain a copy of the License at
-
          http://www.apache.org/licenses/LICENSE-2.0
-    
        Unless required by applicable law or agreed to in writing,
        software distributed under the License is distributed on an
        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
        under the License.
 */
 
-var run = require('./lib/run'),
-    args = process.argv;
-
-//Support basic help commands
-if(args[2] === '--help' || args[2] == '/?' || args[2] == '-h' || 
-        args[2] === 'help' || args[2] == '-help' || args[2] == '/help') {
-    run.help(args);
-} else {
-    run.run(args);
-}
+console.log("cordova/log");
\ No newline at end of file
diff --git a/bin/template/cordova/parser.js b/bin/template/cordova/parser.js
new file mode 100644 (file)
index 0000000..eef08ac
--- /dev/null
@@ -0,0 +1,120 @@
+/**
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+var fs = require('fs');
+var path = require('path');
+var shell = require('shelljs');
+var CordovaError = require('cordova-common').CordovaError;
+var events = require('cordova-common').events;
+var FileUpdater = require('cordova-common').FileUpdater;
+
+function dirExists (dir) {
+    return fs.existsSync(dir) && fs.statSync(dir).isDirectory();
+}
+
+function parser (project) {
+    if (!dirExists(project) || !dirExists(path.join(project, 'cordova'))) {
+        throw new CordovaError('The provided path "' + project + '" is not a valid electron project.');
+    }
+    this.path = project;
+}
+
+module.exports = parser;
+
+// Returns a promise.
+parser.prototype.update_from_config = function () {
+    return Promise.resolve();
+};
+
+parser.prototype.www_dir = function () {
+    return path.join(this.path, 'www');
+};
+
+// Used for creating platform_www in projects created by older versions.
+parser.prototype.cordovajs_path = function (libDir) {
+    var jsPath = path.join(libDir, 'cordova-lib', 'cordova.js');
+    return path.resolve(jsPath);
+};
+
+parser.prototype.cordovajs_src_path = function (libDir) {
+    // console.log("cordovajs_src_path");
+    var jsPath = path.join(libDir, 'cordova-js-src');
+    return path.resolve(jsPath);
+};
+
+/**
+ * Logs all file operations via the verbose event stream, indented.
+ */
+function logFileOp (message) {
+    events.emit('verbose', '  ' + message);
+}
+
+// Replace the www dir with contents of platform_www and app www.
+parser.prototype.update_www = function (cordovaProject, opts) {
+    var platform_www = path.join(this.path, 'platform_www');
+    var my_www = this.www_dir();
+    // add cordova www and platform_www to sourceDirs
+    var sourceDirs = [
+        path.relative(cordovaProject.root, cordovaProject.locations.www),
+        path.relative(cordovaProject.root, platform_www)
+    ];
+
+    // If project contains 'merges' for our platform, use them as another overrides
+    var merges_path = path.join(cordovaProject.root, 'merges', 'electron');
+    if (fs.existsSync(merges_path)) {
+        events.emit('verbose', 'Found "merges/electron" folder. Copying its contents into the electron project.');
+        // add merges/electron to sourceDirs
+        sourceDirs.push(path.join('merges', 'electron'));
+    }
+
+    // targetDir points to electron/www
+    var targetDir = path.relative(cordovaProject.root, my_www);
+    events.emit('verbose', 'Merging and updating files from [' + sourceDirs.join(', ') + '] to ' + targetDir);
+    FileUpdater.mergeAndUpdateDir(sourceDirs, targetDir, { rootDir: cordovaProject.root }, logFileOp);
+};
+
+parser.prototype.update_overrides = function () {
+    // console.log("update_overrides");
+
+    // TODO: ?
+    // var projectRoot = util.isCordova(this.path);
+    // var mergesPath = path.join(util.appDir(projectRoot), 'merges', 'electron');
+    // if(fs.existsSync(mergesPath)) {
+    //     var overrides = path.join(mergesPath, '*');
+    //     shell.cp('-rf', overrides, this.www_dir());
+    // }
+};
+
+parser.prototype.config_xml = function () {
+    return path.join(this.path, 'config.xml');
+};
+
+// Returns a promise.
+parser.prototype.update_project = function (cfg) {
+    // console.log("update_project ",cfg);
+    var defer = this.update_from_config();
+    var self = this;
+    var www_dir = self.www_dir();
+    defer.then(function () {
+        self.update_overrides();
+        // Copy munged config.xml to platform www dir
+        shell.cp('-rf', path.join(www_dir, '..', 'config.xml'), www_dir);
+    });
+    return defer;
+};
diff --git a/bin/template/cordova/run b/bin/template/cordova/run
new file mode 100755 (executable)
index 0000000..592416c
--- /dev/null
@@ -0,0 +1,47 @@
+#!/usr/bin/env node
+
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+var fs = require('fs'),
+    path = require('path'),
+    nopt  = require('nopt'),
+    url = require('url'),
+    runForrest = require('./lib/run'),
+    cordovaServe = require('cordova-serve');
+
+var args = process.argv;
+
+start(args);
+
+function start(argv) {
+    var args  = nopt({'help': Boolean, 'target': String, 'port': Number}, {'help': ['/?', '-h', 'help', '-help', '/help']}, argv);
+    if(args.help) {
+        help();
+    }
+    else {
+        return runForrest.run(args);
+    }
+}
+
+function help() {
+    console.log("\nUsage: run");
+    console.log(""); // TODO ?
+    process.exit(0);
+}
similarity index 97%
rename from bin/templates/project/cordova/version
rename to bin/template/cordova/version
index 2e1ade7..bde86e6 100755 (executable)
@@ -20,6 +20,6 @@
 */
 
 // Coho updates this line:
-var VERSION = "3.7.0-dev";
+var VERSION = "5.1.0-dev";
 
 console.log(VERSION);
diff --git a/bin/template/www/favicon.ico b/bin/template/www/favicon.ico
new file mode 100644 (file)
index 0000000..fa7a758
Binary files /dev/null and b/bin/template/www/favicon.ico differ
diff --git a/bin/template/www/img/logo.png b/bin/template/www/img/logo.png
new file mode 100644 (file)
index 0000000..4453279
Binary files /dev/null and b/bin/template/www/img/logo.png differ
diff --git a/bin/template/www/img/splash.png b/bin/template/www/img/splash.png
new file mode 100644 (file)
index 0000000..38acd8f
Binary files /dev/null and b/bin/template/www/img/splash.png differ
similarity index 92%
rename from bin/templates/project/www/index.html
rename to bin/template/www/index.html
index bde5741..42eb422 100644 (file)
     <head>
         <meta charset="utf-8" />
         <meta name="format-detection" content="telephone=no" />
-        <!-- WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 -->
+        <meta name="theme-color" content="#2196F3"/>
         <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
         <link rel="stylesheet" type="text/css" href="css/index.css" />
+        <link rel="manifest" href="manifest.json">
         <title>Hello World</title>
     </head>
     <body>
similarity index 93%
rename from bin/templates/project/www/js/index.js
rename to bin/template/www/js/index.js
index 31d9064..1750a54 100644 (file)
  */
 var app = {
     // Application Constructor
-    initialize: function() {
+    initialize: function () {
         this.bindEvents();
     },
     // Bind Event Listeners
     //
     // Bind any events that are required on startup. Common events are:
     // 'load', 'deviceready', 'offline', and 'online'.
-    bindEvents: function() {
+    bindEvents: function () {
         document.addEventListener('deviceready', this.onDeviceReady, false);
     },
     // deviceready Event Handler
     //
     // The scope of 'this' is the event. In order to call the 'receivedEvent'
     // function, we must explicity call 'app.receivedEvent(...);'
-    onDeviceReady: function() {
+    onDeviceReady: function () {
         app.receivedEvent('deviceready');
     },
     // Update DOM on a Received Event
-    receivedEvent: function(id) {
+    receivedEvent: function (id) {
         var parentElement = document.getElementById(id);
         var listeningElement = parentElement.querySelector('.listening');
         var receivedElement = parentElement.querySelector('.received');
diff --git a/bin/template/www/manifest.json b/bin/template/www/manifest.json
new file mode 100644 (file)
index 0000000..b7e3981
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "name": "My App",
+  "short_name":"My Ap",
+  "description": "Description of your app from template",
+  "start_url": "index.html",
+  "scope":"index.html",
+  "icons": [{
+    "src": "img/logo.png",
+    "sizes": "192x192",
+    "type": "image/png"
+  }, {
+    "src": "img/splash.png",
+    "sizes": "512x512",
+    "type": "image/png"
+  }],
+  "default_locale": "en",
+  "display": "standalone",
+  "background_color":"#FFF",
+  "theme_color":"#000",
+  "orientation": "landscape"
+}
\ No newline at end of file
diff --git a/bin/templates/project/cordova/lib/build.js b/bin/templates/project/cordova/lib/build.js
deleted file mode 100644 (file)
index e46178c..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/env node
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-var path = require('path'),
-    fs = require('fs'),
-    clean = require('./clean'),
-    shjs = require('shelljs'),
-    zip = require('adm-zip'),
-    check_reqs = require('./check_reqs'),
-    platformWwwDir          = path.join('platforms', 'browser', 'www'),
-    platformBuildDir        = path.join('platforms', 'browser', 'build'),
-    packageFile             = path.join(platformBuildDir, 'package.zip');
-
-/**
- * buildProject
- *   Creates a zip file int platform/build folder
- */
-exports.buildProject = function(){
-
-    // Check that requirements are (stil) met
-    if (!check_reqs.run()) {
-        console.error('Please make sure you meet the software requirements in order to build a browser cordova project');
-        process.exit(2);
-    }
-    
-    clean.cleanProject(); // remove old build result
-
-    if (!fs.existsSync(platformBuildDir)) {
-        fs.mkdirSync(platformBuildDir);
-    }
-
-    // add the project to a zipfile
-    var zipFile = zip();
-    zipFile.addLocalFolder(platformWwwDir, '.');
-    zipFile.writeZip(packageFile);
-
-    console.log('Browser packaged app built in '+ packageFile);
-
-    process.exit(0);
-};
-
-module.exports.help = function() {
-    console.log('Usage: cordova build browser');
-    console.log('Build will create the packaged app in \''+platformBuildDir+'\'.');
-};
diff --git a/bin/templates/project/cordova/lib/exec.js b/bin/templates/project/cordova/lib/exec.js
deleted file mode 100644 (file)
index 43bbc55..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-       Licensed to the Apache Software Foundation (ASF) under one
-       or more contributor license agreements.  See the NOTICE file
-       distributed with this work for additional information
-       regarding copyright ownership.  The ASF licenses this file
-       to you under the Apache License, Version 2.0 (the
-       "License"); you may not use this file except in compliance
-       with the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing,
-       software distributed under the License is distributed on an
-       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-       KIND, either express or implied.  See the License for the
-       specific language governing permissions and limitations
-       under the License.
-*/
-
-var child_process = require('child_process'),
-    Q = require('q');
-
-/**
- * Executes the command specified.
- * @param  {string} cmd Command to execute
- * @param  {[string]}  opt_cwd Current working directory
- * @return {Q} promise a promise that either resolves with the stdout, or rejects with an error message and the stderr.
- */
-module.exports = function(cmd, opt_cwd) {
-    var d = Q.defer();
-    try {
-        child_process.exec(cmd, {cwd: opt_cwd, maxBuffer: 1024000}, function(err, stdout, stderr) {
-            if (err) {
-              d.reject(new Error('Error executing "' + cmd + '": ' + stderr));
-            }
-            else {
-              d.resolve(stdout);
-            }
-        });
-    } catch(e) {
-        console.error('error caught: ' + e);
-        d.reject(e);
-    }
-    return d.promise;
-};
-
diff --git a/bin/templates/project/cordova/lib/main.js b/bin/templates/project/cordova/lib/main.js
deleted file mode 100644 (file)
index f83033b..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-var app = require('app');  // Module to control application life.
-var BrowserWindow = require('browser-window');  // Module to create native browser window.
-
-// Report crashes to our server.
-require('crash-reporter').start();
-
-// Keep a global reference of the window object, if you don't, the window will
-// be closed automatically when the javascript object is GCed.
-var mainWindow = null;
-
-// Quit when all windows are closed.
-app.on('window-all-closed', function() {
-  if (process.platform != 'darwin')
-    app.quit();
-});
-
-// This method will be called when Electron has done everything
-// initialization and ready for creating browser windows.
-app.on('ready', function() {
-  // Create the browser window.
-  mainWindow = new BrowserWindow({width: 800, height: 600});
-  console.log(__dirname)
-  console.log(process.cwd())
-  //console.log('file://'/www/index.html')
-  // and load the index.html of the app.
-  mainWindow.loadUrl('file://' + __dirname + '/helloworld/www/index.html');
-
-  // Emitted when the window is closed.
-  mainWindow.on('closed', function() {
-    // Dereference the window object, usually you would store windows
-    // in an array if your app supports multi windows, this is the time
-    // when you should delete the corresponding element.
-    mainWindow = null;
-  });
-});
diff --git a/bin/templates/project/cordova/lib/run.js b/bin/templates/project/cordova/lib/run.js
deleted file mode 100644 (file)
index fe15996..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-var spawn = require('child_process').spawn,
-    shell = require('shelljs'),
-    path = require('path'),
-    electron = require('electron-prebuilt');
-
-exports.help = function(args) {
-    console.log('Implement Help');
-    process.exit(0);
-}
-
-exports.run = function(args) {
-    console.log('run');
-    console.log(electron);
-    console.log(__dirname)
-    spawn(electron, [path.join(__dirname, '/main.js')])
-}
diff --git a/bin/templates/project/www/img/logo.png b/bin/templates/project/www/img/logo.png
deleted file mode 100644 (file)
index 9519e7d..0000000
Binary files a/bin/templates/project/www/img/logo.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/android/icon-36-ldpi.png b/bin/templates/project/www/res/icon/android/icon-36-ldpi.png
deleted file mode 100644 (file)
index cd5032a..0000000
Binary files a/bin/templates/project/www/res/icon/android/icon-36-ldpi.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/android/icon-48-mdpi.png b/bin/templates/project/www/res/icon/android/icon-48-mdpi.png
deleted file mode 100644 (file)
index e79c606..0000000
Binary files a/bin/templates/project/www/res/icon/android/icon-48-mdpi.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/android/icon-72-hdpi.png b/bin/templates/project/www/res/icon/android/icon-72-hdpi.png
deleted file mode 100644 (file)
index 4d27634..0000000
Binary files a/bin/templates/project/www/res/icon/android/icon-72-hdpi.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/android/icon-96-xhdpi.png b/bin/templates/project/www/res/icon/android/icon-96-xhdpi.png
deleted file mode 100644 (file)
index ec7ffbf..0000000
Binary files a/bin/templates/project/www/res/icon/android/icon-96-xhdpi.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/bada-wac/icon-48-type5.png b/bin/templates/project/www/res/icon/bada-wac/icon-48-type5.png
deleted file mode 100644 (file)
index 8ad8bac..0000000
Binary files a/bin/templates/project/www/res/icon/bada-wac/icon-48-type5.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/bada-wac/icon-50-type3.png b/bin/templates/project/www/res/icon/bada-wac/icon-50-type3.png
deleted file mode 100644 (file)
index c6ddf84..0000000
Binary files a/bin/templates/project/www/res/icon/bada-wac/icon-50-type3.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/bada-wac/icon-80-type4.png b/bin/templates/project/www/res/icon/bada-wac/icon-80-type4.png
deleted file mode 100644 (file)
index f86a27a..0000000
Binary files a/bin/templates/project/www/res/icon/bada-wac/icon-80-type4.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/bada/icon-128.png b/bin/templates/project/www/res/icon/bada/icon-128.png
deleted file mode 100644 (file)
index 3516df3..0000000
Binary files a/bin/templates/project/www/res/icon/bada/icon-128.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/blackberry/icon-80.png b/bin/templates/project/www/res/icon/blackberry/icon-80.png
deleted file mode 100644 (file)
index f86a27a..0000000
Binary files a/bin/templates/project/www/res/icon/blackberry/icon-80.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/blackberry10/icon-80.png b/bin/templates/project/www/res/icon/blackberry10/icon-80.png
deleted file mode 100644 (file)
index f86a27a..0000000
Binary files a/bin/templates/project/www/res/icon/blackberry10/icon-80.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/ios/icon-57-2x.png b/bin/templates/project/www/res/icon/ios/icon-57-2x.png
deleted file mode 100644 (file)
index efd9c37..0000000
Binary files a/bin/templates/project/www/res/icon/ios/icon-57-2x.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/ios/icon-57.png b/bin/templates/project/www/res/icon/ios/icon-57.png
deleted file mode 100644 (file)
index c795fc4..0000000
Binary files a/bin/templates/project/www/res/icon/ios/icon-57.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/ios/icon-72-2x.png b/bin/templates/project/www/res/icon/ios/icon-72-2x.png
deleted file mode 100644 (file)
index dd819da..0000000
Binary files a/bin/templates/project/www/res/icon/ios/icon-72-2x.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/ios/icon-72.png b/bin/templates/project/www/res/icon/ios/icon-72.png
deleted file mode 100644 (file)
index b1cfde7..0000000
Binary files a/bin/templates/project/www/res/icon/ios/icon-72.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/tizen/icon-128.png b/bin/templates/project/www/res/icon/tizen/icon-128.png
deleted file mode 100644 (file)
index 3516df3..0000000
Binary files a/bin/templates/project/www/res/icon/tizen/icon-128.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/webos/icon-64.png b/bin/templates/project/www/res/icon/webos/icon-64.png
deleted file mode 100644 (file)
index 03b3849..0000000
Binary files a/bin/templates/project/www/res/icon/webos/icon-64.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/windows-phone/icon-173-tile.png b/bin/templates/project/www/res/icon/windows-phone/icon-173-tile.png
deleted file mode 100644 (file)
index 4f15e20..0000000
Binary files a/bin/templates/project/www/res/icon/windows-phone/icon-173-tile.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/windows-phone/icon-48.png b/bin/templates/project/www/res/icon/windows-phone/icon-48.png
deleted file mode 100644 (file)
index 8ad8bac..0000000
Binary files a/bin/templates/project/www/res/icon/windows-phone/icon-48.png and /dev/null differ
diff --git a/bin/templates/project/www/res/icon/windows-phone/icon-62-tile.png b/bin/templates/project/www/res/icon/windows-phone/icon-62-tile.png
deleted file mode 100644 (file)
index aab6061..0000000
Binary files a/bin/templates/project/www/res/icon/windows-phone/icon-62-tile.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/android/screen-hdpi-landscape.png b/bin/templates/project/www/res/screen/android/screen-hdpi-landscape.png
deleted file mode 100644 (file)
index a61e2b1..0000000
Binary files a/bin/templates/project/www/res/screen/android/screen-hdpi-landscape.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/android/screen-hdpi-portrait.png b/bin/templates/project/www/res/screen/android/screen-hdpi-portrait.png
deleted file mode 100644 (file)
index 5d6a28a..0000000
Binary files a/bin/templates/project/www/res/screen/android/screen-hdpi-portrait.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/android/screen-ldpi-landscape.png b/bin/templates/project/www/res/screen/android/screen-ldpi-landscape.png
deleted file mode 100644 (file)
index f3934cd..0000000
Binary files a/bin/templates/project/www/res/screen/android/screen-ldpi-landscape.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/android/screen-ldpi-portrait.png b/bin/templates/project/www/res/screen/android/screen-ldpi-portrait.png
deleted file mode 100644 (file)
index 65ad163..0000000
Binary files a/bin/templates/project/www/res/screen/android/screen-ldpi-portrait.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/android/screen-mdpi-landscape.png b/bin/templates/project/www/res/screen/android/screen-mdpi-landscape.png
deleted file mode 100644 (file)
index a1b697c..0000000
Binary files a/bin/templates/project/www/res/screen/android/screen-mdpi-landscape.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/android/screen-mdpi-portrait.png b/bin/templates/project/www/res/screen/android/screen-mdpi-portrait.png
deleted file mode 100644 (file)
index ea15693..0000000
Binary files a/bin/templates/project/www/res/screen/android/screen-mdpi-portrait.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/android/screen-xhdpi-landscape.png b/bin/templates/project/www/res/screen/android/screen-xhdpi-landscape.png
deleted file mode 100644 (file)
index 79f2f09..0000000
Binary files a/bin/templates/project/www/res/screen/android/screen-xhdpi-landscape.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/android/screen-xhdpi-portrait.png b/bin/templates/project/www/res/screen/android/screen-xhdpi-portrait.png
deleted file mode 100644 (file)
index c2e8042..0000000
Binary files a/bin/templates/project/www/res/screen/android/screen-xhdpi-portrait.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/bada-wac/screen-type3.png b/bin/templates/project/www/res/screen/bada-wac/screen-type3.png
deleted file mode 100755 (executable)
index ea15693..0000000
Binary files a/bin/templates/project/www/res/screen/bada-wac/screen-type3.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/bada-wac/screen-type4.png b/bin/templates/project/www/res/screen/bada-wac/screen-type4.png
deleted file mode 100755 (executable)
index 5d6a28a..0000000
Binary files a/bin/templates/project/www/res/screen/bada-wac/screen-type4.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/bada-wac/screen-type5.png b/bin/templates/project/www/res/screen/bada-wac/screen-type5.png
deleted file mode 100755 (executable)
index bd64f76..0000000
Binary files a/bin/templates/project/www/res/screen/bada-wac/screen-type5.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/bada/screen-portrait.png b/bin/templates/project/www/res/screen/bada/screen-portrait.png
deleted file mode 100644 (file)
index 5d6a28a..0000000
Binary files a/bin/templates/project/www/res/screen/bada/screen-portrait.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/blackberry/screen-225.png b/bin/templates/project/www/res/screen/blackberry/screen-225.png
deleted file mode 100644 (file)
index 29873e9..0000000
Binary files a/bin/templates/project/www/res/screen/blackberry/screen-225.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/blackberry10/splash-1280x768.png b/bin/templates/project/www/res/screen/blackberry10/splash-1280x768.png
deleted file mode 100644 (file)
index 5f4bca9..0000000
Binary files a/bin/templates/project/www/res/screen/blackberry10/splash-1280x768.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/blackberry10/splash-720x720.png b/bin/templates/project/www/res/screen/blackberry10/splash-720x720.png
deleted file mode 100644 (file)
index fe1756f..0000000
Binary files a/bin/templates/project/www/res/screen/blackberry10/splash-720x720.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/blackberry10/splash-768x1280.png b/bin/templates/project/www/res/screen/blackberry10/splash-768x1280.png
deleted file mode 100644 (file)
index 0fb9c1b..0000000
Binary files a/bin/templates/project/www/res/screen/blackberry10/splash-768x1280.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/ios/screen-ipad-landscape-2x.png b/bin/templates/project/www/res/screen/ios/screen-ipad-landscape-2x.png
deleted file mode 100644 (file)
index 95c542d..0000000
Binary files a/bin/templates/project/www/res/screen/ios/screen-ipad-landscape-2x.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/ios/screen-ipad-landscape.png b/bin/templates/project/www/res/screen/ios/screen-ipad-landscape.png
deleted file mode 100644 (file)
index 04be5ac..0000000
Binary files a/bin/templates/project/www/res/screen/ios/screen-ipad-landscape.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/ios/screen-ipad-portrait-2x.png b/bin/templates/project/www/res/screen/ios/screen-ipad-portrait-2x.png
deleted file mode 100644 (file)
index aae1862..0000000
Binary files a/bin/templates/project/www/res/screen/ios/screen-ipad-portrait-2x.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/ios/screen-ipad-portrait.png b/bin/templates/project/www/res/screen/ios/screen-ipad-portrait.png
deleted file mode 100644 (file)
index 41e839d..0000000
Binary files a/bin/templates/project/www/res/screen/ios/screen-ipad-portrait.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/ios/screen-iphone-landscape-2x.png b/bin/templates/project/www/res/screen/ios/screen-iphone-landscape-2x.png
deleted file mode 100644 (file)
index 0165669..0000000
Binary files a/bin/templates/project/www/res/screen/ios/screen-iphone-landscape-2x.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/ios/screen-iphone-landscape.png b/bin/templates/project/www/res/screen/ios/screen-iphone-landscape.png
deleted file mode 100644 (file)
index d154883..0000000
Binary files a/bin/templates/project/www/res/screen/ios/screen-iphone-landscape.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/ios/screen-iphone-portrait-2x.png b/bin/templates/project/www/res/screen/ios/screen-iphone-portrait-2x.png
deleted file mode 100644 (file)
index bd24886..0000000
Binary files a/bin/templates/project/www/res/screen/ios/screen-iphone-portrait-2x.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/ios/screen-iphone-portrait-568h-2x.png b/bin/templates/project/www/res/screen/ios/screen-iphone-portrait-568h-2x.png
deleted file mode 100644 (file)
index 10ed683..0000000
Binary files a/bin/templates/project/www/res/screen/ios/screen-iphone-portrait-568h-2x.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/ios/screen-iphone-portrait.png b/bin/templates/project/www/res/screen/ios/screen-iphone-portrait.png
deleted file mode 100644 (file)
index 6fcba56..0000000
Binary files a/bin/templates/project/www/res/screen/ios/screen-iphone-portrait.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/tizen/README.md b/bin/templates/project/www/res/screen/tizen/README.md
deleted file mode 100644 (file)
index 3a0d6fe..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# Tizen Splash Screen
-
-Splash screens are unsupported on the Tizen platform.
diff --git a/bin/templates/project/www/res/screen/webos/screen-64.png b/bin/templates/project/www/res/screen/webos/screen-64.png
deleted file mode 100644 (file)
index 03b3849..0000000
Binary files a/bin/templates/project/www/res/screen/webos/screen-64.png and /dev/null differ
diff --git a/bin/templates/project/www/res/screen/windows-phone/screen-portrait.jpg b/bin/templates/project/www/res/screen/windows-phone/screen-portrait.jpg
deleted file mode 100644 (file)
index 479d3e4..0000000
Binary files a/bin/templates/project/www/res/screen/windows-phone/screen-portrait.jpg and /dev/null differ
diff --git a/bin/templates/project/www/spec.html b/bin/templates/project/www/spec.html
deleted file mode 100644 (file)
index 71f00de..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-<!DOCTYPE html>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing,
-    software distributed under the License is distributed on an
-    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-     KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
--->
-<html>
-    <head>
-        <title>Jasmine Spec Runner</title>
-
-        <!-- jasmine source -->
-        <link rel="shortcut icon" type="image/png" href="spec/lib/jasmine-1.2.0/jasmine_favicon.png">
-        <link rel="stylesheet" type="text/css" href="spec/lib/jasmine-1.2.0/jasmine.css">
-        <script type="text/javascript" src="spec/lib/jasmine-1.2.0/jasmine.js"></script>
-        <script type="text/javascript" src="spec/lib/jasmine-1.2.0/jasmine-html.js"></script>
-
-        <!-- include source files here... -->
-        <script type="text/javascript" src="js/index.js"></script>
-
-        <!-- include spec files here... -->
-        <script type="text/javascript" src="spec/helper.js"></script>
-        <script type="text/javascript" src="spec/index.js"></script>
-
-        <script type="text/javascript">
-            (function() {
-                var jasmineEnv = jasmine.getEnv();
-                jasmineEnv.updateInterval = 1000;
-
-                var htmlReporter = new jasmine.HtmlReporter();
-
-                jasmineEnv.addReporter(htmlReporter);
-
-                jasmineEnv.specFilter = function(spec) {
-                    return htmlReporter.specFilter(spec);
-                };
-
-                var currentWindowOnload = window.onload;
-
-                window.onload = function() {
-                    if (currentWindowOnload) {
-                        currentWindowOnload();
-                    }
-                    execJasmine();
-                };
-
-                function execJasmine() {
-                    jasmineEnv.execute();
-                }
-            })();
-        </script>
-    </head>
-    <body>
-        <div id="stage" style="display:none;"></div>
-    </body>
-</html>
diff --git a/bin/templates/project/www/spec/index.js b/bin/templates/project/www/spec/index.js
deleted file mode 100644 (file)
index 20f8be5..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-describe('app', function() {
-    describe('initialize', function() {
-        it('should bind deviceready', function() {
-            runs(function() {
-                spyOn(app, 'onDeviceReady');
-                app.initialize();
-                helper.trigger(window.document, 'deviceready');
-            });
-
-            waitsFor(function() {
-                return (app.onDeviceReady.calls.length > 0);
-            }, 'onDeviceReady should be called once', 500);
-
-            runs(function() {
-                expect(app.onDeviceReady).toHaveBeenCalled();
-            });
-        });
-    });
-
-    describe('onDeviceReady', function() {
-        it('should report that it fired', function() {
-            spyOn(app, 'receivedEvent');
-            app.onDeviceReady();
-            expect(app.receivedEvent).toHaveBeenCalledWith('deviceready');
-        });
-    });
-
-    describe('receivedEvent', function() {
-        beforeEach(function() {
-            var el = document.getElementById('stage');
-            el.innerHTML = ['<div id="deviceready">',
-                            '    <p class="event listening">Listening</p>',
-                            '    <p class="event received">Received</p>',
-                            '</div>'].join('\n');
-        });
-
-        it('should hide the listening element', function() {
-            app.receivedEvent('deviceready');
-            var displayStyle = helper.getComputedStyle('#deviceready .listening', 'display');
-            expect(displayStyle).toEqual('none');
-        });
-
-        it('should show the received element', function() {
-            app.receivedEvent('deviceready');
-            var displayStyle = helper.getComputedStyle('#deviceready .received', 'display');
-            expect(displayStyle).toEqual('block');
-        });
-    });
-});
diff --git a/bin/templates/project/www/spec/lib/jasmine-1.2.0/MIT.LICENSE b/bin/templates/project/www/spec/lib/jasmine-1.2.0/MIT.LICENSE
deleted file mode 100644 (file)
index 7c435ba..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2008-2011 Pivotal Labs
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/bin/templates/project/www/spec/lib/jasmine-1.2.0/jasmine-html.js b/bin/templates/project/www/spec/lib/jasmine-1.2.0/jasmine-html.js
deleted file mode 100644 (file)
index a0b0639..0000000
+++ /dev/null
@@ -1,616 +0,0 @@
-jasmine.HtmlReporterHelpers = {};
-
-jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) {
-  var el = document.createElement(type);
-
-  for (var i = 2; i < arguments.length; i++) {
-    var child = arguments[i];
-
-    if (typeof child === 'string') {
-      el.appendChild(document.createTextNode(child));
-    } else {
-      if (child) {
-        el.appendChild(child);
-      }
-    }
-  }
-
-  for (var attr in attrs) {
-    if (attr == "className") {
-      el[attr] = attrs[attr];
-    } else {
-      el.setAttribute(attr, attrs[attr]);
-    }
-  }
-
-  return el;
-};
-
-jasmine.HtmlReporterHelpers.getSpecStatus = function(child) {
-  var results = child.results();
-  var status = results.passed() ? 'passed' : 'failed';
-  if (results.skipped) {
-    status = 'skipped';
-  }
-
-  return status;
-};
-
-jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) {
-  var parentDiv = this.dom.summary;
-  var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite';
-  var parent = child[parentSuite];
-
-  if (parent) {
-    if (typeof this.views.suites[parent.id] == 'undefined') {
-      this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views);
-    }
-    parentDiv = this.views.suites[parent.id].element;
-  }
-
-  parentDiv.appendChild(childElement);
-};
-
-
-jasmine.HtmlReporterHelpers.addHelpers = function(ctor) {
-  for(var fn in jasmine.HtmlReporterHelpers) {
-    ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn];
-  }
-};
-
-jasmine.HtmlReporter = function(_doc) {
-  var self = this;
-  var doc = _doc || window.document;
-
-  var reporterView;
-
-  var dom = {};
-
-  // Jasmine Reporter Public Interface
-  self.logRunningSpecs = false;
-
-  self.reportRunnerStarting = function(runner) {
-    var specs = runner.specs() || [];
-
-    if (specs.length == 0) {
-      return;
-    }
-
-    createReporterDom(runner.env.versionString());
-    doc.body.appendChild(dom.reporter);
-
-    reporterView = new jasmine.HtmlReporter.ReporterView(dom);
-    reporterView.addSpecs(specs, self.specFilter);
-  };
-
-  self.reportRunnerResults = function(runner) {
-    reporterView && reporterView.complete();
-  };
-
-  self.reportSuiteResults = function(suite) {
-    reporterView.suiteComplete(suite);
-  };
-
-  self.reportSpecStarting = function(spec) {
-    if (self.logRunningSpecs) {
-      self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
-    }
-  };
-
-  self.reportSpecResults = function(spec) {
-    reporterView.specComplete(spec);
-  };
-
-  self.log = function() {
-    var console = jasmine.getGlobal().console;
-    if (console && console.log) {
-      if (console.log.apply) {
-        console.log.apply(console, arguments);
-      } else {
-        console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
-      }
-    }
-  };
-
-  self.specFilter = function(spec) {
-    if (!focusedSpecName()) {
-      return true;
-    }
-
-    return spec.getFullName().indexOf(focusedSpecName()) === 0;
-  };
-
-  return self;
-
-  function focusedSpecName() {
-    var specName;
-
-    (function memoizeFocusedSpec() {
-      if (specName) {
-        return;
-      }
-
-      var paramMap = [];
-      var params = doc.location.search.substring(1).split('&');
-
-      for (var i = 0; i < params.length; i++) {
-        var p = params[i].split('=');
-        paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
-      }
-
-      specName = paramMap.spec;
-    })();
-
-    return specName;
-  }
-
-  function createReporterDom(version) {
-    dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' },
-      dom.banner = self.createDom('div', { className: 'banner' },
-        self.createDom('span', { className: 'title' }, "Jasmine "),
-        self.createDom('span', { className: 'version' }, version)),
-
-      dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}),
-      dom.alert = self.createDom('div', {className: 'alert'}),
-      dom.results = self.createDom('div', {className: 'results'},
-        dom.summary = self.createDom('div', { className: 'summary' }),
-        dom.details = self.createDom('div', { id: 'details' }))
-    );
-  }
-};
-jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);jasmine.HtmlReporter.ReporterView = function(dom) {
-  this.startedAt = new Date();
-  this.runningSpecCount = 0;
-  this.completeSpecCount = 0;
-  this.passedCount = 0;
-  this.failedCount = 0;
-  this.skippedCount = 0;
-
-  this.createResultsMenu = function() {
-    this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'},
-      this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'),
-      ' | ',
-      this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing'));
-
-    this.summaryMenuItem.onclick = function() {
-      dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, '');
-    };
-
-    this.detailsMenuItem.onclick = function() {
-      showDetails();
-    };
-  };
-
-  this.addSpecs = function(specs, specFilter) {
-    this.totalSpecCount = specs.length;
-
-    this.views = {
-      specs: {},
-      suites: {}
-    };
-
-    for (var i = 0; i < specs.length; i++) {
-      var spec = specs[i];
-      this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views);
-      if (specFilter(spec)) {
-        this.runningSpecCount++;
-      }
-    }
-  };
-
-  this.specComplete = function(spec) {
-    this.completeSpecCount++;
-
-    if (isUndefined(this.views.specs[spec.id])) {
-      this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom);
-    }
-
-    var specView = this.views.specs[spec.id];
-
-    switch (specView.status()) {
-      case 'passed':
-        this.passedCount++;
-        break;
-
-      case 'failed':
-        this.failedCount++;
-        break;
-
-      case 'skipped':
-        this.skippedCount++;
-        break;
-    }
-
-    specView.refresh();
-    this.refresh();
-  };
-
-  this.suiteComplete = function(suite) {
-    var suiteView = this.views.suites[suite.id];
-    if (isUndefined(suiteView)) {
-      return;
-    }
-    suiteView.refresh();
-  };
-
-  this.refresh = function() {
-
-    if (isUndefined(this.resultsMenu)) {
-      this.createResultsMenu();
-    }
-
-    // currently running UI
-    if (isUndefined(this.runningAlert)) {
-      this.runningAlert = this.createDom('a', {href: "?", className: "runningAlert bar"});
-      dom.alert.appendChild(this.runningAlert);
-    }
-    this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount);
-
-    // skipped specs UI
-    if (isUndefined(this.skippedAlert)) {
-      this.skippedAlert = this.createDom('a', {href: "?", className: "skippedAlert bar"});
-    }
-
-    this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
-
-    if (this.skippedCount === 1 && isDefined(dom.alert)) {
-      dom.alert.appendChild(this.skippedAlert);
-    }
-
-    // passing specs UI
-    if (isUndefined(this.passedAlert)) {
-      this.passedAlert = this.createDom('span', {href: "?", className: "passingAlert bar"});
-    }
-    this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount);
-
-    // failing specs UI
-    if (isUndefined(this.failedAlert)) {
-      this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"});
-    }
-    this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount);
-
-    if (this.failedCount === 1 && isDefined(dom.alert)) {
-      dom.alert.appendChild(this.failedAlert);
-      dom.alert.appendChild(this.resultsMenu);
-    }
-
-    // summary info
-    this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount);
-    this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing";
-  };
-
-  this.complete = function() {
-    dom.alert.removeChild(this.runningAlert);
-
-    this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
-
-    if (this.failedCount === 0) {
-      dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount)));
-    } else {
-      showDetails();
-    }
-
-    dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"));
-  };
-
-  return this;
-
-  function showDetails() {
-    if (dom.reporter.className.search(/showDetails/) === -1) {
-      dom.reporter.className += " showDetails";
-    }
-  }
-
-  function isUndefined(obj) {
-    return typeof obj === 'undefined';
-  }
-
-  function isDefined(obj) {
-    return !isUndefined(obj);
-  }
-
-  function specPluralizedFor(count) {
-    var str = count + " spec";
-    if (count > 1) {
-      str += "s"
-    }
-    return str;
-  }
-
-};
-
-jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView);
-
-
-jasmine.HtmlReporter.SpecView = function(spec, dom, views) {
-  this.spec = spec;
-  this.dom = dom;
-  this.views = views;
-
-  this.symbol = this.createDom('li', { className: 'pending' });
-  this.dom.symbolSummary.appendChild(this.symbol);
-
-  this.summary = this.createDom('div', { className: 'specSummary' },
-      this.createDom('a', {
-        className: 'description',
-        href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
-        title: this.spec.getFullName()
-      }, this.spec.description)
-  );
-
-  this.detail = this.createDom('div', { className: 'specDetail' },
-      this.createDom('a', {
-        className: 'description',
-        href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
-        title: this.spec.getFullName()
-      }, this.spec.getFullName())
-  );
-};
-
-jasmine.HtmlReporter.SpecView.prototype.status = function() {
-  return this.getSpecStatus(this.spec);
-};
-
-jasmine.HtmlReporter.SpecView.prototype.refresh = function() {
-  this.symbol.className = this.status();
-
-  switch (this.status()) {
-    case 'skipped':
-      break;
-
-    case 'passed':
-      this.appendSummaryToSuiteDiv();
-      break;
-
-    case 'failed':
-      this.appendSummaryToSuiteDiv();
-      this.appendFailureDetail();
-      break;
-  }
-};
-
-jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() {
-  this.summary.className += ' ' + this.status();
-  this.appendToSummary(this.spec, this.summary);
-};
-
-jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() {
-  this.detail.className += ' ' + this.status();
-
-  var resultItems = this.spec.results().getItems();
-  var messagesDiv = this.createDom('div', { className: 'messages' });
-
-  for (var i = 0; i < resultItems.length; i++) {
-    var result = resultItems[i];
-
-    if (result.type == 'log') {
-      messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
-    } else if (result.type == 'expect' && result.passed && !result.passed()) {
-      messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
-
-      if (result.trace.stack) {
-        messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
-      }
-    }
-  }
-
-  if (messagesDiv.childNodes.length > 0) {
-    this.detail.appendChild(messagesDiv);
-    this.dom.details.appendChild(this.detail);
-  }
-};
-
-jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) {
-  this.suite = suite;
-  this.dom = dom;
-  this.views = views;
-
-  this.element = this.createDom('div', { className: 'suite' },
-      this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(this.suite.getFullName()) }, this.suite.description)
-  );
-
-  this.appendToSummary(this.suite, this.element);
-};
-
-jasmine.HtmlReporter.SuiteView.prototype.status = function() {
-  return this.getSpecStatus(this.suite);
-};
-
-jasmine.HtmlReporter.SuiteView.prototype.refresh = function() {
-  this.element.className += " " + this.status();
-};
-
-jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView);
-
-/* @deprecated Use jasmine.HtmlReporter instead
- */
-jasmine.TrivialReporter = function(doc) {
-  this.document = doc || document;
-  this.suiteDivs = {};
-  this.logRunningSpecs = false;
-};
-
-jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
-  var el = document.createElement(type);
-
-  for (var i = 2; i < arguments.length; i++) {
-    var child = arguments[i];
-
-    if (typeof child === 'string') {
-      el.appendChild(document.createTextNode(child));
-    } else {
-      if (child) { el.appendChild(child); }
-    }
-  }
-
-  for (var attr in attrs) {
-    if (attr == "className") {
-      el[attr] = attrs[attr];
-    } else {
-      el.setAttribute(attr, attrs[attr]);
-    }
-  }
-
-  return el;
-};
-
-jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
-  var showPassed, showSkipped;
-
-  this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' },
-      this.createDom('div', { className: 'banner' },
-        this.createDom('div', { className: 'logo' },
-            this.createDom('span', { className: 'title' }, "Jasmine"),
-            this.createDom('span', { className: 'version' }, runner.env.versionString())),
-        this.createDom('div', { className: 'options' },
-            "Show ",
-            showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
-            this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
-            showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
-            this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
-            )
-          ),
-
-      this.runnerDiv = this.createDom('div', { className: 'runner running' },
-          this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
-          this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
-          this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
-      );
-
-  this.document.body.appendChild(this.outerDiv);
-
-  var suites = runner.suites();
-  for (var i = 0; i < suites.length; i++) {
-    var suite = suites[i];
-    var suiteDiv = this.createDom('div', { className: 'suite' },
-        this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
-        this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
-    this.suiteDivs[suite.id] = suiteDiv;
-    var parentDiv = this.outerDiv;
-    if (suite.parentSuite) {
-      parentDiv = this.suiteDivs[suite.parentSuite.id];
-    }
-    parentDiv.appendChild(suiteDiv);
-  }
-
-  this.startedAt = new Date();
-
-  var self = this;
-  showPassed.onclick = function(evt) {
-    if (showPassed.checked) {
-      self.outerDiv.className += ' show-passed';
-    } else {
-      self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
-    }
-  };
-
-  showSkipped.onclick = function(evt) {
-    if (showSkipped.checked) {
-      self.outerDiv.className += ' show-skipped';
-    } else {
-      self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
-    }
-  };
-};
-
-jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
-  var results = runner.results();
-  var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
-  this.runnerDiv.setAttribute("class", className);
-  //do it twice for IE
-  this.runnerDiv.setAttribute("className", className);
-  var specs = runner.specs();
-  var specCount = 0;
-  for (var i = 0; i < specs.length; i++) {
-    if (this.specFilter(specs[i])) {
-      specCount++;
-    }
-  }
-  var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
-  message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
-  this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
-
-  this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
-};
-
-jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
-  var results = suite.results();
-  var status = results.passed() ? 'passed' : 'failed';
-  if (results.totalCount === 0) { // todo: change this to check results.skipped
-    status = 'skipped';
-  }
-  this.suiteDivs[suite.id].className += " " + status;
-};
-
-jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
-  if (this.logRunningSpecs) {
-    this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
-  }
-};
-
-jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
-  var results = spec.results();
-  var status = results.passed() ? 'passed' : 'failed';
-  if (results.skipped) {
-    status = 'skipped';
-  }
-  var specDiv = this.createDom('div', { className: 'spec '  + status },
-      this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
-      this.createDom('a', {
-        className: 'description',
-        href: '?spec=' + encodeURIComponent(spec.getFullName()),
-        title: spec.getFullName()
-      }, spec.description));
-
-
-  var resultItems = results.getItems();
-  var messagesDiv = this.createDom('div', { className: 'messages' });
-  for (var i = 0; i < resultItems.length; i++) {
-    var result = resultItems[i];
-
-    if (result.type == 'log') {
-      messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
-    } else if (result.type == 'expect' && result.passed && !result.passed()) {
-      messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
-
-      if (result.trace.stack) {
-        messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
-      }
-    }
-  }
-
-  if (messagesDiv.childNodes.length > 0) {
-    specDiv.appendChild(messagesDiv);
-  }
-
-  this.suiteDivs[spec.suite.id].appendChild(specDiv);
-};
-
-jasmine.TrivialReporter.prototype.log = function() {
-  var console = jasmine.getGlobal().console;
-  if (console && console.log) {
-    if (console.log.apply) {
-      console.log.apply(console, arguments);
-    } else {
-      console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
-    }
-  }
-};
-
-jasmine.TrivialReporter.prototype.getLocation = function() {
-  return this.document.location;
-};
-
-jasmine.TrivialReporter.prototype.specFilter = function(spec) {
-  var paramMap = {};
-  var params = this.getLocation().search.substring(1).split('&');
-  for (var i = 0; i < params.length; i++) {
-    var p = params[i].split('=');
-    paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
-  }
-
-  if (!paramMap.spec) {
-    return true;
-  }
-  return spec.getFullName().indexOf(paramMap.spec) === 0;
-};
diff --git a/bin/templates/project/www/spec/lib/jasmine-1.2.0/jasmine.css b/bin/templates/project/www/spec/lib/jasmine-1.2.0/jasmine.css
deleted file mode 100644 (file)
index 826e575..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
-
-#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
-#HTMLReporter a { text-decoration: none; }
-#HTMLReporter a:hover { text-decoration: underline; }
-#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; }
-#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; }
-#HTMLReporter #jasmine_content { position: fixed; right: 100%; }
-#HTMLReporter .version { color: #aaaaaa; }
-#HTMLReporter .banner { margin-top: 14px; }
-#HTMLReporter .duration { color: #aaaaaa; float: right; }
-#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; }
-#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
-#HTMLReporter .symbolSummary li.passed { font-size: 14px; }
-#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; }
-#HTMLReporter .symbolSummary li.failed { line-height: 9px; }
-#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
-#HTMLReporter .symbolSummary li.skipped { font-size: 14px; }
-#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
-#HTMLReporter .symbolSummary li.pending { line-height: 11px; }
-#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
-#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
-#HTMLReporter .runningAlert { background-color: #666666; }
-#HTMLReporter .skippedAlert { background-color: #aaaaaa; }
-#HTMLReporter .skippedAlert:first-child { background-color: #333333; }
-#HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; }
-#HTMLReporter .passingAlert { background-color: #a6b779; }
-#HTMLReporter .passingAlert:first-child { background-color: #5e7d00; }
-#HTMLReporter .failingAlert { background-color: #cf867e; }
-#HTMLReporter .failingAlert:first-child { background-color: #b03911; }
-#HTMLReporter .results { margin-top: 14px; }
-#HTMLReporter #details { display: none; }
-#HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; }
-#HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
-#HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
-#HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
-#HTMLReporter.showDetails .summary { display: none; }
-#HTMLReporter.showDetails #details { display: block; }
-#HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
-#HTMLReporter .summary { margin-top: 14px; }
-#HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; }
-#HTMLReporter .summary .specSummary.passed a { color: #5e7d00; }
-#HTMLReporter .summary .specSummary.failed a { color: #b03911; }
-#HTMLReporter .description + .suite { margin-top: 0; }
-#HTMLReporter .suite { margin-top: 14px; }
-#HTMLReporter .suite a { color: #333333; }
-#HTMLReporter #details .specDetail { margin-bottom: 28px; }
-#HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; }
-#HTMLReporter .resultMessage { padding-top: 14px; color: #333333; }
-#HTMLReporter .resultMessage span.result { display: block; }
-#HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }
-
-#TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ }
-#TrivialReporter a:visited, #TrivialReporter a { color: #303; }
-#TrivialReporter a:hover, #TrivialReporter a:active { color: blue; }
-#TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; }
-#TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; }
-#TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; }
-#TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; }
-#TrivialReporter .runner.running { background-color: yellow; }
-#TrivialReporter .options { text-align: right; font-size: .8em; }
-#TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; }
-#TrivialReporter .suite .suite { margin: 5px; }
-#TrivialReporter .suite.passed { background-color: #dfd; }
-#TrivialReporter .suite.failed { background-color: #fdd; }
-#TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; }
-#TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; }
-#TrivialReporter .spec.failed { background-color: #fbb; border-color: red; }
-#TrivialReporter .spec.passed { background-color: #bfb; border-color: green; }
-#TrivialReporter .spec.skipped { background-color: #bbb; }
-#TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; }
-#TrivialReporter .passed { background-color: #cfc; display: none; }
-#TrivialReporter .failed { background-color: #fbb; }
-#TrivialReporter .skipped { color: #777; background-color: #eee; display: none; }
-#TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; }
-#TrivialReporter .resultMessage .mismatch { color: black; }
-#TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; }
-#TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; }
-#TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; }
-#TrivialReporter #jasmine_content { position: fixed; right: 100%; }
-#TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; }
diff --git a/bin/templates/project/www/spec/lib/jasmine-1.2.0/jasmine.js b/bin/templates/project/www/spec/lib/jasmine-1.2.0/jasmine.js
deleted file mode 100644 (file)
index 03bf89a..0000000
+++ /dev/null
@@ -1,2529 +0,0 @@
-var isCommonJS = typeof window == "undefined";
-
-/**
- * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
- *
- * @namespace
- */
-var jasmine = {};
-if (isCommonJS) exports.jasmine = jasmine;
-/**
- * @private
- */
-jasmine.unimplementedMethod_ = function() {
-  throw new Error("unimplemented method");
-};
-
-/**
- * Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just
- * a plain old variable and may be redefined by somebody else.
- *
- * @private
- */
-jasmine.undefined = jasmine.___undefined___;
-
-/**
- * Show diagnostic messages in the console if set to true
- *
- */
-jasmine.VERBOSE = false;
-
-/**
- * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed.
- *
- */
-jasmine.DEFAULT_UPDATE_INTERVAL = 250;
-
-/**
- * Default timeout interval in milliseconds for waitsFor() blocks.
- */
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
-
-jasmine.getGlobal = function() {
-  function getGlobal() {
-    return this;
-  }
-
-  return getGlobal();
-};
-
-/**
- * Allows for bound functions to be compared.  Internal use only.
- *
- * @ignore
- * @private
- * @param base {Object} bound 'this' for the function
- * @param name {Function} function to find
- */
-jasmine.bindOriginal_ = function(base, name) {
-  var original = base[name];
-  if (original.apply) {
-    return function() {
-      return original.apply(base, arguments);
-    };
-  } else {
-    // IE support
-    return jasmine.getGlobal()[name];
-  }
-};
-
-jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
-jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
-jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
-jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
-
-jasmine.MessageResult = function(values) {
-  this.type = 'log';
-  this.values = values;
-  this.trace = new Error(); // todo: test better
-};
-
-jasmine.MessageResult.prototype.toString = function() {
-  var text = "";
-  for (var i = 0; i < this.values.length; i++) {
-    if (i > 0) text += " ";
-    if (jasmine.isString_(this.values[i])) {
-      text += this.values[i];
-    } else {
-      text += jasmine.pp(this.values[i]);
-    }
-  }
-  return text;
-};
-
-jasmine.ExpectationResult = function(params) {
-  this.type = 'expect';
-  this.matcherName = params.matcherName;
-  this.passed_ = params.passed;
-  this.expected = params.expected;
-  this.actual = params.actual;
-  this.message = this.passed_ ? 'Passed.' : params.message;
-
-  var trace = (params.trace || new Error(this.message));
-  this.trace = this.passed_ ? '' : trace;
-};
-
-jasmine.ExpectationResult.prototype.toString = function () {
-  return this.message;
-};
-
-jasmine.ExpectationResult.prototype.passed = function () {
-  return this.passed_;
-};
-
-/**
- * Getter for the Jasmine environment. Ensures one gets created
- */
-jasmine.getEnv = function() {
-  var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
-  return env;
-};
-
-/**
- * @ignore
- * @private
- * @param value
- * @returns {Boolean}
- */
-jasmine.isArray_ = function(value) {
-  return jasmine.isA_("Array", value);
-};
-
-/**
- * @ignore
- * @private
- * @param value
- * @returns {Boolean}
- */
-jasmine.isString_ = function(value) {
-  return jasmine.isA_("String", value);
-};
-
-/**
- * @ignore
- * @private
- * @param value
- * @returns {Boolean}
- */
-jasmine.isNumber_ = function(value) {
-  return jasmine.isA_("Number", value);
-};
-
-/**
- * @ignore
- * @private
- * @param {String} typeName
- * @param value
- * @returns {Boolean}
- */
-jasmine.isA_ = function(typeName, value) {
-  return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
-};
-
-/**
- * Pretty printer for expecations.  Takes any object and turns it into a human-readable string.
- *
- * @param value {Object} an object to be outputted
- * @returns {String}
- */
-jasmine.pp = function(value) {
-  var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
-  stringPrettyPrinter.format(value);
-  return stringPrettyPrinter.string;
-};
-
-/**
- * Returns true if the object is a DOM Node.
- *
- * @param {Object} obj object to check
- * @returns {Boolean}
- */
-jasmine.isDomNode = function(obj) {
-  return obj.nodeType > 0;
-};
-
-/**
- * Returns a matchable 'generic' object of the class type.  For use in expecations of type when values don't matter.
- *
- * @example
- * // don't care about which function is passed in, as long as it's a function
- * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
- *
- * @param {Class} clazz
- * @returns matchable object of the type clazz
- */
-jasmine.any = function(clazz) {
-  return new jasmine.Matchers.Any(clazz);
-};
-
-/**
- * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the
- * attributes on the object.
- *
- * @example
- * // don't care about any other attributes than foo.
- * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"});
- *
- * @param sample {Object} sample
- * @returns matchable object for the sample
- */
-jasmine.objectContaining = function (sample) {
-    return new jasmine.Matchers.ObjectContaining(sample);
-};
-
-/**
- * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
- *
- * Spies should be created in test setup, before expectations.  They can then be checked, using the standard Jasmine
- * expectation syntax. Spies can be checked if they were called or not and what the calling params were.
- *
- * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
- *
- * Spies are torn down at the end of every spec.
- *
- * Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
- *
- * @example
- * // a stub
- * var myStub = jasmine.createSpy('myStub');  // can be used anywhere
- *
- * // spy example
- * var foo = {
- *   not: function(bool) { return !bool; }
- * }
- *
- * // actual foo.not will not be called, execution stops
- * spyOn(foo, 'not');
-
- // foo.not spied upon, execution will continue to implementation
- * spyOn(foo, 'not').andCallThrough();
- *
- * // fake example
- * var foo = {
- *   not: function(bool) { return !bool; }
- * }
- *
- * // foo.not(val) will return val
- * spyOn(foo, 'not').andCallFake(function(value) {return value;});
- *
- * // mock example
- * foo.not(7 == 7);
- * expect(foo.not).toHaveBeenCalled();
- * expect(foo.not).toHaveBeenCalledWith(true);
- *
- * @constructor
- * @see spyOn, jasmine.createSpy, jasmine.createSpyObj
- * @param {String} name
- */
-jasmine.Spy = function(name) {
-  /**
-   * The name of the spy, if provided.
-   */
-  this.identity = name || 'unknown';
-  /**
-   *  Is this Object a spy?
-   */
-  this.isSpy = true;
-  /**
-   * The actual function this spy stubs.
-   */
-  this.plan = function() {
-  };
-  /**
-   * Tracking of the most recent call to the spy.
-   * @example
-   * var mySpy = jasmine.createSpy('foo');
-   * mySpy(1, 2);
-   * mySpy.mostRecentCall.args = [1, 2];
-   */
-  this.mostRecentCall = {};
-
-  /**
-   * Holds arguments for each call to the spy, indexed by call count
-   * @example
-   * var mySpy = jasmine.createSpy('foo');
-   * mySpy(1, 2);
-   * mySpy(7, 8);
-   * mySpy.mostRecentCall.args = [7, 8];
-   * mySpy.argsForCall[0] = [1, 2];
-   * mySpy.argsForCall[1] = [7, 8];
-   */
-  this.argsForCall = [];
-  this.calls = [];
-};
-
-/**
- * Tells a spy to call through to the actual implemenatation.
- *
- * @example
- * var foo = {
- *   bar: function() { // do some stuff }
- * }
- *
- * // defining a spy on an existing property: foo.bar
- * spyOn(foo, 'bar').andCallThrough();
- */
-jasmine.Spy.prototype.andCallThrough = function() {
-  this.plan = this.originalValue;
-  return this;
-};
-
-/**
- * For setting the return value of a spy.
- *
- * @example
- * // defining a spy from scratch: foo() returns 'baz'
- * var foo = jasmine.createSpy('spy on foo').andReturn('baz');
- *
- * // defining a spy on an existing property: foo.bar() returns 'baz'
- * spyOn(foo, 'bar').andReturn('baz');
- *
- * @param {Object} value
- */
-jasmine.Spy.prototype.andReturn = function(value) {
-  this.plan = function() {
-    return value;
-  };
-  return this;
-};
-
-/**
- * For throwing an exception when a spy is called.
- *
- * @example
- * // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
- * var foo = jasmine.createSpy('spy on foo').andThrow('baz');
- *
- * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
- * spyOn(foo, 'bar').andThrow('baz');
- *
- * @param {String} exceptionMsg
- */
-jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
-  this.plan = function() {
-    throw exceptionMsg;
-  };
-  return this;
-};
-
-/**
- * Calls an alternate implementation when a spy is called.
- *
- * @example
- * var baz = function() {
- *   // do some stuff, return something
- * }
- * // defining a spy from scratch: foo() calls the function baz
- * var foo = jasmine.createSpy('spy on foo').andCall(baz);
- *
- * // defining a spy on an existing property: foo.bar() calls an anonymnous function
- * spyOn(foo, 'bar').andCall(function() { return 'baz';} );
- *
- * @param {Function} fakeFunc
- */
-jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
-  this.plan = fakeFunc;
-  return this;
-};
-
-/**
- * Resets all of a spy's the tracking variables so that it can be used again.
- *
- * @example
- * spyOn(foo, 'bar');
- *
- * foo.bar();
- *
- * expect(foo.bar.callCount).toEqual(1);
- *
- * foo.bar.reset();
- *
- * expect(foo.bar.callCount).toEqual(0);
- */
-jasmine.Spy.prototype.reset = function() {
-  this.wasCalled = false;
-  this.callCount = 0;
-  this.argsForCall = [];
-  this.calls = [];
-  this.mostRecentCall = {};
-};
-
-jasmine.createSpy = function(name) {
-
-  var spyObj = function() {
-    spyObj.wasCalled = true;
-    spyObj.callCount++;
-    var args = jasmine.util.argsToArray(arguments);
-    spyObj.mostRecentCall.object = this;
-    spyObj.mostRecentCall.args = args;
-    spyObj.argsForCall.push(args);
-    spyObj.calls.push({object: this, args: args});
-    return spyObj.plan.apply(this, arguments);
-  };
-
-  var spy = new jasmine.Spy(name);
-
-  for (var prop in spy) {
-    spyObj[prop] = spy[prop];
-  }
-
-  spyObj.reset();
-
-  return spyObj;
-};
-
-/**
- * Determines whether an object is a spy.
- *
- * @param {jasmine.Spy|Object} putativeSpy
- * @returns {Boolean}
- */
-jasmine.isSpy = function(putativeSpy) {
-  return putativeSpy && putativeSpy.isSpy;
-};
-
-/**
- * Creates a more complicated spy: an Object that has every property a function that is a spy.  Used for stubbing something
- * large in one call.
- *
- * @param {String} baseName name of spy class
- * @param {Array} methodNames array of names of methods to make spies
- */
-jasmine.createSpyObj = function(baseName, methodNames) {
-  if (!jasmine.isArray_(methodNames) || methodNames.length === 0) {
-    throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
-  }
-  var obj = {};
-  for (var i = 0; i < methodNames.length; i++) {
-    obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
-  }
-  return obj;
-};
-
-/**
- * All parameters are pretty-printed and concatenated together, then written to the current spec's output.
- *
- * Be careful not to leave calls to <code>jasmine.log</code> in production code.
- */
-jasmine.log = function() {
-  var spec = jasmine.getEnv().currentSpec;
-  spec.log.apply(spec, arguments);
-};
-
-/**
- * Function that installs a spy on an existing object's method name.  Used within a Spec to create a spy.
- *
- * @example
- * // spy example
- * var foo = {
- *   not: function(bool) { return !bool; }
- * }
- * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
- *
- * @see jasmine.createSpy
- * @param obj
- * @param methodName
- * @returns a Jasmine spy that can be chained with all spy methods
- */
-var spyOn = function(obj, methodName) {
-  return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
-};
-if (isCommonJS) exports.spyOn = spyOn;
-
-/**
- * Creates a Jasmine spec that will be added to the current suite.
- *
- * // TODO: pending tests
- *
- * @example
- * it('should be true', function() {
- *   expect(true).toEqual(true);
- * });
- *
- * @param {String} desc description of this specification
- * @param {Function} func defines the preconditions and expectations of the spec
- */
-var it = function(desc, func) {
-  return jasmine.getEnv().it(desc, func);
-};
-if (isCommonJS) exports.it = it;
-
-/**
- * Creates a <em>disabled</em> Jasmine spec.
- *
- * A convenience method that allows existing specs to be disabled temporarily during development.
- *
- * @param {String} desc description of this specification
- * @param {Function} func defines the preconditions and expectations of the spec
- */
-var xit = function(desc, func) {
-  return jasmine.getEnv().xit(desc, func);
-};
-if (isCommonJS) exports.xit = xit;
-
-/**
- * Starts a chain for a Jasmine expectation.
- *
- * It is passed an Object that is the actual value and should chain to one of the many
- * jasmine.Matchers functions.
- *
- * @param {Object} actual Actual value to test against and expected value
- */
-var expect = function(actual) {
-  return jasmine.getEnv().currentSpec.expect(actual);
-};
-if (isCommonJS) exports.expect = expect;
-
-/**
- * Defines part of a jasmine spec.  Used in cominbination with waits or waitsFor in asynchrnous specs.
- *
- * @param {Function} func Function that defines part of a jasmine spec.
- */
-var runs = function(func) {
-  jasmine.getEnv().currentSpec.runs(func);
-};
-if (isCommonJS) exports.runs = runs;
-
-/**
- * Waits a fixed time period before moving to the next block.
- *
- * @deprecated Use waitsFor() instead
- * @param {Number} timeout milliseconds to wait
- */
-var waits = function(timeout) {
-  jasmine.getEnv().currentSpec.waits(timeout);
-};
-if (isCommonJS) exports.waits = waits;
-
-/**
- * Waits for the latchFunction to return true before proceeding to the next block.
- *
- * @param {Function} latchFunction
- * @param {String} optional_timeoutMessage
- * @param {Number} optional_timeout
- */
-var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
-  jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
-};
-if (isCommonJS) exports.waitsFor = waitsFor;
-
-/**
- * A function that is called before each spec in a suite.
- *
- * Used for spec setup, including validating assumptions.
- *
- * @param {Function} beforeEachFunction
- */
-var beforeEach = function(beforeEachFunction) {
-  jasmine.getEnv().beforeEach(beforeEachFunction);
-};
-if (isCommonJS) exports.beforeEach = beforeEach;
-
-/**
- * A function that is called after each spec in a suite.
- *
- * Used for restoring any state that is hijacked during spec execution.
- *
- * @param {Function} afterEachFunction
- */
-var afterEach = function(afterEachFunction) {
-  jasmine.getEnv().afterEach(afterEachFunction);
-};
-if (isCommonJS) exports.afterEach = afterEach;
-
-/**
- * Defines a suite of specifications.
- *
- * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
- * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
- * of setup in some tests.
- *
- * @example
- * // TODO: a simple suite
- *
- * // TODO: a simple suite with a nested describe block
- *
- * @param {String} description A string, usually the class under test.
- * @param {Function} specDefinitions function that defines several specs.
- */
-var describe = function(description, specDefinitions) {
-  return jasmine.getEnv().describe(description, specDefinitions);
-};
-if (isCommonJS) exports.describe = describe;
-
-/**
- * Disables a suite of specifications.  Used to disable some suites in a file, or files, temporarily during development.
- *
- * @param {String} description A string, usually the class under test.
- * @param {Function} specDefinitions function that defines several specs.
- */
-var xdescribe = function(description, specDefinitions) {
-  return jasmine.getEnv().xdescribe(description, specDefinitions);
-};
-if (isCommonJS) exports.xdescribe = xdescribe;
-
-
-// Provide the XMLHttpRequest class for IE 5.x-6.x:
-jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
-  function tryIt(f) {
-    try {
-      return f();
-    } catch(e) {
-    }
-    return null;
-  }
-
-  var xhr = tryIt(function() {
-    return new ActiveXObject("Msxml2.XMLHTTP.6.0");
-  }) ||
-    tryIt(function() {
-      return new ActiveXObject("Msxml2.XMLHTTP.3.0");
-    }) ||
-    tryIt(function() {
-      return new ActiveXObject("Msxml2.XMLHTTP");
-    }) ||
-    tryIt(function() {
-      return new ActiveXObject("Microsoft.XMLHTTP");
-    });
-
-  if (!xhr) throw new Error("This browser does not support XMLHttpRequest.");
-
-  return xhr;
-} : XMLHttpRequest;
-/**
- * @namespace
- */
-jasmine.util = {};
-
-/**
- * Declare that a child class inherit it's prototype from the parent class.
- *
- * @private
- * @param {Function} childClass
- * @param {Function} parentClass
- */
-jasmine.util.inherit = function(childClass, parentClass) {
-  /**
-   * @private
-   */
-  var subclass = function() {
-  };
-  subclass.prototype = parentClass.prototype;
-  childClass.prototype = new subclass();
-};
-
-jasmine.util.formatException = function(e) {
-  var lineNumber;
-  if (e.line) {
-    lineNumber = e.line;
-  }
-  else if (e.lineNumber) {
-    lineNumber = e.lineNumber;
-  }
-
-  var file;
-
-  if (e.sourceURL) {
-    file = e.sourceURL;
-  }
-  else if (e.fileName) {
-    file = e.fileName;
-  }
-
-  var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
-
-  if (file && lineNumber) {
-    message += ' in ' + file + ' (line ' + lineNumber + ')';
-  }
-
-  return message;
-};
-
-jasmine.util.htmlEscape = function(str) {
-  if (!str) return str;
-  return str.replace(/&/g, '&amp;')
-    .replace(/</g, '&lt;')
-    .replace(/>/g, '&gt;');
-};
-
-jasmine.util.argsToArray = function(args) {
-  var arrayOfArgs = [];
-  for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
-  return arrayOfArgs;
-};
-
-jasmine.util.extend = function(destination, source) {
-  for (var property in source) destination[property] = source[property];
-  return destination;
-};
-
-/**
- * Environment for Jasmine
- *
- * @constructor
- */
-jasmine.Env = function() {
-  this.currentSpec = null;
-  this.currentSuite = null;
-  this.currentRunner_ = new jasmine.Runner(this);
-
-  this.reporter = new jasmine.MultiReporter();
-
-  this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
-  this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
-  this.lastUpdate = 0;
-  this.specFilter = function() {
-    return true;
-  };
-
-  this.nextSpecId_ = 0;
-  this.nextSuiteId_ = 0;
-  this.equalityTesters_ = [];
-
-  // wrap matchers
-  this.matchersClass = function() {
-    jasmine.Matchers.apply(this, arguments);
-  };
-  jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
-
-  jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
-};
-
-
-jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
-jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
-jasmine.Env.prototype.setInterval = jasmine.setInterval;
-jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
-
-/**
- * @returns an object containing jasmine version build info, if set.
- */
-jasmine.Env.prototype.version = function () {
-  if (jasmine.version_) {
-    return jasmine.version_;
-  } else {
-    throw new Error('Version not set');
-  }
-};
-
-/**
- * @returns string containing jasmine version build info, if set.
- */
-jasmine.Env.prototype.versionString = function() {
-  if (!jasmine.version_) {
-    return "version unknown";
-  }
-
-  var version = this.version();
-  var versionString = version.major + "." + version.minor + "." + version.build;
-  if (version.release_candidate) {
-    versionString += ".rc" + version.release_candidate;
-  }
-  versionString += " revision " + version.revision;
-  return versionString;
-};
-
-/**
- * @returns a sequential integer starting at 0
- */
-jasmine.Env.prototype.nextSpecId = function () {
-  return this.nextSpecId_++;
-};
-
-/**
- * @returns a sequential integer starting at 0
- */
-jasmine.Env.prototype.nextSuiteId = function () {
-  return this.nextSuiteId_++;
-};
-
-/**
- * Register a reporter to receive status updates from Jasmine.
- * @param {jasmine.Reporter} reporter An object which will receive status updates.
- */
-jasmine.Env.prototype.addReporter = function(reporter) {
-  this.reporter.addReporter(reporter);
-};
-
-jasmine.Env.prototype.execute = function() {
-  this.currentRunner_.execute();
-};
-
-jasmine.Env.prototype.describe = function(description, specDefinitions) {
-  var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
-
-  var parentSuite = this.currentSuite;
-  if (parentSuite) {
-    parentSuite.add(suite);
-  } else {
-    this.currentRunner_.add(suite);
-  }
-
-  this.currentSuite = suite;
-
-  var declarationError = null;
-  try {
-    specDefinitions.call(suite);
-  } catch(e) {
-    declarationError = e;
-  }
-
-  if (declarationError) {
-    this.it("encountered a declaration exception", function() {
-      throw declarationError;
-    });
-  }
-
-  this.currentSuite = parentSuite;
-
-  return suite;
-};
-
-jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
-  if (this.currentSuite) {
-    this.currentSuite.beforeEach(beforeEachFunction);
-  } else {
-    this.currentRunner_.beforeEach(beforeEachFunction);
-  }
-};
-
-jasmine.Env.prototype.currentRunner = function () {
-  return this.currentRunner_;
-};
-
-jasmine.Env.prototype.afterEach = function(afterEachFunction) {
-  if (this.currentSuite) {
-    this.currentSuite.afterEach(afterEachFunction);
-  } else {
-    this.currentRunner_.afterEach(afterEachFunction);
-  }
-
-};
-
-jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {
-  return {
-    execute: function() {
-    }
-  };
-};
-
-jasmine.Env.prototype.it = function(description, func) {
-  var spec = new jasmine.Spec(this, this.currentSuite, description);
-  this.currentSuite.add(spec);
-  this.currentSpec = spec;
-
-  if (func) {
-    spec.runs(func);
-  }
-
-  return spec;
-};
-
-jasmine.Env.prototype.xit = function(desc, func) {
-  return {
-    id: this.nextSpecId(),
-    runs: function() {
-    }
-  };
-};
-
-jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
-  if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
-    return true;
-  }
-
-  a.__Jasmine_been_here_before__ = b;
-  b.__Jasmine_been_here_before__ = a;
-
-  var hasKey = function(obj, keyName) {
-    return obj !== null && obj[keyName] !== jasmine.undefined;
-  };
-
-  for (var property in b) {
-    if (!hasKey(a, property) && hasKey(b, property)) {
-      mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
-    }
-  }
-  for (property in a) {
-    if (!hasKey(b, property) && hasKey(a, property)) {
-      mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
-    }
-  }
-  for (property in b) {
-    if (property == '__Jasmine_been_here_before__') continue;
-    if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
-      mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual.");
-    }
-  }
-
-  if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
-    mismatchValues.push("arrays were not the same length");
-  }
-
-  delete a.__Jasmine_been_here_before__;
-  delete b.__Jasmine_been_here_before__;
-  return (mismatchKeys.length === 0 && mismatchValues.length === 0);
-};
-
-jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
-  mismatchKeys = mismatchKeys || [];
-  mismatchValues = mismatchValues || [];
-
-  for (var i = 0; i < this.equalityTesters_.length; i++) {
-    var equalityTester = this.equalityTesters_[i];
-    var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
-    if (result !== jasmine.undefined) return result;
-  }
-
-  if (a === b) return true;
-
-  if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
-    return (a == jasmine.undefined && b == jasmine.undefined);
-  }
-
-  if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
-    return a === b;
-  }
-
-  if (a instanceof Date && b instanceof Date) {
-    return a.getTime() == b.getTime();
-  }
-
-  if (a.jasmineMatches) {
-    return a.jasmineMatches(b);
-  }
-
-  if (b.jasmineMatches) {
-    return b.jasmineMatches(a);
-  }
-
-  if (a instanceof jasmine.Matchers.ObjectContaining) {
-    return a.matches(b);
-  }
-
-  if (b instanceof jasmine.Matchers.ObjectContaining) {
-    return b.matches(a);
-  }
-
-  if (jasmine.isString_(a) && jasmine.isString_(b)) {
-    return (a == b);
-  }
-
-  if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
-    return (a == b);
-  }
-
-  if (typeof a === "object" && typeof b === "object") {
-    return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
-  }
-
-  //Straight check
-  return (a === b);
-};
-
-jasmine.Env.prototype.contains_ = function(haystack, needle) {
-  if (jasmine.isArray_(haystack)) {
-    for (var i = 0; i < haystack.length; i++) {
-      if (this.equals_(haystack[i], needle)) return true;
-    }
-    return false;
-  }
-  return haystack.indexOf(needle) >= 0;
-};
-
-jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
-  this.equalityTesters_.push(equalityTester);
-};
-/** No-op base class for Jasmine reporters.
- *
- * @constructor
- */
-jasmine.Reporter = function() {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportSpecResults = function(spec) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.log = function(str) {
-};
-
-/**
- * Blocks are functions with executable code that make up a spec.
- *
- * @constructor
- * @param {jasmine.Env} env
- * @param {Function} func
- * @param {jasmine.Spec} spec
- */
-jasmine.Block = function(env, func, spec) {
-  this.env = env;
-  this.func = func;
-  this.spec = spec;
-};
-
-jasmine.Block.prototype.execute = function(onComplete) {  
-  try {
-    this.func.apply(this.spec);
-  } catch (e) {
-    this.spec.fail(e);
-  }
-  onComplete();
-};
-/** JavaScript API reporter.
- *
- * @constructor
- */
-jasmine.JsApiReporter = function() {
-  this.started = false;
-  this.finished = false;
-  this.suites_ = [];
-  this.results_ = {};
-};
-
-jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
-  this.started = true;
-  var suites = runner.topLevelSuites();
-  for (var i = 0; i < suites.length; i++) {
-    var suite = suites[i];
-    this.suites_.push(this.summarize_(suite));
-  }
-};
-
-jasmine.JsApiReporter.prototype.suites = function() {
-  return this.suites_;
-};
-
-jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
-  var isSuite = suiteOrSpec instanceof jasmine.Suite;
-  var summary = {
-    id: suiteOrSpec.id,
-    name: suiteOrSpec.description,
-    type: isSuite ? 'suite' : 'spec',
-    children: []
-  };
-  
-  if (isSuite) {
-    var children = suiteOrSpec.children();
-    for (var i = 0; i < children.length; i++) {
-      summary.children.push(this.summarize_(children[i]));
-    }
-  }
-  return summary;
-};
-
-jasmine.JsApiReporter.prototype.results = function() {
-  return this.results_;
-};
-
-jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
-  return this.results_[specId];
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
-  this.finished = true;
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
-  this.results_[spec.id] = {
-    messages: spec.results().getItems(),
-    result: spec.results().failedCount > 0 ? "failed" : "passed"
-  };
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.log = function(str) {
-};
-
-jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
-  var results = {};
-  for (var i = 0; i < specIds.length; i++) {
-    var specId = specIds[i];
-    results[specId] = this.summarizeResult_(this.results_[specId]);
-  }
-  return results;
-};
-
-jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
-  var summaryMessages = [];
-  var messagesLength = result.messages.length;
-  for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
-    var resultMessage = result.messages[messageIndex];
-    summaryMessages.push({
-      text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
-      passed: resultMessage.passed ? resultMessage.passed() : true,
-      type: resultMessage.type,
-      message: resultMessage.message,
-      trace: {
-        stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
-      }
-    });
-  }
-
-  return {
-    result : result.result,
-    messages : summaryMessages
-  };
-};
-
-/**
- * @constructor
- * @param {jasmine.Env} env
- * @param actual
- * @param {jasmine.Spec} spec
- */
-jasmine.Matchers = function(env, actual, spec, opt_isNot) {
-  this.env = env;
-  this.actual = actual;
-  this.spec = spec;
-  this.isNot = opt_isNot || false;
-  this.reportWasCalled_ = false;
-};
-
-// todo: @deprecated as of Jasmine 0.11, remove soon [xw]
-jasmine.Matchers.pp = function(str) {
-  throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
-};
-
-// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
-jasmine.Matchers.prototype.report = function(result, failing_message, details) {
-  throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
-};
-
-jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
-  for (var methodName in prototype) {
-    if (methodName == 'report') continue;
-    var orig = prototype[methodName];
-    matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
-  }
-};
-
-jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
-  return function() {
-    var matcherArgs = jasmine.util.argsToArray(arguments);
-    var result = matcherFunction.apply(this, arguments);
-
-    if (this.isNot) {
-      result = !result;
-    }
-
-    if (this.reportWasCalled_) return result;
-
-    var message;
-    if (!result) {
-      if (this.message) {
-        message = this.message.apply(this, arguments);
-        if (jasmine.isArray_(message)) {
-          message = message[this.isNot ? 1 : 0];
-        }
-      } else {
-        var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
-        message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
-        if (matcherArgs.length > 0) {
-          for (var i = 0; i < matcherArgs.length; i++) {
-            if (i > 0) message += ",";
-            message += " " + jasmine.pp(matcherArgs[i]);
-          }
-        }
-        message += ".";
-      }
-    }
-    var expectationResult = new jasmine.ExpectationResult({
-      matcherName: matcherName,
-      passed: result,
-      expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
-      actual: this.actual,
-      message: message
-    });
-    this.spec.addMatcherResult(expectationResult);
-    return jasmine.undefined;
-  };
-};
-
-
-
-
-/**
- * toBe: compares the actual to the expected using ===
- * @param expected
- */
-jasmine.Matchers.prototype.toBe = function(expected) {
-  return this.actual === expected;
-};
-
-/**
- * toNotBe: compares the actual to the expected using !==
- * @param expected
- * @deprecated as of 1.0. Use not.toBe() instead.
- */
-jasmine.Matchers.prototype.toNotBe = function(expected) {
-  return this.actual !== expected;
-};
-
-/**
- * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
- *
- * @param expected
- */
-jasmine.Matchers.prototype.toEqual = function(expected) {
-  return this.env.equals_(this.actual, expected);
-};
-
-/**
- * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
- * @param expected
- * @deprecated as of 1.0. Use not.toEqual() instead.
- */
-jasmine.Matchers.prototype.toNotEqual = function(expected) {
-  return !this.env.equals_(this.actual, expected);
-};
-
-/**
- * Matcher that compares the actual to the expected using a regular expression.  Constructs a RegExp, so takes
- * a pattern or a String.
- *
- * @param expected
- */
-jasmine.Matchers.prototype.toMatch = function(expected) {
-  return new RegExp(expected).test(this.actual);
-};
-
-/**
- * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
- * @param expected
- * @deprecated as of 1.0. Use not.toMatch() instead.
- */
-jasmine.Matchers.prototype.toNotMatch = function(expected) {
-  return !(new RegExp(expected).test(this.actual));
-};
-
-/**
- * Matcher that compares the actual to jasmine.undefined.
- */
-jasmine.Matchers.prototype.toBeDefined = function() {
-  return (this.actual !== jasmine.undefined);
-};
-
-/**
- * Matcher that compares the actual to jasmine.undefined.
- */
-jasmine.Matchers.prototype.toBeUndefined = function() {
-  return (this.actual === jasmine.undefined);
-};
-
-/**
- * Matcher that compares the actual to null.
- */
-jasmine.Matchers.prototype.toBeNull = function() {
-  return (this.actual === null);
-};
-
-/**
- * Matcher that boolean not-nots the actual.
- */
-jasmine.Matchers.prototype.toBeTruthy = function() {
-  return !!this.actual;
-};
-
-
-/**
- * Matcher that boolean nots the actual.
- */
-jasmine.Matchers.prototype.toBeFalsy = function() {
-  return !this.actual;
-};
-
-
-/**
- * Matcher that checks to see if the actual, a Jasmine spy, was called.
- */
-jasmine.Matchers.prototype.toHaveBeenCalled = function() {
-  if (arguments.length > 0) {
-    throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
-  }
-
-  if (!jasmine.isSpy(this.actual)) {
-    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
-  }
-
-  this.message = function() {
-    return [
-      "Expected spy " + this.actual.identity + " to have been called.",
-      "Expected spy " + this.actual.identity + " not to have been called."
-    ];
-  };
-
-  return this.actual.wasCalled;
-};
-
-/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
-jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
-
-/**
- * Matcher that checks to see if the actual, a Jasmine spy, was not called.
- *
- * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
- */
-jasmine.Matchers.prototype.wasNotCalled = function() {
-  if (arguments.length > 0) {
-    throw new Error('wasNotCalled does not take arguments');
-  }
-
-  if (!jasmine.isSpy(this.actual)) {
-    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
-  }
-
-  this.message = function() {
-    return [
-      "Expected spy " + this.actual.identity + " to not have been called.",
-      "Expected spy " + this.actual.identity + " to have been called."
-    ];
-  };
-
-  return !this.actual.wasCalled;
-};
-
-/**
- * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
- *
- * @example
- *
- */
-jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
-  var expectedArgs = jasmine.util.argsToArray(arguments);
-  if (!jasmine.isSpy(this.actual)) {
-    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
-  }
-  this.message = function() {
-    if (this.actual.callCount === 0) {
-      // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
-      return [
-        "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
-        "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
-      ];
-    } else {
-      return [
-        "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
-        "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
-      ];
-    }
-  };
-
-  return this.env.contains_(this.actual.argsForCall, expectedArgs);
-};
-
-/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
-jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
-
-/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
-jasmine.Matchers.prototype.wasNotCalledWith = function() {
-  var expectedArgs = jasmine.util.argsToArray(arguments);
-  if (!jasmine.isSpy(this.actual)) {
-    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
-  }
-
-  this.message = function() {
-    return [
-      "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
-      "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
-    ];
-  };
-
-  return !this.env.contains_(this.actual.argsForCall, expectedArgs);
-};
-
-/**
- * Matcher that checks that the expected item is an element in the actual Array.
- *
- * @param {Object} expected
- */
-jasmine.Matchers.prototype.toContain = function(expected) {
-  return this.env.contains_(this.actual, expected);
-};
-
-/**
- * Matcher that checks that the expected item is NOT an element in the actual Array.
- *
- * @param {Object} expected
- * @deprecated as of 1.0. Use not.toContain() instead.
- */
-jasmine.Matchers.prototype.toNotContain = function(expected) {
-  return !this.env.contains_(this.actual, expected);
-};
-
-jasmine.Matchers.prototype.toBeLessThan = function(expected) {
-  return this.actual < expected;
-};
-
-jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
-  return this.actual > expected;
-};
-
-/**
- * Matcher that checks that the expected item is equal to the actual item
- * up to a given level of decimal precision (default 2).
- *
- * @param {Number} expected
- * @param {Number} precision
- */
-jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) {
-  if (!(precision === 0)) {
-    precision = precision || 2;
-  }
-  var multiplier = Math.pow(10, precision);
-  var actual = Math.round(this.actual * multiplier);
-  expected = Math.round(expected * multiplier);
-  return expected == actual;
-};
-
-/**
- * Matcher that checks that the expected exception was thrown by the actual.
- *
- * @param {String} expected
- */
-jasmine.Matchers.prototype.toThrow = function(expected) {
-  var result = false;
-  var exception;
-  if (typeof this.actual != 'function') {
-    throw new Error('Actual is not a function');
-  }
-  try {
-    this.actual();
-  } catch (e) {
-    exception = e;
-  }
-  if (exception) {
-    result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
-  }
-
-  var not = this.isNot ? "not " : "";
-
-  this.message = function() {
-    if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
-      return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' ');
-    } else {
-      return "Expected function to throw an exception.";
-    }
-  };
-
-  return result;
-};
-
-jasmine.Matchers.Any = function(expectedClass) {
-  this.expectedClass = expectedClass;
-};
-
-jasmine.Matchers.Any.prototype.jasmineMatches = function(other) {
-  if (this.expectedClass == String) {
-    return typeof other == 'string' || other instanceof String;
-  }
-
-  if (this.expectedClass == Number) {
-    return typeof other == 'number' || other instanceof Number;
-  }
-
-  if (this.expectedClass == Function) {
-    return typeof other == 'function' || other instanceof Function;
-  }
-
-  if (this.expectedClass == Object) {
-    return typeof other == 'object';
-  }
-
-  return other instanceof this.expectedClass;
-};
-
-jasmine.Matchers.Any.prototype.jasmineToString = function() {
-  return '<jasmine.any(' + this.expectedClass + ')>';
-};
-
-jasmine.Matchers.ObjectContaining = function (sample) {
-  this.sample = sample;
-};
-
-jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
-  mismatchKeys = mismatchKeys || [];
-  mismatchValues = mismatchValues || [];
-
-  var env = jasmine.getEnv();
-
-  var hasKey = function(obj, keyName) {
-    return obj != null && obj[keyName] !== jasmine.undefined;
-  };
-
-  for (var property in this.sample) {
-    if (!hasKey(other, property) && hasKey(this.sample, property)) {
-      mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
-    }
-    else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) {
-      mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual.");
-    }
-  }
-
-  return (mismatchKeys.length === 0 && mismatchValues.length === 0);
-};
-
-jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () {
-  return "<jasmine.objectContaining(" + jasmine.pp(this.sample) + ")>";
-};
-// Mock setTimeout, clearTimeout
-// Contributed by Pivotal Computer Systems, www.pivotalsf.com
-
-jasmine.FakeTimer = function() {
-  this.reset();
-
-  var self = this;
-  self.setTimeout = function(funcToCall, millis) {
-    self.timeoutsMade++;
-    self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
-    return self.timeoutsMade;
-  };
-
-  self.setInterval = function(funcToCall, millis) {
-    self.timeoutsMade++;
-    self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
-    return self.timeoutsMade;
-  };
-
-  self.clearTimeout = function(timeoutKey) {
-    self.scheduledFunctions[timeoutKey] = jasmine.undefined;
-  };
-
-  self.clearInterval = function(timeoutKey) {
-    self.scheduledFunctions[timeoutKey] = jasmine.undefined;
-  };
-
-};
-
-jasmine.FakeTimer.prototype.reset = function() {
-  this.timeoutsMade = 0;
-  this.scheduledFunctions = {};
-  this.nowMillis = 0;
-};
-
-jasmine.FakeTimer.prototype.tick = function(millis) {
-  var oldMillis = this.nowMillis;
-  var newMillis = oldMillis + millis;
-  this.runFunctionsWithinRange(oldMillis, newMillis);
-  this.nowMillis = newMillis;
-};
-
-jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
-  var scheduledFunc;
-  var funcsToRun = [];
-  for (var timeoutKey in this.scheduledFunctions) {
-    scheduledFunc = this.scheduledFunctions[timeoutKey];
-    if (scheduledFunc != jasmine.undefined &&
-        scheduledFunc.runAtMillis >= oldMillis &&
-        scheduledFunc.runAtMillis <= nowMillis) {
-      funcsToRun.push(scheduledFunc);
-      this.scheduledFunctions[timeoutKey] = jasmine.undefined;
-    }
-  }
-
-  if (funcsToRun.length > 0) {
-    funcsToRun.sort(function(a, b) {
-      return a.runAtMillis - b.runAtMillis;
-    });
-    for (var i = 0; i < funcsToRun.length; ++i) {
-      try {
-        var funcToRun = funcsToRun[i];
-        this.nowMillis = funcToRun.runAtMillis;
-        funcToRun.funcToCall();
-        if (funcToRun.recurring) {
-          this.scheduleFunction(funcToRun.timeoutKey,
-              funcToRun.funcToCall,
-              funcToRun.millis,
-              true);
-        }
-      } catch(e) {
-      }
-    }
-    this.runFunctionsWithinRange(oldMillis, nowMillis);
-  }
-};
-
-jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
-  this.scheduledFunctions[timeoutKey] = {
-    runAtMillis: this.nowMillis + millis,
-    funcToCall: funcToCall,
-    recurring: recurring,
-    timeoutKey: timeoutKey,
-    millis: millis
-  };
-};
-
-/**
- * @namespace
- */
-jasmine.Clock = {
-  defaultFakeTimer: new jasmine.FakeTimer(),
-
-  reset: function() {
-    jasmine.Clock.assertInstalled();
-    jasmine.Clock.defaultFakeTimer.reset();
-  },
-
-  tick: function(millis) {
-    jasmine.Clock.assertInstalled();
-    jasmine.Clock.defaultFakeTimer.tick(millis);
-  },
-
-  runFunctionsWithinRange: function(oldMillis, nowMillis) {
-    jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
-  },
-
-  scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
-    jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
-  },
-
-  useMock: function() {
-    if (!jasmine.Clock.isInstalled()) {
-      var spec = jasmine.getEnv().currentSpec;
-      spec.after(jasmine.Clock.uninstallMock);
-
-      jasmine.Clock.installMock();
-    }
-  },
-
-  installMock: function() {
-    jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
-  },
-
-  uninstallMock: function() {
-    jasmine.Clock.assertInstalled();
-    jasmine.Clock.installed = jasmine.Clock.real;
-  },
-
-  real: {
-    setTimeout: jasmine.getGlobal().setTimeout,
-    clearTimeout: jasmine.getGlobal().clearTimeout,
-    setInterval: jasmine.getGlobal().setInterval,
-    clearInterval: jasmine.getGlobal().clearInterval
-  },
-
-  assertInstalled: function() {
-    if (!jasmine.Clock.isInstalled()) {
-      throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
-    }
-  },
-
-  isInstalled: function() {
-    return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
-  },
-
-  installed: null
-};
-jasmine.Clock.installed = jasmine.Clock.real;
-
-//else for IE support
-jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
-  if (jasmine.Clock.installed.setTimeout.apply) {
-    return jasmine.Clock.installed.setTimeout.apply(this, arguments);
-  } else {
-    return jasmine.Clock.installed.setTimeout(funcToCall, millis);
-  }
-};
-
-jasmine.getGlobal().setInterval = function(funcToCall, millis) {
-  if (jasmine.Clock.installed.setInterval.apply) {
-    return jasmine.Clock.installed.setInterval.apply(this, arguments);
-  } else {
-    return jasmine.Clock.installed.setInterval(funcToCall, millis);
-  }
-};
-
-jasmine.getGlobal().clearTimeout = function(timeoutKey) {
-  if (jasmine.Clock.installed.clearTimeout.apply) {
-    return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
-  } else {
-    return jasmine.Clock.installed.clearTimeout(timeoutKey);
-  }
-};
-
-jasmine.getGlobal().clearInterval = function(timeoutKey) {
-  if (jasmine.Clock.installed.clearTimeout.apply) {
-    return jasmine.Clock.installed.clearInterval.apply(this, arguments);
-  } else {
-    return jasmine.Clock.installed.clearInterval(timeoutKey);
-  }
-};
-
-/**
- * @constructor
- */
-jasmine.MultiReporter = function() {
-  this.subReporters_ = [];
-};
-jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
-
-jasmine.MultiReporter.prototype.addReporter = function(reporter) {
-  this.subReporters_.push(reporter);
-};
-
-(function() {
-  var functionNames = [
-    "reportRunnerStarting",
-    "reportRunnerResults",
-    "reportSuiteResults",
-    "reportSpecStarting",
-    "reportSpecResults",
-    "log"
-  ];
-  for (var i = 0; i < functionNames.length; i++) {
-    var functionName = functionNames[i];
-    jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
-      return function() {
-        for (var j = 0; j < this.subReporters_.length; j++) {
-          var subReporter = this.subReporters_[j];
-          if (subReporter[functionName]) {
-            subReporter[functionName].apply(subReporter, arguments);
-          }
-        }
-      };
-    })(functionName);
-  }
-})();
-/**
- * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
- *
- * @constructor
- */
-jasmine.NestedResults = function() {
-  /**
-   * The total count of results
-   */
-  this.totalCount = 0;
-  /**
-   * Number of passed results
-   */
-  this.passedCount = 0;
-  /**
-   * Number of failed results
-   */
-  this.failedCount = 0;
-  /**
-   * Was this suite/spec skipped?
-   */
-  this.skipped = false;
-  /**
-   * @ignore
-   */
-  this.items_ = [];
-};
-
-/**
- * Roll up the result counts.
- *
- * @param result
- */
-jasmine.NestedResults.prototype.rollupCounts = function(result) {
-  this.totalCount += result.totalCount;
-  this.passedCount += result.passedCount;
-  this.failedCount += result.failedCount;
-};
-
-/**
- * Adds a log message.
- * @param values Array of message parts which will be concatenated later.
- */
-jasmine.NestedResults.prototype.log = function(values) {
-  this.items_.push(new jasmine.MessageResult(values));
-};
-
-/**
- * Getter for the results: message & results.
- */
-jasmine.NestedResults.prototype.getItems = function() {
-  return this.items_;
-};
-
-/**
- * Adds a result, tracking counts (total, passed, & failed)
- * @param {jasmine.ExpectationResult|jasmine.NestedResults} result
- */
-jasmine.NestedResults.prototype.addResult = function(result) {
-  if (result.type != 'log') {
-    if (result.items_) {
-      this.rollupCounts(result);
-    } else {
-      this.totalCount++;
-      if (result.passed()) {
-        this.passedCount++;
-      } else {
-        this.failedCount++;
-      }
-    }
-  }
-  this.items_.push(result);
-};
-
-/**
- * @returns {Boolean} True if <b>everything</b> below passed
- */
-jasmine.NestedResults.prototype.passed = function() {
-  return this.passedCount === this.totalCount;
-};
-/**
- * Base class for pretty printing for expectation results.
- */
-jasmine.PrettyPrinter = function() {
-  this.ppNestLevel_ = 0;
-};
-
-/**
- * Formats a value in a nice, human-readable string.
- *
- * @param value
- */
-jasmine.PrettyPrinter.prototype.format = function(value) {
-  if (this.ppNestLevel_ > 40) {
-    throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
-  }
-
-  this.ppNestLevel_++;
-  try {
-    if (value === jasmine.undefined) {
-      this.emitScalar('undefined');
-    } else if (value === null) {
-      this.emitScalar('null');
-    } else if (value === jasmine.getGlobal()) {
-      this.emitScalar('<global>');
-    } else if (value.jasmineToString) {
-      this.emitScalar(value.jasmineToString());
-    } else if (typeof value === 'string') {
-      this.emitString(value);
-    } else if (jasmine.isSpy(value)) {
-      this.emitScalar("spy on " + value.identity);
-    } else if (value instanceof RegExp) {
-      this.emitScalar(value.toString());
-    } else if (typeof value === 'function') {
-      this.emitScalar('Function');
-    } else if (typeof value.nodeType === 'number') {
-      this.emitScalar('HTMLNode');
-    } else if (value instanceof Date) {
-      this.emitScalar('Date(' + value + ')');
-    } else if (value.__Jasmine_been_here_before__) {
-      this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
-    } else if (jasmine.isArray_(value) || typeof value == 'object') {
-      value.__Jasmine_been_here_before__ = true;
-      if (jasmine.isArray_(value)) {
-        this.emitArray(value);
-      } else {
-        this.emitObject(value);
-      }
-      delete value.__Jasmine_been_here_before__;
-    } else {
-      this.emitScalar(value.toString());
-    }
-  } finally {
-    this.ppNestLevel_--;
-  }
-};
-
-jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
-  for (var property in obj) {
-    if (property == '__Jasmine_been_here_before__') continue;
-    fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && 
-                                         obj.__lookupGetter__(property) !== null) : false);
-  }
-};
-
-jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
-jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
-jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
-jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
-
-jasmine.StringPrettyPrinter = function() {
-  jasmine.PrettyPrinter.call(this);
-
-  this.string = '';
-};
-jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
-
-jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
-  this.append(value);
-};
-
-jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
-  this.append("'" + value + "'");
-};
-
-jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
-  this.append('[ ');
-  for (var i = 0; i < array.length; i++) {
-    if (i > 0) {
-      this.append(', ');
-    }
-    this.format(array[i]);
-  }
-  this.append(' ]');
-};
-
-jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
-  var self = this;
-  this.append('{ ');
-  var first = true;
-
-  this.iterateObject(obj, function(property, isGetter) {
-    if (first) {
-      first = false;
-    } else {
-      self.append(', ');
-    }
-
-    self.append(property);
-    self.append(' : ');
-    if (isGetter) {
-      self.append('<getter>');
-    } else {
-      self.format(obj[property]);
-    }
-  });
-
-  this.append(' }');
-};
-
-jasmine.StringPrettyPrinter.prototype.append = function(value) {
-  this.string += value;
-};
-jasmine.Queue = function(env) {
-  this.env = env;
-  this.blocks = [];
-  this.running = false;
-  this.index = 0;
-  this.offset = 0;
-  this.abort = false;
-};
-
-jasmine.Queue.prototype.addBefore = function(block) {
-  this.blocks.unshift(block);
-};
-
-jasmine.Queue.prototype.add = function(block) {
-  this.blocks.push(block);
-};
-
-jasmine.Queue.prototype.insertNext = function(block) {
-  this.blocks.splice((this.index + this.offset + 1), 0, block);
-  this.offset++;
-};
-
-jasmine.Queue.prototype.start = function(onComplete) {
-  this.running = true;
-  this.onComplete = onComplete;
-  this.next_();
-};
-
-jasmine.Queue.prototype.isRunning = function() {
-  return this.running;
-};
-
-jasmine.Queue.LOOP_DONT_RECURSE = true;
-
-jasmine.Queue.prototype.next_ = function() {
-  var self = this;
-  var goAgain = true;
-
-  while (goAgain) {
-    goAgain = false;
-    
-    if (self.index < self.blocks.length && !this.abort) {
-      var calledSynchronously = true;
-      var completedSynchronously = false;
-
-      var onComplete = function () {
-        if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
-          completedSynchronously = true;
-          return;
-        }
-
-        if (self.blocks[self.index].abort) {
-          self.abort = true;
-        }
-
-        self.offset = 0;
-        self.index++;
-
-        var now = new Date().getTime();
-        if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
-          self.env.lastUpdate = now;
-          self.env.setTimeout(function() {
-            self.next_();
-          }, 0);
-        } else {
-          if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
-            goAgain = true;
-          } else {
-            self.next_();
-          }
-        }
-      };
-      self.blocks[self.index].execute(onComplete);
-
-      calledSynchronously = false;
-      if (completedSynchronously) {
-        onComplete();
-      }
-      
-    } else {
-      self.running = false;
-      if (self.onComplete) {
-        self.onComplete();
-      }
-    }
-  }
-};
-
-jasmine.Queue.prototype.results = function() {
-  var results = new jasmine.NestedResults();
-  for (var i = 0; i < this.blocks.length; i++) {
-    if (this.blocks[i].results) {
-      results.addResult(this.blocks[i].results());
-    }
-  }
-  return results;
-};
-
-
-/**
- * Runner
- *
- * @constructor
- * @param {jasmine.Env} env
- */
-jasmine.Runner = function(env) {
-  var self = this;
-  self.env = env;
-  self.queue = new jasmine.Queue(env);
-  self.before_ = [];
-  self.after_ = [];
-  self.suites_ = [];
-};
-
-jasmine.Runner.prototype.execute = function() {
-  var self = this;
-  if (self.env.reporter.reportRunnerStarting) {
-    self.env.reporter.reportRunnerStarting(this);
-  }
-  self.queue.start(function () {
-    self.finishCallback();
-  });
-};
-
-jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
-  beforeEachFunction.typeName = 'beforeEach';
-  this.before_.splice(0,0,beforeEachFunction);
-};
-
-jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
-  afterEachFunction.typeName = 'afterEach';
-  this.after_.splice(0,0,afterEachFunction);
-};
-
-
-jasmine.Runner.prototype.finishCallback = function() {
-  this.env.reporter.reportRunnerResults(this);
-};
-
-jasmine.Runner.prototype.addSuite = function(suite) {
-  this.suites_.push(suite);
-};
-
-jasmine.Runner.prototype.add = function(block) {
-  if (block instanceof jasmine.Suite) {
-    this.addSuite(block);
-  }
-  this.queue.add(block);
-};
-
-jasmine.Runner.prototype.specs = function () {
-  var suites = this.suites();
-  var specs = [];
-  for (var i = 0; i < suites.length; i++) {
-    specs = specs.concat(suites[i].specs());
-  }
-  return specs;
-};
-
-jasmine.Runner.prototype.suites = function() {
-  return this.suites_;
-};
-
-jasmine.Runner.prototype.topLevelSuites = function() {
-  var topLevelSuites = [];
-  for (var i = 0; i < this.suites_.length; i++) {
-    if (!this.suites_[i].parentSuite) {
-      topLevelSuites.push(this.suites_[i]);
-    }
-  }
-  return topLevelSuites;
-};
-
-jasmine.Runner.prototype.results = function() {
-  return this.queue.results();
-};
-/**
- * Internal representation of a Jasmine specification, or test.
- *
- * @constructor
- * @param {jasmine.Env} env
- * @param {jasmine.Suite} suite
- * @param {String} description
- */
-jasmine.Spec = function(env, suite, description) {
-  if (!env) {
-    throw new Error('jasmine.Env() required');
-  }
-  if (!suite) {
-    throw new Error('jasmine.Suite() required');
-  }
-  var spec = this;
-  spec.id = env.nextSpecId ? env.nextSpecId() : null;
-  spec.env = env;
-  spec.suite = suite;
-  spec.description = description;
-  spec.queue = new jasmine.Queue(env);
-
-  spec.afterCallbacks = [];
-  spec.spies_ = [];
-
-  spec.results_ = new jasmine.NestedResults();
-  spec.results_.description = description;
-  spec.matchersClass = null;
-};
-
-jasmine.Spec.prototype.getFullName = function() {
-  return this.suite.getFullName() + ' ' + this.description + '.';
-};
-
-
-jasmine.Spec.prototype.results = function() {
-  return this.results_;
-};
-
-/**
- * All parameters are pretty-printed and concatenated together, then written to the spec's output.
- *
- * Be careful not to leave calls to <code>jasmine.log</code> in production code.
- */
-jasmine.Spec.prototype.log = function() {
-  return this.results_.log(arguments);
-};
-
-jasmine.Spec.prototype.runs = function (func) {
-  var block = new jasmine.Block(this.env, func, this);
-  this.addToQueue(block);
-  return this;
-};
-
-jasmine.Spec.prototype.addToQueue = function (block) {
-  if (this.queue.isRunning()) {
-    this.queue.insertNext(block);
-  } else {
-    this.queue.add(block);
-  }
-};
-
-/**
- * @param {jasmine.ExpectationResult} result
- */
-jasmine.Spec.prototype.addMatcherResult = function(result) {
-  this.results_.addResult(result);
-};
-
-jasmine.Spec.prototype.expect = function(actual) {
-  var positive = new (this.getMatchersClass_())(this.env, actual, this);
-  positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
-  return positive;
-};
-
-/**
- * Waits a fixed time period before moving to the next block.
- *
- * @deprecated Use waitsFor() instead
- * @param {Number} timeout milliseconds to wait
- */
-jasmine.Spec.prototype.waits = function(timeout) {
-  var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
-  this.addToQueue(waitsFunc);
-  return this;
-};
-
-/**
- * Waits for the latchFunction to return true before proceeding to the next block.
- *
- * @param {Function} latchFunction
- * @param {String} optional_timeoutMessage
- * @param {Number} optional_timeout
- */
-jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
-  var latchFunction_ = null;
-  var optional_timeoutMessage_ = null;
-  var optional_timeout_ = null;
-
-  for (var i = 0; i < arguments.length; i++) {
-    var arg = arguments[i];
-    switch (typeof arg) {
-      case 'function':
-        latchFunction_ = arg;
-        break;
-      case 'string':
-        optional_timeoutMessage_ = arg;
-        break;
-      case 'number':
-        optional_timeout_ = arg;
-        break;
-    }
-  }
-
-  var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
-  this.addToQueue(waitsForFunc);
-  return this;
-};
-
-jasmine.Spec.prototype.fail = function (e) {
-  var expectationResult = new jasmine.ExpectationResult({
-    passed: false,
-    message: e ? jasmine.util.formatException(e) : 'Exception',
-    trace: { stack: e.stack }
-  });
-  this.results_.addResult(expectationResult);
-};
-
-jasmine.Spec.prototype.getMatchersClass_ = function() {
-  return this.matchersClass || this.env.matchersClass;
-};
-
-jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
-  var parent = this.getMatchersClass_();
-  var newMatchersClass = function() {
-    parent.apply(this, arguments);
-  };
-  jasmine.util.inherit(newMatchersClass, parent);
-  jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
-  this.matchersClass = newMatchersClass;
-};
-
-jasmine.Spec.prototype.finishCallback = function() {
-  this.env.reporter.reportSpecResults(this);
-};
-
-jasmine.Spec.prototype.finish = function(onComplete) {
-  this.removeAllSpies();
-  this.finishCallback();
-  if (onComplete) {
-    onComplete();
-  }
-};
-
-jasmine.Spec.prototype.after = function(doAfter) {
-  if (this.queue.isRunning()) {
-    this.queue.add(new jasmine.Block(this.env, doAfter, this));
-  } else {
-    this.afterCallbacks.unshift(doAfter);
-  }
-};
-
-jasmine.Spec.prototype.execute = function(onComplete) {
-  var spec = this;
-  if (!spec.env.specFilter(spec)) {
-    spec.results_.skipped = true;
-    spec.finish(onComplete);
-    return;
-  }
-
-  this.env.reporter.reportSpecStarting(this);
-
-  spec.env.currentSpec = spec;
-
-  spec.addBeforesAndAftersToQueue();
-
-  spec.queue.start(function () {
-    spec.finish(onComplete);
-  });
-};
-
-jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
-  var runner = this.env.currentRunner();
-  var i;
-
-  for (var suite = this.suite; suite; suite = suite.parentSuite) {
-    for (i = 0; i < suite.before_.length; i++) {
-      this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
-    }
-  }
-  for (i = 0; i < runner.before_.length; i++) {
-    this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
-  }
-  for (i = 0; i < this.afterCallbacks.length; i++) {
-    this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
-  }
-  for (suite = this.suite; suite; suite = suite.parentSuite) {
-    for (i = 0; i < suite.after_.length; i++) {
-      this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
-    }
-  }
-  for (i = 0; i < runner.after_.length; i++) {
-    this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
-  }
-};
-
-jasmine.Spec.prototype.explodes = function() {
-  throw 'explodes function should not have been called';
-};
-
-jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
-  if (obj == jasmine.undefined) {
-    throw "spyOn could not find an object to spy upon for " + methodName + "()";
-  }
-
-  if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
-    throw methodName + '() method does not exist';
-  }
-
-  if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
-    throw new Error(methodName + ' has already been spied upon');
-  }
-
-  var spyObj = jasmine.createSpy(methodName);
-
-  this.spies_.push(spyObj);
-  spyObj.baseObj = obj;
-  spyObj.methodName = methodName;
-  spyObj.originalValue = obj[methodName];
-
-  obj[methodName] = spyObj;
-
-  return spyObj;
-};
-
-jasmine.Spec.prototype.removeAllSpies = function() {
-  for (var i = 0; i < this.spies_.length; i++) {
-    var spy = this.spies_[i];
-    spy.baseObj[spy.methodName] = spy.originalValue;
-  }
-  this.spies_ = [];
-};
-
-/**
- * Internal representation of a Jasmine suite.
- *
- * @constructor
- * @param {jasmine.Env} env
- * @param {String} description
- * @param {Function} specDefinitions
- * @param {jasmine.Suite} parentSuite
- */
-jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
-  var self = this;
-  self.id = env.nextSuiteId ? env.nextSuiteId() : null;
-  self.description = description;
-  self.queue = new jasmine.Queue(env);
-  self.parentSuite = parentSuite;
-  self.env = env;
-  self.before_ = [];
-  self.after_ = [];
-  self.children_ = [];
-  self.suites_ = [];
-  self.specs_ = [];
-};
-
-jasmine.Suite.prototype.getFullName = function() {
-  var fullName = this.description;
-  for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
-    fullName = parentSuite.description + ' ' + fullName;
-  }
-  return fullName;
-};
-
-jasmine.Suite.prototype.finish = function(onComplete) {
-  this.env.reporter.reportSuiteResults(this);
-  this.finished = true;
-  if (typeof(onComplete) == 'function') {
-    onComplete();
-  }
-};
-
-jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
-  beforeEachFunction.typeName = 'beforeEach';
-  this.before_.unshift(beforeEachFunction);
-};
-
-jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
-  afterEachFunction.typeName = 'afterEach';
-  this.after_.unshift(afterEachFunction);
-};
-
-jasmine.Suite.prototype.results = function() {
-  return this.queue.results();
-};
-
-jasmine.Suite.prototype.add = function(suiteOrSpec) {
-  this.children_.push(suiteOrSpec);
-  if (suiteOrSpec instanceof jasmine.Suite) {
-    this.suites_.push(suiteOrSpec);
-    this.env.currentRunner().addSuite(suiteOrSpec);
-  } else {
-    this.specs_.push(suiteOrSpec);
-  }
-  this.queue.add(suiteOrSpec);
-};
-
-jasmine.Suite.prototype.specs = function() {
-  return this.specs_;
-};
-
-jasmine.Suite.prototype.suites = function() {
-  return this.suites_;
-};
-
-jasmine.Suite.prototype.children = function() {
-  return this.children_;
-};
-
-jasmine.Suite.prototype.execute = function(onComplete) {
-  var self = this;
-  this.queue.start(function () {
-    self.finish(onComplete);
-  });
-};
-jasmine.WaitsBlock = function(env, timeout, spec) {
-  this.timeout = timeout;
-  jasmine.Block.call(this, env, null, spec);
-};
-
-jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
-
-jasmine.WaitsBlock.prototype.execute = function (onComplete) {
-  if (jasmine.VERBOSE) {
-    this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
-  }
-  this.env.setTimeout(function () {
-    onComplete();
-  }, this.timeout);
-};
-/**
- * A block which waits for some condition to become true, with timeout.
- *
- * @constructor
- * @extends jasmine.Block
- * @param {jasmine.Env} env The Jasmine environment.
- * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.
- * @param {Function} latchFunction A function which returns true when the desired condition has been met.
- * @param {String} message The message to display if the desired condition hasn't been met within the given time period.
- * @param {jasmine.Spec} spec The Jasmine spec.
- */
-jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
-  this.timeout = timeout || env.defaultTimeoutInterval;
-  this.latchFunction = latchFunction;
-  this.message = message;
-  this.totalTimeSpentWaitingForLatch = 0;
-  jasmine.Block.call(this, env, null, spec);
-};
-jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
-
-jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
-
-jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
-  if (jasmine.VERBOSE) {
-    this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
-  }
-  var latchFunctionResult;
-  try {
-    latchFunctionResult = this.latchFunction.apply(this.spec);
-  } catch (e) {
-    this.spec.fail(e);
-    onComplete();
-    return;
-  }
-
-  if (latchFunctionResult) {
-    onComplete();
-  } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
-    var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
-    this.spec.fail({
-      name: 'timeout',
-      message: message
-    });
-
-    this.abort = true;
-    onComplete();
-  } else {
-    this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
-    var self = this;
-    this.env.setTimeout(function() {
-      self.execute(onComplete);
-    }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
-  }
-};
-
-jasmine.version_= {
-  "major": 1,
-  "minor": 2,
-  "build": 0,
-  "revision": 1337005947
-};
index eb515b7..ace7b01 100644 (file)
@@ -24,8 +24,8 @@ var update = require('./lib/update');
 if (['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) > -1) {
     update.help();
 } else {
-    update.run(process.argv).done(function () {
-        console.log('Successfully updated browser project.');
+    update.run(process.argv).then(function () {
+        console.log('Successfully updated electron project.'); // won't happen .. it's not supported
     }, function (err) {
         console.error('Update failed due to', err);
         process.exit(2);
index 8a45c1c..b834179 100644 (file)
@@ -61,17 +61,12 @@ function readConfig(success, error) {
         }
     };
 
-    if ("ActiveXObject" in window) {
-        // Needed for XHR-ing via file:// protocol in IE
-        xhr = new window.ActiveXObject("MSXML2.XMLHTTP");
-        xhr.onreadystatechange = xhrStatusChangeHandler;
-    } else {
-        xhr = new XMLHttpRequest();
-        xhr.addEventListener("load", xhrStatusChangeHandler);
-    }
+    xhr = new XMLHttpRequest();
+    xhr.addEventListener("load", xhrStatusChangeHandler);
+
 
     try {
-        xhr.open("get", "config.xml", true);
+        xhr.open("get", "/config.xml", true);
         xhr.send();
     } catch(e) {
         fail('[Electron][cordova.js][readConfig] Could not XHR config.xml: ' + JSON.stringify(e));
index 744282e..97f736a 100644 (file)
  *
 */
 
+/*jslint sloppy:true, plusplus:true*/
+/*global require, module, console */
+
 var cordova = require('cordova');
 var execProxy = require('cordova/exec/proxy');
 
-module.exports = function(success, fail, service, action, args) {
+/**
+ * Execute a cordova command.  It is up to the native side whether this action
+ * is synchronous or asynchronous.  The native side can return:
+ *      Synchronous: PluginResult object as a JSON string
+ *      Asynchronous: Empty string ""
+ * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
+ * depending upon the result of the action.
+ *
+ * @param {Function} success    The success callback
+ * @param {Function} fail       The fail callback
+ * @param {String} service      The name of the service to use
+ * @param {String} action       Action to be run in cordova
+ * @param {String[]} [args]     Zero or more arguments to pass to the method
+ */
+module.exports = function (success, fail, service, action, args) {
 
     var proxy = execProxy.get(service, action);
 
+    args = args || [];
+
     if (proxy) {
+        
         var callbackId = service + cordova.callbackId++;
-
-        if (typeof success == "function" || typeof fail == "function") {
-            cordova.callbacks[callbackId] = {success:success, fail:fail};
+        
+        if (typeof success === "function" || typeof fail === "function") {
+            cordova.callbacks[callbackId] = {success: success, fail: fail};
         }
-
         try {
-            proxy(success, fail, args);
+
+            
+
+            // callbackOptions param represents additional optional parameters command could pass back, like keepCallback or
+            // custom callbackId, for example {callbackId: id, keepCallback: true, status: cordova.callbackStatus.JSON_EXCEPTION }
+            var onSuccess = function (result, callbackOptions) {
+                callbackOptions = callbackOptions || {};
+                var callbackStatus;
+                // covering both undefined and null.
+                // strict null comparison was causing callbackStatus to be undefined
+                // and then no callback was called because of the check in cordova.callbackFromNative
+                // see CB-8996 Mobilespec app hang on windows
+                if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+                    callbackStatus = callbackOptions.status;
+                }
+                else {
+                    callbackStatus = cordova.callbackStatus.OK;
+                }
+                cordova.callbackSuccess(callbackOptions.callbackId || callbackId,
+                    {
+                        status: callbackStatus,
+                        message: result,
+                        keepCallback: callbackOptions.keepCallback || false
+                    });
+            };
+            var onError = function (err, callbackOptions) {
+                callbackOptions = callbackOptions || {};
+                var callbackStatus;
+                // covering both undefined and null.
+                // strict null comparison was causing callbackStatus to be undefined
+                // and then no callback was called because of the check in cordova.callbackFromNative
+                // note: status can be 0
+                if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+                    callbackStatus = callbackOptions.status;
+                }
+                else {
+                    callbackStatus = cordova.callbackStatus.OK;
+                }
+                cordova.callbackError(callbackOptions.callbackId || callbackId,
+                {
+                    status: callbackStatus,
+                    message: err,
+                    keepCallback: callbackOptions.keepCallback || false
+                });
+            };
+            proxy(onSuccess, onError, args);
+
+        } catch (e) {
+            console.log("Exception calling native with command :: " + service + " :: " + action  + " ::exception=" + e);
         }
-        catch(e) {
-            // TODO throw maybe?
-            var msg = "Exception calling :: " + service + " :: " + action  + " ::exception=" + e;
-            console.log(msg);
+    } else {
+
+        console.log("Error: exec proxy not found for :: " + service + " :: " + action);
+        
+        if(typeof fail === "function" ) {
+            fail("Missing Command Error");
         }
     }
-    else {
-        fail && fail("Missing Command Error");
-    }
 };
index 9e6fd42..421701a 100644 (file)
@@ -21,6 +21,7 @@
 
 module.exports = {
     id: 'electron',
+    cordovaVersion: '4.2.0', // cordova-js
 
     bootstrap: function() {
 
@@ -31,6 +32,15 @@ module.exports = {
 
         channel.onNativeReady.fire();
 
+        document.addEventListener("visibilitychange", function(){
+            if(document.hidden) {
+                channel.onPause.fire();
+            }
+            else {
+                channel.onResume.fire();
+            }
+        });
+
     // End of bootstrap
     }
 };
index 3783bc1..73971e8 100644 (file)
@@ -1,5 +1,5 @@
 // Platform: electron
-// 1dc70ecab3f3f41df32b53e4d47765bc55606c04
+// ff66178b108b93be36a1aafe341af17381a727a3
 /*
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
@@ -8,9 +8,9 @@
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at
+
      http://www.apache.org/licenses/LICENSE-2.0
+
  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  under the License.
 */
 ;(function() {
-var PLATFORM_VERSION_BUILD_LABEL = 'N/A';
+var PLATFORM_VERSION_BUILD_LABEL = '5.1.0-dev';
 // file: src/scripts/require.js
 
-/*jshint -W079 */
-/*jshint -W020 */
+/* jshint -W079 */
+/* jshint -W020 */
 
-var require,
-    define;
+var require;
+var define;
 
 (function () {
-    var modules = {},
+    var modules = {};
     // Stack of moduleIds currently being built.
-        requireStack = [],
+    var requireStack = [];
     // Map of module ID -> index into requireStack of modules currently being built.
-        inProgressModules = {},
-        SEPARATOR = ".";
-
-
-
-    function build(module) {
-        var factory = module.factory,
-            localRequire = function (id) {
-                var resultantId = id;
-                //Its a relative path, so lop off the last portion and add the id (minus "./")
-                if (id.charAt(0) === ".") {
-                    resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
-                }
-                return require(resultantId);
-            };
+    var inProgressModules = {};
+    var SEPARATOR = '.';
+
+    function build (module) {
+        var factory = module.factory;
+        var localRequire = function (id) {
+            var resultantId = id;
+            // Its a relative path, so lop off the last portion and add the id (minus "./")
+            if (id.charAt(0) === '.') {
+                resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
+            }
+            return require(resultantId);
+        };
         module.exports = {};
         delete module.factory;
         factory(localRequire, module.exports, module);
@@ -56,10 +54,10 @@ var require,
 
     require = function (id) {
         if (!modules[id]) {
-            throw "module " + id + " not found";
+            throw 'module ' + id + ' not found';
         } else if (id in inProgressModules) {
             var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
-            throw "Cycle in require graph: " + cycle;
+            throw 'Cycle in require graph: ' + cycle;
         }
         if (modules[id].factory) {
             try {
@@ -76,7 +74,7 @@ var require,
 
     define = function (id, factory) {
         if (modules[id]) {
-            throw "module " + id + " already defined";
+            throw 'module ' + id + ' already defined';
         }
 
         modules[id] = {
@@ -92,8 +90,8 @@ var require,
     define.moduleMap = modules;
 })();
 
-//Export for use in node
-if (typeof module === "object" && typeof require === "function") {
+// Export for use in node
+if (typeof module === 'object' && typeof require === 'function') {
     module.exports.require = require;
     module.exports.define = define;
 }
@@ -101,15 +99,15 @@ if (typeof module === "object" && typeof require === "function") {
 // file: src/cordova.js
 define("cordova", function(require, exports, module) {
 
-if(window.cordova){
-    throw new Error("cordova already defined");
+// Workaround for Windows 10 in hosted environment case
+// http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
+if (window.cordova && !(window.cordova instanceof HTMLElement)) { // eslint-disable-line no-undef
+    throw new Error('cordova already defined');
 }
 
-
 var channel = require('cordova/channel');
 var platform = require('cordova/platform');
 
-
 /**
  * Intercept calls to addEventListener + removeEventListener and handle deviceready,
  * resume, and pause events.
@@ -122,48 +120,48 @@ var m_window_removeEventListener = window.removeEventListener;
 /**
  * Houses custom event handlers to intercept on document + window event listeners.
  */
-var documentEventHandlers = {},
-    windowEventHandlers = {};
+var documentEventHandlers = {};
+var windowEventHandlers = {};
 
-document.addEventListener = function(evt, handler, capture) {
+document.addEventListener = function (evt, handler, capture) {
     var e = evt.toLowerCase();
-    if (typeof documentEventHandlers[e] != 'undefined') {
+    if (typeof documentEventHandlers[e] !== 'undefined') {
         documentEventHandlers[e].subscribe(handler);
     } else {
         m_document_addEventListener.call(document, evt, handler, capture);
     }
 };
 
-window.addEventListener = function(evt, handler, capture) {
+window.addEventListener = function (evt, handler, capture) {
     var e = evt.toLowerCase();
-    if (typeof windowEventHandlers[e] != 'undefined') {
+    if (typeof windowEventHandlers[e] !== 'undefined') {
         windowEventHandlers[e].subscribe(handler);
     } else {
         m_window_addEventListener.call(window, evt, handler, capture);
     }
 };
 
-document.removeEventListener = function(evt, handler, capture) {
+document.removeEventListener = function (evt, handler, capture) {
     var e = evt.toLowerCase();
     // If unsubscribing from an event that is handled by a plugin
-    if (typeof documentEventHandlers[e] != "undefined") {
+    if (typeof documentEventHandlers[e] !== 'undefined') {
         documentEventHandlers[e].unsubscribe(handler);
     } else {
         m_document_removeEventListener.call(document, evt, handler, capture);
     }
 };
 
-window.removeEventListener = function(evt, handler, capture) {
+window.removeEventListener = function (evt, handler, capture) {
     var e = evt.toLowerCase();
     // If unsubscribing from an event that is handled by a plugin
-    if (typeof windowEventHandlers[e] != "undefined") {
+    if (typeof windowEventHandlers[e] !== 'undefined') {
         windowEventHandlers[e].unsubscribe(handler);
     } else {
         m_window_removeEventListener.call(window, evt, handler, capture);
     }
 };
 
-function createEvent(type, data) {
+function createEvent (type, data) {
     var event = document.createEvent('Events');
     event.initEvent(type, false, false);
     if (data) {
@@ -176,29 +174,32 @@ function createEvent(type, data) {
     return event;
 }
 
-
+/* eslint-disable no-undef */
 var cordova = {
-    define:define,
-    require:require,
-    version:PLATFORM_VERSION_BUILD_LABEL,
-    platformVersion:PLATFORM_VERSION_BUILD_LABEL,
-    platformId:platform.id,
+    define: define,
+    require: require,
+    version: PLATFORM_VERSION_BUILD_LABEL,
+    platformVersion: PLATFORM_VERSION_BUILD_LABEL,
+    platformId: platform.id,
+
+    /* eslint-enable no-undef */
+
     /**
      * Methods to add/remove your own addEventListener hijacking on document + window.
      */
-    addWindowEventHandler:function(event) {
+    addWindowEventHandler: function (event) {
         return (windowEventHandlers[event] = channel.create(event));
     },
-    addStickyDocumentEventHandler:function(event) {
+    addStickyDocumentEventHandler: function (event) {
         return (documentEventHandlers[event] = channel.createSticky(event));
     },
-    addDocumentEventHandler:function(event) {
+    addDocumentEventHandler: function (event) {
         return (documentEventHandlers[event] = channel.create(event));
     },
-    removeWindowEventHandler:function(event) {
+    removeWindowEventHandler: function (event) {
         delete windowEventHandlers[event];
     },
-    removeDocumentEventHandler:function(event) {
+    removeDocumentEventHandler: function (event) {
         delete documentEventHandlers[event];
     },
     /**
@@ -206,24 +207,23 @@ var cordova = {
      *
      * @return object
      */
-    getOriginalHandlers: function() {
+    getOriginalHandlers: function () {
         return {'document': {'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener},
-        'window': {'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener}};
+            'window': {'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener}};
     },
     /**
      * Method to fire event from native code
      * bNoDetach is required for events which cause an exception which needs to be caught in native code
      */
-    fireDocumentEvent: function(type, data, bNoDetach) {
+    fireDocumentEvent: function (type, data, bNoDetach) {
         var evt = createEvent(type, data);
-        if (typeof documentEventHandlers[type] != 'undefined') {
-            if( bNoDetach ) {
+        if (typeof documentEventHandlers[type] !== 'undefined') {
+            if (bNoDetach) {
                 documentEventHandlers[type].fire(evt);
-            }
-            else {
-                setTimeout(function() {
+            } else {
+                setTimeout(function () {
                     // Fire deviceready on listeners that were registered before cordova.js was loaded.
-                    if (type == 'deviceready') {
+                    if (type === 'deviceready') {
                         document.dispatchEvent(evt);
                     }
                     documentEventHandlers[type].fire(evt);
@@ -233,10 +233,10 @@ var cordova = {
             document.dispatchEvent(evt);
         }
     },
-    fireWindowEvent: function(type, data) {
-        var evt = createEvent(type,data);
-        if (typeof windowEventHandlers[type] != 'undefined') {
-            setTimeout(function() {
+    fireWindowEvent: function (type, data) {
+        var evt = createEvent(type, data);
+        if (typeof windowEventHandlers[type] !== 'undefined') {
+            setTimeout(function () {
                 windowEventHandlers[type].fire(evt);
             }, 0);
         } else {
@@ -250,7 +250,7 @@ var cordova = {
     // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
     // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
     callbackId: Math.floor(Math.random() * 2000000000),
-    callbacks:  {},
+    callbacks: {},
     callbackStatus: {
         NO_RESULT: 0,
         OK: 1,
@@ -267,14 +267,14 @@ var cordova = {
     /**
      * Called by native code when returning successful result from an action.
      */
-    callbackSuccess: function(callbackId, args) {
+    callbackSuccess: function (callbackId, args) {
         cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
     },
 
     /**
      * Called by native code when returning error result from an action.
      */
-    callbackError: function(callbackId, args) {
+    callbackError: function (callbackId, args) {
         // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
         // Derive success from status.
         cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
@@ -283,11 +283,11 @@ var cordova = {
     /**
      * Called by native code when returning the result from an action.
      */
-    callbackFromNative: function(callbackId, isSuccess, status, args, keepCallback) {
+    callbackFromNative: function (callbackId, isSuccess, status, args, keepCallback) {
         try {
             var callback = cordova.callbacks[callbackId];
             if (callback) {
-                if (isSuccess && status == cordova.callbackStatus.OK) {
+                if (isSuccess && status === cordova.callbackStatus.OK) {
                     callback.success && callback.success.apply(null, args);
                 } else if (!isSuccess) {
                     callback.fail && callback.fail.apply(null, args);
@@ -304,26 +304,24 @@ var cordova = {
                     delete cordova.callbacks[callbackId];
                 }
             }
-        }
-        catch (err) {
-            var msg = "Error in " + (isSuccess ? "Success" : "Error") + " callbackId: " + callbackId + " : " + err;
+        } catch (err) {
+            var msg = 'Error in ' + (isSuccess ? 'Success' : 'Error') + ' callbackId: ' + callbackId + ' : ' + err;
             console && console.log && console.log(msg);
-            cordova.fireWindowEvent("cordovacallbackerror", { 'message': msg });
+            cordova.fireWindowEvent('cordovacallbackerror', { 'message': msg });
             throw err;
         }
     },
-    addConstructor: function(func) {
-        channel.onCordovaReady.subscribe(function() {
+    addConstructor: function (func) {
+        channel.onCordovaReady.subscribe(function () {
             try {
                 func();
-            } catch(e) {
-                console.log("Failed to run constructor: " + e);
+            } catch (e) {
+                console.log('Failed to run constructor: ' + e);
             }
         });
     }
 };
 
-
 module.exports = cordova;
 
 });
@@ -331,7 +329,6 @@ module.exports = cordova;
 // file: src/common/argscheck.js
 define("cordova/argscheck", function(require, exports, module) {
 
-var exec = require('cordova/exec');
 var utils = require('cordova/utils');
 
 var moduleExports = module.exports;
@@ -345,29 +342,29 @@ var typeMap = {
     'O': 'Object'
 };
 
-function extractParamName(callee, argIndex) {
+function extractParamName (callee, argIndex) {
     return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
 }
 
-function checkArgs(spec, functionName, args, opt_callee) {
+function checkArgs (spec, functionName, args, opt_callee) {
     if (!moduleExports.enableChecks) {
         return;
     }
     var errMsg = null;
     var typeName;
     for (var i = 0; i < spec.length; ++i) {
-        var c = spec.charAt(i),
-            cUpper = c.toUpperCase(),
-            arg = args[i];
+        var c = spec.charAt(i);
+        var cUpper = c.toUpperCase();
+        var arg = args[i];
         // Asterix means allow anything.
-        if (c == '*') {
+        if (c === '*') {
             continue;
         }
         typeName = utils.typeName(arg);
-        if ((arg === null || arg === undefined) && c == cUpper) {
+        if ((arg === null || arg === undefined) && c === cUpper) {
             continue;
         }
-        if (typeName != typeMap[cUpper]) {
+        if (typeName !== typeMap[cUpper]) {
             errMsg = 'Expected ' + typeMap[cUpper];
             break;
         }
@@ -376,14 +373,14 @@ function checkArgs(spec, functionName, args, opt_callee) {
         errMsg += ', but got ' + typeName + '.';
         errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
         // Don't log when running unit tests.
-        if (typeof jasmine == 'undefined') {
+        if (typeof jasmine === 'undefined') {
             console.error(errMsg);
         }
         throw TypeError(errMsg);
     }
 }
 
-function getValue(value, defaultValue) {
+function getValue (value, defaultValue) {
     return value === undefined ? defaultValue : value;
 }
 
@@ -391,7 +388,6 @@ moduleExports.checkArgs = checkArgs;
 moduleExports.getValue = getValue;
 moduleExports.enableChecks = true;
 
-
 });
 
 // file: src/common/base64.js
@@ -399,58 +395,58 @@ define("cordova/base64", function(require, exports, module) {
 
 var base64 = exports;
 
-base64.fromArrayBuffer = function(arrayBuffer) {
+base64.fromArrayBuffer = function (arrayBuffer) {
     var array = new Uint8Array(arrayBuffer);
     return uint8ToBase64(array);
 };
 
-base64.toArrayBuffer = function(str) {
-    var decodedStr = typeof atob != 'undefined' ? atob(str) : new Buffer(str,'base64').toString('binary');
+base64.toArrayBuffer = function (str) {
+    var decodedStr = typeof atob !== 'undefined' ? atob(str) : Buffer.from(str, 'base64').toString('binary'); // eslint-disable-line no-undef
     var arrayBuffer = new ArrayBuffer(decodedStr.length);
     var array = new Uint8Array(arrayBuffer);
-    for (var i=0, len=decodedStr.length; i < len; i++) {
+    for (var i = 0, len = decodedStr.length; i < len; i++) {
         array[i] = decodedStr.charCodeAt(i);
     }
     return arrayBuffer;
 };
 
-//------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
 
 /* This code is based on the performance tests at http://jsperf.com/b64tests
  * This 12-bit-at-a-time algorithm was the best performing version on all
  * platforms tested.
  */
 
-var b64_6bit = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+var b64_6bit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 var b64_12bit;
 
-var b64_12bitTable = function() {
+var b64_12bitTable = function () {
     b64_12bit = [];
-    for (var i=0; i<64; i++) {
-        for (var j=0; j<64; j++) {
-            b64_12bit[i*64+j] = b64_6bit[i] + b64_6bit[j];
+    for (var i = 0; i < 64; i++) {
+        for (var j = 0; j < 64; j++) {
+            b64_12bit[i * 64 + j] = b64_6bit[i] + b64_6bit[j];
         }
     }
-    b64_12bitTable = function() { return b64_12bit; };
+    b64_12bitTable = function () { return b64_12bit; };
     return b64_12bit;
 };
 
-function uint8ToBase64(rawData) {
+function uint8ToBase64 (rawData) {
     var numBytes = rawData.byteLength;
-    var output="";
+    var output = '';
     var segment;
     var table = b64_12bitTable();
-    for (var i=0;i<numBytes-2;i+=3) {
-        segment = (rawData[i] << 16) + (rawData[i+1] << 8) + rawData[i+2];
+    for (var i = 0; i < numBytes - 2; i += 3) {
+        segment = (rawData[i] << 16) + (rawData[i + 1] << 8) + rawData[i + 2];
         output += table[segment >> 12];
         output += table[segment & 0xfff];
     }
-    if (numBytes - i == 2) {
-        segment = (rawData[i] << 16) + (rawData[i+1] << 8);
+    if (numBytes - i === 2) {
+        segment = (rawData[i] << 16) + (rawData[i + 1] << 8);
         output += table[segment >> 12];
         output += b64_6bit[(segment & 0xfff) >> 6];
         output += '=';
-    } else if (numBytes - i == 1) {
+    } else if (numBytes - i === 1) {
         segment = (rawData[i] << 16);
         output += table[segment >> 12];
         output += '==';
@@ -465,7 +461,7 @@ define("cordova/builder", function(require, exports, module) {
 
 var utils = require('cordova/utils');
 
-function each(objects, func, context) {
+function each (objects, func, context) {
     for (var prop in objects) {
         if (objects.hasOwnProperty(prop)) {
             func.apply(context, [objects[prop], prop]);
@@ -473,7 +469,7 @@ function each(objects, func, context) {
     }
 }
 
-function clobber(obj, key, value) {
+function clobber (obj, key, value) {
     exports.replaceHookForTesting(obj, key);
     var needsProperty = false;
     try {
@@ -483,15 +479,15 @@ function clobber(obj, key, value) {
     }
     // Getters can only be overridden by getters.
     if (needsProperty || obj[key] !== value) {
-        utils.defineGetter(obj, key, function() {
+        utils.defineGetter(obj, key, function () {
             return value;
         });
     }
 }
 
-function assignOrWrapInDeprecateGetter(obj, key, value, message) {
+function assignOrWrapInDeprecateGetter (obj, key, value, message) {
     if (message) {
-        utils.defineGetter(obj, key, function() {
+        utils.defineGetter(obj, key, function () {
             console.log(message);
             delete obj[key];
             clobber(obj, key, value);
@@ -502,7 +498,7 @@ function assignOrWrapInDeprecateGetter(obj, key, value, message) {
     }
 }
 
-function include(parent, objects, clobber, merge) {
+function include (parent, objects, clobber, merge) {
     each(objects, function (obj, key) {
         try {
             var result = obj.path ? require(obj.path) : {};
@@ -522,7 +518,7 @@ function include(parent, objects, clobber, merge) {
                 result = parent[key];
             } else {
                 // Overwrite if not currently defined.
-                if (typeof parent[key] == 'undefined') {
+                if (typeof parent[key] === 'undefined') {
                     assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
                 } else {
                     // Set result to what already exists, so we can build children into it if they exist.
@@ -533,7 +529,7 @@ function include(parent, objects, clobber, merge) {
             if (obj.children) {
                 include(result, obj.children, clobber, merge);
             }
-        } catch(e) {
+        } catch (e) {
             utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
         }
     });
@@ -546,7 +542,7 @@ function include(parent, objects, clobber, merge) {
  * @param target Object to merge properties into.
  * @param src Object to merge properties from.
  */
-function recursiveMerge(target, src) {
+function recursiveMerge (target, src) {
     for (var prop in src) {
         if (src.hasOwnProperty(prop)) {
             if (target.prototype && target.prototype.constructor === target) {
@@ -563,26 +559,26 @@ function recursiveMerge(target, src) {
     }
 }
 
-exports.buildIntoButDoNotClobber = function(objects, target) {
+exports.buildIntoButDoNotClobber = function (objects, target) {
     include(target, objects, false, false);
 };
-exports.buildIntoAndClobber = function(objects, target) {
+exports.buildIntoAndClobber = function (objects, target) {
     include(target, objects, true, false);
 };
-exports.buildIntoAndMerge = function(objects, target) {
+exports.buildIntoAndMerge = function (objects, target) {
     include(target, objects, true, true);
 };
 exports.recursiveMerge = recursiveMerge;
 exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
-exports.replaceHookForTesting = function() {};
+exports.replaceHookForTesting = function () {};
 
 });
 
 // file: src/common/channel.js
 define("cordova/channel", function(require, exports, module) {
 
-var utils = require('cordova/utils'),
-    nextGuid = 1;
+var utils = require('cordova/utils');
+var nextGuid = 1;
 
 /**
  * Custom pub-sub "channel" that can have functions subscribed to it
@@ -622,7 +618,7 @@ var utils = require('cordova/utils'),
  * @constructor
  * @param type  String the channel name
  */
-var Channel = function(type, sticky) {
+var Channel = function (type, sticky) {
     this.type = type;
     // Map of guid -> function.
     this.handlers = {};
@@ -635,69 +631,75 @@ var Channel = function(type, sticky) {
     // Function that is called when the first listener is subscribed, or when
     // the last listener is unsubscribed.
     this.onHasSubscribersChange = null;
-},
-    channel = {
-        /**
-         * Calls the provided function only after all of the channels specified
-         * have been fired. All channels must be sticky channels.
-         */
-        join: function(h, c) {
-            var len = c.length,
-                i = len,
-                f = function() {
-                    if (!(--i)) h();
-                };
-            for (var j=0; j<len; j++) {
-                if (c[j].state === 0) {
-                    throw Error('Can only use join with sticky channels.');
-                }
-                c[j].subscribe(f);
-            }
-            if (!len) h();
-        },
-        create: function(type) {
-            return channel[type] = new Channel(type, false);
-        },
-        createSticky: function(type) {
-            return channel[type] = new Channel(type, true);
-        },
-
-        /**
-         * cordova Channels that must fire before "deviceready" is fired.
-         */
-        deviceReadyChannelsArray: [],
-        deviceReadyChannelsMap: {},
-
-        /**
-         * Indicate that a feature needs to be initialized before it is ready to be used.
-         * This holds up Cordova's "deviceready" event until the feature has been initialized
-         * and Cordova.initComplete(feature) is called.
-         *
-         * @param feature {String}     The unique feature name
-         */
-        waitForInitialization: function(feature) {
-            if (feature) {
-                var c = channel[feature] || this.createSticky(feature);
-                this.deviceReadyChannelsMap[feature] = c;
-                this.deviceReadyChannelsArray.push(c);
-            }
-        },
-
-        /**
-         * Indicate that initialization code has completed and the feature is ready to be used.
-         *
-         * @param feature {String}     The unique feature name
-         */
-        initializationComplete: function(feature) {
-            var c = this.deviceReadyChannelsMap[feature];
-            if (c) {
-                c.fire();
+};
+var channel = {
+    /**
+     * Calls the provided function only after all of the channels specified
+     * have been fired. All channels must be sticky channels.
+     */
+    join: function (h, c) {
+        var len = c.length;
+        var i = len;
+        var f = function () {
+            if (!(--i)) h();
+        };
+        for (var j = 0; j < len; j++) {
+            if (c[j].state === 0) {
+                throw Error('Can only use join with sticky channels.');
             }
+            c[j].subscribe(f);
         }
-    };
+        if (!len) h();
+    },
+    /* eslint-disable no-return-assign */
+    create: function (type) {
+        return channel[type] = new Channel(type, false);
+    },
+    createSticky: function (type) {
+        return channel[type] = new Channel(type, true);
+    },
+    /* eslint-enable no-return-assign */
+    /**
+     * cordova Channels that must fire before "deviceready" is fired.
+     */
+    deviceReadyChannelsArray: [],
+    deviceReadyChannelsMap: {},
+
+    /**
+     * Indicate that a feature needs to be initialized before it is ready to be used.
+     * This holds up Cordova's "deviceready" event until the feature has been initialized
+     * and Cordova.initComplete(feature) is called.
+     *
+     * @param feature {String}     The unique feature name
+     */
+    waitForInitialization: function (feature) {
+        if (feature) {
+            var c = channel[feature] || this.createSticky(feature);
+            this.deviceReadyChannelsMap[feature] = c;
+            this.deviceReadyChannelsArray.push(c);
+        }
+    },
+
+    /**
+     * Indicate that initialization code has completed and the feature is ready to be used.
+     *
+     * @param feature {String}     The unique feature name
+     */
+    initializationComplete: function (feature) {
+        var c = this.deviceReadyChannelsMap[feature];
+        if (c) {
+            c.fire();
+        }
+    }
+};
 
-function forceFunction(f) {
-    if (typeof f != 'function') throw "Function required as first argument!";
+function checkSubscriptionArgument (argument) {
+    if (typeof argument !== 'function' && typeof argument.handleEvent !== 'function') {
+        throw new Error(
+            'Must provide a function or an EventListener object ' +
+                'implementing the handleEvent interface.'
+        );
+    }
 }
 
 /**
@@ -707,30 +709,41 @@ function forceFunction(f) {
  * and a guid that can be used to stop subscribing to the channel.
  * Returns the guid.
  */
-Channel.prototype.subscribe = function(f, c) {
-    // need a function to call
-    forceFunction(f);
-    if (this.state == 2) {
-        f.apply(c || this, this.fireArgs);
+Channel.prototype.subscribe = function (eventListenerOrFunction, eventListener) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+        eventListener = eventListenerOrFunction;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
+
+    if (this.state === 2) {
+        handleEvent.apply(eventListener || this, this.fireArgs);
         return;
     }
 
-    var func = f,
-        guid = f.observer_guid;
-    if (typeof c == "object") { func = utils.close(c, f); }
+    guid = eventListenerOrFunction.observer_guid;
+    if (typeof eventListener === 'object') {
+        handleEvent = utils.close(eventListener, handleEvent);
+    }
 
     if (!guid) {
-        // first time any channel has seen this subscriber
+        // First time any channel has seen this subscriber
         guid = '' + nextGuid++;
     }
-    func.observer_guid = guid;
-    f.observer_guid = guid;
+    handleEvent.observer_guid = guid;
+    eventListenerOrFunction.observer_guid = guid;
 
     // Don't add the same handler more than once.
     if (!this.handlers[guid]) {
-        this.handlers[guid] = func;
+        this.handlers[guid] = handleEvent;
         this.numHandlers++;
-        if (this.numHandlers == 1) {
+        if (this.numHandlers === 1) {
             this.onHasSubscribersChange && this.onHasSubscribersChange();
         }
     }
@@ -739,12 +752,20 @@ Channel.prototype.subscribe = function(f, c) {
 /**
  * Unsubscribes the function with the given guid from the channel.
  */
-Channel.prototype.unsubscribe = function(f) {
-    // need a function to unsubscribe
-    forceFunction(f);
+Channel.prototype.unsubscribe = function (eventListenerOrFunction) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid, handler;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
 
-    var guid = f.observer_guid,
-        handler = this.handlers[guid];
+    guid = handleEvent.observer_guid;
+    handler = this.handlers[guid];
     if (handler) {
         delete this.handlers[guid];
         this.numHandlers--;
@@ -757,11 +778,11 @@ Channel.prototype.unsubscribe = function(f) {
 /**
  * Calls all functions subscribed to this channel.
  */
-Channel.prototype.fire = function(e) {
-    var fail = false,
-        fireArgs = Array.prototype.slice.call(arguments);
+Channel.prototype.fire = function (e) {
+    var fail = false; // eslint-disable-line no-unused-vars
+    var fireArgs = Array.prototype.slice.call(arguments);
     // Apply stickiness.
-    if (this.state == 1) {
+    if (this.state === 1) {
         this.state = 2;
         this.fireArgs = fireArgs;
     }
@@ -775,7 +796,7 @@ Channel.prototype.fire = function(e) {
         for (var i = 0; i < toCall.length; ++i) {
             toCall[i].apply(this, fireArgs);
         }
-        if (this.state == 2 && this.numHandlers) {
+        if (this.state === 2 && this.numHandlers) {
             this.numHandlers = 0;
             this.handlers = {};
             this.onHasSubscribersChange && this.onHasSubscribersChange();
@@ -783,7 +804,6 @@ Channel.prototype.fire = function(e) {
     }
 };
 
-
 // defining them here so they are ready super fast!
 // DOM event that is received when the web page is loaded and parsed.
 channel.createSticky('onDOMContentLoaded');
@@ -816,7 +836,7 @@ module.exports = channel;
 
 });
 
-// file: src/legacy-exec/electron/confighelper.js
+// file: /Users/steveng/repo/cordova/cordova-browser/cordova-js-src/confighelper.js
 define("cordova/confighelper", function(require, exports, module) {
 
 var config;
@@ -861,20 +881,15 @@ function readConfig(success, error) {
         }
     };
 
-    if ("ActiveXObject" in window) {
-        // Needed for XHR-ing via file:// protocol in IE
-        xhr = new window.ActiveXObject("MSXML2.XMLHTTP");
-        xhr.onreadystatechange = xhrStatusChangeHandler;
-    } else {
-        xhr = new XMLHttpRequest();
-        xhr.addEventListener("load", xhrStatusChangeHandler);
-    }
+    xhr = new XMLHttpRequest();
+    xhr.addEventListener("load", xhrStatusChangeHandler);
+
 
     try {
-        xhr.open("get", "config.xml", true);
+        xhr.open("get", "/config.xml", true);
         xhr.send();
     } catch(e) {
-        fail('[Electron][cordova.js][readConfig] Could not XHR config.xml: ' + JSON.stringify(e));
+        fail('[Browser][cordova.js][readConfig] Could not XHR config.xml: ' + JSON.stringify(e));
     }
 }
 
@@ -896,35 +911,101 @@ exports.readConfig = readConfig;
 
 });
 
-// file: src/legacy-exec/electron/exec.js
+// file: /Users/steveng/repo/cordova/cordova-browser/cordova-js-src/exec.js
 define("cordova/exec", function(require, exports, module) {
 
+/*jslint sloppy:true, plusplus:true*/
+/*global require, module, console */
+
 var cordova = require('cordova');
 var execProxy = require('cordova/exec/proxy');
 
-module.exports = function(success, fail, service, action, args) {
+/**
+ * Execute a cordova command.  It is up to the native side whether this action
+ * is synchronous or asynchronous.  The native side can return:
+ *      Synchronous: PluginResult object as a JSON string
+ *      Asynchronous: Empty string ""
+ * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
+ * depending upon the result of the action.
+ *
+ * @param {Function} success    The success callback
+ * @param {Function} fail       The fail callback
+ * @param {String} service      The name of the service to use
+ * @param {String} action       Action to be run in cordova
+ * @param {String[]} [args]     Zero or more arguments to pass to the method
+ */
+module.exports = function (success, fail, service, action, args) {
 
     var proxy = execProxy.get(service, action);
 
+    args = args || [];
+
     if (proxy) {
+
         var callbackId = service + cordova.callbackId++;
 
-        if (typeof success == "function" || typeof fail == "function") {
-            cordova.callbacks[callbackId] = {success:success, fail:fail};
+        if (typeof success === "function" || typeof fail === "function") {
+            cordova.callbacks[callbackId] = {success: success, fail: fail};
         }
-
         try {
-            proxy(success, fail, args);
+
+
+
+            // callbackOptions param represents additional optional parameters command could pass back, like keepCallback or
+            // custom callbackId, for example {callbackId: id, keepCallback: true, status: cordova.callbackStatus.JSON_EXCEPTION }
+            var onSuccess = function (result, callbackOptions) {
+                callbackOptions = callbackOptions || {};
+                var callbackStatus;
+                // covering both undefined and null.
+                // strict null comparison was causing callbackStatus to be undefined
+                // and then no callback was called because of the check in cordova.callbackFromNative
+                // see CB-8996 Mobilespec app hang on windows
+                if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+                    callbackStatus = callbackOptions.status;
+                }
+                else {
+                    callbackStatus = cordova.callbackStatus.OK;
+                }
+                cordova.callbackSuccess(callbackOptions.callbackId || callbackId,
+                    {
+                        status: callbackStatus,
+                        message: result,
+                        keepCallback: callbackOptions.keepCallback || false
+                    });
+            };
+            var onError = function (err, callbackOptions) {
+                callbackOptions = callbackOptions || {};
+                var callbackStatus;
+                // covering both undefined and null.
+                // strict null comparison was causing callbackStatus to be undefined
+                // and then no callback was called because of the check in cordova.callbackFromNative
+                // note: status can be 0
+                if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+                    callbackStatus = callbackOptions.status;
+                }
+                else {
+                    callbackStatus = cordova.callbackStatus.OK;
+                }
+                cordova.callbackError(callbackOptions.callbackId || callbackId,
+                {
+                    status: callbackStatus,
+                    message: err,
+                    keepCallback: callbackOptions.keepCallback || false
+                });
+            };
+            proxy(onSuccess, onError, args);
+
+        } catch (e) {
+            console.log("Exception calling native with command :: " + service + " :: " + action  + " ::exception=" + e);
         }
-        catch(e) {
-            // TODO throw maybe?
-            var msg = "Exception calling :: " + service + " :: " + action  + " ::exception=" + e;
-            console.log(msg);
+    } else {
+
+        console.log("Error: exec proxy not found for :: " + service + " :: " + action);
+
+        if(typeof fail === "function" ) {
+            fail("Missing Command Error");
         }
     }
-    else {
-        fail && fail("Missing Command Error");
-    }
 };
 
 });
@@ -932,31 +1013,31 @@ module.exports = function(success, fail, service, action, args) {
 // file: src/common/exec/proxy.js
 define("cordova/exec/proxy", function(require, exports, module) {
 
-
 // internal map of proxy function
 var CommandProxyMap = {};
 
 module.exports = {
 
     // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
-    add:function(id,proxyObj) {
-        console.log("adding proxy for " + id);
+    add: function (id, proxyObj) {
+        console.log('adding proxy for ' + id);
         CommandProxyMap[id] = proxyObj;
         return proxyObj;
     },
 
     // cordova.commandProxy.remove("Accelerometer");
-    remove:function(id) {
+    remove: function (id) {
         var proxy = CommandProxyMap[id];
         delete CommandProxyMap[id];
         CommandProxyMap[id] = null;
         return proxy;
     },
 
-    get:function(service,action) {
-        return ( CommandProxyMap[service] ? CommandProxyMap[service][action] : null );
+    get: function (service, action) {
+        return (CommandProxyMap[service] ? CommandProxyMap[service][action] : null);
     }
 };
+
 });
 
 // file: src/common/init.js
@@ -971,16 +1052,16 @@ var utils = require('cordova/utils');
 
 var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
 
-function logUnfiredChannels(arr) {
+function logUnfiredChannels (arr) {
     for (var i = 0; i < arr.length; ++i) {
-        if (arr[i].state != 2) {
+        if (arr[i].state !== 2) {
             console.log('Channel not fired: ' + arr[i].type);
         }
     }
 }
 
-window.setTimeout(function() {
-    if (channel.onDeviceReady.state != 2) {
+window.setTimeout(function () {
+    if (channel.onDeviceReady.state !== 2) {
         console.log('deviceready has not fired after 5 seconds.');
         logUnfiredChannels(platformInitChannelsArray);
         logUnfiredChannels(channel.deviceReadyChannelsArray);
@@ -989,20 +1070,19 @@ window.setTimeout(function() {
 
 // Replace navigator before any modules are required(), to ensure it happens as soon as possible.
 // We replace it so that properties that can't be clobbered can instead be overridden.
-function replaceNavigator(origNavigator) {
-    var CordovaNavigator = function() {};
+function replaceNavigator (origNavigator) {
+    var CordovaNavigator = function () {};
     CordovaNavigator.prototype = origNavigator;
     var newNavigator = new CordovaNavigator();
     // This work-around really only applies to new APIs that are newer than Function.bind.
     // Without it, APIs such as getGamepads() break.
     if (CordovaNavigator.bind) {
         for (var key in origNavigator) {
-            if (typeof origNavigator[key] == 'function') {
+            if (typeof origNavigator[key] === 'function') {
                 newNavigator[key] = origNavigator[key].bind(origNavigator);
-            }
-            else {
-                (function(k) {
-                    utils.defineGetterSetter(newNavigator,key,function() {
+            } else {
+                (function (k) {
+                    utils.defineGetterSetter(newNavigator, key, function () {
                         return origNavigator[k];
                     });
                 })(key);
@@ -1018,25 +1098,26 @@ if (window.navigator) {
 
 if (!window.console) {
     window.console = {
-        log: function(){}
+        log: function () {}
     };
 }
 if (!window.console.warn) {
-    window.console.warn = function(msg) {
-        this.log("warn: " + msg);
+    window.console.warn = function (msg) {
+        this.log('warn: ' + msg);
     };
 }
 
 // Register pause, resume and deviceready channels as events on document.
 channel.onPause = cordova.addDocumentEventHandler('pause');
 channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onActivated = cordova.addDocumentEventHandler('activated');
 channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
 
 // Listen for DOMContentLoaded and notify our channel subscribers.
-if (document.readyState == 'complete' || document.readyState == 'interactive') {
+if (document.readyState === 'complete' || document.readyState === 'interactive') {
     channel.onDOMContentLoaded.fire();
 } else {
-    document.addEventListener('DOMContentLoaded', function() {
+    document.addEventListener('DOMContentLoaded', function () {
         channel.onDOMContentLoaded.fire();
     }, false);
 }
@@ -1057,8 +1138,8 @@ platform.bootstrap && platform.bootstrap();
 
 // Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
 // The delay allows the attached modules to be defined before the plugin loader looks for them.
-setTimeout(function() {
-    pluginloader.load(function() {
+setTimeout(function () {
+    pluginloader.load(function () {
         channel.onPluginsReady.fire();
     });
 }, 0);
@@ -1066,7 +1147,7 @@ setTimeout(function() {
 /**
  * Create all cordova objects once native side is ready.
  */
-channel.join(function() {
+channel.join(function () {
     modulemapper.mapModules(window);
 
     platform.initialize && platform.initialize();
@@ -1077,13 +1158,12 @@ channel.join(function() {
     // Fire onDeviceReady event once page has fully loaded, all
     // constructors have run and cordova info has been received from native
     // side.
-    channel.join(function() {
+    channel.join(function () {
         require('cordova').fireDocumentEvent('deviceready');
     }, channel.deviceReadyChannelsArray);
 
 }, platformInitChannelsArray);
 
-
 });
 
 // file: src/common/init_b.js
@@ -1091,24 +1171,26 @@ define("cordova/init_b", function(require, exports, module) {
 
 var channel = require('cordova/channel');
 var cordova = require('cordova');
+var modulemapper = require('cordova/modulemapper');
 var platform = require('cordova/platform');
+var pluginloader = require('cordova/pluginloader');
 var utils = require('cordova/utils');
 
-var platformInitChannelsArray = [channel.onDOMContentLoaded, channel.onNativeReady];
+var platformInitChannelsArray = [channel.onDOMContentLoaded, channel.onNativeReady, channel.onPluginsReady];
 
 // setting exec
 cordova.exec = require('cordova/exec');
 
-function logUnfiredChannels(arr) {
+function logUnfiredChannels (arr) {
     for (var i = 0; i < arr.length; ++i) {
-        if (arr[i].state != 2) {
+        if (arr[i].state !== 2) {
             console.log('Channel not fired: ' + arr[i].type);
         }
     }
 }
 
-window.setTimeout(function() {
-    if (channel.onDeviceReady.state != 2) {
+window.setTimeout(function () {
+    if (channel.onDeviceReady.state !== 2) {
         console.log('deviceready has not fired after 5 seconds.');
         logUnfiredChannels(platformInitChannelsArray);
         logUnfiredChannels(channel.deviceReadyChannelsArray);
@@ -1117,20 +1199,19 @@ window.setTimeout(function() {
 
 // Replace navigator before any modules are required(), to ensure it happens as soon as possible.
 // We replace it so that properties that can't be clobbered can instead be overridden.
-function replaceNavigator(origNavigator) {
-    var CordovaNavigator = function() {};
+function replaceNavigator (origNavigator) {
+    var CordovaNavigator = function () {};
     CordovaNavigator.prototype = origNavigator;
     var newNavigator = new CordovaNavigator();
     // This work-around really only applies to new APIs that are newer than Function.bind.
     // Without it, APIs such as getGamepads() break.
     if (CordovaNavigator.bind) {
         for (var key in origNavigator) {
-            if (typeof origNavigator[key] == 'function') {
+            if (typeof origNavigator[key] === 'function') {
                 newNavigator[key] = origNavigator[key].bind(origNavigator);
-            }
-            else {
-                (function(k) {
-                    utils.defineGetterSetter(newNavigator,key,function() {
+            } else {
+                (function (k) {
+                    utils.defineGetterSetter(newNavigator, key, function () {
                         return origNavigator[k];
                     });
                 })(key);
@@ -1145,25 +1226,26 @@ if (window.navigator) {
 
 if (!window.console) {
     window.console = {
-        log: function(){}
+        log: function () {}
     };
 }
 if (!window.console.warn) {
-    window.console.warn = function(msg) {
-        this.log("warn: " + msg);
+    window.console.warn = function (msg) {
+        this.log('warn: ' + msg);
     };
 }
 
 // Register pause, resume and deviceready channels as events on document.
 channel.onPause = cordova.addDocumentEventHandler('pause');
 channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onActivated = cordova.addDocumentEventHandler('activated');
 channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
 
 // Listen for DOMContentLoaded and notify our channel subscribers.
-if (document.readyState == 'complete' || document.readyState == 'interactive') {
+if (document.readyState === 'complete' || document.readyState === 'interactive') {
     channel.onDOMContentLoaded.fire();
 } else {
-    document.addEventListener('DOMContentLoaded', function() {
+    document.addEventListener('DOMContentLoaded', function () {
         channel.onDOMContentLoaded.fire();
     }, false);
 }
@@ -1178,10 +1260,19 @@ if (window._nativeReady) {
 // Call the platform-specific initialization.
 platform.bootstrap && platform.bootstrap();
 
+// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
+// The delay allows the attached modules to be defined before the plugin loader looks for them.
+setTimeout(function () {
+    pluginloader.load(function () {
+        channel.onPluginsReady.fire();
+    });
+}, 0);
+
 /**
  * Create all cordova objects once native side is ready.
  */
-channel.join(function() {
+channel.join(function () {
+    modulemapper.mapModules(window);
 
     platform.initialize && platform.initialize();
 
@@ -1191,7 +1282,7 @@ channel.join(function() {
     // Fire onDeviceReady event once page has fully loaded, all
     // constructors have run and cordova info has been received from native
     // side.
-    channel.join(function() {
+    channel.join(function () {
         require('cordova').fireDocumentEvent('deviceready');
     }, channel.deviceReadyChannelsArray);
 
@@ -1202,17 +1293,17 @@ channel.join(function() {
 // file: src/common/modulemapper.js
 define("cordova/modulemapper", function(require, exports, module) {
 
-var builder = require('cordova/builder'),
-    moduleMap = define.moduleMap,
-    symbolList,
-    deprecationMap;
+var builder = require('cordova/builder');
+var moduleMap = define.moduleMap; // eslint-disable-line no-undef
+var symbolList;
+var deprecationMap;
 
-exports.reset = function() {
+exports.reset = function () {
     symbolList = [];
     deprecationMap = {};
 };
 
-function addEntry(strategy, moduleName, symbolPath, opt_deprecationMessage) {
+function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
     if (!(moduleName in moduleMap)) {
         throw new Error('Module ' + moduleName + ' does not exist.');
     }
@@ -1223,35 +1314,35 @@ function addEntry(strategy, moduleName, symbolPath, opt_deprecationMessage) {
 }
 
 // Note: Android 2.3 does have Function.bind().
-exports.clobbers = function(moduleName, symbolPath, opt_deprecationMessage) {
+exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
     addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
 };
 
-exports.merges = function(moduleName, symbolPath, opt_deprecationMessage) {
+exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
     addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
 };
 
-exports.defaults = function(moduleName, symbolPath, opt_deprecationMessage) {
+exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
     addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
 };
 
-exports.runs = function(moduleName) {
+exports.runs = function (moduleName) {
     addEntry('r', moduleName, null);
 };
 
-function prepareNamespace(symbolPath, context) {
+function prepareNamespace (symbolPath, context) {
     if (!symbolPath) {
         return context;
     }
     var parts = symbolPath.split('.');
     var cur = context;
-    for (var i = 0, part; part = parts[i]; ++i) {
+    for (var i = 0, part; part = parts[i]; ++i) { // eslint-disable-line no-cond-assign
         cur = cur[part] = cur[part] || {};
     }
     return cur;
 }
 
-exports.mapModules = function(context) {
+exports.mapModules = function (context) {
     var origSymbols = {};
     context.CDV_origSymbols = origSymbols;
     for (var i = 0, len = symbolList.length; i < len; i += 3) {
@@ -1259,7 +1350,7 @@ exports.mapModules = function(context) {
         var moduleName = symbolList[i + 1];
         var module = require(moduleName);
         // <runs/>
-        if (strategy == 'r') {
+        if (strategy === 'r') {
             continue;
         }
         var symbolPath = symbolList[i + 2];
@@ -1271,9 +1362,9 @@ exports.mapModules = function(context) {
         var parentObj = prepareNamespace(namespace, context);
         var target = parentObj[lastName];
 
-        if (strategy == 'm' && target) {
+        if (strategy === 'm' && target) {
             builder.recursiveMerge(target, module);
-        } else if ((strategy == 'd' && !target) || (strategy != 'd')) {
+        } else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
             if (!(symbolPath in origSymbols)) {
                 origSymbols[symbolPath] = target;
             }
@@ -1282,7 +1373,7 @@ exports.mapModules = function(context) {
     }
 };
 
-exports.getOriginalSymbol = function(context, symbolPath) {
+exports.getOriginalSymbol = function (context, symbolPath) {
     var origSymbols = context.CDV_origSymbols;
     if (origSymbols && (symbolPath in origSymbols)) {
         return origSymbols[symbolPath];
@@ -1297,14 +1388,110 @@ exports.getOriginalSymbol = function(context, symbolPath) {
 
 exports.reset();
 
+});
+
+// file: src/common/modulemapper_b.js
+define("cordova/modulemapper_b", function(require, exports, module) {
+
+var builder = require('cordova/builder');
+var symbolList = [];
+var deprecationMap;
+
+exports.reset = function () {
+    symbolList = [];
+    deprecationMap = {};
+};
+
+function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
+    symbolList.push(strategy, moduleName, symbolPath);
+    if (opt_deprecationMessage) {
+        deprecationMap[symbolPath] = opt_deprecationMessage;
+    }
+}
+
+// Note: Android 2.3 does have Function.bind().
+exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.runs = function (moduleName) {
+    addEntry('r', moduleName, null);
+};
+
+function prepareNamespace (symbolPath, context) {
+    if (!symbolPath) {
+        return context;
+    }
+    var parts = symbolPath.split('.');
+    var cur = context;
+    for (var i = 0, part; part = parts[i]; ++i) { // eslint-disable-line no-cond-assign
+        cur = cur[part] = cur[part] || {};
+    }
+    return cur;
+}
+
+exports.mapModules = function (context) {
+    var origSymbols = {};
+    context.CDV_origSymbols = origSymbols;
+    for (var i = 0, len = symbolList.length; i < len; i += 3) {
+        var strategy = symbolList[i];
+        var moduleName = symbolList[i + 1];
+        var module = require(moduleName);
+        // <runs/>
+        if (strategy === 'r') {
+            continue;
+        }
+        var symbolPath = symbolList[i + 2];
+        var lastDot = symbolPath.lastIndexOf('.');
+        var namespace = symbolPath.substr(0, lastDot);
+        var lastName = symbolPath.substr(lastDot + 1);
+
+        var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
+        var parentObj = prepareNamespace(namespace, context);
+        var target = parentObj[lastName];
+
+        if (strategy === 'm' && target) {
+            builder.recursiveMerge(target, module);
+        } else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
+            if (!(symbolPath in origSymbols)) {
+                origSymbols[symbolPath] = target;
+            }
+            builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
+        }
+    }
+};
+
+exports.getOriginalSymbol = function (context, symbolPath) {
+    var origSymbols = context.CDV_origSymbols;
+    if (origSymbols && (symbolPath in origSymbols)) {
+        return origSymbols[symbolPath];
+    }
+    var parts = symbolPath.split('.');
+    var obj = context;
+    for (var i = 0; i < parts.length; ++i) {
+        obj = obj && obj[parts[i]];
+    }
+    return obj;
+};
+
+exports.reset();
 
 });
 
-// file: src/legacy-exec/electron/platform.js
+// file: /Users/steveng/repo/cordova/cordova-browser/cordova-js-src/platform.js
 define("cordova/platform", function(require, exports, module) {
 
 module.exports = {
     id: 'electron',
+    cordovaVersion: '4.2.0', // cordova-js
 
     bootstrap: function() {
 
@@ -1315,6 +1502,15 @@ module.exports = {
 
         channel.onNativeReady.fire();
 
+        document.addEventListener("visibilitychange", function(){
+            if(document.hidden) {
+                channel.onPause.fire();
+            }
+            else {
+                channel.onResume.fire();
+            }
+        });
+
     // End of bootstrap
     }
 };
@@ -1325,12 +1521,11 @@ module.exports = {
 define("cordova/pluginloader", function(require, exports, module) {
 
 var modulemapper = require('cordova/modulemapper');
-var urlutil = require('cordova/urlutil');
 
 // Helper function to inject a <script> tag.
 // Exported for testing.
-exports.injectScript = function(url, onload, onerror) {
-    var script = document.createElement("script");
+exports.injectScript = function (url, onload, onerror) {
+    var script = document.createElement('script');
     // onload fires even when script fails loads with an error.
     script.onload = onload;
     // onerror fires for malformed URLs.
@@ -1339,13 +1534,13 @@ exports.injectScript = function(url, onload, onerror) {
     document.head.appendChild(script);
 };
 
-function injectIfNecessary(id, url, onload, onerror) {
+function injectIfNecessary (id, url, onload, onerror) {
     onerror = onerror || onload;
-    if (id in define.moduleMap) {
+    if (id in define.moduleMap) { // eslint-disable-line no-undef
         onload();
     } else {
-        exports.injectScript(url, function() {
-            if (id in define.moduleMap) {
+        exports.injectScript(url, function () {
+            if (id in define.moduleMap) { // eslint-disable-line no-undef
                 onload();
             } else {
                 onerror();
@@ -1354,9 +1549,9 @@ function injectIfNecessary(id, url, onload, onerror) {
     }
 }
 
-function onScriptLoadingComplete(moduleList, finishPluginLoading) {
+function onScriptLoadingComplete (moduleList, finishPluginLoading) {
     // Loop through all the plugins and then through their clobbers and merges.
-    for (var i = 0, module; module = moduleList[i]; i++) {
+    for (var i = 0, module; module = moduleList[i]; i++) { // eslint-disable-line no-cond-assign
         if (module.clobbers && module.clobbers.length) {
             for (var j = 0; j < module.clobbers.length; j++) {
                 modulemapper.clobbers(module.id, module.clobbers[j]);
@@ -1382,7 +1577,7 @@ function onScriptLoadingComplete(moduleList, finishPluginLoading) {
 // See plugman's plugin_loader.js for the details of this object.
 // This function is only called if the really is a plugins array that isn't empty.
 // Otherwise the onerror response handler will just call finishPluginLoading().
-function handlePluginsObject(path, moduleList, finishPluginLoading) {
+function handlePluginsObject (path, moduleList, finishPluginLoading) {
     // Now inject the scripts.
     var scriptCounter = moduleList.length;
 
@@ -1390,7 +1585,7 @@ function handlePluginsObject(path, moduleList, finishPluginLoading) {
         finishPluginLoading();
         return;
     }
-    function scriptLoadedCallback() {
+    function scriptLoadedCallback () {
         if (!--scriptCounter) {
             onScriptLoadingComplete(moduleList, finishPluginLoading);
         }
@@ -1401,13 +1596,13 @@ function handlePluginsObject(path, moduleList, finishPluginLoading) {
     }
 }
 
-function findCordovaPath() {
+function findCordovaPath () {
     var path = null;
     var scripts = document.getElementsByTagName('script');
     var term = '/cordova.js';
-    for (var n = scripts.length-1; n>-1; n--) {
+    for (var n = scripts.length - 1; n > -1; n--) {
         var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
-        if (src.indexOf(term) == (src.length - term.length)) {
+        if (src.indexOf(term) === (src.length - term.length)) {
             path = src.substring(0, src.length - term.length) + '/';
             break;
         }
@@ -1418,36 +1613,80 @@ function findCordovaPath() {
 // Tries to load all plugins' js-modules.
 // This is an async process, but onDeviceReady is blocked on onPluginsReady.
 // onPluginsReady is fired when there are no plugins to load, or they are all done.
-exports.load = function(callback) {
+exports.load = function (callback) {
     var pathPrefix = findCordovaPath();
     if (pathPrefix === null) {
         console.log('Could not find cordova.js script tag. Plugin loading may fail.');
         pathPrefix = '';
     }
-    injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function() {
-        var moduleList = require("cordova/plugin_list");
+    injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function () {
+        var moduleList = require('cordova/plugin_list');
         handlePluginsObject(pathPrefix, moduleList, callback);
     }, callback);
 };
 
+});
+
+// file: src/common/pluginloader_b.js
+define("cordova/pluginloader_b", function(require, exports, module) {
+
+var modulemapper = require('cordova/modulemapper');
+
+// Handler for the cordova_plugins.js content.
+// See plugman's plugin_loader.js for the details of this object.
+function handlePluginsObject (moduleList) {
+    // if moduleList is not defined or empty, we've nothing to do
+    if (!moduleList || !moduleList.length) {
+        return;
+    }
+
+    // Loop through all the modules and then through their clobbers and merges.
+    for (var i = 0, module; module = moduleList[i]; i++) { // eslint-disable-line no-cond-assign
+        if (module.clobbers && module.clobbers.length) {
+            for (var j = 0; j < module.clobbers.length; j++) {
+                modulemapper.clobbers(module.id, module.clobbers[j]);
+            }
+        }
+
+        if (module.merges && module.merges.length) {
+            for (var k = 0; k < module.merges.length; k++) {
+                modulemapper.merges(module.id, module.merges[k]);
+            }
+        }
+
+        // Finally, if runs is truthy we want to simply require() the module.
+        if (module.runs) {
+            modulemapper.runs(module.id);
+        }
+    }
+}
+
+// Loads all plugins' js-modules. Plugin loading is syncronous in browserified bundle
+// but the method accepts callback to be compatible with non-browserify flow.
+// onDeviceReady is blocked on onPluginsReady. onPluginsReady is fired when there are
+// no plugins to load, or they are all done.
+exports.load = function (callback) {
+    var moduleList = require('cordova/plugin_list');
+    handlePluginsObject(moduleList);
+
+    callback();
+};
 
 });
 
 // file: src/common/urlutil.js
 define("cordova/urlutil", function(require, exports, module) {
 
-
 /**
  * For already absolute URLs, returns what is passed in.
  * For relative URLs, converts them to absolute ones.
  */
-exports.makeAbsolute = function makeAbsolute(url) {
+exports.makeAbsolute = function makeAbsolute (url) {
     var anchorEl = document.createElement('a');
     anchorEl.href = url;
     return anchorEl.href;
 };
 
-
 });
 
 // file: src/common/utils.js
@@ -1458,7 +1697,7 @@ var utils = exports;
 /**
  * Defines a property getter / setter for obj[key].
  */
-utils.defineGetterSetter = function(obj, key, getFunc, opt_setFunc) {
+utils.defineGetterSetter = function (obj, key, getFunc, opt_setFunc) {
     if (Object.defineProperty) {
         var desc = {
             get: getFunc,
@@ -1481,13 +1720,13 @@ utils.defineGetterSetter = function(obj, key, getFunc, opt_setFunc) {
  */
 utils.defineGetter = utils.defineGetterSetter;
 
-utils.arrayIndexOf = function(a, item) {
+utils.arrayIndexOf = function (a, item) {
     if (a.indexOf) {
         return a.indexOf(item);
     }
     var len = a.length;
     for (var i = 0; i < len; ++i) {
-        if (a[i] == item) {
+        if (a[i] === item) {
             return i;
         }
     }
@@ -1497,53 +1736,55 @@ utils.arrayIndexOf = function(a, item) {
 /**
  * Returns whether the item was found in the array.
  */
-utils.arrayRemove = function(a, item) {
+utils.arrayRemove = function (a, item) {
     var index = utils.arrayIndexOf(a, item);
-    if (index != -1) {
+    if (index !== -1) {
         a.splice(index, 1);
     }
-    return index != -1;
+    return index !== -1;
 };
 
-utils.typeName = function(val) {
+utils.typeName = function (val) {
     return Object.prototype.toString.call(val).slice(8, -1);
 };
 
 /**
  * Returns an indication of whether the argument is an array or not
  */
-utils.isArray = function(a) {
-    return utils.typeName(a) == 'Array';
-};
+utils.isArray = Array.isArray ||
+                function (a) { return utils.typeName(a) === 'Array'; };
 
 /**
  * Returns an indication of whether the argument is a Date or not
  */
-utils.isDate = function(d) {
-    return utils.typeName(d) == 'Date';
+utils.isDate = function (d) {
+    return (d instanceof Date);
 };
 
 /**
  * Does a deep clone of the object.
  */
-utils.clone = function(obj) {
-    if(!obj || typeof obj == 'function' || utils.isDate(obj) || typeof obj != 'object') {
+utils.clone = function (obj) {
+    if (!obj || typeof obj === 'function' || utils.isDate(obj) || typeof obj !== 'object') {
         return obj;
     }
 
     var retVal, i;
 
-    if(utils.isArray(obj)){
+    if (utils.isArray(obj)) {
         retVal = [];
-        for(i = 0; i < obj.length; ++i){
+        for (i = 0; i < obj.length; ++i) {
             retVal.push(utils.clone(obj[i]));
         }
         return retVal;
     }
 
     retVal = {};
-    for(i in obj){
-        if(!(i in retVal) || retVal[i] != obj[i]) {
+    for (i in obj) {
+        // https://issues.apache.org/jira/browse/CB-11522 'unknown' type may be returned in
+        // custom protocol activation case on Windows Phone 8.1 causing "No such interface supported" exception
+        // on cloning.
+        if ((!(i in retVal) || retVal[i] !== obj[i]) && typeof obj[i] !== 'undefined' && typeof obj[i] !== 'unknown') { // eslint-disable-line valid-typeof
             retVal[i] = utils.clone(obj[i]);
         }
     }
@@ -1553,22 +1794,30 @@ utils.clone = function(obj) {
 /**
  * Returns a wrapped version of the function
  */
-utils.close = function(context, func, params) {
-    if (typeof params == 'undefined') {
-        return function() {
-            return func.apply(context, arguments);
-        };
-    } else {
-        return function() {
-            return func.apply(context, params);
-        };
-    }
+utils.close = function (context, func, params) {
+    return function () {
+        var args = params || arguments;
+        return func.apply(context, args);
+    };
 };
 
+// ------------------------------------------------------------------------------
+function UUIDcreatePart (length) {
+    var uuidpart = '';
+    for (var i = 0; i < length; i++) {
+        var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
+        if (uuidchar.length === 1) {
+            uuidchar = '0' + uuidchar;
+        }
+        uuidpart += uuidchar;
+    }
+    return uuidpart;
+}
+
 /**
  * Create a UUID
  */
-utils.createUUID = function() {
+utils.createUUID = function () {
     return UUIDcreatePart(4) + '-' +
         UUIDcreatePart(2) + '-' +
         UUIDcreatePart(2) + '-' +
@@ -1580,11 +1829,12 @@ utils.createUUID = function() {
  * Extends a child object from a parent object using classical inheritance
  * pattern.
  */
-utils.extend = (function() {
+utils.extend = (function () {
     // proxy used to establish prototype chain
-    var F = function() {};
+    var F = function () {};
     // extend Child from Parent
-    return function(Child, Parent) {
+    return function (Child, Parent) {
+
         F.prototype = Parent.prototype;
         Child.prototype = new F();
         Child.__super__ = Parent.prototype;
@@ -1595,7 +1845,7 @@ utils.extend = (function() {
 /**
  * Alerts a message in any available way: alert or console.log.
  */
-utils.alert = function(msg) {
+utils.alert = function (msg) {
     if (window.alert) {
         window.alert(msg);
     } else if (console && console.log) {
@@ -1603,21 +1853,6 @@ utils.alert = function(msg) {
     }
 };
 
-
-//------------------------------------------------------------------------------
-function UUIDcreatePart(length) {
-    var uuidpart = "";
-    for (var i=0; i<length; i++) {
-        var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
-        if (uuidchar.length == 1) {
-            uuidchar = "0" + uuidchar;
-        }
-        uuidpart += uuidchar;
-    }
-    return uuidpart;
-}
-
-
 });
 
 window.cordova = require('cordova');
index 827599c..ae2e73c 100644 (file)
@@ -1,27 +1,62 @@
 {
   "name": "cordova-electron",
-  "version": "0.0.1",
-  "description": "Adding electron as a platform for cordova",
-  "main": "main.js",
-  "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1",
-    "start": "./node_modules/electron-prebuilt/dist/Electron.app/Contents/MacOS/Electron ."
+  "version": "1.0.0",
+  "description": "electron apps as a target for cordova developers",
+  "main": "bin/template/cordova/Api.js",
+  "bin": "bin/create",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/apache/cordova-electron"
+  },
+  "bugs": {
+    "url": "https://issues.apache.org/jira/browse/CB"
   },
   "kewords": [
     "cordova",
     "electron",
     "apache"
   ],
-  "author": "Steve Gill",
-  "license": "Apache Version 2.0",
+  "scripts": {
+    "eslint": "eslint bin && eslint spec",
+    "jasmine": "jasmine",
+    "test": "npm run eslint && npm run jasmine"
+  },
   "dependencies": {
-    "q": "^1.4.0",
-    "shelljs": "^0.4.0",
-    "electron-prebuilt": "^0.27.1"
+    "cordova-common": "^2.1.1",
+    "electron": "^1.7.9",
+    "nopt": "^3.0.6",
+    "shelljs": "^0.5.3"
+  },
+  "devDependencies": {
+    "eslint": "^4.0.0",
+    "eslint-config-semistandard": "^11.0.0",
+    "eslint-config-standard": "^10.2.1",
+    "eslint-plugin-import": "^2.3.0",
+    "eslint-plugin-node": "^5.0.0",
+    "eslint-plugin-promise": "^3.5.0",
+    "eslint-plugin-standard": "^3.0.1",
+    "jasmine": "^2.5.3",
+    "tmp": "^0.0.26"
   },
   "bundleDependencies": [
-    "q",
+    "nopt",
     "shelljs",
-    "electron-prebuilt"
-  ]
+    "cordova-common"
+  ],
+  "author": "Apache Software Foundation",
+  "contributors": [
+    {
+      "name": "Steve Gill",
+      "email": "steveng@adobe.com"
+    },
+    {
+      "name": "Jesse MacFadyen",
+      "email": "purplecabbage@apache.org"
+    }
+  ],
+  "license": "Apache-2.0",
+  "engines": {
+    "node": ">=4.0.0"
+  },
+  "engineStrict": true
 }
diff --git a/spec/.eslintrc.yml b/spec/.eslintrc.yml
new file mode 100644 (file)
index 0000000..6afba65
--- /dev/null
@@ -0,0 +1,2 @@
+env:
+    jasmine: true
\ No newline at end of file
diff --git a/spec/create.spec.js b/spec/create.spec.js
new file mode 100644 (file)
index 0000000..ed92a11
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+var shell = require('shelljs');
+var fs = require('fs');
+var path = require('path');
+var util = require('util');
+
+var cordova_bin = path.join(__dirname, '../bin');// is this the same on all platforms?
+var tmpDir = path.join(__dirname, '../temp');
+var createScriptPath = path.join(cordova_bin, 'create');
+
+function createAndBuild (projectname, projectid) {
+
+    var return_code = 0;
+    var command;
+
+    // remove existing folder
+    shell.rm('-rf', tmpDir);
+    shell.mkdir(tmpDir);
+
+    // create the project
+    command = util.format('"%s" "%s/%s" "%s" "%s"', createScriptPath, tmpDir, projectname, projectid, projectname);
+    // shell.echo(command);
+    return_code = shell.exec(command).code;
+    expect(return_code).toBe(0);
+
+    var tempCordovaScriptsPath = path.join(tmpDir, projectname, 'cordova');
+
+    console.log('tempCordovaScriptsPath = ' + tempCordovaScriptsPath);
+
+    // created project has scripts in the cordova folder
+    // build, clean, log, run, version
+    expect(fs.existsSync(path.join(tempCordovaScriptsPath, 'build'))).toBe(true);
+    expect(fs.existsSync(path.join(tempCordovaScriptsPath, 'clean'))).toBe(true);
+    expect(fs.existsSync(path.join(tempCordovaScriptsPath, 'log'))).toBe(true);
+    expect(fs.existsSync(path.join(tempCordovaScriptsPath, 'run'))).toBe(true);
+    expect(fs.existsSync(path.join(tempCordovaScriptsPath, 'version'))).toBe(true);
+
+    // // build the project
+    command = util.format('"%s/cordova/build"', path.join(tmpDir, projectname));
+    // shell.echo(command);
+    return_code = shell.exec(command, { silent: true }).code;
+    expect(return_code).toBe(0);
+
+    // clean-up
+    shell.rm('-rf', tmpDir);
+}
+
+describe('create', function () {
+
+    it('has a create script in bin/cordova', function () {
+        expect(fs.existsSync(createScriptPath)).toBe(true);
+    });
+
+    it('create project with ascii name, no spaces', function () {
+        var projectname = 'testcreate';
+        var projectid = 'com.test.app1';
+
+        createAndBuild(projectname, projectid);
+    });
+
+    it('create project with ascii name, and spaces', function () {
+        var projectname = 'test create';
+        var projectid = 'com.test.app2';
+
+        createAndBuild(projectname, projectid);
+    });
+
+    it('create project with unicode name, no spaces', function () {
+        var projectname = '応応応応用用用用';
+        var projectid = 'com.test.app3';
+
+        createAndBuild(projectname, projectid);
+    });
+
+    it('create project with unicode name, and spaces', function () {
+        var projectname = '応応応応 用用用用';
+        var projectid = 'com.test.app4';
+
+        createAndBuild(projectname, projectid);
+    });
+
+    it('create project with ascii+unicode name, no spaces', function () {
+        var projectname = '応応応応hello用用用用';
+        var projectid = 'com.test.app5';
+
+        createAndBuild(projectname, projectid);
+    });
+
+    it('create project with ascii+unicode name, and spaces', function () {
+        var projectname = '応応応応 hello 用用用用';
+        var projectid = 'com.test.app6';
+
+        createAndBuild(projectname, projectid);
+    });
+
+});
diff --git a/spec/handler.spec.js b/spec/handler.spec.js
new file mode 100644 (file)
index 0000000..0489b00
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+var handler = require('../bin/template/cordova/handler');
+var shell = require('shelljs');
+var fs = require('fs');
+var path = require('path');
+
+describe('Asset install tests', function () {
+    var fsstatMock;
+    var asset = { itemType: 'asset', src: 'someSrc/ServiceWorker.js', target: 'ServiceWorker.js' };
+    var plugin_dir = 'pluginDir';
+    var wwwDest = 'dest';
+    var cpPath = path.join(plugin_dir, asset.src);
+
+    it('if src is a directory, should be called with cp, -Rf', function () {
+        var cp = spyOn(shell, 'cp').and.returnValue('-Rf');
+        fsstatMock = {
+            isDirectory: function () {
+                return true;
+            }
+        };
+        spyOn(fs, 'statSync').and.returnValue(fsstatMock);
+        handler.asset.install(asset, plugin_dir, wwwDest);
+        expect(cp).toHaveBeenCalledWith('-Rf', jasmine.any(String), path.join('dest', asset.target));
+    });
+    it('if src is not a directory, should be called with cp, -f', function () {
+        var cp = spyOn(shell, 'cp').and.returnValue('-f');
+        fsstatMock = {
+            isDirectory: function () {
+                return false;
+            }
+        };
+        spyOn(fs, 'statSync').and.returnValue(fsstatMock);
+        handler.asset.install(asset, plugin_dir, wwwDest);
+        expect(cp).toHaveBeenCalledWith('-f', cpPath, path.join('dest', asset.target));
+    });
+});
diff --git a/spec/manifest.spec.js b/spec/manifest.spec.js
new file mode 100644 (file)
index 0000000..8bc144f
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+var shell = require('shelljs');
+var fs = require('fs');
+var path = require('path');
+var util = require('util');
+
+var cordova_bin = path.join(__dirname, '../bin');// is this the same on all platforms?
+var tmpDir = path.join(__dirname, '../temp');
+var createScriptPath = path.join(cordova_bin, 'create');
+
+function createAndBuild (projectname, projectid) {
+
+    var return_code = 0;
+    var command;
+
+    // remove existing folder
+    shell.rm('-rf', tmpDir);
+    shell.mkdir(tmpDir);
+
+    // create the project
+    command = util.format('"%s" "%s/%s" "%s" "%s"', createScriptPath, tmpDir, projectname, projectid, projectname);
+
+    return_code = shell.exec(command).code;
+    expect(return_code).toBe(0);
+
+    var platWwwPath = path.join(tmpDir, projectname, 'platform_www');
+
+    var manifestPath = path.join(platWwwPath, 'manifest.json');
+    expect(fs.existsSync(manifestPath)).toBe(true);
+
+    var manifestObj = require(manifestPath);
+    expect(manifestObj.name).toBe(projectname);
+    // start_url
+    expect(manifestObj.start_url).toBe('index.html');
+    // display
+    expect(manifestObj.display).toBe('standalone');
+    // description
+    expect(manifestObj.description).toBeDefined();
+    // background_color
+    expect(manifestObj.background_color).toBeDefined();
+    // theme_color
+    expect(manifestObj.theme_color).toBeDefined();
+    // scope
+    expect(manifestObj.scope).toBeDefined();
+    // orientation
+    expect(manifestObj.orientation).toBeDefined();
+    // icons
+    expect(manifestObj.icons).toBeDefined();
+    expect(Array.isArray(manifestObj.icons)).toBe(true);
+    expect(manifestObj.icons.length).toBeDefined();
+    expect(manifestObj.icons.length).toBeGreaterThan(0);
+
+    // related_applications[{platform:'web'},{platform:'play',url:...}] ?
+
+    // clean-up
+    shell.rm('-rf', tmpDir);
+}
+
+describe('create', function () {
+
+    it('create project with manifest.json', function () {
+        var projectname = 'testcreate';
+        var projectid = 'com.test.app1';
+
+        createAndBuild(projectname, projectid);
+    });
+});
diff --git a/spec/projectApi.spec.js b/spec/projectApi.spec.js
new file mode 100644 (file)
index 0000000..072a1d8
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+var Api = require('../bin/template/cordova/Api');
+var shell = require('shelljs');
+var path = require('path');
+var tmpDir = path.join(__dirname, './temp');
+
+describe('can get the Api', function () {
+
+    it('should be defined', function () {
+        expect(Api).toBeDefined();
+    });
+
+    it('should export static createPlatform function', function (done) {
+        expect(Api.createPlatform).toBeDefined();
+        expect(typeof Api.createPlatform).toBe('function');
+
+        // TODO: make this do something real
+        var promise = Api.createPlatform(tmpDir);
+        expect(promise).toBeDefined();
+        expect(promise.then).toBeDefined();
+        promise.then(function (res) {
+            console.log('result = ' + res);
+            shell.rm('-rf', tmpDir);
+            done();
+        },
+        function (err) {
+            console.log('spec-error ' + err);
+            shell.rm('-rf', tmpDir);
+            done();
+        });
+    });
+
+    it('should export static updatePlatform function', function () {
+        expect(Api.updatePlatform).toBeDefined();
+        expect(typeof Api.updatePlatform).toBe('function');
+    });
+
+});
+
+describe('project level Api', function () {
+
+    var testApi = new Api();
+
+    it('can be created', function () {
+        expect(testApi).toBeDefined();
+    });
+
+    it('has a requirements method', function () {
+        expect(testApi.requirements).toBeDefined();
+        expect(typeof testApi.requirements).toBe('function');
+    });
+
+    it('has a clean method', function () {
+        expect(testApi.clean).toBeDefined();
+        expect(typeof testApi.clean).toBe('function');
+    });
+
+    it('has a run method', function () {
+        expect(testApi.run).toBeDefined();
+        expect(typeof testApi.run).toBe('function');
+    });
+
+    it('has a build method', function () {
+        expect(testApi.build).toBeDefined();
+        expect(typeof testApi.build).toBe('function');
+    });
+
+    it('has a removePlugin method', function () {
+        expect(testApi.removePlugin).toBeDefined();
+        expect(typeof testApi.removePlugin).toBe('function');
+    });
+
+    it('has a addPlugin method', function () {
+        expect(testApi.addPlugin).toBeDefined();
+        expect(typeof testApi.addPlugin).toBe('function');
+    });
+
+    it('has a prepare method', function () {
+        expect(testApi.prepare).toBeDefined();
+        expect(typeof testApi.prepare).toBe('function');
+    });
+
+    it('has a getPlatformInfo method', function () {
+        expect(testApi.getPlatformInfo).toBeDefined();
+        expect(typeof testApi.getPlatformInfo).toBe('function');
+    });
+
+});
+
+// Static methods
+// Static method: createPlatform
+// returns promise fulfilled with Api
+// emits error using provided emmitter on error
+
+// Static method: updatePlatform
+// returns a promise fulfilled with an Api
+// emits error using provided emmitter on error
+
+// Instance methods
+// requirements, clean, run, build, removePlugin, addPlugin, prepare, getPlatformInfo
diff --git a/spec/support/jasmine.json b/spec/support/jasmine.json
new file mode 100644 (file)
index 0000000..7122dfd
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "spec_dir": "spec",
+    "spec_files": [
+       "*[sS]pec.js"
+    ],
+    "helpers": [
+    ],
+    "stopSpecOnExpectationFailure": false,
+    "random": false
+}
\ No newline at end of file