[
  {
    "path": ".drone.yml",
    "content": "build:\n  image: julienrf/docker-scala-sbt-git\n  commands:\n    - sbt clean test scripted\n\ncache:\n  mount:\n    - .git\n    - /drone/.ivy2\n    - /drone/.sbt"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    branches:\n      - main\njobs:\n  build:\n    strategy:\n      matrix:\n        os: [ubuntu-latest, windows-latest]\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v4\n      - uses: coursier/cache-action@v5\n      - uses: actions/setup-java@v4\n        with:\n          java-version: \"11\"\n          distribution: \"adopt\"\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 16.14.2\n      - name: Setup yarn\n        run: npm install -g yarn@1.22.15\n      - name: Unit tests\n        run: sbt test\n      - name: Scripted tests\n        run: sbt scripted\n      - name: Build the manual\n        run: sbt manual/makeSite\n"
  },
  {
    "path": ".github/workflows/ghpages.yml",
    "content": "\nname: Build and Deploy GhPages docs\n\non:\n  push:\n    branches:\n      - main\n\njobs:\n  build-and-deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n      - uses: actions/setup-java@v4\n        with:\n          java-version: \"11\"\n          distribution: \"adopt\"\n      - uses: coursier/cache-action@v5\n      - name: Build\n        run: sbt manual/makeSite\n      - name: Deploy\n        uses: JamesIves/github-pages-deploy-action@3.6.2\n        with:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          BRANCH: gh-pages\n          FOLDER: manual/target/site\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\non:\n  push:\n    branches: [main]\n    tags: [\"*\"]\njobs:\n  publish:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          # fetches all tags, required to correctly set the version\n          fetch-depth: 0\n      - uses: actions/setup-java@v4\n        with:\n          java-version: \"8\"\n          distribution: \"adopt\"\n      - uses: olafurpg/setup-gpg@v3\n      - uses: coursier/cache-action@v5\n      - name: Publish\n        run: sbt clean ci-release\n        env:\n          PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }}\n          PGP_SECRET: ${{ secrets.PGP_SECRET }}\n          SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}\n          SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}\n          CI_RELEASE: \"; scalajs-bundler-linker/publishSigned; sbt-scalajs-bundler/publishSigned; sbt-web-scalajs-bundler/publishSigned\"\n          CI_SNAPSHOT_RELEASE: \"; scalajs-bundler-linker/publish; sbt-scalajs-bundler/publish; sbt-web-scalajs-bundler/publish\"\n\n\n"
  },
  {
    "path": ".gitignore",
    "content": "target/\n.idea\nlocal.*"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "Contributing\n===========\n\n## General recommendations\n\nTest and document each added feature.\n\n## Organization of the repository\n\n- `sbt-scalajs-bundler/` The scalajs-bundler sbt plugin\n- `sbt-web-scalajs-bundler/` sbt plugin for integrating scalajs-bundler and\n[sbt-web-scalajs](https://github.com/vmunier/sbt-web-scalajs)\n- `manual/` Sources of the documentation\n\n## Build the project\n\n~~~ sh\n$ sbt package\n~~~\n\n## Run the tests\n\nWe use [sbt-scripted](http://eed3si9n.com/testing-sbt-plugins) to test the plugins. However, we customized\nthe way tests are launched to filter tests according to their compatibility with major versions of sbt and Scala.js:\n\n- tests can have a `project/build.properties` file defining a specific sbt version they are compatible with,\n\nTo run all the tests:\n\n~~~ sh\n$ sbt scripted\n~~~\n\nTo run a single test:\n\n~~~ sh\n$ sbt \"sbt-scalajs-bundler/scripted sbt-scalajs-bundler/<test-name>\"\n~~~\n\n(where `<test-name>` is replaced by one of the\n[tests](https://github.com/scalacenter/scalajs-bundler/tree/main/sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler)).\n\nSometimes you would like to open an interactive sbt shell and manually play with\nsbt tasks instead of writing them into a sbt-scripted test. In such a case, you\ncan start with an existing sbt-scripted test and add the following commands at\nthe top of its `test` file:\n\n~~~\n$ pause\n$ fail\n~~~\n\nThen, when you will run the scripted task on this this test, it will start by\nmaking a pause. You can then open a new sbt shell in the running test:\n\n~~~\n$ cd /tmp/sbt_fa1e13d43/test-name\n$ sbt -Dplugin.version=x.y.z-SNAPSHOT\n~~~\n\n(where `x.y.z` is replaced by the current version of sbt-scalajs-bundler)\n\n## Publish locally\n\n~~~ sh\n$ sbt publishLocal\n~~~\n\n## Preview the documentation\n\n~~~ sh\n$ sbt manual/previewSite\n~~~\n\n## Publish a release\n\n- Check that the `changelog.md` file is up to date (in the `manual` project)\n- Push a Git tag (name it `vX.Y.Z`, where `X`, `Y`, `Z` are major, minor and revision numbers, respectively)\n  - Either from GitHub [web interface](https://github.com/scalacenter/scalajs-bundler/releases/new),\n  - Or from the Git CLI: `$ git tag v1.0.0; git push --tags`\n"
  },
  {
    "path": "LICENSE",
    "content": "scalajs-bundler is licensed under the [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause).\n\nCopyright (c) 2016 EPFL\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n    this list of conditions and the following disclaimer.\n  2. Redistributions in binary form must reproduce the above copyright notice,\n    this list of conditions and the following disclaimer in the documentation\n    and/or other materials provided with the distribution.\n  3. Neither the name of the EPFL nor the names of its contributors\n    may be used to endorse or promote products derived from this software\n    without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  },
  {
    "path": "README.md",
    "content": "scalajs-bundler [![](https://index.scala-lang.org/scalacenter/scalajs-bundler/sbt-scalajs-bundler/latest.svg)](https://index.scala-lang.org/scalacenter/scalajs-bundler) [![Gitter](https://img.shields.io/badge/gitter-join%20chat-green.svg)](https://gitter.im/scalacenter/scalajs-bundler) [![CI](https://github.com/scalacenter/scalajs-bundler/actions/workflows/ci.yml/badge.svg)](https://github.com/scalacenter/scalajs-bundler/actions/workflows/ci.yml)\n==============\n\nModule bundler for Scala.js projects that use NPM packages.\n\nUses [npm](https://www.npmjs.com) and [webpack](https://webpack.github.io/) under the hood.\n\n## Documentation\n\nMore information on how to use it in the [documentation](https://scalacenter.github.io/scalajs-bundler).\n\n## Contributing\n\nscalajs-bundler is community-maintained.\n\nContributions are welcome! See the [open issues](https://github.com/scalacenter/scalajs-bundler/issues) and\nthe [CONTRIBUTING.md](CONTRIBUTING.md) file.\n\n## License\n\nThis content is released under the [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause).\n"
  },
  {
    "path": "build.sbt",
    "content": "val scalaJSVersion = sys.env.getOrElse(\"SCALAJS_VERSION\", \"1.3.0\")\n\nlazy val `scalajs-bundler-linker` =\n  project.in(file(\"scalajs-bundler-linker\"))\n    .settings(\n      scalaVersion := \"2.12.11\",\n      libraryDependencies += \"org.scala-js\" %% \"scalajs-linker\" % scalaJSVersion\n    )\n\nval `sbt-scalajs-bundler` =\n  project.in(file(\"sbt-scalajs-bundler\"))\n    .enablePlugins(SbtPlugin, BuildInfoPlugin)\n    .settings(commonSettings)\n    .settings(\n      description := \"Module bundler for Scala.js projects\",\n      libraryDependencies += \"com.google.jimfs\" % \"jimfs\" % \"1.2\",\n      libraryDependencies += \"com.typesafe.play\" %% \"play-json\" % \"2.9.4\",\n      addSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion),\n      buildInfoKeys := Seq[BuildInfoKey](version),\n      buildInfoPackage := \"scalajsbundler.sbtplugin.internal\",\n      // When supported, add: buildInfoOptions += sbtbuildinfo.BuildInfoOption.PackagePrivate\n      scriptedDependencies := {\n        val () = scriptedDependencies.value\n        val () = publishLocal.value\n        val () = (`scalajs-bundler-linker` / publishLocal).value\n      },\n    )\n\nval `sbt-web-scalajs-bundler` =\n  project.in(file(\"sbt-web-scalajs-bundler\"))\n    .enablePlugins(SbtPlugin)\n    .settings(commonSettings)\n    .settings(\n      // sbt-web-scalajs does not support sbt 1.2.x\n      scriptedDependencies := {\n        val () = scriptedDependencies.value\n        val () = publishLocal.value\n        val () = (`sbt-scalajs-bundler` / publishLocal).value\n        val () = (`scalajs-bundler-linker` / publishLocal).value\n      },\n      description := \"Module bundler for Scala.js projects (integration with sbt-web-scalajs)\",\n      addSbtPlugin(\"com.vmunier\" % \"sbt-web-scalajs\" % \"1.1.0\")\n    )\n    .dependsOn(`sbt-scalajs-bundler`)\n\n// Dummy project that exists just for the purpose of aggregating the two sbt\n// plugins. I can not do that in the `doc` project below because the\n// scalaVersion is not compatible.\nval apiDoc =\n  project.in(file(\"api-doc\"))\n    .enablePlugins(ScalaUnidocPlugin)\n    .settings(noPublishSettings: _*)\n    .settings(\n      (ScalaUnidoc / unidoc / scalacOptions) ++= Seq(\n        \"-groups\",\n        \"-doc-source-url\", s\"https://github.com/scalacenter/scalajs-bundler/blob/v${version.value}€{FILE_PATH}.scala\",\n        \"-sourcepath\", (ThisBuild / baseDirectory).value.absolutePath\n      ),\n      (ScalaUnidoc / unidoc / unidocProjectFilter) := inAnyProject -- inProjects(`scalajs-bundler-linker`)\n    )\n    .aggregate(`sbt-scalajs-bundler`, `sbt-web-scalajs-bundler`)\n\nval ornateTarget = Def.setting(target.value / \"ornate\")\n\nval manual =\n  project.in(file(\"manual\"))\n    .enablePlugins(OrnatePlugin)\n    .settings(noPublishSettings: _*)\n    .settings(\n      scalaVersion := \"2.12.11\",\n      ornateSourceDir := Some(sourceDirectory.value / \"ornate\"),\n      ornateTargetDir := Some(ornateTarget.value),\n      ornateSettings := Map(\"version\" -> version.value),\n      ornate / siteSubdirName := \"\",\n      addMappingsToSiteDir(ornate / mappings, ornate / siteSubdirName),\n      ornate / mappings := {\n        val _ = ornate.value\n        val output = ornateTarget.value\n        output ** AllPassFilter --- output pair Path.relativeTo(output)\n      },\n      packageDoc / siteSubdirName := \"api/latest\",\n      addMappingsToSiteDir(mappings in ScalaUnidoc in packageDoc in apiDoc, packageDoc / siteSubdirName)\n    )\n\nval `scalajs-bundler` =\n  project.in(file(\".\"))\n    .settings(noPublishSettings: _*)\n    .aggregate(`sbt-scalajs-bundler`, `sbt-web-scalajs-bundler`)\n\ninThisBuild(List(\n  scalacOptions ++= Seq(\n    \"-feature\",\n    \"-deprecation\",\n    \"-encoding\", \"UTF-8\",\n    \"-unchecked\",\n    \"-Xlint\",\n    \"-Yno-adapted-args\",\n    \"-Ywarn-dead-code\",\n    \"-Ywarn-numeric-widen\",\n    \"-Ywarn-value-discard\",\n    \"-Xfuture\"\n  ),\n  scmInfo := Some(\n    ScmInfo(\n      url(\"https://github.com/scalacenter/scalajs-bundler\"),\n      \"scm:git@github.com:scalacenter/scalajs-bundler.git\"\n    )\n  ),\n  organization := \"ch.epfl.scala\",\n  homepage := Some(url(s\"https://github.com/scalacenter/scalajs-bundler\")),\n  licenses := Seq(\"MIT License\" -> url(\"http://opensource.org/licenses/mit-license.php\")),\n  developers := List(Developer(\"julienrf\", \"Julien Richard-Foy\", \"julien.richard-foy@epfl.ch\", url(\"http://julien.richard-foy.fr\")))\n))\n\nlazy val commonSettings = List(\n  scriptedLaunchOpts ++= Seq(\n    \"-Dplugin.version=\" + version.value,\n    s\"-Dscalajs.version=$scalaJSVersion\",\n    \"-Dsbt.execute.extrachecks=true\" // Avoid any deadlocks.\n  ),\n  scriptedBufferLog := false,\n)\n\nlazy val noPublishSettings =\n  Seq(\n    publishArtifact := false,\n    publish := {},\n    publishLocal := {}\n  )\n\nThisBuild / ivyLoggingLevel := UpdateLogging.Quiet\n"
  },
  {
    "path": "manual/src/ornate/changelog.md",
    "content": "# Changelog\n\n## Version 0.20.0\n\n> 2020 October 22\n\nThis release upgrades to Scala.js 1.3.0.\n\n- Drop support for Scala.js 0.6.x\n- Drop support for Scala.js 1.0.x through 1.2.x\n- Add support for Scala.js 1.3.x\n\n## Version 0.19.0\n\n> 2020 October 16\n\nThis release drops support for sbt 0.13.x, and adds support for sbt-web-scalajs 1.1.0+.\n\n## Version 0.18.0\n\n> 2020 May 16\n\nThis release adds support for scala.js 1.1.0\n\n## Version 0.17.0\n\n> 2020 Feb 24\n\nThe main highlight of this release is better support for Scala.js 1.0.0+ out of the box.\nWe still support Scala.js 0.6.31+ as well.\n\n- With Scala.js 1.x, dynamically load the appropriate scalajs-linker, removing the need for the\n  `libraryDependencies += \"org.scala-js\" %% \"scalajs-linker\" % scalaVersion`\n  workaround.\n- With Scala.js 1.x, do not internally link twice when using the `LibraryOnly` and\n  `LibraryAndApplication` bundling modes, improving performance.\n- With Scala.js 1.x, better integrate with the `jsEnv` and `jsEnvInput` tasks of\n  Scala.js when using `requireJsDomEnv`.\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.16.0...v0.17.0).\n\n## Version 0.16.0\n\n> 2019 Dec 09\n\nThe main highlight of this release is the support of Scala.js 1.0.0-RC1 instead of 1.0.0-M7.\nWe still support Scala.js 0.6.x, but we require at least version 0.6.31.\n\n- Add support for Scala.js 1.0.0-RC1 (drop support for 1.0.0-M7)\n- Require Scala.js 0.6.31 or later in the 0.6.x branch\n- Require sbt 1.2.1 or later in the sbt 1.x branch (sbt 0.13.17+ is still supported)\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.15.0...v0.16.0).\n\n## Version 0.15.0\n\n> 2019 May 21\n\nThe main highlight of this release is the support of Scala.js 1.x. We still support Scala.js 0.6.x, but\nwe require at least version 0.6.26.\n\nNew features:\n- [#201](https://github.com/scalacenter/scalajs-bundler/issues/201): Introduce a `jsSourceDirectories` setting,\n  which points to a list of directories containing files (`.js`, `.json`, etc.) that can be used by Scala.js\n  projects.\n- [#246](https://github.com/scalacenter/scalajs-bundler/issues/246): Support Scala.js 1.0.0-M7.\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.14.0...v0.15.0).\n\n## Version 0.14.0\n\n> 2018 Nov 5\n\nThis release modifies the `npmUpdate` task and splits the logic into two separate tasks; `npmInstallDependencies` and\n`npmInstallJSResources`. `npmUpdate` has a less obvious side effect that, not only does it run `npm install`, it would\nalso copy all the JavaScript resources to the `node_modules` directory. This behaviour is fine except that it is not\nsuitable for use in `sourceGenerators` and would cause a cycle in the tasks. `npmInstallDependencies` should be used in\ncases where you want to want to use a npm module from a sbt task.\n\nThis fixes the following bugs:\n - [#258](https://github.com/scalacenter/scalajs-bundler/issues/258): Unable to use npmUpdate in sourceGenerators\n - [#261](https://github.com/scalacenter/scalajs-bundler/issues/261): Support jsdom v12.x\n - [#267](https://github.com/scalacenter/scalajs-bundler/issues/267): Support JDK9+\n\nNew features:\n  - [#264](https://github.com/scalacenter/scalajs-bundler/issues/264): Ability to set `node` [flags](https://nodejs.org/api/cli.html)\n  - [#266](https://github.com/scalacenter/scalajs-bundler/issues/266): Custom setting for DOM enabled `JSEnv` in `test`. (`requiresDOM` is deprecated)\n\nAnd documentation fixes:\n  - [#269](https://github.com/scalacenter/scalajs-bundler/issues/269): Update docs\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.13.1...v0.14.0).\n\n## Version 0.13.1\n\n> 2018 Jul 13\n\nThis fixes the following bugs:\n\n  - [#224](https://github.com/scalacenter/scalajs-bundler/issues/224): Use project-level custom NPM registry\n\nThe following PRs are included in this release\n\n- [#254](https://github.com/scalacenter/scalajs-bundler/pull/254): Npm/yarn args\n- [#251](https://github.com/scalacenter/scalajs-bundler/pull/251): Fix typo\n- [#249](https://github.com/scalacenter/scalajs-bundler/pull/249): Sync yarn.lock between baseDir and installDir\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.13.0...v0.14.1).\n\n## Version 0.13.0\n\n> 2018 Jun 5\n\nThis release contains an important revamp on the way webpack support works.\nWebpack produces a json [stats output](https://webpack.js.org/api/stats) which\ndescribes in detail the results of processing your application. Thus, parsing\nstats we can learn exactly what files are produced rather than guessing.\n\nDue to the very nature of parsing the output, and the wide variety of webpack\nconfigurations this process may not work in all cases. Please lets us know if\nyou find any issues.\n\n**Note:** `Stats` parsing has been tested mostly in Webpack 4. The results may vary with\nolder versions.\n\n**Note:** If your webpack produces any kind of std output, parsing stats will likely break.\n\nThis fixes the following bugs:\n\n- [#192](https://github.com/scalacenter/scalajs-bundler/issues/192): Webpack failed to create application bundle\n- [#111](https://github.com/scalacenter/scalajs-bundler/issues/111): Lots of warnings about source map URLs\n\nThe following PRs are included in this release\n\n- [#247](https://github.com/scalacenter/scalajs-bundler/pull/247): Assets to sbt\n- [#242](https://github.com/scalacenter/scalajs-bundler/pull/242): Better error display when the webpack call fails\n- [#241](https://github.com/scalacenter/scalajs-bundler/pull/241): Use Public path from webpack stats\n- [#240](https://github.com/scalacenter/scalajs-bundler/pull/240): Update concat-with-sourcemaps\n- [#239](https://github.com/scalacenter/scalajs-bundler/pull/239): Bugfix parsing errors on the output\n- [#238](https://github.com/scalacenter/scalajs-bundler/pull/238): Fix thread leak\n- [#237](https://github.com/scalacenter/scalajs-bundler/pull/237): add function as a module example\n- [#234](https://github.com/scalacenter/scalajs-bundler/pull/234): Read application asset name from stats\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.12.0...v0.13.0).\n\n## Version 0.12.0\n\n> 2018 March 27\n\n- [#223](https://github.com/scalacenter/scalajs-bundler/pull/223): Webpack4 support\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.11.0...v0.12.0).\n\n## Version 0.11.0\n\n> 2018 March 15\n\n- [#228](https://github.com/scalacenter/scalajs-bundler/pull/228): Implements npmUdpdate in a separate object;\n- [#225](https://github.com/scalacenter/scalajs-bundler/pull/225): Add --mutex to yarn command;\n- [#222](https://github.com/scalacenter/scalajs-bundler/pull/222): Make library example work in OSX;\n- [#220](https://github.com/scalacenter/scalajs-bundler/pull/220): Support passing an extra list of arguments to webpack;\n- [#218](https://github.com/scalacenter/scalajs-bundler/pull/218): Fix [#136](https://github.com/scalacenter/scalajs-bundler/issues/136): Add more precise jsdom detection:\n- [#216](https://github.com/scalacenter/scalajs-bundler/pull/216): Fix [#200](https://github.com/scalacenter/scalajs-bundler/issues/200): current webpack devserver version does not accept watchOptions;\n- [#215](https://github.com/scalacenter/scalajs-bundler/pull/215): Fix [#99](https://github.com/scalacenter/scalajs-bundler/issues/99): Relax NPM dependency version conflict resolution;\n- [#213](https://github.com/scalacenter/scalajs-bundler/pull/213): Fix [#168](https://github.com/scalacenter/scalajs-bundler/issues/168): Update the snabbdom facade for Scala.js 1.0\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.10.0...v0.11.0).\n\n## Version 0.10.0\n\n> 2018 January 31\n\nThis release requires sbt 0.13.16+ and adds support for Scala.js 0.6.22.\n\n- [#210](https://github.com/scalacenter/scalajs-bundler/pull/210): Bundler doesn't support version of jsdom more than 9;\n- [#185](https://github.com/scalacenter/scalajs-bundler/pull/185): Correct webpackBundlingMode key in docs;\n- [#212](https://github.com/scalacenter/scalajs-bundler/pull/212): Migrate to sbt-scalajs 0.6.22;\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.9.0...v0.10.0).\n\n## Version 0.9.0\n\n> 2017 October 12\n\nWhen upgrading to this release, make sure to migrate your webpack configuration to [webpack 3.X](https://webpack.js.org/guides/migrating/).\n\nThis version works with both sbt version 0.13 and 1.0. In order to support sbt 1.0,\nScala.js has been upgraded to [0.6.19](https://www.scala-js.org/news/2017/07/29/announcing-scalajs-0.6.19/).\n\n- [#175](https://github.com/scalacenter/scalajs-bundler/pull/175): Set webpack 3.X as default version;\n- [#179](https://github.com/scalacenter/scalajs-bundler/pull/179): Cross publish for sbt 1.0;\n- [#176](https://github.com/scalacenter/scalajs-bundler/pull/176): Run webpack-dev-server from the scalajs-bundler folder;\n- [#177](https://github.com/scalacenter/scalajs-bundler/pull/176): Scope webpackBundlingMode per Scala.js stage (`fastOptJS` or `fullOptJS`);\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.8.0...v0.9.0).\n\n## Version 0.8.0\n\n> 2017 September 10\n\nWhen upgrading to this release, make sure to check out the new [webpackBundlingMode](reference.md#bundling-mode)\nconfiguration value. The old `enableReloadWorkflow` key has been removed, in favor\nof `BundlingMode.LibraryAndApplication()`.\n\n- [#143](https://github.com/scalacenter/scalajs-bundler/pull/143): Document the compatible versions of npm;\n- [#146](https://github.com/scalacenter/scalajs-bundler/pull/146): Document how to use global modules with jsdom in tests;\n- [#149](https://github.com/scalacenter/scalajs-bundler/pull/149): Introduce `webpackBundlingMode` to finely control whether to bundle the output of Scala.js or not;\n- [#153](https://github.com/scalacenter/scalajs-bundler/pull/153): Use the non interactive mode of Yarn;\n- [#161](https://github.com/scalacenter/scalajs-bundler/pull/161): Set `\"private\": true` in generated `package.json` file to eliminate errors from npm;\n- [#162](https://github.com/scalacenter/scalajs-bundler/pull/162): Differentiate between missing and unsupported Webpack versions;\n- [#166](https://github.com/scalacenter/scalajs-bundler/pull/166): Move to Travis-CI;\n- [#167](https://github.com/scalacenter/scalajs-bundler/pull/167): Upgrade tests that use `uuid`;\n- [#171](https://github.com/scalacenter/scalajs-bundler/pull/171): Add `scalaJSProjects` resource directories to `monitoredScalaJSDirectories`;\n- [#172](https://github.com/scalacenter/scalajs-bundler/pull/172): Use `npm install` command instead of `npm update`.\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.7.0...v0.8.0).\n\n## Version 0.7.0\n\n> 2017 July 4\n\nWhen upgrading to this release, make sure to enable `scalaJSUseMainModuleInitializer := true` in your build if you have a `main` method.\n\n- [#125](https://github.com/scalacenter/scalajs-bundler/pull/125): Copy `webpackResources` only if a custom webpack config file is used ;\n- [#126](https://github.com/scalacenter/scalajs-bundler/pull/126): Ability to add custom `package.json` entries ;\n- [#129](https://github.com/scalacenter/scalajs-bundler/pull/129): Generate a JavaScript array of webpack entries rather than a string ;\n- [#140](https://github.com/scalacenter/scalajs-bundler/pull/140): Upgrade to Scala.js 0.6.18 ;\n- [#141](https://github.com/scalacenter/scalajs-bundler/pull/141): Handle `ImportWithGlobalFallback` in reload workflow.\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.6.0...v0.7.0).\n\n## Version 0.6.0\n\n> 2017 April 26\n\n- [#96](https://github.com/scalacenter/scalajs-bundler/pull/96): webpack-dev-server integration ;\n- [#102](https://github.com/scalacenter/scalajs-bundler/pull/102): Make it possible to set the version of jsdom and webpack-dev-server to use ;\n- [#106](https://github.com/scalacenter/scalajs-bundler/pull/106): Add a [Community](community.md) page ;\n- [#108](https://github.com/scalacenter/scalajs-bundler/pull/108): Add gitter badge to the README ;\n- [#121](https://github.com/scalacenter/scalajs-bundler/pull/121): Make the sbt task fail when webpack fails ;\n- [#119](https://github.com/scalacenter/scalajs-bundler/pull/119): Add support for custom webpack config files in tests and in the reload workflow ;\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.5.0...v0.6.0).\n\n## Version 0.5.0\n\n> 2017 January 18\n\n- [#57](https://github.com/scalacenter/scalajs-bundler/pull/57): Webpack 2.x support ;\n- [#80](https://github.com/scalacenter/scalajs-bundler/pull/80): Upgrade to Scala.js 0.6.14 ;\n- [#81](https://github.com/scalacenter/scalajs-bundler/pull/81): Disable the reload workflow by default ;\n- [#94](https://github.com/scalacenter/scalajs-bundler/pull/94): Improve caching of tasks ;\n- [#95](https://github.com/scalacenter/scalajs-bundler/pull/95): Fix support for spaces in paths ;\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.4.0...v0.5.0).\n\n## Version 0.4.0\n\n> 2016 December 15\n\n- [#53](https://github.com/scalacenter/scalajs-bundler/pull/53): Fix cache invalidation when .js resources change ;\n- [#54](https://github.com/scalacenter/scalajs-bundler/pull/54): Add support for importing assets from NPM packages ;\n- [#56](https://github.com/scalacenter/scalajs-bundler/pull/56): Add [Yarn](https://yarnpkg.com/) support ;\n- [#65](https://github.com/scalacenter/scalajs-bundler/pull/65): Use distinct target directories for `npmUpdate in Compile` and `npmUpdate in Test` ;\n- [#69](https://github.com/scalacenter/scalajs-bundler/pull/69): Publish the API documentation ;\n- [#70](https://github.com/scalacenter/scalajs-bundler/pull/70): Ensure that there is no duplicates in NPM dependencies ;\n- [#71](https://github.com/scalacenter/scalajs-bundler/pull/71): Add a resolution mechanism for conflicting dependencies.\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.3.1...v0.4.0).\n\n## Version 0.3.1\n\n> 2016 December 2\n\n- [#51](https://github.com/scalacenter/scalajs-bundler/pull/51): Support history API within jsdom.\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.3.0...v0.3.1).\n\n## Version 0.3.0\n\n> 2016 November 29\n\n- [#32](https://github.com/scalacenter/scalajs-bundler/pull/32): Add a detailed documentation\nsection on how to write a facade with `@JSImport` (see it [here](cookbook.md#facade)) ;\n- [#33](https://github.com/scalacenter/scalajs-bundler/pull/33): Fix cache invalidation\n  after custom webpack config file is changed ;\n- [#35](https://github.com/scalacenter/scalajs-bundler/pull/35): Fix tests on Windows ;\n- [#37](https://github.com/scalacenter/scalajs-bundler/pull/37): Throw an error if there is no main class ;\n- [#39](https://github.com/scalacenter/scalajs-bundler/pull/39): Add support for jsdom in tests ;\n- [#45](https://github.com/scalacenter/scalajs-bundler/pull/45): Forbid `scalaJSModuleKind`\n  to be different from `CommonJSModule` on projects where `ScalaJSBundler` plugin is enabled.\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.2.1...v0.3.0).\n\n## Version 0.2.1\n\n> 2016 November 2\n\n- [#24](https://github.com/scalacenter/scalajs-bundler/pull/24): Fixed npm command in Windows (thanks\n  to [@DylanArnold](https://github.com/DylanArnold)) ;\n- [#25](https://github.com/scalacenter/scalajs-bundler/pull/25): Fixed the `scalaJSPipeline` task\n  to correctly support source maps.\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.2...v0.2.1).\n\n## Version 0.2\n\n> 2016 November 1\n\n- [#14](https://github.com/scalacenter/scalajs-bundler/pull/14): Improved documentation ;\n- [#17](https://github.com/scalacenter/scalajs-bundler/pull/17): Faster live-reloading workflow\n  (`fastOptJS::webpack` is ~10x faster) ;\n- [#18](https://github.com/scalacenter/scalajs-bundler/pull/18): `ScalaJSBundlerPlugin` is not\n  anymore automatically triggered: you have to manually enable it on your projects.\n  `scalaJSModuleKind` is automatically set to `ModuleKind.CommonJSModule` when `ScalaJSBundlerPlugin`\n  is enabled, so you don’t anymore have to set it in your build ;\n- [#20](https://github.com/scalacenter/scalajs-bundler/pull/20): JavaScript files that are on\n  the classpath can be `@JSImport`ed by your Scala facades.\n\nYou can find the complete list of commits since the last release\n[here](https://github.com/scalacenter/scalajs-bundler/compare/v0.1...v0.2).\n"
  },
  {
    "path": "manual/src/ornate/community.md",
    "content": "# Community\n\n- [![Gitter](https://badges.gitter.im/scalacenter/scalajs-bundler.svg)](https://gitter.im/scalacenter/scalajs-bundler?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)\n- [![Stackoverflow](https://img.shields.io/badge/ask-on%20stackoverflow-blue.svg)](http://stackoverflow.com/questions/tagged/scalajs-bundler)\n- [![Github](https://img.shields.io/badge/contribute-on%20github-green.svg)](https://github.com/scalacenter/scalajs-bundler)"
  },
  {
    "path": "manual/src/ornate/cookbook.md",
    "content": "# Cookbook\n\n![](toctree:local=true,mergeFirst=true)\n\n## How to use a custom webpack configuration file? {#custom-config}\n\nFirst, configure the `webpackConfigFile` setting to refer to your configuration file:\n\n~~~ scala\nwebpackConfigFile in fastOptJS := Some(baseDirectory.value / \"my.custom.webpack.config.js\")\n~~~\n\nOr, if you want to use the same configuration file for both `fastOptJS` and `fullOptJS`:\n\n~~~ scala\nwebpackConfigFile := Some(baseDirectory.value / \"my.custom.webpack.config.js\")\n~~~\n\nThen, you can write your configuration in file `my.custom.webpack.config.js`.\nWe recommend that you reuse the configuration file generated by scalajs-bundler\nand extend it, rather than writing a configuration file from scratch.\n\nYou can do so as follows (in file `my.custom.webpack.config.js``):\n\n~~~ javascript\nvar webpack = require('webpack');\n\nmodule.exports = require('./scalajs.webpack.config');\n\n// And then modify `module.exports` to extend the configuration\n~~~\n\nThe key part is the `require('./scalajs.webpack.config')`. It loads the configuration\nfile generated by scalajs-bundler so that you can tweak it. It works because your configuration\nfile will be copied into the internal target directory, where the scalajs-bundler generates\nits configuration file, and where all the npm dependencies have been downloaded (so you can\nalso `require` these dependencies).\n\nBy default `webpack` task only actually launches webpack if it detects changes in\nsettings or in the custom webpack config file. Depending on your usage scenario, you might\nwant to monitor some other files as well (for example, if your webpack config references\nsome additional resources). This can be achieved by using `webpackMonitoredDirectories`\nsetting:\n\n~~~ scala\nwebpackMonitoredDirectories += baseDirectory.value / \"my-scss\"\nincludeFilter in webpackMonitoredFiles := \"*.scss\"\n~~~\n\nMore fine-grained control over the list of monitored files is possible by overriding the\n`webpackMonitoredFiles` task.\n\nYou can find a working example of custom configuration file\n[here](https://github.com/scalacenter/scalajs-bundler/blob/main/sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/static/prod.webpack.config.js).\n\nIt is also possible to configure a webpack config file to be used in reload workflow and when running the tests.\nThis configuration may not contain `entry` and `output` configuration but can be used to configure loaders etc.\n\nThese configuration files are configured using `webpackConfigFile in reloadTask` or `webpackConfigFile in Test`.\nFor example:\n\n~~~ scala\nwebpackConfigFile in webpackReload := Some(baseDirectory.value / \"common.webpack.config.js\")\n\nwebpackConfigFile in Test := Some(baseDirectory.value / \"common.webpack.config.js\")\n~~~\n\n## Sharing webpack configuration among configuration files {#shared-config}\n\nIn addition to the configured webpack config file, all .js files in the project base directory\n(as configured using the `webpackResources` setting) are copied to the target directory so they can be imported\nfrom the various configuration files.\n\nHere are the steps to share the loader configuration among your prod and dev config files. This\nuses webpack-merge for convenience. The same result could be accomplished using plain js only.\n\n1. Put configuration in a common.webpack.config.js file:\n\n~~~ javascript\nmodule.exports = {\n  module: {\n    loaders: [\n        ...\n    ],\n    rules: [\n        ...\n    ]\n  }\n}\n~~~\n\n2. Add webpack-merge to your `npmDevDependencies`:\n\n~~~\nnpmDevDependencies in Compile += \"webpack-merge\" -> \"4.1.0\"\n~~~\n\n3. Merge in the common configuration in your dev.webpack.js file:\n\n~~~ javascript\nvar merge = require(\"webpack-merge\")\nvar commonConfig = require(\"./common.webpack.config.js\")\n\nmodule.exports = merge(commonConfig, {\n    ...\n})\n~~~\n\nYou can find a working example of a project using a shared configuration file\n[here](https://github.com/scalacenter/scalajs-bundler/blob/main/sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sharedconfig).\n\n\n## How to use npm modules from Scala code? {#facade}\n\nOnce you have [added npm dependencies](getting-started.md) to the packages you are interested\nin, you have to *import* them from your code to effectively use them.\n\nThe recommended way to do that is to:\n\n1. Write a [Scala.js](https://www.scala-js.org/doc/interoperability/facade-types.html)\n  facade annotated with\n  [`@JSImport`](https://www.scala-js.org/doc/interoperability/facade-types.html#a-nameimporta-imports-from-other-javascript-modules) ;\n2. Refer to this facade from your code.\n\nLet’s illustrate this with an example. Say that you want to write a facade for the following\nnpm module:\n\n~~~ javascript tab=\"foo.js (CommonJS)\"\nexports.bar = function (i) { return i + 1 };\n~~~\n\n~~~ javascript tab=\"foo.js (ES6)\"\nexport const bar = i => i + 1;\n~~~\n\nThe corresponding Scala.js facade looks like the following:\n\n~~~ scala\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation.JSImport\n\n@JSImport(\"foo\", JSImport.Namespace)\n@js.native\nobject foo extends js.Object {\n  def bar(i: Int): Int = js.native\n}\n~~~\n\nThere are several points worth highlighting:\n\n- The first parameter of the `@JSImport` annotation is the npm module path. This is\n  the value you would pass to the\n  [Nodejs `require`](https://nodejs.org/docs/latest/api/modules.html#modules_all_together)\n  function ;\n- The second parameter of `@JSImport` is the name of the imported member, or like in our\n  case, `JSImport.Namespace`, to import the whole module instead of just one particular\n  member ;\n- The facade is concrete. It can either be a Scala `object` or a `class` ;\n- The facade has a\n  [“JS native” type](https://www.scala-js.org/doc/interoperability/facade-types.html).\n\n> {.note}\n> Other styles of facades (importing a member in particular, importing functions and classes,\n> importing local JavaScript files, etc.) can be found in\n> [these tests](https://github.com/scalacenter/scalajs-bundler/blob/main/sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade-examples).\n\nFinally, in your Scala code, just refer to the `foo` object:\n\n~~~ scala\nobject Main {\n  def main(args: Array[String]): Unit = {\n    println(foo.bar(42))\n  }\n}\n~~~\n\n## How to publish a facade for an npm module? {#publish}\n\nCreate a project for the facade and enable the `ScalaJSBundlerPlugin` as described\n[here](getting-started.md).\n\nImplement the facade as explained in the [above section](cookbook.md#facade).\n\nPublish the Scala.js project [as usual](http://www.scala-sbt.org/1.0/docs/Publishing.html).\n\nFinally, to use the facade from another Scala.js project, this one needs both to add a\ndependency on the facade and to enable the `ScalaJSBundlerPlugin` plugin.\n\n> {.warning}\n> Projects that **use** the facade also have to enable the `ScalaJSBundlerPlugin` plugin,\n> otherwise the dependencies of the facade will not be resolved.\n\n## How to use an existing facade assuming the JS library to be exposed to the global namespace? {#global-namespace}\n\nWebpack is able to require external modules by using [imports-loader](https://github.com/webpack-contrib/imports-loader)\nand expose them to the global namespace by using [expose-loader](https://github.com/webpack/expose-loader).\nThus, you can write a custom webpack configuration file that uses this loaders to expose the required\nmodules to the global namespace. Typically, this file will look like this:\n\n~~~ javascript src=../../../sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/global-namespace-with-jsdom-unit-testing/common.webpack.config.js\n~~~\n\nAlso, tweak your `build.sbt` to add the corresponding NPM dependencies and to use the\ncustom webpack configuration file:\n\n~~~ scala src=../../../sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/global-namespace-with-jsdom-unit-testing/build.sbt#relevant-settings\n~~~\n\nYou can find a fully working example\n[here](https://github.com/scalacenter/scalajs-bundler/blob/main/sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/global-namespace-with-jsdom-unit-testing).\n\n## How to bundle an application having several entry points as exports? {#several-entry-points}\n\nBy default, `ScalaJSBundlerPlugin` assumes that your application only has a main class, activated through\n`scalaJSUseMainModuleInitializer := true`, and disregards top-level *exports*. If you have exports that\nneed to be exposed as several entry points, this will not work.\n\nIn such a case, you can use `BundlingMode.LibraryAndApplication()`.\n\n`build.sbt`:\n~~~ scala src=../../../sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/library/build.sbt#relevant-settings\n~~~\n\nThen, assuming that you defined the following library:\n\n~~~ scala src=\"../../../sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/library/src/main/scala/example/Library.scala#library-definition\"\n~~~\n\nYou can call its methods as follows from your JavaScript code:\n\n~~~ scala src=\"../../../sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/library/index.html#library-usage\"\n~~~\n\n## How to improve the performance of the bundling process? {#performance}\n\nYou can enable the [library-only bundling mode](reference.md#bundling-mode-library-only) and disable source maps:\n\n~~~ scala\nwebpackBundlingMode := BundlingMode.LibraryOnly()\nemitSourceMaps := false\n~~~\n\n## How to select specific files from the `BundlingMode.Library` output\n\nIn [library-only bundling mode](reference.md#bundling-mode-library-only) and\n[library with application bundling mode](reference.md#bundling-mode-library-and-application), the `webpack` task\nproduces multiple files. In order to determine which of these files is, for instance, the\n[BundlerFileType.Application](api:scalajsbundler.BundlerFileType$$Application$), you\ncan use the `_.metadata` property of the files, like this:\n\n~~~ scala src=\"../../../sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/static/build.sbt#filter-files\"\n~~~\n\n## How to rebuild and reload your page on code changes? {#webpack-dev-server}\n\n`scalajs-bundler` includes a simple wrapper over webpack-dev-server to simplify your\nworkflow. It is exposed as two stage-level tasks (`startWebpackDevServer` and\n`stopWebpackDevServer`).\nThe standard work session looks like this:\n\n1. Spawn background server process:\n    ~~~\n    > fastOptJS::startWebpackDevServer\n    ~~~\n    By default the server is started on port `8080`. Use `webpackDevServerPort` setting to change this.\n2. Instruct SBT to rebuild on source changes:\n    ~~~\n    > ~fastOptJS\n    ~~~\n3. Now each time you change a source file, Scala.js recompiles it, and webpack-dev-server\n    switches to the updated version.\n4. Shut down the background process:\n    ~~~\n    > fastOptJS::stopWebpackDevServer\n    ~~~\n\nAdditional arguments can be passed to webpack-dev-server via `webpackDevServerExtraArgs`\nsetting. For example, you can add the following to your `build.sbt` to make your page\nreload on every change:\n~~~\nwebpackDevServerExtraArgs := Seq(\"--inline\")\n~~~\n\n## How to pass extra parameters to webpack\n\n`scalajs-bundler` invokes `webpack` with a configuration generated either automatically from the build or set with `webpackConfigFile`.\n`webpack` is then called with the following arguments:\n\n~~~\n--config <configfile>\n~~~\n\nYou can add extra params to the `webpack` call, for example, to increase debugging\n\n~~~\nwebpackExtraArgs := Seq(\"--profile\", \"--progress\", \"true\")\n~~~\n\n**Note** Params are passed verbatim, they are not sanitized and could produce errors when passed to webpack.\nIn particular, don't attempt to override the `--config` param.\n\n## How to use webpack 4\n\n`scalajs-bundler` (version 0.12.0 onwards) supports webpack 4. To enable webpack 4, set the correct versions in `build.sbt`\n\n~~~ scala\nversion in webpack := \"4.8.1\"\n\nversion in startWebpackDevServer := \"3.1.4\"\n~~~\n\nAdditionally, you need to update any webpack plugins your config uses, to Webpack 4 compatible versions.\n\nWebpack 4 has the potential to substantially reduce your webpack compilation times (80% reductions have been observed but your mileage may vary)\n\n## How to get and use a list of assets\n\n`scalajs-bundler` (version 0.13.0 onwards) will export a list of all assets produced by webpack. You can read that list on sbt\n\n~~~ scala\nval files = (webpack in (Compile, fullOptJS)).value\n~~~\n\nYou can this list e.g. with [sbt-native-packager](https://github.com/sbt/sbt-native-packager)` to add mappings as:\n~~~ scala src=\"../../../sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets-cookbook/build.sbt#scalajs-files\"\n~~~\n\nThis will add all artifacts produced by the fully optimized Scala.JS run to the 'assets' directory of the target archive.\n\nIf you need to package additional libraries that have been downloaded by `scalajs-bundler`, you can do something like:\n~~~ scala src=\"../../../sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets-cookbook/build.sbt#additional-files\"\n~~~\nAlso, any static resources that you would like to have in the resulting archive (i.e. `index.html`), should live inside the `src/universal` directory of your project.\n"
  },
  {
    "path": "manual/src/ornate/getting-started.md",
    "content": "# Getting started\n\n## Basic setup\n\nYou need to have `npm` installed on your system.\n\nAdd the `sbt-scalajs-bundler` plugin to your Scala.js project, in your `project/plugins.sbt` file:\n\n~~~ scala expandVars=true\n// For Scala.js 1.x\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % \"{{version}}\")\n// Or, for Scala.js 0.6.x\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler-sjs06\" % \"{{version}}\")\n~~~\n\n> {.note}\n> The plugin requires Scala.js 0.6.26+ or 1.0.0-RC1 and either\n> sbt 0.13.17+ or 1.2.1+.\n\nEnable the `ScalaJSBundlerPlugin`, in your `build.sbt` file:\n\n~~~ scala\nenablePlugins(ScalaJSBundlerPlugin)\n~~~\n\nIf you have a `main` method, make sure that you enable the Scala.js main module initializer with the following setting:\n\n~~~ scala\nscalaJSUseMainModuleInitializer := true\n~~~\n\nAdd dependencies to the npm packages your application requires, in your `build.sbt` file, e.g.:\n\n~~~ scala\nnpmDependencies in Compile += \"snabbdom\" -> \"0.5.3\"\n~~~\n\n> {.note}\n> You will most probably want to write a [Scala.js facade](https://www.scala-js.org/doc/interoperability/facade-types.html#-imports-from-other-javascript-modules)\n> for the JavaScript module. You can find information on how to do that in the\n> [cookbook](cookbook.md#facade), or draw inspiration from\n> [this example](https://github.com/scalacenter/scalajs-bundler/blob/main/sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/browserless/src/main/scala/uuid/uuid.scala).\n\nThen, use the `fastOptJS::webpack` sbt command to download the npm packages and bundle your Scala.js\napplication and its dependencies into a single JavaScript file executable by a web browser.\n\nIn this example, the `webpack` sbt task produces a single file located at\n`target/scala-2.12/scalajs-bundler/main/<project-id>-fastopt-bundle.js`.\n\nSee complete examples in the [tests](https://github.com/scalacenter/scalajs-bundler/tree/main/sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler).\n\n## Integrating with sbt-web {#sbt-web}\n\nFor sbt-web integration use the `sbt-web-scalajs-bundler` plugin instead of `sbt-scalajs-bundler`:\n\n~~~ scala expandVars=true\n// For Scala.js 1.x\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-web-scalajs-bundler\" % \"{{version}}\")\n// Or, for Scala.js 0.6.x\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-web-scalajs-bundler-sjs06\" % \"{{version}}\")\n~~~\n\nThen, enable the `WebScalaJSBundlerPlugin` on the project that uses sbt-web:\n\n~~~ scala\nlazy val server = project\n  .settings(\n    scalaJSProjects := Seq(client),\n    pipelineStages in Assets := Seq(scalaJSPipeline)\n  )\n  .enablePlugins(WebScalaJSBundlerPlugin)\n\nlazy val client = project.enablePlugins(ScalaJSBundlerPlugin)\n~~~\n\nYou also need to setup the `ScalaJSBundlerPlugin` on the Scala.js project, as described in the preceding section, and\nthe `sbt-web-scalajs` plugins as described in [their documentation](https://github.com/vmunier/sbt-web-scalajs).\nNote that `sbt-web-scalajs`'s `ScalaJSWeb` plugin must **not** be enabled, because `ScalaJSWeb` will create source\nmappings to source files copied to a hash path, which conflict with `ScalaJSBundlerPlugin`'s webpack-based source mappings.\n\nThe `WebScalaJSBundlerPlugin` plugin automatically configures the `scalaJSPipeline` task to use\nthe bundles rather than the output of the Scala.js compilation.\n\nYou can see a complete example [here](https://github.com/scalacenter/scalajs-bundler/tree/ma/sbt-web-scalajs-bundler/src/sbt-test/sbt-web-scalajs-bundler/play).\n"
  },
  {
    "path": "manual/src/ornate/index.md",
    "content": "# scalajs-bundler\n\nscalajs-bundler is a module bundler for Scala.js projects that use npm packages: it bundles the .js file\nemitted by the Scala.js compiler with its npm dependencies into a single .js file executable by Web browsers.\n\nscalajs-bundler uses [npm](https://www.npmjs.com) and [webpack](https://webpack.github.io/) under the hood.\n\nLast stable version is ![](config:version):\n\n~~~ scala expandVars=true\n// For Scala.js 1.x\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % \"{{version}}\")\n// Or, for Scala.js 0.6.x\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler-sjs06\" % \"{{version}}\")\n~~~\n\nIf you're using [sbt-crossproject](https://github.com/portable-scala/sbt-crossproject) you need to add plugin via `jsConfigure`:\n\n~~~ scala expandVars=true\nlazy val cross = crossProject(JSPlatform, JVMPlatform).in(file(\".\"))\n  .jvmSettings(BuildSettings.jvmSettings)\n  .jsSettings(BuildSettings.jsSettings)\n  .jsConfigure { project => project.enablePlugins(ScalaJSBundlerPlugin) }\n~~~\n\nSee the [**getting started**](getting-started.md) page for more details about\nthe setup process.\n"
  },
  {
    "path": "manual/src/ornate/motivation.md",
    "content": "# Motivation\n\nThe most popular JavaScript package registry is npm. Scala.js projects are usually based on sbt,\nwhich has no knowledge of npm. So, how can Scala.js developers get an *integrated experience* when\nthey use libraries published on npm?\n\n## WebJars\n\nA first solution is to use [WebJars](http://www.webjars.org/). WebJars wrap .js files into .jar\narchives published on maven central, so that Scala developers can depend on them just like\nthey depend on JVM libraries. However, WebJars have limitations.\n\nFirst, npm packages are not automatically available as WebJars as soon as they are published on\nthe npm registry. So, WebJars users have to explicitly publish these npm packages as .jar packages.\nThis is just a matter of filling and submitting a form with the name and version of the package, \nbut, still, this is one extra step.\n\nSecond, the tool that re-publishes npm packages as .jar packages does not keep track of\n[transitive dependencies](https://github.com/webjars/webjars/issues/1186).\nIt means that when your program depends on a library `foo` that itself depends on a library `bar`,\nthen you have to explicitly convert both and depend on both in your program. This situation\nmight turn into a dependency management hell.\n\n## Double build\n\nAnother solution consists in having two build systems: one for the Scala world and one for\nthe npm world. At some point, the npm build writes files consumed by the Scala application.\n\nTypically, the npm build defines npm dependencies and bundles them into a single .js\nfile suitable for web browser consumption and that the Scala.js program can depend\non (e.g. using `jsDependencies`).\n\nThis approach works well and allows developers to use whatever tools they want to process\nthe npm dependencies.\n\nHowever, having two build systems is not really an _integrated_ developer experience:\ndevelopers have to setup two builds, run two shells, and manually take care of the\nrelationship between the two builds.\n\n## scalajs-bundler\n\nscalajs-bundler aims to provide an integrated solution to work with npm packages from\nScala.js projects. It lets developers define their npm dependencies from within their sbt build,\nfetches them (using npm itself), and bundles them with the output of the Scala.js compilation.\nThe result is a single .js file suitable for web browser consumption.\n"
  },
  {
    "path": "manual/src/ornate/reference.md",
    "content": "# Reference\n\n## `ScalaJSBundlerPlugin`\n\nThe `ScalaJSBundlerPlugin` sbt plugin automatically enables `ScalaJSPlugin` on the project. It configures\nthe kind of output of the project to be `ModuleKind.CommonJSModule`. Finally, it also configures its\nexecution environment so that npm packages are fetched (by running the `npm update` command in the\nproject’s target directory) before the project is `run` or `test`ed.\n\nIt is also possible to bundle the application and its dependencies into a single .js file by using\nthe `webpack` task scoped to a Scala.js stage (`fastOptJS` or `fullOptJS`):\n\n~~~\n> fastOptJS::webpack\n~~~\n\nThe `webpack` task returns a list of artifacts produced by the bundling process.\n\n### JavaScript Dependencies {#npm-dependencies}\n\nTo define the npm packages your project depends on, use the `npmDependencies` key:\n\n~~~ scala\nnpmDependencies in Compile += \"uuid\" -> \"~3.1.0\"\n~~~\n\nYou can also scope dependencies to `Test`:\n\n~~~ scala\nnpmDependencies in Test += \"jasmine\" -> \"2.5.2\"\n~~~\n\n> {.note}\n> Your facades must use\n> [`@JSImport`](https://www.scala-js.org/doc/interoperability/facade-types.html#a-nameimporta-imports-from-other-javascript-modules)\n> in order to work with the npm modules, otherwise you will need some additional configuration, as explained\n> [here](cookbook.md#global-namespace).\n\nLast but not least, the `.js` files that are in your classpath and in the `jsSourceDirectories` are automatically\ncopied to the working directory of the `node` command. This means that you can also `@JSImport` these modules from\nyour Scala facades (you can see an example\n[here](https://github.com/scalacenter/scalajs-bundler/blob/main/sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-resources/src/main/scala/example/MyModule.scala#L6)).\n\n### jsdom Support for Tests {#jsdom}\n\nIf your tests execution environment require the DOM, add the following line to your build:\n\n~~~ scala\nrequireJsDomEnv in Test := true\n~~~\n\nThen, `ScalaJSBundlerPlugin` will automatically download jsdom and bundle the tests before\ntheir execution so that they can be loaded by jsdom.\n\nYou can find an example of project requiring the DOM for its tests\n[here](https://github.com/scalacenter/scalajs-bundler/blob/main/sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/static/).\n\n### Yarn {#yarn}\n\nBy default, `npm` is used to fetch the dependencies but you can use [Yarn](https://yarnpkg.com/) by setting the\n`useYarn` key to `true`:\n\n~~~ scala\nuseYarn := true\n~~~\n\nIf your sbt (sub-)project directory contains a `yarn.lock`, it will be used. Else, a new one will be created. You should check `yarn.lock` into source control.\n\nYarn 0.22.0+ must be available on your machine.\n\n### Bundling Mode {#bundling-mode}\n\nEach time you change something in your application source code and compile the project, Scala.js emits a new .js \nfile that can weigh several MBs if your application is large. Scalajs-bundler provides\na few different options with respect to handling this large output file, controlled by setting the optional\n`webpackBundlingMode` key and can be scoped to a Scala.js stage (`fastOptJS` or `fullOptJS`).\n\n#### Application (default) {#bundling-mode-application}\n\n`webpackBundlingMode := BundlingMode.Application` generates a webpack config that simply processes the Scala.js output file as an \nentrypoint. This means that webpack loaders, plugins, etc will work as usual. It also means that webpack will \nhave to process a very large Scala.Js output file.\n\nTurning this CommonJS module into code executable by web browsers takes time, often upwards of a minute. \n\nNonetheless, this is identical to what you'd get if were to duplicate your workflow outside scalajs-bundler, \nso it remains the default.\n\n#### Library Only {#bundling-mode-library-only}\n\nYou can get a much faster “change source and reload application” workflow by setting the \n`webpackBundlingMode := BundlingMode.LibraryOnly()` key. This bundling mode avoids having webpack process the entire\nScala.js output, but instead uses webpack to bundle all the javascript dependencies (determined via `@JSImport` \nand any changes to the `webpack.config.js`). This is accomplished by setting the webpack `output.library` and \n`output.libraryTarget` keys in the webpack.config. By default, this generates a global variable named\n`ScalaJSBundlerLibrary`, but if needed, that variable name can be overridden via the `exportedName` \nparameter provided to `BundlingMode.LibraryOnly`.\n\nThe drawback of this mode is that because the output of Scala.js is not processed by Webpack, it is\nstill a CommonJS module that is not directly executable by web browsers. This problem is addressed\nby including a special “loader” before including the Scala.js module.\n\n> {.warning}\n> The inclusion of a CommonJS module in the web browser is not guaranteed to work. In particular,\n> in `fullOptJS` mode the name mangler might produce names that could clash with other existing\n> global names. For this reason, we don’t recommend using the `LibraryOnly` bundling mode in `fullOptJS`,\n> or in production.\n\nIn order to use this mode, instead of including `yourapp-bundle.js` in your page, you will need to include\n`yourapp-library.js` (which contains all the application libraries bundled into a single file),\n`yourapp-loader.js` (which contains a hack to make the application work), and `yourapp-fastopt.js` or\n`yourapp-opt.js` (which contains the output of Scala.js, that is a CommonJS module). If you're using Play \nFramework, you could use a twirl template similar to this one:\n\n~~~ html\n@(projectName: String,\n  assets: String => String,\n  resourceExists: String => Boolean,\n  htmlAttributes: Html = Html(\"\")\n)\n\n@defining(s\"${projectName.toLowerCase}\") { name =>\n  @Seq(s\"$name-opt-library.js\", s\"$name-fastopt-library.js\").find(resourceExists).map(name => jsScript(assets(name), htmlAttributes))\n}\n<script language=\"JavaScript\">\nvar exports = window;\nexports.require = window[\"ScalaJSBundlerLibrary\"].require;\n</script>\n@defining(s\"${projectName.toLowerCase}\") { name =>\n  @Seq(s\"$name-opt.js\", s\"$name-fastopt.js\").find(resourceExists).map(name => jsScript(assets(name), htmlAttributes))\n}\n~~~\n\nThe default variable global for the library is `ScalaJsBundlerDependencies`. Should you need to change it, \nyou can provide a new variable name to the configuration, such as `webpackBundlingMode := BundlingMode.LibrariesOnly(\"myLib\")`.\n\n##### Benefits\n\nBy avoiding processing the entire Scala.js output file, webpack times from 10's of seconds to minutes to \na couple of seconds, depending on how many dependencies webpack has to resolve. In addition, since the \nmodule references are all still managed by webpack, any custom loaders such as the `html-loader` or `text-loader`\nwill work as usual. Other webpack configuration such as external modules also work out of the box.\n\nBy splitting the output into a separate library and Scala.js app we are able to leverage browser caching for most\nreloads, since it's seldom that both .js assets and Scala.js assets change at the same time. \n\nBy avoiding any post-processing of the Scala.js output, we leave the sourcemap generated by the Scala.js compiler\nentirely intact. This means we avoid any translation or lookup errors introduced by webpack, and also means\nwe save a bunch more processing time even if sourcemaps are enabled.\n\n##### How It Works\nScalajs-bundler has a unique advantage in the JavaScript build ecosystem in that it runs inside SBT and has\naccess to the Scala.Js compiler internals. By leveraging these, we can generate a fake `entrypoint.js` file that \nrepresents all the `@JSImport`s from a Scala.JS project. We can use this entrypoint to generate a library file\nthat provides access to all those imports without webpack having to ever process the entire Scala.js output. \n\nInside the `entrypoint.js` file we also provide a trivial `require` implementation that provides access to the\nmodules which were imported.\n\nAll that remains is to provide an `exports` variable with a reference to the `require` implementation\nfor the Scala.js out to hang onto, which is what the loader provides.\n\n#### Library and Application {#bundling-mode-library-and-application}\n\n`bundlingMode := BundlingMode.LibraryAndApplication()` builds on `BundlingMode.LibraryOnly` and attempts to \nproduce only one artifact (like the `Application` bundling mode) without the overhead processing the entire\nScala.js output file. \nIt uses the same library file generation process as `BundlingMode.LibraryOnly`. It then bundles that library, \nthe loader, and the Scala.js output into a `yourapp-bundle` file by concatenating them. If `enableSourceMaps := true`, \nit will attempt to use the node.js `concat-with-sourcemaps` module to combine the sourcemaps as well. \n\nIf you need interoperability with the full `Application` mode or somehow can't handle the two files generated\nby the `LibraryOnly()` mode, this mode may be useful for you. However, it relies on post-processing and eliminates\nsome of the benefits of the `LibraryOnly` mode, so consider carefully if you really need it before turning it on.\n\n### Tasks and Settings {#tasks-and-settings}\n\nThe tasks and settings that control the plugin are documented in the API documentation\nof the [ScalaJSBundlerPlugin](api:scalajsbundler.sbtplugin.ScalaJSBundlerPlugin$).\n\n## `WebScalaJSBundlerPlugin`\n\nThe `WebScalaJSBundlerPlugin` provides integration with [sbt-web-scalajs](https://github.com/vmunier/sbt-web-scalajs).\nEnable this plugin on JVM projects that need to use .js artifacts produced by Scala.js projects (ie in places\nwhere you used to enable `WebScalaJS`).\n\nThe plugin tunes the `scalaJSPipeline` to use the bundles produced by webpack rather than the direct\noutput of the Scala.js compilation.\n\n### Importing Assets from NPM Packages {#npm-assets}\n\nSome NPM packages also contain static assets (e.g. fonts, stylesheets, images, etc.). You can make them available\nas sbt-web assets as follows:\n\n~~~ scala\nnpmAssets ++= NpmAssets.ofProject(client) { nodeModules =>\n  (nodeModules / \"font-awesome\").allPaths // sbt 1.0.0+\n}.value\n~~~\n\n> Note: for older sbt versions use `(nodeModules / \"font-awesome\").***` instead.\n\nWhere `client` is the identifier of an sbt project that uses the `ScalaJSBundlerPlugin`. The above configuration\nmakes all the files within the `font-awesome` package available as sbt-web assets.\nThese assets keep their path prefix relative to the `node_modules` directory: for instance the asset path of the\n`css/font-awesome.min.css` resource is `font-awesome/css/font-awesome.min.css`.\n\n### Tasks and Settings {#web-tasks-and-settings}\n\nThe tasks and settings that control the plugin are documented in the API documentation\nof the [WebScalaJSBundlerPlugin](api:scalajsbundler.sbtplugin.WebScalaJSBundlerPlugin$).\n"
  },
  {
    "path": "manual/src/ornate.conf",
    "content": "global {\n  toc = [\n    { title = \"Introduction\", url = \"index.md\" }\n    motivation.md\n    getting-started.md\n    reference.md\n    cookbook.md\n    community.md\n    changelog.md\n  ]\n}\n\nmeta {\n  siteTitle = \"scalajs-bundler\"\n}\n\nversion = ${version}\n\nextension.scaladocLinks {\n  api {\n    index = \"unchecked:/api/latest/index.html\"\n  }\n}"
  },
  {
    "path": "project/build.properties",
    "content": "sbt.version = 1.8.2\n"
  },
  {
    "path": "project/plugins.sbt",
    "content": "addSbtPlugin(\"com.typesafe.sbt\"  % \"sbt-site\"       % \"1.4.1\")\naddSbtPlugin(\"com.novocode\"      % \"sbt-ornate\"     % \"0.6\")\naddSbtPlugin(\"com.github.sbt\"      % \"sbt-unidoc\"     % \"0.5.0\")\naddSbtPlugin(\"com.eed3si9n\"      % \"sbt-buildinfo\"  % \"0.11.0\")\naddSbtPlugin(\"com.github.sbt\"      % \"sbt-ci-release\" % \"1.5.12\")\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/BundlerFile.scala",
    "content": "package scalajsbundler\n\nimport java.io.File\nimport java.nio.file.Path\n\nimport scalajsbundler.Stats.WebpackStats\nimport scalajsbundler.util.CachedBundleFiles\nimport scala.collection.immutable.ListSet\n\n/**\n  * Files used in the `ScalaJSBundler` pipeline.\n  */\nsealed trait BundlerFile extends Product with Serializable {\n  def file: File\n}\n\nobject BundlerFile {\n  /**\n    * Files that may be inputs to the webpack process\n    */\n  sealed trait WebpackInput extends BundlerFile {\n    def project: String\n  }\n\n  /**\n    * Internal-only files\n    */\n  sealed abstract class Internal extends BundlerFile\n\n  /**\n    * A library-mode entrypoint file\n    * @param application The [[Application]] this entrypoint was generated from\n    * @param file The file containing the entry point\n    */\n  case class EntryPoint(application: Application, file: java.io.File)\n      extends Internal\n      with WebpackInput {\n    def project: String = application.project\n  }\n\n  object EntryPoint {\n    /** Filename of the generated bundle, given its module entry name */\n    def fileName(entry: String): String = s\"$entry-entrypoint.js\"\n  }\n\n  /**\n    * The package.json file, used for populating the node_modules folder\n    *\n    * @param file The file reference for the package.json\n    */\n  case class PackageJson(file: java.io.File) extends Internal\n\n  /**\n    * A webpack configuration file.\n    *\n    * @param application The [[Application]] this file runs webpack for\n    * @param file The webpack.config.js file reference\n    */\n  case class WebpackConfig(application: Application, file: java.io.File)\n      extends Internal {\n    def project: String = application.project\n\n    def targetDir: Path = file.getParentFile.toPath\n\n    /**\n      * Returns the Library identifying the asset produced by scala.js through webpack stats\n      */\n    def asLibrary(stats: Option[WebpackStats]): Library =\n      Library(project,\n              stats.flatMap { s =>\n                s.resolveAsset(targetDir, project)\n              }.getOrElse(targetDir.resolve(Library.fileName(project)).toFile),\n              stats.map { s =>\n                s.resolveAllAssets(targetDir)\n              }.getOrElse(Nil)\n            )\n\n    /**\n      * Returns library from a set of cached files\n      * By convention the first element is the `file` and the rest are the assets\n      */\n    def asLibraryFromCached(cached: Set[File]): Library = {\n      assert(cached.size >= 1)\n      val assets = if (cached.size == 1) Nil else cached.tail.toList\n      Library(project, cached.head, assets)\n    }\n\n    /**\n      * Returns the Application for this configuration identifying the asset produced by scala.js through webpack stats\n      */\n    def asApplicationBundle(stats: Option[WebpackStats]): ApplicationBundle =\n      ApplicationBundle(project,\n                        stats.flatMap { s =>\n                          s.resolveAsset(targetDir, project)\n                        }.getOrElse(targetDir.resolve(ApplicationBundle.fileName(project)).toFile),\n                        stats.map { s =>\n                          s.resolveAllAssets(targetDir)\n                        }.getOrElse(Nil))\n\n    /**\n      * Returns an application bundle from a set of cached files\n      * By convention the first element is the `file` and the rest are the assets\n      */\n    def asApplicationBundleFromCached(cached: Set[File]): ApplicationBundle = {\n      assert(cached.size >= 1)\n      val assets = if (cached.size == 1) Nil else cached.tail.toList\n      ApplicationBundle(project, cached.head, assets)\n    }\n  }\n\n  /**\n    * Public webpack artifacts -- those that might be served to clients or packaged\n    */\n  sealed abstract class Public extends BundlerFile {\n    def project: String\n    // Attributed files, the first is the main file and the rest are assets\n    def attributedFiles: (File, Seq[File]) = (file, Seq.empty)\n    def `type`: BundlerFileType\n  }\n\n  /**\n    * The Scala.js application itself, aka -fastopt.js or -opt.js\n    *\n    * @param project The application project name\n    * @param file The file containing the application javascript\n    * @param assets All the assets on the application\n    */\n  case class Application(project: String, file: File, assets: List[java.io.File])\n      extends Public\n      with WebpackInput {\n\n    def targetDir: Path = file.getParentFile.toPath\n\n    val `type`: BundlerFileType = BundlerFileType.Application\n    def asLoader: Loader =\n      Loader(this,\n             targetDir\n               .resolve(Loader.fileName(project))\n               .toFile)\n\n    def asEntryPoint: EntryPoint =\n      EntryPoint(this,\n                 targetDir\n                   .resolve(EntryPoint.fileName(project))\n                   .toFile)\n\n    def asApplicationBundle: ApplicationBundle =\n      ApplicationBundle(project,\n                        targetDir\n                          .resolve(ApplicationBundle.fileName(project))\n                          .toFile,\n                        assets)\n\n    /**\n      * Returns an application bundle from a set of cached files\n      */\n    def asApplicationBundleFromCached(cached: Set[File]): ApplicationBundle = {\n      assert(cached.size >= 1)\n      val assets = if (cached.size == 1) Nil else cached.tail.toList\n      ApplicationBundle(project, cached.head, assets)\n    }\n  }\n\n  /**\n    * A webpack library bundle, containing only libraries\n    * @param project The project the library bundle was generated for\n    * @param file The file containing the application javascript\n    * @param assets All the assets on the application\n    */\n  case class Library(project: String, file: File, assets: List[java.io.File]) extends Public {\n    val `type`: BundlerFileType = BundlerFileType.Library\n    val cached: ListSet[File] = CachedBundleFiles.cached(file, assets)\n\n    override def attributedFiles: (File, Seq[File]) = (file, assets)\n  }\n\n  object Library {\n\n    /** Suffix to apply to the libraries bundle */\n    val suffix: String = \"-library.js\"\n\n    /** Filename of the generated libraries bundle, given its module entry name */\n    def fileName(entry: String): String = s\"$entry$suffix\"\n  }\n\n  /**\n    * A webpack loader file. Allows an [[Application]] to access the dependencies bundled\n    * into a [[Library]]\n    * @param application Application to be loaded\n    * @param file Loader file\n    */\n  case class Loader(application: Application, file: java.io.File)\n      extends Public {\n    val `type`: BundlerFileType = BundlerFileType.Loader\n    def project: String = application.project\n  }\n\n  object Loader {\n\n    /** Suffix to apply to the loaders file */\n    val suffix: String = \"-loader.js\"\n\n    /** Filename of the generated bundle, given its module entry name */\n    def fileName(entry: String): String = s\"$entry$suffix\"\n  }\n\n  /**\n    * A fully self-contained application bundle, including all dependencies.\n    *\n    * @param project The project name\n    * @param file The file containing the application javascript\n    * @param assets All the assets on the application\n    */\n  case class ApplicationBundle(project: String, file: File, assets: List[java.io.File])\n      extends Public {\n    val `type`: BundlerFileType = BundlerFileType.ApplicationBundle\n\n    val cached: ListSet[File] = CachedBundleFiles.cached(file, assets)\n\n    override def attributedFiles: (File, Seq[File]) = (file, assets)\n  }\n\n  object ApplicationBundle {\n\n    /** Filename of the generated bundle, given its module entry name */\n    def fileName(entry: String): String = s\"$entry-bundle.js\"\n  }\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/BundlerFileType.scala",
    "content": "package scalajsbundler\n\n/**\n  * The type of a given [[BundlerFile.Public]]. Used for tagging files when they are produced by\n  * the ScalaJsBundler and handed off to other SBT tasks.\n  */\nsealed abstract class BundlerFileType\n\nobject BundlerFileType {\n\n  /**\n    * Scala.js application\n    */\n  case object Application extends BundlerFileType\n\n  /**\n    * Library dependencies provided by webpack\n    */\n  case object Library extends BundlerFileType\n\n  /**\n    * Dependency loader, provides [[Library]] dependencies to [[Application]]\n    */\n  case object Loader extends BundlerFileType\n\n  /**\n    * Fully linked application bundle, containing [[Application]] and all it's dependencies\n    */\n  case object ApplicationBundle extends BundlerFileType\n\n  /**\n    * An asset of the bundled application\n    */\n  case object Asset extends BundlerFileType\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/BundlingMode.scala",
    "content": "package scalajsbundler\n\n/**\n  * The BundlingMode dictates how webpack is configured for bundling. Please refer\n  * to the members of the sealed family details.\n  */\nsealed trait BundlingMode\n\nobject BundlingMode {\n\n  /**\n    * Bundle the entire application with webpack. Using this mode, the webpack `entry` key will\n    * contain the Scala.js output file. All dependencies will be resolved via webpack, and the entire\n    * bundle will be processed by any plugins. The output will be a runnable bundle, not a library.\n    *\n    * To see the specific webpack configuration that will be generated, refer to [[Webpack.writeConfigFile]].\n    */\n  case object Application extends BundlingMode\n\n  /**\n    * Shared base class for [[LibraryOnly]] and [[LibraryAndApplication]]. Both\n    * must provide an `exportedName` field indicating what javascript global\n    * the libraries will be exported to. Both library modes will generate an `entrypoints` file based\n    * on the Scala.js imports and use that as the `entrypoint` for the generated `webpack.config.js`. The webpack\n    * output will be a library, which will assign itself to a global variable when loaded.\n    *\n    * The `entrypoints` file also contains a `require` implementation, which can be exposed globally by including\n    * the `loader` file. Refer to [[util.JSBundler.loaderScript]] for an example of such a script.\n    *\n    * To see the specific webpack configuration that will be generated, refer to [[Webpack.writeConfigFile]].\n    */\n  sealed trait Library extends BundlingMode {\n\n    /**\n      * Name of the global variable containing the dependencies\n      */\n    def exportedName: String\n  }\n\n  /**\n    * Bundle only the libraries used by the application. This mode will generate an `entrypoints` file based\n    * on the Scala.js imports and use that as the entrypoint for the generated `webpack.config.js`. The webpack\n    * output will be a library, which will assign itself to a global variable when loaded.\n    *\n    * The `library` file produce in this mode must be combined with the `loader` and the Scala.js output in order\n    * to fully duplicate the usability of [[Application]] mode.\n    *\n    * Refer to [[Library]] for additional details.\n    *\n    */\n  case class LibraryOnly(exportedName: String = defaultLibraryExportedName) extends Library\n\n  /**\n    * Builds on [[LibraryOnly]] by generating the `loader` and concatenating it with the Scala.js output file. This\n    * output is designed to be a drop-in replacement for fully processing the file via webpack ([[Application]] mode). When\n    * `webpackEmitSourceMaps := true`, this mode will attempt to merge all the files using the node.js\n    * 'concat-with-sourcemaps' module.\n    *\n    * Refer to [[Library]] for additional details.\n    */\n  case class LibraryAndApplication(exportedName: String = defaultLibraryExportedName) extends Library\n\n  /**\n    * The default exported library name, used by [[LibraryOnly]] and [[LibraryAndApplication]]\n    */\n  val defaultLibraryExportedName = \"ScalaJSBundlerLibrary\"\n\n  /**\n    * The default BundlingMode used by the ScalaJSBundler\n    */\n  val Default: BundlingMode = Application\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/ExternalCommand.scala",
    "content": "package scalajsbundler\n\nimport java.io.File\n\nimport sbt._\nimport scalajsbundler.util.Commands\n\n/**\n  * Attempts to smoothen platform-specific differences when invoking commands.\n  *\n  * @param name Name of the command to run\n  */\nclass ExternalCommand(name: String) {\n\n  /**\n    * Runs the command `cmd`\n    * @param args Command arguments\n    * @param workingDir Working directory of the process\n    * @param logger Logger\n    */\n  def run(args: String*)(workingDir: File, logger: Logger): Unit =\n    Commands.run(cmd ++: args, workingDir, logger)\n\n  private val cmd = sys.props(\"os.name\").toLowerCase match {\n    case os if os.contains(\"win\") => Seq(\"cmd\", \"/c\", name)\n    case _                        => Seq(name)\n  }\n\n}\n\nobject Npm extends ExternalCommand(\"npm\")\n\nobject Yarn extends ExternalCommand(\"yarn\")\n\nobject ExternalCommand {\n  private val yarnOptions = List(\"--non-interactive\", \"--mutex\", \"network\")\n\n  private def syncLockfile(\n    lockFileName: String,\n    baseDir: File,\n    installDir: File,\n    logger: Logger\n  )(\n      command: => Unit\n  ): Unit = {\n    val sourceLockFile = baseDir / lockFileName\n    val targetLockFile = installDir / lockFileName\n\n    if (sourceLockFile.exists()) {\n      logger.info(\"Using lockfile \" + sourceLockFile)\n      IO.copyFile(sourceLockFile, targetLockFile)\n    }\n\n    command\n\n    if (targetLockFile.exists()) {\n      logger.debug(\"Wrote lockfile to \" + sourceLockFile)\n      IO.copyFile(targetLockFile, sourceLockFile)\n    }\n  }\n\n  private def syncYarnLockfile(\n    baseDir: File,\n    installDir: File,\n    logger: Logger\n  )(\n    command: => Unit\n  ): Unit = {\n    syncLockfile(\"yarn.lock\", baseDir, installDir, logger)(command)\n  }\n\n  private def syncNpmLockfile(\n    baseDir: File,\n    installDir: File,\n    logger: Logger\n  )(\n    command: => Unit\n  ): Unit = {\n    syncLockfile(\"package-lock.json\", baseDir, installDir, logger)(command)\n  }\n\n  /**\n    * Locally install NPM packages\n    *\n    * @param baseDir The (sub-)project directory which contains yarn.lock\n    * @param installDir The directory in which to install the packages\n    * @param useYarn Whether to use yarn or npm\n    * @param logger sbt logger\n    * @param npmExtraArgs Additional arguments to pass to npm\n    * @param npmPackages Packages to install (e.g. \"webpack\", \"webpack@2.2.1\")\n    */\n  def addPackages(baseDir: File,\n                  installDir: File,\n                  useYarn: Boolean,\n                  logger: Logger,\n                  npmExtraArgs: Seq[String],\n                  yarnExtraArgs: Seq[String])(npmPackages: String*): Unit =\n    if (useYarn) {\n      syncYarnLockfile(baseDir, installDir, logger) {\n        Yarn.run(\"add\" +: (yarnOptions ++ yarnExtraArgs ++ npmPackages): _*)(\n          installDir,\n          logger)\n      }\n    } else {\n      syncNpmLockfile(baseDir, installDir, logger) {\n        Npm.run(\"install\" +: (npmPackages ++ npmExtraArgs): _*)(installDir, logger)\n      }\n    }\n\n  def install(baseDir: File,\n              installDir: File,\n              useYarn: Boolean,\n              logger: Logger,\n              npmExtraArgs: Seq[String],\n              yarnExtraArgs: Seq[String]): Unit =\n    if (useYarn) {\n      syncYarnLockfile(baseDir, installDir, logger) {\n        Yarn.run(\"install\" +: (yarnOptions ++ yarnExtraArgs): _*)(installDir,\n                                                                  logger)\n      }\n    } else {\n      syncNpmLockfile(baseDir, installDir, logger) {\n        Npm.run(\"install\" +: npmExtraArgs: _*)(installDir, logger)\n      }\n    }\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/JSDOMNodeJSEnv.scala",
    "content": "package scalajsbundler\n\nimport scala.util.control.NonFatal\n\nimport sbt._\n\nimport java.io._\nimport java.nio.charset.StandardCharsets\nimport java.nio.file.{Files, Path, StandardCopyOption}\nimport java.net.URI\n\nimport org.scalajs.jsenv._\nimport org.scalajs.jsenv.nodejs._\nimport org.scalajs.jsenv.JSUtils.escapeJS\n\n// HACK Copy of Scala.js’ JSDOMNodeJSEnv. The only change is the ability to pass the directory in which jsdom has been installed\nclass JSDOMNodeJSEnv(config: JSDOMNodeJSEnv.Config) extends JSEnv {\n\n  val name: String = \"Node.js with JSDOM\"\n\n  def start(input: Seq[Input], runConfig: RunConfig): JSRun = {\n    JSDOMNodeJSEnv.validator.validate(runConfig)\n    val scripts = validateInput(input)\n    try {\n      internalStart(codeWithJSDOMContext(scripts), runConfig)\n    } catch {\n      case NonFatal(t) =>\n        JSRun.failed(t)\n    }\n  }\n\n  def startWithCom(input: Seq[Input], runConfig: RunConfig,\n      onMessage: String => Unit): JSComRun = {\n    JSDOMNodeJSEnv.validator.validate(runConfig)\n    val scripts = validateInput(input)\n    ComRun.start(runConfig, onMessage) { comLoader =>\n      internalStart(comLoader :: codeWithJSDOMContext(scripts), runConfig)\n    }\n  }\n\n  private def validateInput(input: Seq[Input]): List[Path] = {\n    input.map {\n      case Input.Script(script) =>\n        script\n\n      case _ =>\n        throw new UnsupportedInputException(input)\n    }.toList\n  }\n\n  private def internalStart(files: List[Path], runConfig: RunConfig): JSRun = {\n    val command = config.executable :: config.args\n    val externalConfig = ExternalJSRun.Config()\n      .withEnv(env)\n      .withRunConfig(runConfig)\n    ExternalJSRun.start(command, externalConfig)(JSDOMNodeJSEnv.write(files))\n  }\n\n  private def env: Map[String, String] =\n    Map(\"NODE_MODULE_CONTEXTS\" -> \"0\") ++ config.env\n\n  private def codeWithJSDOMContext(scripts: List[Path]): List[Path] = {\n    val scriptsURIs = scripts.map(JSDOMNodeJSEnv.materialize(_))\n    val scriptsURIsAsJSStrings =\n      scriptsURIs.map(uri => \"\\\"\" + escapeJS(uri.toASCIIString) + \"\\\"\")\n    val scriptsURIsJSArray = scriptsURIsAsJSStrings.mkString(\"[\", \", \", \"]\")\n    val jsDOMCode = {\n      s\"\"\"\n         |\n         |(function () {\n         |  var jsdom = require(\"jsdom\");\n         |\n         |  if (typeof jsdom.JSDOM === \"function\") {\n         |    // jsdom >= 10.0.0\n         |    var virtualConsole = new jsdom.VirtualConsole()\n         |      .sendTo(console, { omitJSDOMErrors: true });\n         |    virtualConsole.on(\"jsdomError\", function (error) {\n         |      try {\n         |        // Display as much info about the error as possible\n         |        if (error.detail && error.detail.stack) {\n         |          console.error(\"\" + error.detail);\n         |          console.error(error.detail.stack);\n         |        } else {\n         |          console.error(error);\n         |        }\n         |      } finally {\n         |        // Whatever happens, kill the process so that the run fails\n         |        process.exit(1);\n         |      }\n         |    });\n         |\n         |    var dom = new jsdom.JSDOM(\"\", {\n         |      virtualConsole: virtualConsole,\n         |      url: \"http://localhost/\",\n         |\n         |      /* Allow unrestricted <script> tags. This is exactly as\n         |       * \"dangerous\" as the arbitrary execution of script files we\n         |       * do in the non-jsdom Node.js env.\n         |       */\n         |      resources: \"usable\",\n         |      runScripts: \"dangerously\"\n         |    });\n         |\n         |    var window = dom.window;\n         |    window[\"scalajsCom\"] = global.scalajsCom;\n         |\n         |    var scriptsSrcs = $scriptsURIsJSArray;\n         |    for (var i = 0; i < scriptsSrcs.length; i++) {\n         |      var script = window.document.createElement(\"script\");\n         |      script.src = scriptsSrcs[i];\n         |      window.document.body.appendChild(script);\n         |    }\n         |  } else {\n         |    // jsdom v9.x\n         |    var virtualConsole = jsdom.createVirtualConsole()\n         |      .sendTo(console, { omitJsdomErrors: true });\n         |    virtualConsole.on(\"jsdomError\", function (error) {\n         |      /* This inelegant if + console.error is the only way I found\n         |       * to make sure the stack trace of the original error is\n         |       * printed out.\n         |       */\n         |      if (error.detail && error.detail.stack)\n         |        console.error(error.detail.stack);\n         |\n         |      // Throw the error anew to make sure the whole execution fails\n         |      throw error;\n         |    });\n         |\n         |    jsdom.env({\n         |      html: \"\",\n         |      virtualConsole: virtualConsole,\n         |      url: \"http://localhost/\",\n         |      created: function (error, window) {\n         |        if (error == null) {\n         |          window[\"scalajsCom\"] = global.scalajsCom;\n         |        } else {\n         |          throw error;\n         |        }\n         |      },\n         |      scripts: $scriptsURIsJSArray\n         |    });\n         |  }\n         |})();\n         |\"\"\".stripMargin\n    }\n\n    val codeFile = config.jsDomDirectory / \"codeWithJSDOMContext.js\"\n    IO.write(codeFile, jsDOMCode)\n    List(codeFile.toPath())\n  }\n}\n\nobject JSDOMNodeJSEnv {\n  private lazy val validator = ExternalJSRun.supports(RunConfig.Validator())\n\n  /* Unlike NodeJSEnv.scala upstream, we use `require` to load files on-disk\n   * rather than `runInThisContext`. We do this to preserve the enclosing\n   * directory of the scripts, which is necessary for Node.js to find npm\n   * packages in the directory hierarchy.\n   *\n   * We can do this in `JSDOMNodeJSEnv` because all the `files` are under our\n   * control, and we know that none of them declares `var`s at the top-level\n   * that would need to be accessed from other scripts.\n   */\n  private def write(files: List[Path])(out: OutputStream): Unit = {\n    val p = new PrintStream(out, false, \"UTF8\")\n    try {\n      def writeRunScript(path: Path): Unit = {\n        try {\n          val f = path.toFile\n          val pathJS = \"\\\"\" + escapeJS(f.getAbsolutePath) + \"\\\"\"\n          p.println(s\"\"\"require($pathJS);\"\"\")\n        } catch {\n          case _: UnsupportedOperationException =>\n            val code = new String(Files.readAllBytes(path), StandardCharsets.UTF_8)\n            val codeJS = \"\\\"\" + escapeJS(code) + \"\\\"\"\n            val pathJS = \"\\\"\" + escapeJS(path.toString) + \"\\\"\"\n            p.println(s\"\"\"\n              require('vm').runInThisContext(\n                $codeJS,\n                { filename: $pathJS, displayErrors: true }\n              );\n            \"\"\")\n        }\n      }\n\n      for (file <- files)\n        writeRunScript(file)\n    } finally {\n      p.close()\n    }\n  }\n\n  // tmpSuffixRE and tmpFile copied from HTMLRunnerBuilder.scala in Scala.js\n\n  private val tmpSuffixRE = \"\"\"[a-zA-Z0-9-_.]*$\"\"\".r\n\n  private def tmpFile(path: String, in: InputStream): URI = {\n    try {\n      /* - createTempFile requires a prefix of at least 3 chars\n       * - we use a safe part of the path as suffix so the extension stays (some\n       *   browsers need that) and there is a clue which file it came from.\n       */\n      val suffix = tmpSuffixRE.findFirstIn(path).orNull\n\n      val f = File.createTempFile(\"tmp-\", suffix)\n      f.deleteOnExit()\n      Files.copy(in, f.toPath(), StandardCopyOption.REPLACE_EXISTING)\n      f.toURI()\n    } finally {\n      in.close()\n    }\n  }\n\n  private def materialize(path: Path): URI = {\n    try {\n      path.toFile.toURI\n    } catch {\n      case _: UnsupportedOperationException =>\n        tmpFile(path.toString, Files.newInputStream(path))\n    }\n  }\n\n  final class Config private (\n    val jsDomDirectory: File,\n    val executable: String,\n    val args: List[String],\n    val env: Map[String, String]\n  ) {\n    private def this(jsDomDirectory: File) = {\n      this(\n        jsDomDirectory,\n        executable = \"node\",\n        args = Nil,\n        env = Map.empty\n      )\n    }\n\n    def withExecutable(executable: String): Config =\n      copy(executable = executable)\n\n    def withArgs(args: List[String]): Config =\n      copy(args = args)\n\n    def withEnv(env: Map[String, String]): Config =\n      copy(env = env)\n\n    private def copy(\n      executable: String = executable,\n      args: List[String] = args,\n      env: Map[String, String] = env\n    ): Config = {\n      new Config(jsDomDirectory, executable, args, env)\n    }\n  }\n\n  object Config {\n    /** Returns a default configuration for a [[JSDOMNodeJSEnv]].\n      *\n      *  The defaults are:\n      *\n      *  - `executable`: `\"node\"`\n      *  - `args`: `Nil`\n      *  - `env`: `Map.empty`\n      */\n    def apply(jsDomDirectory: File): Config = new Config(jsDomDirectory)\n  }\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/JsDomTestEntries.scala",
    "content": "package scalajsbundler\n\nimport sbt._\n\nimport scalajsbundler.util.JS\n\nobject JsDomTestEntries {\n\n  /**\n    * Loads the output of Scala.js and exports all its exported properties to the global namespace,\n    * so that they are found by jsdom.\n    * @param sjsOutput Scala.js output\n    * @param loaderFile File to write the loader to\n    */\n  def writeLoader(sjsOutput: File, loaderFile: File): Unit = {\n    val window = JS.ref(\"window\")\n    val require = JS.ref(\"require\")\n    val Object = JS.ref(\"Object\")\n    val loader =\n      JS.let(\n        require.apply(JS.str(sjsOutput.absolutePath))\n      ) { tests =>\n        Object.dot(\"keys\").apply(tests).dot(\"forEach\").apply(JS.fun { key =>\n          window.bracket(key).assign(tests.bracket(key)) // Export all properties of the Scala.js module to the global namespace\n        })\n      }\n\n    IO.write(loaderFile, loader.show)\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/NpmDependencies.scala",
    "content": "package scalajsbundler\n\nimport java.io.{BufferedInputStream, FileInputStream}\nimport java.util.zip.ZipInputStream\n\nimport play.api.libs.functional.syntax._\nimport play.api.libs.json.{Format, JsPath, Json, OFormat}\nimport sbt._\nimport scalajsbundler.NpmDependencies.Dependencies\n\n/**\n  * NPM dependencies, for each configuration.\n  * This information can not be included in the pom.xml, so we\n  * serialize for each Scala.js artifact into an additional file\n  * in the artifact .jar.\n  */\ncase class NpmDependencies(\n  compileDependencies: Dependencies,\n  testDependencies: Dependencies,\n  compileDevDependencies: Dependencies,\n  testDevDependencies: Dependencies\n) {\n  /** Merge operator */\n  def ++ (that: NpmDependencies): NpmDependencies =\n    NpmDependencies(\n      compileDependencies ++ that.compileDependencies,\n      testDependencies ++ that.testDependencies,\n      compileDevDependencies ++ that.compileDevDependencies,\n      testDevDependencies ++ that.testDevDependencies\n    )\n}\n\nobject NpmDependencies {\n\n  /** Name of the file containing the NPM dependencies */\n  val manifestFileName = \"NPM_DEPENDENCIES\"\n\n  type Dependencies = List[(String, String)]\n\n  implicit val serializer: OFormat[NpmDependencies] = (\n    (JsPath \\ \"compile-dependencies\").format[Dependencies] and\n    (JsPath \\ \"test-dependencies\").format[Dependencies] and\n    (JsPath \\ \"compile-devDependencies\").format[Dependencies] and\n    (JsPath \\ \"test-devDependencies\").format[Dependencies]\n  )(NpmDependencies.apply, Function.unlift(NpmDependencies.unapply))\n\n  implicit def tuple2Serializer[A](implicit aSerializer: Format[A]): Format[(String, A)] =\n    implicitly[Format[Map[String, A]]].inmap(_.head, Map(_))\n\n  /**\n    * @param cp Classpath\n    * @return All the NPM dependencies found in the given classpath\n    */\n  def collectFromClasspath(cp: Def.Classpath): NpmDependencies =\n    (\n      for {\n        cpEntry <- Attributed.data(cp) if cpEntry.exists\n        results <-\n          if (cpEntry.isFile && cpEntry.name.endsWith(\".jar\")) {\n            val stream = new ZipInputStream(new BufferedInputStream(new FileInputStream(cpEntry)))\n            try {\n              Iterator.continually(stream.getNextEntry())\n                .takeWhile(_ != null)\n                .filter(_.getName == NpmDependencies.manifestFileName)\n                .map(_ => Json.parse(IO.readStream(stream)).as[NpmDependencies])\n                .to[Seq]\n            } finally {\n              stream.close()\n            }\n          } else if (cpEntry.isDirectory) {\n            for {\n              (file, _) <- Path.selectSubpaths(cpEntry, new ExactFilter(NpmDependencies.manifestFileName))\n            } yield {\n              Json.parse(IO.read(file)).as[NpmDependencies]\n            }\n          } else sys.error(s\"Illegal classpath entry: ${cpEntry.absolutePath}\")\n      } yield results\n    ).fold(NpmDependencies(Nil, Nil, Nil, Nil))(_ ++ _)\n\n  /**\n    * Writes the given dependencies into a manifest file\n    */\n  def writeManifest(\n    npmDependencies: NpmDependencies,\n    classDirectory: File\n  ): File = {\n    val manifestFile = classDirectory / manifestFileName\n    IO.write(manifestFile, Json.stringify(Json.toJson(npmDependencies)))\n    manifestFile\n  }\n\n}"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/NpmPackage.scala",
    "content": "package scalajsbundler\n\nimport play.api.libs.json.{JsPath, Json, Reads}\nimport sbt._\n\nimport scala.util.Try\n\ncase class NpmPackage(version: String) {\n  def major: Option[Int] = {\n    val r = \"\"\"^(\\d+)(\\..*|)$\"\"\".r\n    version match {\n      case r(v, _) => Try(v.toInt).toOption\n      case _ => None\n    }\n  }\n}\n\nobject NpmPackage {\n  implicit val npmPackageDeserializer: Reads[NpmPackage] =\n    (JsPath \\ \"version\").read[String].map(NpmPackage.apply)\n\n  def getForModule(targetDir: File, module: String): Option[NpmPackage] = {\n    val webpackPackageJsonFilePath = targetDir / \"node_modules\" / module / \"package.json\"\n\n    Try(Json.parse(IO.read(webpackPackageJsonFilePath)).as[NpmPackage]).toOption\n  }\n}"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/PackageJson.scala",
    "content": "package scalajsbundler\n\nimport sbt._\n\nimport scalajsbundler.util.JSON\n\nobject PackageJson {\n\n  /**\n    * Write a package.json file defining the NPM dependencies of the application, plus the ones\n    * required to do the bundling.\n    *\n    * @param log Logger\n    * @param targetFile File to write into\n    * @param npmDependencies NPM dependencies\n    * @param npmDevDependencies NPM devDependencies\n    * @param npmResolutions Resolutions to use in case of conflicting dependencies\n    * @param additionalNpmConfig Additional options to include in 'package.json'\n    * @param fullClasspath Classpath (used to look for dependencies of Scala.js libraries this project depends on)\n    * @param currentConfiguration Current configuration\n    * @return The created package.json file\n    */\n  def write(\n    log: Logger,\n    targetFile: File,\n    npmDependencies: Seq[(String, String)],\n    npmDevDependencies: Seq[(String, String)],\n    npmResolutions: Map[String, String],\n    additionalNpmConfig: Map[String, JSON],\n    fullClasspath: Seq[Attributed[File]],\n    currentConfiguration: Configuration,\n    webpackVersion: String,\n    webpackDevServerVersion: String,\n    webpackCliVersion: String\n  ): Unit = {\n    val npmManifestDependencies = NpmDependencies.collectFromClasspath(fullClasspath)\n    val dependencies =\n      npmDependencies ++ (\n        if (currentConfiguration == Compile) npmManifestDependencies.compileDependencies\n        else npmManifestDependencies.testDependencies\n      )\n\n    val sourceMapLoaderVersion =\n      NpmPackage(webpackVersion).major match {\n        case Some(5) => \"2.0.0\"\n        case Some(x) => sys.error(s\"Unsupported webpack major version $x\")\n        case None    => sys.error(\"No webpack version defined\")\n      }\n\n    val devDependencies =\n      npmDevDependencies ++ (\n        if (currentConfiguration == Compile) npmManifestDependencies.compileDevDependencies\n        else npmManifestDependencies.testDevDependencies\n      ) ++ Seq(\n        \"webpack\" -> webpackVersion,\n        \"webpack-cli\" -> webpackCliVersion,\n        \"webpack-dev-server\" -> webpackDevServerVersion,\n        \"concat-with-sourcemaps\" -> \"1.0.7\", // Used by the reload workflow\n        \"source-map-loader\" -> sourceMapLoaderVersion // Used by webpack when emitSourceMaps is enabled\n      )\n\n    val packageJson =\n      JSON.obj(\n        (\n          additionalNpmConfig.toSeq :+\n          \"dependencies\" -> JSON.objStr(resolveDependencies(dependencies, npmResolutions, log)) :+\n          \"devDependencies\" -> JSON.objStr(resolveDependencies(devDependencies, npmResolutions, log))\n        ): _*\n      )\n\n    log.debug(\"Writing 'package.json'\")\n    IO.write(targetFile, packageJson.toJson)\n  }\n\n  /**\n    * Resolves multiple occurrences of a dependency to a same package.\n    *\n    *  - If all the occurrences refer to the same version, pick this one ;\n    *  - If they refer to different versions, pick the one defined in `resolutions` (or fail\n    *    if there is no such resolution).\n    *\n    * @return The resolved dependencies\n    * @param dependencies The dependencies to resolve\n    * @param resolutions The resolutions to use in case of conflict (they will be ignored if there are no conflicts)\n    * @param log Logger\n    */\n  def resolveDependencies(\n    dependencies: Seq[(String, String)],\n    resolutions: Map[String, String],\n    log: Logger\n  ): List[(String, String)] ={\n    val resolvedDependencies =\n      dependencies\n        .groupBy { case (name, version) => name }\n        .mapValues(_.map(_._2).distinct)\n        .foldRight(List.empty[(String, String)]) { case ((name, versions), result) =>\n          val resolvedDependency =\n            versions match {\n              case Seq(single) =>\n                name -> single\n              case _ =>\n                val resolution = resolutions.get(name) match {\n                  case Some(v) => v\n                  case None => versions.mkString(\" \")\n                }\n                name -> resolution\n            }\n          resolvedDependency :: result\n        }\n\n    // Add a warning in case a resolution was defined but not used because the corresponding\n    // dependency was not in conflict.\n    val unusedResolutions =\n      resolutions.filter { case (name, resolution) =>\n        resolvedDependencies.exists { case (n, v) => n == name && v != resolution }\n      }\n    if (unusedResolutions.nonEmpty) {\n      log.warn(s\"Unused resolutions: $unusedResolutions\")\n    }\n\n    log.debug(s\"Resolved the following dependencies: $resolvedDependencies\")\n\n    resolvedDependencies\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/Stats.scala",
    "content": "\npackage scalajsbundler\n\nimport play.api.libs.json._\nimport play.api.libs.functional.syntax._\nimport sbt.Logger\nimport scala.math.max\nimport java.io.File\nimport java.nio.file.Path\n\n/**\n * Webpack stats model and json parsers\n */\nobject Stats {\n\n  final case class Asset(name: String, size: Long, emitted: Boolean, chunkNames: List[String]) {\n    def formattedSize: String = {\n      val oneKiB = 1024L\n      val oneMiB = oneKiB * oneKiB\n\n      if (size < oneKiB) s\"$size bytes\"\n      else if (size < oneMiB) f\"${size / oneKiB.toFloat}%1.2f KiB\"\n      else f\"${size / oneMiB.toFloat}%1.2f MiB\"\n    }\n  }\n\n  object formatting {\n\n    final case class Part(t: String, l: Int) {\n      def maxL(p: Part): Part =\n        copy(l = max(l, p.l))\n\n      def leftPad: String =\n        // String interpolation doesn't support dynamic padding\n        t.reverse.padTo(l, ' ').reverse.mkString\n    }\n\n    object Part {\n      def apply(t: String) = new Part(t, t.length)\n    }\n\n    final case class AssetLine(asset: Part, size: Part, emitted: Part, chunks: Part) {\n      def adjustPadding(p: AssetLine): AssetLine = copy(asset.maxL(p.asset), size.maxL(p.size), emitted.maxL(p.emitted), chunks.maxL(p.chunks))\n      def show: String = List(asset, size, emitted, chunks).map(_.leftPad).mkString(\"   \")\n    }\n\n    object AssetLine {\n      val Zero: AssetLine = AssetLine(Part(\"Asset\"), Part(\"Size\"), Part(\"\"), Part(\"Chunks\"))\n    }\n\n  }\n\n  final case class WebpackError(moduleName: String, message: String, loc: String)\n\n  final case class WebpackWarning(moduleName: String, message: String)\n\n  final case class WebpackStats(\n    version: String,\n    hash: String,\n    time: Long,\n    outputPath: Option[Path],\n    errors: List[WebpackError],\n    warnings: List[WebpackWarning],\n    assets: List[Asset]\n  ) {\n\n    /**\n      * Prints to the log an output similar to what webpack pushes to stdout\n      */\n    def print(log: Logger): Unit = {\n      import formatting._\n      // Print base info\n      List(s\"Version: $version\", s\"Hash: $hash\", s\"Time: ${time}ms\", s\"Path: ${outputPath.getOrElse(\"<default>\")}\").foreach(x => log.info(x))\n      log.info(\"\")\n      // Print the assets\n      assets.map { a =>\n        val emitted = if (a.emitted) \"[emitted]\" else \"\"\n        AssetLine(Part(a.name), Part(a.formattedSize), Part(emitted), Part(a.chunkNames.mkString(\"[\", \",\", \"]\")))\n      }.foldLeft(List(AssetLine.Zero)) {\n        case (lines, curr) =>\n          val adj = lines.map(_.adjustPadding(curr))\n          val adjNew = adj.headOption.fold(curr)(curr.adjustPadding)\n          (adjNew :: adj.reverse).reverse\n      }.foreach { l =>\n        log.info(l.show)\n      }\n      log.info(\"\")\n    }\n\n    /**\n      * Attempts to find the name of the asset for the project name\n      * Note that we only search on files ending on .js skipping e.g. map files\n      */\n    def assetName(project: String): Option[String] =\n      assets.find(a => a.chunkNames.contains(project) && a.name.endsWith(\".js\")).map(_.name)\n\n    /**\n     * Resolve the asset on the output path or the target dir if unavailable\n     */\n    def resolveAsset(altDir: Path, asset: String): Option[File] =\n      assetName(asset).map(a => outputPath.getOrElse(altDir).resolve(a).toFile)\n\n    /**\n     * Resolve alles asset on the output path or the target dir if unavailable\n     */\n    def resolveAllAssets(altDir: Path): List[File] =\n      assets.map(a => outputPath.getOrElse(altDir).resolve(a.name).toFile)\n  }\n\n  implicit val assetsReads: Reads[Asset] = (\n    (JsPath \\ \"name\").read[String] and\n    (JsPath \\ \"size\").read[Long] and\n    (JsPath \\ \"emitted\").read[Boolean] and\n    (JsPath \\ \"chunkNames\").read[List[String]]\n  )(Asset.apply _)\n\n  implicit val errorReads: Reads[WebpackError] = (\n    (JsPath \\ \"moduleName\").read[String] and\n      (JsPath \\ \"message\").read[String] and\n      (JsPath \\ \"loc\").read[String]\n    )(WebpackError.apply _)\n\n  implicit val warningReads: Reads[WebpackWarning] = (\n    (JsPath \\ \"moduleName\").read[String] and\n      (JsPath \\ \"message\").read[String]\n    )(WebpackWarning.apply _)\n\n  implicit val statsReads: Reads[WebpackStats] = (\n    (JsPath \\ \"version\").read[String] and\n    (JsPath \\ \"hash\").read[String] and\n    (JsPath \\ \"time\").read[Long] and\n    (JsPath \\ \"outputPath\").readNullable[String].map(x => x.map(new File(_).toPath)) and // It seems webpack 2 doesn't produce outputPath\n    (JsPath \\ \"errors\").read[List[WebpackError]] and\n    (JsPath \\ \"warnings\").read[List[WebpackWarning]] and\n    (JsPath \\ \"assets\").read[List[Asset]]\n  )(WebpackStats.apply _)\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/Webpack.scala",
    "content": "package scalajsbundler\n\nimport sbt._\nimport scalajsbundler.util.{Commands, JS}\nimport java.io.InputStream\n\nimport play.api.libs.json._\nimport Stats._\n\nimport scala.util.{Failure, Success, Try}\n\nobject Webpack {\n  // Represents webpack 5 modes\n  sealed trait WebpackMode {\n    def mode: String\n  }\n  case object DevelopmentMode extends WebpackMode {\n    val mode = \"development\"\n  }\n  case object ProductionMode extends WebpackMode {\n    val mode = \"production\"\n  }\n  object WebpackMode {\n    def fromBooleanProductionMode(productionMode: Boolean): WebpackMode =\n      if (productionMode) ProductionMode\n      else DevelopmentMode\n  }\n\n  /**\n    * Copies the custom webpack configuration file and the webpackResources to the target dir\n    *\n    * @param targetDir target directory\n    * @param webpackResources Resources to copy\n    * @param customConfigFile User supplied config file\n    * @return The copied config file.\n    */\n  def copyCustomWebpackConfigFiles(targetDir: File, webpackResources: Seq[File])(customConfigFile: File): File = {\n    def copyToWorkingDir(targetDir: File)(file: File): File = {\n      val copy = targetDir / file.name\n      IO.copyFile(file, copy)\n      copy\n    }\n\n    webpackResources.foreach(copyToWorkingDir(targetDir))\n    copyToWorkingDir(targetDir)(customConfigFile)\n  }\n\n  /**\n    * Writes the webpack configuration file. The output file is designed to be minimal, and to be extended,\n    * however, the `entry` and `output` keys must be preserved in order for the bundler to work as expected.\n    *\n    * @param emitSourceMaps Whether source maps is enabled at all\n    * @param entry The input entrypoint file to process via webpack\n    * @param webpackConfigFile webpack configuration file to write to\n    * @param libraryBundleName If defined, generate a library bundle named `libraryBundleName`\n    * @param log Logger\n    */\n  def writeConfigFile(\n    emitSourceMaps: Boolean,\n    entry: BundlerFile.WebpackInput,\n    webpackConfigFile: BundlerFile.WebpackConfig,\n    libraryBundleName: Option[String],\n    mode: WebpackMode,\n    devServerPort: Int,\n    log: Logger\n  ): Unit = {\n    val webpackConfigContent = generateConfigFile(emitSourceMaps, entry, webpackConfigFile, libraryBundleName, mode,\n      devServerPort)\n\n    log.info(\"Writing scalajs.webpack.config.js\")\n    IO.write(webpackConfigFile.file, webpackConfigContent.show)\n  }\n\n  private def generateConfigFile(\n    emitSourceMaps: Boolean,\n    entry: BundlerFile.WebpackInput,\n    webpackConfigFile: BundlerFile.WebpackConfig,\n    libraryBundleName: Option[String],\n    mode: WebpackMode,\n    devServerPort: Int\n  ): JS = {\n    val webpackNpmPackage = NpmPackage.getForModule(webpackConfigFile.targetDir.toFile, \"webpack\")\n    webpackNpmPackage.flatMap(_.major) match {\n      case Some(5) =>\n        // Build the output configuration, configured for library output\n        // if a library bundle name is provided\n        val output = libraryBundleName match {\n          case Some(bundleName) =>\n            JS.obj(\n              \"path\" -> JS.str(webpackConfigFile.targetDir.toAbsolutePath.toString),\n              \"filename\" -> JS.str(BundlerFile.Library.fileName(\"[name]\")),\n              \"library\" -> JS.str(bundleName),\n              \"libraryTarget\" -> JS.str(\"var\")\n            )\n          case None =>\n            JS.obj(\n              \"path\" -> JS.str(webpackConfigFile.targetDir.toAbsolutePath.toString),\n              \"filename\" -> JS.str(BundlerFile.ApplicationBundle.fileName(\"[name]\"))\n            )\n        }\n\n        JS.ref(\"module\").dot(\"exports\").assign(JS.obj(Seq(\n          \"entry\" -> JS.obj(\n            entry.project -> JS.arr(JS.str(entry.file.absolutePath))\n          ),\n          \"output\" -> output,\n          \"mode\" -> JS.str(mode.mode),\n          \"devServer\" -> JS.obj(\"port\" -> JS.int(devServerPort)),\n        ) ++ (\n          if (emitSourceMaps) {\n            Seq(\n              \"devtool\" -> JS.str(\"source-map\"),\n              \"module\" -> JS.obj(\n                \"rules\" -> JS.arr(\n                  JS.obj(\n                    \"test\" -> JS.regex(\"\\\\.js$\"),\n                    \"enforce\" -> JS.str(\"pre\"),\n                    \"use\" -> JS.arr(JS.str(\"source-map-loader\"))\n                  )\n                )\n              )\n            )\n          } else Nil\n          ): _*))\n\n      case Some(x) =>\n        sys.error(s\"Unsupported webpack major version $x\")\n\n      case None =>\n        sys.error(\"No webpack version defined\")\n    }\n  }\n\n  /**\n    * Run webpack to bundle the application.\n    *\n    * @param emitSourceMaps Whether or not source maps are enabled\n    * @param generatedWebpackConfigFile Webpack config file generated by scalajs-bundler\n    * @param customWebpackConfigFile User supplied config file\n    * @param webpackResources Additional resources to be copied to the working folder\n    * @param entry Scala.js application to bundle\n    * @param targetDir Target directory (and working directory for Nodejs)\n    * @param extraArgs Extra arguments passed to webpack\n    * @param mode Mode for webpack 5\n    * @param devServerPort Port used by webpack-dev-server\n    * @param log Logger\n    * @return The generated bundles\n    */\n  def bundle(\n     emitSourceMaps: Boolean,\n     generatedWebpackConfigFile: BundlerFile.WebpackConfig,\n     customWebpackConfigFile: Option[File],\n     webpackResources: Seq[File],\n     entry: BundlerFile.Application,\n     targetDir: File,\n     extraArgs: Seq[String],\n     nodeArgs: Seq[String],\n     mode: WebpackMode,\n     devServerPort: Int,\n     log: Logger\n  ): BundlerFile.ApplicationBundle = {\n    writeConfigFile(emitSourceMaps, entry, generatedWebpackConfigFile, None, mode, devServerPort, log)\n\n    val configFile = customWebpackConfigFile\n      .map(Webpack.copyCustomWebpackConfigFiles(targetDir, webpackResources))\n      .getOrElse(generatedWebpackConfigFile.file)\n\n    log.info(\"Bundling the application with its NPM dependencies\")\n    val args = extraArgs ++: Seq(\"--config\", configFile.absolutePath)\n    val stats = Webpack.run(nodeArgs: _*)(args: _*)(targetDir, log)\n    stats.foreach(_.print(log))\n\n    // Attempt to discover the actual name produced by webpack indexing by chunk name and discarding maps\n    val bundle = generatedWebpackConfigFile.asApplicationBundle(stats)\n    assert(bundle.file.exists(), \"Webpack failed to create application bundle\")\n    assert(bundle.assets.forall(_.exists()), \"Webpack failed to create application assets\")\n    bundle\n  }\n\n  /**\n    * Run webpack to bundle the application.\n    *\n    * @param emitSourceMaps Are source maps enabled?\n    * @param generatedWebpackConfigFile Webpack config file generated by scalajs-bundler\n    * @param customWebpackConfigFile User supplied config file\n    * @param webpackResources Additional webpack resources to include in the working directory\n    * @param entryPointFile The entrypoint file to bundle dependencies for\n    * @param libraryModuleName The library module name to assign the webpack bundle to\n    * @param extraArgs Extra arguments passed to webpack\n    * @param mode Mode for webpack 5\n    * @param log Logger\n    * @return The generated bundle\n    */\n  def bundleLibraries(\n    emitSourceMaps: Boolean,\n    generatedWebpackConfigFile: BundlerFile.WebpackConfig,\n    customWebpackConfigFile: Option[File],\n    webpackResources: Seq[File],\n    entryPointFile: BundlerFile.EntryPoint,\n    libraryModuleName: String,\n    extraArgs: Seq[String],\n    nodeArgs: Seq[String],\n    mode: WebpackMode,\n    devServerPort: Int,\n    log: Logger\n  ): BundlerFile.Library = {\n    writeConfigFile(\n      emitSourceMaps,\n      entryPointFile,\n      generatedWebpackConfigFile,\n      Some(libraryModuleName),\n      mode,\n      devServerPort,\n      log\n    )\n\n    val configFile = customWebpackConfigFile\n      .map(Webpack.copyCustomWebpackConfigFiles(generatedWebpackConfigFile.targetDir.toFile, webpackResources))\n      .getOrElse(generatedWebpackConfigFile.file)\n\n    val args = extraArgs ++: Seq(\"--config\", configFile.absolutePath)\n    val stats = Webpack.run(nodeArgs: _*)(args: _*)(generatedWebpackConfigFile.targetDir.toFile, log)\n    stats.foreach(_.print(log))\n\n    val library = generatedWebpackConfigFile.asLibrary(stats)\n    assert(library.file.exists, \"Webpack failed to create library file\")\n    assert(library.assets.forall(_.exists), \"Webpack failed to create library assets\")\n    library\n  }\n\n  private def jsonOutput(cmd: Seq[String], logger: Logger)(in: InputStream): Option[WebpackStats] = {\n    Try {\n      val parsed = Json.parse(in)\n      parsed.validate[WebpackStats] match {\n        case JsError(e) =>\n          logger.error(\"Error parsing webpack stats output\")\n          // In case of error print the result and return None. it will be ignored upstream\n          e.foreach {\n            case (p, v) => logger.error(s\"$p: ${v.mkString(\",\")}\")\n          }\n          None\n        case JsSuccess(p, _) =>\n          if (p.warnings.nonEmpty || p.errors.nonEmpty) {\n            logger.info(\"\")\n            // Filtering is a workaround for #111\n            p.warnings.filterNot(_.message.contains(\"https://raw.githubusercontent.com\")).foreach { warning =>\n              logger.warn(s\"WARNING in ${warning.moduleName}\")\n              logger.warn(warning.message)\n              logger.warn(\"\\n\")\n            }\n            p.errors.foreach { error =>\n              logger.error(s\"ERROR in ${error.moduleName} ${error.loc}\")\n              logger.error(error.message)\n              logger.error(\"\\n\")\n            }\n          }\n          Some(p)\n      }\n    } match {\n      case Success(x) =>\n        x\n      case Failure(e) =>\n        // In same cases errors are not reported on the json output but comes on stdout\n        // where they cannot be parsed as json. The best we can do here is to suggest\n        // running the command manually\n        logger.error(s\"Failure on parsing the output of webpack: ${e.getMessage}\")\n        logger.error(s\"You can try to manually execute the command\")\n        logger.error(cmd.mkString(\" \"))\n        logger.error(\"\\n\")\n        None\n    }\n  }\n\n  /**\n    * Runs the webpack command.\n    *\n    * @param nodeArgs node.js cli flags\n    * @param args Arguments to pass to the webpack command\n    * @param workingDir Working directory in which the Nodejs will be run (where there is the `node_modules` subdirectory)\n    * @param log Logger\n    */\n  def run(nodeArgs: String*)(args: String*)(workingDir: File, log: Logger): Option[WebpackStats] = {\n    val webpackBin = workingDir / \"node_modules\" / \"webpack\" / \"bin\" / \"webpack\"\n    val params = nodeArgs ++ Seq(webpackBin.absolutePath, \"--profile\", \"--json\") ++ args\n    val cmd = \"node\" +: params\n    Commands.run(cmd, workingDir, log, jsonOutput(cmd, log)).fold(sys.error, _.flatten)\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/WebpackDevServer.scala",
    "content": "package scalajsbundler\n\nimport sbt._\nimport java.io.File\n\n/**\n  * Simple wrapper over webpack-dev-server\n  */\nprivate [scalajsbundler] class WebpackDevServer {\n\n  private var worker: Option[Worker] = None\n\n  /**\n    * @param workDir - path to working directory for webpack-dev-server\n    * @param configPath - path to webpack config.\n    * @param extraArgs - additional arguments for webpack-dev-server.\n    * @param logger - a logger to use for output\n    * @param globalLogger - a global logger to use for output even when the task is terminated\n    */\n  def start(\n    workDir: File,\n    configPath: File,\n    extraArgs: Seq[String],\n    logger: Logger,\n    globalLogger: Logger,\n  ) = this.synchronized {\n    stop()\n    worker = Some(new Worker(\n      workDir,\n      configPath,\n      extraArgs,\n      logger,\n      globalLogger\n    ))\n  }\n\n  def stop() = this.synchronized {\n    worker.foreach { w => {\n      w.stop()\n      worker = None\n    }}\n  }\n\n  private class Worker(\n    workDir: File,\n    configPath: File,\n    extraArgs: Seq[String],\n    logger: Logger,\n    globalLogger: Logger,\n  ) {\n    logger.info(\"Starting webpack-dev-server\");\n\n    val command = Seq(\n      \"node\",\n      \"node_modules/webpack/bin/webpack\",\n      \"serve\",\n      \"--config\",\n      configPath.getAbsolutePath\n    ) ++ extraArgs\n\n    val process = util.Commands.start(command, workDir, globalLogger)\n\n    def stop() = {\n      logger.info(\"Stopping webpack-dev-server\");\n      process.destroy()\n    }\n  }\n\n  override def finalize() = stop()\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/WebpackEntryPoint.scala",
    "content": "package scalajsbundler\n\nimport sbt.{IO, Logger}\n\nimport scalajsbundler.util.JS\n\nobject WebpackEntryPoint {\n\n  /**\n    * @return The written loader file (faking a `require` implementation)\n    * @param entryPoint File to write the loader to\n    * @param logger Logger\n    */\n  def writeEntryPoint(\n      imports: Seq[String],\n      entryPoint: BundlerFile.EntryPoint,\n      logger: Logger\n  ): Unit = {\n    logger.info(s\"Writing module entry point for ${entryPoint.file.getName}\")\n    val depsFileContent =\n      JS.ref(\"module\")\n        .dot(\"exports\")\n        .assign(\n          JS.obj(\n            Seq(\n              \"require\" -> JS.fun(name =>\n                JS.obj(imports.map { moduleName =>\n                    moduleName -> JS.ref(\"require\").apply(JS.str(moduleName))\n                  }: _*)\n                  .bracket(name))): _*)\n        )\n    IO.write(entryPoint.file, depsFileContent.show)\n  }\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/sbtplugin/LibraryTasks.scala",
    "content": "package scalajsbundler.sbtplugin\n\nimport sbt.Keys._\nimport sbt.{Def, _}\n\nimport org.scalajs.sbtplugin.ScalaJSPlugin.autoImport.scalaJSLinkerConfig\nimport scalajsbundler.{BundlerFile, Webpack, WebpackEntryPoint}\nimport scalajsbundler.sbtplugin.ScalaJSBundlerPlugin.autoImport._\nimport scalajsbundler.sbtplugin.ScalaJSBundlerPlugin._\nimport scalajsbundler.util.{Caching, JSBundler}\n\nobject LibraryTasks {\n\n  private[sbtplugin] def entryPoint(stage: TaskKey[Attributed[File]])\n    : Def.Initialize[Task[BundlerFile.EntryPoint]] =\n    Def.task {\n      val s = streams.value\n      val importedModules = (scalaJSBundlerImportedModules in stage).value\n      val entry = WebpackTasks.entry(stage).value\n      val cacheLocation = streams.value.cacheDirectory / s\"${stage.key.label}-webpack-entrypoint\"\n      val entryPointFile = entry.asEntryPoint\n\n      // Avoid re-writing the entrypoint file if the list of modules hasn't changed\n      // allowing downstream caching to detect change reliably\n      Caching.cached(entryPointFile.file, importedModules.mkString(\",\"), cacheLocation)(\n        () =>\n          WebpackEntryPoint.writeEntryPoint(\n            importedModules,\n            entryPointFile,\n            s.log\n        ))\n      entryPointFile\n    }.dependsOn(npmUpdate in stage)\n\n  private[sbtplugin] def bundle(\n      stage: TaskKey[Attributed[File]],\n      mode: BundlingMode.Library): Def.Initialize[Task[BundlerFile.Library]] =\n    Def.task {\n      assert(ensureModuleKindIsCommonJSModule.value)\n      val log = streams.value.log\n      val emitSourceMaps = (finallyEmitSourceMaps in stage).value\n      val customWebpackConfigFile = (webpackConfigFile in stage).value\n      val generatedWebpackConfigFile =\n        (scalaJSBundlerWebpackConfig in stage).value\n      val compileResources = (resources in Compile).value\n      val webpackResourceFiles = (webpackResources in stage).value.get\n      val entryPointFile = entryPoint(stage).value\n      val monitoredFiles = customWebpackConfigFile.toSeq ++\n        Seq(generatedWebpackConfigFile.file, entryPointFile.file) ++\n        webpackResourceFiles ++ compileResources\n      val cacheLocation = streams.value.cacheDirectory / s\"${stage.key.label}-webpack-libraries\"\n      val extraArgs = (webpackExtraArgs in stage).value\n      val nodeArgs = (webpackNodeArgs in stage).value\n      val webpackMode =\n        Webpack.WebpackMode.fromBooleanProductionMode((scalaJSLinkerConfig in stage).value.semantics.productionMode)\n      val devServerPort = webpackDevServerPort.value\n\n      val cachedActionFunction =\n        FileFunction.cached(\n          cacheLocation,\n          inStyle = FilesInfo.hash\n        ) { _ =>\n          log.info(s\"Building webpack library bundles for ${entryPointFile.project} in $cacheLocation\")\n\n          Webpack.bundleLibraries(\n            emitSourceMaps,\n            generatedWebpackConfigFile,\n            customWebpackConfigFile,\n            webpackResourceFiles,\n            entryPointFile,\n            mode.exportedName,\n            extraArgs,\n            nodeArgs,\n            webpackMode,\n            devServerPort,\n            log\n          ).cached\n        }\n      val cached = cachedActionFunction(monitoredFiles.to[Set])\n      generatedWebpackConfigFile.asLibraryFromCached(cached)\n    }\n\n  private[sbtplugin] def loader(\n      stage: TaskKey[Attributed[File]],\n      mode: BundlingMode.Library): Def.Initialize[Task[BundlerFile.Loader]] =\n    Def.task {\n      assert(ensureModuleKindIsCommonJSModule.value)\n      val entry = WebpackTasks.entry(stage).value\n      val loaderFile = entry.asLoader\n\n      JSBundler.writeLoader(\n        loaderFile,\n        mode.exportedName\n      )\n      loaderFile\n    }\n\n  private[sbtplugin] def bundleAll(stage: TaskKey[Attributed[File]],\n                                   mode: BundlingMode.LibraryAndApplication)\n    : Def.Initialize[Task[Seq[BundlerFile.Public]]] =\n    Def.task {\n      assert(ensureModuleKindIsCommonJSModule.value)\n      val cacheLocation = streams.value.cacheDirectory / s\"${stage.key.label}-webpack-bundle-all\"\n      val targetDir = npmUpdate.value\n      val entry = WebpackTasks.entry(stage).value\n      val library = bundle(stage, mode).value\n      val emitSourceMaps = (finallyEmitSourceMaps in stage).value\n      val log = streams.value.log\n      val filesToMonitor = Seq(entry.file, library.file)\n\n      val cachedActionFunction =\n        FileFunction.cached(\n          cacheLocation,\n          inStyle = FilesInfo.hash\n        ) { _ =>\n          JSBundler.bundle(\n            targetDir = targetDir,\n            entry,\n            library,\n            emitSourceMaps,\n            mode.exportedName,\n            log\n          ).cached\n        }\n      val cached = cachedActionFunction(filesToMonitor.toSet)\n      Seq(entry.asApplicationBundleFromCached(cached), entry.asLoader, library, entry)\n    }\n\n  private[sbtplugin] def librariesAndLoaders(stage: TaskKey[Attributed[File]],\n                                             mode: BundlingMode.LibraryOnly)\n    : Def.Initialize[Task[Seq[Attributed[File]]]] =\n    Def.task {\n      Seq(WebpackTasks.entry(stage).value,\n        loader(stage, mode).value,\n        bundle(stage, mode).value).flatMap(_.asAttributedFiles)\n    }\n\n  private[sbtplugin] def libraryAndLoadersBundle(\n      stage: TaskKey[Attributed[File]],\n      mode: BundlingMode.LibraryAndApplication)\n    : Def.Initialize[Task[Seq[Attributed[File]]]] =\n    Def.task {\n      bundleAll(stage, mode).value.flatMap(_.asAttributedFiles)\n    }\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/sbtplugin/NpmUpdateTasks.scala",
    "content": "package scalajsbundler.sbtplugin\n\nimport java.nio.file.Path\nimport scalajsbundler.ExternalCommand\nimport sbt._\n\nobject NpmUpdateTasks {\n\n  /**\n    * Runs either `npm install` or `yarn install` and installs JavaScript resources as node packages.\n    *\n    * @param targetDir npm directory\n    * @param packageJsonFile Json file containing NPM dependencies\n    * @param useYarn Whether to use yarn or npm\n    * @param jsResources A sequence of JavaScript resources\n    * @param streams A sbt TaskStream\n    * @param npmExtraArgs Additional arguments to pass to npm\n    * @param yarnExtraArgs Additional arguments to pass to yarn\n    * @return The written npm directory\n    */\n  def npmUpdate(baseDir: File,\n                targetDir: File,\n                packageJsonFile: File,\n                useYarn: Boolean,\n                jsResources: Seq[(String, Path)],\n                streams: Keys.TaskStreams,\n                npmExtraArgs: Seq[String],\n                yarnExtraArgs: Seq[String]): File = {\n    val dir = npmInstallDependencies(baseDir, targetDir, packageJsonFile, useYarn, streams, npmExtraArgs, yarnExtraArgs)\n    npmInstallJSResources(targetDir, jsResources, Seq.empty, streams)\n    dir\n  }\n\n  /**\n    * Runs either `npm install` or `yarn install`.\n    *\n    * @param targetDir npm directory\n    * @param packageJsonFile Json file containing NPM dependencies\n    * @param useYarn Whether to use yarn or npm\n    * @param streams A sbt TaskStream\n    * @param npmExtraArgs Additional arguments to pass to npm\n    * @param yarnExtraArgs Additional arguments to pass to yarn\n    * @return The written npm directory\n    */\n  def npmInstallDependencies(baseDir: File,\n                             targetDir: File,\n                             packageJsonFile: File,\n                             useYarn: Boolean,\n                             streams: Keys.TaskStreams,\n                             npmExtraArgs: Seq[String],\n                             yarnExtraArgs: Seq[String]): File = {\n    val log = streams.log\n    val cachedActionFunction =\n      FileFunction.cached(\n        streams.cacheDirectory / \"scalajsbundler-npm-install\",\n        inStyle = FilesInfo.hash\n      ) { _ =>\n        log.info(\"Updating NPM dependencies\")\n        ExternalCommand.install(baseDir, targetDir, useYarn, log, npmExtraArgs, yarnExtraArgs)\n        Set.empty\n      }\n    cachedActionFunction(Set(packageJsonFile))\n    targetDir\n  }\n\n  private object PathWithFile {\n    def unapply(path: Path): Option[File] = {\n      try {\n        Some(path.toFile())\n      } catch {\n        case _: UnsupportedOperationException => None\n      }\n    }\n  }\n\n  /**\n    * Installs JavaScript resources as node packages.\n    *\n    * @param targetDir npm directory\n    * @param jsResources The JavaScript resources\n    * @param streams A sbt TaskStream\n    * @return The paths to the node packages\n    */\n  def npmInstallJSResources(targetDir: File,\n                            jsResources: Seq[(String, Path)],\n                            jsSourceDirectories: Seq[File],\n                            streams: Keys.TaskStreams): Seq[File] = {\n    val jsFileResources =   jsResources.collect {\n      case (relativePath, PathWithFile(jsfile)) => jsfile -> relativePath\n    }.toSet ++ jsSourceDirectories.flatMap { f =>\n      if (f.isDirectory)\n        sbt.Path.allSubpaths(f).filterNot(_._1.isDirectory)\n      else Seq.empty\n    }.toSet\n\n    val cachedActionFunction = FileFunction.cached(\n        streams.cacheDirectory / \"scalajsbundler-npm-install-resources\",\n        inStyle = FilesInfo.hash\n      ) { _ =>\n      jsFileResources.map { case (file, relativePath) =>\n        val resourcePath = targetDir / relativePath\n        IO.copyFile(file, resourcePath)\n        resourcePath\n        }\n      }\n    val files = jsFileResources.map { case (rFile, _) => rFile }\n    cachedActionFunction(files).toSeq\n  }\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/sbtplugin/PackageJsonTasks.scala",
    "content": "package scalajsbundler.sbtplugin\n\nimport sbt._\n\nimport scalajsbundler.{BundlerFile, PackageJson}\nimport scalajsbundler.util.{Caching, JSON}\n\nobject PackageJsonTasks {\n\n  /**\n    * Writes the package.json file that describes the project dependencies\n    * @param targetDir Directory in which write the file\n    * @param npmDependencies NPM dependencies\n    * @param npmDevDependencies NPM devDependencies\n    * @param npmResolutions Resolutions to use in case of conflicts\n    * @param additionalNpmConfig Additional options to include in 'package.json'\n    * @param fullClasspath Classpath\n    * @param configuration Current configuration (Compile or Test)\n    * @param webpackVersion Webpack version\n    * @param webpackDevServerVersion Webpack development server version\n    * @return The written package.json file\n    */\n  def writePackageJson(\n    targetDir: File,\n    npmDependencies: Seq[(String, String)],\n    npmDevDependencies: Seq[(String, String)],\n    npmResolutions: Map[String, String],\n    additionalNpmConfig: Map[String, JSON],\n    fullClasspath: Seq[Attributed[File]],\n    configuration: Configuration,\n    webpackVersion: String,\n    webpackDevServerVersion: String,\n    webpackCliVersion: String,\n    streams: Keys.TaskStreams\n  ): BundlerFile.PackageJson = {\n\n    val hash = Seq(\n      configuration.name,\n      npmDependencies.toString,\n      npmDevDependencies.toString,\n      npmResolutions.toString,\n      fullClasspath.map(_.data.name).toString,\n      webpackVersion,\n      webpackDevServerVersion,\n      webpackCliVersion\n    ).mkString(\",\")\n\n    val packageJsonFile = targetDir / \"package.json\"\n\n    Caching.cached(\n      packageJsonFile,\n      hash,\n      streams.cacheDirectory / s\"scalajsbundler-package-json-${if (configuration == Compile) \"main\" else \"test\"}\"\n    ) { () =>\n      PackageJson.write(\n        streams.log,\n        packageJsonFile,\n        npmDependencies,\n        npmDevDependencies,\n        npmResolutions,\n        additionalNpmConfig,\n        fullClasspath,\n        configuration,\n        webpackVersion,\n        webpackDevServerVersion,\n        webpackCliVersion\n      )\n      ()\n    }\n\n    BundlerFile.PackageJson(packageJsonFile)\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/sbtplugin/SBTBundlerFile.scala",
    "content": "package scalajsbundler.sbtplugin\n\nimport sbt.{AttributeKey, Attributed}\n\nimport scalajsbundler.{BundlerFile, BundlerFileType}\n\n/**\n  * SBT Specific Extensions to [[scalajsbundler.BundlerFile]]\n  *\n  * @param f The BundlerFile to enrich\n  */\nclass SBTBundlerFile(f: BundlerFile.Public) {\n    import SBTBundlerFile._\n\n    def asAttributedFiles: Seq[sbt.Attributed[sbt.File]] = {\n      val main = Attributed\n        .blank(f.attributedFiles._1)\n        .put(ProjectNameAttr, f.project)\n        .put(BundlerFileTypeAttr, f.`type`)\n      val assets = Attributed\n        .blankSeq(f.attributedFiles._2).map {\n          _\n          .put(ProjectNameAttr, f.project)\n          .put(BundlerFileTypeAttr, BundlerFileType.Asset)\n        }\n      main +: assets\n    }\n}\n\nobject SBTBundlerFile {\n\n  /**\n    * A string attribute describing the project and output stage (fastopt vs. opt)\n    */\n  val ProjectNameAttr: AttributeKey[String] = AttributeKey(\"project-name\")\n\n  /**\n    * A [[scalajsbundler.BundlerFileType]], allowing unambigiuous selection of output files\n    * downstream from the plugin.\n    */\n  val BundlerFileTypeAttr: AttributeKey[BundlerFileType] = AttributeKey(\n    \"bundler-file-type\")\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/sbtplugin/ScalaJSBundlerPlugin.scala",
    "content": "package scalajsbundler.sbtplugin\n\nimport org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._\nimport org.scalajs.sbtplugin.{ScalaJSPlugin, Stage}\nimport sbt.Keys._\nimport sbt.{Def, _}\nimport scalajsbundler.{BundlerFile, NpmDependencies, Webpack, WebpackDevServer}\n\nimport scalajsbundler.ExternalCommand.addPackages\nimport scalajsbundler.util.{JSON, ScalaJSNativeLibraries}\n\n\n/**\n  * This plugin enables `ScalaJSPlugin` and sets the `scalaJSModuleKind` to `CommonJSModule`. It also makes it\n  * possible to define dependencies to NPM packages and provides tasks to fetch them or to bundle the application\n  * with its dependencies.\n  *\n  * = Tasks and Settings =\n  *\n  * The [[ScalaJSBundlerPlugin.autoImport autoImport]] member documents the keys provided by this plugin. Besides these keys, the\n  * following existing keys also control the plugin:\n  *\n  * == `version in webpack` ==\n  *\n  * Version of webpack to use. Example:\n  *\n  * {{{\n  *   version in webpack := \"3.5.5\"\n  * }}}\n  *\n  * == `version in installJsdom` ==\n  *\n  * Version of jsdom to use.\n  *\n  * == `version in startWebpackDevServer` ==\n  *\n  * Version of webpack-dev-server to use.\n  *\n  * {{{\n  *   version in startWebpackDevServer := \"2.11.1\"\n  * }}}\n  *\n  * == `crossTarget in npmUpdate` ==\n  *\n  * The directory in which NPM dependencies will be fetched, and where all the .js files\n  * will be generated. The directory is different according to the current `Configuration`\n  * (either `Compile` or `Test`).\n  *\n  * Defaults to `crossTarget.value / \"scalajs-bundler\" / \"main\"` for `Compile` and\n  * `crossTarget.value / \"scalajs-bundler\" / \"test\"` for `Test`.\n  */\nobject ScalaJSBundlerPlugin extends AutoPlugin {\n\n  override lazy val requires = ScalaJSPlugin\n\n  // Exported keys\n  /**\n    * @groupname tasks Tasks\n    * @groupname settings Settings\n    */\n  object autoImport {\n    type BundlingMode = scalajsbundler.BundlingMode\n    val BundlingMode = scalajsbundler.BundlingMode\n    type BundlerFile = scalajsbundler.BundlerFile\n    val BundlerFile = scalajsbundler.BundlerFile\n    type BundlerFileType = scalajsbundler.BundlerFileType\n    val BundlerFileType = scalajsbundler.BundlerFileType\n    val ProjectNameAttr: AttributeKey[String] = SBTBundlerFile.ProjectNameAttr\n    val BundlerFileTypeAttr: AttributeKey[BundlerFileType] = SBTBundlerFile.BundlerFileTypeAttr\n    implicit class RichBundlerFile(f: BundlerFile.Public) extends SBTBundlerFile(f)\n\n    /**\n      * Installs NPM dependencies and all JavaScript resources found on the classpath as node packages.\n      *\n      * The JavaScript resources are installed locally in `node_modules` and can be used any other node package,\n      * such as to load a module using `require()`.\n      *\n      * Do not use this from `sourceGenerators` or any other task that is used either directly or indirectly by\n      * `fullClasspath` otherwise it will result in a deadlock. For this, use [[npmInstallDependencies]] instead.\n      *\n      * The plugin uses different directories according to the configuration (`Compile` or `Test`). Thus,\n      * this setting is scoped by a `Configuration`.\n      *\n      * The task returns the directory in which the dependencies have been fetched (the directory\n      * that contains the `node_modules` directory).\n      *\n      * @group tasks\n      */\n    val npmUpdate: TaskKey[File] =\n      taskKey[File](\"Install NPM dependencies and JavaScript resources\")\n\n    /**\n      * Installs NPM dependencies.\n      *\n      * Unlike [[npmUpdate]] this does not stage the javascript resources and so is safe to use in `sourceGenerators`\n      * or any other task that is used by `fullClasspath`.\n      *\n      * The plugin uses different directories according to the configuration (`Compile` or `Test`). Thus,\n      * this setting is scoped by a `Configuration`.\n      *\n      * Typically, if you want to define a task that uses the downloaded NPM packages you should\n      * specify the `Configuration` you are interested in:\n      *\n      * {{{\n      *   myCustomTask := {\n      *     val npmDirectory = (npmInstallDependencies in Compile).value\n      *     doSomething(npmDirectory / \"node_modules\" / \"some-package\")\n      *   }\n      * }}}\n      *\n      * The task returns the directory in which the dependencies have been fetched (the directory\n      * that contains the `node_modules` directory).\n      *\n      * @group tasks\n      */\n    val npmInstallDependencies: TaskKey[File] =\n      taskKey[File](\"Install NPM dependencies\")\n\n    /**\n      * Installs all JavaScript resources found on the classpath as node packages.\n      *\n      * Additionally, it installs also the resources found under [[jsSourceDirectories]]\n      *\n      * The JavaScript resources are installed locally in `node_modules` and can be used any other node package,\n      * such as to load a module using `require()`.\n      *\n      * The plugin uses different directories according to the configuration (`Compile` or `Test`). Thus,\n      * this setting is scoped by a `Configuration`.\n      *\n      * The task returns the path to each JavaScript resource within the `node_modules` directory.\n      *\n      * @group tasks\n      */\n    val npmInstallJSResources: TaskKey[Seq[File]] =\n      taskKey[Seq[File]](\"Install JavaScript resources found on the classpath\")\n\n    /**\n      * List of the NPM packages (name and version) your application depends on.\n      * You can use [semver](https://docs.npmjs.com/misc/semver) versions:\n      *\n      * {{{\n      *   npmDependencies in Compile += \"uuid\" -> \"~3.0.0\"\n      * }}}\n      *\n      * Note that this key must be scoped by a `Configuration` (either `Compile` or `Test`).\n      *\n      * @group settings\n      */\n    val npmDependencies: SettingKey[Seq[(String, String)]] =\n      settingKey[Seq[(String, String)]](\"NPM dependencies (libraries that your program uses)\")\n\n    /** @group settings */\n    val npmDevDependencies: SettingKey[Seq[(String, String)]] =\n      settingKey[Seq[(String, String)]](\"NPM dev dependencies (libraries that the build uses)\")\n\n    /**\n      * Map of NPM packages (name -> version) to use in case transitive NPM dependencies\n      * refer to a same package but with different version numbers. In such a\n      * case, this setting defines which version should be used for the conflicting\n      * package. Example:\n      *\n      * {{{\n      *   npmResolutions in Compile := Map(\"react\" -> \"15.4.1\")\n      * }}}\n      *\n      * If several Scala.js projects depend on different versions of `react`, the version `15.4.1`\n      * will be picked. But if all the projects depend on the same version of `react`, the version\n      * given in `npmResolutions` will be ignored.\n      *\n      * If different versions of the packages are referred but the package is NOT configured in `npmResolutions`,\n      * a version conflict resolution is delegated to npm/yarn. This behavior may reduce a need to configure\n      * `npmResolutions` explicitly. E.g. \"14.4.2\" can be automatically-picked for \">=14.0.0 14.4.2 ^14.4.1\".\n      *\n      * Note that this key must be scoped by a `Configuration` (either `Compile` or `Test`).\n      *\n      * @group settings\n      */\n    val npmResolutions: SettingKey[Map[String, String]] =\n      settingKey[Map[String, String]](\"NPM dependencies resolutions in case of conflict\")\n\n    /**\n      * List of the additional configuration options to include in the generated 'package.json'.\n      * Note that package dependencies are automatically generated from `npmDependencies` and\n      * `npmDevDependencies` and should '''not''' be specified in this setting.\n      *\n      * {{{\n      *   import scalajsbundler.util.JSON._\n      *   additionalNpmConfig in Compile := Map(\n      *     \"name\"        -> str(name.value),\n      *     \"version\"     -> str(version.value),\n      *     \"description\" -> str(\"Awesome ScalaJS project...\"),\n      *     \"other\"       -> obj(\n      *       \"value0\" -> bool(true),\n      *       \"value1\" -> obj(\n      *         \"foo\" -> str(\"bar\")\n      *       )\n      *     )\n      *   )\n      * }}}\n      *\n      * Note that this key must be scoped by a `Configuration` (either `Compile` or `Test`).\n      *\n      * @group settings\n      */\n    val additionalNpmConfig: SettingKey[Map[String, JSON]] =\n      settingKey[Map[String, JSON]](\"Additional option to include in the generated 'package.json'\")\n\n    /**\n      * Additional arguments for npm\n      *\n      * Defaults to an empty list.\n      *\n      * @group settings\n      */\n    val npmExtraArgs = SettingKey[Seq[String]](\n      \"npmExtraArgs\",\n      \"Custom arguments for npm\"\n    )\n\n    /**\n      * [[scalajsbundler.BundlingMode]] to use.\n      *\n      * Must be one of:\n      *   `Application`             - Process the entire Scala.js output file with webpack, producing a bundle including all dependencies\n      *   `LibraryOnly()`           - Process only the entrypoints via webpack and produce a library of dependencies\n      *   `LibraryAndApplication()  - Process only the entrypoints, concatenating the library with the application to produce a bundle\n      *\n      * The default value is `Application`\n      */\n    val webpackBundlingMode: SettingKey[BundlingMode] =\n      settingKey[BundlingMode](\"Bundling mode, one of BundlingMode.{ Application,  LibraryOnly, LibraryAndApplication }.\")\n\n    /**\n      * Bundles the output of a Scala.js stage.\n      *\n      * This task must be scoped by a Scala.js stage (either `fastOptJS` or `fullOptJS`) and\n      * a `Configuration` (either `Compile` or `Test`).\n      *\n      * For instance, to bundle the output of `fastOptJS`, run the following task from the sbt shell:\n      *\n      * {{{\n      *   fastOptJS::webpack\n      * }}}\n      *\n      * Or, in an sbt build definition:\n      *\n      * {{{\n      *   webpack in (Compile, fastOptJS)\n      * }}}\n      *\n      * Note that to scope the task to a different project than the “current” sbt project, you\n      * have to write the following:\n      *\n      * {{{\n      *   webpack in (projectRef, Compile, fastOptJS in projectRef)\n      * }}}\n      *\n      * The task returns the produced bundles.\n      *\n      * The task is cached, so webpack is only launched when some of the\n      * used files have changed. The list of files to be monitored is\n      * provided by webpackMonitoredFiles\n      *\n      * The files produced are wrapped in `sbt.Attributed`, and tagged with\n      * [[scalajsbundler.sbtplugin.SBTBundlerFile.ProjectNameAttr]] and\n      * [[scalajsbundler.sbtplugin.SBTBundlerFile.BundlerFileTypeAttr]]. The\n      * [[scalajsbundler.sbtplugin.SBTBundlerFile.ProjectNameAttr]] contains the \"prefix\" of the file names, such\n      * as `yourapp-fastopt`, while the\n      * [[scalajsbundler.sbtplugin.SBTBundlerFile.BundlerFileTypeAttr]] contains the bundle file type, which can be\n      * used to filter the list of files by their [[scalajsbundler.BundlerFileType]]. For example:\n      *\n      * {{{\n      *   webpack.value.find(_.metadata.get(BundlerFileTypeAttr).exists(_ == BundlerFileType.ApplicationBundle))\n      * }}}\n      *\n      * @group tasks\n      */\n    val webpack: TaskKey[Seq[Attributed[File]]] =\n      taskKey[Seq[Attributed[File]]](\"Bundle the output of a Scala.js stage using webpack\")\n\n    /**\n      * configuration file to use with webpack. By default, the plugin generates a\n      * configuration file, but you can supply your own file via this setting. Example of use:\n      *\n      * {{{\n      *   webpackConfigFile in fullOptJS := Some(baseDirectory.value / \"my.dev.webpack.config.js\")\n      * }}}\n      *\n      * You can find more insights on how to write a custom configuration file in the\n      * [[http://scalacenter.github.io/scalajs-bundler/cookbook.html#custom-config cookbook]].\n      *\n      * @group settings\n      */\n    val webpackConfigFile: SettingKey[Option[File]] =\n      settingKey[Option[File]](\"Configuration file to use with webpack\")\n\n    /**\n      * Webpack configuration files to copy to the target directory. These files can be merged into the main\n      * configuration file.\n      *\n      * By default all .js files in the project base directory are copied:\n      *\n      * {{{\n      *   baseDirectory.value * \"*.js\"\n      * }}}\n      *\n      * How to share these configuration files among your webpack config files is documented in the\n      * [[http://scalacenter.github.io/scalajs-bundler/cookbook.html#shared-config cookbook]].\n      *\n      * @group settings\n      */\n    val webpackResources: SettingKey[PathFinder] =\n      settingKey[PathFinder](\"Webpack resources to copy to target directory (defaults to *.js)\")\n\n    /**\n      * whether to enable (or not) source-map in\n      * a given configuration (`Compile` or `Test`) and stage (`fastOptJS` or `fullOptJS`). Example\n      * of use:\n      *\n      * {{{\n      *   webpackEmitSourceMaps in (Compile, fullOptJS) := false\n      * }}}\n      *\n      * By default, this setting is undefined and scalajs-bundler fallbacks to Scala.js’ `sourceMap`\n      * setting, so, to globally disable source maps you can just configure the `sourceMap`\n      * setting:\n      *\n      * {{{\n      *   scalaJSLinkerConfig ~= _.withSourceMap(false)\n      * }}}\n      *\n      * @group settings\n      */\n    val webpackEmitSourceMaps: SettingKey[Boolean] =\n      settingKey[Boolean](\"Whether webpack should emit source maps at all\")\n\n    private[scalajsbundler] val finallyEmitSourceMaps: SettingKey[Boolean] =\n      SettingKey(\"finallyEmitSourceMaps\", rank = KeyRanks.Invisible)\n\n    /**\n      * Additional directories, monitored for webpack launch.\n      *\n      * Changes to files in these directories that match\n      * `includeFilter` scoped to `webpackMonitoredFiles` enable\n      *  webpack launch in `webpack` task.\n      *\n      * Defaults to an empty `Seq`.\n      *\n      * @group settings\n      * @see [[webpackMonitoredFiles]]\n      */\n    val webpackMonitoredDirectories: SettingKey[Seq[File]] =\n      settingKey[Seq[File]](\"Directories, monitored for webpack launch\")\n\n    /**\n      * List of files, monitored for webpack launch.\n      *\n      * By default includes the following files:\n      *  - Generated `package.json`\n      *  - Generated webpack config\n      *  - Custom webpack config (if any)\n      *  - Files, provided by `webpackEntries` task.\n      *  - Files from `webpackMonitoredDirectories`, filtered by\n      *    `includeFilter`\n      *\n      * @group settings\n      * @see [[webpackMonitoredDirectories]]\n      * @see [[webpack]]\n      */\n    val webpackMonitoredFiles: TaskKey[Seq[File]] =\n      taskKey[Seq[File]](\"Files that trigger webpack launch\")\n\n    /**\n      * Additional arguments to webpack\n      *\n      * Defaults to an empty list.\n      *\n      * @group settings\n      */\n    val webpackExtraArgs = SettingKey[Seq[String]](\n      \"webpackExtraArgs\",\n      \"Custom arguments to webpack\"\n    )\n\n    /**\n      * node.js cli custom arguments as described in https://nodejs.org/api/cli.html\n      *\n      * Defaults to an empty list.\n      *\n      * @group settings\n      */\n    val webpackNodeArgs = SettingKey[Seq[String]](\n      \"webpackNodeArgs\",\n      \"Custom arguments to node.js when running webpack tasks\"\n    )\n\n    /**\n      * Whether to use [[https://yarnpkg.com/ Yarn]] to fetch dependencies instead\n      * of `npm`. Yarn has a caching mechanism that makes the process faster.\n      *\n      * If set to `true`, it requires Yarn 0.22.0+ to be available on the\n      * host platform.\n      *\n      * Defaults to `false`.\n      *\n      * @group settings\n      */\n    val useYarn: SettingKey[Boolean] =\n      settingKey[Boolean](\"Whether to use yarn for updates\")\n\n    /**\n      * Port, on which webpack-dev-server will be launched.\n      *\n      * Defaults to 8080.\n      *\n      * @see [[startWebpackDevServer]]\n      * @group settings\n      */\n    val webpackDevServerPort = SettingKey[Int](\n      \"webpackDevServerPort\",\n      \"Port, on which webpack-dev-server operates\"\n    )\n\n    /**\n      * Additional arguments for yarn\n      *\n      * Defaults to an empty list.\n      *\n      * @group settings\n      */\n    val yarnExtraArgs = SettingKey[Seq[String]](\n      \"yarnExtraArgs\",\n      \"Custom arguments for yarn\"\n    )\n    /**\n      * Additional arguments to webpack-dev-server.\n      *\n      * Defaults to an empty list.\n      *\n      * @see [[startWebpackDevServer]]\n      * @group settings\n      */\n    val webpackDevServerExtraArgs = SettingKey[Seq[String]](\n      \"webpackDevServerExtraArgs\",\n      \"Custom arguments to webpack-dev-server\"\n    )\n\n    /**\n      * Version of webpack-cli\n      *\n      * @group settings\n      */\n    val webpackCliVersion: SettingKey[String] =\n      settingKey[String](\"Version of webpack-cli to use\")\n\n    /**\n      * Start background webpack-dev-server process.\n      *\n      * If webpack-dev-server is already running, it will be restarted.\n      *\n      * The started webpack-dev-server receives the following arguments:\n      * - `--config` is set to value of `webpackConfigFile` setting.\n      * - `--port` is set to value of `webpackDevServerPort` setting.\n      * - Contents of `webpackDevServerExtraArgs` setting.\n      *\n      * @see [[stopWebpackDevServer]]\n      * @see [[webpackDevServerPort]]\n      * @see [[webpackDevServerExtraArgs]]\n      * @group tasks\n      */\n    val startWebpackDevServer = TaskKey[Unit](\n      \"startWebpackDevServer\",\n      \"(Re)start webpack-dev-server process\"\n    )\n\n    /**\n      * Stop running webpack-dev-server process.\n      *\n      * Does nothing if the server is not running.\n      *\n      * @see [[startWebpackDevServer]]\n      * @group tasks\n      */\n    val stopWebpackDevServer = TaskKey[Unit](\n      \"stopWebpackDevServer\",\n      \"Stop webpack-dev-server process (if running)\"\n    )\n\n    /**\n      * Locally install jsdom.\n      *\n      * You can set the jsdom package version to install with the key `version in installJsdom`.\n      *\n      * Returns the installation directory.\n      *\n      * @group tasks\n      */\n    val installJsdom = taskKey[File](\"Locally install jsdom\")\n\n    /**\n      * A flag to indicate the need to use a DOM enabled JS environment in test.\n      *\n      * Default is false.\n      *\n      * @group tasks\n      */\n    val requireJsDomEnv = taskKey[Boolean](\"Require DOM enabled environment in test\")\n\n    /**\n      * Local js source directories to be collected by the bundler\n      *\n      * Default is `src/main/js`\n      *\n      * @group settings\n      */\n    val jsSourceDirectories = settingKey[Seq[File]](\"Local js source directories to be collected by the bundler\")\n  }\n\n  private[sbtplugin] val scalaJSBundlerImportedModules =\n    TaskKey[List[String]](\"scalaJSBundlerImportedModules\",\n      \"Computes the list of imported modules\",\n      KeyRanks.Invisible\n    )\n\n  private val scalaJSBundlerPackageJson =\n    TaskKey[BundlerFile.PackageJson](\"scalaJSBundlerPackageJson\",\n      \"Write a package.json file defining the NPM dependencies of project\",\n      KeyRanks.Invisible\n    )\n\n  private[sbtplugin] val scalaJSBundlerWebpackConfig =\n    TaskKey[BundlerFile.WebpackConfig](\"scalaJSBundlerWebpackConfig\",\n      \"Write the webpack configuration file\",\n      KeyRanks.Invisible\n    )\n\n  private val webpackDevServer = SettingKey[WebpackDevServer](\n    \"webpackDevServer\",\n    \"Global WebpackDevServer instance\",\n    KeyRanks.Invisible\n  )\n\n  private[scalajsbundler] val ensureModuleKindIsCommonJSModule =\n    SettingKey[Boolean](\n      \"ensureModuleKindIsCommonJSModule\",\n      \"Checks that scalaJSModuleKind is set to CommonJSModule\",\n      KeyRanks.Invisible\n    )\n\n  import autoImport.{BundlerFile => _, _}\n\n  override lazy val projectSettings: Seq[Def.Setting[_]] = Seq(\n\n    scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) },\n\n    version in webpack := \"5.75.0\",\n\n    webpackCliVersion := \"4.5.0\",\n\n    version in startWebpackDevServer := \"3.11.2\",\n\n    version in installJsdom := \"9.9.0\",\n\n    webpackConfigFile := None,\n\n    webpackResources := baseDirectory.value * \"*.js\",\n\n    // Include the manifest in the produced artifact\n    (products in Compile) := (products in Compile).dependsOn(scalaJSBundlerManifest).value,\n\n    useYarn := false,\n\n    ensureModuleKindIsCommonJSModule := {\n      if (scalaJSLinkerConfig.value.moduleKind == ModuleKind.CommonJSModule) true\n      else sys.error(s\"scalaJSModuleKind must be set to ModuleKind.CommonJSModule in projects where ScalaJSBundler plugin is enabled\")\n    },\n\n    webpackBundlingMode := BundlingMode.Default,\n\n    // Make these settings project-level, since we don't expect much\n    // difference between configurations/stages. This way the\n    // API user can modify it just once.\n    webpackMonitoredDirectories := Seq(),\n    (includeFilter in webpackMonitoredFiles) := AllPassFilter,\n    webpackExtraArgs := Seq.empty,\n    webpackNodeArgs := Seq.empty,\n\n    npmExtraArgs := Seq.empty,\n    yarnExtraArgs := Seq.empty,\n\n    // The defaults are specified at top level.\n    webpackDevServerPort := 8080,\n    webpackDevServerExtraArgs := Seq(),\n\n    // We can only have one server per project - for simplicity\n    webpackDevServer := new WebpackDevServer(),\n\n    (onLoad in Global) := {\n      (onLoad in Global).value.compose(\n        _.addExitHook {\n          webpackDevServer.value.stop()\n        }\n      )\n    },\n\n    installJsdom := {\n      val installDir = target.value / \"scalajs-bundler-jsdom\"\n      val baseDir = baseDirectory.value\n      val jsdomDir = installDir / \"node_modules\" / \"jsdom\"\n      val log = streams.value.log\n      val jsdomVersion = (version in installJsdom).value\n      if (!jsdomDir.exists()) {\n        log.info(s\"Installing jsdom in ${installDir.absolutePath}\")\n        IO.createDirectory(installDir)\n        addPackages(baseDir, installDir, useYarn.value, log, npmExtraArgs.value, yarnExtraArgs.value)(s\"jsdom@$jsdomVersion\")\n      }\n      installDir\n    }\n  ) ++\n    inConfig(Compile)(perConfigSettings) ++\n    inConfig(Test)(perConfigSettings ++ testSettings)\n\n  private lazy val perConfigSettings: Seq[Def.Setting[_]] =\n    Def.settings(\n      npmDependencies := Seq.empty,\n\n      npmDevDependencies := Seq.empty,\n\n      npmResolutions := Map.empty,\n\n      additionalNpmConfig := Map(\n        \"private\" -> JSON.bool(true),\n        \"license\" -> JSON.str(\"UNLICENSED\")\n      ),\n\n      jsSourceDirectories := Seq(sourceDirectory.value  / \"js\"),\n\n      npmUpdate := {\n        val _ = npmInstallJSResources.value\n        npmInstallDependencies.value\n      },\n\n      npmInstallDependencies := NpmUpdateTasks.npmInstallDependencies(\n        baseDirectory.value,\n        (crossTarget in npmUpdate).value,\n        scalaJSBundlerPackageJson.value.file,\n        useYarn.value,\n        streams.value,\n        npmExtraArgs.value,\n        yarnExtraArgs.value),\n\n      npmInstallJSResources := NpmUpdateTasks.npmInstallJSResources(\n        (crossTarget in npmUpdate).value,\n        ScalaJSNativeLibraries(fullClasspath.value),\n        jsSourceDirectories.value,\n        streams.value),\n\n      scalaJSBundlerPackageJson :=\n        PackageJsonTasks.writePackageJson(\n          (crossTarget in npmUpdate).value,\n          npmDependencies.value,\n          npmDevDependencies.value,\n          npmResolutions.value,\n          additionalNpmConfig.value,\n          dependencyClasspath.value,\n          configuration.value,\n          (version in webpack).value,\n          (version in startWebpackDevServer).value,\n          webpackCliVersion.value,\n          streams.value\n        ),\n\n\n      crossTarget in npmUpdate := {\n        crossTarget.value / \"scalajs-bundler\" / (if (configuration.value == Compile) \"main\" else \"test\")\n      },\n\n      Settings.configSettings\n    ) ++\n    perScalaJSStageSettings(Stage.FastOpt) ++\n    perScalaJSStageSettings(Stage.FullOpt)\n\n  override def globalSettings: Seq[Def.Setting[_]] =\n    Settings.globalSettings\n\n  private lazy val testSettings: Seq[Setting[_]] =\n    Def.settings(\n      npmDependencies ++= (npmDependencies in Compile).value,\n\n      npmDevDependencies ++= (npmDevDependencies in Compile).value,\n\n      jsSourceDirectories ++= (jsSourceDirectories in Compile).value,\n\n      requireJsDomEnv := false,\n\n      Settings.testConfigSettings\n\n    )\n\n  private def perScalaJSStageSettings(stage: Stage): Seq[Def.Setting[_]] = {\n\n    val stageTask = stage match {\n      case Stage.FastOpt => fastOptJS\n      case Stage.FullOpt => fullOptJS\n    }\n\n    Seq(\n      // Ask Scala.js to output its result in our target directory\n      crossTarget in stageTask := (crossTarget in npmUpdate).value,\n\n      finallyEmitSourceMaps in stageTask := {\n        (webpackEmitSourceMaps in stageTask).?.value\n          .getOrElse((scalaJSLinkerConfig in stageTask).value.sourceMap)\n      },\n\n      // Override Scala.js’ relativeSourceMaps in case we have to emit source maps in the webpack task, because it does not work with absolute source maps\n      scalaJSLinkerConfig in stageTask := {\n        val prev = (scalaJSLinkerConfig in stageTask).value\n        val relSourceMaps = (webpackEmitSourceMaps in stageTask).?.value.getOrElse(prev.sourceMap)\n        val relSourceMapBase = (artifactPath in stageTask).value.toURI\n        if (!relSourceMaps) {\n          prev\n        } else {\n          prev.withRelativizeSourceMapBase(Some(relSourceMapBase))\n        }\n      },\n\n      scalaJSBundlerWebpackConfig in stageTask := BundlerFile.WebpackConfig(\n        WebpackTasks.entry(stageTask).value,\n        npmUpdate.value / \"scalajs.webpack.config.js\"\n      ),\n\n      webpack in stageTask := Def.taskDyn {\n        (webpackBundlingMode in stageTask).value match {\n          case scalajsbundler.BundlingMode.Application =>\n            WebpackTasks.webpack(stageTask)\n          case mode: scalajsbundler.BundlingMode.LibraryOnly =>\n            LibraryTasks.librariesAndLoaders(stageTask, mode)\n          case mode: scalajsbundler.BundlingMode.LibraryAndApplication =>\n            LibraryTasks.libraryAndLoadersBundle(stageTask, mode)\n        }\n      }.value,\n\n      webpackMonitoredFiles in stageTask := {\n        val generatedWebpackConfigFile = (scalaJSBundlerWebpackConfig in stageTask).value\n        val customWebpackConfigFile = (webpackConfigFile in stageTask).value\n        val packageJsonFile = scalaJSBundlerPackageJson.value\n        val entry = WebpackTasks.entry(stageTask).value\n        val filter = (includeFilter in webpackMonitoredFiles).value\n        val dirs = (webpackMonitoredDirectories in stageTask).value\n\n        val generatedFiles: Seq[File] = Seq(\n          packageJsonFile.file,\n          generatedWebpackConfigFile.file,\n          entry.file)\n        val additionalFiles: Seq[File] = dirs.flatMap(\n          dir => (dir ** filter).get\n        )\n        generatedFiles ++\n          customWebpackConfigFile.toSeq ++\n          webpackResources.value.get ++\n          additionalFiles\n      },\n\n      // webpack-dev-server wiring\n      startWebpackDevServer in stageTask := Def.task {\n        val extraArgs = (webpackDevServerExtraArgs in stageTask).value\n\n        // This duplicates file layout logic from `Webpack`\n        val targetDir = (npmUpdate in stageTask).value\n        val customConfigOption = (webpackConfigFile in stageTask).value\n        val generatedConfig = (scalaJSBundlerWebpackConfig in stageTask).value\n\n        val config = customConfigOption\n          .map(Webpack.copyCustomWebpackConfigFiles(targetDir, webpackResources.value.get))\n          .getOrElse(generatedConfig.file)\n\n        // To match `webpack` task behavior\n        val workDir = targetDir\n\n        // Server instance is project-level\n        val server = webpackDevServer.value\n        val logger = (streams in stageTask).value.log\n        val globalLogger = state.value.globalLogging.full\n\n        server.start(\n          workDir,\n          config,\n          extraArgs,\n          logger,\n          globalLogger\n        )\n      }.dependsOn(\n        // We need to execute the full webpack task once, since it generates\n        // the required config file\n        (webpack in stageTask),\n\n        npmUpdate\n      ).value,\n\n      // Stops the global server instance, but is defined on stage\n      // level to match `startWebpackDevServer`\n      stopWebpackDevServer in stageTask := {\n        webpackDevServer.value.stop()\n      }\n    )\n  }\n\n  /**\n    * Writes the scalajs-bundler manifest file.\n    */\n  val scalaJSBundlerManifest: Def.Initialize[Task[File]] =\n    Def.task {\n      NpmDependencies.writeManifest(\n        NpmDependencies(\n          (npmDependencies in Compile).value.to[List],\n          (npmDependencies in Test).value.to[List],\n          (npmDevDependencies in Compile).value.to[List],\n          (npmDevDependencies in Test).value.to[List]\n        ),\n        (classDirectory in Compile).value\n      )\n    }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/sbtplugin/Settings.scala",
    "content": "package scalajsbundler.sbtplugin\n\nimport java.nio.charset.StandardCharsets\nimport java.nio.file.{Files, Path}\nimport scala.collection.JavaConverters._\nimport org.scalajs.jsenv.Input._\nimport org.scalajs.linker.interface._\nimport org.scalajs.sbtplugin._\nimport org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._\nimport sbt.Keys._\nimport sbt._\nimport scalajsbundler.{JSDOMNodeJSEnv, Webpack, JsDomTestEntries, NpmPackage}\nimport scalajsbundler.sbtplugin.ScalaJSBundlerPlugin.autoImport.{installJsdom, npmUpdate, requireJsDomEnv, webpackConfigFile, webpackNodeArgs, webpackResources, webpack}\nimport scalajsbundler.sbtplugin.ScalaJSBundlerPlugin.{ensureModuleKindIsCommonJSModule, scalaJSBundlerImportedModules}\nimport scalajsbundler.sbtplugin.internal.BuildInfo\n\nprivate[sbtplugin] object Settings {\n\n  private class BundlerLinkerImpl(base: LinkerImpl.Reflect)\n      extends LinkerImpl.Forwarding(base) {\n\n    private val loader = base.loader\n\n    private val clearableLinkerMethod = {\n      Class.forName(\"scalajsbundler.bundlerlinker.BundlerLinkerImpl\", true, loader)\n        .getMethod(\"clearableLinker\", classOf[StandardConfig], classOf[Path])\n    }\n\n    def bundlerLinker(config: StandardConfig, entryPointOutputFile: Path): ClearableLinker = {\n      clearableLinkerMethod.invoke(null, config, entryPointOutputFile)\n        .asInstanceOf[ClearableLinker]\n    }\n  }\n\n  // Settings that must be applied in Global\n  val globalSettings: Seq[Setting[_]] =\n    Def.settings(\n      fullClasspath in scalaJSLinkerImpl := {\n        val s = streams.value\n        val log = s.log\n        val retrieveDir = s.cacheDirectory / \"scalajs-bundler-linker\"\n        val lm = (dependencyResolution in scalaJSLinkerImpl).value\n        val dummyModuleID =\n          \"ch.epfl.scala\" % \"scalajs-bundler-linker-and-scalajs-linker_2.12\" % s\"${BuildInfo.version}-$scalaJSVersion\"\n        val dependencies = Vector(\n            // Load our linker back-end\n            \"ch.epfl.scala\" % \"scalajs-bundler-linker_2.12\" % BuildInfo.version,\n            // And force-bump the dependency on scalajs-linker to match the version of sbt-scalajs\n            \"org.scala-js\" % \"scalajs-linker_2.12\" % scalaJSVersion\n        )\n        val moduleDescriptor = lm.moduleDescriptor(dummyModuleID, dependencies, scalaModuleInfo = None)\n        lm.retrieve(moduleDescriptor, retrieveDir, log)\n          .fold(w => throw w.resolveException, Attributed.blankSeq(_))\n      },\n\n      scalaJSLinkerImpl := {\n        val cp = (fullClasspath in scalaJSLinkerImpl).value\n        scalaJSLinkerImplBox.value.ensure {\n          new BundlerLinkerImpl(LinkerImpl.reflect(Attributed.data(cp)))\n        }\n      }\n    )\n\n  // Settings that must be applied for each stage in each configuration\n  private def scalaJSStageSettings(stage: Stage, key: TaskKey[Attributed[Report]],\n      legacyKey: TaskKey[Attributed[File]]): Seq[Setting[_]] = {\n    val entryPointOutputFileName =\n      s\"entrypoints-${stage.toString.toLowerCase}.txt\"\n\n    Def.settings(\n      scalaJSLinker in legacyKey := {\n        val config = (scalaJSLinkerConfig in key).value\n        val box = (scalaJSLinkerBox in key).value\n        val linkerImpl = (scalaJSLinkerImpl in key).value\n        val entryPointOutputFile = crossTarget.value / entryPointOutputFileName\n\n        box.ensure {\n          linkerImpl.asInstanceOf[BundlerLinkerImpl]\n            .bundlerLinker(config, entryPointOutputFile.toPath)\n        }\n      },\n\n      scalaJSBundlerImportedModules in legacyKey := {\n        val _ = legacyKey.value\n        val entryPointOutputFile = crossTarget.value / entryPointOutputFileName\n        val lines = Files.readAllLines(entryPointOutputFile.toPath, StandardCharsets.UTF_8)\n        lines.asScala.toList\n      }\n    )\n  }\n\n  // Settings that must be applied for each configuration\n  val configSettings: Seq[Setting[_]] =\n    Def.settings(\n      // Override Scala.js’ jsEnvInput to first run `npm update`\n      jsEnvInput := jsEnvInput.dependsOn(npmUpdate).value,\n\n      /* Moreover, force it to use the output of the legacy key, because lots\n       * of things in scalajs-bundler assume that there is only one .js file\n       * that we can put in a specific directory to make things work.\n       */\n      jsEnvInput := {\n        val prev = jsEnvInput.value\n        val linkingResult = scalaJSLinkerResult.value\n        val legacyKeyOutput = scalaJSLinkedFile.value\n\n        // Compute the path to the `main` module, which is what sbt-scalajs puts in jsEnvInput\n        val report = linkingResult.data\n        val optMainModule = report.publicModules.find(_.moduleID == \"main\")\n        val optMainModulePath = optMainModule.map { mainModule =>\n          val linkerOutputDirectory = linkingResult.get(scalaJSLinkerOutputDirectory.key).getOrElse {\n            throw new MessageOnlyException(\n                \"Linking report was not attributed with output directory. \" +\n                \"Please report this as a Scala.js bug.\")\n          }\n          (linkerOutputDirectory / mainModule.jsFileName).toPath\n        }\n\n        // Replace the path to the `main` module by the path to the legacy key output\n        optMainModulePath match {\n          case Some(mainModulePath) =>\n            prev.map {\n              case CommonJSModule(module) if module == mainModulePath =>\n                CommonJSModule(legacyKeyOutput.data.toPath())\n              case inputItem =>\n                inputItem\n            }\n          case None =>\n            prev\n        }\n      },\n\n      scalaJSStageSettings(FastOptStage, fastLinkJS, fastOptJS),\n      scalaJSStageSettings(FullOptStage, fullLinkJS, fullOptJS)\n    )\n\n  // Settings that must be applied in the Test configuration\n  val testConfigSettings: Seq[Setting[_]] =\n    Def.settings(\n      // Configure a JSDOMNodeJSEnv with an installation of jsdom if requireJsDomEnv is true\n      jsEnv := {\n        val defaultJSEnv = jsEnv.value\n        val optJsdomDir = Def.taskDyn[Option[File]] {\n          if (requireJsDomEnv.value)\n            installJsdom.map(Some(_))\n          else\n            Def.task(None)\n        }.value\n        optJsdomDir match {\n          case Some(jsdomDir) => new JSDOMNodeJSEnv(JSDOMNodeJSEnv.Config(jsdomDir))\n          case None           => defaultJSEnv\n        }\n      },\n\n      // Use the product of bundling in jsEnvInput if requireJsDomEnv is true\n      jsEnvInput := Def.task {\n        assert(ensureModuleKindIsCommonJSModule.value)\n        val prev = jsEnvInput.value\n        val sjsOutput = scalaJSLinkedFile.value.data\n\n        val optBundle = {\n          Def.taskDyn[Option[org.scalajs.jsenv.Input]] {\n            val sjsOutput = scalaJSLinkedFile.value.data\n            // If jsdom is going to be used, then we should bundle the test module\n            if (requireJsDomEnv.value) Def.task {\n              val logger = streams.value.log\n              val targetDir = npmUpdate.value\n              val sjsOutputName = sjsOutput.name.stripSuffix(\".js\")\n              val bundle = targetDir / s\"$sjsOutputName-bundle.js\"\n              val webpackVersion = (version in webpack).value\n\n              val customWebpackConfigFile = (webpackConfigFile in Test).value\n              val nodeArgs = (webpackNodeArgs in Test).value\n\n              val writeTestBundleFunction =\n                FileFunction.cached(\n                  streams.value.cacheDirectory / \"test-loader\",\n                  inStyle = FilesInfo.hash\n                ) { _ =>\n                  logger.info(\"Writing and bundling the test loader\")\n                  val loader = targetDir / s\"$sjsOutputName-loader.js\"\n                  JsDomTestEntries.writeLoader(sjsOutput, loader)\n\n                  val configArgs = customWebpackConfigFile match {\n                    case Some(configFile) =>\n                      val customConfigFileCopy = Webpack.copyCustomWebpackConfigFiles(targetDir, webpackResources.value.get)(configFile)\n                      Seq(\"--config\", customConfigFileCopy.getAbsolutePath)\n\n                    case None =>\n                      Seq.empty\n                  }\n\n                  // TODO: It assumes tests are run on development mode. It should instead use build settings\n                  val allArgs = Seq(\n                    \"--mode\", \"development\",\n                    \"--entry\", loader.absolutePath,\n                    \"--output-path\", bundle.getParentFile.absolutePath,\n                    \"--output-filename\", bundle.name\n                  ) ++ configArgs\n\n                  NpmPackage(webpackVersion).major match {\n                    case Some(5) =>\n                      Webpack.run(nodeArgs: _*)(allArgs: _*)(targetDir, logger)\n                    case Some(x) =>\n                      sys.error(s\"Unsupported webpack major version $x\")\n                    case None =>\n                      sys.error(\"No webpack version defined\")\n                  }\n\n                  Set.empty\n                }\n              writeTestBundleFunction(Set(sjsOutput))\n\n              Some(Script(bundle.toPath))\n            } else Def.task {\n              None\n            }\n          }.value\n        }\n\n        optBundle match {\n          case Some(bundle) =>\n            prev.map {\n              case CommonJSModule(module) if module == sjsOutput.toPath() =>\n                bundle\n              case inputItem =>\n                inputItem\n            }\n          case None =>\n            prev\n        }\n      }.dependsOn(npmUpdate).value\n    )\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/sbtplugin/WebpackTasks.scala",
    "content": "package scalajsbundler.sbtplugin\nimport sbt.Keys._\nimport sbt.{Def, _}\n\nimport org.scalajs.sbtplugin.ScalaJSPlugin.autoImport.scalaJSLinkerConfig\nimport scalajsbundler.sbtplugin.ScalaJSBundlerPlugin._\nimport scalajsbundler.sbtplugin.ScalaJSBundlerPlugin.autoImport._\nimport scalajsbundler.Webpack\n\nobject WebpackTasks {\n  private[sbtplugin] def entry(stage: TaskKey[Attributed[File]])\n  : Def.Initialize[Task[BundlerFile.Application]] =\n    Def.task {\n      val projectName = stage.value.data.name.stripSuffix(\".js\")\n      BundlerFile.Application(projectName, stage.value.data, Nil)\n    }\n\n  private[sbtplugin] def webpack(\n      stage: TaskKey[Attributed[File]]): Def.Initialize[Task[Seq[Attributed[File]]]] =\n    Def.task {\n      assert(ensureModuleKindIsCommonJSModule.value)\n      val cacheLocation = streams.value.cacheDirectory / s\"${stage.key.label}-webpack\"\n      val generatedWebpackConfigFile =\n        (scalaJSBundlerWebpackConfig in stage).value\n      val emitSourceMaps = (finallyEmitSourceMaps in stage).value\n      val customWebpackConfigFile = (webpackConfigFile in stage).value\n      val webpackResourceFiles = webpackResources.value.get\n      val entriesList = entry(stage).value\n      val targetDir = npmUpdate.value\n      val log = streams.value.log\n      val monitoredFiles = (webpackMonitoredFiles in stage).value\n      val extraArgs = (webpackExtraArgs in stage).value\n      val nodeArgs = (webpackNodeArgs in stage).value\n      val webpackMode =\n        Webpack.WebpackMode.fromBooleanProductionMode((scalaJSLinkerConfig in stage).value.semantics.productionMode)\n      val devServerPort = webpackDevServerPort.value\n\n      val cachedActionFunction =\n        FileFunction.cached(\n          cacheLocation,\n          inStyle = FilesInfo.hash\n        ) { _ =>\n          Webpack.bundle(\n            emitSourceMaps,\n            generatedWebpackConfigFile,\n            customWebpackConfigFile,\n            webpackResourceFiles,\n            entriesList,\n            targetDir,\n            extraArgs,\n            nodeArgs,\n            webpackMode,\n            devServerPort,\n            log\n          ).cached\n        }\n      val cached = cachedActionFunction(monitoredFiles.to[Set])\n      generatedWebpackConfigFile.asApplicationBundleFromCached(cached).asAttributedFiles\n    }\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/util/CachedBundleFiles.scala",
    "content": "package scalajsbundler.util\n\nimport java.io.File\nimport scala.collection.immutable.ListSet\n\nobject CachedBundleFiles {\n  def cached(file: File, assets: List[File]): ListSet[File] = {\n    // Let's put the main file first\n    val sortedAssets = file :: assets.filterNot(_ == file)\n    // use list set to preserve the order\n    ListSet(sortedAssets: _*)\n  }\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/util/Caching.scala",
    "content": "package scalajsbundler.util\n\nimport sbt._\n\nobject Caching {\n\n  def cached(\n    fileToWrite: File,\n    hash: String,\n    cache: File\n  )(\n    write: () => Unit\n  ): Unit = {\n    if (!fileToWrite.exists() || (cache.exists() && IO.read(cache) != hash)) {\n      write()\n      IO.write(cache, hash)\n    }\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/util/Commands.scala",
    "content": "package scalajsbundler.util\n\nimport sbt.Logger\nimport java.io.{InputStream, File}\nimport scala.sys.process.Process\nimport scala.sys.process.BasicIO\nimport scala.sys.process.ProcessLogger\n\nobject Commands {\n\n  def run[A](cmd: Seq[String], cwd: File, logger: Logger, outputProcess: InputStream => A): Either[String, Option[A]] = {\n    val toErrorLog = (is: InputStream) => {\n      scala.io.Source.fromInputStream(is).getLines.foreach(msg => logger.error(msg))\n      is.close()\n    }\n\n    // Unfortunately a var is the only way to capture the result\n    var result: Option[A] = None\n    def outputCapture(o: InputStream): Unit = {\n      result = Some(outputProcess(o))\n      o.close()\n      ()\n    }\n\n    logger.debug(s\"Command: ${cmd.mkString(\" \")}\")\n    val process = Process(cmd, cwd)\n    val processIO = BasicIO.standard(false).withOutput(outputCapture).withError(toErrorLog)\n    val code: Int = process.run(processIO).exitValue()\n    if (code != 0) {\n      Left(s\"Non-zero exit code: $code\")\n    } else {\n      Right(result)\n    }\n  }\n\n  def run(cmd: Seq[String], cwd: File, logger: Logger): Unit = {\n    val toInfoLog = (is: InputStream) => scala.io.Source.fromInputStream(is).getLines.foreach(msg => logger.info(msg))\n    run(cmd, cwd, logger, toInfoLog).fold(sys.error, _ => ())\n  }\n\n  def start(cmd: Seq[String], cwd: File, logger: Logger): Process =\n    Process(cmd, cwd).run(toProcessLogger(logger))\n\n  private def toProcessLogger(logger: Logger): ProcessLogger =\n    ProcessLogger(msg => logger.info(msg), msg => logger.error(msg))\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/util/JS.scala",
    "content": "package scalajsbundler.util\n\nimport java.util.concurrent.atomic.AtomicInteger\n\nimport JSTrees._\n\nprivate[util] sealed abstract class JSLike(val tree: Tree) {\n  def show: String = tree.show\n  def show(isStat: Boolean = true): String = JSLike.show(tree, isStat)\n  def toJson: String = JSLike.show(tree, isStat = false)\n}\n\nobject JSLike {\n  private def show(tree: Tree, isStat: Boolean): String = {\n    val writer = new java.io.StringWriter\n    val printer = new JSPrinters.JSTreePrinter(writer)\n    printer.printTree(tree, isStat)\n    writer.toString\n  }\n}\n\n/** A convenient wrapper around JS trees */\nfinal class JS private(tree: Tree) extends JSLike(tree) {\n  def dot(ident: String): JS = JS(DotSelect(tree, Ident(ident)))\n  def bracket(ident: String): JS = JS(BracketSelect(tree, StringLiteral(ident)))\n  def bracket(ident: JSLike): JS = JS(BracketSelect(tree, ident.tree))\n  def assign(rhs: JSLike): JS = JS(Assign(tree, rhs.tree))\n  def apply(args: JSLike*): JS = JS(Apply(tree, args.map(_.tree).to[List]))\n}\n\nobject JS {\n\n  private[util] def apply(tree: Tree): JS = new JS(tree)\n\n  /** Array literal. */\n  def arr(elems: JSLike*): JS = JS(ArrayConstr(elems.map(_.tree).to[List]))\n\n  /** Boolean literal */\n  def bool(value: Boolean): JS = JS(BooleanLiteral(value))\n\n  /** Object literal */\n  def obj(fields: (String, JSLike)*): JS =\n    JS(ObjectConstr(fields.map { case (ident, value) => (StringLiteral(ident), value.tree) }.to[List]))\n\n  /** Object literal */\n  def objStr(fields: Seq[(String, String)]): JS =\n    obj(fields.map { case (k, v) => k -> JS.str(v) }: _*)\n\n  /** String literal */\n  def str(value: String): JS = JS(StringLiteral(value))\n\n  /** Numeric literal */\n  def int(value: Int): JS = JS(IntLiteral(value))\n\n  /** Variable reference */\n  def ref(ident: String): JS =\n    JS(varRef(ident))\n\n  private def varRef(ident: String): VarRef = VarRef(Ident(ident))\n\n  /** Variable definition */\n  def `var`(ident: String, rhs: Option[JSLike] = None): JS =\n    JS(VarDef(Ident(ident), rhs.map(_.tree)))\n\n  def regex(value: String): JS =\n    JS(New(varRef(\"RegExp\"), List(StringLiteral(value))))\n\n  /** Block of several statements */\n  def block(stats: JS*): JS = JS(Block(stats.map(_.tree).to[List]))\n\n  /** Anonymous function definition */\n  def fun(body: JS => JSLike): JS = {\n    val param = freshIdentifier()\n    JS(Function(arrow = false, List(ParamDef(Ident(param), rest = false)), Return(body(ref(param)).tree)))\n  }\n\n  /** Name binding */\n  def let(value: JS)(usage: JS => JS): JS = {\n    val ident = freshIdentifier()\n    JS(Block(VarDef(Ident(ident), Some(value.tree)), usage(ref(ident)).tree))\n  }\n\n  /** Name binding */\n  def let(value1: JS, value2: JS)(usage: (JS, JS) => JS): JS = {\n    val ident1 = freshIdentifier()\n    val ident2 = freshIdentifier()\n    JS(\n      Block(\n        VarDef(Ident(ident1), Some(value1.tree)),\n        VarDef(Ident(ident2), Some(value2.tree)),\n        usage(ref(ident1), ref(ident2)).tree\n      )\n    )\n  }\n\n  def `new`(ctor: JS, args: JSLike*): JS = JS(New(ctor.tree, args.map(_.tree).to[List]))\n\n  private val identifierSeq = new AtomicInteger(0)\n  private def freshIdentifier(): String =\n    s\"x${identifierSeq.getAndIncrement()}\"\n\n}\n\nfinal class JSON private(tree: Tree) extends JSLike(tree)\n\nobject JSON {\n\n  private[util] def apply(tree: Tree): JSON = new JSON(tree)\n\n  /** Array literal. */\n  def arr(elems: JSON*): JSON = JSON(ArrayConstr(elems.map(_.tree).to[List]))\n\n  /** Boolean literal */\n  def bool(value: Boolean): JSON = JSON(BooleanLiteral(value))\n\n  /** Object literal */\n  def obj(fields: (String, JSON)*): JSON =\n    JSON(ObjectConstr(fields.map { case (ident, value) => (StringLiteral(ident), value.tree) }.to[List]))\n\n  /** Object literal */\n  def objStr(fields: Seq[(String, String)]): JSON =\n    obj(fields.map { case (k, v) => k -> JSON.str(v) }: _*)\n\n  /** String literal */\n  def str(value: String): JSON = JSON(StringLiteral(value))\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/util/JSBundler.scala",
    "content": "package scalajsbundler.util\n\nimport sbt._\n\nimport scalajsbundler.BundlerFile\n\nobject JSBundler {\n\n  def loaderScript(bundleName: String): String =\n    s\"\"\"\n       |var exports = window;\n       |exports.require = window[\"$bundleName\"].require;\n    \"\"\".stripMargin\n\n  def writeLoader(\n      loaderFile: BundlerFile.Loader,\n      bundleName: String\n  ): Unit =\n    IO.write(loaderFile.file, loaderScript(bundleName))\n\n  /**\n    * Run webpack to bundle the application.\n    *\n    * @param targetDir Target directory (and working directory for Nodejs)\n    * @param logger Logger\n    * @return The generated bundles\n    */\n  def bundle(\n      targetDir: File,\n      entry: BundlerFile.Application,\n      libraryFile: BundlerFile.Library,\n      emitSourceMaps: Boolean = false,\n      libraryBundleName: String,\n      logger: Logger\n  ): BundlerFile.ApplicationBundle = {\n    val bundleFile = entry.asApplicationBundle\n    val loaderFile = entry.asLoader\n    writeLoader(loaderFile, libraryBundleName)\n    if (emitSourceMaps) {\n      logger.info(\"Bundling dependencies with source maps\")\n      val concatContent =\n        JS.let(\n          JS.ref(\"require\")(JS.str(\"concat-with-sourcemaps\")),\n          JS.ref(\"require\")(JS.str(\"fs\"))\n        ) { (Concat, fs) =>\n          JS.let(\n            JS.`new`(Concat,\n                     JS.bool(true),\n                     JS.str(bundleFile.file.name),\n                     JS.str(\";\\n\"))) { concat =>\n            JS.block(\n              concat\n                .dot(\"add\")\n                .apply(\n                  JS.str(\"\"),\n                  fs.dot(\"readFileSync\")\n                    .apply(JS.str(libraryFile.file.absolutePath),\n                           JS.str(\"utf-8\")),\n                  fs.dot(\"readFileSync\")\n                    .apply(JS.str(libraryFile.file.absolutePath ++ \".map\"))\n                ),\n              concat\n                .dot(\"add\")\n                .apply(JS.str(loaderFile.file.name),\n                       fs.dot(\"readFileSync\")\n                         .apply(JS.str(loaderFile.file.absolutePath))),\n              concat\n                .dot(\"add\")\n                .apply(\n                  JS.str(\"\"),\n                  fs.dot(\"readFileSync\")\n                    .apply(JS.str(entry.file.absolutePath), JS.str(\"utf-8\")),\n                  fs.dot(\"readFileSync\")\n                    .apply(JS.str(entry.file.absolutePath ++ \".map\"),\n                           JS.str(\"utf-8\"))\n                ),\n              JS.let(JS.ref(\"Buffer\").dot(\"from\").apply(\n                JS.str(s\"\\n//# sourceMappingURL=${bundleFile.file.name ++ \".map\"}\\n\"))\n              ) { endBuffer =>\n                  JS.let(\n                    JS.ref(\"Buffer\")\n                      .dot(\"concat\")\n                      .apply(JS.arr(concat.dot(\"content\"), endBuffer))) {\n                    result =>\n                      fs.dot(\"writeFileSync\")\n                        .apply(JS.str(bundleFile.file.absolutePath), result)\n                  }\n              },\n              fs.dot(\"writeFileSync\")\n                .apply(JS.str(bundleFile.file.absolutePath ++ \".map\"),\n                       concat.dot(\"sourceMap\"))\n            )\n          }\n        }\n      val concatFile = targetDir / s\"scalajsbundler-concat-${bundleFile.file.name}\"\n      IO.write(concatFile, concatContent.show)\n      Commands.run(Seq(\"node\", concatFile.absolutePath), targetDir, logger)\n    } else {\n      logger.info(\"Bundling dependencies without source maps\")\n      IO.withTemporaryFile(\"scalajs-bundler\", entry.project) { tmpFile =>\n        IO.append(tmpFile, IO.readBytes(libraryFile.file))\n        IO.append(tmpFile, \"\\n\")\n        IO.append(tmpFile, IO.readBytes(loaderFile.file))\n        IO.append(tmpFile, \"\\n\")\n        IO.append(tmpFile, IO.readBytes(entry.file))\n        IO.move(tmpFile, bundleFile.file)\n      }\n    }\n    bundleFile\n  }\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/util/JSPrinters.scala",
    "content": "package scalajsbundler.util\n\nimport scala.annotation.switch\n\n// Unimport default print and println to avoid invoking them by mistake\nimport scala.Predef.{print => _, println => _, _}\n\nimport java.io.Writer\n\nimport JSTrees._\n\n// This is copied from `org.scalajs.linker.backend.javascript.Printers` in Scala.js.\nprivate[util] object JSPrinters {\n\n  abstract class IndentationManager {\n    protected val out: Writer\n\n    private var indentMargin = 0\n    private val indentStep = 2\n    private var indentString = \"                                        \" // 40\n\n    protected def indent(): Unit = indentMargin += indentStep\n    protected def undent(): Unit = indentMargin -= indentStep\n\n    protected def getIndentMargin(): Int = indentMargin\n\n    protected def println(): Unit = {\n      out.write('\\n')\n      while (indentMargin > indentString.length())\n        indentString += indentString\n      if (indentMargin > 0)\n        out.write(indentString, 0, indentMargin)\n    }\n  }\n\n  class JSTreePrinter(protected val out: Writer) extends IndentationManager {\n\n    def printTopLevelTree(tree: Tree): Unit = {\n      tree match {\n        case Skip() =>\n          // do not print anything\n        case tree: Block =>\n          var rest = tree.stats\n          while (rest.nonEmpty) {\n            printTopLevelTree(rest.head)\n            rest = rest.tail\n          }\n        case _ =>\n          printStat(tree)\n          if (shouldPrintSepAfterTree(tree))\n            print(';')\n          println()\n      }\n    }\n\n    protected def shouldPrintSepAfterTree(tree: Tree): Boolean = tree match {\n      case _:DocComment | _:FunctionDef | _:ClassDef => false\n      case _                                         => true\n    }\n\n    protected def printRow(ts: List[Tree], start: Char, end: Char): Unit = {\n      print(start.toInt)\n      var rest = ts\n      while (rest.nonEmpty) {\n        print(rest.head)\n        rest = rest.tail\n        if (rest.nonEmpty)\n          print(\", \")\n      }\n      print(end.toInt)\n    }\n\n    protected def printBlock(tree: Tree): Unit = {\n      print('{'); indent(); println()\n      tree match {\n        case tree: Block =>\n          var rest = tree.stats\n          while (rest.nonEmpty) {\n            val x = rest.head\n            rest = rest.tail\n            printStat(x)\n            if (rest.nonEmpty) {\n              if (shouldPrintSepAfterTree(x))\n                print(';')\n              println()\n            }\n          }\n\n        case _ =>\n          printStat(tree)\n      }\n      undent(); println(); print('}')\n    }\n\n    protected def printSig(args: List[ParamDef]): Unit = {\n      printRow(args, '(', ')')\n      print(' ')\n    }\n\n    protected def printArgs(args: List[Tree]): Unit =\n      printRow(args, '(', ')')\n\n    protected def printStat(tree: Tree): Unit =\n      printTree(tree, isStat = true)\n\n    protected def print(tree: Tree): Unit =\n      printTree(tree, isStat = false)\n\n    def printTree(tree: Tree, isStat: Boolean): Unit = {\n      tree match {\n        // Comments\n\n        case DocComment(text) =>\n          val lines = text.split(\"\\n\").toList\n          if (lines.tail.isEmpty) {\n            print(\"/** \")\n            print(lines.head)\n            print(\" */\")\n          } else {\n            print(\"/** \")\n            print(lines.head)\n            println()\n            var rest = lines.tail\n            while (rest.nonEmpty) {\n              print(\" *  \")\n              print(rest.head)\n              println()\n              rest = rest.tail\n            }\n            print(\" */\")\n          }\n\n        // Definitions\n\n        case VarDef(ident, optRhs) =>\n          print(\"var \")\n          print(ident)\n          optRhs foreach { rhs =>\n            print(\" = \")\n            print(rhs)\n          }\n\n        case Let(ident, mutable, optRhs) =>\n          print(if (mutable) \"let \" else \"const \")\n          print(ident)\n          optRhs foreach { rhs =>\n            print(\" = \")\n            print(rhs)\n          }\n\n        case ParamDef(ident, rest) =>\n          if (rest)\n            print(\"...\")\n          print(ident)\n\n        // Control flow constructs\n\n        case Skip() =>\n          print(\"/*<skip>*/\")\n\n        case tree: Block =>\n          if (isStat)\n            printBlock(tree)\n          else\n            printRow(tree.stats, '(', ')')\n\n        case Labeled(label, body) =>\n          print(label)\n          print(\": \")\n          printBlock(body)\n\n        case Assign(lhs, rhs) =>\n          print(lhs)\n          print(\" = \")\n          print(rhs)\n\n        case Return(expr) =>\n          print(\"return \")\n          print(expr)\n\n        case If(cond, thenp, elsep) =>\n          if (isStat) {\n            print(\"if (\")\n            print(cond)\n            print(\") \")\n            printBlock(thenp)\n            elsep match {\n              case Skip() => ()\n              case _: If =>\n                print(\" else \")\n                printTree(elsep, isStat)\n              case _ =>\n                print(\" else \")\n                printBlock(elsep)\n            }\n          } else {\n            print('(')\n            print(cond)\n            print(\" ? \")\n            print(thenp)\n            print(\" : \")\n            print(elsep)\n            print(')')\n          }\n\n        case While(cond, body, label) =>\n          if (label.isDefined) {\n            print(label.get)\n            print(\": \")\n          }\n          print(\"while (\")\n          print(cond)\n          print(\") \")\n          printBlock(body)\n\n        case DoWhile(body, cond, label) =>\n          if (label.isDefined) {\n            print(label.get)\n            print(\": \")\n          }\n          print(\"do \")\n          printBlock(body)\n          print(\" while (\")\n          print(cond)\n          print(')')\n\n        case ForIn(lhs, obj, body) =>\n          print(\"for (\")\n          print(lhs)\n          print(\" in \")\n          print(obj)\n          print(\") \")\n          printBlock(body)\n\n        case For(init, guard, update, body) =>\n          print(\"for (\")\n          print(init)\n          print(\"; \")\n          print(guard)\n          print(\"; \")\n          print(update)\n          print(\") \")\n          printBlock(body)\n\n        case TryFinally(TryCatch(block, errVar, handler), finalizer) =>\n          print(\"try \")\n          printBlock(block)\n          print(\" catch (\")\n          print(errVar)\n          print(\") \")\n          printBlock(handler)\n          print(\" finally \")\n          printBlock(finalizer)\n\n        case TryCatch(block, errVar, handler) =>\n          print(\"try \")\n          printBlock(block)\n          print(\" catch (\")\n          print(errVar)\n          print(\") \")\n          printBlock(handler)\n\n        case TryFinally(block, finalizer) =>\n          print(\"try \")\n          printBlock(block)\n          print(\" finally \")\n          printBlock(finalizer)\n\n        case Throw(expr) =>\n          print(\"throw \")\n          print(expr)\n\n        case Break(label) =>\n          if (label.isEmpty) print(\"break\")\n          else {\n            print(\"break \")\n            print(label.get)\n          }\n\n        case Continue(label) =>\n          if (label.isEmpty) print(\"continue\")\n          else {\n            print(\"continue \")\n            print(label.get)\n          }\n\n        case Switch(selector, cases, default) =>\n          print(\"switch (\")\n          print(selector)\n          print(\") \")\n          print('{')\n          indent()\n          var rest = cases\n          while (rest.nonEmpty) {\n            val next = rest.head\n            rest = rest.tail\n            println()\n            print(\"case \")\n            print(next._1)\n            print(':')\n            if (!next._2.isInstanceOf[Skip]) {\n              print(' ')\n              printBlock(next._2)\n            }\n          }\n\n          default match {\n            case Skip() =>\n            case _ =>\n              println()\n              print(\"default: \")\n              printBlock(default)\n          }\n\n          undent()\n          println()\n          print('}')\n\n        case Debugger() =>\n          print(\"debugger\")\n\n        // Expressions\n\n        case New(ctor, args) =>\n          def containsOnlySelectsFromAtom(tree: Tree): Boolean = tree match {\n            case DotSelect(qual, _)     => containsOnlySelectsFromAtom(qual)\n            case BracketSelect(qual, _) => containsOnlySelectsFromAtom(qual)\n            case VarRef(_)              => true\n            case This()                 => true\n            case _                      => false // in particular, Apply\n          }\n          if (containsOnlySelectsFromAtom(ctor)) {\n            print(\"new \")\n            print(ctor)\n          } else {\n            print(\"new (\")\n            print(ctor)\n            print(')')\n          }\n          printArgs(args)\n\n        case DotSelect(qualifier, item) =>\n          qualifier match {\n            case _:IntLiteral | _:DoubleLiteral =>\n              print(\"(\")\n              print(qualifier)\n              print(\")\")\n            case _ =>\n              print(qualifier)\n          }\n          print(\".\")\n          print(item)\n\n        case BracketSelect(qualifier, item) =>\n          print(qualifier)\n          print('[')\n          print(item)\n          print(']')\n\n        case Apply(fun, args) =>\n          print(fun)\n          printArgs(args)\n\n        case ImportCall(arg) =>\n          print(\"import(\")\n          print(arg)\n          print(')')\n\n        case Spread(items) =>\n          print(\"...\")\n          print(items)\n\n        case Delete(prop) =>\n          print(\"delete \")\n          print(prop)\n\n        case UnaryOp(op, lhs) =>\n          import UnaryOp._\n          print('(')\n          if (op == `typeof`) {\n            print(\"typeof \")\n          } else {\n            (op: @switch) match {\n              case + => print('+')\n              case - => print('-')\n              case ~ => print('~')\n              case ! => print('!')\n              case `typeof` => print(\"typeof \")\n            }\n          }\n          print(lhs)\n          print(')')\n\n        case IncDec(prefix, inc, arg) =>\n          val op = if (inc) \"++\" else \"--\"\n          print('(')\n          if (prefix)\n            print(op)\n          print(arg)\n          if (!prefix)\n            print(op)\n          print(')')\n\n        case BinaryOp(op, lhs, rhs) =>\n          import BinaryOp._\n          print('(')\n          print(lhs)\n          print(' ')\n          print((op: @switch) match {\n            case === => \"===\"\n            case !== => \"!==\"\n\n            case + => \"+\"\n            case - => \"-\"\n            case * => \"*\"\n            case / => \"/\"\n            case % => \"%\"\n\n            case |   => \"|\"\n            case &   => \"&\"\n            case ^   => \"^\"\n            case <<  => \"<<\"\n            case >>  => \">>\"\n            case >>> => \">>>\"\n\n            case <  => \"<\"\n            case <= => \"<=\"\n            case >  => \">\"\n            case >= => \">=\"\n\n            case && => \"&&\"\n            case || => \"||\"\n\n            case `in`         => \"in\"\n            case `instanceof` => \"instanceof\"\n          })\n          print(' ')\n          print(rhs)\n          print(')')\n\n        case ArrayConstr(items) =>\n          printRow(items, '[', ']')\n\n        case ObjectConstr(Nil) =>\n          if (isStat)\n            print(\"({})\") // force expression position for the object literal\n          else\n            print(\"{}\")\n\n        case ObjectConstr(fields) =>\n          if (isStat)\n            print('(') // force expression position for the object literal\n          print('{')\n          indent()\n          println()\n          var rest = fields\n          while (rest.nonEmpty) {\n            val x = rest.head\n            rest = rest.tail\n            print(x._1)\n            print(\": \")\n            print(x._2)\n            if (rest.nonEmpty) {\n              print(',')\n              println()\n            }\n          }\n          undent()\n          println()\n          print('}')\n          if (isStat)\n            print(')')\n\n        // Literals\n\n        case Undefined() =>\n          print(\"(void 0)\")\n\n        case Null() =>\n          print(\"null\")\n\n        case BooleanLiteral(value) =>\n          print(if (value) \"true\" else \"false\")\n\n        case IntLiteral(value) =>\n          if (value >= 0) {\n            print(value.toString)\n          } else {\n            print('(')\n            print(value.toString)\n            print(')')\n          }\n\n        case DoubleLiteral(value) =>\n          if (value == 0 && 1 / value < 0) {\n            print(\"(-0)\")\n          } else if (value >= 0) {\n            print(value.toString)\n          } else {\n            print('(')\n            print(value.toString)\n            print(')')\n          }\n\n        case StringLiteral(value) =>\n          print('\\\"')\n          printEscapeJS(value)\n          print('\\\"')\n\n        case BigIntLiteral(value) =>\n          if (value >= 0) {\n            print(value.toString)\n            print('n')\n          } else {\n            print('(')\n            print(value.toString)\n            print(\"n)\")\n          }\n\n        // Atomic expressions\n\n        case VarRef(ident) =>\n          print(ident)\n\n        case This() =>\n          print(\"this\")\n\n        case Function(arrow, args, body) =>\n          if (arrow) {\n            print('(')\n            printSig(args)\n            print(\"=> \")\n            body match {\n              case Return(expr: ObjectConstr) =>\n                /* #3926 An ObjectConstr needs to be wrapped in () not to be\n                 * parsed as a block.\n                 */\n                print('(')\n                print(expr)\n                print(')')\n              case Return(expr) =>\n                print(expr)\n              case _ =>\n                printBlock(body)\n            }\n            print(')')\n          } else {\n            print(\"(function\")\n            printSig(args)\n            printBlock(body)\n            print(')')\n          }\n\n        // Named function definition\n\n        case FunctionDef(name, args, body) =>\n          if (!isStat)\n            print('(')\n          print(\"function \")\n          print(name)\n          printSig(args)\n          printBlock(body)\n          if (!isStat)\n            print(')')\n\n        // ECMAScript 6 classes\n\n        case ClassDef(optClassName, optParentClass, members) =>\n          print(\"class\")\n          if (optClassName.isDefined) {\n            print(' ')\n            print(optClassName.get)\n          }\n          if (optParentClass.isDefined) {\n            print(\" extends \")\n            print(optParentClass.get)\n          }\n          print(\" {\"); indent()\n          var rest = members\n          while (rest.nonEmpty) {\n            println()\n            print(rest.head)\n            print(';')\n            rest = rest.tail\n          }\n          undent(); println(); print('}')\n\n        case MethodDef(static, name, params, body) =>\n          if (static)\n            print(\"static \")\n          print(name)\n          printSig(params)\n          printBlock(body)\n\n        case GetterDef(static, name, body) =>\n          if (static)\n            print(\"static \")\n          print(\"get \")\n          print(name)\n          printSig(Nil)\n          printBlock(body)\n\n        case SetterDef(static, name, param, body) =>\n          if (static)\n            print(\"static \")\n          print(\"set \")\n          print(name)\n          print('(')\n          print(param)\n          print(\") \")\n          printBlock(body)\n\n        case Super() =>\n          print(\"super\")\n\n        // ECMAScript 6 modules\n\n        case Import(bindings, from) =>\n          print(\"import { \")\n          var first = true\n          var rest = bindings\n          while (rest.nonEmpty) {\n            val binding = rest.head\n            if (first)\n              first = false\n            else\n              print(\", \")\n            print(binding._1)\n            print(\" as \")\n            print(binding._2)\n            rest = rest.tail\n          }\n          print(\" } from \")\n          print(from: Tree)\n\n        case ImportNamespace(binding, from) =>\n          print(\"import * as \")\n          print(binding)\n          print(\" from \")\n          print(from: Tree)\n\n        case Export(bindings) =>\n          print(\"export { \")\n          var first = true\n          var rest = bindings\n          while (rest.nonEmpty) {\n            val binding = rest.head\n            if (first)\n              first = false\n            else\n              print(\", \")\n            print(binding._1)\n            print(\" as \")\n            print(binding._2)\n            rest = rest.tail\n          }\n          print(\" }\")\n      }\n    }\n\n    protected def printEscapeJS(s: String): Unit =\n      JSPrinters.printEscapeJS(s, out)\n\n    protected def print(ident: Ident): Unit =\n      printEscapeJS(ident.name)\n\n    private final def print(propName: PropertyName): Unit = propName match {\n      case lit: StringLiteral => print(lit: Tree)\n      case ident: Ident       => print(ident)\n\n      case ComputedName(tree) =>\n        print(\"[\")\n        print(tree)\n        print(\"]\")\n    }\n\n    protected def print(exportName: ExportName): Unit =\n      printEscapeJS(exportName.name)\n\n    protected def print(s: String): Unit =\n      out.write(s)\n\n    protected def print(c: Int): Unit =\n      out.write(c)\n  }\n\n  private final val EscapeJSChars = \"\\\\b\\\\t\\\\n\\\\v\\\\f\\\\r\\\\\\\"\\\\\\\\\"\n\n  private def printEscapeJS(str: String, out: java.io.Writer): Unit = {\n    /* Note that Java and JavaScript happen to use the same encoding for\n     * Unicode, namely UTF-16, which means that 1 char from Java always equals\n     * 1 char in JavaScript. */\n    val end = str.length()\n    var i = 0\n    /* Loop prints all consecutive ASCII printable characters starting\n     * from current i and one non ASCII printable character (if it exists).\n     * The new i is set at the end of the appended characters.\n     */\n    while (i != end) {\n      val start = i\n      var c: Int = str.charAt(i).toInt\n      // Find all consecutive ASCII printable characters from `start`\n      while (i != end && c >= 32 && c <= 126 && c != 34 && c != 92) {\n        i += 1\n        if (i != end)\n          c = str.charAt(i).toInt\n      }\n      // Print ASCII printable characters from `start`\n      if (start != i) {\n        out.write(str, start, i - start)\n      }\n\n      // Print next non ASCII printable character\n      if (i != end) {\n        def escapeJSEncoded(c: Int): Unit = {\n          if (7 < c && c < 14) {\n            val i = 2 * (c - 8)\n            out.write(EscapeJSChars, i, 2)\n          } else if (c == 34) {\n            out.write(EscapeJSChars, 12, 2)\n          } else if (c == 92) {\n            out.write(EscapeJSChars, 14, 2)\n          } else {\n            out.write(\"\\\\u%04x\".format(c))\n          }\n        }\n        escapeJSEncoded(c)\n        i += 1\n      }\n    }\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/util/JSTrees.scala",
    "content": "package scalajsbundler.util\n\n// This is copied from `org.scalajs.linker.backend.javascript.Trees` in Scala.js.\nprivate[util] object JSTrees {\n  /* The case classes for JS Trees are sealed instead of final because making\n   * them final triggers bugs with Scala 2.11.x and 2.12.{1-4}, in combination\n   * with their `implicit val pos`.\n   */\n\n  /** AST node of JavaScript. */\n  abstract sealed class Tree {\n    def show: String = {\n      val writer = new java.io.StringWriter\n      val printer = new JSPrinters.JSTreePrinter(writer)\n      printer.printTree(this, isStat = true)\n      writer.toString()\n    }\n  }\n\n  // Comments\n\n  sealed case class DocComment(text: String) extends Tree\n\n  // Identifiers and properties\n\n  sealed trait PropertyName\n\n  sealed case class Ident(name: String) extends PropertyName {\n    require(Ident.isValidJSIdentifierName(name),\n        s\"'$name' is not a valid JS identifier name\")\n  }\n\n  object Ident {\n    /** Tests whether the given string is a valid `IdentifierName` for the\n     *  ECMAScript language specification.\n     *\n     *  This does not exclude keywords, as they can be used as identifiers in\n     *  some productions, notably as property names.\n     */\n    def isValidJSIdentifierName(name: String): Boolean = {\n      // scalastyle:off return\n      // This method is called on every `Ident` creation; it should be fast.\n      val len = name.length()\n      if (len == 0)\n        return false\n      val c = name.charAt(0)\n      if (c != '$' && c != '_' && !Character.isUnicodeIdentifierStart(c))\n        return false\n      var i = 1\n      while (i != len) {\n        val c = name.charAt(i)\n        if (c != '$' && !Character.isUnicodeIdentifierPart(c))\n          return false\n        i += 1\n      }\n      true\n      // scalastyle:on return\n    }\n  }\n\n  sealed case class ComputedName(tree: Tree) extends PropertyName\n\n  // Definitions\n\n  sealed trait LocalDef extends Tree {\n    def name: Ident\n    def mutable: Boolean\n\n    def ref: Tree = VarRef(name)\n  }\n\n  sealed case class VarDef(name: Ident, rhs: Option[Tree]) extends LocalDef {\n    def mutable: Boolean = true\n  }\n\n  /** ES6 let or const (depending on the mutable flag). */\n  sealed case class Let(name: Ident, mutable: Boolean, rhs: Option[Tree]) extends LocalDef\n\n  sealed case class ParamDef(name: Ident, rest: Boolean) extends LocalDef {\n    def mutable: Boolean = true\n  }\n\n  // Control flow constructs\n\n  sealed case class Skip() extends Tree\n\n  sealed class Block private (val stats: List[Tree]) extends Tree {\n    override def toString(): String =\n      stats.mkString(\"Block(\", \",\", \")\")\n  }\n\n  object Block {\n    def apply(stats: List[Tree]): Tree = {\n      val flattenedStats = stats flatMap {\n        case Skip() => Nil\n        case Block(subStats) => subStats\n        case other => other :: Nil\n      }\n      flattenedStats match {\n        case Nil => Skip()\n        case only :: Nil => only\n        case _ => new Block(flattenedStats)\n      }\n    }\n\n    def apply(stats: Tree*): Tree =\n      apply(stats.toList)\n\n    def unapply(block: Block): Some[List[Tree]] = Some(block.stats)\n  }\n\n  sealed case class Labeled(label: Ident, body: Tree) extends Tree\n\n  sealed case class Assign(lhs: Tree, rhs: Tree) extends Tree {\n    require(lhs match {\n      case _:VarRef | _:DotSelect | _:BracketSelect => true\n      case _ => false\n    }, s\"Invalid lhs for Assign: $lhs\")\n  }\n\n  sealed case class Return(expr: Tree) extends Tree\n\n  sealed case class If(cond: Tree, thenp: Tree, elsep: Tree) extends Tree\n\n  sealed case class While(cond: Tree, body: Tree, label: Option[Ident] = None) extends Tree\n\n  sealed case class DoWhile(body: Tree, cond: Tree, label: Option[Ident] = None) extends Tree\n\n  sealed case class ForIn(lhs: Tree, obj: Tree, body: Tree) extends Tree\n\n  sealed case class For(init: Tree, guard: Tree, update: Tree, body: Tree) extends Tree\n\n  sealed case class TryCatch(block: Tree, errVar: Ident, handler: Tree) extends Tree\n\n  sealed case class TryFinally(block: Tree, finalizer: Tree) extends Tree\n\n  sealed case class Throw(expr: Tree) extends Tree\n\n  sealed case class Break(label: Option[Ident] = None) extends Tree\n\n  sealed case class Continue(label: Option[Ident] = None) extends Tree\n\n  sealed case class Switch(selector: Tree, cases: List[(Tree, Tree)], default: Tree) extends Tree\n\n  sealed case class Debugger() extends Tree\n\n  // Expressions\n\n  sealed case class New(ctor: Tree, args: List[Tree]) extends Tree\n\n  sealed case class DotSelect(qualifier: Tree, item: Ident) extends Tree\n\n  sealed case class BracketSelect(qualifier: Tree, item: Tree) extends Tree\n\n  /** Syntactic apply.\n   *  It is a method call if fun is a dot-select or bracket-select. It is a\n   *  function call otherwise.\n   */\n  sealed case class Apply(fun: Tree, args: List[Tree]) extends Tree\n\n  /** Dynamic `import(arg)`. */\n  sealed case class ImportCall(arg: Tree) extends Tree\n\n  /** `...items`, the \"spread\" operator of ECMAScript 6.\n   *\n   *  It is only valid in ECMAScript 6, in the `args`/`items` of a [[New]],\n   *  [[Apply]], or [[ArrayConstr]].\n   *\n   *  @param items An iterable whose items will be spread\n   */\n  sealed case class Spread(items: Tree) extends Tree\n\n  sealed case class Delete(prop: Tree) extends Tree {\n    require(prop match {\n      case _:DotSelect | _:BracketSelect => true\n      case _ => false\n    }, s\"Invalid prop for Delete: $prop\")\n  }\n\n  /** Unary operation (always preserves pureness).\n   *\n   *  Operations which do not preserve pureness are not allowed in this tree.\n   *  These are notably ++ and --\n   */\n  sealed case class UnaryOp(op: UnaryOp.Code, lhs: Tree) extends Tree\n\n  object UnaryOp {\n    /** Codes are raw Ints to be able to switch-match on them. */\n    type Code = Int\n\n    final val + = 1\n    final val - = 2\n    final val ~ = 3\n    final val ! = 4\n\n    final val typeof = 5\n  }\n\n  /** `++x`, `x++`, `--x` or `x--`. */\n  sealed case class IncDec(prefix: Boolean, inc: Boolean, arg: Tree) extends Tree\n\n  /** Binary operation (always preserves pureness).\n   *\n   *  Operations which do not preserve pureness are not allowed in this tree.\n   *  These are notably +=, -=, *=, /= and %=\n   */\n  sealed case class BinaryOp(op: BinaryOp.Code, lhs: Tree, rhs: Tree) extends Tree\n\n  object BinaryOp {\n    /** Codes are raw Ints to be able to switch-match on them. */\n    type Code = Int\n\n    final val === = 1\n    final val !== = 2\n\n    final val + = 3\n    final val - = 4\n    final val * = 5\n    final val / = 6\n    final val % = 7\n\n    final val | = 8\n    final val & = 9\n    final val ^ = 10\n    final val << = 11\n    final val >> = 12\n    final val >>> = 13\n\n    final val < = 14\n    final val <= = 15\n    final val > = 16\n    final val >= = 17\n\n    final val && = 18\n    final val || = 19\n\n    final val in = 20\n    final val instanceof = 21\n  }\n\n  sealed case class ArrayConstr(items: List[Tree]) extends Tree\n\n  sealed case class ObjectConstr(fields: List[(PropertyName, Tree)]) extends Tree\n\n  // Literals\n\n  /** Marker for literals. Literals are always pure. */\n  sealed trait Literal extends Tree\n\n  sealed case class Undefined() extends Literal\n\n  sealed case class Null() extends Literal\n\n  sealed case class BooleanLiteral(value: Boolean) extends Literal\n\n  sealed case class IntLiteral(value: Int) extends Literal\n\n  sealed case class DoubleLiteral(value: Double) extends Literal\n\n  sealed case class StringLiteral(value: String) extends Literal with PropertyName\n\n  sealed case class BigIntLiteral(value: BigInt) extends Literal\n\n  // Atomic expressions\n\n  sealed case class VarRef(ident: Ident) extends Tree\n\n  sealed case class This() extends Tree\n\n  sealed case class Function(arrow: Boolean, args: List[ParamDef], body: Tree) extends Tree\n\n  // Named function definition\n\n  sealed case class FunctionDef(name: Ident, args: List[ParamDef], body: Tree) extends Tree\n\n  // ECMAScript 6 classes\n\n  sealed case class ClassDef(className: Option[Ident], parentClass: Option[Tree], members: List[Tree]) extends Tree\n\n  sealed case class MethodDef(static: Boolean, name: PropertyName, args: List[ParamDef], body: Tree) extends Tree\n\n  sealed case class GetterDef(static: Boolean, name: PropertyName, body: Tree) extends Tree\n\n  sealed case class SetterDef(static: Boolean, name: PropertyName, param: ParamDef, body: Tree) extends Tree\n\n  sealed case class Super() extends Tree\n\n  // ECMAScript 6 modules\n\n  /** The name of an ES module export.\n   *\n   *  It must be a valid `IdentifierName`, as tested by\n   *  [[ExportName.isValidExportName]].\n   */\n  sealed case class ExportName(name: String) {\n    require(ExportName.isValidExportName(name), s\"'$name' is not a valid export name\")\n  }\n\n  object ExportName {\n    /** Tests whether a string is a valid export name.\n     *\n     *  A string is a valid export name if and only if it is a valid ECMAScript\n     *  `IdentifierName`, which is defined in\n     *  [[http://www.ecma-international.org/ecma-262/6.0/#sec-names-and-keywords\n     *  Section 11.6 of the ECMAScript 2015 specification]].\n     *\n     *  Currently, this implementation is buggy in some corner cases, as it does\n     *  not accept code points with the Unicode properties `Other_ID_Start` and\n     *  `Other_ID_Continue`. For example,\n     *  `isValidIdentifierName(0x2118.toChar.toString)` will return `false`\n     *  instead of `true`.\n     *\n     *  In theory, it does not really account for code points with the Unicode\n     *  properties `Pattern_Syntax` and `Pattern_White_Space`, which should be\n     *  rejected. However, with the current version of Unicode (9.0.0), there\n     *  seems to be no such character that would be accepted by this method.\n     */\n    final def isValidExportName(name: String): Boolean = {\n      // scalastyle:off return\n      import java.lang.Character._\n\n      def isJSIdentifierStart(cp: Int): Boolean =\n        isUnicodeIdentifierStart(cp) || cp == '$' || cp == '_'\n\n      def isJSIdentifierPart(cp: Int): Boolean = {\n        val ZWNJ = 0x200c\n        val ZWJ = 0x200d\n        isUnicodeIdentifierPart(cp) || cp == '$' || cp == '_' || cp == ZWNJ || cp == ZWJ\n      }\n\n      if (name.isEmpty)\n        return false\n\n      val firstCP = name.codePointAt(0)\n      if (!isJSIdentifierStart(firstCP))\n        return false\n\n      var i = charCount(firstCP)\n      while (i < name.length) {\n        val cp = name.codePointAt(i)\n        if (!isJSIdentifierPart(cp))\n          return false\n        i += charCount(cp)\n      }\n\n      true\n      // scalastyle:on return\n    }\n  }\n\n  /** `import` statement, except namespace import.\n   *\n   *  This corresponds to the following syntax:\n   *  {{{\n   *  import { <binding1_1> as <binding1_2>, ..., <bindingN_1> as <bindingN_2> } from <from>\n   *  }}}\n   *  The `_1` parts of bindings are therefore the identifier names that are\n   *  imported, as specified in `export` clauses of the module. The `_2` parts\n   *  are the names under which they are imported in the current module.\n   *\n   *  Special cases:\n   *  - When `_1.name == _2.name`, there is shorter syntax in ES, i.e.,\n   *    `import { binding } from 'from'`.\n   *  - When `_1.name == \"default\"`, it is equivalent to a default import.\n   */\n  sealed case class Import(bindings: List[(ExportName, Ident)], from: StringLiteral) extends Tree\n\n  /** Namespace `import` statement.\n   *\n   *  This corresponds to the following syntax:\n   *  {{{\n   *  import * as <binding> from <from>\n   *  }}}\n   */\n  sealed case class ImportNamespace(binding: Ident, from: StringLiteral) extends Tree\n\n  /** `export` statement.\n   *\n   *  This corresponds to the following syntax:\n   *  {{{\n   *  export { <binding1_1> as <binding1_2>, ..., <bindingN_1> as <bindingN_2> }\n   *  }}}\n   *  The `_1` parts of bindings are therefore the identifiers from the current\n   *  module that are exported. The `_2` parts are the names under which they\n   *  are exported to other modules.\n   */\n  sealed case class Export(bindings: List[(Ident, ExportName)]) extends Tree\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/main/scala/scalajsbundler/util/ScalaJSNativeLibraries.scala",
    "content": "package scalajsbundler.util\n\nimport com.google.common.jimfs.Jimfs\n\nimport java.io.{BufferedInputStream, ByteArrayOutputStream, FileInputStream, OutputStream}\nimport java.nio.file.{Files, Path}\n\nimport sbt.{Attributed, Def, File, FileFilter, globFilter}\n\nimport scala.annotation.tailrec\n\nprivate[scalajsbundler] object ScalaJSNativeLibraries {\n\n  // Copied from https://github.com/scala-js/jsdependencies\n  def apply(fullClasspath: Seq[Attributed[File]]): Seq[(String, Path)] = {\n    collectFromClasspath(fullClasspath,\n      \"*.js\", collectJar = jsFilesInJar,\n      collectFile = (f, relPath) => relPath -> f.toPath())\n  }\n\n  /** Collect certain file types from a classpath.\n    *\n    *  @param cp Classpath to collect from\n    *  @param filter Filter for (real) files of interest (not in jars)\n    *  @param collectJar Collect elements from a jar (called for all jars)\n    *  @param collectFile Collect a single file. Params are the file and the\n    *      relative path of the file (to its classpath entry root).\n    *  @return Collected elements attributed with physical files they originated\n    *      from (key: scalaJSSourceFiles).\n    */\n  private def collectFromClasspath[T](cp: Def.Classpath, filter: FileFilter,\n    collectJar: File => Seq[T],\n    collectFile: (File, String) => T): Seq[T] = {\n\n    val results = Seq.newBuilder[T]\n\n    for (cpEntry <- Attributed.data(cp) if cpEntry.exists) {\n      if (cpEntry.isFile && cpEntry.getName.endsWith(\".jar\")) {\n        results ++= collectJar(cpEntry)\n      } else if (cpEntry.isDirectory) {\n        for {\n          (file, relPath0) <- sbt.Path.selectSubpaths(cpEntry, filter)\n        } {\n          val relPath = relPath0.replace(java.io.File.separatorChar, '/')\n          results += collectFile(file, relPath)\n        }\n      } else {\n        throw new IllegalArgumentException(\n          \"Illegal classpath entry: \" + cpEntry.getPath)\n      }\n    }\n\n    results.result()\n  }\n\n  private def jsFilesInJar(jar: File): List[(String, Path)] =\n    jarListEntries(jar, _.endsWith(\".js\"))\n\n  private def jarListEntries[T](jar: File,\n    p: String => Boolean): List[(String, Path)] = {\n\n    import java.util.zip._\n\n    val jarPath = jar.getPath\n\n    val memFileSystem = Jimfs.newFileSystem()\n\n    val stream =\n      new ZipInputStream(new BufferedInputStream(new FileInputStream(jar)))\n    try {\n      val buf = new Array[Byte](4096)\n\n      @tailrec\n      def readAll(out: OutputStream): Unit = {\n        val read = stream.read(buf)\n        if (read != -1) {\n          out.write(buf, 0, read)\n          readAll(out)\n        }\n      }\n\n      def makeVF(e: ZipEntry): (String, Path) = {\n        val size = e.getSize\n        val out =\n          if (0 <= size && size <= Int.MaxValue) new ByteArrayOutputStream(size.toInt)\n          else new ByteArrayOutputStream()\n\n        try {\n          readAll(out)\n          val relName = e.getName\n          val path = memFileSystem.getPath(s\"$jarPath/$relName\")\n          Files.createDirectories(path.getParent())\n          Files.write(path, out.toByteArray())\n          relName -> path\n        } finally {\n          out.close()\n        }\n      }\n\n      Iterator.continually(stream.getNextEntry())\n        .takeWhile(_ != null)\n        .filter(e => p(e.getName))\n        .map(makeVF)\n        .toList\n    } finally {\n      stream.close()\n    }\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/additonalNpmConfig/build.sbt",
    "content": "import scalajsbundler.util.JSON._\n\nval checkPackageJson = taskKey[Unit](\"Check that the package.json file does not contain duplicate entries for the 'react' dependency\")\n\nlazy val npmConfig =\n  Project(\"npmConfig\", file(\"npmConfig\"))\n    .enablePlugins(ScalaJSBundlerPlugin)\n    .settings(\n      scalaVersion := \"2.13.1\",\n      npmDependencies in Compile += \"react\" -> \"16.13.1\",\n      npmExtraArgs in Compile := Seq(\"-silent\"),\n      additionalNpmConfig in Compile := Map(\n        \"name\" -> str(\"foo\"),\n        \"version\" -> str(\"1.0.0\"),\n        \"zoo\" -> obj(\n          \"bees\" -> bool(true),\n          \"cows\" -> bool(false),\n          \"sharks\" -> bool(true)\n        )\n      )\n    ).settings(\n      checkPackageJson := {\n        val json = IO.read((npmUpdate in Compile).value / \"package.json\")\n        val jsonLines = json.split(\"\\n\")\n\n        findPackageJsonLine(jsonLines, \"react\" -> \"16.13.1\")\n\n        findPackageJsonLine(jsonLines, \"name\" -> \"foo\")\n        findPackageJsonLine(jsonLines, \"version\" -> \"1.0.0\")\n        findPackageJsonLine(jsonLines, \"bees\" -> \"true\")\n        findPackageJsonLine(jsonLines, \"cows\" -> \"false\")\n        findPackageJsonLine(jsonLines, \"sharks\" -> \"true\")\n      }\n    )\n\ndef findPackageJsonLine(lines: Array[String], keyValue: (String, String)) = {\n\n  val (key, value) = keyValue\n\n  assert(\n    lines.count(l => l.containsSlice(key) && l.containsSlice(value)) == 1,\n    s\"'package.json' missing expected key/value: ($key, $value)\"\n  )\n}\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/additonalNpmConfig/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/additonalNpmConfig/test",
    "content": "> npmConfig/npmUpdate\n> npmConfig/checkPackageJson\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/browserless/README.md",
    "content": "scalajs-bundler/browserless\n==========================\n\nAn application that uses npm packages and\nthat does not target Web browsers.\n\nDemonstrates how to:\n- depend on npm packages ; \n- run the bundled code with Node.js ;\n- run tests with Node.js.\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/browserless/build.sbt",
    "content": "name := \"browserless\"\n\nenablePlugins(ScalaJSBundlerPlugin, ScalaJSJUnitPlugin)\n\nscalaVersion := \"2.13.2\"\n\nscalaJSUseMainModuleInitializer := true\n\n// Adds a dependency on the uuid npm package\nnpmDependencies in Compile += \"uuid\" -> \"3.1.0\"\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/browserless/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/browserless/src/main/scala/example/Foo.scala",
    "content": "package example\n\nimport uuid.uuid\n\nobject Foo {\n\n  def bar(): String = uuid.v4()\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/browserless/src/main/scala/example/Main.scala",
    "content": "package example\n\nobject Main {\n\n  def main(args: Array[String]): Unit = {\n    println(Foo.bar())\n  }\n\n}"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/browserless/src/main/scala/uuid/uuid.scala",
    "content": "package uuid\n\nimport scala.annotation.meta.field\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation.JSImport.Namespace\nimport scala.scalajs.js.annotation.{JSExport, JSImport}\nimport scala.scalajs.js.|\n\n@JSImport(\"uuid\", Namespace)\n@js.native\nobject uuid extends js.Object {\n\n  def v1(options: js.UndefOr[UUIDOptions] = js.undefined): String = js.native\n\n  def v1(\n    options: UUIDOptions,\n    buffer: js.Array[Double],\n    offset: js.UndefOr[Double]\n  ): js.Array[Double] = js.native\n\n  def v4(options: js.UndefOr[UUIDOptions] = js.undefined): String = js.native\n\n  def v4(\n    options: UUIDOptions,\n    buffer: js.Array[Double],\n    offset: js.UndefOr[Double]\n  ): js.Array[Double] = js.native\n\n  def parse(\n    id: String,\n    buffer: js.UndefOr[js.Array[Double]] = js.undefined,\n    offset: js.UndefOr[Double] = js.undefined\n  ): js.Array[Double] = js.native\n\n  def unparse(\n    buffer: js.Array[Double],\n    offset: js.UndefOr[Double] = js.undefined\n  ): String = js.native\n\n}\n\ncase class UUIDOptions(\n  @(JSExport @field) node: js.UndefOr[js.Array[js.Any]] = js.undefined,\n  @(JSExport @field) clockseq: js.UndefOr[Double] = js.undefined,\n  @(JSExport @field) msecs: js.UndefOr[Double | js.Date] = js.undefined,\n  @(JSExport @field) nsecs: js.UndefOr[Double] = js.undefined\n)\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/browserless/src/test/scala/example/FooTest.scala",
    "content": "package example\n\nimport org.junit.Assert._\nimport org.junit.Test\n\nclass FooTest {\n\n  @Test def bar(): Unit = {\n    assertNotNull(Foo.bar())\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/browserless/test",
    "content": "> run\n> test\n\n# Deactivated because `clean` followed by `run` kills the AppVeyor build.\n# Testing yarn support is done enough in other tests.\n#> set useYarn := true\n#> clean\n#> run\n#> test\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/custom-test-config/README.md",
    "content": "# scalajs-bundler/custom-test-config\n\nAn application that uses webpack 4 and requires a custom test configuration\n\nDemonstrates how to:\n\n* use webpack 4.\n* use utest to run tests.\n* example of using react and react test.\n* differentiate the webpack configuration for tests.\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/custom-test-config/build.sbt",
    "content": "name := \"custom-test\"\n\nval reactJS = \"16.13.1\"\nval scalaJsReact = \"1.7.0\"\n\nenablePlugins(ScalaJSBundlerPlugin)\n\nscalaVersion := \"2.13.2\"\n\nscalaJSUseMainModuleInitializer := true\n\nlibraryDependencies ++= Seq(\n  \"com.github.japgolly.scalajs-react\" %%% \"core\"  % scalaJsReact,\n  \"com.github.japgolly.scalajs-react\" %%% \"test\"  % scalaJsReact % Test,\n  \"com.lihaoyi\"                       %%% \"utest\" % \"0.7.4\" % Test\n)\n\n// Use a different Webpack configuration file for test\nwebpackConfigFile in Test := Some(baseDirectory.value / \"test.webpack.config.js\")\n\ntestFrameworks += new TestFramework(\"utest.runner.Framework\")\n\n// Execute the tests in browser-like environment\nrequireJsDomEnv in Test := true\n\nwebpackBundlingMode := BundlingMode.LibraryAndApplication()\n\nuseYarn := true\n\nnpmDependencies in Compile ++= Seq(\n  \"react\"     -> reactJS,\n  \"react-dom\" -> reactJS\n)\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/custom-test-config/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/custom-test-config/src/main/scala/example/Component.scala",
    "content": "package example\n\nimport japgolly.scalajs.react._\nimport japgolly.scalajs.react.vdom.html_<^._\n\nobject Component {\n\n  private val component =\n    ScalaComponent\n      .builder[Unit]\n      .render_P ( _ =>\n        <.div(\n          ^.cls := \"app\"\n        )\n      ).build\n\n  def apply() = component()\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/custom-test-config/src/test/scala/example/SomeTest.scala",
    "content": "package example\n\nimport utest._\nimport japgolly.scalajs.react.test._\n\nimport scala.scalajs.js\n\nobject RenderTest extends TestSuite {\n  val tests = Tests {\n    'render - {\n      val component = Component()\n      ReactTestUtils.withRenderedIntoDocument(component) { m =>\n        assert(m.outerHtmlScrubbed() == \"\"\"<div class=\"app\"></div>\"\"\")\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/custom-test-config/test",
    "content": "> clean\n> test\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/custom-test-config/test.webpack.config.js",
    "content": "const Webpack = require(\"webpack\");\n\nconst Test = {\n  plugins: [\n    new Webpack.DefinePlugin({\n      \"process.env\": {\n        NODE_ENV: JSON.stringify(\"test\")\n      }\n    })\n  ]\n};\n\nmodule.exports = Test;\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade/build.sbt",
    "content": "val `facade-project` =\n  project.in(file(\".\"))\n    .aggregate(usage)\n\nlazy val usage =\n  project.in(file(\"usage\"))\n    .enablePlugins(ScalaJSBundlerPlugin, ScalaJSJUnitPlugin)\n    .settings(commonSettings: _*)\n    .settings(\n      scalaJSUseMainModuleInitializer := true\n    )\n    .dependsOn(facade)\n\nlazy val facade =\n  project.in(file(\"facade\"))\n    .enablePlugins(ScalaJSBundlerPlugin)\n    .settings(commonSettings: _*)\n    .settings(\n      npmDependencies in Compile += \"uuid\" -> \"3.1.0\"\n    )\n\nlazy val commonSettings = Seq(\n  scalaVersion := \"2.13.2\"\n)\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade/facade/src/main/scala/uuid/uuid.scala",
    "content": "package uuid\n\nimport scala.annotation.meta.field\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation.JSImport.Namespace\nimport scala.scalajs.js.annotation.{JSExport, JSImport}\nimport scala.scalajs.js.|\n\n@JSImport(\"uuid\", Namespace)\n@js.native\nobject uuid extends js.Object {\n\n  def v1(options: js.UndefOr[UUIDOptions] = js.undefined): String = js.native\n\n  def v1(\n    options: UUIDOptions,\n    buffer: js.Array[Double],\n    offset: js.UndefOr[Double]\n  ): js.Array[Double] = js.native\n\n  def v4(options: js.UndefOr[UUIDOptions] = js.undefined): String = js.native\n\n  def v4(\n    options: UUIDOptions,\n    buffer: js.Array[Double],\n    offset: js.UndefOr[Double]\n  ): js.Array[Double] = js.native\n\n  def parse(\n    id: String,\n    buffer: js.UndefOr[js.Array[Double]] = js.undefined,\n    offset: js.UndefOr[Double] = js.undefined\n  ): js.Array[Double] = js.native\n\n  def unparse(\n    buffer: js.Array[Double],\n    offset: js.UndefOr[Double] = js.undefined\n  ): String = js.native\n\n}\n\ncase class UUIDOptions(\n  @(JSExport @field) node: js.UndefOr[js.Array[js.Any]] = js.undefined,\n  @(JSExport @field) clockseq: js.UndefOr[Double] = js.undefined,\n  @(JSExport @field) msecs: js.UndefOr[Double | js.Date] = js.undefined,\n  @(JSExport @field) nsecs: js.UndefOr[Double] = js.undefined\n)\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade/test",
    "content": "> usage/run\n> usage/clean\n> usage/test\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade/usage/src/main/scala/example/Foo.scala",
    "content": "package example\n\nimport uuid.uuid\n\nobject Foo {\n\n  def bar(): String = uuid.v4()\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade/usage/src/main/scala/example/Main.scala",
    "content": "package example\n\nobject Main {\n\n  def main(args: Array[String]): Unit = {\n    println(Foo.bar())\n  }\n\n}"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade/usage/src/test/scala/example/FooTest.scala",
    "content": "package example\n\nimport org.junit.Assert._\nimport org.junit.Test\n\nclass FooTest {\n\n  @Test def bar(): Unit = {\n    assertNotNull(Foo.bar())\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade-examples/build.sbt",
    "content": "name := \"facade-examples\"\n\nenablePlugins(ScalaJSBundlerPlugin, ScalaJSJUnitPlugin)\n\nscalaVersion := \"2.11.12\"\n\nscalaJSUseMainModuleInitializer := true\n\nnpmDependencies in Compile += \"uuid\" -> \"3.1.0\"\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade-examples/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade-examples/src/main/resources/class.js",
    "content": "module.exports = function (name, age) {\n  this.name = name;\n  this.age = age;\n};"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade-examples/src/main/resources/foo.js",
    "content": "exports.bar = function (i) { return i + 1 };"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade-examples/src/main/resources/function.js",
    "content": "module.exports = (first, second) => `Konrad says ${first} plus ${second} is ${first + second}`;"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade-examples/src/main/scala/example/Main.scala",
    "content": "package example\n\nobject Main {\n\n  def main(args: Array[String]): Unit = {\n    println(Obj.bar(42))\n    println(Member(42))\n    val user = new User(\"Julien\", 30)\n    println(user.name)\n    println(Func(8, 12))\n  }\n\n}"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade-examples/src/main/scala/example/facades.scala",
    "content": "package example\n\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation.JSImport\n\n// Note: the corresponding JS modules are defined in the src/main/resources/ directory\n\n// --- Import a whole module as an object\n\n@JSImport(\"./foo.js\", JSImport.Namespace)\n@js.native\nobject Obj extends js.Object {\n  def bar(i: Int): Int = js.native\n}\n\n// --- Import a whole module as a function\n\n@JSImport(\"./function.js\", JSImport.Default)\n@js.native\nobject Func extends js.Function2[Int, Int, String] {\n  def apply(first: Int, second: Int): String = js.native\n}\n\n// --- Import just a module member, which is a function\n\n@JSImport(\"./foo.js\", \"bar\")\n@js.native\nobject Member extends js.Function1[Int, Int] {\n  def apply(i: Int): Int = js.native\n}\n\n// --- Import a class\n\n@JSImport(\"./class.js\", JSImport.Namespace)\n@js.native\nclass User(val name: String, val age: Int) extends js.Object"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade-examples/src/test/scala/example/FacadesTest.scala",
    "content": "package example\n\nimport org.junit.Assert._\nimport org.junit.Test\n\nclass FacadesTest {\n\n  @Test def testObj(): Unit = {\n    assertEquals(42, Obj.bar(41))\n  }\n\n  @Test def testFunc(): Unit = {\n    assertEquals(\"Konrad says 2 plus 5 is 7\", Func(2, 5))\n  }\n\n  @Test def testMember(): Unit = {\n    assertEquals(42, Member(41))\n  }\n\n  @Test def testUser(): Unit = {\n    val user = new User(\"Julien\", 30)\n    assertEquals(\"Julien\", user.name)\n    assertEquals(30, user.age)\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/facade-examples/test",
    "content": "> run\n> clean\n> test"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/generated-sources/build.sbt",
    "content": "enablePlugins(ScalaJSBundlerPlugin)\n\nscalaVersion := \"2.12.8\"\n\nsourceGenerators in Compile += Def.task {\n  val _ = (npmInstallDependencies in Compile).value\n  Seq.empty[File]\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/generated-sources/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/generated-sources/test",
    "content": "# Tests that it is possible to use npm dev dependencies to generate sources\n# without creating a cycle in the tasks.\n> sources\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/global-namespace-with-jsdom-unit-testing/build.sbt",
    "content": "\nname := \"global-namespace-with-jsdom-unit-testing\"\n\nenablePlugins(ScalaJSBundlerPlugin, ScalaJSJUnitPlugin)\n\nscalaVersion := \"2.12.11\"\n\nscalaJSUseMainModuleInitializer := true\n\n//#relevant-settings\nnpmDependencies in Compile ++= Seq(\n  \"moment\" -> \"2.29.1\"\n)\n\nnpmDevDependencies in Compile ++= Seq(\n  \"webpack-merge\" -> \"5.7.3\",\n  \"imports-loader\" -> \"2.0.0\",\n  \"expose-loader\" -> \"2.0.0\"\n)\n\nwebpackConfigFile in fastOptJS := Some(baseDirectory.value / \"dev.webpack.config.js\")\n\nwebpackConfigFile in Test := Some(baseDirectory.value / \"test.webpack.config.js\")\n\n// Execute the tests in browser-like environment\nrequireJsDomEnv in Test := true\n//#relevant-settings\n\nversion in installJsdom := \"12.0.0\"\n\nuseYarn := true\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/global-namespace-with-jsdom-unit-testing/common.webpack.config.js",
    "content": "var globalModules = {\n  moment: \"moment\"\n};\n\nconst importRule = {\n  // Force require global modules\n  test: /.*-(fast|full)opt\\.js$/,\n  loader:\n    \"imports-loader\",\n  options: {\n    type: 'commonjs',\n    imports: Object.keys(globalModules)\n      .map(function(modName) {\n        return {\n          moduleName: globalModules[modName],\n          name: modName,\n        }\n      })\n  }\n};\n\nconst exposeRules = Object.keys(globalModules).map(function(modName) {\n  // Expose global modules\n  return {\n    test: require.resolve(modName),\n    loader: \"expose-loader\",\n    options: {\n      exposes: [globalModules[modName]],\n    },\n  };\n});\n\nconst allRules = exposeRules.concat(importRule);\n\nmodule.exports = {\n  performance: { hints: false },\n  module: {\n    rules: allRules\n  }\n};\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/global-namespace-with-jsdom-unit-testing/dev.webpack.config.js",
    "content": "var { merge } = require('webpack-merge');\n\nvar commonConfig = require('./common.webpack.config');\nvar generatedConfig = require('./scalajs.webpack.config');\n\nmodule.exports = merge(generatedConfig, commonConfig);\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/global-namespace-with-jsdom-unit-testing/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/global-namespace-with-jsdom-unit-testing/src/main/scala/example/Main.scala",
    "content": "package example\n\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation._\n\n// Emulate a Scala.js facade library that assumes everything to be in the global scope\nobject moment {\n  @js.native\n  @JSGlobal(\"moment\")\n  object Moment extends js.Object {\n    def apply(): Date = js.native\n  }\n\n  @js.native\n  trait Date extends js.Object {\n    @JSName(\"valueOf\")\n    def value(): Double = js.native\n  }\n}\n\nimport moment._\n\nobject Main {\n  def main(args: Array[String]): Unit = {\n\n  }\n\n  val getNowInMillis: Double = Moment().value()\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/global-namespace-with-jsdom-unit-testing/src/test/scala/example/MainTest.scala",
    "content": "package example\n\nimport org.junit.Assert._\nimport org.junit.Test\n\nimport scala.scalajs.js\nimport scala.scalajs.js.Date\n\nclass MainTest {\n\n  @Test def getMillis(): Unit = {\n    val millisBefore = Date.now().toLong\n    val millis = Main.getNowInMillis\n    val millisAfter = Date.now().toLong\n    assertTrue(millis >= millisBefore)\n    assertTrue(millis <= millisAfter)\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/global-namespace-with-jsdom-unit-testing/test",
    "content": "> fastOptJS::webpack\n> test\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/global-namespace-with-jsdom-unit-testing/test.webpack.config.js",
    "content": "var { merge } = require('webpack-merge');\n\nvar commonConfig = require('./common.webpack.config');\n\nmodule.exports = merge(commonConfig, {});\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-resources/build.sbt",
    "content": "name := \"js-resources\"\n\nenablePlugins(ScalaJSBundlerPlugin, ScalaJSJUnitPlugin)\n\nscalaVersion := \"2.11.12\"\n\nscalaJSUseMainModuleInitializer := true\n\nnpmDependencies in Compile += \"uuid\" -> \"3.1.0\"\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-resources/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-resources/src/main/resources/my-module.js",
    "content": "var uuid = require('uuid');\n\nmodule.exports = {\n  someUuid: uuid.v4()\n};\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-resources/src/main/scala/example/Main.scala",
    "content": "package example\n\nobject Main {\n\n  def main(args: Array[String]): Unit = {\n    println(MyModule.someUuid)\n  }\n\n}"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-resources/src/main/scala/example/MyModule.scala",
    "content": "package example\n\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation.JSImport\n\n@JSImport(\"./my-module\", JSImport.Namespace)\n@js.native\nobject MyModule extends js.Object {\n  val someUuid: String = js.native\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-resources/src/test/scala/example/MyModuleTest.scala",
    "content": "package example\n\nimport org.junit.Assert._\nimport org.junit.Test\n\nclass MyModuleTest {\n\n  @Test def someUuid(): Unit = {\n    assertNotNull(MyModule.someUuid)\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-resources/test",
    "content": "> run\n> clean\n> test\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-source-directory/build.sbt",
    "content": "name := \"js-resources\"\n\nenablePlugins(ScalaJSBundlerPlugin, ScalaJSJUnitPlugin)\n\nscalaVersion := \"2.11.12\"\n\nscalaJSUseMainModuleInitializer := true\n\nnpmDependencies in Compile += \"uuid\" -> \"3.1.0\"\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-source-directory/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-source-directory/src/main/js/config.json",
    "content": "{\n  \"value\": 1\n}"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-source-directory/src/main/js/my-module.js",
    "content": "var uuid = require('uuid');\nvar config = require('./config.json');\nvar nestedConfig = require('./nested/config2.json');\n\nconsole.log(JSON.stringify(config));\nconsole.log(JSON.stringify(nestedConfig));\n\nmodule.exports = {\n  someUuid: uuid.v4(),\n  someConfig: config,\n  someNestedConfig: nestedConfig\n};\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-source-directory/src/main/js/nested/config2.json",
    "content": "{\n  \"value\": 2\n}"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-source-directory/src/main/scala/example/Main.scala",
    "content": "package example\n\nobject Main {\n\n  def main(args: Array[String]): Unit = {\n    println(MyModule.someUuid)\n  }\n\n}"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-source-directory/src/main/scala/example/MyModule.scala",
    "content": "package example\n\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation.JSImport\n\n@JSImport(\"./my-module\", JSImport.Namespace)\n@js.native\nobject MyModule extends js.Object {\n  val someUuid: String = js.native\n  val someConfig: js.Object = js.native\n  val someNestedConfig: js.Object = js.native\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-source-directory/src/test/scala/example/MyModuleTest.scala",
    "content": "package example\n\nimport org.junit.Assert._\nimport org.junit.Test\n\nclass MyModuleTest {\n\n  @Test def someUuid(): Unit = {\n    assertNotNull(MyModule.someUuid)\n  }\n\n  @Test def someConfig(): Unit = {\n    assertNotNull(MyModule.someConfig)\n  }\n\n  @Test def someNestedConfig(): Unit = {\n    assertNotNull(MyModule.someNestedConfig)\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/js-source-directory/test",
    "content": "> run\n> clean\n> test\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/library/build.sbt",
    "content": "name := \"library\"\n\nenablePlugins(ScalaJSBundlerPlugin)\n\nscalaVersion := \"2.11.12\"\n\nnpmDependencies in Compile += \"uuid\" -> \"3.1.0\"\n\n//#relevant-settings\nwebpackBundlingMode := BundlingMode.LibraryAndApplication()\n//#relevant-settings\n\n// HtmlUnit does not support ECMAScript 2015\nscalaJSLinkerConfig ~= { _.withESFeatures(_.withUseECMAScript2015(false)) }\n\n// Check that a HTML can be loaded (and that its JavaScript can be executed) without errors\nInputKey[Unit](\"html\") := {\n  import complete.DefaultParsers._\n  val page = (Space ~> StringBasic).parsed\n  import com.gargoylesoftware.htmlunit.WebClient\n  val client = new WebClient()\n  try {\n    client.getPage(s\"file://${baseDirectory.value.absolutePath}/$page\")\n  } finally {\n    client.close()\n  }\n}\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/library/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Example</title>\n  </head>\n  <body>\n    <script src=\"target/scala-2.11/scalajs-bundler/main/library-opt-bundle.js\"></script>\n    <script>\n      //#library-usage\n      console.log(sjs_example_Library.foo());\n      console.log(sjs_example_Library.bar());\n      //#library-usage\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/library/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nlibraryDependencies += \"net.sourceforge.htmlunit\" % \"htmlunit\" % \"2.46.0\"\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/library/src/main/scala/example/Library.scala",
    "content": "//#library-definition\npackage example\n\nimport scala.scalajs.js.annotation.{JSExportTopLevel, JSExportAll}\n\n@JSExportTopLevel(name=\"sjs_example_Library\") @JSExportAll\nobject Library {\n  def foo(): String = SomeOtherCode.quux(true)\n  def bar(): String = SomeOtherCode.quux(false)\n}\n//#library-definition\n\nobject SomeOtherCode {\n  import uuid.UUID\n\n  def quux(b: Boolean): String = if (b) UUID.v4() else UUID.v1()\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/library/src/main/scala/uuid/uuid.scala",
    "content": "package uuid\n\nimport scala.annotation.meta.field\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation.JSImport.Namespace\nimport scala.scalajs.js.annotation.{JSExport, JSImport}\nimport scala.scalajs.js.|\n\n@JSImport(\"uuid\", Namespace)\n@js.native\nobject UUID extends js.Object {\n\n  def v1(options: js.UndefOr[UUIDOptions] = js.undefined): String = js.native\n\n  def v1(\n    options: UUIDOptions,\n    buffer: js.Array[Double],\n    offset: js.UndefOr[Double]\n  ): js.Array[Double] = js.native\n\n  def v4(options: js.UndefOr[UUIDOptions] = js.undefined): String = js.native\n\n  def v4(\n    options: UUIDOptions,\n    buffer: js.Array[Double],\n    offset: js.UndefOr[Double]\n  ): js.Array[Double] = js.native\n\n  def parse(\n    id: String,\n    buffer: js.UndefOr[js.Array[Double]] = js.undefined,\n    offset: js.UndefOr[Double] = js.undefined\n  ): js.Array[Double] = js.native\n\n  def unparse(\n    buffer: js.Array[Double],\n    offset: js.UndefOr[Double] = js.undefined\n  ): String = js.native\n\n}\n\ncase class UUIDOptions(\n  @(JSExport @field) node: js.UndefOr[js.Array[js.Any]] = js.undefined,\n  @(JSExport @field) clockseq: js.UndefOr[Double] = js.undefined,\n  @(JSExport @field) msecs: js.UndefOr[Double | js.Date] = js.undefined,\n  @(JSExport @field) nsecs: js.UndefOr[Double] = js.undefined\n)\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/library/test",
    "content": "> fullOptJS::webpack\n> html index.html\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/newer-linker/build.sbt",
    "content": "name := \"newer-linker\"\n\nenablePlugins(ScalaJSBundlerPlugin, ScalaJSJUnitPlugin)\n\nscalaVersion := \"2.13.1\"\n\nscalaJSUseMainModuleInitializer := true\n\n// Adds a dependency on the uuid npm package\nnpmDependencies in Compile += \"uuid\" -> \"3.1.0\"\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/newer-linker/project/newer-scala-js.sbt",
    "content": "// TODO Set this to a version > 1.3.0 when there is one\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % \"1.3.0\")\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/newer-linker/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/newer-linker/src/test/scala/example/NewerLinkerTest.scala",
    "content": "package example\n\nimport org.junit.Assert._\nimport org.junit.Test\n\nclass NewerLinkerTest {\n\n  @Test def newerLinker(): Unit = {\n    /* TODO Set this to a version > 1.3.0 when there is one, and adapt the\n     * test below to something that would have been fixed in the meantime.\n     */\n    assertEquals(\"1.3.0\", System.getProperty(\"java.vm.version\"))\n\n    /* Test the fix to https://github.com/scala-js/scala-js/issues/3984, which\n     * was shipped in Scala.js 1.0.1.\n     */\n    def minusZero: Any = -0.0f\n    assertSame(classOf[java.lang.Float], minusZero.getClass())\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/newer-linker/test",
    "content": "> test\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sbt-1.8/build.sbt",
    "content": "name := \"newer-linker\"\n\nenablePlugins(ScalaJSBundlerPlugin, ScalaJSJUnitPlugin)\n\nscalaVersion := \"2.13.1\"\n\nscalaJSUseMainModuleInitializer := true\n\n// Adds a dependency on the uuid npm package\nnpmDependencies in Compile += \"uuid\" -> \"3.1.0\"\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sbt-1.8/project/build.properties",
    "content": "sbt.version=1.8.2\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sbt-1.8/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sbt-1.8/src/test/scala/example/BasicTest.scala",
    "content": "package example\n\nimport org.junit.Assert._\nimport org.junit.Test\n\nclass BasicTest {\n\n  @Test def newerLinker(): Unit = {\n    assertEquals(\"1\", 1.0.toString())\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sbt-1.8/test",
    "content": "> test\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sharedconfig/README.md",
    "content": "scalajs-bundler/sharedconfig\n=====================\n\nAn application that uses npm packages and that produces\na static HTML page containing a leaflet map\n\nDemonstrates how to:\n- depend on npm packages ;\n- using custom webpack loader configuration ;\n- use a shared webpack configuration ;\n- differentiate prod/dev builds.\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sharedconfig/build.sbt",
    "content": "\nname := \"sharedconfig\"\n\nenablePlugins(ScalaJSBundlerPlugin, ScalaJSJUnitPlugin)\n\nscalaVersion := \"2.11.12\"\n\nscalaJSUseMainModuleInitializer := true\n\nlibraryDependencies += \"org.scala-js\" %%% \"scalajs-dom\" % \"1.0.0\"\n\nnpmDependencies in Compile += \"leaflet\" -> \"0.7.7\"\n\nnpmDevDependencies in Compile ++= Seq(\n  \"webpack-merge\" -> \"4.1.2\",\n  \"file-loader\" -> \"6.2.0\",\n  \"image-webpack-loader\" -> \"7.0.1\",\n  \"css-loader\" -> \"5.0.1\",\n  \"style-loader\" -> \"2.0.0\",\n  \"url-loader\" -> \"4.1.0\"\n)\n\nwebpackConfigFile in fastOptJS := Some(baseDirectory.value / \"dev.webpack.config.js\")\n\n// Use a different Webpack configuration file for production\nwebpackConfigFile in fullOptJS := Some(baseDirectory.value / \"prod.webpack.config.js\")\n\n// Use the shared Webpack configuration file for reload workflow and for running the tests\nwebpackConfigFile in Test := Some(baseDirectory.value / \"common.webpack.config.js\")\n\n// Execute the tests in browser-like environment\nrequireJsDomEnv in Test := true\n\nwebpackBundlingMode in fastOptJS := BundlingMode.LibraryAndApplication()\n\nuseYarn := true\n\n// HtmlUnit does not support ECMAScript 2015\nscalaJSLinkerConfig ~= { _.withESFeatures(_.withUseECMAScript2015(false)) }\n\n// Check that a HTML can be loaded (and that its JavaScript can be executed) without errors\nInputKey[Unit](\"html\") := {\n  import complete.DefaultParsers._\n  val page = (Space ~> StringBasic).parsed\n  import com.gargoylesoftware.htmlunit.WebClient\n  val client = new WebClient()\n  try {\n    client.getPage(s\"file://${baseDirectory.value.absolutePath}/$page\")\n  } finally {\n    client.close()\n  }\n}\n\nTaskKey[Unit](\"checkSize\") := {\n  val files = (webpack in (Compile, fullOptJS)).value\n  val bundleFile = files\n    .find(_.metadata.get(BundlerFileTypeAttr).exists(_ == BundlerFileType.ApplicationBundle))\n    .get.data\n  val artifactSize = IO.readBytes(bundleFile).length\n  // Account for minor variance in size due to transitive dependency updates\n  assert(artifactSize > 150000 && artifactSize < 170000)\n}\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sharedconfig/common.webpack.config.js",
    "content": "module.exports = {\n  module: {\n    rules: [\n      {\n        test: /\\.(jpe?g|png|gif|svg)$/i,\n        use: [\n          {\n            loader: \"file-loader\",\n            options: {\n              hash: \"sha512\",\n              digest: \"hex\",\n              name: \"[hash].[ext]\"\n            }\n          },\n          {\n            loader: \"image-webpack-loader\",\n            options: {\n              bypassOnDebug: true,\n              query: {\n                mozjpeg: {\n                  progressive: true\n                },\n                gifsicle: {\n                  interlaced: true\n                },\n                optipng: {\n                  optimizationLevel: 7\n                }\n              }\n            }\n          }\n        ]\n      },\n      {\n        test: /\\.css$/,\n        use: [\"style-loader\", \"css-loader\"]\n      },\n      {\n        test: /\\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,\n        loader: \"url-loader\",\n        options: {\n          limit: 10000\n        }\n      }\n    ]\n  }\n};\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sharedconfig/dev.webpack.config.js",
    "content": "var merge = require(\"webpack-merge\");\n\nvar generatedConfig = require('./scalajs.webpack.config');\nvar commonConfig = require(\"./common.webpack.config.js\");\n\nmodule.exports = merge(generatedConfig, commonConfig);"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sharedconfig/index-prod.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Example</title>\n    <style>\n      #container {\n        width: 12cm;\n        height: 8cm;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"target/scala-2.11/scalajs-bundler/main/sharedconfig-opt-bundle.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sharedconfig/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Example</title>\n    <style>\n      #container {\n        width: 12cm;\n        height: 8cm;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"target/scala-2.11/scalajs-bundler/main/sharedconfig-fastopt-bundle.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sharedconfig/prod.webpack.config.js",
    "content": "var merge = require(\"webpack-merge\");\n\nvar generatedConfig = require(\"./scalajs.webpack.config\");\nvar commonConfig = require(\"./common.webpack.config.js\");\n\nmodule.exports = merge(generatedConfig, commonConfig);"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sharedconfig/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nlibraryDependencies += \"net.sourceforge.htmlunit\" % \"htmlunit\" % \"2.46.0\"\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sharedconfig/src/main/scala/example/Main.scala",
    "content": "package example\n\nimport scala.scalajs.js\nimport leaflet.modules._\n\nobject Main {\n  def main(args: Array[String]): Unit = {\n    LeafletAssets\n\n    val map = Leaflet.map(\"container\").setView(js.Array(51.505f, -0.09f), 13)\n    val tileLayer = Leaflet.tileLayer(\"http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png\")\n    map.addLayer(tileLayer)\n  }\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sharedconfig/src/main/scala/leaflet/modules/modules.scala",
    "content": "package leaflet\npackage modules\n\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation.JSImport\nimport scala.scalajs.js.annotation.JSImport.Namespace\n\n@js.native\ntrait Map extends js.Object {\n  def setView(center: js.Array[Float], zoom: Int): Map = js.native\n\n  def getZoom(): Int = js.native\n\n  def addLayer(layer: Layer): js.Dynamic = js.native\n}\n\n@js.native\ntrait Layer extends js.Object {\n  def addTo(map: Map): js.Dynamic = js.native\n}\n\n@JSImport(\"leaflet\", JSImport.Namespace)\n@js.native\nobject Leaflet extends js.Object {\n\n  def map(elem: String): Map = js.native\n\n  def tileLayer(url: String): Layer = js.native\n}\n\n@JSImport(\"!style-loader!css-loader!leaflet/dist/leaflet.css\", JSImport.Default )\n@js.native\nobject LeafletAssets extends js.Object {}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sharedconfig/src/test/scala/example/SomeTest.scala",
    "content": "package example\n\nimport org.junit.Assert._\nimport org.junit.Test\n\nimport org.scalajs.dom.document\n\nimport scala.scalajs.js\nimport leaflet.modules._\n\nclass SomeTest {\n\n  @Test def leafletZoom(): Unit = {\n    val container = document.body.innerHTML = \"\"\"<div id=\"container\" />\"\"\"\n\n    val map = Leaflet.map(\"container\").setView(js.Array(51.505f, -0.09f), 13)\n    val zoomlevel = map.getZoom()\n    assertEquals(13, zoomlevel)\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/sharedconfig/test",
    "content": "$ absent target/scala-2.11/scalajs-bundler/main/sharedconfig-fastopt-bundle.js target/scala-2.11/scalajs-bundler/main/sharedconfig-fastopt-bundle.js.map\n> fastOptJS::webpack\n$ exists target/scala-2.11/scalajs-bundler/main/sharedconfig-fastopt-bundle.js target/scala-2.11/scalajs-bundler/main/sharedconfig-fastopt-bundle.js.map\n> html index.html\n\n$ absent target/scala-2.11/scalajs-bundler/main/sharedconfig-opt-bundle.js target/scala-2.11/scalajs-bundler/main/sharedconfig-opt-bundle.js.map\n> fullOptJS::webpack\n$ exists target/scala-2.11/scalajs-bundler/main/sharedconfig-opt-bundle.js\n> html index-prod.html\n> checkSize\n\n> test"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/static/README.md",
    "content": "scalajs-bundler/static\n=====================\n\nAn application that uses npm packages and that produces\na static HTML page.\n\nDemonstrates how to:\n- depend on npm packages.\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/static/build.sbt",
    "content": "name := \"static\"\n\nenablePlugins(ScalaJSBundlerPlugin, ScalaJSJUnitPlugin)\n\nscalaVersion := \"2.11.12\"\n\nscalaJSUseMainModuleInitializer := true\n\nlibraryDependencies += \"org.scala-js\" %%% \"scalajs-dom\" % \"1.0.0\"\n\nnpmDependencies in Compile += \"snabbdom\" -> \"0.5.3\"\n\n// Execute the tests in browser-like environment\nrequireJsDomEnv in Test := true\n\nversion in installJsdom := \"16.4.0\"\n\nwebpackBundlingMode := BundlingMode.LibraryAndApplication()\n\nuseYarn := true\n\n// HtmlUnit does not support ECMAScript 2015\nscalaJSLinkerConfig ~= { _.withESFeatures(_.withUseECMAScript2015(false)) }\n\n// Check that a HTML can be loaded (and that its JavaScript can be executed) without errors\nInputKey[Unit](\"html\") := {\n  import complete.DefaultParsers._\n  val page = (Space ~> StringBasic).parsed\n  import com.gargoylesoftware.htmlunit.WebClient\n  val client = new WebClient()\n  try {\n    client.getPage(s\"file://${baseDirectory.value.absolutePath}/$page\")\n  } finally {\n    client.close()\n  }\n}\n\nTaskKey[Unit](\"checkSize\") := {\n  //#filter-files\n  val files = (webpack in (Compile, fullOptJS)).value\n  val bundleFile = files\n    .find(_.metadata.get(BundlerFileTypeAttr).exists(_ == BundlerFileType.ApplicationBundle))\n    .get.data\n  //#filter-files\n  val artifactSize = IO.readBytes(bundleFile).length\n\n  val sizeLow = 17000\n  val sizeHigh = 22000\n\n  // Account for minor variance in size due to transitive dependency updates\n  assert(\n    artifactSize >= sizeLow && artifactSize <= sizeHigh,\n    s\"expected: [$sizeLow, $sizeHigh], got: $artifactSize\"\n  )\n}\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/static/index-prod.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Example</title>\n  </head>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"target/scala-2.11/scalajs-bundler/main/static-opt-bundle.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/static/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Example</title>\n  </head>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"target/scala-2.11/scalajs-bundler/main/static-fastopt-bundle.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/static/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nlibraryDependencies += \"net.sourceforge.htmlunit\" % \"htmlunit\" % \"2.46.0\"\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/static/src/main/scala/example/Main.scala",
    "content": "package example\n\nimport scala.scalajs.js\nimport scala.scalajs.js.Dynamic.literal\n\nimport snabbdom.{snabbdom, h, modules}\n\nimport org.scalajs.dom.document\n\nobject Main {\n  def main(args: Array[String]): Unit = {\n\n    val someFn = () => println(\"someFn\")\n    val anotherEventHandler = () => println(\"another event handler\")\n\n    // Based on https://github.com/paldepind/snabbdom#inline-example\n    val patch =\n      snabbdom.init(js.Array( // Init patch function with choosen modules\n        modules.`class`, // makes it easy to toggle classes\n        modules.props, // for setting properties on DOM elements\n        modules.style, // handles styling on elements with support for animations\n        modules.eventlisteners // attaches event listeners\n      ))\n\n    val vnode = h(\"div#container.two.classes\", literal(on = literal(click = someFn)), js.Array(\n      h(\"span\", literal(style = literal(fontWeight = \"bold\")), \"This is bold\": js.Any),\n      \" and this is just normal text\",\n      h(\"a\", literal(props = literal(href = \"/foo\")), \"I'll take you places!\": js.Any)\n    ))\n    val container = document.getElementById(\"container\")\n    // Patch into empty DOM element – this modifies the DOM as a side effect\n    patch(container, vnode)\n    val newVnode = h(\"div#container.two.classes\", literal(on = literal(click = anotherEventHandler)), js.Array(\n      h(\"span\", literal(style = literal(fontWeight = \"normal\", fontStyle = \"italic\")), \"This is now italic type\": js.Any),\n      \" and this is still just normal text\",\n      h(\"a\", literal(props = literal(href = \"/bar\")), \"I'll take you places!\": js.Any)\n    ))\n    // Second `patch` invocation\n    patch(vnode, newVnode) // Snabbdom efficiently updates the old view to the new state\n  }\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/static/src/main/scala/snabbdom/modules/modules.scala",
    "content": "package snabbdom\npackage modules\n\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation.JSImport\nimport scala.scalajs.js.annotation.JSImport.Namespace\n\n@JSImport(\"snabbdom/modules/class\", Namespace)\n@js.native\nobject `class` extends js.Object\n\n@JSImport(\"snabbdom/modules/props\", Namespace)\n@js.native\nobject props extends js.Object\n\n@JSImport(\"snabbdom/modules/style\", Namespace)\n@js.native\nobject style extends js.Object\n\n@JSImport(\"snabbdom/modules/eventlisteners\", Namespace)\n@js.native\nobject eventlisteners extends js.Object"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/static/src/main/scala/snabbdom/snabbdom.scala",
    "content": "package snabbdom\n\nimport org.scalajs.dom.{Element, Text}\n\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation.JSImport\nimport scala.scalajs.js.annotation.JSImport.Namespace\nimport scala.scalajs.js.|\n\n@JSImport(\"snabbdom\", Namespace)\n@js.native\nobject snabbdom extends js.Object {\n  def init(modules: js.Array[js.Object]): js.Function2[VNode | Element, VNode, VNode] = js.native\n}\n\n@JSImport(\"snabbdom/h\", Namespace)\n@js.native\nobject h extends js.Function3[String, js.UndefOr[js.Any], js.UndefOr[js.Any], VNode] {\n  def apply(selector: String, b: js.UndefOr[js.Any] = js.undefined, c: js.UndefOr[js.Any] = js.undefined): VNode = js.native\n}\n\n@js.native\ntrait VNode extends js.Object {\n  var selector: js.UndefOr[String] = js.native\n  var data: js.UndefOr[VNodeData]= js.native\n  var children: js.UndefOr[js.Array[VNode | String]]= js.native\n  var text: js.UndefOr[String]= js.native\n  var elm: js.UndefOr[Element | Text]= js.native\n  var key: js.UndefOr[String | Double]= js.native\n}\n\n@js.native\ntrait VNodeData extends js.Object\n\n\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/static/src/test/scala/example/SomeTest.scala",
    "content": "package example\n\nimport org.junit.Assert._\nimport org.junit.Test\n\nimport org.scalajs.dom.document\n\nimport scala.scalajs.js\n\nclass SomeTest {\n\n  @Test def testSnabbdom(): Unit = {\n    import snabbdom.{snabbdom, h, modules}\n    val patch =\n      snabbdom.init(js.Array(\n        modules.props\n      ))\n\n    val vnode = h(\"h1\", \"It works\": js.Any)\n\n    val container = document.createElement(\"div\")\n    document.body.appendChild(container)\n\n    patch(container, vnode)\n\n    val patchedNode = document.body.lastChild\n    assertEquals(\"H1\", patchedNode.nodeName)\n    assertEquals(\"It works\", patchedNode.textContent)\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/static/test",
    "content": "$ absent target/scala-2.11/scalajs-bundler/main/static-fastopt-bundle.js target/scala-2.11/scalajs-bundler/main/static-fastopt-bundle.js.map\n> fastOptJS::webpack\n$ exists target/scala-2.11/scalajs-bundler/main/static-fastopt-bundle.js target/scala-2.11/scalajs-bundler/main/static-fastopt-bundle.js.map\n> html index.html\n\n$ absent target/scala-2.11/scalajs-bundler/main/static-opt-bundle.js target/scala-2.11/scalajs-bundler/main/static-opt-bundle.js.map\n> fullOptJS::webpack\n$ exists target/scala-2.11/scalajs-bundler/main/static-opt-bundle.js target/scala-2.11/scalajs-bundler/main/static-opt-bundle.js.map\n> html index-prod.html\n> checkSize\n\n# Disabling source maps in Scala.js also disables it for scalajs-bundler\n\n$ delete target/scala-2.11/scalajs-bundler/main/static-fastopt-bundle.js.map target/scala-2.11/scalajs-bundler/main/static-opt-bundle.js.map\n> set scalaJSLinkerConfig := scalaJSLinkerConfig.value.withSourceMap(false)\n> fastOptJS::webpack\n$ absent target/scala-2.11/scalajs-bundler/main/static-fastopt-bundle.js.map\n> fullOptJS::webpack\n$ absent target/scala-2.11/scalajs-bundler/main/static-opt-bundle.js.map\n\n# webpackEmitSourceMaps controls source maps emission for the webpack task\n\n> set scalaJSLinkerConfig := scalaJSLinkerConfig.value.withSourceMap(true)\n> set webpackEmitSourceMaps in (Compile, fastOptJS) := false\n> fastOptJS::webpack\n$ exists target/scala-2.11/scalajs-bundler/main/static-fastopt.js.map\n$ absent target/scala-2.11/scalajs-bundler/main/static-fastopt-bundle.js.map\n\n> set webpackEmitSourceMaps in (Compile, fullOptJS) := false\n> fullOptJS::webpack\n$ exists target/scala-2.11/scalajs-bundler/main/static-opt.js.map\n$ absent target/scala-2.11/scalajs-bundler/main/static-opt-bundle.js.map\n\n> test\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/transitive/build.sbt",
    "content": "val sub1 =\n  proj(\"sub1\")\n    .settings(\n      npmDependencies in Compile += \"react\" -> \"15.4.1\"\n    )\n\nval sub2 =\n  proj(\"sub2\")\n    .settings(\n      npmDependencies in Compile += \"react\" -> \"15.4.1\"\n    )\n\nval sub3 =\n  proj(\"sub3\")\n    .settings(\n      npmDependencies in Compile += \"react\" -> \"15.3.2\"\n    )\n\nval sub4 =\n  proj(\"sub4\")\n    .settings(\n      npmDependencies in Compile += \"react\" -> \">=15.3.2\"\n    )\n\nval checkPackageJson = taskKey[Unit](\"Check that the package.json file does not contain duplicate entries for the 'react' dependency\")\n\nval noConflicts =\n  proj(\"no-conflicts\")\n    .settings(\n      checkPackageJson := {\n        val json = IO.read((npmUpdate in Compile).value / \"package.json\")\n        assert(json.split(\"\\n\").count(_.containsSlice(\"react\")) == 1, json)\n      }\n    ).dependsOn(sub1, sub2)\n\nval conflict =\n  proj(\"conflict\")\n    .dependsOn(sub1, sub3)\n\nval resolution =\n  proj(\"resolution\")\n    .dependsOn(sub1, sub3)\n    .settings(\n      npmResolutions in Compile := Map(\"react\" -> \"15.4.1\")\n    )\n\nval delegatedToPackageManager =\n  proj(\"delegatedToPackageManager\")\n    .dependsOn(sub1, sub4)\n\ndef proj(id: String): Project =\n  Project(id, file(id))\n    .enablePlugins(ScalaJSBundlerPlugin)\n    .settings(scalaVersion := \"2.11.12\")\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/transitive/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/transitive/test",
    "content": "> no-conflicts/npmUpdate\n> no-conflicts/checkPackageJson\n-> conflict/npmUpdate\n> resolution/npmUpdate\n> delegatedToPackageManager/npmUpdate\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets/README.md",
    "content": "# scalajs-bundler/webpack-assets\n\nAn application that uses an advanced webpack configuration\n\nDemonstrates how to:\n\n* set a custom name for the output file\n* demonstrates bug #192 and its fix\n* Use a different mode and configuration file for dev and production\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets/badconfig1.js",
    "content": "const ScalaJS = require(\"./scalajs.webpack.config\");\nconst { merge } = require(\"webpack-merge\");\nconst HtmlWebpackPlugin = require(\"html-webpack-plugin\");\n// LessLoader is requested but it is missing from npmDevDependencies\nconst LessLoaderPlugin = require(\"less-loader\");\n\nconst WebApp = merge(ScalaJS, {\n  output: {\n    filename: \"library.js\"\n  },\n  plugins: [new HtmlWebpackPlugin()]\n});\n\nmodule.exports = WebApp;\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets/badconfig2.js",
    "content": "const ScalaJS = require(\"./scalajs.webpack.config\");\nconst { merge } = require(\"webpack-merge\");\nconst HtmlWebpackPlugin = require(\"html-webpack-plugin\");\nconst path = require(\"path\");\nconst rootDir = path.resolve(__dirname, \"../../../..\");\nconst resourcesDir = path.resolve(rootDir, \"src/main/resources\");\n\nconst WebApp = merge(ScalaJS, {\n  entry: {\n    app: [path.resolve(resourcesDir, \"./entry.js\")]\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.css$/,\n        use: [\"style-loader\"] // We should include css-loader\n      }\n    ]\n  },\n  plugins: [new HtmlWebpackPlugin()]\n});\n\nmodule.exports = WebApp;\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets/build.sbt",
    "content": "import com.gargoylesoftware.htmlunit.WebClient\nimport com.gargoylesoftware.htmlunit.WebConsole.Logger\n\nname := \"webpack-assets\"\n\nenablePlugins(ScalaJSBundlerPlugin)\n\nscalaVersion := \"2.13.2\"\n\nscalaJSUseMainModuleInitializer := true\n\n// Use library mode for fastOptJS\nwebpackBundlingMode in fastOptJS := BundlingMode.LibraryOnly()\n\nwebpackConfigFile in fastOptJS := Some(baseDirectory.value / \"dev.config.js\")\n\n// Use application model mode for fullOptJS\nwebpackBundlingMode in fullOptJS := BundlingMode.Application\n\nwebpackConfigFile in fullOptJS := Some(baseDirectory.value / \"prod.config.js\")\n\nnpmDevDependencies in Compile += \"html-webpack-plugin\" -> \"5.2.0\"\n\nnpmDevDependencies in Compile += \"webpack-merge\" -> \"5.7.3\"\n\nnpmDevDependencies in Compile += \"style-loader\" -> \"2.0.0\"\n\nnpmDevDependencies in Compile += \"css-loader\" -> \"5.0.1\"\n\nnpmDevDependencies in Compile += \"mini-css-extract-plugin\" -> \"1.3.4\"\n\nwebpackDevServerPort := 7357\n\nuseYarn := true\n\n// HtmlUnit does not support ECMAScript 2015\nscalaJSLinkerConfig ~= { _.withESFeatures(_.withUseECMAScript2015(false)) }\n\n// Check that a HTML can be loaded (and that its JavaScript can be executed) without errors\nInputKey[Unit](\"html\") := {\n  import complete.DefaultParsers._\n  import scala.sys.process._\n\n  val (page, assetsCount) = (token(Space ~> StringBasic) ~ token(Space ~> IntBasic)).parsed\n  import com.gargoylesoftware.htmlunit.WebClient\n  val files = (webpack in (Compile, fastOptJS)).value\n  assert(files.length == assetsCount)\n  // Check all files are present\n  assert(files.map(_.data.exists).forall(_ == true))\n  // There is only one app file\n  assert(files.count(_.metadata.get(BundlerFileTypeAttr) == Some(BundlerFileType.Application)) == 1)\n  // There is only one library file\n  assert(files.count(_.metadata.get(BundlerFileTypeAttr) == Some(BundlerFileType.Library)) == 1)\n  // There is only one library file\n  assert(files.count(_.metadata.get(BundlerFileTypeAttr) == Some(BundlerFileType.Loader)) == 1)\n  // And 1 asset (HTML file)\n  assert(files.count(_.metadata.get(BundlerFileTypeAttr) == Some(BundlerFileType.Asset)) == 1)\n  // The application is the first\n  assert(files.head.metadata.get(BundlerFileTypeAttr) == Some(BundlerFileType.Application))\n  val client = new WebClient()\n  try {\n    val scalajsBundleDir = s\"${(npmUpdate in Compile).value.absolutePath}\"\n    client.getPage(s\"file://$scalajsBundleDir/$page\")\n  } finally {\n    client.close()\n  }\n}\n\n// Check that a HTML can be loaded on the output path specified\nInputKey[Unit](\"htmlProd\") := {\n  import complete.DefaultParsers._\n  import scala.sys.process._\n\n  val ((page, path), assetsCount) = (token(Space ~> StringBasic) ~ token(Space ~> StringBasic) ~ token(Space ~> IntBasic)).parsed\n  val files = (webpack in (Compile, fullOptJS)).value\n  assert(files.length == assetsCount)\n  // Check all files are present\n  assert(files.map(_.data.exists).forall(_ == true))\n  // There is only one library file\n  assert(files.count(_.metadata.get(BundlerFileTypeAttr) == Some(BundlerFileType.ApplicationBundle)) == 1)\n  // The rest are assets\n  assert(files.count(_.metadata.get(BundlerFileTypeAttr) == Some(BundlerFileType.Asset)) == assetsCount - 1)\n  // The bundle is the first\n  assert(files.head.metadata.get(BundlerFileTypeAttr) == Some(BundlerFileType.ApplicationBundle))\n  import com.gargoylesoftware.htmlunit.WebClient\n  val client = new WebClient()\n  try {\n    val demoDir = s\"${new File((baseDirectory in Compile).value, path).absolutePath}\"\n    client.getPage(s\"file://$demoDir/$page\")\n  } finally {\n    client.close()\n  }\n}\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets/dev.config.js",
    "content": "const ScalaJS = require(\"./scalajs.webpack.config\");\nconst { merge } = require(\"webpack-merge\");\nconst HtmlWebpackPlugin = require(\"html-webpack-plugin\");\n\nconst WebApp = merge(ScalaJS, {\n  output: {\n    filename: \"library.js\"\n  },\n  plugins: [new HtmlWebpackPlugin()]\n});\n\nmodule.exports = WebApp;\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets/prod.config.js",
    "content": "const ScalaJS = require(\"./scalajs.webpack.config\");\nconst { merge } = require(\"webpack-merge\");\nconst HtmlWebpackPlugin = require(\"html-webpack-plugin\");\nconst MiniCssExtractPlugin = require(\"mini-css-extract-plugin\");\n\nconst path = require(\"path\");\nconst rootDir = path.resolve(__dirname, \"../../../..\");\nconst resourcesDir = path.resolve(rootDir, \"src/main/resources\");\n\nconst WebApp = merge(ScalaJS, {\n  entry: {\n    app: [path.resolve(resourcesDir, \"./entry.js\")]\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.css$/,\n        use: [MiniCssExtractPlugin.loader, \"css-loader\"]\n      }\n    ]\n  },\n  output: {\n    filename: \"[name].[chunkhash].js\",\n    path: path.resolve(rootDir, \"demo\")\n  },\n  plugins: [new HtmlWebpackPlugin(), new MiniCssExtractPlugin({})]\n});\n\nmodule.exports = WebApp;\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nlibraryDependencies += \"net.sourceforge.htmlunit\" % \"htmlunit\" % \"2.46.0\"\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets/src/main/resources/entry.js",
    "content": "import \"./styles.css\";\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets/src/main/resources/styles.css",
    "content": "body {\n  color: red;\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets/src/main/scala/example/Main.scala",
    "content": "package example\n\nobject Main {\n  def main(args: Array[String]): Unit = {\n    println(\"6051a036-bfb4-4158-a171-950416b5bd9a\")\n  }\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets/test",
    "content": "# the server should properly start\n> fastOptJS::webpack\n# 1 assets and 3 for library, loader and app\n> html index.html 4\n> clean\n\n# Now let's try optimized\n> fullOptJS::webpack\n> htmlProd index.html demo 4\n\n# Error case 1\n> set webpackConfigFile in fastOptJS := Some(new File(\"badconfig1.js\"))\n> clean\n-> fastOptJS::webpack\n\n# Error case 2\n> set webpackConfigFile in fastOptJS := Some(new File(\"badconfig2.js\"))\n> clean\n-> fastOptJS::webpack\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets-cookbook/README.md",
    "content": "scalajs-bundler/webpack-assets-cookbook\n=====================\n\nAn application to demonstrate how to package up the relevant ScalaJS artifacts in a zip-file.\n\nDemonstrates how to:\n- use the files produced by 'fastOptJs/webpack' or 'fullOptJs/webpack' ;\n- create an archive containing those files ;\n- enrich the archive with other files if required.\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets-cookbook/build.sbt",
    "content": "import java.util.zip.ZipFile\n\nimport com.typesafe.sbt.packager.SettingsHelper._\n\nname := \"webpack-assets\"\n\nscalaVersion := \"2.13.2\"\n\nscalaJSUseMainModuleInitializer := true\n\nresolvers += Resolver.sonatypeRepo(\"snapshots\")\n\nnpmDependencies.in(Compile) := Seq(\n  \"react\" -> \"16.13.1\",\n  \"react-dom\" -> \"16.13.1\"\n)\n\nwebpackBundlingMode := scalajsbundler.BundlingMode.LibraryAndApplication()\n\nlibraryDependencies ++= Seq(\n  \"com.github.ahnfelt\" %%% \"react4s\" % \"0.10.0-SNAPSHOT\"\n)\n\n//#scalajs-files\n// Use ScalaJs and the sbt native packager\nenablePlugins(ScalaJSBundlerPlugin, UniversalPlugin, UniversalDeployPlugin)\n\n// All files shall go directly into the archive rather than having a top level directory matching\n// the module name\ntopLevelDirectory := None\n\n// Map all assets produced by the ScalaJs Bundler to their location within the archive\nmappings.in(Universal) ++= webpack.in(Compile, fullOptJS).value.map { f =>\n  f.data -> s\"assets/${f.data.getName()}\"\n}\n//#scalajs-files\n\n//#additional-files\n// Add any other required files to the archive\nmappings.in(Universal) ++= Seq(\n  target.value / (\"scala-\" + scalaBinaryVersion.value) / \"scalajs-bundler\" / \"main\" / \"node_modules\" / \"react\" / \"umd\" / \"react.production.min.js\" -> \"assets/react.production.min.js\",\n  target.value / (\"scala-\" + scalaBinaryVersion.value) / \"scalajs-bundler\" / \"main\" / \"node_modules\" / \"react-dom\" / \"umd\" / \"react-dom.production.min.js\" -> \"assets/react-dom.production.min.js\"\n)\n//#additional-files\n\nmakeDeploymentSettings(Universal, packageBin.in(Universal), \"zip\")\n\nTaskKey[Unit](\"checkArchive\") := {\n\n  val expected : List[String] = List(\n    \"index.html\",\n    \"assets/webpack-assets-opt-bundle.js\",\n    \"assets/webpack-assets-opt-loader.js\",\n    \"assets/webpack-assets-opt-library.js\",\n    \"assets/webpack-assets-opt.js\",\n    \"assets/react.production.min.js\",\n    \"assets/react-dom.production.min.js\"\n  )\n\n  val archive = packageBin.in(Universal).value\n  assert(archive.exists() && archive.isFile())\n\n  val entries = new ZipHelper(archive).entries\n\n  assert(expected.size == entries.size)\n  assert(expected.forall(e => entries.contains(e)))\n}\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets-cookbook/project/ZipHelper.scala",
    "content": "import java.io.File\nimport java.util.zip.ZipFile\n\nimport scala.collection.JavaConverters._\n\nclass ZipHelper(f: File) {\n\n  val zipFile = new ZipFile(f)\n\n  lazy val entries : List[String] = zipFile.entries().asScala.toList.map { e => e.getName() }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets-cookbook/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\naddSbtPlugin(\"com.typesafe.sbt\" % \"sbt-native-packager\" % \"1.7.2\")\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets-cookbook/src/main/scala/example/Main.scala",
    "content": "package example\n\nimport com.github.ahnfelt.react4s._\n\ncase class HelloComponent() extends Component[NoEmit] {\n\n  override def render(get: Get): Node = E.div(\n    E.h1(Text(\"Hello World !\"))\n  )\n}\n\nobject Main {\n\n  def main(args: Array[String]) : Unit = {\n    val main = Component(HelloComponent)\n    ReactBridge.renderToDomById(main, \"content\")\n  }\n\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets-cookbook/src/universal/index.html",
    "content": "<!DOCTYPE html>\n<!--suppress ALL -->\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <title>WebAsset Demo </title>\n</head>\n<body>\n\n<div id=\"content\"></div>\n<script type=\"text/javascript\" src=\"assets/react.production.min.js\"></script>\n<script type=\"text/javascript\" src=\"assets/react-dom.production.min.js\"></script>\n<script type=\"text/javascript\" src=\"assets/webpack-assets-opt-library.js\"></script>\n<script type=\"text/javascript\" src=\"assets/webpack-assets-opt-loader.js\"></script>\n<script type=\"text/javascript\" src=\"assets/webpack-assets-opt.js\"></script>\n\n</body>\n</html>"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-assets-cookbook/test",
    "content": "> clean\n> universal:packageBin\n> checkArchive"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-dev-server/build.sbt",
    "content": "import com.gargoylesoftware.htmlunit.WebClient\nimport com.gargoylesoftware.htmlunit.WebConsole.Logger\n\nname := \"webpack-dev-server\"\n\nenablePlugins(ScalaJSBundlerPlugin)\n\nscalaVersion := \"2.13.2\"\n\nscalaJSUseMainModuleInitializer := true\n\n// Use a custom config file\nwebpackConfigFile := Some(baseDirectory.value / \"webpack.config.js\")\n\n(npmDevDependencies in Compile) += (\"html-webpack-plugin\" -> \"5.2.0\")\n\nwebpackCliVersion := \"4.9.0\"\n\nwebpackDevServerPort := 7357\n\n// HtmlUnit does not support ECMAScript 2015\nscalaJSLinkerConfig ~= { _.withESFeatures(_.withUseECMAScript2015(false)) }\n\n// (Used by tests only) checks that a HTML can be loaded (and that its JavaScript can be executed) without errors\nInputKey[Unit](\"html\") := {\n  import complete.DefaultParsers._\n  val ags = Def.spaceDelimited().parsed.toList\n\n  val (page, timeout, shouldPass) =\n    ags match {\n      case List(page, rawTimeout, pass) => (page, rawTimeout.toInt, pass.toBoolean)\n      case _ => sys.error(\"expected: page timeout\")\n    }\n\n  var totalTime = 0\n  val dt = 100\n  var connected = false\n  var gotMessage = false\n\n  println(\"Connecting to webpack-dev-server\")\n  println(\"\")\n\n  while(totalTime < timeout && !connected) {\n    val expected = \"6051a036-bfb4-4158-a171-950416b5bd9a\"\n\n    val client = new WebClient()\n    client.getWebConsole.setLogger(new Logger(){\n      def info(message: Any): Unit = {\n        if (message == expected){\n          gotMessage = true\n        } else {\n          println(s\"info $message\")\n        }\n      }\n      def debug(message: Any): Unit = println(s\"debug: $message\")\n      def error(message: Any): Unit = println(s\"error: $message\")\n      def trace(message: Any): Unit = println(s\"trace: $message\")\n      def warn(message: Any): Unit = println(s\"warn: $message\")\n      def isDebugEnabled(): Boolean = true\n      def isErrorEnabled(): Boolean = true\n      def isInfoEnabled(): Boolean = true\n      def isTraceEnabled(): Boolean = true\n      def isWarnEnabled(): Boolean = true\n    })\n\n    try {\n      client.getPage(s\"http://localhost:7357/$page\")\n      connected = true\n    } catch {\n      case ex: org.apache.http.conn.HttpHostConnectException => {\n        print(\"*\")\n      }\n    } finally {\n      client.close()\n    }\n    Thread.sleep(dt)\n    totalTime += dt\n  }\n\n  assert(!shouldPass || gotMessage, \"Did not get println result\")\n}\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-dev-server/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nlibraryDependencies += \"net.sourceforge.htmlunit\" % \"htmlunit\" % \"2.46.0\"\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-dev-server/src/main/scala/example/Main.scala",
    "content": "package example\n\nobject Main {\n  def main(args: Array[String]): Unit = {\n    println(\"6051a036-bfb4-4158-a171-950416b5bd9a\")\n  }\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-dev-server/test",
    "content": "# keep at least this test while the rest is disabled\n> fastOptJS::webpack\n\n# disabled because Webpack/webpack-cli/htmlunit don't want to work together anymore\n# # the server should properly start\n# > fastOptJS::startWebpackDevServer\n# > html index.html 20000 true\n\n# # the server should properly stop\n# > fastOptJS::stopWebpackDevServer\n# > html index.html 1000 false\n\n# # the server should properly terminate on exit\n# > fastOptJS::startWebpackDevServer\n# > html index.html 20000 true\n# -> exit\n# > html index.html 1000 false\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/webpack-dev-server/webpack.config.js",
    "content": "// Load the config generated by scalajs-bundler\nvar config = require('./scalajs.webpack.config');\n\nvar HtmlWebpackPlugin = require('html-webpack-plugin');\n\nmodule.exports = config;\n\nmodule.exports.plugins = [\n  new HtmlWebpackPlugin()\n];\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/yarn-interactive/build.sbt",
    "content": "scalaVersion := \"2.12.8\"\n\nuseYarn := true\n\nyarnExtraArgs in Compile := Seq(\"--silent\")\n\nscalaJSUseMainModuleInitializer := true\n\nnpmDependencies in Compile += \"neat\" -> \"2.1.0\"\n\nenablePlugins(ScalaJSBundlerPlugin)\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/yarn-interactive/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-scalajs-bundler\" % scalaJSBundlerVersion)\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/yarn-interactive/src/main/scala/example/Main.scala",
    "content": "package example\n\nobject Main {\n  def main(args: Array[String]): Unit = {\n    println(\"yarn-interactive main\")\n  }\n}\n"
  },
  {
    "path": "sbt-scalajs-bundler/src/sbt-test/sbt-scalajs-bundler/yarn-interactive/test",
    "content": "> fastOptJS::webpack\n"
  },
  {
    "path": "sbt-web-scalajs-bundler/src/main/scala/scalajsbundler/sbtplugin/NpmAssets.scala",
    "content": "package scalajsbundler.sbtplugin\n\nimport com.typesafe.sbt.web.PathMapping\nimport sbt._\n\nimport scalajsbundler.sbtplugin.ScalaJSBundlerPlugin.autoImport.npmUpdate\n\nobject NpmAssets {\n\n  /**\n    * {{{\n    *   npmAssets ++= NpmAssets.ofProject(client) { _ / \"some-package\" / \"some-relevant\" ** \"files\" }.value\n    * }}}\n    *\n    * @return A task producing a sequence of files paired with their path relative to the `node_modules` directory\n    *         of `project`.\n    * @param project The project that depends on the NPM package containing the assets to publish.\n    * @param assets A function that finds files given the `node_modules` directory of `project`\n    */\n  def ofProject(project: ProjectReference)(assets: File => PathFinder): Def.Initialize[Task[Seq[PathMapping]]] =\n    Def.task {\n      val nodeModules = (npmUpdate in (project, Compile)).value / \"node_modules\"\n      assets(nodeModules).pair(Path.relativeTo(nodeModules))\n    }\n\n}\n"
  },
  {
    "path": "sbt-web-scalajs-bundler/src/main/scala/scalajsbundler/sbtplugin/WebScalaJSBundlerPlugin.scala",
    "content": "package scalajsbundler.sbtplugin\n\nimport com.typesafe.sbt.web.PathMapping\nimport com.typesafe.sbt.web.pipeline.Pipeline\nimport org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._\nimport org.scalajs.sbtplugin.Stage\nimport sbt.Keys._\nimport sbt._\nimport webscalajs.WebScalaJS\nimport webscalajs.WebScalaJS.autoImport._\n\nimport scala.collection.immutable.Nil\nimport scalajsbundler.sbtplugin.ScalaJSBundlerPlugin.autoImport._\n\n/**\n  * If WebScalaJS is enabled, tweaks the pipelineStage so that the bundle is produced\n  * as an sbt-web asset.\n  *\n  * = Tasks and Settings =\n  *\n  * See the [[WebScalaJSBundlerPlugin.autoImport autoImport]] member.\n  */\nobject WebScalaJSBundlerPlugin extends AutoPlugin {\n\n  /**\n    * @groupname settings Settings\n    */\n  object autoImport {\n\n    /**\n      * Sequence of PathMapping’s to include to sbt-web’s assets.\n      *\n      * @see [[scalajsbundler.sbtplugin.NpmAssets.ofProject NpmAssets.ofProject]]\n      * @group settings\n      */\n    val npmAssets: TaskKey[Seq[PathMapping]] = taskKey[Seq[PathMapping]](\"Assets (resources that are not CommonJS modules) imported from the NPM packages\")\n\n    val NpmAssets = scalajsbundler.sbtplugin.NpmAssets\n\n  }\n\n  import autoImport._\n\n  override lazy val requires = WebScalaJS\n\n  override lazy val projectSettings = Seq(\n    monitoredScalaJSDirectories ++= allFrontendProjectResourceDirectories.value,\n    scalaJSPipeline := pipelineStage.value,\n    npmAssets := Nil\n  )\n\n  val allFrontendProjectResourceDirectories: Def.Initialize[Seq[File]] = Def.settingDyn {\n    val projectRefs = scalaJSProjects.value.map(Project.projectToRef)\n    projectRefs.map { project =>\n      Def.setting {\n        (resourceDirectories in Compile in project).value\n      }\n    }.foldLeft(Def.setting(Seq.empty[File]))((acc, resourceDirectories) =>\n      Def.setting(acc.value ++ resourceDirectories.value)\n    )\n  }\n\n  val bundlesWithSourceMaps: Def.Initialize[Task[Seq[(File, String)]]] =\n    Def.settingDyn {\n      val projects = scalaJSProjects.value.map(Project.projectToRef)\n      Def.task {\n        // ((file, relative-path), sourceMapsEnabled)\n        val bundles: Seq[((File, String), Boolean)] =\n          projects\n            .map { project =>\n              Def.settingDyn {\n                val sjsStage = (scalaJSStage in project).value match {\n                  case Stage.FastOpt => fastOptJS\n                  case Stage.FullOpt => fullOptJS\n                }\n                Def.task {\n                  val files = (webpack in (project, Compile, sjsStage)).value\n                  val clientTarget = (npmUpdate in (project, Compile)).value\n                  val sourceMapsEnabled = (finallyEmitSourceMaps in (project, Compile, sjsStage)).value\n                  files.map(_.data).pair(Path.relativeTo(clientTarget)).map((_, sourceMapsEnabled))\n                }\n              }\n            }\n            .foldLeft(Def.task(Seq.empty[((File, String), Boolean)]))((acc, bundleFiles) => Def.task(acc.value ++ bundleFiles.value))\n            .value\n\n        bundles.flatMap { case ((file, path), bundleSourceMapsEnabled) =>\n          val sourceMapFile = file.getParentFile / (file.name ++ \".map\")\n          if (bundleSourceMapsEnabled && sourceMapFile.exists) {\n            val sourceMapPath = path ++ \".map\"\n            Seq(file -> path, sourceMapFile -> sourceMapPath)\n          } else Seq(file -> path)\n        }\n      }\n    }\n\n  val pipelineStage: Def.Initialize[Task[Pipeline.Stage]] =\n    Def.taskDyn {\n      val npmAssetsMappings = npmAssets.value\n      val include = (includeFilter in scalaJSPipeline).value\n      val exclude = (excludeFilter in scalaJSPipeline).value\n      val bundleMappings = bundlesWithSourceMaps.value\n      val sourcemapScalaFiles = WebScalaJS.sourcemapScalaFiles.value\n      Def.task { mappings: Seq[PathMapping] =>\n        val filtered = filterMappings(mappings, include, exclude)\n\n        filtered ++ bundleMappings ++ sourcemapScalaFiles ++ npmAssetsMappings\n      }\n    }\n\n  def filterMappings(mappings: Seq[PathMapping], include: FileFilter, exclude: FileFilter): Seq[PathMapping] =\n    for {\n      (file, path) <- mappings\n      if include.accept(file) && !exclude.accept(file)\n    } yield file -> path\n\n}\n"
  },
  {
    "path": "sbt-web-scalajs-bundler/src/sbt-test/sbt-web-scalajs-bundler/play/build.sbt",
    "content": "val client =\n  project.in(file(\"client\"))\n    .enablePlugins(ScalaJSBundlerPlugin)\n    .settings(\n      // Required to solve https://github.com/scala/bug/issues/11955\n      scalaVersion := \"2.13.4\",\n      scalaJSUseMainModuleInitializer := true,\n      libraryDependencies += \"org.scala-js\" %%% \"scalajs-dom\" % \"1.0.0\",\n      npmDependencies in Compile ++= Seq(\n        \"snabbdom\" -> \"0.5.3\",\n        \"font-awesome\" -> \"4.7.0\",\n        \"url-loader\" -> \"0.5.9\"\n      ),\n      ivyLoggingLevel := UpdateLogging.Quiet\n    )\n\nval server =\n  project.in(file(\"server\"))\n    .enablePlugins(PlayScala, WebScalaJSBundlerPlugin)\n    .disablePlugins(PlayLayoutPlugin)\n    .settings(\n      // Required to solve https://github.com/scala/bug/issues/11955\n      scalaVersion := \"2.13.4\",\n      libraryDependencies ++= Seq(\n        \"com.vmunier\" %% \"scalajs-scripts\" % \"1.1.4\",\n        \"org.scalatestplus.play\" %% \"scalatestplus-play\" % \"5.1.0\" % Test\n      ),\n      scalaJSProjects := Seq(client),\n      pipelineStages in Assets := Seq(scalaJSPipeline),\n      pipelineStages := Seq(digest, gzip),\n      // Expose as sbt-web assets some files retrieved from the NPM packages of the `client` project\n      npmAssets ++= NpmAssets.ofProject(client) { modules => (modules / \"font-awesome\").allPaths }.value,\n      ivyLoggingLevel := UpdateLogging.Quiet\n    )\n\nval play =\n  project.in(file(\".\"))\n    .aggregate(client, server)\n    .settings(\n      ivyLoggingLevel := UpdateLogging.Quiet\n    )\n"
  },
  {
    "path": "sbt-web-scalajs-bundler/src/sbt-test/sbt-web-scalajs-bundler/play/client/src/main/scala/example/Main.scala",
    "content": "package example\n\nimport snabbdom.{snabbdom, modules, h}\n\nimport scala.scalajs.js\n\nimport org.scalajs.dom.document\n\nobject Main {\n\n  def main(args: Array[String]): Unit = {\n    val patch = snabbdom.init(js.Array(modules.props, modules.eventlisteners))\n\n    val view =\n      h(\"p\", \"Hello, world!\": js.Any)\n\n    patch(document.body.querySelector(\"div\"), view)\n  }\n\n}\n"
  },
  {
    "path": "sbt-web-scalajs-bundler/src/sbt-test/sbt-web-scalajs-bundler/play/client/src/main/scala/snabbdom/modules/modules.scala",
    "content": "package snabbdom.modules\n\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation.JSImport\nimport scala.scalajs.js.annotation.JSImport.Namespace\n\n@JSImport(\"snabbdom/modules/class\", Namespace)\n@js.native\nobject `class` extends js.Object\n\n@JSImport(\"snabbdom/modules/props\", Namespace)\n@js.native\nobject props extends js.Object\n\n@JSImport(\"snabbdom/modules/style\", Namespace)\n@js.native\nobject style extends js.Object\n\n@JSImport(\"snabbdom/modules/eventlisteners\", Namespace)\n@js.native\nobject eventlisteners extends js.Object"
  },
  {
    "path": "sbt-web-scalajs-bundler/src/sbt-test/sbt-web-scalajs-bundler/play/client/src/main/scala/snabbdom/snabbdom.scala",
    "content": "package snabbdom\n\nimport org.scalajs.dom.{Element, Text}\n\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation.JSImport\nimport scala.scalajs.js.annotation.JSImport.Namespace\nimport scala.scalajs.js.|\n\n@JSImport(\"snabbdom\", Namespace)\n@js.native\nobject snabbdom extends js.Object {\n  def init(modules: js.Array[js.Object]): js.Function2[VNode | Element, VNode, VNode] = js.native\n}\n\n@JSImport(\"snabbdom/h\", Namespace)\n@js.native\nobject h extends js.Function3[String, js.UndefOr[js.Any], js.UndefOr[js.Any], VNode] {\n  def apply(selector: String, b: js.UndefOr[js.Any] = js.undefined, c: js.UndefOr[js.Any] = js.undefined): VNode = js.native\n}\n\n@js.native\ntrait VNode extends js.Object {\n  var selector: js.UndefOr[String] = js.native\n  var data: js.UndefOr[VNodeData]= js.native\n  var children: js.UndefOr[js.Array[VNode | String]]= js.native\n  var text: js.UndefOr[String]= js.native\n  var elm: js.UndefOr[Element | Text]= js.native\n  var key: js.UndefOr[String | Double]= js.native\n}\n\n@js.native\ntrait VNodeData extends js.Object\n"
  },
  {
    "path": "sbt-web-scalajs-bundler/src/sbt-test/sbt-web-scalajs-bundler/play/project/plugins.sbt",
    "content": "val scalaJSVersion = sys.props.getOrElse(\"scalajs.version\", sys.error(\"'scalajs.version' environment variable is not defined\"))\nval scalaJSBundlerVersion = sys.props.getOrElse(\"plugin.version\", sys.error(\"'plugin.version' environment variable is not set\"))\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % scalaJSVersion)\n\naddSbtPlugin(\"ch.epfl.scala\" % \"sbt-web-scalajs-bundler\" % scalaJSBundlerVersion)\n\naddSbtPlugin(\"com.typesafe.play\" % \"sbt-plugin\" % \"2.9.0\")\n\naddSbtPlugin(\"com.typesafe.sbt\" % \"sbt-gzip\" % \"1.0.2\")\n\naddSbtPlugin(\"com.typesafe.sbt\" % \"sbt-digest\" % \"1.1.4\")\n\nivyLoggingLevel in ThisBuild := UpdateLogging.Quiet\n"
  },
  {
    "path": "sbt-web-scalajs-bundler/src/sbt-test/sbt-web-scalajs-bundler/play/server/src/main/resources/application.conf",
    "content": "play {\n  crypto.secret = \"abc123\"\n  application.loader = \"example.Loader\"\n}"
  },
  {
    "path": "sbt-web-scalajs-bundler/src/sbt-test/sbt-web-scalajs-bundler/play/server/src/main/resources/router.routes",
    "content": "GET     /                           example.ExampleController.index\nGET     /assets/*file               controllers.Assets.versioned(path=\"/public\", file: Asset)\n"
  },
  {
    "path": "sbt-web-scalajs-bundler/src/sbt-test/sbt-web-scalajs-bundler/play/server/src/main/scala/example/ExampleController.scala",
    "content": "package example\n\nimport play.api.mvc.{AbstractController, ControllerComponents}\nimport play.twirl.api.StringInterpolation\n\nclass ExampleController(cc: ControllerComponents) extends AbstractController(cc) {\n\n  val index = {\n    val result =\n      Ok(\n        html\"\"\"<!doctype html>\n        <html>\n          <head></head>\n          <body>\n            <div>App is not loaded.</div>\n            ${scalajs.html.scripts(\"client\", controllers.routes.Assets.versioned(_).toString, name => getClass.getResource(s\"/public/$name\") != null)}\n          </body>\n        </html>\n      \"\"\"\n      )\n    Action(result)\n  }\n\n}\n"
  },
  {
    "path": "sbt-web-scalajs-bundler/src/sbt-test/sbt-web-scalajs-bundler/play/server/src/main/scala/example/Loader.scala",
    "content": "package example\n\nimport play.api.ApplicationLoader.Context\nimport play.api.{Application, ApplicationLoader, BuiltInComponentsFromContext}\nimport play.filters.HttpFiltersComponents\nimport router.Routes\n\nclass Loader extends ApplicationLoader {\n  def load(context: Context): Application = new ExampleComponents(context).application\n}\n\nclass ExampleComponents(context: Context)\n    extends BuiltInComponentsFromContext(context)\n    with HttpFiltersComponents\n    with controllers.AssetsComponents {\n  val controller = new ExampleController(controllerComponents)\n  val router = new Routes(httpErrorHandler, controller, assets)\n}\n"
  },
  {
    "path": "sbt-web-scalajs-bundler/src/sbt-test/sbt-web-scalajs-bundler/play/server/src/test/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration debug=\"false\">\n    <appender name=\"CONSOLE\" class=\"ch.qos.logback.core.ConsoleAppender\">\n        <encoder class=\"ch.qos.logback.core.encoder.LayoutWrappingEncoder\">\n            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>\n        </encoder>\n    </appender>\n\n    <logger name=\"org.apache\" level=\"WARNING\" />\n\n    <root>\n        <level value=\"info\"/>\n        <appender-ref ref=\"CONSOLE\"/>\n    </root>\n</configuration>\n"
  },
  {
    "path": "sbt-web-scalajs-bundler/src/sbt-test/sbt-web-scalajs-bundler/play/server/src/test/scala/example/ExampleSpec.scala",
    "content": "package example\n\nimport org.scalatestplus.play.guice.GuiceOneServerPerSuite\nimport org.scalatestplus.play.{HtmlUnitFactory, OneBrowserPerSuite, PlaySpec}\nimport play.api.ApplicationLoader.Context\nimport play.api.Environment\n\nclass ExampleSpec extends PlaySpec with GuiceOneServerPerSuite with OneBrowserPerSuite with HtmlUnitFactory {\n\n  implicit override lazy val app =\n    (new Loader).load(Context.create(Environment.simple()))\n\n  \"The application\" must {\n    \"load assets imported from NPM modules\" in {\n      go to s\"http://localhost:$port/assets/font-awesome/css/font-awesome.min.css\"\n      pageSource must include(\"Font Awesome\")\n    }\n  }\n\n}\n"
  },
  {
    "path": "sbt-web-scalajs-bundler/src/sbt-test/sbt-web-scalajs-bundler/play/test",
    "content": "> server/assets\n$ exists client/target/scala-2.13/scalajs-bundler/main/client-fastopt-bundle.js\n$ absent client/target/scala-2.13/scalajs-bundler/main/client-opt-bundle.js\n$ delete client/target/scala-2.13/scalajs-bundler/main/client-fastopt-bundle.js\n\n> set scalaJSStage in Global := FullOptStage\n> server/assets\n$ exists client/target/scala-2.13/scalajs-bundler/main/client-opt-bundle.js\n$ absent client/target/scala-2.13/scalajs-bundler/main/client-fastopt-bundle.js\n$ delete client/target/scala-2.13/scalajs-bundler/main/client-opt-bundle.js\n\n> set scalaJSStage in Global := FastOptStage\n> server/test\n> client/test\n\n> server/stage\n"
  },
  {
    "path": "scalajs-bundler-linker/src/main/scala/scalajsbundler/bundlerlinker/BundlerLinkerImpl.scala",
    "content": "package scalajsbundler.bundlerlinker\n\nimport java.nio.file.Path\n\nimport org.scalajs.linker._\nimport org.scalajs.linker.interface._\nimport org.scalajs.linker.standard._\n\nobject BundlerLinkerImpl {\n  def linker(config: StandardConfig, entryPointOutputFile: Path): Linker = {\n    val frontend = StandardLinkerFrontend(config)\n    val backend = new EntryPointAnalyzerBackend(config, entryPointOutputFile)\n    StandardLinkerImpl(frontend, backend)\n  }\n\n  def clearableLinker(config: StandardConfig, entryPointOutputFile: Path): ClearableLinker =\n    ClearableLinker(() => linker(config, entryPointOutputFile), config.batchMode)\n}\n"
  },
  {
    "path": "scalajs-bundler-linker/src/main/scala/scalajsbundler/bundlerlinker/EntryPointAnalyzerBackend.scala",
    "content": "package scalajsbundler.bundlerlinker\n\nimport scala.concurrent.{ExecutionContext, Future}\nimport scala.collection.JavaConverters._\n\nimport java.nio.charset.StandardCharsets\nimport java.nio.file.{Files, Path}\n\nimport org.scalajs.logging.Logger\n\nimport org.scalajs.linker.interface._\nimport org.scalajs.linker.standard._\n\nfinal class EntryPointAnalyzerBackend(linkerConfig: StandardConfig, entryPointOutputFile: Path) extends LinkerBackend {\n  private val standard = StandardLinkerBackend(linkerConfig)\n\n  val coreSpec: CoreSpec = standard.coreSpec\n  val symbolRequirements: SymbolRequirement = standard.symbolRequirements\n\n  def injectedIRFiles: Seq[IRFile] = standard.injectedIRFiles\n\n  def emit(moduleSet: ModuleSet, output: OutputDirectory, logger: Logger)(\n      implicit ec: ExecutionContext): Future[Report] = {\n    val modules = moduleSet.modules.flatMap(_.externalDependencies).toSet\n    Files.write(entryPointOutputFile, modules.toIterable.asJava, StandardCharsets.UTF_8)\n    standard.emit(moduleSet, output, logger)\n  }\n}\n"
  }
]