[
  {
    "path": ".babelrc",
    "content": "{\n  \"presets\": [\n    [\"env\", {\n      \"targets\": {\n        \"node\": 4,\n      }\n    }],\n    \"stage-2\"\n  ],\n  \"plugins\": [\n    [\"transform-runtime\", {\n      \"helpers\": false,\n      \"polyfill\": false,\n      \"regenerator\": true,\n      \"moduleName\": \"babel-runtime\"\n    }]\n  ]\n}\n"
  },
  {
    "path": ".eslintrc.js",
    "content": "module.exports = {\n  root: true,\n  parser: 'babel-eslint',\n  // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style\n  extends: 'standard',\n  // add your custom rules here\n  'rules': {\n    // allow paren-less arrow functions\n    'arrow-parens': 0\n  }\n}\n"
  },
  {
    "path": ".gitignore",
    "content": "# Created by https://www.gitignore.io/api/node,macos,linux,windows,visualstudiocode\n\n### Linux ###\n*~\n\n# temporary files which can be created if a process still has a handle open of a deleted file\n.fuse_hidden*\n\n# KDE directory preferences\n.directory\n\n# Linux trash folder which might appear on any partition or disk\n.Trash-*\n\n# .nfs files are created when an open file is removed but is still being accessed\n.nfs*\n\n### macOS ###\n*.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \\r\nIcon\n\n# Thumbnails\n._*\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n.VolumeIcon.icns\n.com.apple.timemachine.donotpresent\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n### Node ###\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# Typescript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n\n### VisualStudioCode ###\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n\n### Windows ###\n# Windows thumbnail cache files\nThumbs.db\nehthumbs.db\nehthumbs_vista.db\n\n# Folder config file\nDesktop.ini\n\n# Recycle Bin used on file shares\n$RECYCLE.BIN/\n\n# Windows Installer files\n*.cab\n*.msi\n*.msm\n*.msp\n\n# Windows shortcuts\n*.lnk\n"
  },
  {
    "path": "LICENSE.md",
    "content": "## MIT License\n\nCopyright (c) 2017 Chris Fritz\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<h1 align=\"center\">[DEPRECATED]</h1>\n\n<h2 align=\"center\">Prerender SPA Plugin</h2>\n<p align=\"center\">\n  <em>Flexible, framework-agnostic static site generation for sites and SPAs built with webpack.</em>\n</p>\n\n<p align=\"center\"><img width=\"200\" src=\"https://raw.githubusercontent.com/chrisvfritz/prerender-spa-plugin/master/assets/logo.png?raw=true\"></p>\n\n---\n\n<div align=\"center\">\n\n[![Maintainers Wanted](https://img.shields.io/badge/maintainers-wanted-red.svg)]()\n[![npm version](https://img.shields.io/npm/v/prerender-spa-plugin.svg)]()\n[![npm downloads](https://img.shields.io/npm/dt/prerender-spa-plugin.svg)]()\n[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](https://standardjs.com/)\n[![license](https://img.shields.io/github/license/chrisvfritz/prerender-spa-plugin.svg)]()\n\n</div>\n\n---\n\n<div align=\"center\">\n\n[![NPM](https://nodei.co/npm/prerender-spa-plugin.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/prerender-spa-plugin/)\n\n</div>\n\n## About prerender-spa-plugin\n\n**:point_right: This is the stable `3.x` version of `prerender-spa-plugin` based on puppeteer. If you're looking for the (now-deprecated) `2.x` version, based on PhantomJS, take a look at the `v2` branch.**\n\nThe goal of this plugin is to provide a simple prerendering solution that is easily extensible and usable for any site or single-page-app built with webpack.\n\nPlugins for other task runners and build systems are planned.\n\n## Examples\nFramework-specific examples can be found in the `examples/` directory.\n\n- [Vanilla JS](examples/vanilla-simple)\n- [Vue.js 2 Simple](examples/vue2-webpack-simple)\n- [Vue.js 2 Router](examples/vue2-webpack-router)\n- [React (Create React App)](examples/create-react-app)\n- [Angular (Angular CLI + Eject)](examples/angular-cli-eject)\n\n### Basic Usage (`webpack.config.js`)\n```js\nconst path = require('path')\nconst PrerenderSPAPlugin = require('prerender-spa-plugin')\n\nmodule.exports = {\n  plugins: [\n    ...\n    new PrerenderSPAPlugin({\n      // Required - The path to the webpack-outputted app to prerender.\n      staticDir: path.join(__dirname, 'dist'),\n      // Required - Routes to render.\n      routes: [ '/', '/about', '/some/deep/nested/route' ],\n    })\n  ]\n}\n```\n\n### Advanced Usage (`webpack.config.js`)\n\n```js\nconst path = require('path')\nconst PrerenderSPAPlugin = require('prerender-spa-plugin')\nconst Renderer = PrerenderSPAPlugin.PuppeteerRenderer\n\nmodule.exports = {\n  plugins: [\n    ...\n    new PrerenderSPAPlugin({\n      // Required - The path to the webpack-outputted app to prerender.\n      staticDir: path.join(__dirname, 'dist'),\n\n      // Optional - The path your rendered app should be output to.\n      // (Defaults to staticDir.)\n      outputDir: path.join(__dirname, 'prerendered'),\n\n      // Optional - The location of index.html\n      indexPath: path.join(__dirname, 'dist', 'index.html'),\n\n      // Required - Routes to render.\n      routes: [ '/', '/about', '/some/deep/nested/route' ],\n\n      // Optional - Allows you to customize the HTML and output path before\n      // writing the rendered contents to a file.\n      // renderedRoute can be modified and it or an equivelant should be returned.\n      // renderedRoute format:\n      // {\n      //   route: String, // Where the output file will end up (relative to outputDir)\n      //   originalRoute: String, // The route that was passed into the renderer, before redirects.\n      //   html: String, // The rendered HTML for this route.\n      //   outputPath: String // The path the rendered HTML will be written to.\n      // }\n      postProcess (renderedRoute) {\n        // Ignore any redirects.\n        renderedRoute.route = renderedRoute.originalRoute\n        // Basic whitespace removal. (Don't use this in production.)\n        renderedRoute.html = renderedRoute.html.split(/>[\\s]+</gmi).join('><')\n        // Remove /index.html from the output path if the dir name ends with a .html file extension.\n        // For example: /dist/dir/special.html/index.html -> /dist/dir/special.html\n        if (renderedRoute.route.endsWith('.html')) {\n          renderedRoute.outputPath = path.join(__dirname, 'dist', renderedRoute.route)\n        }\n\n        return renderedRoute\n      },\n\n      // Optional - Uses html-minifier (https://github.com/kangax/html-minifier)\n      // To minify the resulting HTML.\n      // Option reference: https://github.com/kangax/html-minifier#options-quick-reference\n      minify: {\n        collapseBooleanAttributes: true,\n        collapseWhitespace: true,\n        decodeEntities: true,\n        keepClosingSlash: true,\n        sortAttributes: true\n      },\n\n      // Server configuration options.\n      server: {\n        // Normally a free port is autodetected, but feel free to set this if needed.\n        port: 8001\n      },\n\n      // The actual renderer to use. (Feel free to write your own)\n      // Available renderers: https://github.com/Tribex/prerenderer/tree/master/renderers\n      renderer: new Renderer({\n        // Optional - The name of the property to add to the window object with the contents of `inject`.\n        injectProperty: '__PRERENDER_INJECTED',\n        // Optional - Any values you'd like your app to have access to via `window.injectProperty`.\n        inject: {\n          foo: 'bar'\n        },\n\n        // Optional - defaults to 0, no limit.\n        // Routes are rendered asynchronously.\n        // Use this to limit the number of routes rendered in parallel.\n        maxConcurrentRoutes: 4,\n\n        // Optional - Wait to render until the specified event is dispatched on the document.\n        // eg, with `document.dispatchEvent(new Event('custom-render-trigger'))`\n        renderAfterDocumentEvent: 'custom-render-trigger',\n\n        // Optional - Wait to render until the specified element is detected using `document.querySelector`\n        renderAfterElementExists: 'my-app-element',\n\n        // Optional - Wait to render until a certain amount of time has passed.\n        // NOT RECOMMENDED\n        renderAfterTime: 5000, // Wait 5 seconds.\n\n        // Other puppeteer options.\n        // (See here: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions)\n        headless: false // Display the browser window when rendering. Useful for debugging.\n      })\n    })\n  ]\n}\n```\n\n### v2.x Compability\nMost usages of `prerender-spa-plugin` v2.x should be compatible with v3.x.\nThe exception being advanced configuration options that controlled PhantomJS. These have been replaced by pluggable renderers with their own specific configuration options.\n\nIf you use this format, you will be greeted with a warning prompting you to migrate to the new object-based configuration format, but it should still function for the time being.\n\n```js\nconst path = require('path')\nconst PrerenderSPAPlugin = require('prerender-spa-plugin')\n\nmodule.exports = {\n\n  // ...\n\n  plugins: [\n    new PrerenderSPAPlugin(\n      // (REQUIRED) Absolute path to static root\n      path.join(__dirname, 'relative/path/to/static/root'),\n      // (REQUIRED) List of routes to prerender\n      [ '/', '/about', '/contact' ],\n      // (OPTIONAL) Compatible options from v2.\n      {\n        // NOTE: Unless you are relying on asynchronously rendered content,\n        // such as after an Ajax request, none of these options should be\n        // necessary. All synchronous scripts are already executed before\n        // capturing the page content.\n\n        // Wait until a specific event is fired on the document.\n        captureAfterDocumentEvent: 'custom-post-render-event',\n        // This is how you would trigger this example event:\n        // document.dispatchEvent(new Event('custom-post-render-event'))\n\n        // Wait until a specific element is detected with\n        // document.querySelector.\n        captureAfterElementExists: '#content',\n\n        // Wait until a number of milliseconds has passed after scripts\n        // have been executed. It's important to note that this may\n        // produce unreliable results when relying on network\n        // communication or other operations with highly variable timing.\n        captureAfterTime: 5000,\n\n        // path of index file. By default it's index.html in static root.\n        indexPath: path.resolve('/dist/path/to/index.html'),\n\n        // Manually transform the HTML for each page after prerendering,\n        // for example to set the page title and metadata in edge cases\n        // where you cannot handle this via your routing solution.\n        //\n        // The function's context argument contains two properties:\n        //\n        // - html :: the resulting HTML after prerendering)\n        // - route :: the route currently being processed\n        //            e.g. \"/\", \"/about\", or \"/contact\")\n        //\n        // Whatever is returned will be printed to the prerendered file.\n        // NOTE: this has been deprecated in favor of the `postProcess` option.\n        // See the documentation below.\n        postProcessHtml: function (context) {\n          var titles = {\n            '/': 'Home',\n            '/about': 'Our Story',\n            '/contact': 'Contact Us'\n          }\n          return context.html.replace(\n            /<title>[^<]*<\\/title>/i,\n            '<title>' + titles[context.route] + '</title>'\n          )\n        }\n      }\n    )\n  ]\n}\n```\n\n#### Additional Changes\n- It is no longer possible to use multiple `renderAfterX` (`captureAfterX`) options at the same time. Only one may be selected. The reason for this removal is to prevent ambiguity.\n- The recommended configuration format has changed from `new PrerenderSPAPlugin(staticDir: String, routes: Array<String>, config: Object)` to\n  ```javascript\n  new PrerenderSPAPlugin({\n    staticDir: String,\n    routes: String,\n    ...\n  })\n  ```\n  in order to reduce ambiguity. The old format still works for the time being.\n- The default renderer is no longer PhantomJS. It has been replaced with [puppeteer](https://github.com/GoogleChrome/puppeteer). It is fairly simple to develop your own renderer as well. An alternate [jsdom](https://github.com/tmpvar/jsdom)-based renderer is available at [@prerenderer/renderer-jsdom](https://www.npmjs.com/package/@prerenderer/renderer-jsdom).\n- `prerender-spa-plugin` is now based on [prerenderer](https://github.com/Tribex/prerenderer). Accordingly, most bugs should be reported in that repository.\n\n## What is Prerendering?\n\nRecently, SSR (Server Side Rendering) has taken the JavaScript front-end world by storm. The fact that you can now render your sites and apps on the server before sending them to your clients is an absolutely *revolutionary* idea (and totally not what everyone was doing before JS client-side apps got popular in the first place...)\n\nHowever, the same criticisms that were valid for PHP, ASP, JSP, (and such) sites are valid for server-side rendering today. It's slow, breaks fairly easily, and is difficult to implement properly.\n\nThing is, despite what everyone might be telling you, you probably don't *need* SSR. You can get almost all the advantages of it (without the disadvantages) by using **prerendering.** Prerendering is basically firing up a headless browser, loading your app's routes, and saving the results to a static HTML file. You can then serve it with whatever static-file-serving solution you were using previously. It *just works* with HTML5 navigation and the likes. No need to change your code or add server-side rendering workarounds.\n\nIn the interest of transparency, there are some use-cases where prerendering might not be a great idea.\n\n- **Tons of routes** - If your site has hundreds or thousands of routes, prerendering will be really slow. Sure you only have to do it once per update, but it could take ages. Most people don't end up with thousands of static routes, but just in-case...\n- **Dynamic Content** - If your render routes that have content that's specific to the user viewing it or other dynamic sources, you should make sure you have placeholder components that can display until the dynamic content loads on the client-side. Otherwise it might be a tad weird.\n\n## Available Renderers\n- `@prerenderer/renderer-puppeteer` - Uses [puppeteer](https://github.com/GoogleChrome/puppeteer) to render pages in headless Chrome.\n- `@prerenderer/renderer-jsdom` - Uses [jsdom](https://npmjs.com/package/jsdom). Extremely fast, but unreliable and cannot handle advanced usages. May not work with all front-end frameworks and apps.\n\n### Which renderer should I use?\n\n**Use `@prerenderer/renderer-puppeteer` if:** You're prerendering up to a couple hundred pages and want accurate results (bye-bye RAM!).\n\n**Use `@prerenderer/renderer-jsdom` if:** You need to prerender thousands upon thousands of pages, but quality isn't all that important, and you're willing to work around issues for more advanced cases. (Programmatic SVG support, etc.)\n\n## Documentation\n\n### Plugin Options\n\n| Option | Type | Required? | Default | Description |\n|-------------|-------------------------------------------|-----------|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| staticDir | String | Yes | None | The root path to serve your app from. |\n| outputDir | String | No | None | Where the prerendered pages should be output. If not set, defaults to staticDir. |\n| indexPath | String | No | `staticDir/index.html` | The index file to fall back on for SPAs. |\n| postProcess | Function(Object context): [Object \\| Promise] | No | None | See the [Using the postProcess Option](#using-the-postprocess-option) section. |\n| minify | Object | No | None | Minifies the resulting HTML using [html-minifier](https://github.com/kangax/html-minifier). Full list of options available [here](https://github.com/kangax/html-minifier#options-quick-reference). |\n| server | Object | No | None | App server configuration options (See below) |\n| renderer | Renderer Instance or Configuration Object | No | `new PuppeteerRenderer()` | The renderer you'd like to use to prerender the app. It's recommended that you specify this, but if not it will default to `@prerenderer/renderer-puppeteer`. |\n\n#### Server Options\n\n| Option | Type    | Required? | Default                    | Description                            |\n|--------|---------|-----------|----------------------------|----------------------------------------|\n| port   | Integer | No        | First free port after 8000 | The port for the app server to run on. |\n| proxy  | Object  | No        | No proxying                | Proxy configuration. Has the same signature as [webpack-dev-server](https://github.com/webpack/docs/wiki/webpack-dev-server#proxy) |\n\n\n#### Using The postProcess Option\n\nThe `postProcess(Object context): Object | Promise` function in your renderer configuration allows you to adjust the output of `prerender-spa-plugin` before writing it to a file. It is called once per rendered route and is passed a `context` object in the form of:\n\n```javascript\n{\n  // The prerendered route, after following redirects.\n  route: String,\n  // The original route passed, before redirects.\n  originalRoute: String,\n  // The resulting HTML for the route.\n  html: String,\n  // The path to write the rendered HTML to.\n  // This is null (automatically calculated after postProcess)\n  // unless explicitly set.\n  outputPath: String || null\n}\n```\n\nYou can modify `context.html` to change what gets written to the prerendered files and/or modify `context.route` or `context.outputPath` to change the output location.\n\nYou are expected to adjust those properties as needed, then return the context object, or a promise that resolves to it like so:\n\n```javascript\npostProcess(context) {\n  // Remove /index.html from the output path if the dir name ends with a .html file extension.\n  // For example: /dist/dir/special.html/index.html -> /dist/dir/special.html\n  if (context.route.endsWith('.html')) {\n    context.outputPath = path.join(__dirname, 'dist', context.route)\n  }\n\n  return context\n}\n\npostProcess(context) {\n  return someAsyncProcessing(context.html)\n    .then((html) => {\n      context.html = html;\n      return context;\n    });\n}\n```\n\n#### Vue.js Notes\nIf you are having issues prerendering with Vue.js, try adding the [`data-server-rendered=\"true\"`](https://ssr.vuejs.org/guide/hydration.html) attribute to your root app element. This will cause Vue to treat your current page as an already-rendered app and update it rather than completely rerendering the whole tree. You can add the attribute using `postProcess` or by manipulating the DOM with JavaScript prior prerendering with `renderAfterDocumentEvent`.\n\n---\n\n### `@prerenderer/renderer-puppeteer` options\n\n| Option                                                                                                                 | Type                                                                                                                                       | Required? | Default                | Description                                                                                                                                                                                                                                                           |\n|------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|-----------|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| maxConcurrentRoutes                                                                                                    | Number                                                                                                                                     | No        | 0 (No limit)           | The number of routes allowed to be rendered at the same time. Useful for breaking down massive batches of routes into smaller chunks.                                                                                                                                 |\n| inject                                                                                                                 | Object                                                                                                                                     | No        | None                   | An object to inject into the global scope of the rendered page before it finishes loading. Must be `JSON.stringifiy`-able. The property injected to is `window['__PRERENDER_INJECTED']` by default.                                                                   |\n| injectProperty                                                                                                         | String                                                                                                                                     | No        | `__PRERENDER_INJECTED` | The property to mount `inject` to during rendering.                                                                                                                                                                                                                   |\n| renderAfterDocumentEvent                                                                                               | String                                                                                                                                     | No        | None                   | Wait to render until the specified event is fired on the document. (You can fire an event like so: `document.dispatchEvent(new Event('custom-render-trigger'))`                                                                                                       |\n| renderAfterElementExists                                                                                               | String (Selector)                                                                                                                          | No        | None                   | Wait to render until the specified element is detected using `document.querySelector`                                                                                                                                                                                 |\n| renderAfterTime                                                                                                        | Integer (Milliseconds)                                                                                                                     | No        | None                   | Wait to render until a certain amount of time has passed.                                                                                                                                                                                                             |\n| skipThirdPartyRequests                                                                                                 | Boolean                                                                                                                                    | No        | `false`                | Automatically block any third-party requests. (This can make your pages load faster by not loading non-essential scripts, styles, or fonts.)                                                                                                                          |\n| consoleHandler                                                                                                         | function(route: String, message: [ConsoleMessage](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-consolemessage)) | No        | None                   | Allows you to provide a custom console.* handler for pages. Argument one to your function is the route being rendered, argument two is the [Puppeteer ConsoleMessage](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-consolemessage) object. |\n| [[Puppeteer Launch Options]](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions) | ?                                                                                                                                          | No        | None                   | Any additional options will be passed to `puppeteer.launch()`, such as `headless: false`.                                                                                                                                                                             |\n\n---\n\n### `@prerenderer/renderer-jsdom` options\n\n| Option                   | Type                   | Required? | Default                  | Description                                                                                                                                                                                         |\n|--------------------------|------------------------|-----------|--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| maxConcurrentRoutes      | Number                 | No        | 0 (No limit)             | The number of routes allowed to be rendered at the same time. Useful for breaking down massive batches of routes into smaller chunks.                                                               |\n| inject                   | Object                 | No        | None                     | An object to inject into the global scope of the rendered page before it finishes loading. Must be `JSON.stringifiy`-able. The property injected to is `window['__PRERENDER_INJECTED']` by default. |\n| injectProperty           | String                 | No        | `__PRERENDER_INJECTED` | The property to mount `inject` to during rendering.                                                                                                                                                 |\n| renderAfterDocumentEvent | String                 | No        | None                     | Wait to render until the specified event is fired on the document. (You can fire an event like so: `document.dispatchEvent(new Event('custom-render-trigger'))`                                     |\n| renderAfterElementExists | String (Selector)      | No        | None                     | Wait to render until the specified element is detected using `document.querySelector`                                                                                                               |\n| renderAfterTime          | Integer (Milliseconds) | No        | None                     | Wait to render until a certain amount of time has passed.                                                                                                                                           |\n\n---\n\n## Tips & Troubleshooting\n\n### JS not firing before prerender?\n\nIf you have code that relies on the existence of `<body>` (and you almost certainly do), simply run it in a callback to the `DOMContentLoaded` event:\n*(Otherwise you'll find that `prerender-spa-plugin` will output the contents of your page before your JS runs.)*\n\n```js\ndocument.addEventListener('DOMContentLoaded', function () {\n  // your code\n})\n```\n\nFor example, if you're using Vue.js and mounting to a `<div id=\"app\">` in `<body>`:\n\n``` js\nconst root = new Vue({\n  // ...\n})\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  root.$mount('#app')\n})\n```\n\n### Inline Styles\n\nIf you rely on inline CSS, i.e. you do not extract CSS from your bundle and, thus, experience duplicate CSS style tags, consider using [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) to extract CSS into a separate file and then either inject CSS back into a `template.html` file using [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) or just call it as an external CSS file.\n\nEither way, there will not be any unnecessary styles inside JS.\n\n### Caveats\n\n- For obvious reasons, `prerender-spa-plugin` only works for SPAs that route using the HTML5 history API. `index.html#/hash/route` URLs will unfortunately not work.\n- Whatever client-side rendering library you're using should be able to at least replace any server-rendered content or diff with it.\n  - For **Vue.js 1** use [`replace: false`](http://vuejs.org/api/#replace) on root components.\n  - For **Vue.js 2**  Ensure your root component has the same id as the prerendered element it's replacing. Otherwise you'll end up with duplicated content.\n\n---\n\n## Alternatives\n\n- [react-snap](https://github.com/stereobooster/react-snap) - Zero-configuration framework-agnostic prerendering. Does not depend on webpack. Handles a variety of edge-cases.\n- [snapshotify](https://github.com/errorception/snapshotify) - An experimental prerenderer that performes a number of speed optimizations.\n- [presite](https://github.com/egoist/presite) - Minimal-configuration framework-agnostic prerendering.\n- [prerenderer](https://github.com/tribex/prerenderer) - Pluggable prerendering library that `prerender-spa-plugin` `v3+` is based on.\n\n## License (MIT)\n\n```\nCopyright (c) 2017 Chris Fritz\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n\n## Maintainers\n\n<table>\n  <tbody>\n    <tr>\n      <td align=\"center\">\n        <a href=\"https://github.com/chrisvfritz\">\n          <img width=\"150\" height=\"150\" src=\"https://github.com/chrisvfritz.png?v=3&s=150\">\n          </br>\n          Chris Fritz\n        </a>\n      </td>\n      <td align=\"center\">\n        <a href=\"https://github.com/drewlustro\">\n          <img width=\"150\" height=\"150\" src=\"https://github.com/drewlustro.png?v=3&s=150\">\n          </br>\n          Drew Lustro\n        </a>\n      </td>\n      <td align=\"center\">\n        <a href=\"https://github.com/tribex\">\n          <img width=\"150\" height=\"150\" src=\"https://github.com/tribex.png?v=3&s=150\">\n          </br>\n          Joshua Bemenderfer\n        </a>\n      </td>\n    </tr>\n  <tbody>\n</table>\n"
  },
  {
    "path": "es5-autogenerated/index.js",
    "content": "'use strict';\n\nvar path = require('path');\nvar Prerenderer = require('@prerenderer/prerenderer');\nvar PuppeteerRenderer = require('@prerenderer/renderer-puppeteer');\n\nvar _require = require('html-minifier'),\n    minify = _require.minify;\n\nfunction PrerenderSPAPlugin() {\n  var _this = this;\n\n  var rendererOptions = {}; // Primarily for backwards-compatibility.\n\n  this._options = {};\n\n  // Normal args object.\n\n  for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {\n    args[_key] = arguments[_key];\n  }\n\n  if (args.length === 1) {\n    this._options = args[0] || {};\n\n    // Backwards-compatibility with v2\n  } else {\n    console.warn(\"[prerender-spa-plugin] You appear to be using the v2 argument-based configuration options. It's recommended that you migrate to the clearer object-based configuration system.\\nCheck the documentation for more information.\");\n    var staticDir = void 0,\n        routes = void 0;\n\n    args.forEach(function (arg) {\n      if (typeof arg === 'string') staticDir = arg;else if (Array.isArray(arg)) routes = arg;else if (typeof arg === 'object') _this._options = arg;\n    });\n\n    staticDir ? this._options.staticDir = staticDir : null;\n    routes ? this._options.routes = routes : null;\n  }\n\n  // Backwards compatiblity with v2.\n  if (this._options.captureAfterDocumentEvent) {\n    console.warn('[prerender-spa-plugin] captureAfterDocumentEvent has been renamed to renderAfterDocumentEvent and should be moved to the renderer options.');\n    rendererOptions.renderAfterDocumentEvent = this._options.captureAfterDocumentEvent;\n  }\n\n  if (this._options.captureAfterElementExists) {\n    console.warn('[prerender-spa-plugin] captureAfterElementExists has been renamed to renderAfterElementExists and should be moved to the renderer options.');\n    rendererOptions.renderAfterElementExists = this._options.captureAfterElementExists;\n  }\n\n  if (this._options.captureAfterTime) {\n    console.warn('[prerender-spa-plugin] captureAfterTime has been renamed to renderAfterTime and should be moved to the renderer options.');\n    rendererOptions.renderAfterTime = this._options.captureAfterTime;\n  }\n\n  this._options.server = this._options.server || {};\n  this._options.renderer = this._options.renderer || new PuppeteerRenderer(Object.assign({}, { headless: true }, rendererOptions));\n\n  if (this._options.postProcessHtml) {\n    console.warn('[prerender-spa-plugin] postProcessHtml should be migrated to postProcess! Consult the documentation for more information.');\n  }\n}\n\nPrerenderSPAPlugin.prototype.apply = function (compiler) {\n  var _this2 = this;\n\n  var compilerFS = compiler.outputFileSystem;\n\n  // From https://github.com/ahmadnassri/mkdirp-promise/blob/master/lib/index.js\n  var mkdirp = function mkdirp(dir, opts) {\n    return new Promise(function (resolve, reject) {\n      compilerFS.mkdirp(dir, opts, function (err, made) {\n        return err === null ? resolve(made) : reject(err);\n      });\n    });\n  };\n\n  var afterEmit = function afterEmit(compilation, done) {\n    var PrerendererInstance = new Prerenderer(_this2._options);\n\n    PrerendererInstance.initialize().then(function () {\n      return PrerendererInstance.renderRoutes(_this2._options.routes || []);\n    })\n    // Backwards-compatibility with v2 (postprocessHTML should be migrated to postProcess)\n    .then(function (renderedRoutes) {\n      return _this2._options.postProcessHtml ? renderedRoutes.map(function (renderedRoute) {\n        var processed = _this2._options.postProcessHtml(renderedRoute);\n        if (typeof processed === 'string') renderedRoute.html = processed;else renderedRoute = processed;\n\n        return renderedRoute;\n      }) : renderedRoutes;\n    })\n    // Run postProcess hooks.\n    .then(function (renderedRoutes) {\n      return _this2._options.postProcess ? Promise.all(renderedRoutes.map(function (renderedRoute) {\n        return _this2._options.postProcess(renderedRoute);\n      })) : renderedRoutes;\n    })\n    // Check to ensure postProcess hooks returned the renderedRoute object properly.\n    .then(function (renderedRoutes) {\n      var isValid = renderedRoutes.every(function (r) {\n        return typeof r === 'object';\n      });\n      if (!isValid) {\n        throw new Error('[prerender-spa-plugin] Rendered routes are empty, did you forget to return the `context` object in postProcess?');\n      }\n\n      return renderedRoutes;\n    })\n    // Minify html files if specified in config.\n    .then(function (renderedRoutes) {\n      if (!_this2._options.minify) return renderedRoutes;\n\n      renderedRoutes.forEach(function (route) {\n        route.html = minify(route.html, _this2._options.minify);\n      });\n\n      return renderedRoutes;\n    })\n    // Calculate outputPath if it hasn't been set already.\n    .then(function (renderedRoutes) {\n      renderedRoutes.forEach(function (rendered) {\n        if (!rendered.outputPath) {\n          rendered.outputPath = path.join(_this2._options.outputDir || _this2._options.staticDir, rendered.route, 'index.html');\n        }\n      });\n\n      return renderedRoutes;\n    })\n    // Create dirs and write prerendered files.\n    .then(function (processedRoutes) {\n      var promises = Promise.all(processedRoutes.map(function (processedRoute) {\n        return mkdirp(path.dirname(processedRoute.outputPath)).then(function () {\n          return new Promise(function (resolve, reject) {\n            compilerFS.writeFile(processedRoute.outputPath, processedRoute.html.trim(), function (err) {\n              if (err) reject(`[prerender-spa-plugin] Unable to write rendered route to file \"${processedRoute.outputPath}\" \\n ${err}.`);else resolve();\n            });\n          });\n        }).catch(function (err) {\n          if (typeof err === 'string') {\n            err = `[prerender-spa-plugin] Unable to create directory ${path.dirname(processedRoute.outputPath)} for route ${processedRoute.route}. \\n ${err}`;\n          }\n\n          throw err;\n        });\n      }));\n\n      return promises;\n    }).then(function (r) {\n      PrerendererInstance.destroy();\n      done();\n    }).catch(function (err) {\n      PrerendererInstance.destroy();\n      var msg = '[prerender-spa-plugin] Unable to prerender all routes!';\n      console.error(msg);\n      compilation.errors.push(new Error(msg));\n      done();\n    });\n  };\n\n  if (compiler.hooks) {\n    var plugin = { name: 'PrerenderSPAPlugin' };\n    compiler.hooks.afterEmit.tapAsync(plugin, afterEmit);\n  } else {\n    compiler.plugin('after-emit', afterEmit);\n  }\n};\n\nPrerenderSPAPlugin.PuppeteerRenderer = PuppeteerRenderer;\n\nmodule.exports = PrerenderSPAPlugin;"
  },
  {
    "path": "es6/index.js",
    "content": "const path = require('path')\nconst Prerenderer = require('@prerenderer/prerenderer')\nconst PuppeteerRenderer = require('@prerenderer/renderer-puppeteer')\nconst { minify } = require('html-minifier')\n\nfunction PrerenderSPAPlugin (...args) {\n  const rendererOptions = {} // Primarily for backwards-compatibility.\n\n  this._options = {}\n\n  // Normal args object.\n  if (args.length === 1) {\n    this._options = args[0] || {}\n\n  // Backwards-compatibility with v2\n  } else {\n    console.warn(\"[prerender-spa-plugin] You appear to be using the v2 argument-based configuration options. It's recommended that you migrate to the clearer object-based configuration system.\\nCheck the documentation for more information.\")\n    let staticDir, routes\n\n    args.forEach(arg => {\n      if (typeof arg === 'string') staticDir = arg\n      else if (Array.isArray(arg)) routes = arg\n      else if (typeof arg === 'object') this._options = arg\n    })\n\n    staticDir ? this._options.staticDir = staticDir : null\n    routes ? this._options.routes = routes : null\n  }\n\n  // Backwards compatiblity with v2.\n  if (this._options.captureAfterDocumentEvent) {\n    console.warn('[prerender-spa-plugin] captureAfterDocumentEvent has been renamed to renderAfterDocumentEvent and should be moved to the renderer options.')\n    rendererOptions.renderAfterDocumentEvent = this._options.captureAfterDocumentEvent\n  }\n\n  if (this._options.captureAfterElementExists) {\n    console.warn('[prerender-spa-plugin] captureAfterElementExists has been renamed to renderAfterElementExists and should be moved to the renderer options.')\n    rendererOptions.renderAfterElementExists = this._options.captureAfterElementExists\n  }\n\n  if (this._options.captureAfterTime) {\n    console.warn('[prerender-spa-plugin] captureAfterTime has been renamed to renderAfterTime and should be moved to the renderer options.')\n    rendererOptions.renderAfterTime = this._options.captureAfterTime\n  }\n\n  this._options.server = this._options.server || {}\n  this._options.renderer = this._options.renderer || new PuppeteerRenderer(Object.assign({}, { headless: true }, rendererOptions))\n\n  if (this._options.postProcessHtml) {\n    console.warn('[prerender-spa-plugin] postProcessHtml should be migrated to postProcess! Consult the documentation for more information.')\n  }\n}\n\nPrerenderSPAPlugin.prototype.apply = function (compiler) {\n  const compilerFS = compiler.outputFileSystem\n\n  // From https://github.com/ahmadnassri/mkdirp-promise/blob/master/lib/index.js\n  const mkdirp = function (dir, opts) {\n    return new Promise((resolve, reject) => {\n      compilerFS.mkdirp(dir, opts, (err, made) => err === null ? resolve(made) : reject(err))\n    })\n  }\n\n  const afterEmit = (compilation, done) => {\n    const PrerendererInstance = new Prerenderer(this._options)\n\n    PrerendererInstance.initialize()\n      .then(() => {\n        return PrerendererInstance.renderRoutes(this._options.routes || [])\n      })\n      // Backwards-compatibility with v2 (postprocessHTML should be migrated to postProcess)\n      .then(renderedRoutes => this._options.postProcessHtml\n        ? renderedRoutes.map(renderedRoute => {\n          const processed = this._options.postProcessHtml(renderedRoute)\n          if (typeof processed === 'string') renderedRoute.html = processed\n          else renderedRoute = processed\n\n          return renderedRoute\n        })\n        : renderedRoutes\n      )\n      // Run postProcess hooks.\n      .then(renderedRoutes => this._options.postProcess\n        ? Promise.all(renderedRoutes.map(renderedRoute => this._options.postProcess(renderedRoute)))\n        : renderedRoutes\n      )\n      // Check to ensure postProcess hooks returned the renderedRoute object properly.\n      .then(renderedRoutes => {\n        const isValid = renderedRoutes.every(r => typeof r === 'object')\n        if (!isValid) {\n          throw new Error('[prerender-spa-plugin] Rendered routes are empty, did you forget to return the `context` object in postProcess?')\n        }\n\n        return renderedRoutes\n      })\n      // Minify html files if specified in config.\n      .then(renderedRoutes => {\n        if (!this._options.minify) return renderedRoutes\n\n        renderedRoutes.forEach(route => {\n          route.html = minify(route.html, this._options.minify)\n        })\n\n        return renderedRoutes\n      })\n      // Calculate outputPath if it hasn't been set already.\n      .then(renderedRoutes => {\n        renderedRoutes.forEach(rendered => {\n          if (!rendered.outputPath) {\n            rendered.outputPath = path.join(this._options.outputDir || this._options.staticDir, rendered.route, 'index.html')\n          }\n        })\n\n        return renderedRoutes\n      })\n      // Create dirs and write prerendered files.\n      .then(processedRoutes => {\n        const promises = Promise.all(processedRoutes.map(processedRoute => {\n          return mkdirp(path.dirname(processedRoute.outputPath))\n            .then(() => {\n              return new Promise((resolve, reject) => {\n                compilerFS.writeFile(processedRoute.outputPath, processedRoute.html.trim(), err => {\n                  if (err) reject(`[prerender-spa-plugin] Unable to write rendered route to file \"${processedRoute.outputPath}\" \\n ${err}.`)\n                  else resolve()\n                })\n              })\n            })\n            .catch(err => {\n              if (typeof err === 'string') {\n                err = `[prerender-spa-plugin] Unable to create directory ${path.dirname(processedRoute.outputPath)} for route ${processedRoute.route}. \\n ${err}`\n              }\n\n              throw err\n            })\n        }))\n\n        return promises\n      })\n      .then(r => {\n        PrerendererInstance.destroy()\n        done()\n      })\n      .catch(err => {\n        PrerendererInstance.destroy()\n        const msg = '[prerender-spa-plugin] Unable to prerender all routes!'\n        console.error(msg)\n        compilation.errors.push(new Error(msg))\n        done()\n      })\n  }\n\n  if (compiler.hooks) {\n    const plugin = { name: 'PrerenderSPAPlugin' }\n    compiler.hooks.afterEmit.tapAsync(plugin, afterEmit)\n  } else {\n    compiler.plugin('after-emit', afterEmit)\n  }\n}\n\nPrerenderSPAPlugin.PuppeteerRenderer = PuppeteerRenderer\n\nmodule.exports = PrerenderSPAPlugin\n"
  },
  {
    "path": "examples/angular-cli-eject/.angular-cli.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"project\": {\n    \"name\": \"angular\",\n    \"ejected\": true\n  },\n  \"apps\": [\n    {\n      \"root\": \"src\",\n      \"outDir\": \"dist\",\n      \"assets\": [\n        \"assets\",\n        \"favicon.ico\"\n      ],\n      \"index\": \"index.html\",\n      \"main\": \"main.ts\",\n      \"polyfills\": \"polyfills.ts\",\n      \"test\": \"test.ts\",\n      \"tsconfig\": \"tsconfig.app.json\",\n      \"testTsconfig\": \"tsconfig.spec.json\",\n      \"prefix\": \"app\",\n      \"styles\": [\n        \"styles.css\"\n      ],\n      \"scripts\": [],\n      \"environmentSource\": \"environments/environment.ts\",\n      \"environments\": {\n        \"dev\": \"environments/environment.ts\",\n        \"prod\": \"environments/environment.prod.ts\"\n      }\n    }\n  ],\n  \"e2e\": {\n    \"protractor\": {\n      \"config\": \"./protractor.conf.js\"\n    }\n  },\n  \"lint\": [\n    {\n      \"project\": \"src/tsconfig.app.json\",\n      \"exclude\": \"**/node_modules/**\"\n    },\n    {\n      \"project\": \"src/tsconfig.spec.json\",\n      \"exclude\": \"**/node_modules/**\"\n    },\n    {\n      \"project\": \"e2e/tsconfig.e2e.json\",\n      \"exclude\": \"**/node_modules/**\"\n    }\n  ],\n  \"test\": {\n    \"karma\": {\n      \"config\": \"./karma.conf.js\"\n    }\n  },\n  \"defaults\": {\n    \"styleExt\": \"css\",\n    \"component\": {\n    }\n  }\n}\n"
  },
  {
    "path": "examples/angular-cli-eject/.editorconfig",
    "content": "# Editor configuration, see http://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.md]\nmax_line_length = off\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": "examples/angular-cli-eject/.gitignore",
    "content": "# See http://help.github.com/ignore-files/ for more about ignoring files.\n\n# compiled output\n/dist\n/dist-server\n/tmp\n/out-tsc\n\n# dependencies\n/node_modules\n\n# IDEs and editors\n/.idea\n.project\n.classpath\n.c9/\n*.launch\n.settings/\n*.sublime-workspace\n\n# IDE - VSCode\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n\n# misc\n/.sass-cache\n/connect.lock\n/coverage\n/libpeerconnection.log\nnpm-debug.log\ntestem.log\n/typings\n\n# e2e\n/e2e/*.js\n/e2e/*.map\n\n# System Files\n.DS_Store\nThumbs.db\n"
  },
  {
    "path": "examples/angular-cli-eject/README.md",
    "content": "# Ejected Angular CLI App - Prerender SPA Example\n\nThis project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.7.0.\n\n## Build\n\n```bash\nnpm install\nnpm run build\n```\n\nNow check the new `build` directory for your prerendered static files!\n\nTo view the rendered files, install [http-server](https://www.npmjs.com/package/http-server) (`npm install -g http-server`) if you haven't already and run it in the dist directory.\n\nNow visit the following route in your browser (note the trailing slash):\n\n- [http://localhost:8000/](http://localhost:8000/)\n\nIf all went well, it should load without JavaScript.\n\n## Development\n\nTo edit the `prerender-spa-plugin` configuration, look for `new PrerenderSPAPlugin` in the plugins section of `webpack.config.js`.\n\nIf you're using a router or have more than one page to prerender, edit the `routes` array under that config object.\n\n```bash\nnpm install\nnpm start\n```\n"
  },
  {
    "path": "examples/angular-cli-eject/e2e/app.e2e-spec.ts",
    "content": "import { AppPage } from './app.po';\n\ndescribe('angular App', () => {\n  let page: AppPage;\n\n  beforeEach(() => {\n    page = new AppPage();\n  });\n\n  it('should display welcome message', () => {\n    page.navigateTo();\n    expect(page.getParagraphText()).toEqual('Welcome to app!');\n  });\n});\n"
  },
  {
    "path": "examples/angular-cli-eject/e2e/app.po.ts",
    "content": "import { browser, by, element } from 'protractor';\n\nexport class AppPage {\n  navigateTo() {\n    return browser.get('/');\n  }\n\n  getParagraphText() {\n    return element(by.css('app-root h1')).getText();\n  }\n}\n"
  },
  {
    "path": "examples/angular-cli-eject/e2e/tsconfig.e2e.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../out-tsc/e2e\",\n    \"baseUrl\": \"./\",\n    \"module\": \"commonjs\",\n    \"target\": \"es5\",\n    \"types\": [\n      \"jasmine\",\n      \"jasminewd2\",\n      \"node\"\n    ]\n  }\n}\n"
  },
  {
    "path": "examples/angular-cli-eject/karma.conf.js",
    "content": "// Karma configuration file, see link for more information\n// https://karma-runner.github.io/1.0/config/configuration-file.html\n\nmodule.exports = function (config) {\n  config.set({\n    basePath: '',\n    frameworks: ['jasmine', '@angular/cli'],\n    plugins: [\n      require('karma-jasmine'),\n      require('karma-chrome-launcher'),\n      require('karma-jasmine-html-reporter'),\n      require('karma-coverage-istanbul-reporter'),\n      require('@angular/cli/plugins/karma')\n    ],\n    client:{\n      clearContext: false // leave Jasmine Spec Runner output visible in browser\n    },\n    coverageIstanbulReporter: {\n      reports: [ 'html', 'lcovonly' ],\n      fixWebpackSourcePaths: true\n    },\n    angularCli: {\n      environment: 'dev'\n    },\n    reporters: ['progress', 'kjhtml'],\n    port: 9876,\n    colors: true,\n    logLevel: config.LOG_INFO,\n    autoWatch: true,\n    browsers: ['Chrome'],\n    singleRun: false\n  });\n};\n"
  },
  {
    "path": "examples/angular-cli-eject/package.json",
    "content": "{\n  \"name\": \"prerender-spa-plugin-example-angular-cli-eject\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"webpack-dev-server --port=4200\",\n    \"build\": \"webpack\",\n    \"test\": \"karma start ./karma.conf.js\",\n    \"lint\": \"ng lint\",\n    \"e2e\": \"protractor ./protractor.conf.js\",\n    \"pree2e\": \"webdriver-manager update --standalone false --gecko false --quiet\"\n  },\n  \"dependencies\": {\n    \"@angular/animations\": \"^5.2.0\",\n    \"@angular/common\": \"^5.2.0\",\n    \"@angular/compiler\": \"^5.2.0\",\n    \"@angular/core\": \"^5.2.0\",\n    \"@angular/forms\": \"^5.2.0\",\n    \"@angular/http\": \"^5.2.0\",\n    \"@angular/platform-browser\": \"^5.2.0\",\n    \"@angular/platform-browser-dynamic\": \"^5.2.0\",\n    \"@angular/router\": \"^5.2.0\",\n    \"core-js\": \"^2.4.1\",\n    \"rxjs\": \"^5.5.6\",\n    \"zone.js\": \"^0.8.19\"\n  },\n  \"devDependencies\": {\n    \"@angular-devkit/core\": \"0.3.1\",\n    \"@angular/cli\": \"~1.7.0\",\n    \"@angular/compiler-cli\": \"^5.2.0\",\n    \"@angular/language-service\": \"^5.2.0\",\n    \"@ngtools/webpack\": \"1.10.0\",\n    \"@types/jasmine\": \"~2.8.3\",\n    \"@types/jasminewd2\": \"~2.0.2\",\n    \"@types/node\": \"~6.0.60\",\n    \"autoprefixer\": \"^7.2.3\",\n    \"circular-dependency-plugin\": \"^4.2.1\",\n    \"codelyzer\": \"^4.0.1\",\n    \"copy-webpack-plugin\": \"~4.4.1\",\n    \"file-loader\": \"^1.1.5\",\n    \"html-webpack-plugin\": \"^2.29.0\",\n    \"istanbul-instrumenter-loader\": \"^3.0.0\",\n    \"jasmine-core\": \"~2.8.0\",\n    \"jasmine-spec-reporter\": \"~4.2.1\",\n    \"karma\": \"~2.0.0\",\n    \"karma-chrome-launcher\": \"~2.2.0\",\n    \"karma-coverage-istanbul-reporter\": \"^1.2.1\",\n    \"karma-jasmine\": \"~1.1.0\",\n    \"karma-jasmine-html-reporter\": \"^0.2.2\",\n    \"less-loader\": \"^4.0.5\",\n    \"postcss-import\": \"^11.0.0\",\n    \"postcss-loader\": \"^2.0.10\",\n    \"postcss-url\": \"^7.1.2\",\n    \"prerender-spa-plugin\": \"^3.0.0\",\n    \"protractor\": \"~5.1.2\",\n    \"raw-loader\": \"^0.5.1\",\n    \"sass-loader\": \"^6.0.6\",\n    \"style-loader\": \"^0.19.1\",\n    \"stylus-loader\": \"^3.0.1\",\n    \"ts-node\": \"~4.1.0\",\n    \"tslint\": \"~5.9.1\",\n    \"typescript\": \"~2.5.3\",\n    \"uglifyjs-webpack-plugin\": \"^1.1.8\",\n    \"url-loader\": \"^0.6.2\",\n    \"webpack\": \"~3.11.0\",\n    \"webpack-dev-server\": \"~2.11.0\"\n  }\n}\n"
  },
  {
    "path": "examples/angular-cli-eject/protractor.conf.js",
    "content": "// Protractor configuration file, see link for more information\n// https://github.com/angular/protractor/blob/master/lib/config.ts\n\nconst { SpecReporter } = require('jasmine-spec-reporter');\n\nexports.config = {\n  allScriptsTimeout: 11000,\n  specs: [\n    './e2e/**/*.e2e-spec.ts'\n  ],\n  capabilities: {\n    'browserName': 'chrome'\n  },\n  directConnect: true,\n  baseUrl: 'http://localhost:4200/',\n  framework: 'jasmine',\n  jasmineNodeOpts: {\n    showColors: true,\n    defaultTimeoutInterval: 30000,\n    print: function() {}\n  },\n  onPrepare() {\n    require('ts-node').register({\n      project: 'e2e/tsconfig.e2e.json'\n    });\n    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));\n  }\n};\n"
  },
  {
    "path": "examples/angular-cli-eject/src/app/app.component.css",
    "content": ""
  },
  {
    "path": "examples/angular-cli-eject/src/app/app.component.html",
    "content": "<!--The content below is only a placeholder and can be replaced.-->\n<div style=\"text-align:center\">\n  <h1>\n    Welcome to {{ title }}!\n  </h1>\n  <img width=\"300\" alt=\"Angular Logo\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==\">\n</div>\n<h2>Here are some links to help you start: </h2>\n<ul>\n  <li>\n    <h2><a target=\"_blank\" rel=\"noopener\" href=\"https://angular.io/tutorial\">Tour of Heroes</a></h2>\n  </li>\n  <li>\n    <h2><a target=\"_blank\" rel=\"noopener\" href=\"https://github.com/angular/angular-cli/wiki\">CLI Documentation</a></h2>\n  </li>\n  <li>\n    <h2><a target=\"_blank\" rel=\"noopener\" href=\"https://blog.angular.io/\">Angular blog</a></h2>\n  </li>\n</ul>\n\n"
  },
  {
    "path": "examples/angular-cli-eject/src/app/app.component.spec.ts",
    "content": "import { TestBed, async } from '@angular/core/testing';\nimport { AppComponent } from './app.component';\ndescribe('AppComponent', () => {\n  beforeEach(async(() => {\n    TestBed.configureTestingModule({\n      declarations: [\n        AppComponent\n      ],\n    }).compileComponents();\n  }));\n  it('should create the app', async(() => {\n    const fixture = TestBed.createComponent(AppComponent);\n    const app = fixture.debugElement.componentInstance;\n    expect(app).toBeTruthy();\n  }));\n  it(`should have as title 'app'`, async(() => {\n    const fixture = TestBed.createComponent(AppComponent);\n    const app = fixture.debugElement.componentInstance;\n    expect(app.title).toEqual('app');\n  }));\n  it('should render title in a h1 tag', async(() => {\n    const fixture = TestBed.createComponent(AppComponent);\n    fixture.detectChanges();\n    const compiled = fixture.debugElement.nativeElement;\n    expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');\n  }));\n});\n"
  },
  {
    "path": "examples/angular-cli-eject/src/app/app.component.ts",
    "content": "import { Component } from '@angular/core';\n\n@Component({\n  selector: 'app-root',\n  templateUrl: './app.component.html',\n  styleUrls: ['./app.component.css']\n})\nexport class AppComponent {\n  title = 'app';\n}\n"
  },
  {
    "path": "examples/angular-cli-eject/src/app/app.module.ts",
    "content": "import { BrowserModule } from '@angular/platform-browser';\nimport { NgModule } from '@angular/core';\n\n\nimport { AppComponent } from './app.component';\n\n\n@NgModule({\n  declarations: [\n    AppComponent\n  ],\n  imports: [\n    BrowserModule\n  ],\n  providers: [],\n  bootstrap: [AppComponent]\n})\nexport class AppModule { }\n"
  },
  {
    "path": "examples/angular-cli-eject/src/assets/.gitkeep",
    "content": ""
  },
  {
    "path": "examples/angular-cli-eject/src/environments/environment.prod.ts",
    "content": "export const environment = {\n  production: true\n};\n"
  },
  {
    "path": "examples/angular-cli-eject/src/environments/environment.ts",
    "content": "// The file contents for the current environment will overwrite these during build.\n// The build system defaults to the dev environment which uses `environment.ts`, but if you do\n// `ng build --env=prod` then `environment.prod.ts` will be used instead.\n// The list of which env maps to which file can be found in `.angular-cli.json`.\n\nexport const environment = {\n  production: false\n};\n"
  },
  {
    "path": "examples/angular-cli-eject/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>Angular</title>\n  <base href=\"/\">\n\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n  <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\">\n</head>\n<body>\n  <app-root></app-root>\n</body>\n</html>\n"
  },
  {
    "path": "examples/angular-cli-eject/src/main.ts",
    "content": "import { enableProdMode } from '@angular/core';\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\n\nimport { AppModule } from './app/app.module';\nimport { environment } from './environments/environment';\n\nif (environment.production) {\n  enableProdMode();\n}\n\nplatformBrowserDynamic().bootstrapModule(AppModule)\n  .catch(err => console.log(err));\n"
  },
  {
    "path": "examples/angular-cli-eject/src/polyfills.ts",
    "content": "/**\n * This file includes polyfills needed by Angular and is loaded before the app.\n * You can add your own extra polyfills to this file.\n *\n * This file is divided into 2 sections:\n *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.\n *   2. Application imports. Files imported after ZoneJS that should be loaded before your main\n *      file.\n *\n * The current setup is for so-called \"evergreen\" browsers; the last versions of browsers that\n * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),\n * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.\n *\n * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html\n */\n\n/***************************************************************************************************\n * BROWSER POLYFILLS\n */\n\n/** IE9, IE10 and IE11 requires all of the following polyfills. **/\n// import 'core-js/es6/symbol';\n// import 'core-js/es6/object';\n// import 'core-js/es6/function';\n// import 'core-js/es6/parse-int';\n// import 'core-js/es6/parse-float';\n// import 'core-js/es6/number';\n// import 'core-js/es6/math';\n// import 'core-js/es6/string';\n// import 'core-js/es6/date';\n// import 'core-js/es6/array';\n// import 'core-js/es6/regexp';\n// import 'core-js/es6/map';\n// import 'core-js/es6/weak-map';\n// import 'core-js/es6/set';\n\n/** IE10 and IE11 requires the following for NgClass support on SVG elements */\n// import 'classlist.js';  // Run `npm install --save classlist.js`.\n\n/** IE10 and IE11 requires the following for the Reflect API. */\n// import 'core-js/es6/reflect';\n\n\n/** Evergreen browsers require these. **/\n// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.\nimport 'core-js/es7/reflect';\n\n\n/**\n * Required to support Web Animations `@angular/platform-browser/animations`.\n * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation\n **/\n// import 'web-animations-js';  // Run `npm install --save web-animations-js`.\n\n/**\n * By default, zone.js will patch all possible macroTask and DomEvents\n * user can disable parts of macroTask/DomEvents patch by setting following flags\n */\n\n // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame\n // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick\n // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames\n\n /*\n * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js\n * with the following flag, it will bypass `zone.js` patch for IE/Edge\n */\n// (window as any).__Zone_enable_cross_context_check = true;\n\n/***************************************************************************************************\n * Zone JS is required by default for Angular itself.\n */\nimport 'zone.js/dist/zone';  // Included with Angular CLI.\n\n\n\n/***************************************************************************************************\n * APPLICATION IMPORTS\n */\n"
  },
  {
    "path": "examples/angular-cli-eject/src/styles.css",
    "content": "/* You can add global styles to this file, and also import other style files */\n"
  },
  {
    "path": "examples/angular-cli-eject/src/test.ts",
    "content": "// This file is required by karma.conf.js and loads recursively all the .spec and framework files\n\nimport 'zone.js/dist/zone-testing';\nimport { getTestBed } from '@angular/core/testing';\nimport {\n  BrowserDynamicTestingModule,\n  platformBrowserDynamicTesting\n} from '@angular/platform-browser-dynamic/testing';\n\ndeclare const require: any;\n\n// First, initialize the Angular testing environment.\ngetTestBed().initTestEnvironment(\n  BrowserDynamicTestingModule,\n  platformBrowserDynamicTesting()\n);\n// Then we find all the tests.\nconst context = require.context('./', true, /\\.spec\\.ts$/);\n// And load the modules.\ncontext.keys().map(context);\n"
  },
  {
    "path": "examples/angular-cli-eject/src/tsconfig.app.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../out-tsc/app\",\n    \"baseUrl\": \"./\",\n    \"module\": \"es2015\",\n    \"types\": []\n  },\n  \"exclude\": [\n    \"test.ts\",\n    \"**/*.spec.ts\"\n  ]\n}\n"
  },
  {
    "path": "examples/angular-cli-eject/src/tsconfig.spec.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../out-tsc/spec\",\n    \"baseUrl\": \"./\",\n    \"module\": \"commonjs\",\n    \"types\": [\n      \"jasmine\",\n      \"node\"\n    ]\n  },\n  \"files\": [\n    \"test.ts\"\n  ],\n  \"include\": [\n    \"**/*.spec.ts\",\n    \"**/*.d.ts\"\n  ]\n}\n"
  },
  {
    "path": "examples/angular-cli-eject/src/typings.d.ts",
    "content": "/* SystemJS module definition */\ndeclare var module: NodeModule;\ninterface NodeModule {\n  id: string;\n}\n"
  },
  {
    "path": "examples/angular-cli-eject/tsconfig.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/out-tsc\",\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"moduleResolution\": \"node\",\n    \"emitDecoratorMetadata\": true,\n    \"experimentalDecorators\": true,\n    \"target\": \"es5\",\n    \"typeRoots\": [\n      \"node_modules/@types\"\n    ],\n    \"lib\": [\n      \"es2017\",\n      \"dom\"\n    ]\n  }\n}\n"
  },
  {
    "path": "examples/angular-cli-eject/tslint.json",
    "content": "{\n  \"rulesDirectory\": [\n    \"node_modules/codelyzer\"\n  ],\n  \"rules\": {\n    \"arrow-return-shorthand\": true,\n    \"callable-types\": true,\n    \"class-name\": true,\n    \"comment-format\": [\n      true,\n      \"check-space\"\n    ],\n    \"curly\": true,\n    \"deprecation\": {\n      \"severity\": \"warn\"\n    },\n    \"eofline\": true,\n    \"forin\": true,\n    \"import-blacklist\": [\n      true,\n      \"rxjs\",\n      \"rxjs/Rx\"\n    ],\n    \"import-spacing\": true,\n    \"indent\": [\n      true,\n      \"spaces\"\n    ],\n    \"interface-over-type-literal\": true,\n    \"label-position\": true,\n    \"max-line-length\": [\n      true,\n      140\n    ],\n    \"member-access\": false,\n    \"member-ordering\": [\n      true,\n      {\n        \"order\": [\n          \"static-field\",\n          \"instance-field\",\n          \"static-method\",\n          \"instance-method\"\n        ]\n      }\n    ],\n    \"no-arg\": true,\n    \"no-bitwise\": true,\n    \"no-console\": [\n      true,\n      \"debug\",\n      \"info\",\n      \"time\",\n      \"timeEnd\",\n      \"trace\"\n    ],\n    \"no-construct\": true,\n    \"no-debugger\": true,\n    \"no-duplicate-super\": true,\n    \"no-empty\": false,\n    \"no-empty-interface\": true,\n    \"no-eval\": true,\n    \"no-inferrable-types\": [\n      true,\n      \"ignore-params\"\n    ],\n    \"no-misused-new\": true,\n    \"no-non-null-assertion\": true,\n    \"no-shadowed-variable\": true,\n    \"no-string-literal\": false,\n    \"no-string-throw\": true,\n    \"no-switch-case-fall-through\": true,\n    \"no-trailing-whitespace\": true,\n    \"no-unnecessary-initializer\": true,\n    \"no-unused-expression\": true,\n    \"no-use-before-declare\": true,\n    \"no-var-keyword\": true,\n    \"object-literal-sort-keys\": false,\n    \"one-line\": [\n      true,\n      \"check-open-brace\",\n      \"check-catch\",\n      \"check-else\",\n      \"check-whitespace\"\n    ],\n    \"prefer-const\": true,\n    \"quotemark\": [\n      true,\n      \"single\"\n    ],\n    \"radix\": true,\n    \"semicolon\": [\n      true,\n      \"always\"\n    ],\n    \"triple-equals\": [\n      true,\n      \"allow-null-check\"\n    ],\n    \"typedef-whitespace\": [\n      true,\n      {\n        \"call-signature\": \"nospace\",\n        \"index-signature\": \"nospace\",\n        \"parameter\": \"nospace\",\n        \"property-declaration\": \"nospace\",\n        \"variable-declaration\": \"nospace\"\n      }\n    ],\n    \"unified-signatures\": true,\n    \"variable-name\": false,\n    \"whitespace\": [\n      true,\n      \"check-branch\",\n      \"check-decl\",\n      \"check-operator\",\n      \"check-separator\",\n      \"check-type\"\n    ],\n    \"directive-selector\": [\n      true,\n      \"attribute\",\n      \"app\",\n      \"camelCase\"\n    ],\n    \"component-selector\": [\n      true,\n      \"element\",\n      \"app\",\n      \"kebab-case\"\n    ],\n    \"no-output-on-prefix\": true,\n    \"use-input-property-decorator\": true,\n    \"use-output-property-decorator\": true,\n    \"use-host-property-decorator\": true,\n    \"no-input-rename\": true,\n    \"no-output-rename\": true,\n    \"use-life-cycle-interface\": true,\n    \"use-pipe-transform-interface\": true,\n    \"component-class-suffix\": true,\n    \"directive-class-suffix\": true\n  }\n}\n"
  },
  {
    "path": "examples/angular-cli-eject/webpack.config.js",
    "content": "const fs = require('fs');\nconst path = require('path');\nconst CopyWebpackPlugin = require('copy-webpack-plugin');\nconst ProgressPlugin = require('webpack/lib/ProgressPlugin');\nconst CircularDependencyPlugin = require('circular-dependency-plugin');\nconst HtmlWebpackPlugin = require('html-webpack-plugin');\nconst rxPaths = require('rxjs/_esm5/path-mapping');\nconst autoprefixer = require('autoprefixer');\nconst postcssUrl = require('postcss-url');\nconst postcssImports = require('postcss-import');\n\nconst { NoEmitOnErrorsPlugin, SourceMapDevToolPlugin, NamedModulesPlugin } = require('webpack');\nconst { NamedLazyChunksWebpackPlugin, BaseHrefWebpackPlugin, PostcssCliResources } = require('@angular/cli/plugins/webpack');\nconst { CommonsChunkPlugin } = require('webpack').optimize;\nconst { AngularCompilerPlugin } = require('@ngtools/webpack');\nconst PrerenderSPAPlugin = require('prerender-spa-plugin')\nconst Renderer = PrerenderSPAPlugin.PuppeteerRenderer\n\nconst nodeModules = path.join(process.cwd(), 'node_modules');\nconst realNodeModules = fs.realpathSync(nodeModules);\nconst genDirNodeModules = path.join(process.cwd(), 'src', '$$_gendir', 'node_modules');\nconst entryPoints = [\"inline\",\"polyfills\",\"sw-register\",\"styles\",\"vendor\",\"main\"];\nconst hashFormat = {\"chunk\":\"\",\"extract\":\"\",\"file\":\".[hash:20]\",\"script\":\"\"};\nconst baseHref = \"\";\nconst deployUrl = \"\";\nconst projectRoot = process.cwd();\nconst maximumInlineSize = 10;\nconst postcssPlugins = function (loader) {\n        return [\n            postcssImports({\n                resolve: (url, context) => {\n                    return new Promise((resolve, reject) => {\n                        let hadTilde = false;\n                        if (url && url.startsWith('~')) {\n                            url = url.substr(1);\n                            hadTilde = true;\n                        }\n                        loader.resolve(context, (hadTilde ? '' : './') + url, (err, result) => {\n                            if (err) {\n                                if (hadTilde) {\n                                    reject(err);\n                                    return;\n                                }\n                                loader.resolve(context, url, (err, result) => {\n                                    if (err) {\n                                        reject(err);\n                                    }\n                                    else {\n                                        resolve(result);\n                                    }\n                                });\n                            }\n                            else {\n                                resolve(result);\n                            }\n                        });\n                    });\n                },\n                load: (filename) => {\n                    return new Promise((resolve, reject) => {\n                        loader.fs.readFile(filename, (err, data) => {\n                            if (err) {\n                                reject(err);\n                                return;\n                            }\n                            const content = data.toString();\n                            resolve(content);\n                        });\n                    });\n                }\n            }),\n            postcssUrl({\n                filter: ({ url }) => url.startsWith('~'),\n                url: ({ url }) => {\n                    const fullPath = path.join(projectRoot, 'node_modules', url.substr(1));\n                    return path.relative(loader.context, fullPath).replace(/\\\\/g, '/');\n                }\n            }),\n            postcssUrl([\n                {\n                    // Only convert root relative URLs, which CSS-Loader won't process into require().\n                    filter: ({ url }) => url.startsWith('/') && !url.startsWith('//'),\n                    url: ({ url }) => {\n                        if (deployUrl.match(/:\\/\\//) || deployUrl.startsWith('/')) {\n                            // If deployUrl is absolute or root relative, ignore baseHref & use deployUrl as is.\n                            return `${deployUrl.replace(/\\/$/, '')}${url}`;\n                        }\n                        else if (baseHref.match(/:\\/\\//)) {\n                            // If baseHref contains a scheme, include it as is.\n                            return baseHref.replace(/\\/$/, '') +\n                                `/${deployUrl}/${url}`.replace(/\\/\\/+/g, '/');\n                        }\n                        else {\n                            // Join together base-href, deploy-url and the original URL.\n                            // Also dedupe multiple slashes into single ones.\n                            return `/${baseHref}/${deployUrl}/${url}`.replace(/\\/\\/+/g, '/');\n                        }\n                    }\n                },\n                {\n                    // TODO: inline .cur if not supporting IE (use browserslist to check)\n                    filter: (asset) => {\n                        return maximumInlineSize > 0 && !asset.hash && !asset.absolutePath.endsWith('.cur');\n                    },\n                    url: 'inline',\n                    // NOTE: maxSize is in KB\n                    maxSize: maximumInlineSize,\n                    fallback: 'rebase',\n                },\n                { url: 'rebase' },\n            ]),\n            PostcssCliResources({\n                deployUrl: loader.loaders[loader.loaderIndex].options.ident == 'extracted' ? '' : deployUrl,\n                loader,\n                filename: `[name]${hashFormat.file}.[ext]`,\n            }),\n            autoprefixer({ grid: true }),\n        ];\n    };\n\n\n\n\nmodule.exports = {\n  \"resolve\": {\n    \"extensions\": [\n      \".ts\",\n      \".js\"\n    ],\n    \"symlinks\": true,\n    \"modules\": [\n      \"./src\",\n      \"./node_modules\"\n    ],\n    \"alias\": rxPaths(),\n    \"mainFields\": [\n      \"browser\",\n      \"module\",\n      \"main\"\n    ]\n  },\n  \"resolveLoader\": {\n    \"modules\": [\n      \"./node_modules\"\n    ],\n    \"alias\": rxPaths()\n  },\n  \"entry\": {\n    \"main\": [\n      \"./src/main.ts\"\n    ],\n    \"polyfills\": [\n      \"./src/polyfills.ts\"\n    ],\n    \"styles\": [\n      \"./src/styles.css\"\n    ]\n  },\n  \"output\": {\n    \"path\": path.join(process.cwd(), \"dist\"),\n    \"filename\": \"[name].bundle.js\",\n    \"chunkFilename\": \"[id].chunk.js\",\n    \"crossOriginLoading\": false\n  },\n  \"module\": {\n    \"rules\": [\n      {\n        \"test\": /\\.html$/,\n        \"loader\": \"raw-loader\"\n      },\n      {\n        \"test\": /\\.(eot|svg|cur)$/,\n        \"loader\": \"file-loader\",\n        \"options\": {\n          \"name\": \"[name].[hash:20].[ext]\",\n          \"limit\": 10000\n        }\n      },\n      {\n        \"test\": /\\.(jpg|png|webp|gif|otf|ttf|woff|woff2|ani)$/,\n        \"loader\": \"url-loader\",\n        \"options\": {\n          \"name\": \"[name].[hash:20].[ext]\",\n          \"limit\": 10000\n        }\n      },\n      {\n        \"exclude\": [\n          path.join(process.cwd(), \"src/styles.css\")\n        ],\n        \"test\": /\\.css$/,\n        \"use\": [\n          {\n            \"loader\": \"raw-loader\"\n          },\n          {\n            \"loader\": \"postcss-loader\",\n            \"options\": {\n              \"ident\": \"embedded\",\n              \"plugins\": postcssPlugins,\n              \"sourceMap\": true\n            }\n          }\n        ]\n      },\n      {\n        \"exclude\": [\n          path.join(process.cwd(), \"src/styles.css\")\n        ],\n        \"test\": /\\.scss$|\\.sass$/,\n        \"use\": [\n          {\n            \"loader\": \"raw-loader\"\n          },\n          {\n            \"loader\": \"postcss-loader\",\n            \"options\": {\n              \"ident\": \"embedded\",\n              \"plugins\": postcssPlugins,\n              \"sourceMap\": true\n            }\n          },\n          {\n            \"loader\": \"sass-loader\",\n            \"options\": {\n              \"sourceMap\": true,\n              \"precision\": 8,\n              \"includePaths\": []\n            }\n          }\n        ]\n      },\n      {\n        \"exclude\": [\n          path.join(process.cwd(), \"src/styles.css\")\n        ],\n        \"test\": /\\.less$/,\n        \"use\": [\n          {\n            \"loader\": \"raw-loader\"\n          },\n          {\n            \"loader\": \"postcss-loader\",\n            \"options\": {\n              \"ident\": \"embedded\",\n              \"plugins\": postcssPlugins,\n              \"sourceMap\": true\n            }\n          },\n          {\n            \"loader\": \"less-loader\",\n            \"options\": {\n              \"sourceMap\": true\n            }\n          }\n        ]\n      },\n      {\n        \"exclude\": [\n          path.join(process.cwd(), \"src/styles.css\")\n        ],\n        \"test\": /\\.styl$/,\n        \"use\": [\n          {\n            \"loader\": \"raw-loader\"\n          },\n          {\n            \"loader\": \"postcss-loader\",\n            \"options\": {\n              \"ident\": \"embedded\",\n              \"plugins\": postcssPlugins,\n              \"sourceMap\": true\n            }\n          },\n          {\n            \"loader\": \"stylus-loader\",\n            \"options\": {\n              \"sourceMap\": true,\n              \"paths\": []\n            }\n          }\n        ]\n      },\n      {\n        \"include\": [\n          path.join(process.cwd(), \"src/styles.css\")\n        ],\n        \"test\": /\\.css$/,\n        \"use\": [\n          \"style-loader\",\n          {\n            \"loader\": \"raw-loader\"\n          },\n          {\n            \"loader\": \"postcss-loader\",\n            \"options\": {\n              \"ident\": \"embedded\",\n              \"plugins\": postcssPlugins,\n              \"sourceMap\": true\n            }\n          }\n        ]\n      },\n      {\n        \"include\": [\n          path.join(process.cwd(), \"src/styles.css\")\n        ],\n        \"test\": /\\.scss$|\\.sass$/,\n        \"use\": [\n          \"style-loader\",\n          {\n            \"loader\": \"raw-loader\"\n          },\n          {\n            \"loader\": \"postcss-loader\",\n            \"options\": {\n              \"ident\": \"embedded\",\n              \"plugins\": postcssPlugins,\n              \"sourceMap\": true\n            }\n          },\n          {\n            \"loader\": \"sass-loader\",\n            \"options\": {\n              \"sourceMap\": true,\n              \"precision\": 8,\n              \"includePaths\": []\n            }\n          }\n        ]\n      },\n      {\n        \"include\": [\n          path.join(process.cwd(), \"src/styles.css\")\n        ],\n        \"test\": /\\.less$/,\n        \"use\": [\n          \"style-loader\",\n          {\n            \"loader\": \"raw-loader\"\n          },\n          {\n            \"loader\": \"postcss-loader\",\n            \"options\": {\n              \"ident\": \"embedded\",\n              \"plugins\": postcssPlugins,\n              \"sourceMap\": true\n            }\n          },\n          {\n            \"loader\": \"less-loader\",\n            \"options\": {\n              \"sourceMap\": true\n            }\n          }\n        ]\n      },\n      {\n        \"include\": [\n          path.join(process.cwd(), \"src/styles.css\")\n        ],\n        \"test\": /\\.styl$/,\n        \"use\": [\n          \"style-loader\",\n          {\n            \"loader\": \"raw-loader\"\n          },\n          {\n            \"loader\": \"postcss-loader\",\n            \"options\": {\n              \"ident\": \"embedded\",\n              \"plugins\": postcssPlugins,\n              \"sourceMap\": true\n            }\n          },\n          {\n            \"loader\": \"stylus-loader\",\n            \"options\": {\n              \"sourceMap\": true,\n              \"paths\": []\n            }\n          }\n        ]\n      },\n      {\n        \"test\": /\\.ts$/,\n        \"loader\": \"@ngtools/webpack\"\n      }\n    ]\n  },\n  \"plugins\": [\n    new NoEmitOnErrorsPlugin(),\n    new CopyWebpackPlugin([\n      {\n        \"context\": \"src\",\n        \"to\": \"\",\n        \"from\": {\n          \"glob\": \"assets/**/*\",\n          \"dot\": true\n        }\n      },\n      {\n        \"context\": \"src\",\n        \"to\": \"\",\n        \"from\": {\n          \"glob\": \"favicon.ico\",\n          \"dot\": true\n        }\n      }\n    ], {\n      \"ignore\": [\n        \".gitkeep\",\n        \"**/.DS_Store\",\n        \"**/Thumbs.db\"\n      ],\n      \"debug\": \"warning\"\n    }),\n    new ProgressPlugin(),\n    new CircularDependencyPlugin({\n      \"exclude\": /(\\\\|\\/)node_modules(\\\\|\\/)/,\n      \"failOnError\": false,\n      \"onDetected\": false,\n      \"cwd\": projectRoot\n    }),\n    new NamedLazyChunksWebpackPlugin(),\n    new HtmlWebpackPlugin({\n      \"template\": \"./src/index.html\",\n      \"filename\": \"./index.html\",\n      \"hash\": false,\n      \"inject\": true,\n      \"compile\": true,\n      \"favicon\": false,\n      \"minify\": false,\n      \"cache\": true,\n      \"showErrors\": true,\n      \"chunks\": \"all\",\n      \"excludeChunks\": [],\n      \"title\": \"Webpack App\",\n      \"xhtml\": true,\n      \"chunksSortMode\": function sort(left, right) {\n        let leftIndex = entryPoints.indexOf(left.names[0]);\n        let rightindex = entryPoints.indexOf(right.names[0]);\n        if (leftIndex > rightindex) {\n            return 1;\n        }\n        else if (leftIndex < rightindex) {\n            return -1;\n        }\n        else {\n            return 0;\n        }\n    }\n    }),\n    new BaseHrefWebpackPlugin({}),\n    new CommonsChunkPlugin({\n      \"name\": [\n        \"inline\"\n      ],\n      \"minChunks\": null\n    }),\n    new CommonsChunkPlugin({\n      \"name\": [\n        \"vendor\"\n      ],\n      \"minChunks\": (module) => {\n                return module.resource\n                    && (module.resource.startsWith(nodeModules)\n                        || module.resource.startsWith(genDirNodeModules)\n                        || module.resource.startsWith(realNodeModules));\n            },\n      \"chunks\": [\n        \"main\"\n      ]\n    }),\n    new SourceMapDevToolPlugin({\n      \"filename\": \"[file].map[query]\",\n      \"moduleFilenameTemplate\": \"[resource-path]\",\n      \"fallbackModuleFilenameTemplate\": \"[resource-path]?[hash]\",\n      \"sourceRoot\": \"webpack:///\"\n    }),\n    new CommonsChunkPlugin({\n      \"name\": [\n        \"main\"\n      ],\n      \"minChunks\": 2,\n      \"async\": \"common\"\n    }),\n    new NamedModulesPlugin({}),\n    new AngularCompilerPlugin({\n      \"mainPath\": \"main.ts\",\n      \"platform\": 0,\n      \"hostReplacementPaths\": {\n        \"environments/environment.ts\": \"environments/environment.ts\"\n      },\n      \"sourceMap\": true,\n      \"tsConfigPath\": \"src/tsconfig.app.json\",\n      \"skipCodeGeneration\": true,\n      \"compilerOptions\": {}\n    }),\n    // == PRERENDER SPA PLUGIN == //\n    new PrerenderSPAPlugin({\n      // Index.html is in the root directory.\n      staticDir: path.join(__dirname, 'dist'),\n      routes: [ '/' ],\n      // Optional minification.\n      minify: {\n        collapseBooleanAttributes: true,\n        collapseWhitespace: true,\n        decodeEntities: true,\n        keepClosingSlash: true,\n        sortAttributes: true\n      },\n\n      renderer: new Renderer({\n        renderAfterTime: 500\n      })\n    })\n  ],\n  \"node\": {\n    \"fs\": \"empty\",\n    \"global\": true,\n    \"crypto\": \"empty\",\n    \"tls\": \"empty\",\n    \"net\": \"empty\",\n    \"process\": true,\n    \"module\": false,\n    \"clearImmediate\": false,\n    \"setImmediate\": false\n  },\n  \"devServer\": {\n    \"historyApiFallback\": true\n  }\n};\n"
  },
  {
    "path": "examples/create-react-app/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "examples/create-react-app/README.md",
    "content": "# Create-React-App - Prerender SPA Example\n\nThis project was bootstrapped with [Create React App](https://github.com/facebookincubator/create-react-app) and uses [react-app-rewired](https://github.com/timarney/react-app-rewired) to allow modification of the webpack configuration.\n\n## Build\n\n```bash\nnpm install\nnpm run build\n```\n\nNow check the new `build` directory for your prerendered static files!\n\nTo view the rendered files, install [http-server](https://www.npmjs.com/package/http-server) (`npm install -g http-server`) if you haven't already and run it in the `build` directory.\n\nNow visit the following route in your browser (note the trailing slash):\n\n- [http://localhost:8000/](http://localhost:8000/)\n\nIf all went well, it should load without JavaScript.\n\n## Development\n\nTo edit the `prerender-spa-plugin` configuration, look for `new PrerenderSPAPlugin` in `config-overrides.js`.\n\nIf you're using a router or have more than one page to prerender, edit the `routes` array under that config object.\n\n```bash\nnpm install\nnpm start\n```\n"
  },
  {
    "path": "examples/create-react-app/config-overrides.js",
    "content": "const PrerenderSPAPlugin = require('prerender-spa-plugin');\nconst path = require('path');\n\nmodule.exports = (config, env) => {\n  if (env === 'production') {\n    config.plugins = config.plugins.concat([\n      new PrerenderSPAPlugin({\n        routes: ['/'],\n        staticDir: path.join(__dirname, 'build'),\n      }),\n    ]);\n  }\n\n  return config;\n};\n"
  },
  {
    "path": "examples/create-react-app/package.json",
    "content": "{\n  \"name\": \"prerender-spa-plugin-example-create-react-app\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"react\": \"^16.7.0\",\n    \"react-dom\": \"^16.7.0\",\n    \"react-scripts\": \"2.1.3\"\n  },\n  \"scripts\": {\n    \"start\": \"react-app-rewired start\",\n    \"build\": \"react-app-rewired build\",\n    \"test\": \"react-app-rewired test\",\n    \"eject\": \"react-scripts eject\"\n  },\n  \"eslintConfig\": {\n    \"extends\": \"react-app\"\n  },\n  \"browserslist\": [\n    \">0.2%\",\n    \"not dead\",\n    \"not ie <= 11\",\n    \"not op_mini all\"\n  ],\n  \"devDependencies\": {\n    \"prerender-spa-plugin\": \"3.4.0\",\n    \"react-app-rewired\": \"2.0.2\"\n  }\n}\n"
  },
  {
    "path": "examples/create-react-app/public/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"shortcut icon\" href=\"%PUBLIC_URL%/favicon.ico\" />\n    <meta\n      name=\"viewport\"\n      content=\"width=device-width, initial-scale=1, shrink-to-fit=no\"\n    />\n    <meta name=\"theme-color\" content=\"#000000\" />\n    <!--\n      manifest.json provides metadata used when your web app is added to the\n      homescreen on Android. See https://developers.google.com/web/fundamentals/web-app-manifest/\n    -->\n    <link rel=\"manifest\" href=\"%PUBLIC_URL%/manifest.json\" />\n    <!--\n      Notice the use of %PUBLIC_URL% in the tags above.\n      It will be replaced with the URL of the `public` folder during the build.\n      Only files inside the `public` folder can be referenced from the HTML.\n\n      Unlike \"/favicon.ico\" or \"favicon.ico\", \"%PUBLIC_URL%/favicon.ico\" will\n      work correctly both with client-side routing and a non-root public URL.\n      Learn how to configure a non-root public URL by running `npm run build`.\n    -->\n    <title>React App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <!--\n      This HTML file is a template.\n      If you open it directly in the browser, you will see an empty page.\n\n      You can add webfonts, meta tags, or analytics to this file.\n      The build step will place the bundled scripts into the <body> tag.\n\n      To begin the development, run `npm start` or `yarn start`.\n      To create a production bundle, use `npm run build` or `yarn build`.\n    -->\n  </body>\n</html>\n"
  },
  {
    "path": "examples/create-react-app/public/manifest.json",
    "content": "{\n  \"short_name\": \"React App\",\n  \"name\": \"Create React App Sample\",\n  \"icons\": [\n    {\n      \"src\": \"favicon.ico\",\n      \"sizes\": \"64x64 32x32 24x24 16x16\",\n      \"type\": \"image/x-icon\"\n    }\n  ],\n  \"start_url\": \".\",\n  \"display\": \"standalone\",\n  \"theme_color\": \"#000000\",\n  \"background_color\": \"#ffffff\"\n}\n"
  },
  {
    "path": "examples/create-react-app/src/App.css",
    "content": ".App {\n  text-align: center;\n}\n\n.App-logo {\n  animation: App-logo-spin infinite 20s linear;\n  height: 40vmin;\n}\n\n.App-header {\n  background-color: #282c34;\n  min-height: 100vh;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  font-size: calc(10px + 2vmin);\n  color: white;\n}\n\n.App-link {\n  color: #61dafb;\n}\n\n@keyframes App-logo-spin {\n  from {\n    transform: rotate(0deg);\n  }\n  to {\n    transform: rotate(360deg);\n  }\n}\n"
  },
  {
    "path": "examples/create-react-app/src/App.js",
    "content": "import React, { Component } from 'react';\nimport logo from './logo.svg';\nimport './App.css';\n\nclass App extends Component {\n  render() {\n    return (\n      <div className=\"App\">\n        <header className=\"App-header\">\n          <img src={logo} className=\"App-logo\" alt=\"logo\" />\n          <p>\n            Edit <code>src/App.js</code> and save to reload.\n          </p>\n          <a\n            className=\"App-link\"\n            href=\"https://reactjs.org\"\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n          >\n            Learn React\n          </a>\n        </header>\n      </div>\n    );\n  }\n}\n\nexport default App;\n"
  },
  {
    "path": "examples/create-react-app/src/App.test.js",
    "content": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App';\n\nit('renders without crashing', () => {\n  const div = document.createElement('div');\n  ReactDOM.render(<App />, div);\n  ReactDOM.unmountComponentAtNode(div);\n});\n"
  },
  {
    "path": "examples/create-react-app/src/index.css",
    "content": "body {\n  margin: 0;\n  padding: 0;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n    \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n    sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n  font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\",\n    monospace;\n}\n"
  },
  {
    "path": "examples/create-react-app/src/index.js",
    "content": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\nimport * as serviceWorker from './serviceWorker';\n\nReactDOM.render(<App />, document.getElementById('root'));\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: http://bit.ly/CRA-PWA\nserviceWorker.unregister();\n"
  },
  {
    "path": "examples/create-react-app/src/serviceWorker.js",
    "content": "// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read http://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n  window.location.hostname === 'localhost' ||\n    // [::1] is the IPv6 localhost address.\n    window.location.hostname === '[::1]' ||\n    // 127.0.0.1/8 is considered localhost for IPv4.\n    window.location.hostname.match(\n      /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n    )\n);\n\nexport function register(config) {\n  if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n    // The URL constructor is available in all browsers that support SW.\n    const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\n    if (publicUrl.origin !== window.location.origin) {\n      // Our service worker won't work if PUBLIC_URL is on a different origin\n      // from what our page is served on. This might happen if a CDN is used to\n      // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n      return;\n    }\n\n    window.addEventListener('load', () => {\n      const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n      if (isLocalhost) {\n        // This is running on localhost. Let's check if a service worker still exists or not.\n        checkValidServiceWorker(swUrl, config);\n\n        // Add some additional logging to localhost, pointing developers to the\n        // service worker/PWA documentation.\n        navigator.serviceWorker.ready.then(() => {\n          console.log(\n            'This web app is being served cache-first by a service ' +\n              'worker. To learn more, visit http://bit.ly/CRA-PWA'\n          );\n        });\n      } else {\n        // Is not localhost. Just register service worker\n        registerValidSW(swUrl, config);\n      }\n    });\n  }\n}\n\nfunction registerValidSW(swUrl, config) {\n  navigator.serviceWorker\n    .register(swUrl)\n    .then(registration => {\n      registration.onupdatefound = () => {\n        const installingWorker = registration.installing;\n        if (installingWorker == null) {\n          return;\n        }\n        installingWorker.onstatechange = () => {\n          if (installingWorker.state === 'installed') {\n            if (navigator.serviceWorker.controller) {\n              // At this point, the updated precached content has been fetched,\n              // but the previous service worker will still serve the older\n              // content until all client tabs are closed.\n              console.log(\n                'New content is available and will be used when all ' +\n                  'tabs for this page are closed. See http://bit.ly/CRA-PWA.'\n              );\n\n              // Execute callback\n              if (config && config.onUpdate) {\n                config.onUpdate(registration);\n              }\n            } else {\n              // At this point, everything has been precached.\n              // It's the perfect time to display a\n              // \"Content is cached for offline use.\" message.\n              console.log('Content is cached for offline use.');\n\n              // Execute callback\n              if (config && config.onSuccess) {\n                config.onSuccess(registration);\n              }\n            }\n          }\n        };\n      };\n    })\n    .catch(error => {\n      console.error('Error during service worker registration:', error);\n    });\n}\n\nfunction checkValidServiceWorker(swUrl, config) {\n  // Check if the service worker can be found. If it can't reload the page.\n  fetch(swUrl)\n    .then(response => {\n      // Ensure service worker exists, and that we really are getting a JS file.\n      const contentType = response.headers.get('content-type');\n      if (\n        response.status === 404 ||\n        (contentType != null && contentType.indexOf('javascript') === -1)\n      ) {\n        // No service worker found. Probably a different app. Reload the page.\n        navigator.serviceWorker.ready.then(registration => {\n          registration.unregister().then(() => {\n            window.location.reload();\n          });\n        });\n      } else {\n        // Service worker found. Proceed as normal.\n        registerValidSW(swUrl, config);\n      }\n    })\n    .catch(() => {\n      console.log(\n        'No internet connection found. App is running in offline mode.'\n      );\n    });\n}\n\nexport function unregister() {\n  if ('serviceWorker' in navigator) {\n    navigator.serviceWorker.ready.then(registration => {\n      registration.unregister();\n    });\n  }\n}\n"
  },
  {
    "path": "examples/vanilla-simple/.gitignore",
    "content": "node_modules/\ndist/\n"
  },
  {
    "path": "examples/vanilla-simple/README.md",
    "content": "# Vanilla JS - Prerender SPA Example\n\nDemonstrates usage of `prerender-spa-plugin` with Vanilla JS and Webpack 3. Build will generate 3 static routes at the following paths:\n\n- `/`\n- `/about`\n- `/some/deep/nested/route`\n\n## Build\n\n```bash\nnpm install\nnpm run build\n```\n\nNow check the new `dist` directory for your prerendered static files!\n\nTo view the rendered files, install [http-server](https://www.npmjs.com/package/http-server) (`npm install -g http-server`) if you haven't already and run it in the dist directory.\n\nNow visit the following routes in your browser (note the trailing slash):\n\n- [http://localhost:8000/](http://localhost:8000/)\n- [http://localhost:8000/about/](http://localhost:8000/about/)\n- [http://localhost:8000/some/deep/nested/route/](http://localhost:8000/some/deep/nested/route/)\n\nYou should notice that the TODOs are rendered and populated already.\n\n## Development\n\nTo edit the `prerender-spa-plugin` configuration, look for `new PrerenderSPAPlugin` in the plugins section of `webpack.config.js`.\n\nIf you're using a router or have more than one page to prerender, edit the `routes` array under that config object.\n"
  },
  {
    "path": "examples/vanilla-simple/package.json",
    "content": "{\n  \"name\": \"prerender-spa-plugin-example-vanilla-simple\",\n  \"version\": \"3.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"webpack --progress --hide-modules\"\n  },\n  \"devDependencies\": {\n    \"copy-webpack-plugin\": \"^4.4.1\",\n    \"prerender-spa-plugin\": \"^3.0.0\",\n    \"webpack\": \"^3.11.0\"\n  }\n}\n"
  },
  {
    "path": "examples/vanilla-simple/src/main.js",
    "content": "// -----\n// STATE\n// -----\n\nvar todos = [\n  'Do the dishes',\n  'Make the bed',\n  'Take out the trash'\n]\n\n// --------\n// ELEMENTS\n// --------\n\nvar newTodoInput = document.getElementById('new-todo')\nvar todosContainer = document.getElementById('todos')\n\n// ------\n// RENDER\n// ------\n\nfunction render () {\n  todosContainer.innerHTML = '<ul>' +\n    todos.map(function (todo, index) {\n      return '<li class=\"item\">' +\n        todo +\n        ' <button class=\"remove-todo\" data-index=\"' + index + '\">X</button>' +\n      '</li>'\n    }).join('') +\n  '</ul>'\n\n  document.dispatchEvent(new Event('render-event'))\n}\nrender()\n\n// ------\n// EVENTS\n// ------\n\nnewTodoInput.addEventListener('keyup', function (event) {\n  if (event.which === 13) {\n    todos.push(event.target.value)\n    newTodoInput.value = ''\n    render()\n  }\n})\n\ntodosContainer.addEventListener('click', function (event) {\n  var clickedElement = event.target\n  if (clickedElement.className === 'remove-todo') {\n    todos.splice(clickedElement.dataset.index, 1)\n    render()\n  }\n})\n\ndocument.body.innerHTML += `<p>Injected: ${JSON.stringify(window['__PRERENDER_INJECTED'])}</p>`\n"
  },
  {
    "path": "examples/vanilla-simple/src/static/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Generic &amp; Simple Prerendering Demo</title>\n  </head>\n  <body>\n    <input id=\"new-todo\" placeholder=\"New todo\">\n    <div id=\"todos\"></div>\n    <script src=\"/main.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/vanilla-simple/webpack.config.js",
    "content": "const path = require('path')\nconst CopyWebpackPlugin = require('copy-webpack-plugin')\nconst PrerenderSPAPlugin = require('prerender-spa-plugin')\nconst Renderer = PrerenderSPAPlugin.PuppeteerRenderer\n\nmodule.exports = {\n  entry: [ './src/main.js' ],\n  output: {\n    path: path.join(__dirname, 'dist'),\n    filename: '[name].js'\n  },\n  plugins: [\n    new CopyWebpackPlugin([{\n      from: 'src/static',\n      to: '.'\n    }]),\n    // == PRERENDER SPA PLUGIN == //\n    new PrerenderSPAPlugin({\n      // Index.html is in the root directory.\n      staticDir: path.join(__dirname, 'dist'),\n      routes: [ '/', '/about', '/some/deep/nested/route' ],\n      // Optional minification.\n      minify: {\n        collapseBooleanAttributes: true,\n        collapseWhitespace: true,\n        decodeEntities: true,\n        keepClosingSlash: true,\n        sortAttributes: true\n      },\n\n      renderer: new Renderer({\n        inject: {\n          foo: 'bar'\n        },\n        renderAfterDocumentEvent: 'render-event'\n      })\n    })\n  ]\n}\n"
  },
  {
    "path": "examples/vue2-webpack-router/.babelrc",
    "content": "{\n  \"presets\": [\"@babel/preset-env\"]\n}"
  },
  {
    "path": "examples/vue2-webpack-router/.gitignore",
    "content": "node_modules/\ndist/\n"
  },
  {
    "path": "examples/vue2-webpack-router/README.md",
    "content": "# Vue.js 2.0 + vue-router Prerender SPA Example\n\nDemonstrates usage of Vuejs 2.0 with Vue Router and Webpack 3. Build will generate 3 static routes at the following paths:\n\n- `/`\n- `/about`\n- `/contact`\n\n## Build\n\n```bash\nnpm install\nnpm run build\n```\n\nNow check the new `dist` directory for your prerendered static files!\n\nTo view the rendered files, install [http-server](https://www.npmjs.com/package/http-server) (`npm install -g http-server`) if you haven't already and run it in the dist directory.\n\nNow visit the following routes in your browser (note the trailing slash):\n\n- [http://localhost:8000/](http://localhost:8000/)\n- [http://localhost:8000/about/](http://localhost:8000/about/)\n- [http://localhost:8000/contact/](http://localhost:8000/contact/)\n\n## Development\n\nTo edit the `prerender-spa-plugin` configuration, look for `new PrerenderSPAPlugin` in the plugins section of `webpack.config.js`.\n\nIf you're using a router or have more than one page to prerender, edit the `routes` array under that config object.\n\n```bash\nnpm install\nnpm run dev\n```\n"
  },
  {
    "path": "examples/vue2-webpack-router/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <title><%= htmlWebpackPlugin.options.title %></title>\n</head>\n<body>\n  <div id=\"app\"></div>\n</body>\n</html>\n"
  },
  {
    "path": "examples/vue2-webpack-router/package.json",
    "content": "{\n  \"name\": \"prerender-spa-plugin-example-vue2-webpack-router\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"author\": \"Drew Lustro <drewlustro@gmail.com>\",\n  \"scripts\": {\n    \"dev\": \"cross-env NODE_ENV=development webpack-dev-server --open --hot\",\n    \"build\": \"cross-env NODE_ENV=production webpack --progress --hide-modules\",\n    \"serve\": \"http-server dist\"\n  },\n  \"dependencies\": {\n    \"vue\": \"^2.6.7\",\n    \"vue-router\": \"^3.0.2\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.3.3\",\n    \"@babel/preset-env\": \"^7.3.1\",\n    \"babel-loader\": \"^8.0.5\",\n    \"cross-env\": \"^5.2.0\",\n    \"css-loader\": \"^2.1.0\",\n    \"file-loader\": \"^3.0.1\",\n    \"html-webpack-plugin\": \"^3.2.0\",\n    \"http-server\": \"^0.11.1\",\n    \"prerender-spa-plugin\": \"^3.4.0\",\n    \"vue-loader\": \"^15.6.4\",\n    \"vue-template-compiler\": \"^2.6.7\",\n    \"webpack\": \"^4.29.5\",\n    \"webpack-cli\": \"^3.2.3\",\n    \"webpack-dev-server\": \"^3.2.0\"\n  }\n}\n"
  },
  {
    "path": "examples/vue2-webpack-router/src/App.vue",
    "content": "<template>\n  <div id=\"app\">\n    <img src=\"./assets/logo.png\">\n    <h1>{{ msg }}</h1>\n    <p>\n      <router-link to=\"/\">Home</router-link>\n      <router-link to=\"/about\">About</router-link>\n      <router-link to=\"/contact\">Contact</router-link>\n    </p>\n    <router-view></router-view>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'app',\n  data () {\n    return {\n      msg: 'Welcome to your prerender-spa-plugin Vuejs 2.0 demo app!'\n    }\n  }\n}\n</script>\n\n<style>\n#app {\n  font-family: 'Avenir', Helvetica, Arial, sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  text-align: center;\n  color: #2c3e50;\n  margin-top: 60px;\n}\n\nh1, h2 {\n  font-weight: normal;\n}\n\nul {\n  list-style-type: none;\n  padding: 0;\n}\n\nli {\n  display: inline-block;\n  margin: 0 10px;\n}\n\na {\n  color: #42b983;\n}\n</style>\n"
  },
  {
    "path": "examples/vue2-webpack-router/src/main.js",
    "content": "import Vue from 'vue'\nimport VueRouter from 'vue-router'\nimport App from './App.vue'\n\nVue.use(VueRouter)\n\nconst Home = { template: '<div><h2>Home Page</h2></div>' }\nconst About = { template: '<div><h2>About Page</h2></div>' }\nconst Contact = { template: '<div><h2>Contact Page</h2></div>' }\n\nconst routes = [\n  { path: '/', component: Home },\n  { path: '/about', component: About },\n  { path: '/contact', component: Contact }\n]\n\nconst router = new VueRouter({\n  routes,\n  mode: 'history'\n})\n\nnew Vue({\n  el: '#app',\n  router,\n  render: h => h(App),\n  mounted () {\n    // You'll need this for renderAfterDocumentEvent.\n    document.dispatchEvent(new Event('render-event'))\n  }\n})\n"
  },
  {
    "path": "examples/vue2-webpack-router/webpack.config.js",
    "content": "var path = require('path')\nvar webpack = require('webpack')\nvar HtmlWebpackPlugin = require('html-webpack-plugin')\nconst PrerenderSPAPlugin = require('prerender-spa-plugin')\nconst Renderer = PrerenderSPAPlugin.PuppeteerRenderer\nconst VueLoaderPlugin = require('vue-loader/lib/plugin')\n\nmodule.exports = {\n  mode: process.env.NODE_ENV,\n  entry: './src/main.js',\n  output: {\n    path: path.resolve(__dirname, './dist'),\n    publicPath: '/',\n    filename: 'build.js'\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.vue$/,\n        loader: 'vue-loader'\n      },\n      {\n        test: /\\.js$/,\n        loader: 'babel-loader',\n        exclude: /node_modules/\n      },\n      {\n        test: /\\.(png|jpg|gif|svg)$/,\n        loader: 'file-loader',\n        options: {\n          name: '[name].[ext]?[hash]'\n        }\n      },\n      {\n        test: /\\.css$/,\n        use: [\n          'vue-style-loader',\n          'css-loader'\n        ]\n      }\n    ]\n  },\n  resolve: {\n    alias: {\n      'vue$': 'vue/dist/vue.esm.js'\n    }\n  },\n  devServer: {\n    historyApiFallback: true,\n    noInfo: false,\n  },\n  devtool: '#eval-source-map',\n  plugins: [\n    new VueLoaderPlugin(),\n  ]\n}\nif (process.env.NODE_ENV === 'production') {\n  module.exports.devtool = '#source-map'\n  module.exports.plugins = (module.exports.plugins || []).concat([\n    new webpack.DefinePlugin({\n      'process.env': {\n        NODE_ENV: '\"production\"'\n      }\n    }),\n    new HtmlWebpackPlugin({\n      title: 'PRODUCTION prerender-spa-plugin',\n      template: 'index.html',\n      filename: path.resolve(__dirname, 'dist/index.html'),\n      favicon: 'favicon.ico'\n    }),\n    new PrerenderSPAPlugin({\n      staticDir: path.join(__dirname, 'dist'),\n      routes: [ '/', '/about', '/contact' ],\n\n      renderer: new Renderer({\n        inject: {\n          foo: 'bar'\n        },\n        headless: true,\n        renderAfterDocumentEvent: 'render-event'\n      })\n    })\n  ])\n} else {\n  // NODE_ENV === 'development'\n  module.exports.plugins = (module.exports.plugins || []).concat([\n    new webpack.DefinePlugin({\n      'process.env': {\n        NODE_ENV: '\"development\"'\n      }\n    }),\n    new HtmlWebpackPlugin({\n      title: 'DEVELOPMENT prerender-spa-plugin',\n      template: 'index.html',\n      filename: 'index.html',\n      favicon: 'favicon.ico'\n    }),\n  ])\n}\n"
  },
  {
    "path": "examples/vue2-webpack-simple/.babelrc",
    "content": "{\n  \"presets\": [\"@babel/preset-env\"]\n}"
  },
  {
    "path": "examples/vue2-webpack-simple/.editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n"
  },
  {
    "path": "examples/vue2-webpack-simple/.gitignore",
    "content": ".DS_Store\nnode_modules/\ndist/\nnpm-debug.log\nyarn-error.log\n\n# Editor directories and files\n.idea\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n"
  },
  {
    "path": "examples/vue2-webpack-simple/README.md",
    "content": "# Vue.js 2.0 Webpack Simple Template - Prerender SPA Example\n\nDemonstrates usage of Vuejs 2.0 with Webpack 3. Build will populate `dist/index.html` with the prerendered page.\n\n## Build\n\n```bash\nnpm install\nnpm run build\n```\n\nNow check the new `dist` directory for your prerendered static files!\n\nTo view the rendered files, install [http-server](https://www.npmjs.com/package/http-server) (`npm install -g http-server`) if you haven't already and run it in the dist directory.\n\nNow visit the following route in your browser (note the trailing slash):\n\n- [http://localhost:8000/](http://localhost:8000/)\n\n## Development\n\nTo edit the `prerender-spa-plugin` configuration, look for `new PrerenderSPAPlugin` in the plugins section of `webpack.config.js`.\n\nIf you're using a router or have more than one page to prerender, edit the `routes` array under that config object.\n\n```bash\nnpm install\nnpm run dev\n```\n"
  },
  {
    "path": "examples/vue2-webpack-simple/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <title><%= htmlWebpackPlugin.options.title %></title>\n</head>\n<body>\n  <div id=\"app\"></div>\n</body>\n</html>"
  },
  {
    "path": "examples/vue2-webpack-simple/package.json",
    "content": "{\n  \"name\": \"prerender-spa-plugin-example-vue2-webpack-simple\",\n  \"version\": \"1.0.0\",\n  \"author\": \"Joshua Bemenderfer <tribex10@gmail.com>\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"cross-env NODE_ENV=development webpack-dev-server --open --hot\",\n    \"build\": \"cross-env NODE_ENV=production webpack --progress --hide-modules\",\n    \"serve\": \"http-server ./dist\"\n  },\n  \"dependencies\": {\n    \"vue\": \"^2.6.7\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.3.3\",\n    \"@babel/preset-env\": \"^7.3.1\",\n    \"babel-loader\": \"^8.0.5\",\n    \"cross-env\": \"^5.2.0\",\n    \"css-loader\": \"^2.1.0\",\n    \"file-loader\": \"^3.0.1\",\n    \"html-webpack-plugin\": \"^3.2.0\",\n    \"http-server\": \"^0.11.1\",\n    \"prerender-spa-plugin\": \"^3.4.0\",\n    \"vue-loader\": \"^15.6.4\",\n    \"vue-template-compiler\": \"^2.6.7\",\n    \"webpack\": \"^4.29.5\",\n    \"webpack-cli\": \"^3.2.3\",\n    \"webpack-dev-server\": \"^3.2.0\"\n  }\n}\n"
  },
  {
    "path": "examples/vue2-webpack-simple/src/App.vue",
    "content": "<template>\n  <div id=\"app\">\n    <img src=\"./assets/logo.png\">\n    <h1>{{ msg }}</h1>\n    <h2>Essential Links</h2>\n    <ul>\n      <li><a href=\"https://vuejs.org\" target=\"_blank\">Core Docs</a></li>\n      <li><a href=\"https://forum.vuejs.org\" target=\"_blank\">Forum</a></li>\n      <li><a href=\"https://chat.vuejs.org\" target=\"_blank\">Community Chat</a></li>\n      <li><a href=\"https://twitter.com/vuejs\" target=\"_blank\">Twitter</a></li>\n    </ul>\n    <h2>Ecosystem</h2>\n    <ul>\n      <li><a href=\"http://router.vuejs.org/\" target=\"_blank\">vue-router</a></li>\n      <li><a href=\"http://vuex.vuejs.org/\" target=\"_blank\">vuex</a></li>\n      <li><a href=\"http://vue-loader.vuejs.org/\" target=\"_blank\">vue-loader</a></li>\n      <li><a href=\"https://github.com/vuejs/awesome-vue\" target=\"_blank\">awesome-vue</a></li>\n    </ul>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'app',\n  data () {\n    return {\n      msg: 'Welcome to Your Vue.js App'\n    }\n  }\n}\n</script>\n\n<style>\n#app {\n  font-family: 'Avenir', Helvetica, Arial, sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  text-align: center;\n  color: #2c3e50;\n  margin-top: 60px;\n}\n\nh1, h2 {\n  font-weight: normal;\n}\n\nul {\n  list-style-type: none;\n  padding: 0;\n}\n\nli {\n  display: inline-block;\n  margin: 0 10px;\n}\n\na {\n  color: #42b983;\n}\n</style>\n"
  },
  {
    "path": "examples/vue2-webpack-simple/src/main.js",
    "content": "import Vue from 'vue'\nimport App from './App.vue'\n\nnew Vue({\n  el: '#app',\n  render: h => h(App),\n  mounted () {\n    // You'll need this for renderAfterDocumentEvent.\n    document.dispatchEvent(new Event('render-event'))\n  }\n})\n"
  },
  {
    "path": "examples/vue2-webpack-simple/webpack.config.js",
    "content": "var path = require('path')\nvar webpack = require('webpack')\nvar HtmlWebpackPlugin = require('html-webpack-plugin')\nconst PrerenderSPAPlugin = require('prerender-spa-plugin')\nconst Renderer = PrerenderSPAPlugin.PuppeteerRenderer\nconst VueLoaderPlugin = require('vue-loader/lib/plugin')\n\nmodule.exports = {\n  mode: process.env.NODE_ENV,\n  entry: './src/main.js',\n  output: {\n    path: path.resolve(__dirname, './dist'),\n    publicPath: '/',\n    filename: 'build.js'\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.vue$/,\n        loader: 'vue-loader'\n      },\n      {\n        test: /\\.js$/,\n        loader: 'babel-loader',\n        exclude: /node_modules/\n      },\n      {\n        test: /\\.(png|jpg|gif|svg)$/,\n        loader: 'file-loader',\n        options: {\n          name: '[name].[ext]?[hash]'\n        }\n      },\n      {\n        test: /\\.css$/,\n        use: [\n          'vue-style-loader',\n          'css-loader'\n        ]\n      }\n    ]\n  },\n  resolve: {\n    alias: {\n      'vue$': 'vue/dist/vue.esm.js'\n    }\n  },\n  devServer: {\n    historyApiFallback: true,\n    noInfo: false,\n  },\n  devtool: '#eval-source-map',\n  plugins: [\n    new VueLoaderPlugin(),\n  ]\n}\nif (process.env.NODE_ENV === 'production') {\n  module.exports.devtool = '#source-map'\n  module.exports.plugins = (module.exports.plugins || []).concat([\n    new webpack.DefinePlugin({\n      'process.env': {\n        NODE_ENV: '\"production\"'\n      }\n    }),\n    new HtmlWebpackPlugin({\n      title: 'PRODUCTION prerender-spa-plugin',\n      template: 'index.html',\n      filename: path.resolve(__dirname, 'dist/index.html')\n    }),\n    new PrerenderSPAPlugin({\n      staticDir: path.join(__dirname, 'dist'),\n      routes: [ '/', '/about', '/contact' ],\n\n      renderer: new Renderer({\n        inject: {\n          foo: 'bar'\n        },\n        headless: true,\n        renderAfterDocumentEvent: 'render-event'\n      })\n    })\n  ])\n} else {\n  // NODE_ENV === 'development'\n  module.exports.plugins = (module.exports.plugins || []).concat([\n    new webpack.DefinePlugin({\n      'process.env': {\n        NODE_ENV: '\"development\"'\n      }\n    }),\n    new HtmlWebpackPlugin({\n      title: 'DEVELOPMENT prerender-spa-plugin',\n      template: 'index.html',\n      filename: 'index.html'\n    }),\n  ])\n}"
  },
  {
    "path": "index.js",
    "content": "/**\n * @file Just a super-simple wrapper for determining whether to load the original ES6 version\n * of the code or the ES5 version at runtime.\n * @author Joshua Bemenderfer <tribex10@gmail.com>\n */\n\n// Is there a better way to check versions? Haven't really looked into it.\nif (parseInt(process.versions.node.split('.')[0]) >= 8) {\n  // Native (Node 8+) ES6. (Requires async / await.)\n  module.exports = require('./es6/index.js')\n} else {\n  // Transpiled through babel to target Node 4+.\n  module.exports = require('./es5-autogenerated/index.js')\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"prerender-spa-plugin\",\n  \"version\": \"3.4.0\",\n  \"description\": \"Flexible, framework-agnostic static site generation for sites and SPAs built with webpack.\",\n  \"license\": \"MIT\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"build\": \"babel es6 --out-dir es5-autogenerated\",\n    \"prepublishOnly\": \"npm run build\"\n  },\n  \"files\": [\n    \"es6/*\",\n    \"es5-autogenerated/*\"\n  ],\n  \"keywords\": [\n    \"prerender\",\n    \"spa\",\n    \"ssr\",\n    \"serverside-rendering\"\n  ],\n  \"author\": {\n    \"name\": \"Chris Fritz\",\n    \"email\": \"chrisvfritz@gmail.com\",\n    \"url\": \"https://twitter.com/chrisvfritz\"\n  },\n  \"contributors\": [\n    {\n      \"name\": \"Chris Fritz\",\n      \"email\": \"chrisvfritz@gmail.com\",\n      \"url\": \"https://twitter.com/chrisvfritz\"\n    },\n    {\n      \"name\": \"Drew Lustro\",\n      \"url\": \"https://drewlustro.com/\"\n    },\n    {\n      \"name\": \"Joshua Bemenderfer\",\n      \"email\": \"tribex10@gmail.com\",\n      \"url\": \"https://joshderf.com/\"\n    },\n    {\n      \"name\": \"qkdreyer\",\n      \"email\": \"quentin.dreyer@gmail.com\"\n    }\n  ],\n  \"repository\": \"chrisvfritz/prerender-spa-plugin\",\n  \"bugs\": {\n    \"url\": \"https://github.com/chrisvfritz/prerender-spa-plugin/issues\",\n    \"email\": \"chrisvfritz@gmail.com\"\n  },\n  \"dependencies\": {\n    \"@prerenderer/prerenderer\": \"^0.7.2\",\n    \"@prerenderer/renderer-puppeteer\": \"^0.2.0\",\n    \"html-minifier\": \"^3.5.16\"\n  },\n  \"devDependencies\": {\n    \"ava\": \"^3.9.0\",\n    \"babel-cli\": \"^6.24.1\",\n    \"babel-eslint\": \"^8.2.3\",\n    \"babel-plugin-transform-runtime\": \"^6.23.0\",\n    \"babel-preset-env\": \"^1.7.0\",\n    \"babel-preset-stage-2\": \"^6.24.1\",\n    \"eslint\": \"^4.19.1\",\n    \"eslint-config-standard\": \"^5.3.5\",\n    \"eslint-plugin-import\": \"^2.12.0\",\n    \"eslint-plugin-node\": \"^6.0.1\",\n    \"eslint-plugin-promise\": \"^1.3.2\",\n    \"eslint-plugin-standard\": \"^1.3.3\"\n  },\n  \"engines\": {\n    \"node\": \">=4.0.0\"\n  }\n}\n"
  },
  {
    "path": "test/assets/single-route/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>Single Route Rendering Test</title>\n</head>\n<body>\n  <script>\n    document.addEventListener('DOMContentLoaded', () => {\n      document.body.innerHTML = 'Render Successful!'\n    })\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/index.js",
    "content": ""
  },
  {
    "path": "test/single-route.js",
    "content": "module.exports = {\n  name: 'Render Single Route',\n  description: '',\n\n  webpackConfig: {\n\n  },\n\n  isValid (t) {\n\n  }\n}\n"
  }
]