[
  {
    "path": ".asf.yaml",
    "content": "# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n\nnotifications:\n  commits:              commits@cordova.apache.org\n  issues:               issues@cordova.apache.org\n  pullrequests_status:  issues@cordova.apache.org\n  pullrequests_comment: issues@cordova.apache.org\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n\n* text eol=lf\n\n# source code\n*.php text\n*.css text\n*.sass text\n*.scss text\n*.less text\n*.styl text\n*.js text\n*.coffee text\n*.json text\n*.htm text\n*.html text\n*.xml text\n*.svg text\n*.txt text\n*.ini text\n*.inc text\n*.pl text\n*.rb text\n*.py text\n*.scm text\n*.sql text\n*.sh text\n*.bat text\n\n# templates\n*.ejs text\n*.hbt text\n*.jade text\n*.haml text\n*.hbs text\n*.dot text\n*.tmpl text\n*.phtml text\n\n# server config\n.htaccess text\n\n# git config\n.gitattributes text\n.gitignore text\n.gitconfig text\n\n# code analysis config\n.jshintrc text\n.jscsrc text\n.jshintignore text\n.csslintrc text\n\n# misc config\n*.yaml text\n*.yml text\n.editorconfig text\n\n# build config\n*.npmignore text\n*.bowerrc text\n\n# Heroku\nProcfile text\n.slugignore text\n\n# Documentation\n*.md text\nLICENSE text\nAUTHORS text\n\n\n#\n## These files are binary and should be left untouched\n#\n\n# (binary is a macro for -text -diff)\n*.png binary\n*.jpg binary\n*.jpeg binary\n*.gif binary\n*.ico binary\n*.mov binary\n*.mp4 binary\n*.mp3 binary\n*.flv binary\n*.fla binary\n*.swf binary\n*.gz binary\n*.zip binary\n*.7z binary\n*.ttf binary\n*.eot binary\n*.woff binary\n*.pyc binary\n*.pdf binary\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/BUG_REPORT.md",
    "content": "---\nname: 🐛 Bug Report\nabout: If something isn't working as expected.\n\n---\n\n# Bug Report\n\n## Problem\n\n### What is expected to happen?\n\n\n\n### What does actually happen?\n\n\n\n## Information\n<!-- Include all relevant information that might help understand and reproduce the problem -->\n\n\n\n### Command or Code\n<!-- What command or code is needed to reproduce the problem? -->\n\n\n\n### Environment, Platform, Device\n<!-- In what environment, on what platform or on which device are you experiencing the issue? -->\n\n\n\n### Version information\n<!-- \nWhat are relevant versions you are using?\nFor example:\nCordova: Cordova CLI, Cordova Platforms, Cordova Plugins \nOther Frameworks: Ionic Framework and CLI version\nOperating System, Android Studio, Xcode etc.\n-->\n\n\n\n## Checklist\n<!-- Please check the boxes by putting an x in the [ ] like so: [x] -->\n\n- [ ] I searched for existing GitHub issues\n- [ ] I updated all Cordova tooling to most recent version\n- [ ] I included all the necessary information above\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/FEATURE_REQUEST.md",
    "content": "---\nname: 🚀 Feature Request\nabout: A suggestion for a new functionality\n\n---\n\n# Feature Request\n\n## Motivation Behind Feature\n<!-- Why should this feature be implemented? What problem does it solve? -->\n\n\n\n## Feature Description\n<!-- \nDescribe your feature request in detail\nPlease provide any code examples or screenshots of what this feature would look like\nAre there any drawbacks? Will this break anything for existing users? \n-->\n\n\n\n## Alternatives or Workarounds\n<!-- \nDescribe alternatives or workarounds you are currently using \nAre there ways to do this with existing functionality?\n-->\n\n\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/SUPPORT_QUESTION.md",
    "content": "---\nname: 💬 Support Question\nabout: If you have a question, please check out our Slack or StackOverflow!\n\n---\n\n<!------------^ Click \"Preview\" for a nicer view! -->\n\nApache Cordova uses GitHub Issues as a feature request and bug tracker _only_.\nFor usage and support questions, please check out the resources below. Thanks!\n\n---\n\nYou can get answers to your usage and support questions about **Apache Cordova** on:\n\n* Slack Community Chat: https://cordova.slack.com (you can sign-up at http://slack.cordova.io/)\n* StackOverflow: https://stackoverflow.com/questions/tagged/cordova using the tag `cordova`\n\n---\n\nIf you are using a tool that uses Cordova internally, like e.g. Ionic, check their support channels:\n\n* **Ionic Framework**\n  * [Ionic Community Forum](https://forum.ionicframework.com/)\n  * [Ionic Worldwide Slack](https://ionicworldwide.herokuapp.com/)\n* **PhoneGap**\n  * [PhoneGap Developer Community](https://forums.adobe.com/community/phonegap)\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "<!--\nPlease have a look at the issue templates you get when you click \"New issue\" in the GitHub UI.\nWe very much prefer issues created by using one of these templates.\n-->\n\n### Issue Type\n<!-- Please check the boxes by putting an x in the [ ] like so: [x] -->\n\n- [ ] Bug Report\n- [ ] Feature Request\n- [ ] Support Question\n\n## Description\n\n## Information\n<!-- Include all relevant information that might help understand and reproduce the problem -->\n\n### Command or Code\n<!-- What command or code is needed to reproduce the problem? -->\n\n### Environment, Platform, Device\n<!-- In what environment, on what platform or on which device are you experiencing the issue? -->\n\n\n\n### Version information\n<!-- \nWhat are relevant versions you are using?\nFor example:\nCordova: Cordova CLI, Cordova Platforms, Cordova Plugins \nOther Frameworks: Ionic Framework and CLI version\nOperating System, Android Studio, Xcode etc.\n-->\n\n\n\n## Checklist\n<!-- Please check the boxes by putting an `x` in the `[ ]` like so: `[x]` -->\n\n- [ ] I searched for already existing GitHub issues about this\n- [ ] I updated all Cordova tooling to their most recent version\n- [ ] I included all the necessary information above\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--\nPlease make sure the checklist boxes are all checked before submitting the PR. The checklist is intended as a quick reference, for complete details please see our Contributor Guidelines:\n\nhttp://cordova.apache.org/contribute/contribute_guidelines.html\n\nThanks!\n-->\n\n### Platforms affected\n\n\n\n### Motivation and Context\n<!-- Why is this change required? What problem does it solve? -->\n<!-- If it fixes an open issue, please link to the issue here. -->\n\n\n\n### Description\n<!-- Describe your changes in detail -->\n\n\n\n### Testing\n<!-- Please describe in detail how you tested your changes. -->\n\n\n\n### Checklist\n\n- [ ] I've run the tests to see all new and existing tests pass\n- [ ] I added automated test coverage as appropriate for this change\n- [ ] Commit is prefixed with `(platform)` if this change only applies to one platform (e.g. `(android)`)\n- [ ] If this Pull Request resolves an issue, I linked to the issue in the text above (and used the correct [keyword to close issues using keywords](https://help.github.com/articles/closing-issues-using-keywords/))\n- [ ] I've updated the documentation if necessary\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n\nname: Node CI\n\non:\n  push:\n    branches-ignore:\n      - 'dependabot/**'\n  pull_request:\n    branches:\n      - '*'\n\npermissions:\n  contents: read\n  security-events: write\n\njobs:\n  test:\n    name: NodeJS ${{ matrix.node-version }} on ${{ matrix.os }}\n\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      matrix:\n        node-version: [20.x, 22.x, 24.x]\n        os: [ubuntu-latest, windows-latest, macos-15]\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n\n      - name: Environment Information\n        run: |\n          node --version\n          npm --version\n\n      # \"bin/template/www/cordova.js\" is ignored because it is a generated file.\n      # It contains mixed content from the npm package \"cordova-js\" and \"./cordova-js-src\".\n      # The report might not be resolvable because of the external package.\n      # If the report is related to this repository, it would be detected when scanning \"./cordova-js-src\".\n      - uses: github/codeql-action/init@v3\n        with:\n          languages: javascript\n          queries: security-and-quality\n          config: |\n            paths-ignore:\n              - coverage\n              - node_modules\n              - bin/template/www/cordova.js\n\n      - name: npm install and test\n        run: |\n          npm i\n          npm t\n        env:\n          CI: true\n\n      - uses: github/codeql-action/analyze@v3\n\n      # v4.6.0\n      - uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238\n        if: success()\n        with:\n          name: ${{ runner.os }} node.js ${{ matrix.node-version }}\n          token: ${{ secrets.CORDOVA_CODECOV_TOKEN }}\n          fail_ci_if_error: false\n"
  },
  {
    "path": ".github/workflows/release-audit.yml",
    "content": "# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n\nname: Release Auditing\n\non:\n  push:\n    branches-ignore:\n      - 'dependabot/**'\n  pull_request:\n    branches:\n      - '*'\n\npermissions:\n  contents: read\n\njobs:\n  test:\n    name: Audit Licenses\n    runs-on: ubuntu-latest\n    steps:\n      # Checkout project\n      - uses: actions/checkout@v6\n\n      # Check license headers (v2.0.0)\n      - uses: erisu/apache-rat-action@46fb01ce7d8f76bdcd7ab10e7af46e1ea95ca01c\n\n      # Setup environment with node\n      - uses: actions/setup-node@v6\n        with:\n          node-version: 24\n\n      # Install node packages\n      - name: npm install packages\n        run: npm ci\n\n      # Check node package licenses (v2.0.1)\n      - uses: erisu/license-checker-action@99cffa11264fe545fd0baa6c13bca5a00ae608f2\n        with:\n          license-config: 'licence_checker.yml'\n          include-asf-category-a: true\n"
  },
  {
    "path": ".gitignore",
    "content": "# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n\n# System\n.DS_Store\n\n# IDE\n.vscode\n\n# npm\nnpm-debug.log\nnode_modules/\n\n# Testing, code coverage, and linting output\ncoverage/\n.nyc_output/\ntemp\n\n# Output of 'npm pack'\n*.tgz\n\n# Other\nbin/template/www/cordova.js\n"
  },
  {
    "path": ".npmignore",
    "content": "# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n\n# Config related files\n.*\n\n# Testing, code coverage, and linting\ncoverage\nspec\neslint.config.js\nlicence_checker.yml\n\n# Logging\nlogs\n*.log\nnpm-debug.log*\n\n# Output of 'npm pack'\n*.tgz\n\n# others\ncordova-js-src\n"
  },
  {
    "path": ".npmrc",
    "content": "# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n\nregistry=https://registry.npmjs.org\n"
  },
  {
    "path": ".ratignore",
    "content": "# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n\n.git/\ncoverage/\nnode_modules/\nVERSION\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "<!--\n#\n# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n#\n-->\n\n# Contributing to Apache Cordova\n\nAnyone can contribute to Cordova. And we need your contributions.\n\nThere are multiple ways to contribute: report bugs, improve the docs, and\ncontribute code.\n  \nFor instructions on this, start with the\n[contribution overview](http://cordova.apache.org/contribute/).\n\nThe details are explained there, but the important items are:\n - Check for Github issues that corresponds to your contribution and link or create them if necessary.\n - Run the tests so your patch doesn't break existing functionality.\n\nWe look forward to your contributions!\n\n"
  },
  {
    "path": "LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "NOTICE",
    "content": "Apache Cordova\nCopyright 2012-2015 The Apache Software Foundation\n\nThis product includes software developed at\nThe Apache Software Foundation (http://www.apache.org/).\n"
  },
  {
    "path": "README.md",
    "content": "<!--\n#\n# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n#\n-->\n\n[![Node CI](https://github.com/apache/cordova-browser/workflows/Node%20CI/badge.svg?branch=master)](https://github.com/apache/cordova-browser/actions?query=branch%3Amaster)\n[![codecov.io](https://codecov.io/github/apache/cordova-browser/coverage.svg?branch=master)](https://codecov.io/github/apache/cordova-browser?branch=master)\n\n# Cordova Browser\n\nTarget modern web browsers to build Apache Cordova based applications.\n\n# Goals\n\n- Browser targeted deployment\n- Surfacing native platform incompatibilities from the open web platform\n\n# PWA support\n\n## cordova-browser now includes support for progressive web apps (PWAs)\n\n- if your project supplies a `manifest.json` in the `www/` dir, it will be used\n    - a `manifest.json` will be generated otherwise\n- if your js code registers a service worker, it will also be used\n\n\n"
  },
  {
    "path": "RELEASENOTES.md",
    "content": "<!--\n#\n# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n#\n-->\n\n## Release Notes for Cordova Browser ##\n\n### 7.0.0 (May 13, 2023)\n\n#### Breaking Changes\n\n* [GH-121](https://github.com/apache/cordova-browser/pull/121) Minimum NodeJS Required: 16.13.0\n* [GH-115](https://github.com/apache/cordova-browser/pull/115) Update ShellJS to 0.8.5.\n* [GH-78](https://github.com/apache/cordova-browser/pull/78) feat: Replace `Q` with native Promises.\n\n#### Other Notable Changes\n\n* [GH-117](https://github.com/apache/cordova-browser/pull/117) Added `.npmrc` file to ensure the official NPM registry is used during development and deployments.\n* [GH-107](https://github.com/apache/cordova-browser/pull/107) Enabled `package-lock.json` file.\n* [GH-119](https://github.com/apache/cordova-browser/pull/119) Added NodeJS 20 to our test matrix.\n* [GH-118](https://github.com/apache/cordova-browser/pull/118) Updated ESLint config to match better match Apache Cordova's coding style standards.\n* [GH-80](https://github.com/apache/cordova-browser/pull/80) Enabled CodeCov test coverage\n* [GH-113](https://github.com/apache/cordova-browser/pull/113) Migrated to GitHub Action workflows for our testing CI.\n\nFor a full list of changes, see the [commit history](https://github.com/apache/cordova-browser/compare/rel/6.0.0...4669c4dce952c658ba7eb951ebfcae35b96a56ea)\n\n### 6.0.0 (Feb 01, 2019)\n* [GH-70](https://github.com/apache/cordova-browser/pull/70) Browser Platform Release Preparation (Cordova 9)\n* [GH-68](https://github.com/apache/cordova-browser/pull/68) Copy node_modules if the directory exists\n* [GH-63](https://github.com/apache/cordova-browser/pull/63) Dependency bump cordova-common@^3.0.0\n* [CB-13740](https://issues.apache.org/jira/browse/CB-13740) Return expected promise resolving with array\n* [GH-59](https://github.com/apache/cordova-browser/pull/59) Remove Bundled Dependencies\n* [CB-14073](https://issues.apache.org/jira/browse/CB-14073) **Browser**: Drop Node 4, Added Node 10\n* [CB-14252](https://issues.apache.org/jira/browse/CB-14252) Allow to send --silent arg to run command to disable output (#57)\n* [CB-13999](https://issues.apache.org/jira/browse/CB-13999) (browser) - Reading `config.xml` respects base href (#52)\n* [GH-50](https://github.com/apache/cordova-browser/pull/50) corrected path for `config.xml`\n* [CB-13689](https://issues.apache.org/jira/browse/CB-13689) Updated RELEASENOTES and Version for release 5.0.3\n\n### 5.0.2 (Dec 18, 2017)\n* [CB-13689](https://issues.apache.org/jira/browse/CB-13689): Updated checked-in node_modules\n* [CB-13562](https://issues.apache.org/jira/browse/CB-13562): fixed asset tag when adding push plugin to **Browser**\n\n### 5.0.1 (Oct 16, 2017)\n* [CB-13444](https://issues.apache.org/jira/browse/CB-13444) Updated checked-in `node_modules`\n* [CB-13435](https://issues.apache.org/jira/browse/CB-13435) fix merges directory support for **Browser**\n* [CB-12895](https://issues.apache.org/jira/browse/CB-12895) ignoring `cordova.js` for `eslint`\n\n### 5.0.0 (Aug 24, 2017)\n* [CB-13214](https://issues.apache.org/jira/browse/CB-13214) Updated `cordova-serve` dependnecy to 2.0.0. `cordova serve` command now opens system default browser instead of a new instance of `chrome`. A specific target can still be passed in. \n* [CB-13214](https://issues.apache.org/jira/browse/CB-13214) Updated checked-in `node_modules`\n* [CB-13188](https://issues.apache.org/jira/browse/CB-13188) fixed issues with run and build scripts. \n* [CB-12895](https://issues.apache.org/jira/browse/CB-12895): set up `eslint` and remove `jshint`\n* [CB-11181](https://issues.apache.org/jira/browse/CB-11181) add default favicon\n* [CB-11710](https://issues.apache.org/jira/browse/CB-11710) Add missing 'clean.bat' file\n* remove old `xhr-activex` **Windows** code, update to use `pagevisibility` instead of `webkitpagevisibility`\n* [CB-12804](https://issues.apache.org/jira/browse/CB-12804): `manifest.json` added to **Browser** during create. Adding basic PWA support\n* [CB-12762](https://issues.apache.org/jira/browse/CB-12762) Point repo items to github mirrors\n* Clean up PRs. Closes #2. Closes #25\n* [CB-12617](https://issues.apache.org/jira/browse/CB-12617) : removed node 0.x support and added engineStrict. This closes #27\n* [CB-12847](https://issues.apache.org/jira/browse/CB-12847) added `bugs` entry to `package.json`.\n* [CB-12527](https://issues.apache.org/jira/browse/CB-12527) large refactor. Implemented `PlatformApi`\n* [CB-12114](https://issues.apache.org/jira/browse/CB-12114) added travis and appveyor files\n* Add github pull request template\n\n### 4.0.0 (Aug 13, 2015)\n* updated version in version script\n* added `.ratignore` and added missing AL header to readme\n* removed other platform screens from template\n* updated to 4.0.0-dev\n* [CB-8965](https://issues.apache.org/jira/browse/CB-8965) Copy `cordova-js-src` directory to platform folder during create\n* Adds LICENSE and NOTICE files.\n* [CB-9350](https://issues.apache.org/jira/browse/CB-9350) 'cordova run browser' throws an exception.\n* Update 'cordova run browser' command to use cordova-serve module.\n* [CB-8417](https://issues.apache.org/jira/browse/CB-8417) update platform specific js from cordovajs\n* [CB-8760](https://issues.apache.org/jira/browse/CB-8760) platform list shows wrong version for browser platform.\n* [CB-8182](https://issues.apache.org/jira/browse/CB-8182) port `cordova serve` to `cordova run browser`\n* [CB-8182](https://issues.apache.org/jira/browse/CB-8182) add dependency on `mime` library\n* [CB-8196](https://issues.apache.org/jira/browse/CB-8196) Browser platform `run` should default source file to index.html even if it's missing in the config.xml\n* [CB-8223](https://issues.apache.org/jira/browse/CB-8223) Expose config.xml in the Browser platform\n* [CB-8417](https://issues.apache.org/jira/browse/CB-8417) renamed platform_modules into cordova-js-src\n* [CB-8417](https://issues.apache.org/jira/browse/CB-8417) moved platform specific js into platform\n* [CB-8224](https://issues.apache.org/jira/browse/CB-8224) Add support to launch a specified browser using --target switch. Support for multiple browsers on Windows, Mac and Linux\n* Add Windows specific shim wrappers for shjs - auto-generated by npm install\n* [CB-8206](https://issues.apache.org/jira/browse/CB-8206) Browser platform: Add support for update\n* --user-data-dir working on windows\n* [CB-7978](https://issues.apache.org/jira/browse/CB-7978) Cleaning code and creating temporary dir - Using path.resolve and path.join instead of concatenating paths - Fixing error when temporary dir already exists by using shelljs instead of fs\n* [CB-7978](https://issues.apache.org/jira/browse/CB-7978) Cleaning code and creating temporary dir - Cleaning code - Declaring variables only when needed - Creating chrome for Cordova temp dir prior using it by std and err\n* [CB-7978](https://issues.apache.org/jira/browse/CB-7978) Fixed launching chrome in Linux\n\n### 3.6.0 ###\n* Update JS snapshot to version 3.6.0 (via coho)\n* Set VERSION to 3.6.0 (via coho)\n* added run.bat file\n* added windows run support, still a few issues\n* No longer need to kill Chrome for mac\n* added create.bat for windows support\n* Removed old dependency from source\n* Fixed issue with npm cache when adding browser\n* Fixed directory structure\n* Creating browser project\n* [CB-6818](https://issues.apache.org/jira/browse/CB-6818) Add license for CONTRIBUTING.md\n* [CB-6491](https://issues.apache.org/jira/browse/CB-6491) add CONTRIBUTING.md\n"
  },
  {
    "path": "bin/lib/check_reqs.js",
    "content": "#!/usr/bin/env node\n\n/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\n// add methods as we determine what are the requirements\n\nmodule.exports.run = function () {\n    // caller expects a promise resolved with an array of conditions\n    return Promise.resolve([]);\n};\n"
  },
  {
    "path": "bin/lib/create.js",
    "content": "#!/usr/bin/env node\n\n/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\nconst fs = require('node:fs');\nconst path = require('node:path');\nconst ROOT = path.join(__dirname, '..', '..');\nconst events = require('cordova-common').events;\nconst check_reqs = require('./check_reqs');\n\n// exported method to create a project, returns a promise that resolves with null\nmodule.exports.createProject = function (project_path, package_name, project_name) {\n/*\n    // create the dest and the standard place for our api to live\n    // platforms/platformName/cordova/Api.js\n*/\n\n    events.emit('log', 'Creating Cordova project for cordova-browser:');\n    events.emit('log', '\\tPath: ' + project_path);\n    events.emit('log', '\\tName: ' + project_name);\n\n    // Set default values for path, package and name\n    project_path = project_path || 'CordovaExample';\n\n    // Check if project already exists\n    if (fs.existsSync(project_path)) {\n        events.emit('error', 'Oops, destination already exists! Delete it and try again');\n    } else {\n        fs.mkdirSync(project_path);\n    }\n\n    // Check that requirements are met and proper targets are installed\n    if (!check_reqs.run()) {\n        // TODO: use events.emit\n        events.emit('error', 'Please make sure you meet the software requirements in order to build a browser cordova project');\n    }\n\n    // copy template/* to project_path directory ( recursive )\n    fs.cpSync(path.join(ROOT, 'bin/template'), project_path, { recursive: true });\n\n    // TODO: stop copying cordova-browser logic into platforms/browser/\n    // recreate our node_modules structure in the new project\n    const nodeModulesDir = path.join(ROOT, 'node_modules');\n    if (fs.existsSync(nodeModulesDir)) {\n        fs.cpSync(nodeModulesDir, path.join(project_path, 'cordova/node_modules'), { recursive: true });\n    }\n\n    // copy check_reqs file\n    fs.cpSync(\n        path.join(ROOT, 'bin/lib/check_reqs.js'),\n        path.join(project_path, 'cordova/lib/check_reqs.js')\n    );\n\n    // create platform_www dir if it does not exist yet\n    const platform_www = path.join(project_path, 'platform_www');\n    fs.mkdirSync(platform_www, { recursive: true });\n\n    // copy cordova js file to platform_www\n    fs.cpSync(\n        path.join(ROOT, 'bin/template/www/cordova.js'),\n        path.join(platform_www, 'cordova.js')\n    );\n\n    // copy favicon file to platform_www\n    fs.cpSync(\n        path.join(ROOT, 'bin/template/www/favicon.ico'),\n        path.join(platform_www, 'favicon.ico')\n    );\n\n    // load manifest to write name/shortname\n    const manifest = require(path.join(ROOT, 'bin/template/www', 'manifest.json'));\n    manifest.name = project_name;\n    manifest.short_name = project_name;\n    // copy manifest file to platform_www\n    fs.writeFileSync(path.join(platform_www, 'manifest.json'),\n        JSON.stringify(manifest, null, 2), 'utf-8');\n\n    return Promise.resolve();\n};\n"
  },
  {
    "path": "bin/lib/update.js",
    "content": "/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\nconst create = require('./create');\nconst fs = require('node:fs');\nconst { CordovaError } = require('cordova-common');\n\nmodule.exports.help = function () {\n    console.log('WARNING : Make sure to back up your project before updating!');\n    console.log('Usage: update PathToProject ');\n    console.log('    PathToProject : The path the project you would like to update.');\n    console.log('examples:');\n    console.log('    update C:\\\\Users\\\\anonymous\\\\Desktop\\\\MyProject');\n};\n\nmodule.exports.run = function (argv) {\n    const projectPath = argv[2];\n\n    // If the specified project path is not valid then reject promise.\n    if (!fs.existsSync(projectPath)) {\n        return Promise.reject(new CordovaError(`Browser platform does not exist here: ${projectPath}`));\n    }\n\n    console.log('Removing existing browser platform.');\n    fs.rmSync(projectPath, { recursive: true, force: true });\n\n    // Create Project returns a resolved promise.\n    return create.createProject(projectPath);\n};\n"
  },
  {
    "path": "bin/template/cordova/Api.js",
    "content": "/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\n/*\n    this file is found by cordova-lib when you attempt to\n    'cordova platform add PATH' where path is this repo.\n*/\n\nconst path = require('node:path');\nconst fs = require('node:fs');\n\nconst cdvcmn = require('cordova-common');\nconst CordovaLogger = cdvcmn.CordovaLogger;\nconst ConfigParser = cdvcmn.ConfigParser;\nconst ActionStack = cdvcmn.ActionStack;\nconst selfEvents = cdvcmn.events;\nconst xmlHelpers = cdvcmn.xmlHelpers;\nconst PlatformJson = cdvcmn.PlatformJson;\nconst PlatformMunger = cdvcmn.ConfigChanges.PlatformMunger;\nconst PluginInfoProvider = cdvcmn.PluginInfoProvider;\nconst CordovaError = cdvcmn.CordovaError;\nconst FileUpdater = cdvcmn.FileUpdater;\n\nconst PLATFORM_NAME = 'browser';\n\nfunction setupEvents (externalEventEmitter) {\n    if (externalEventEmitter) {\n        // This will make the platform internal events visible outside\n        selfEvents.forwardEventsTo(externalEventEmitter);\n        return externalEventEmitter;\n    }\n\n    // There is no logger if external emitter is not present,\n    // so attach a console logger\n    CordovaLogger.get().subscribe(selfEvents);\n    return selfEvents;\n}\n\n/**\n * Logs all file operations via the verbose event stream, indented.\n */\nfunction logFileOp (message) {\n    selfEvents.emit('verbose', '  ' + message);\n}\n\nfunction dirExists (dir) {\n    return fs.existsSync(dir) && fs.statSync(dir).isDirectory();\n}\n\nfunction Api (platform, platformRootDir, events) {\n    this.platform = platform || PLATFORM_NAME;\n\n    // MyApp/platforms/browser\n    this.root = path.resolve(__dirname, '..');\n    this.events = setupEvents(events);\n    if (!dirExists(this.root) || !dirExists(path.join(this.root, 'cordova'))) {\n        throw new CordovaError('The provided path \"' + this.root + '\" is not a valid browser project.');\n    }\n    this._handler = require('./browser_handler');\n\n    this.locations = {\n        platformRootDir,\n        root: this.root,\n        www: path.join(this.root, 'www'),\n        res: path.join(this.root, 'res'),\n        platformWww: path.join(this.root, 'platform_www'),\n        configXml: path.join(this.root, 'config.xml'),\n        defaultConfigXml: path.join(this.root, 'cordova/defaults.xml'),\n        build: path.join(this.root, 'build'),\n        // NOTE: Due to platformApi spec we need to return relative paths here\n        cordovaJs: 'bin/templates/project/assets/www/cordova.js',\n        cordovaJsSrc: 'cordova-js-src'\n    };\n\n    this._platformJson = PlatformJson.load(this.root, platform);\n    this._pluginInfoProvider = new PluginInfoProvider();\n    this._munger = new PlatformMunger(platform, this.root, this._platformJson, this._pluginInfoProvider);\n}\n\nApi.createPlatform = function (dest, config, options, events) {\n    const creator = require('../../lib/create');\n    events = setupEvents(events);\n\n    let name = 'HelloCordova';\n    let id = 'io.cordova.hellocordova';\n    if (config) {\n        name = config.name();\n        id = config.packageName();\n    }\n\n    let result;\n    try {\n        // we create the project using our scripts in this platform\n        result = creator.createProject(dest, id, name, options)\n            .then(function () {\n                // after platform is created we return Api instance based on new Api.js location\n                // Api.js has been copied to the new project\n                // This is required to correctly resolve paths in the future api calls\n                const PlatformApi = require(path.resolve(dest, 'cordova/Api'));\n                return new PlatformApi('browser', dest, events);\n            });\n    } catch (e) {\n        events.emit('error', 'createPlatform is not callable from the browser project API.');\n        throw (e);\n    }\n    return result;\n};\n\nApi.updatePlatform = function (dest, options, events) {\n    // console.log(\"test-platform:Api:updatePlatform\");\n    // todo?: create projectInstance and fulfill promise with it.\n    return Promise.resolve();\n};\n\nApi.prototype.getPlatformInfo = function () {\n    // console.log(\"browser-platform:Api:getPlatformInfo\");\n    // return PlatformInfo object\n    return {\n        locations: this.locations,\n        root: this.root,\n        name: this.platform,\n        version: { version: '1.0.0' }, // um, todo!\n        projectConfig: this.config\n    };\n};\n\nApi.prototype.prepare = async function (cordovaProject, options) {\n    // First cleanup current config and merge project's one into own\n    const defaultConfigPath = path.join(this.locations.platformRootDir, 'cordova',\n        'defaults.xml');\n    const ownConfigPath = this.locations.configXml;\n    const sourceCfg = cordovaProject.projectConfig;\n\n    // If defaults.xml is present, overwrite platform config.xml with it.\n    // Otherwise save whatever is there as defaults so it can be\n    // restored or copy project config into platform if none exists.\n    if (fs.existsSync(defaultConfigPath)) {\n        this.events.emit('verbose', 'Generating config.xml from defaults for platform \"' + this.platform + '\"');\n        fs.cpSync(defaultConfigPath, ownConfigPath, { force: true });\n    } else if (fs.existsSync(ownConfigPath)) {\n        this.events.emit('verbose', 'Generating defaults.xml from own config.xml for platform \"' + this.platform + '\"');\n        fs.cpSync(ownConfigPath, defaultConfigPath, { force: true });\n    } else {\n        this.events.emit('verbose', 'case 3\"' + this.platform + '\"');\n        fs.cpSync(sourceCfg.path, ownConfigPath, { force: true });\n    }\n\n    // merge our configs\n    this.config = new ConfigParser(ownConfigPath);\n    xmlHelpers.mergeXml(cordovaProject.projectConfig.doc.getroot(),\n        this.config.doc.getroot(),\n        this.platform, true);\n    this.config.write();\n\n    // Update own www dir with project's www assets and plugins' assets and js-files\n    this._updateWww(cordovaProject);\n\n    // Copy or Create manifest.json\n    // todo: move this to a manifest helper module\n    // output path\n    const manifestPath = path.join(this.locations.www, 'manifest.json');\n    const srcManifestPath = path.join(cordovaProject.locations.www, 'manifest.json');\n    if (fs.existsSync(srcManifestPath)) {\n        // just blindly copy it to our output/www\n        // todo: validate it? ensure all properties we expect exist?\n        this.events.emit('verbose', 'copying ' + srcManifestPath + ' => ' + manifestPath);\n        fs.cpSync(srcManifestPath, manifestPath, { force: true });\n    } else {\n        const manifestJson = {\n            background_color: '#FFF',\n            display: 'standalone'\n        };\n        if (this.config) {\n            if (this.config.name()) {\n                manifestJson.name = this.config.name();\n            }\n            if (this.config.shortName()) {\n                manifestJson.short_name = this.config.shortName();\n            }\n            if (this.config.packageName()) {\n                manifestJson.version = this.config.packageName();\n            }\n            if (this.config.description()) {\n                manifestJson.description = this.config.description();\n            }\n            if (this.config.author()) {\n                manifestJson.author = this.config.author();\n            }\n            // icons\n            const icons = this.config.getStaticResources('browser', 'icon');\n            const manifestIcons = icons.map(function (icon) {\n                // given a tag like this :\n                // <icon src=\"res/ios/icon.png\" width=\"57\" height=\"57\" density=\"mdpi\" />\n                /* configParser returns icons that look like this :\n                {   src: 'res/ios/icon.png',\n                    target: undefined,\n                    density: 'mdpi',\n                    platform: null,\n                    width: 57,\n                    height: 57\n                } ******/\n                /* manifest expects them to be like this :\n                {   \"src\": \"images/touch/icon-128x128.png\",\n                    \"type\": \"image/png\",\n                    \"sizes\": \"128x128\"\n                } ******/\n                // ?Is it worth looking at file extentions?\n                return {\n                    src: icon.src,\n                    type: 'image/png',\n                    sizes: (icon.width + 'x' + icon.height)\n                };\n            });\n            manifestJson.icons = manifestIcons;\n\n            // orientation\n            // <preference name=\"Orientation\" value=\"landscape\" />\n            const oriPref = this.config.getGlobalPreference('Orientation');\n            if (oriPref) {\n                // if it's a supported value, use it\n                if (['landscape', 'portrait'].indexOf(oriPref) > -1) {\n                    manifestJson.orientation = oriPref;\n                } else { // anything else maps to 'any'\n                    manifestJson.orientation = 'any';\n                }\n            }\n\n            // get start_url\n            const contentNode = this.config.doc.find('content') || { attrib: { src: 'index.html' } }; // sensible default\n            manifestJson.start_url = contentNode.attrib.src;\n\n            // now we get some values from start_url page ...\n            const startUrlPath = path.join(cordovaProject.locations.www, manifestJson.start_url);\n            if (fs.existsSync(startUrlPath)) {\n                const contents = fs.readFileSync(startUrlPath, 'utf-8');\n                // matches <meta name=\"theme-color\" content=\"#FF0044\">\n                const themeColorRegex = /<meta(?=[^>]*name=\"theme-color\")\\s[^>]*content=\"([^>]*)\"/i;\n                const result = themeColorRegex.exec(contents);\n                let themeColor;\n                if (result && result.length >= 2) {\n                    themeColor = result[1];\n                } else { // see if there is a preference in config.xml\n                    // <preference name=\"StatusBarBackgroundColor\" value=\"#000000\" />\n                    themeColor = this.config.getGlobalPreference('StatusBarBackgroundColor');\n                }\n                if (themeColor) {\n                    manifestJson.theme_color = themeColor;\n                }\n            }\n        }\n        fs.writeFileSync(manifestPath, JSON.stringify(manifestJson, null, 2), 'utf8');\n    }\n\n    // Copy munged config.xml to platform www dir\n    fs.cpSync(\n        this.locations.configXml,\n        path.join(this.locations.www, 'config.xml'),\n        { force: true, recursive: true }\n    );\n};\n\n// Replace the www dir with contents of platform_www and app www.\nApi.prototype._updateWww = function (cordovaProject) {\n    // add cordova www and platform_www to sourceDirs\n    const sourceDirs = [\n        path.relative(cordovaProject.root, cordovaProject.locations.www),\n        path.relative(cordovaProject.root, this.locations.platformWww)\n    ];\n\n    // If project contains 'merges' for our platform, use them as another overrides\n    const merges_path = path.join(cordovaProject.root, 'merges', 'browser');\n    if (fs.existsSync(merges_path)) {\n        selfEvents.emit('verbose', 'Found \"merges/browser\" folder. Copying its contents into the browser project.');\n        // add merges/browser to sourceDirs\n        sourceDirs.push(path.join('merges', 'browser'));\n    }\n\n    // targetDir points to browser/www\n    const targetDir = path.relative(cordovaProject.root, this.locations.www);\n    selfEvents.emit('verbose', 'Merging and updating files from [' + sourceDirs.join(', ') + '] to ' + targetDir);\n    FileUpdater.mergeAndUpdateDir(sourceDirs, targetDir, { rootDir: cordovaProject.root }, logFileOp);\n};\n\nApi.prototype.addPlugin = function (pluginInfo, installOptions) {\n    // console.log(new Error().stack);\n    if (!pluginInfo) {\n        return Promise.reject(new Error('The parameter is incorrect. The first parameter ' +\n            'should be valid PluginInfo instance'));\n    }\n\n    installOptions = installOptions || {};\n    installOptions.variables = installOptions.variables || {};\n    // CB-10108 platformVersion option is required for proper plugin installation\n    installOptions.platformVersion = installOptions.platformVersion ||\n        this.getPlatformInfo().version;\n\n    const self = this;\n    const actions = new ActionStack();\n    const projectFile = this._handler.parseProjectFile && this._handler.parseProjectFile(this.root);\n\n    // gather all files needs to be handled during install\n    pluginInfo.getFilesAndFrameworks(this.platform)\n        .concat(pluginInfo.getAssets(this.platform))\n        .concat(pluginInfo.getJsModules(this.platform))\n        .forEach(function (item) {\n            actions.push(actions.createAction(\n                self._getInstaller(item.itemType),\n                [item, pluginInfo.dir, pluginInfo.id, installOptions, projectFile],\n                self._getUninstaller(item.itemType),\n                [item, pluginInfo.dir, pluginInfo.id, installOptions, projectFile]));\n        });\n\n    // run through the action stack\n    return actions.process(this.platform, this.root)\n        .then(function () {\n            if (projectFile) {\n                projectFile.write();\n            }\n\n            // Add PACKAGE_NAME variable into vars\n            if (!installOptions.variables.PACKAGE_NAME) {\n                installOptions.variables.PACKAGE_NAME = self._handler.package_name(self.root);\n            }\n\n            self._munger\n                // Ignore passed `is_top_level` option since platform itself doesn't know\n                // anything about managing dependencies - it's responsibility of caller.\n                .add_plugin_changes(pluginInfo, installOptions.variables, /* is_top_level= */true, /* should_increment= */true)\n                .save_all();\n\n            const targetDir = installOptions.usePlatformWww\n                ? self.getPlatformInfo().locations.platformWww\n                : self.getPlatformInfo().locations.www;\n\n            self._addModulesInfo(pluginInfo, targetDir);\n        });\n};\n\nApi.prototype.removePlugin = function (plugin, uninstallOptions) {\n    // console.log(\"NotImplemented :: browser-platform:Api:removePlugin \",plugin, uninstallOptions);\n\n    uninstallOptions = uninstallOptions || {};\n    // CB-10108 platformVersion option is required for proper plugin installation\n    uninstallOptions.platformVersion = uninstallOptions.platformVersion ||\n        this.getPlatformInfo().version;\n\n    const self = this;\n    const actions = new ActionStack();\n    const projectFile = this._handler.parseProjectFile && this._handler.parseProjectFile(this.root);\n\n    // queue up plugin files\n    plugin.getFilesAndFrameworks(this.platform)\n        .concat(plugin.getAssets(this.platform))\n        .concat(plugin.getJsModules(this.platform))\n        .forEach(function (item) {\n            actions.push(actions.createAction(\n                self._getUninstaller(item.itemType), [item, plugin.dir, plugin.id, uninstallOptions, projectFile],\n                self._getInstaller(item.itemType), [item, plugin.dir, plugin.id, uninstallOptions, projectFile]));\n        });\n\n    // run through the action stack\n    return actions.process(this.platform, this.root)\n        .then(function () {\n            if (projectFile) {\n                projectFile.write();\n            }\n\n            self._munger\n                // Ignore passed `is_top_level` option since platform itself doesn't know\n                // anything about managing dependencies - it's responsibility of caller.\n                .remove_plugin_changes(plugin, /* is_top_level= */true)\n                .save_all();\n\n            const targetDir = uninstallOptions.usePlatformWww\n                ? self.getPlatformInfo().locations.platformWww\n                : self.getPlatformInfo().locations.www;\n\n            self._removeModulesInfo(plugin, targetDir);\n            // Remove stale plugin directory\n            // TODO: this should be done by plugin files uninstaller\n            fs.rmSync(\n                path.resolve(self.root, 'Plugins', plugin.id),\n                { force: true, recursive: true }\n            );\n        });\n};\n\nApi.prototype._getInstaller = function (type) {\n    const self = this;\n    return function (item, plugin_dir, plugin_id, options, project) {\n        const installer = self._handler[type];\n\n        if (!installer) {\n            console.log('unrecognized type ' + type);\n        } else {\n            const wwwDest = options.usePlatformWww\n                ? self.getPlatformInfo().locations.platformWww\n                : self._handler.www_dir(self.root);\n\n            if (type === 'asset') {\n                installer.install(item, plugin_dir, wwwDest);\n            } else if (type === 'js-module') {\n                installer.install(item, plugin_dir, plugin_id, wwwDest);\n            } else {\n                installer.install(item, plugin_dir, self.root, plugin_id, options, project);\n            }\n        }\n    };\n};\n\nApi.prototype._getUninstaller = function (type) {\n    const self = this;\n    return function (item, plugin_dir, plugin_id, options, project) {\n        const installer = self._handler[type];\n\n        if (!installer) {\n            console.log('browser plugin uninstall: unrecognized type, skipping : ' + type);\n        } else {\n            const wwwDest = options.usePlatformWww\n                ? self.getPlatformInfo().locations.platformWww\n                : self._handler.www_dir(self.root);\n\n            if (['asset', 'js-module'].indexOf(type) > -1) {\n                return installer.uninstall(item, wwwDest, plugin_id);\n            } else {\n                return installer.uninstall(item, self.root, plugin_id, options, project);\n            }\n        }\n    };\n};\n\n/**\n * Removes the specified modules from list of installed modules and updates\n *   platform_json and cordova_plugins.js on disk.\n *\n * @param   {PluginInfo}  plugin  PluginInfo instance for plugin, which modules\n *   needs to be added.\n * @param   {String}  targetDir  The directory, where updated cordova_plugins.js\n *   should be written to.\n */\nApi.prototype._addModulesInfo = function (plugin, targetDir) {\n    const installedModules = this._platformJson.root.modules || [];\n\n    const installedPaths = installedModules.map(function (installedModule) {\n        return installedModule.file;\n    });\n\n    const modulesToInstall = plugin.getJsModules(this.platform)\n        .filter(function (moduleToInstall) {\n            return installedPaths.indexOf(moduleToInstall.file) === -1;\n        }).map(function (moduleToInstall) {\n            const moduleName = plugin.id + '.' + (moduleToInstall.name || moduleToInstall.src.match(/([^/]+)\\.js/)[1]);\n            const obj = {\n                file: ['plugins', plugin.id, moduleToInstall.src].join('/'),\n                id: moduleName,\n                pluginId: plugin.id\n            };\n            if (moduleToInstall.clobbers.length > 0) {\n                obj.clobbers = moduleToInstall.clobbers.map(function (o) { return o.target; });\n            }\n            if (moduleToInstall.merges.length > 0) {\n                obj.merges = moduleToInstall.merges.map(function (o) { return o.target; });\n            }\n            if (moduleToInstall.runs) {\n                obj.runs = true;\n            }\n\n            return obj;\n        });\n\n    this._platformJson.root.modules = installedModules.concat(modulesToInstall);\n    if (!this._platformJson.root.plugin_metadata) {\n        this._platformJson.root.plugin_metadata = {};\n    }\n    this._platformJson.root.plugin_metadata[plugin.id] = plugin.version;\n\n    this._writePluginModules(targetDir);\n    this._platformJson.save();\n};\n/**\n * Fetches all installed modules, generates cordova_plugins contents and writes\n *   it to file.\n *\n * @param   {String}  targetDir  Directory, where write cordova_plugins.js to.\n *   Ususally it is either <platform>/www or <platform>/platform_www\n *   directories.\n */\nApi.prototype._writePluginModules = function (targetDir) {\n    // Write out moduleObjects as JSON wrapped in a cordova module to cordova_plugins.js\n    let final_contents = 'cordova.define(\\'cordova/plugin_list\\', function(require, exports, module) {\\n';\n    final_contents += 'module.exports = ' + JSON.stringify(this._platformJson.root.modules, null, '    ') + ';\\n';\n    final_contents += 'module.exports.metadata = \\n';\n    final_contents += '// TOP OF METADATA\\n';\n    final_contents += JSON.stringify(this._platformJson.root.plugin_metadata || {}, null, '    ') + '\\n';\n    final_contents += '// BOTTOM OF METADATA\\n';\n    final_contents += '});'; // Close cordova.define.\n\n    fs.mkdirSync(targetDir, { recursive: true });\n    fs.writeFileSync(path.join(targetDir, 'cordova_plugins.js'), final_contents, 'utf-8');\n};\n\n/**\n * Removes the specified modules from list of installed modules and updates\n *   platform_json and cordova_plugins.js on disk.\n *\n * @param   {PluginInfo}  plugin  PluginInfo instance for plugin, which modules\n *   needs to be removed.\n * @param   {String}  targetDir  The directory, where updated cordova_plugins.js\n *   should be written to.\n */\nApi.prototype._removeModulesInfo = function (plugin, targetDir) {\n    const installedModules = this._platformJson.root.modules || [];\n    const modulesToRemove = plugin.getJsModules(this.platform)\n        .map(function (jsModule) {\n            return ['plugins', plugin.id, jsModule.src].join('/');\n        });\n\n    const updatedModules = installedModules\n        .filter(function (installedModule) {\n            return (modulesToRemove.indexOf(installedModule.file) === -1);\n        });\n\n    this._platformJson.root.modules = updatedModules;\n    if (this._platformJson.root.plugin_metadata) {\n        delete this._platformJson.root.plugin_metadata[plugin.id];\n    }\n\n    this._writePluginModules(targetDir);\n    this._platformJson.save();\n};\n\nApi.prototype.build = function (buildOptions) {\n    const self = this;\n    return require('./lib/check_reqs').run()\n        .then(function () {\n            return require('./lib/build').run.call(self, buildOptions);\n        });\n};\n\nApi.prototype.run = function (runOptions) {\n    return require('./lib/run').run(runOptions);\n};\n\nApi.prototype.clean = function (cleanOptions) {\n    return require('./lib/clean').run(cleanOptions);\n};\n\nApi.prototype.requirements = function () {\n    return require('./lib/check_reqs').run();\n};\n\nmodule.exports = Api;\n"
  },
  {
    "path": "bin/template/cordova/browser_handler.js",
    "content": "/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\nconst path = require('node:path');\nconst fs = require('node:fs');\nconst events = require('cordova-common').events;\n\nmodule.exports = {\n    www_dir: function (project_dir) {\n        return path.join(project_dir, 'www');\n    },\n    package_name: function (project_dir) {\n        // this method should the id from root config.xml => <widget id=xxx\n        // return common.package_name(project_dir, this.www_dir(project_dir));\n        // console.log('package_name called with ' + project_dir);\n        let pkgName = 'io.cordova.hellocordova';\n        const widget_id_regex = /(?:<widget\\s+id=['\"])(\\S+)(?:['\"])/;\n\n        const configPath = path.join(project_dir, 'config.xml');\n        if (fs.existsSync(configPath)) {\n            const configStr = fs.readFileSync(configPath, 'utf8');\n            const res = configStr.match(widget_id_regex);\n            if (res && res.length > 1) {\n                pkgName = res[1];\n            }\n        }\n        return pkgName;\n    },\n    'js-module': {\n        install: function (jsModule, plugin_dir, plugin_id, www_dir) {\n            // Copy the plugin's files into the www directory.\n            const moduleSource = path.resolve(plugin_dir, jsModule.src);\n            // Get module name based on existing 'name' attribute or filename\n            // Must use path.extname/path.basename instead of path.parse due to CB-9981\n            const moduleName = plugin_id + '.' + (jsModule.name || path.basename(jsModule.src, path.extname(jsModule.src)));\n\n            // Read in the file, prepend the cordova.define, and write it back out.\n            let scriptContent = fs.readFileSync(moduleSource, 'utf-8').replace(/^\\ufeff/, ''); // Window BOM\n            if (moduleSource.match(/.*\\.json$/)) {\n                scriptContent = 'module.exports = ' + scriptContent;\n            }\n            scriptContent = 'cordova.define(\"' + moduleName + '\", function(require, exports, module) { ' + scriptContent + '\\n});\\n';\n\n            const moduleDestination = path.resolve(www_dir, 'plugins', plugin_id, jsModule.src);\n            fs.mkdirSync(path.dirname(moduleDestination), { recursive: true });\n            fs.writeFileSync(moduleDestination, scriptContent, 'utf-8');\n        },\n        uninstall: function (jsModule, www_dir, plugin_id) {\n            const pluginRelativePath = path.join('plugins', plugin_id, jsModule.src);\n            // common.removeFileAndParents(www_dir, pluginRelativePath);\n            console.log('js-module uninstall called : ' + pluginRelativePath);\n        }\n    },\n    'source-file': {\n        install: function (obj, plugin_dir, project_dir, plugin_id, options) {\n            // var dest = path.join(obj.targetDir, path.basename(obj.src));\n            // common.copyFile(plugin_dir, obj.src, project_dir, dest);\n            console.log('install called');\n        },\n        uninstall: function (obj, project_dir, plugin_id, options) {\n            // var dest = path.join(obj.targetDir, path.basename(obj.src));\n            // common.removeFile(project_dir, dest);\n            console.log('uninstall called');\n        }\n    },\n    'header-file': {\n        install: function (obj, plugin_dir, project_dir, plugin_id, options) {\n            events.emit('verbose', 'header-fileinstall is not supported for browser');\n        },\n        uninstall: function (obj, project_dir, plugin_id, options) {\n            events.emit('verbose', 'header-file.uninstall is not supported for browser');\n        }\n    },\n    'resource-file': {\n        install: function (obj, plugin_dir, project_dir, plugin_id, options) {\n            events.emit('verbose', 'resource-file.install is not supported for browser');\n        },\n        uninstall: function (obj, project_dir, plugin_id, options) {\n            events.emit('verbose', 'resource-file.uninstall is not supported for browser');\n        }\n    },\n    framework: {\n        install: function (obj, plugin_dir, project_dir, plugin_id, options) {\n            events.emit('verbose', 'framework.install is not supported for browser');\n        },\n        uninstall: function (obj, project_dir, plugin_id, options) {\n            events.emit('verbose', 'framework.uninstall is not supported for browser');\n        }\n    },\n    'lib-file': {\n        install: function (obj, plugin_dir, project_dir, plugin_id, options) {\n            events.emit('verbose', 'lib-file.install is not supported for browser');\n        },\n        uninstall: function (obj, project_dir, plugin_id, options) {\n            events.emit('verbose', 'lib-file.uninstall is not supported for browser');\n        }\n    },\n    asset: {\n        install: function (asset, plugin_dir, wwwDest) {\n            const src = path.join(plugin_dir, asset.src);\n            const dest = path.join(wwwDest, asset.target);\n            const destDir = path.parse(dest).dir;\n            if (destDir !== '' && !fs.existsSync(destDir)) {\n                fs.mkdirSync(destDir, { recursive: true });\n            }\n\n            if (fs.statSync(src).isDirectory()) {\n                fs.cpSync(src, dest, { recursive: true, force: true });\n            } else {\n                fs.cpSync(src, dest, { force: true });\n            }\n        },\n        uninstall: function (asset, wwwDest, plugin_id) {\n            fs.rmSync(path.join(wwwDest, asset.target), { recursive: true, force: true });\n            fs.rmSync(path.join(wwwDest, 'plugins', plugin_id), { recursive: true, force: true });\n        }\n    }\n};\n"
  },
  {
    "path": "bin/template/cordova/browser_parser.js",
    "content": "/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\nconst fs = require('node:fs');\nconst path = require('node:path');\nconst CordovaError = require('cordova-common').CordovaError;\nconst events = require('cordova-common').events;\nconst FileUpdater = require('cordova-common').FileUpdater;\n\nfunction dirExists (dir) {\n    return fs.existsSync(dir) && fs.statSync(dir).isDirectory();\n}\n\nfunction browser_parser (project) {\n    if (!dirExists(project) || !dirExists(path.join(project, 'cordova'))) {\n        throw new CordovaError('The provided path \"' + project + '\" is not a valid browser project.');\n    }\n    this.path = project;\n}\n\nmodule.exports = browser_parser;\n\nbrowser_parser.prototype.www_dir = function () {\n    return path.join(this.path, 'www');\n};\n\n/**\n * Logs all file operations via the verbose event stream, indented.\n */\nfunction logFileOp (message) {\n    events.emit('verbose', '  ' + message);\n}\n\n// Replace the www dir with contents of platform_www and app www.\nbrowser_parser.prototype.update_www = function (cordovaProject, opts) {\n    const platform_www = path.join(this.path, 'platform_www');\n    const my_www = this.www_dir();\n    // add cordova www and platform_www to sourceDirs\n    const sourceDirs = [\n        path.relative(cordovaProject.root, cordovaProject.locations.www),\n        path.relative(cordovaProject.root, platform_www)\n    ];\n\n    // If project contains 'merges' for our platform, use them as another overrides\n    const merges_path = path.join(cordovaProject.root, 'merges', 'browser');\n    if (fs.existsSync(merges_path)) {\n        events.emit('verbose', 'Found \"merges/browser\" folder. Copying its contents into the browser project.');\n        // add merges/browser to sourceDirs\n        sourceDirs.push(path.join('merges', 'browser'));\n    }\n\n    // targetDir points to browser/www\n    const targetDir = path.relative(cordovaProject.root, my_www);\n    events.emit('verbose', 'Merging and updating files from [' + sourceDirs.join(', ') + '] to ' + targetDir);\n    FileUpdater.mergeAndUpdateDir(sourceDirs, targetDir, { rootDir: cordovaProject.root }, logFileOp);\n};\n\nbrowser_parser.prototype.config_xml = function () {\n    return path.join(this.path, 'config.xml');\n};\n\nbrowser_parser.prototype.update_project = async function (cfg) {\n    // Copy munged config.xml to platform www dir\n    fs.cpSync(this.config_xml(), this.www_dir(), { recursive: true, force: true });\n};\n"
  },
  {
    "path": "bin/template/cordova/defaults.xml",
    "content": "<?xml version='1.0' encoding='utf-8'?>\n<!--\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n-->\n<widget id=\"io.cordova.hellocordova\" version=\"0.0.1\" xmlns=\"http://www.w3.org/ns/widgets\" xmlns:cdv=\"http://cordova.apache.org/ns/1.0\">\n\n</widget>\n"
  },
  {
    "path": "bin/template/cordova/lib/build.js",
    "content": "#!/usr/bin/env node\n\n/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\nconst path = require('node:path');\nconst check_reqs = require('./check_reqs');\n\n/**\n * run\n *   Creates a zip file int platform/build folder\n */\nmodule.exports.run = function () {\n    return check_reqs.run();\n};\n\nmodule.exports.help = function () {\n    console.log('Usage: cordova build browser');\n    const wwwPath = path.resolve(path.join(__dirname, '../../www'));\n    console.log(\"Build will create the packaged app in '\" + wwwPath + \"'.\");\n};\n"
  },
  {
    "path": "bin/template/cordova/lib/clean.js",
    "content": "#!/usr/bin/env node\n\n/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\nconst fs = require('node:fs');\nconst path = require('node:path');\nconst check_reqs = require('./check_reqs');\nconst platformBuildDir = path.join('platforms', 'browser', 'www');\n\nconst run = function () {\n    // TODO: everything calls check_reqs ... why?\n    // Check that requirements are (still) met\n    if (!check_reqs.run()) {\n        console.error('Please make sure you meet the software requirements in order to clean an browser cordova project');\n        process.exit(2);\n    }\n\n    try {\n        if (fs.existsSync(platformBuildDir)) {\n            fs.rmSync(platformBuildDir, { recursive: true });\n        }\n    } catch (err) {\n        console.log('could not remove ' + platformBuildDir + ' : ' + err.message);\n    }\n};\n\nmodule.exports.run = run;\n// just on the off chance something is still calling cleanProject, we will leave this here for a while\nmodule.exports.cleanProject = function () {\n    console.log('lib/clean will soon only export a `run` command, please update to not call `cleanProject`.');\n    return run();\n};\n"
  },
  {
    "path": "bin/template/cordova/lib/run.js",
    "content": "#!/usr/bin/env node\n\n/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\nconst fs = require('node:fs');\nconst path = require('node:path');\nconst url = require('node:url');\nconst cordovaServe = require('cordova-serve');\n\nmodule.exports.run = function (args) {\n    // defaults\n    args.port = args.port || 8000;\n    args.target = args.target || 'default'; // make default the system browser\n    args.noLogOutput = args.silent || false;\n\n    const wwwPath = path.join(__dirname, '../../www');\n    const manifestFilePath = path.resolve(path.join(wwwPath, 'manifest.json'));\n\n    let startPage;\n\n    // get start page from manifest\n    if (fs.existsSync(manifestFilePath)) {\n        try {\n            const manifest = require(manifestFilePath);\n            startPage = manifest.start_url;\n        } catch (err) {\n            console.log('failed to require manifest ... ' + err);\n        }\n    }\n\n    const server = cordovaServe();\n    server.servePlatform('browser', { port: args.port, noServerInfo: true, noLogOutput: args.noLogOutput })\n        .then(function () {\n            if (!startPage) {\n                // failing all else, set the default\n                startPage = 'index.html';\n            }\n\n            const projectUrl = (new url.URL(`http://localhost:${server.port}/${startPage}`)).href;\n\n            console.log('startPage = ' + startPage);\n            console.log('Static file server running @ ' + projectUrl + '\\nCTRL + C to shut down');\n            return server.launchBrowser({ target: args.target, url: projectUrl });\n        })\n        .catch(function (error) {\n            console.log(error.message || error.toString());\n            if (server.server) {\n                server.server.close();\n            }\n        });\n};\n"
  },
  {
    "path": "bin/template/cordova/version",
    "content": "#!/usr/bin/env node\n\n/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\n// Coho updates this line:\nconst VERSION = '8.0.0-dev';\n\nconsole.log(VERSION);\n"
  },
  {
    "path": "bin/template/www/css/index.css",
    "content": "/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\n* {\n    -webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */\n}\n\nbody {\n    -webkit-touch-callout: none;                /* prevent callout to copy image, etc when tap to hold */\n    -webkit-text-size-adjust: none;             /* prevent webkit from resizing text to fit */\n    -webkit-user-select: none;                  /* prevent copy paste, to allow, change 'none' to 'text' */\n    background-color:#E4E4E4;\n    background-image:linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);\n    background-image:-webkit-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);\n    background-image:-ms-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);\n    background-image:-webkit-gradient(\n        linear,\n        left top,\n        left bottom,\n        color-stop(0, #A7A7A7),\n        color-stop(0.51, #E4E4E4)\n    );\n    background-attachment:fixed;\n    font-family:'HelveticaNeue-Light', 'HelveticaNeue', Helvetica, Arial, sans-serif;\n    font-size:12px;\n    height:100%;\n    margin:0px;\n    padding:0px;\n    text-transform:uppercase;\n    width:100%;\n}\n\n/* Portrait layout (default) */\n.app {\n    background:url(../img/logo.png) no-repeat center top; /* 170px x 200px */\n    position:absolute;             /* position in the center of the screen */\n    left:50%;\n    top:50%;\n    height:50px;                   /* text area height */\n    width:225px;                   /* text area width */\n    text-align:center;\n    padding:180px 0px 0px 0px;     /* image height is 200px (bottom 20px are overlapped with text) */\n    margin:-115px 0px 0px -112px;  /* offset vertical: half of image height and text area height */\n                                   /* offset horizontal: half of text area width */\n}\n\n/* Landscape layout (with min-width) */\n@media screen and (min-aspect-ratio: 1/1) and (min-width:400px) {\n    .app {\n        background-position:left center;\n        padding:75px 0px 75px 170px;  /* padding-top + padding-bottom + text area = image height */\n        margin:-90px 0px 0px -198px;  /* offset vertical: half of image height */\n                                      /* offset horizontal: half of image width and text area width */\n    }\n}\n\nh1 {\n    font-size:24px;\n    font-weight:normal;\n    margin:0px;\n    overflow:visible;\n    padding:0px;\n    text-align:center;\n}\n\n.event {\n    border-radius:4px;\n    -webkit-border-radius:4px;\n    color:#FFFFFF;\n    font-size:12px;\n    margin:0px 30px;\n    padding:2px 0px;\n}\n\n.event.listening {\n    background-color:#333333;\n    display:block;\n}\n\n.event.received {\n    background-color:#4B946A;\n    display:none;\n}\n\n@keyframes fade {\n    from { opacity: 1.0; }\n    50% { opacity: 0.4; }\n    to { opacity: 1.0; }\n}\n \n@-webkit-keyframes fade {\n    from { opacity: 1.0; }\n    50% { opacity: 0.4; }\n    to { opacity: 1.0; }\n}\n \n.blink {\n    animation:fade 3000ms infinite;\n    -webkit-animation:fade 3000ms infinite;\n}\n"
  },
  {
    "path": "bin/template/www/index.html",
    "content": "<!DOCTYPE html>\n<!--\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n-->\n<html>\n    <head>\n        <meta charset=\"utf-8\" />\n        <meta name=\"format-detection\" content=\"telephone=no\" />\n        <meta name=\"theme-color\" content=\"#2196F3\"/>\n        <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\" />\n        <link rel=\"stylesheet\" type=\"text/css\" href=\"css/index.css\" />\n        <link rel=\"manifest\" href=\"manifest.json\">\n        <title>Hello World</title>\n    </head>\n    <body>\n        <div class=\"app\">\n            <h1>Apache Cordova</h1>\n            <div id=\"deviceready\" class=\"blink\">\n                <p class=\"event listening\">Connecting to Device</p>\n                <p class=\"event received\">Device is Ready</p>\n            </div>\n        </div>\n        <script type=\"text/javascript\" src=\"cordova.js\"></script>\n        <script type=\"text/javascript\" src=\"js/index.js\"></script>\n        <script type=\"text/javascript\">\n            app.initialize();\n        </script>\n    </body>\n</html>\n"
  },
  {
    "path": "bin/template/www/js/index.js",
    "content": "/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\nconst app = {\n    // Application Constructor\n    initialize: function () {\n        this.bindEvents();\n    },\n    // Bind Event Listeners\n    //\n    // Bind any events that are required on startup. Common events are:\n    // 'load', 'deviceready', 'offline', and 'online'.\n    bindEvents: function () {\n        document.addEventListener('deviceready', this.onDeviceReady, false);\n    },\n    // deviceready Event Handler\n    //\n    // The scope of 'this' is the event. In order to call the 'receivedEvent'\n    // function, we must explicity call 'app.receivedEvent(...);'\n    onDeviceReady: function () {\n        app.receivedEvent('deviceready');\n    },\n    // Update DOM on a Received Event\n    receivedEvent: function (id) {\n        const parentElement = document.getElementById(id);\n        const listeningElement = parentElement.querySelector('.listening');\n        const receivedElement = parentElement.querySelector('.received');\n\n        listeningElement.setAttribute('style', 'display:none;');\n        receivedElement.setAttribute('style', 'display:block;');\n\n        console.log('Received Event: ' + id);\n    }\n};\n"
  },
  {
    "path": "bin/template/www/manifest.json",
    "content": "{\n  \"name\": \"My App\",\n  \"short_name\":\"My Ap\",\n  \"description\": \"Description of your app from template\",\n  \"start_url\": \"index.html\",\n  \"scope\":\"index.html\",\n  \"icons\": [{\n    \"src\": \"img/logo.png\",\n    \"sizes\": \"192x192\",\n    \"type\": \"image/png\"\n  }, {\n    \"src\": \"img/splash.png\",\n    \"sizes\": \"512x512\",\n    \"type\": \"image/png\"\n  }],\n  \"default_locale\": \"en\",\n  \"display\": \"standalone\",\n  \"background_color\":\"#FFF\",\n  \"theme_color\":\"#000\",\n  \"orientation\": \"landscape\"\n}"
  },
  {
    "path": "cordova-js-src/confighelper.js",
    "content": "/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\nlet config;\n\nfunction Config (xhr) {\n    function loadPreferences (xhr) {\n        const parser = new DOMParser();\n        const doc = parser.parseFromString(xhr.responseText, 'application/xml');\n\n        const preferences = doc.getElementsByTagName('preference');\n        return Array.prototype.slice.call(preferences);\n    }\n\n    this.xhr = xhr;\n    this.preferences = loadPreferences(this.xhr);\n}\n\nfunction readConfig (success, error) {\n    const xhr = new XMLHttpRequest();\n\n    if (typeof config !== 'undefined') {\n        success(config);\n    }\n\n    function fail (msg) {\n        console.error(msg);\n\n        if (error) {\n            error(msg);\n        }\n    }\n\n    const xhrStatusChangeHandler = function () {\n        if (xhr.readyState === 4) {\n            if (xhr.status === 200 || xhr.status === 304 || xhr.status === 0 /* file:// */) {\n                config = new Config(xhr);\n                success(config);\n            } else {\n                fail('[Browser][cordova.js][xhrStatusChangeHandler] Could not XHR config.xml: ' + xhr.statusText);\n            }\n        }\n    };\n\n    xhr.addEventListener('load', xhrStatusChangeHandler);\n\n    try {\n        xhr.open('get', 'config.xml', true);\n        xhr.send();\n    } catch (e) {\n        fail('[Browser][cordova.js][readConfig] Could not XHR config.xml: ' + JSON.stringify(e));\n    }\n}\n\n/**\n * Reads a preference value from config.xml.\n * Returns preference value or undefined if it does not exist.\n * @param {String} preferenceName Preference name to read */\nConfig.prototype.getPreferenceValue = function getPreferenceValue (preferenceName) {\n    const preferenceItem = this.preferences && this.preferences.filter(function (item) {\n        return item.attributes.name && item.attributes.name.value === preferenceName;\n    });\n\n    if (preferenceItem && preferenceItem[0] && preferenceItem[0].attributes && preferenceItem[0].attributes.value) {\n        return preferenceItem[0].attributes.value.value;\n    }\n};\n\nexports.readConfig = readConfig;\n"
  },
  {
    "path": "cordova-js-src/exec.js",
    "content": "/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\n/* jslint sloppy:true, plusplus:true */\n/* global require, module, console */\n\nconst cordova = require('cordova');\nconst execProxy = require('cordova/exec/proxy');\n\n/**\n * Execute a cordova command.  It is up to the native side whether this action\n * is synchronous or asynchronous.  The native side can return:\n *      Synchronous: PluginResult object as a JSON string\n *      Asynchronous: Empty string \"\"\n * If async, the native side will cordova.callbackSuccess or cordova.callbackError,\n * depending upon the result of the action.\n *\n * @param {Function} success    The success callback\n * @param {Function} fail       The fail callback\n * @param {String} service      The name of the service to use\n * @param {String} action       Action to be run in cordova\n * @param {String[]} [args]     Zero or more arguments to pass to the method\n */\nmodule.exports = function (success, fail, service, action, args) {\n    const proxy = execProxy.get(service, action);\n\n    args = args || [];\n\n    if (proxy) {\n        const callbackId = service + cordova.callbackId++;\n\n        if (typeof success === 'function' || typeof fail === 'function') {\n            cordova.callbacks[callbackId] = { success, fail };\n        }\n        try {\n            // callbackOptions param represents additional optional parameters command could pass back, like keepCallback or\n            // custom callbackId, for example {callbackId: id, keepCallback: true, status: cordova.callbackStatus.JSON_EXCEPTION }\n            const onSuccess = function (result, callbackOptions) {\n                callbackOptions = callbackOptions || {};\n                let callbackStatus;\n                // covering both undefined and null.\n                // strict null comparison was causing callbackStatus to be undefined\n                // and then no callback was called because of the check in cordova.callbackFromNative\n                // see CB-8996 Mobilespec app hang on windows\n                if (callbackOptions.status !== undefined && callbackOptions.status !== null) {\n                    callbackStatus = callbackOptions.status;\n                } else {\n                    callbackStatus = cordova.callbackStatus.OK;\n                }\n                cordova.callbackSuccess(callbackOptions.callbackId || callbackId,\n                    {\n                        status: callbackStatus,\n                        message: result,\n                        keepCallback: callbackOptions.keepCallback || false\n                    });\n            };\n            const onError = function (err, callbackOptions) {\n                callbackOptions = callbackOptions || {};\n                let callbackStatus;\n                // covering both undefined and null.\n                // strict null comparison was causing callbackStatus to be undefined\n                // and then no callback was called because of the check in cordova.callbackFromNative\n                // note: status can be 0\n                if (callbackOptions.status !== undefined && callbackOptions.status !== null) {\n                    callbackStatus = callbackOptions.status;\n                } else {\n                    callbackStatus = cordova.callbackStatus.OK;\n                }\n                cordova.callbackError(callbackOptions.callbackId || callbackId,\n                    {\n                        status: callbackStatus,\n                        message: err,\n                        keepCallback: callbackOptions.keepCallback || false\n                    });\n            };\n            proxy(onSuccess, onError, args);\n        } catch (e) {\n            console.log('Exception calling native with command :: ' + service + ' :: ' + action + ' ::exception=' + e);\n        }\n    } else {\n        console.log('Error: exec proxy not found for :: ' + service + ' :: ' + action);\n\n        if (typeof fail === 'function') {\n            fail('Missing Command Error');\n        }\n    }\n};\n"
  },
  {
    "path": "cordova-js-src/platform.js",
    "content": "/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\nmodule.exports = {\n    id: 'browser',\n    cordovaVersion: '4.2.0', // cordova-js\n\n    bootstrap: function () {\n        const modulemapper = require('cordova/modulemapper');\n        const channel = require('cordova/channel');\n\n        modulemapper.clobbers('cordova/exec/proxy', 'cordova.commandProxy');\n\n        channel.onNativeReady.fire();\n\n        document.addEventListener('visibilitychange', function () {\n            if (document.hidden) {\n                channel.onPause.fire();\n            } else {\n                channel.onResume.fire();\n            }\n        });\n\n    // End of bootstrap\n    }\n};\n"
  },
  {
    "path": "eslint.config.js",
    "content": "/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\nconst { defineConfig, globalIgnores } = require('eslint/config');\nconst nodeConfig = require('@cordova/eslint-config/node');\nconst nodeTestConfig = require('@cordova/eslint-config/node-tests');\nconst browserConfig = require('@cordova/eslint-config/browser');\n\nmodule.exports = defineConfig([\n    globalIgnores([\n        '**/coverage/',\n        'bin/template/www/cordova.js'\n    ]),\n    ...nodeConfig.map(config => ({\n        files: [\n            '**/*.js',\n            'bin/template/cordova/version'\n        ],\n        ...config\n    })),\n    ...nodeTestConfig.map(config => ({\n        files: ['spec/**/*.js'],\n        ...config\n    })),\n    ...browserConfig.map(config => ({\n        files: [\n            'cordova-js-src/**/*.js',\n            'bin/template/www/**/*.js'\n        ],\n        ...config,\n        languageOptions: {\n            ...(config?.languageOptions || {}),\n            globals: {\n                ...(config.languageOptions?.globals || {}),\n                require: 'readonly',\n                module: 'readonly'\n            }\n        }\n    }))\n]);\n"
  },
  {
    "path": "licence_checker.yml",
    "content": "# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n\n# Empty for the release audit workflow.\n# The `license-config` is required even if there are no custom configs\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"cordova-browser\",\n  \"version\": \"8.0.0-dev\",\n  \"description\": \"cordova-browser release\",\n  \"main\": \"bin/template/cordova/Api.js\",\n  \"repository\": \"github:apache/cordova-browser\",\n  \"bugs\": \"https://github.com/apache/cordova-browser/issues\",\n  \"keywords\": [\n    \"cordova\",\n    \"browser\",\n    \"apache\"\n  ],\n  \"scripts\": {\n    \"prepare\": \"cordova-js build > bin/template/www/cordova.js\",\n    \"cover\": \"c8 jasmine\",\n    \"lint\": \"eslint .\",\n    \"lint:fix\": \"npm run lint -- --fix\",\n    \"jasmine\": \"jasmine\",\n    \"test\": \"npm run lint && npm run cover\"\n  },\n  \"dependencies\": {\n    \"cordova-common\": \"^6.0.0\",\n    \"cordova-serve\": \"^4.0.1\"\n  },\n  \"devDependencies\": {\n    \"@cordova/eslint-config\": \"^6.0.1\",\n    \"c8\": \"^11.0.0\",\n    \"cordova-js\": \"^6.1.0\",\n    \"jasmine\": \"^6.1.0\",\n    \"tmp\": \"^0.2.5\"\n  },\n  \"author\": \"Apache Software Foundation\",\n  \"license\": \"Apache-2.0\",\n  \"engines\": {\n    \"node\": \"^20.17.0 || >=22.9.0\"\n  },\n  \"c8\": {\n    \"include\": [\n      \"bin/lib/**\",\n      \"bin/templates/cordova/**\"\n    ],\n    \"reporter\": [\n      \"lcov\",\n      \"text\"\n    ]\n  }\n}\n"
  },
  {
    "path": "spec/browser_handler.spec.js",
    "content": "/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\nconst browser_handler = require('../bin/template/cordova/browser_handler');\nconst fs = require('node:fs');\nconst path = require('node:path');\n\ndescribe('Asset install tests', function () {\n    let fsstatMock;\n    const asset = {\n        itemType: 'asset',\n        src: path.join('someSrc', 'ServiceWorker.js'),\n        target: 'ServiceWorker.js'\n    };\n    const assetWithPath = {\n        itemType: 'asset',\n        src: path.join('someSrc', 'reformat.js'),\n        target: path.join('js', 'deepdown', 'reformat.js')\n    };\n    const assetWithPath2 = {\n        itemType: 'asset',\n        src: path.join('someSrc', 'reformat.js'),\n        target: path.join('js', 'deepdown', 'reformat2.js')\n    };\n\n    const plugin_dir = 'pluginDir';\n    const wwwDest = 'dest';\n\n    it('if src is a directory, should be called with cpSync recursive force', function () {\n        const cp = spyOn(fs, 'cpSync').and.callFake(() => {});\n        fsstatMock = {\n            isDirectory: function () {\n                return true;\n            }\n        };\n        spyOn(fs, 'statSync').and.returnValue(fsstatMock);\n        browser_handler.asset.install(asset, plugin_dir, wwwDest);\n        expect(cp).toHaveBeenCalledWith(jasmine.any(String), path.join('dest', asset.target), {\n            recursive: true,\n            force: true\n        });\n    });\n    it('if src is not a directory and asset has no path, should be called with cp, -f', function () {\n        const cp = spyOn(fs, 'cpSync').and.callFake(() => {});\n        const mkdir = spyOn(fs, 'mkdirSync');\n        spyOn(fs, 'existsSync').and.returnValue(true);\n        fsstatMock = {\n            isDirectory: function () {\n                return false;\n            }\n        };\n        spyOn(fs, 'statSync').and.returnValue(fsstatMock);\n        browser_handler.asset.install(asset, plugin_dir, wwwDest);\n        expect(mkdir).not.toHaveBeenCalled();\n        expect(cp).toHaveBeenCalledWith(path.join('pluginDir', asset.src), path.join('dest', asset.target), {\n            force: true\n        });\n    });\n    it('if src is not a directory and asset has a path, should be called with cp, -f', function () {\n        /*\n            Test that a dest directory gets created if it does not exist\n        */\n        const cp = spyOn(fs, 'cpSync').and.callFake(() => {});\n        const mkdir = spyOn(fs, 'mkdirSync');\n        fsstatMock = {\n            isDirectory: function () {\n                return false;\n            }\n        };\n        spyOn(fs, 'statSync').and.returnValue(fsstatMock);\n\n        browser_handler.asset.install(assetWithPath, plugin_dir, wwwDest);\n        expect(mkdir).toHaveBeenCalledWith(path.join('dest', 'js', 'deepdown'), {\n            recursive: true\n        });\n        expect(cp).toHaveBeenCalledWith(path.join('pluginDir', assetWithPath.src), path.join('dest', assetWithPath.target), {\n            force: true\n        });\n        /*\n            Now test that a second call to the same dest folder skips mkdir because the first asset call should have created it.\n        */\n        spyOn(fs, 'existsSync').and.returnValue(true);\n        browser_handler.asset.install(assetWithPath2, plugin_dir, wwwDest);\n        expect(mkdir.calls.count()).toBe(1); // not called again\n    });\n});\n"
  },
  {
    "path": "spec/create.spec.js",
    "content": "/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\nconst fs = require('node:fs');\nconst path = require('node:path');\nconst tmp = require('tmp');\nconst create = require('../bin/lib/create');\n\ntmp.setGracefulCleanup();\n\nfunction makeTempDir () {\n    const tempdir = tmp.dirSync({ unsafeCleanup: true });\n    return path.join(tempdir.name, `cordova-browser-create-test-${Date.now()}`);\n}\n\n/**\n * Verifies that some of the project file exists. Not all will be tested.\n * E.g. App's resource directory, xcodeproj, xcworkspace, and CordovaLib.\n *\n * @param {String} tmpDir\n * @param {String} projectName\n */\nfunction verifyProjectFiles (tmpDir, projectName) {\n    expect(fs.existsSync(path.join(tmpDir, 'www'))).toBe(true);\n    expect(fs.existsSync(path.join(tmpDir, 'platform_www'))).toBe(true);\n}\n\n/**\n * Runs various project creation checks.\n *\n * @param {String} tmpDir\n * @param {String} packageName\n * @param {String} projectName\n * @returns {Promise}\n */\nasync function verifyCreatedProject (tmpDir, packageName, projectName) {\n    await create.createProject(tmpDir, packageName, projectName)\n        .then(() => verifyProjectFiles(tmpDir, projectName));\n}\n\nfunction verifyManifestFiles (tmpDir, projectName) {\n    const manifestPath = path.join(tmpDir, 'platform_www/manifest.json');\n    expect(fs.existsSync(manifestPath)).toBe(true);\n    const manifestObj = require(manifestPath);\n    expect(manifestObj.name).toBe(projectName);\n    // start_url\n    expect(manifestObj.start_url).toBe('index.html');\n    // display\n    expect(manifestObj.display).toBe('standalone');\n    // description\n    expect(manifestObj.description).toBeDefined();\n    // background_color\n    expect(manifestObj.background_color).toBeDefined();\n    // theme_color\n    expect(manifestObj.theme_color).toBeDefined();\n    // scope\n    expect(manifestObj.scope).toBeDefined();\n    // orientation\n    expect(manifestObj.orientation).toBeDefined();\n    // icons\n    expect(manifestObj.icons).toBeDefined();\n    expect(Array.isArray(manifestObj.icons)).toBe(true);\n    expect(manifestObj.icons.length).toBeDefined();\n    expect(manifestObj.icons.length).toBeGreaterThan(0);\n}\n\ndescribe('create', () => {\n    let tmpDir;\n\n    beforeEach(function () {\n        tmpDir = makeTempDir();\n    });\n\n    afterEach(() => {\n        fs.rmSync(tmpDir, { recursive: true, force: true });\n    });\n\n    it('create project with ascii name, no spaces', function () {\n        const projectName = 'testcreate';\n        const packageName = 'com.test.app1';\n        return verifyCreatedProject(tmpDir, packageName, projectName);\n    });\n\n    it('create project with ascii name, and spaces', function () {\n        const projectName = 'test create';\n        const packageName = 'com.test.app2';\n        return verifyCreatedProject(tmpDir, packageName, projectName);\n    });\n\n    it('create project with unicode name, no spaces', function () {\n        const projectName = '応応応応用用用用';\n        const packageName = 'com.test.app3';\n        return verifyCreatedProject(tmpDir, packageName, projectName);\n    });\n\n    it('create project with unicode name, and spaces', function () {\n        const projectName = '応応応応 用用用用';\n        const packageName = 'com.test.app4';\n        return verifyCreatedProject(tmpDir, packageName, projectName);\n    });\n\n    it('create project with ascii+unicode name, no spaces', function () {\n        const projectName = '応応応応hello用用用用';\n        const packageName = 'com.test.app5';\n        return verifyCreatedProject(tmpDir, packageName, projectName);\n    });\n\n    it('create project with ascii+unicode name, and spaces', function () {\n        const projectName = '応応応応 hello 用用用用';\n        const packageName = 'com.test.app6';\n        return verifyCreatedProject(tmpDir, packageName, projectName);\n    });\n\n    it('should have manifest.json', function () {\n        const projectName = 'testcreate';\n        const packageName = 'com.test.app1';\n        return verifyCreatedProject(tmpDir, packageName, projectName)\n            .then(() => verifyManifestFiles(tmpDir, projectName));\n    });\n});\n"
  },
  {
    "path": "spec/projectApi.spec.js",
    "content": "/*\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n*/\n\nconst path = require('node:path');\nconst EventEmitter = require('node:events');\n\nconst Api = require('../bin/template/cordova/Api');\nconst create = require('../bin/lib/create');\n\ndescribe('can get the Api', function () {\n    it('should be defined', function () {\n        expect(Api).toBeDefined();\n    });\n\n    it('should export static createPlatform function', function () {\n        expect(Api.createPlatform).toBeDefined();\n        expect(typeof Api.createPlatform).toBe('function');\n    });\n\n    it('should export static updatePlatform function', function () {\n        expect(Api.updatePlatform).toBeDefined();\n        expect(typeof Api.updatePlatform).toBe('function');\n    });\n\n    describe('static createPlatform method', () => {\n        it('should create a platform app and return the Api', () => {\n            // Trick function under test to load our Api after calling createProject\n            const testDir = path.join(__dirname, '../bin/template');\n            const testOpts = {};\n            spyOn(create, 'createProject').and.returnValue(Promise.resolve());\n\n            return Api.createPlatform(testDir, null, testOpts, new EventEmitter()).then(api => {\n                expect(api).toBeInstanceOf(Api);\n                expect(create.createProject).toHaveBeenCalledWith(\n                    testDir, jasmine.any(String), jasmine.any(String), testOpts\n                );\n            });\n        });\n    });\n});\n\ndescribe('project level Api', function () {\n    const testApi = new Api();\n\n    it('can be created', function () {\n        expect(testApi).toBeDefined();\n    });\n\n    it('has a requirements method', function () {\n        expect(testApi.requirements).toBeDefined();\n        expect(typeof testApi.requirements).toBe('function');\n    });\n\n    it('has a clean method', function () {\n        expect(testApi.clean).toBeDefined();\n        expect(typeof testApi.clean).toBe('function');\n    });\n\n    it('has a run method', function () {\n        expect(testApi.run).toBeDefined();\n        expect(typeof testApi.run).toBe('function');\n    });\n\n    it('has a build method', function () {\n        expect(testApi.build).toBeDefined();\n        expect(typeof testApi.build).toBe('function');\n    });\n\n    it('has a removePlugin method', function () {\n        expect(testApi.removePlugin).toBeDefined();\n        expect(typeof testApi.removePlugin).toBe('function');\n    });\n\n    it('has a addPlugin method', function () {\n        expect(testApi.addPlugin).toBeDefined();\n        expect(typeof testApi.addPlugin).toBe('function');\n    });\n\n    it('has a prepare method', function () {\n        expect(testApi.prepare).toBeDefined();\n        expect(typeof testApi.prepare).toBe('function');\n    });\n\n    it('has a getPlatformInfo method', function () {\n        expect(testApi.getPlatformInfo).toBeDefined();\n        expect(typeof testApi.getPlatformInfo).toBe('function');\n    });\n});\n\n// Static methods\n// Static method: createPlatform\n// returns promise fulfilled with Api\n// emits error using provided emmitter on error\n\n// Static method: updatePlatform\n// returns a promise fulfilled with an Api\n// emits error using provided emmitter on error\n\n// Instance methods\n// requirements, clean, run, build, removePlugin, addPlugin, prepare, getPlatformInfo\n"
  },
  {
    "path": "spec/support/jasmine.json",
    "content": "{\n    \"spec_dir\": \"spec\",\n    \"spec_files\": [\n    \t\"*[sS]pec.js\"\n    ],\n    \"helpers\": [\n    ],\n    \"stopSpecOnExpectationFailure\": false,\n    \"random\": false\n}"
  }
]