[
  {
    "path": ".gitattributes",
    "content": "# Auto detect text files and perform LF normalization\n* text=auto\n"
  },
  {
    "path": ".github/workflows/sentinel.yml",
    "content": "name: Generate Sentinel Report\n\non:\n  repository_dispatch:\n    types: generate-sentinel-report\n\njobs:\n  build-and-test:\n    name: Build Project\n    runs-on: ubuntu-latest\n    steps:\n      - name: Check Out Repository\n        uses: actions/checkout@v2\n\n      - name: Install Dependencies\n        run: npm ci\n\n      - name: Run Test Suite\n        run: npm run generate-test-report\n\n      - name: Upload Test Report\n        uses: actions/upload-artifact@v1\n        with:\n          name: report\n          path: report.json\n\n  send-data:\n    name: Generate Report\n    needs: build-and-test\n    runs-on: ubuntu-latest\n    steps:\n      - name: Download Report\n        uses: actions/download-artifact@v1\n        with:\n          name: report\n\n      - name: Send Data to Sentinel\n        uses: codebytere/sentinel-client@v1\n\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\nout\nnpm-debug.log\n"
  },
  {
    "path": ".node-version",
    "content": "v8.9.3\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\n\nnode_js:\n  - \"node\"\n  - \"lts/*\"\n\nbefore_script:\n  - export DISPLAY=:99.0\n  - sh -e /etc/init.d/xvfb start\n  - sleep 3\n\nscript:\n  - npm test\n  - npm run package:linux\n\nbranches:\n  only:\n    - master\n\ncache:\n  directories:\n    - node_modules\n\nnotifications:\n  email:\n    on_success: never\n    on_failure: change\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Code of Conduct\n\nAs contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.\n\nWe are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.\n\nExamples of unacceptable behavior by participants include:\n\n- The use of sexualized language or imagery\n- Personal attacks\n- Trolling or insulting/derogatory comments\n- Public or private harassment\n- Publishing other's private information, such as physical or electronic addresses, without explicit permission\n- Other unethical or unprofessional conduct\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.\n\nBy adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.\n\nThis Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at [coc@electronjs.org](mailto:coc@electronjs.org). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident.\n\nThis Code of Conduct is adapted from the Contributor Covenant, version 1.3.0, available from http://contributor-covenant.org/version/1/3/0/\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Electron API Demos\n\n[![JavaScript Standard Style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com)\n\n:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:\n\nThis project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md).\nBy participating, you are expected to uphold this code. Please report unacceptable\nbehavior to [coc@electronjs.org](mailto:coc@electronjs.org).\n\n**See the [documentation](docs.md) for information on how this project works.**\n\n## Code Style & ES6\n\nThis project uses the [JavaScript Standard](http://standardjs.com) style and limited ES6 syntax.\n\nBecause this project is intended for beginners we stick to mostly vanilla JavaScript. One of the features we want illustrate about Electron, however, is that you can use most of ES6 out of the box. To that end, in this project we use these parts of ES6:\n\n- [`const`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const)\n- [`let`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let)\n- [string templates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)\n\n## Pull Requests and Issues\n\nTips for making an easier-to-review contribution:\n\n- Please provide a description.\n- Include screenshots and animated GIFs whenever possible.\n- Use short, present tense commit messages.\n"
  },
  {
    "path": "ISSUE_TEMPLATE.md",
    "content": "* What operating system are you using?\n* What version of Node.js is on your system?\n"
  },
  {
    "path": "README.md",
    "content": "# <img src=\"https://cloud.githubusercontent.com/assets/378023/15172388/b2b81950-1790-11e6-9a7c-ccc39912bb3a.png\" width=\"60px\" align=\"center\" alt=\"Electron API Demos icon\"> Electron API Demos\n\n[![Build Status](https://travis-ci.org/electron/electron-api-demos.svg?branch=master)](https://travis-ci.org/electron/electron-api-demos)\n[![JavaScript Standard Style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com)\n\nThis is a desktop app that interactively and with sample code demonstrates core features of the [Electron](http://electronjs.org) API. It's built with Electron, too, of course. This app works on Windows, macOS and Linux operating systems.\n\nUse this app to see what you can do with Electron and use the source code to learn how to create a basic Electron app.\n\n![Electron API Demos Screenshots](https://cloud.githubusercontent.com/assets/378023/15016148/ae06cc80-124a-11e6-80dd-076d83e492f6.png)\n\n---\n\nThis project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md).\nBy participating, you are expected to uphold this code. Please report unacceptable\nbehavior to [coc@electronjs.org](mailto:coc@electronjs.org).\n\nFollow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important\nannouncements. Visit the [electron website](http://electronjs.org).\n\n## Using\n\nYou can [download the latest release](https://github.com/electron/electron-api-demos/releases) for your operating system or build it yourself (see below).\n\n## Building\n\nYou'll need [Node.js](https://nodejs.org) installed on your computer in order to build this app.\n\n```bash\n$ git clone https://github.com/electron/electron-api-demos\n$ cd electron-api-demos\n$ npm install\n$ npm start\n```\n\nIf you don't wish to clone, you can [download the source code](https://github.com/electron/electron-api-demos/archive/master.zip).\n\nFor easier developing you can launch the app in fullscreen with DevTools open:\n\n```bash\n$ npm run dev\n```\n\n## Extending\n\n [Read the docs](docs.md) to learn more about how this app is built or how to [add a new demo](docs.md#add-a-section-or-demo).\n\n## Translations\n\n* Simplified Chinese translation of this app is available at [`demopark/electron-api-demos-Zh_CN`](https://github.com/demopark/electron-api-demos-Zh_CN).\n* Traditional Chinese translation of this app is available at [`CalvertYang/electron-api-demos-zh-Hant`](https://github.com/CalvertYang/electron-api-demos-zh-Hant).\n* Japanese translation of this app is available at [`LeeDDHH/electron-api-demos-ja`](https://github.com/LeeDDHH/electron-api-demos-ja).\n\nNote: these versions are maintained by outside contributors and may not always be in sync with this version.\n"
  },
  {
    "path": "assets/code-blocks.js",
    "content": "const fs = require('fs')\nconst path = require('path')\n\nconst codeBlocksWithPaths = document.querySelectorAll('code[data-path]')\n\nArray.prototype.forEach.call(codeBlocksWithPaths, (code) => {\n  const codePath = path.join(__dirname, '..', code.dataset.path)\n  const extension = path.extname(codePath)\n  code.classList.add(`language-${extension.substring(1)}`)\n  code.textContent = fs.readFileSync(codePath)\n})\n\ndocument.addEventListener('DOMContentLoaded', () => {\n  const highlight = require('highlight.js')\n  const codeBlocks = document.querySelectorAll('pre code')\n  Array.prototype.forEach.call(codeBlocks, (code) => {\n    highlight.highlightBlock(code)\n  })\n})\n"
  },
  {
    "path": "assets/css/about.css",
    "content": "/* Welcome ------------------------ */\n\n.about {\n  --about-space: 4rem;\n\n  position: absolute;\n  display: flex;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  z-index: 1;\n  overflow-x: hidden;\n  overflow-y: auto;\n  padding: 0;\n  background-color: hsl(0,0%,98%);\n  pointer-events: none;\n  visibility: hidden;\n  opacity: 0;\n  transform: scale(1.1);\n  transition: visibility 0s .12s linear , opacity .12s ease-in, transform .12s ease-in;\n}\n.about.is-shown {\n  pointer-events: auto;\n  visibility: visible;\n  opacity: 1;\n  transform: scale(1);\n  transition: visibility 0s 0s linear , opacity .24s ease-out, transform .24s ease-out;\n}\n\n.about-wrapper {\n  margin: auto;\n}\n\n.about-header {\n  padding: var(--about-space) 0;\n  border-bottom: 1px solid hsl(0,0%,88%);\n}\n\n.about-logo {\n  display: block;\n  margin: 0 auto;\n  width: 320px; /* TODO: Adjust asset to this size */\n  max-width: 100%;\n}\n\n.about-sections {\n  max-width: 680px;\n  padding: 0 var(--about-space);\n}\n\n.about-section {\n  margin: var(--about-space) 0;\n}\n\n.about h2 {\n  text-align: center;\n  margin: 0 0 1em 0;\n  font-size: 1.5em;\n  color: hsl(0, 0%, 55%);\n}\n\n.about .about-code h2 {\n  color: hsl(330, 65%, 55%);\n}\n\n.about .play-along h2 {\n  color: hsl(222, 53%, 50%);\n}\n\n.about-button {\n  display: block;\n  margin: 0 auto;\n  padding: .4em 1.2em;\n  font: inherit;\n  font-size: 1.6em;\n  color: inherit;\n  border: 2px solid;\n  border-radius: 4px;\n  background-color: transparent;\n}\n.about-button:focus {\n  outline: none;\n  border-color: hsl(0,0%,88%);\n}\n\nfooter.about-section {\n  text-align: center;\n}\n\n.rainbow-button-wrapper {\n  --rainbow-button-width: 170px;\n  --rainbow-button-height: 50px;\n  --rainbow-button-width-inner: 164px;\n  --rainbow-button-height-inner: 44px;\n  --rainbow-color-1: hsl(116, 30%, 36%);\n  --rainbow-color-2: hsl(194, 60%, 36%);\n  --rainbow-color-3: hsl(222, 53%, 50%);\n  --rainbow-color-4: hsl(285, 47%, 46%);\n  --rainbow-color-5: hsl(330, 65%, 48%);\n  --rainbow-color-6: hsl(32, 79%, 49%);\n  --rainbow-color-7: hsl(53, 84%, 50%);\n\n  display: inline-block;\n  width: var(--rainbow-button-width);\n  height: var(--rainbow-button-height);\n  position: relative;\n  overflow: hidden;\n  border-radius: 5px;\n}\n\n.rainbow-button-wrapper:before {\n  display: block;\n  position: absolute;\n  z-index: 2;\n  top: 0;\n  left: 0;\n  width: 600px;\n  height: var(--rainbow-button-height);\n  background: #CCC;\n  background: linear-gradient(to right, var(--rainbow-color-1) 0%, var(--rainbow-color-2) 14%, var(--rainbow-color-3) 28%, var(--rainbow-color-4) 42%, var(--rainbow-color-5) 56%, var(--rainbow-color-6) 70%, var(--rainbow-color-7) 84%, var(--rainbow-color-1) 100%);\n  background-position: -200px 0;\n  transition: all 0.5s;\n  content: \"\";\n}\n\n.rainbow-button-wrapper button {\n  display: block;\n  width: var(--rainbow-button-width-inner);\n  height: var(--rainbow-button-height-inner);\n  position: absolute;\n  z-index: 3;\n  top: 3px;\n  left: 3px;\n  border: none;\n  background: white;\n  color: black;\n  font-size: 1.3rem;\n}\n\n.rainbow-button-wrapper:hover:before {\n  background-position: 200px 0;\n}\n\n@media (min-width: 940px) {\n  .about-header {\n    align-self: center;\n    padding: var(--about-space);\n    border-right: 1px solid hsl(0,0%,88%);\n    border-bottom: none;\n  }\n  .about-wrapper {\n    display: flex;\n  }\n}\n"
  },
  {
    "path": "assets/css/demo.css",
    "content": "/* Demo */\n\n.demo:first-of-type {\n  margin-top: 2rem;\n}\n.demo:last-of-type {\n  margin-bottom: 2rem;\n}\n@media (min-width: 940px) {\n  .demo:last-of-type {\n    margin-bottom: 4rem;\n  }\n}\n\n.demo-wrapper {\n  position: relative;\n  max-width: 740px;\n  margin: 0 auto;\n  padding: 0 2rem;\n}\n\n\n/* Toggle Button ----------------------------- */\n\n.demo-toggle-button {\n  position: relative;\n  display: block;\n  margin: 0;\n  padding: .5em 1.5em;\n  line-height: 1.5;\n  font: inherit;\n  font-weight: 600;\n  font-size: 1.2em;\n  text-align: left;\n  border: none;\n  color: inherit;\n  background-color: transparent;\n  transition: border-color .12s;\n  outline: none;\n}\n\n.demo-toggle-button:before,\n.demo-toggle-button:after {\n  content: \"\";\n  position: absolute;\n  left: 0;\n  width: 2px;\n  height: 50%;\n  background-color: hsl(0,0%,88%);\n  transition: transform .2s cubic-bezier(.4,.1,0,1);\n}\n.demo-toggle-button:before {\n  top: 0;\n  transform-origin: bottom center;\n  transform: translateX(.7em) rotate(-30deg) scale(.75);\n}\n.demo-toggle-button:after {\n  bottom: 0;\n  transform-origin: top center;\n  transform: translateX(.7em) rotate(30deg) scale(.75);\n}\n.is-open .demo-toggle-button:before,\n.is-open .demo-toggle-button:after {\n  transform: rotate(0deg);\n}\n.demo-toggle-button:focus:before,\n.demo-toggle-button:focus:after {\n  background-color: currentColor;\n}\n\n/* Meta info */\n\n.demo-meta {\n  margin-top: .2em;\n  font-size: 11px;\n  font-weight: 300;\n  text-transform: uppercase;\n  color: var(--color-subtle);\n}\n.demo-meta-divider {\n  margin: 0 .5em;\n}\n\n\n/* Demo Box ----------------------------- */\n\n.demo-box {\n  display: none;\n  position: relative;\n  padding: 2em;\n  margin-top: 1em;\n  margin-bottom: 2em;\n  border-radius: 6px;\n  border: 1px solid var(--color-border);\n  background-color: var(--color-bg);\n}\n.demo-box:before {\n  content: \"\";\n  position: absolute;\n  top: -11px;\n  width: 20px;\n  height: 20px;\n  background-color: inherit;\n  border-top: inherit;\n  border-right: inherit;\n  border-top-right-radius: 3px;\n  transform: rotate(-45deg);\n}\n\n.is-open .demo-box {\n  display: block;\n  animation: demo-box-fade-in .2s cubic-bezier(0, .20, .20, .96);\n}\n@keyframes demo-box-fade-in {\n    0% { opacity: 0; transform: translateY(-20px); }\n  100% { opacity: 1; transform: translateY(0); }\n}\n\n.demo-box > p:first-child {\n  margin-top: 0;\n}\n\n.demo-box h5 {\n  font-size: 1em;\n  margin-bottom: .6em;\n}\n\n\n/* Demo Controls ----------------------------- */\n\n.demo-controls {\n  display: flex;\n  align-items: center;\n}\n\n.demo-button {\n  align-self: flex-start;\n  margin-right: 1em;\n  border: 2px solid;\n  border-radius: 4px;\n  font: inherit;\n  font-size: 1.2em;\n  padding: .4em 1.2em;\n  color: inherit;\n  background-color: transparent;\n}\n.demo-button:focus {\n  outline: none;\n  background-color: white;\n}\n.demo-button:active {\n  border-color: var(--color-border);\n}\n\n.demo-input {\n  flex: 1;\n  border: 2px solid var(--color-border);\n  border-radius: 4px;\n  font: inherit;\n  font-size: 1.2em;\n  padding: .4em .8em;\n  color: inherit;\n  background-color: transparent;\n}\n.demo-input:focus {\n  outline: none;\n  border-color: hsl(0,0%,80%);\n  background-color: white;\n}\n\n.demo-response {\n  flex: 1;\n  word-break: break-word;\n}\n\n.smooth-appear {\n  opacity: 1;\n  transition: opacity .5s ease-in-out;\n}\n\n.disappear {\n  opacity: 0;\n}\n.demo-button.smooth-disappear:focus {\n  outline: inherit;\n  border-color: inherit;\n  background-color: inherit;\n}\n\n/* ProTip ----------------------------- */\n\n.demo-protip {\n  margin-top: 2rem;\n  padding: 1.5rem 2rem 2rem 2rem;\n  border: 1px solid hsla(0,0%,0%,.06);\n  border-radius: 6px;\n  background: var(--color-accent) linear-gradient(hsla(0,0%,100%,.85), hsla(0,0%,100%,.85));\n}\n.demo-protip h2 {\n  margin: 0 0 .5rem 0;\n}\n.demo-protip strong {\n  font-weight: 600;\n}\n\n"
  },
  {
    "path": "assets/css/github.css",
    "content": "/*\n\ngithub.com style (c) Vasily Polovnyov <vast@whiteants.net>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  color: #333;\n  background: #f8f8f8;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #998;\n  font-style: italic;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-subst {\n  color: #333;\n  font-weight: bold;\n}\n\n.hljs-number,\n.hljs-literal,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-tag .hljs-attr {\n  color: #008080;\n}\n\n.hljs-string,\n.hljs-doctag {\n  color: #d14;\n}\n\n.hljs-title,\n.hljs-section,\n.hljs-selector-id {\n  color: #900;\n  font-weight: bold;\n}\n\n.hljs-subst {\n  font-weight: normal;\n}\n\n.hljs-type,\n.hljs-class .hljs-title {\n  color: #458;\n  font-weight: bold;\n}\n\n.hljs-tag,\n.hljs-name,\n.hljs-attribute {\n  color: #000080;\n  font-weight: normal;\n}\n\n.hljs-regexp,\n.hljs-link {\n  color: #009926;\n}\n\n.hljs-symbol,\n.hljs-bullet {\n  color: #990073;\n}\n\n.hljs-built_in,\n.hljs-builtin-name {\n  color: #0086b3;\n}\n\n.hljs-meta {\n  color: #999;\n  font-weight: bold;\n}\n\n.hljs-deletion {\n  background: #fdd;\n}\n\n.hljs-addition {\n  background: #dfd;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "assets/css/global.css",
    "content": "/* Fonts ---------------------------- */\n\n@font-face {\n  font-family: 'Source Code Pro';\n  font-style: normal;\n  font-weight: 400;\n  src: local('Source Code Pro'), local('SourceCodePro'), url(fonts/SourceCodePro-Regular.ttf) format('truetype');\n}\n\n\n/* Global ---------------------------- */\n\n* {\n  box-sizing: border-box;\n}\n\nhtml {\n  height: 100%;\n  font-family: 'BlinkMacSystemFont', 'Lucida Grande', 'Segoe UI', Ubuntu, Cantarell, sans-serif;\n  font-size: 14px;\n  line-height: 1.5;\n  overflow: hidden; /* Prevents rubber-band scrolling of the whole \"page\" */\n  color: var(--color);\n  background-color: #fff; /* To cover OSes with no default background color */\n}\n\nbody {\n  margin: 0;\n  height: 100%;\n  display: flex;\n}\n\na {\n  color: var(--color-link);\n}\n\nh1,\nh2,\nh3 {\n  margin-top: 0;\n  line-height: 1.5;\n}\n\nh1 {\n  font-size: 1.5em;\n  font-weight: 600;\n}\n\nh2 {\n  font-size: 1.3em;\n  font-weight: normal;\n}\n\nh3 {\n  font-size: 1.12em;\n  font-weight: 600;\n}\n\ntable {\n  width: 100%;\n  border-spacing: 0;\n  border: 1px solid hsla(0,0%,0%,.08);\n  border-width: 0 1px 1px 0;\n}\nth {\n  background-color: hsla(0,0%,50%,.06);\n}\nth,\ntd {\n  text-align: center;\n  border: 1px solid hsla(0,0%,0%,.08);\n  border-width: 1px 0 0 1px;\n}\n\nsvg {\n  fill: currentColor;\n}\n\n/* Code */\n\ncode, kbd {\n  font-family: 'Source Code Pro', monospace;\n  border-radius: 4px;\n  padding: 1px 4px;\n  white-space: nowrap;\n  color: hsl(0,0%,36%);\n  background-color: hsla(0,0%,60%,.15);\n}\n\npre, kbd {\n  font-size: 13px;\n  overflow: auto;\n  padding: 1em;\n  margin: 0;\n  border-radius: 4px;\n  border: 1px solid;\n  border-color: var(--color-border);\n  background-color: white;\n}\n\npre code {\n  white-space: pre;\n}\n\npre > .hljs {\n  color: var(--color-subtle);\n  background-color: white;\n}\n\nkbd {\n  padding: 0.5em;\n}\n\n\n/* Utilities ---------------------------- */\n\n.u-avoid-clicks {\n  pointer-events: none;\n}\n\n/* Visually hidden, but will be read by screen readers */\n.u-visible-to-screen-reader {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  padding: 0;\n  margin: -1px;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  border: 0;\n}\n\n.no-display {\n  display: none;\n}\n\n\n/* Content ------------------ */\n\n.content {\n  flex: 1;\n  position: relative;\n  overflow: hidden;\n  visibility: hidden;\n  opacity: 0;\n}\n.content.is-shown {\n  visibility: visible;;\n  opacity: 1;\n}\n\n\n/* Hacks ---------------------------- */\n\n/* Fixes horizontal scrolling in code blocks on OS X El Cap (10.11.3), retina screen\n *\n * By adding an invisible outline property, it will force a repaint\n * which enables the scrolling.\n */\n\n.hljs:hover,\n.hljs:active {\n  outline: 1px solid transparent;\n}\n"
  },
  {
    "path": "assets/css/nativize.css",
    "content": "/*\n** nativize.css\n** Makes the UI feel more native\n*/\n\nhtml {\n  font-family: sans-serif;\n  user-select: none; /* disable selection */\n  -webkit-user-drag: none; /* disable dragging */\n  cursor: default; /* use default cursor */\n}\n\nbody {\n  margin: 0; /* remove default margin */\n}\n\n\n/* enable text selection */\n\n.is-selectable,\npre,\ncode {\n  user-select: text;\n  cursor: auto;\n}\n\n\n/* Buttons and links */\n\nbutton{\n  cursor: default;\n}\n\n/* Internal links */\na {\n  cursor: pointer;\n  text-decoration: none;\n  border-bottom: 1px dashed;\n  outline: none;\n}\n\n/* New window (target) + external links */\na[target],\na[href^=\"https://\"],\na[href^=\"http://\"] {\n  border-bottom: 1px solid;\n}\n\na:hover,\na:focus {\n  border-bottom: none;\n}\n\n\n/* Images */\n\nimg {\n  -webkit-user-drag: none; /* disable dragging */\n}\n"
  },
  {
    "path": "assets/css/nav.css",
    "content": "/* Nav */\n\n.nav {\n  width: 340px;\n  overflow-x: hidden;\n  overflow-y: auto;\n  color: var(--color-subtle);\n  border-right: 1px solid var(--color-border);\n  background-color: var(--color-bg);\n  visibility: hidden;\n  opacity: 0;\n}\n.nav.is-shown {\n  visibility: visible;;\n  opacity: 1;\n}\n\n.nav-header {\n  position: relative;\n  padding: 2rem;\n  margin-bottom: 1rem;\n  border-bottom: 1px solid var(--color-border);\n}\n\n.nav-title {\n  text-transform: uppercase;\n  font-weight: 300;\n  line-height: 1;\n  margin: 0;\n}\n\n.nav-title strong {\n  font-weight: 600;\n  color: var(--color-strong);\n}\n\n.nav-header-icon {\n  position: absolute;\n  width: 36px;\n  height: 36px;\n  top: 1.5rem; /* magic */\n  right: 1.75rem; /* magic */\n}\n\n\n\n.nav-item {\n  padding: .5em 0;\n}\n\n.nav-icon {\n  width: 16px;\n  height: 16px;\n  vertical-align: top;\n  margin-right: .25rem;\n}\n\n.nav-category {\n  margin: .2em 0;\n  padding-left: 2rem;\n  font-size: 11px;\n  font-weight: normal;\n  text-transform: uppercase;\n}\n\n.nav-button {\n  display: block;\n  width: 100%;\n  padding: .3rem;\n  padding-left: calc(2rem + 16px + .5rem); /* padding + icon + magic */\n  line-height: 2;\n  text-align: left;\n  font: inherit;\n  font-size: 13px;\n  color: inherit;\n  border: none;\n  background-color: transparent;\n  cursor: default;\n  outline: none;\n}\n.nav-button:hover,\n.nav-button:focus:not(.is-selected) {\n  background-color: hsla(0,0%,0%,.1);\n}\n.nav-button.is-selected {\n  background-color: var(--color-accent);\n}\n.nav-button.is-selected,\n.nav-button.is-selected em {\n  color: #fff;\n}\n.nav-button.is-selected:focus {\n  opacity: .8;\n}\n\n.nav-button em {\n  font-style: normal;\n  font-weight: 600;\n  color: var(--color-strong);\n  pointer-events: none; /* makes it invisible to clicks */\n}\n\n.nav-footer {\n  margin-top: 1rem;\n  padding: 2rem;\n  border-top: 1px solid var(--color-border);\n  text-align: center;\n}\n\n.nav-footer-icon {\n  width: calc(770px / 6.5);\n  height: calc(88px / 6.5);\n}\n\n.nav-footer a {\n  outline: none;\n}\n\n.nav-footer-button {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: .75rem;\n  line-height: 2;\n  text-align: left;\n  font: inherit;\n  font-size: 13px;\n  color: inherit;\n  border: none;\n  background-color: transparent;\n  cursor: default;\n  outline: none;\n  text-align: center;\n}\n.nav-footer-button:focus {\n  color: var(--color-strong);\n}\n\n.nav-footer-logo {\n  color: hsl(0,0%,66%);\n}\n.nav-footer-logo:focus {\n  color: hsl(0,0%,33%);\n}\n\n/* Remove border on the logo */\n.nav-footer-logo.nav-footer-logo {\n  border-bottom: none;\n}\n"
  },
  {
    "path": "assets/css/print.css",
    "content": "@media print {\n  body {\n    background: none;\n    color: black !important;\n    font-size: 70%;\n    margin: 0; padding: 0;\n  }\n\n  h1 {\n    font-size: 22px;\n  }\n\n  .nav, button, .demo-box:before,\n  header p {\n    display: none;\n  }\n\n  .demo-box, h2,\n  pre, code {\n    padding: 0 !important;\n    margin: 0 !important;\n  }\n\n  header {\n    padding: 0 0 10px 0;\n  }\n\n  code, .support {\n    font-size: 10px;\n  }\n}\n"
  },
  {
    "path": "assets/css/section.css",
    "content": "/* Section ------------------ */\n\n.section {\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  overflow-x: hidden;\n  overflow-y: auto;\n  color: var(--color-accent);\n\n  /* Hide */\n  pointer-events: none;\n  visibility: hidden;\n  opacity: 0;\n  transform: translateX(-20px);\n  transition: visibility 0s .12s linear , opacity .12s ease-in, transform .12s ease-in;\n}\n.section.is-shown {\n  pointer-events: auto;\n  visibility: visible;\n  opacity: 1;\n  transform: translateX(0);\n  transition: visibility 0s 0s linear , opacity .36s ease-out, transform .36s ease-out;\n}\n\n.section h3,\n.section p {\n  color: var(--color);\n}\n\n.section-wrapper {\n  position: relative;\n  max-width: 740px;\n  margin: 0 auto;\n  padding: 2rem 2rem 1rem 2rem;\n  border-bottom: 1px solid var(--color-border);\n}\n@media (min-width: 940px) {\n  .section-wrapper {\n    padding-top: 4rem;\n  }\n}\n\n.section-icon {\n  width: 32px;\n  height: 32px;\n  vertical-align: middle;\n  margin-right: .5em;\n}\n"
  },
  {
    "path": "assets/css/variables.css",
    "content": "\n/* Custom Properties */\n\n:root {\n  --color:          hsl(0,0%,22%);\n  --color-subtle:   hsl(0,0%,44%);\n  --color-strong:   hsl(0,0%,11%);\n  --color-link:     hsl(0,0%,22%);\n\n  --color-border:   hsl(0,0%,88%);\n  --color-bg:       hsl(0,0%,96%);\n\n  --color-accent:   black; /* Fallback */\n}\n\n\n/* Category Colors */\n\n.u-category-windows       { --color-accent: hsl(116, 30%, 36%); }\n.u-category-menu          { --color-accent: hsl(194, 60%, 36%); }\n.u-category-native-ui     { --color-accent: hsl(222, 53%, 50%); }\n.u-category-communication { --color-accent: hsl(285, 47%, 46%); }\n.u-category-system        { --color-accent: hsl(330, 65%, 48%); }\n.u-category-media      { --color-accent: hsl( 36, 77%, 34%); }\n"
  },
  {
    "path": "assets/demo-btns.js",
    "content": "const settings = require('electron-settings')\n\nconst demoBtns = document.querySelectorAll('.js-container-target')\n// Listen for demo button clicks\nArray.prototype.forEach.call(demoBtns, (btn) => {\n  btn.addEventListener('click', (event) => {\n    const parent = event.target.parentElement\n\n    // Toggles the \"is-open\" class on the demo's parent element.\n    parent.classList.toggle('is-open')\n\n    // Saves the active demo if it is open, or clears it if the demo was user\n    // collapsed by the user\n    if (parent.classList.contains('is-open')) {\n      settings.set('activeDemoButtonId', event.target.getAttribute('id'))\n    } else {\n      settings.delete('activeDemoButtonId')\n    }\n  })\n})\n\n// Default to the demo that was active the last time the app was open\nconst buttonId = settings.get('activeDemoButtonId')\nif (buttonId) {\n  document.getElementById(buttonId).click()\n}\n"
  },
  {
    "path": "assets/ex-links.js",
    "content": "const shell = require('electron').shell\n\nconst links = document.querySelectorAll('a[href]')\n\nArray.prototype.forEach.call(links, (link) => {\n  const url = link.getAttribute('href')\n  if (url.indexOf('http') === 0) {\n    link.addEventListener('click', (e) => {\n      e.preventDefault()\n      shell.openExternal(url)\n    })\n  }\n})\n"
  },
  {
    "path": "assets/imports.js",
    "content": "const links = document.querySelectorAll('link[rel=\"import\"]')\n\n// Import and add each page to the DOM\nArray.prototype.forEach.call(links, (link) => {\n  let template = link.import.querySelector('.task-template')\n  let clone = document.importNode(template.content, true)\n  if (link.href.match('about.html')) {\n    document.querySelector('body').appendChild(clone)\n  } else {\n    document.querySelector('.content').appendChild(clone)\n  }\n})\n"
  },
  {
    "path": "assets/mac/child.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n  <dict>\n    <key>com.apple.security.app-sandbox</key>\n    <true/>\n    <key>com.apple.security.inherit</key>\n    <true/>\n  </dict>\n</plist>\n"
  },
  {
    "path": "assets/mac/info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n  <key>CFBundleURLTypes</key>\n  <array>\n    <dict>\n      <key>CFBundleURLSchemes</key>\n      <array>\n        <string>electron-api-demos</string>\n      </array>\n      <key>CFBundleURLName</key>\n      <string>Electron API Demos Protocol</string>\n    </dict>\n  </array>\n  <key>ElectronTeamID</key>\n  <string>VEKTX9H2N7</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "assets/mac/parent.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n  <dict>\n    <key>com.apple.security.app-sandbox</key>\n    <true/>\n    <key>com.apple.security.application-groups</key>\n    <string>VEKTX9H2N7.com.github.electron-api-demos</string>\n    <key>com.apple.security.files.user-selected.read-write</key>\n    <true/>\n  </dict>\n</plist>\n"
  },
  {
    "path": "assets/nav.js",
    "content": "const settings = require('electron-settings')\n\ndocument.body.addEventListener('click', (event) => {\n  if (event.target.dataset.section) {\n    handleSectionTrigger(event)\n  } else if (event.target.dataset.modal) {\n    handleModalTrigger(event)\n  } else if (event.target.classList.contains('modal-hide')) {\n    hideAllModals()\n  }\n})\n\nfunction handleSectionTrigger (event) {\n  hideAllSectionsAndDeselectButtons()\n\n  // Highlight clicked button and show view\n  event.target.classList.add('is-selected')\n\n  // Display the current section\n  const sectionId = `${event.target.dataset.section}-section`\n  document.getElementById(sectionId).classList.add('is-shown')\n\n  // Save currently active button in localStorage\n  const buttonId = event.target.getAttribute('id')\n  settings.set('activeSectionButtonId', buttonId)\n}\n\nfunction activateDefaultSection () {\n  document.getElementById('button-windows').click()\n}\n\nfunction showMainContent () {\n  document.querySelector('.js-nav').classList.add('is-shown')\n  document.querySelector('.js-content').classList.add('is-shown')\n}\n\nfunction handleModalTrigger (event) {\n  hideAllModals()\n  const modalId = `${event.target.dataset.modal}-modal`\n  document.getElementById(modalId).classList.add('is-shown')\n}\n\nfunction hideAllModals () {\n  const modals = document.querySelectorAll('.modal.is-shown')\n  Array.prototype.forEach.call(modals, (modal) => {\n    modal.classList.remove('is-shown')\n  })\n  showMainContent()\n}\n\nfunction hideAllSectionsAndDeselectButtons () {\n  const sections = document.querySelectorAll('.js-section.is-shown')\n  Array.prototype.forEach.call(sections, (section) => {\n    section.classList.remove('is-shown')\n  })\n\n  const buttons = document.querySelectorAll('.nav-button.is-selected')\n  Array.prototype.forEach.call(buttons, (button) => {\n    button.classList.remove('is-selected')\n  })\n}\n\nfunction displayAbout () {\n  document.querySelector('#about-modal').classList.add('is-shown')\n}\n\n// Default to the view that was active the last time the app was open\nconst sectionId = settings.get('activeSectionButtonId')\nif (sectionId) {\n  showMainContent()\n  const section = document.getElementById(sectionId)\n  if (section) section.click()\n} else {\n  activateDefaultSection()\n  displayAbout()\n}\n"
  },
  {
    "path": "assets/normalize-shortcuts.js",
    "content": "const normalize = require('electron-shortcut-normalizer')\nlet shortcuts = document.querySelectorAll('kbd.normalize-to-platform')\n\nArray.prototype.forEach.call(shortcuts, (shortcut) => {\n  shortcut.innerText = normalize(shortcut.innerText, process.platform)\n})\n"
  },
  {
    "path": "cli.js",
    "content": "#!/usr/bin/env node\n\nconst {spawn} = require('child_process')\nconst electron = require('electron')\nconst path = require('path')\n\nconst appPath = path.join(__dirname, 'main.js')\nconst args = [appPath].concat(process.argv.slice(2))\nconst proc = spawn(electron, args, {stdio: 'inherit'})\n\nproc.on('close', (code) => process.exit(code))\n"
  },
  {
    "path": "docs.md",
    "content": "# Documentation\n\nThis app has been developed to be a lightweight Electron app, demonstrating how to create a basic Electron app with a few exceptions that have been made for the sake of code organization in regards to the demos themselves.\n\nAll of the sample code shown in the app _is the actual code used in the app_. These JavaScript bits have been pulled out into their own file and organized by process (main or renderer) and then by section (communication, menus, native UI, media, system, windows).\n\nThis was done for maintainability—code updates only have to be made in one place—and organization—it's easy to find the sample code you're looking for.\n\nAll of the pages (or views) are separate `.html` files which are appended onto the `index.html` using [HTML imports](http://www.html5rocks.com/en/tutorials/webcomponents/imports/).\n\nAre you looking to add a demo? Jump to the [add a new demo section](#add-a-section-or-demo).\n\n## Folder Structure\n\n![Diagram of App Structure and Operations](/assets/img/diagram.png)\n\n#### `assets`\nThis directory contains assets for the app itself: CSS, fonts, images and shared JavaScript libraries or helpers.\n\n#### `main-process`\nThis directory contains sub folders for each demo section that requires JavaScript in the main process. This structure is mirrored in the `renderer-process` directory.\n\nThe `main.js` file, located in the root, takes each `.js` file in these directories and executes them.\n\n#### `renderer-process`\nThis directory contains sub folders for each demo section that requires JavaScript in the renderer process. This structure is mirrored in the `main-process` directory.\n\nEach of the HTML page views requires the corresponding renderer-process `.js` files that it needs for its demo.\n\nEach page view reads the content of its relevant main and renderer process files and adds them to the page for the snippets.\n\n#### `sections`\nThis directory contains sub folders for each demo section. These subfolders contain the HTML files for each of the demo pages. Each of these files is appended to `index.html`, located at the root.\n\n#### `index.html`\nThis is the main view in the app. It contains the sidebar with navigation and uses [HTML imports](http://www.html5rocks.com/en/tutorials/webcomponents/imports/) to append each section HTML page to the `body`.\n\n#### `main.js`\nThis file contains the lifecycle instructions for the app like how to start and quit, it is the app's main process. It grabs every `.js` file in the `main-process` directory and executes.\n\nThe `package.json` sets this file as the `main` file.\n\n#### `package.json`\nThis file is required when using `npm` and Electron.js. It contains details on the app: the author, dependencies, repository and points to `main.js` as the application's main process file.\n\n#### Docs\nThe files: `CODE_OF_CONDUCT`, `README`, `docs` and `CONTRIBUTING` files make up the documentation for the project.\n\n## UI Terminology\n\n![UI Terminology](/assets/img/ui-terminology.png)\n\n## CSS Naming Convention\n\nNothing too strict and used more as a guide:\n\n- Styling elements directly should be avoided, but ok in some cases. Like `<p>` or `<code>`.\n- Elements that belong together are prefixed with their parent class. `.section`, `.section-header`, `.section-icon`.\n- States use `is-` prefix\n- Utilities use `u-` prefix\n\n## Add a Section or Demo\n\nHere are tips for covering the bases when adding a new section or demo. General tip—for some of these just copy the line or file of a similar existing item to get started!\n\n### New Section\n\nA whole new page with one or more demos.\n\n#### index.html\n\nThis page contains the sidebar list of sections as well as each section template that is imported with HTML imports.\n\n- Add demo to sidebar in the appropriate category in `index.html`\n - update `id` i.e. `id=\"button-dialogs\"`\n - update `data-section` i.e. `data-section=\"dialogs\"`\n- Add demo template path to the import links in the `head` of `index.html`\n - i.e. `<link rel=\"import\" href=\"sections/native-ui/dialogs.html\">`\n\n#### Template\n\nThis template is added to the `index.html` in the app.\n\n- In the `sections` directory, copy an existing template `html` file from the category you're adding a section to.\n- Update these tags `id`\n - i.e. `id=\"dialogs-section\"`\n- Update all the text in the `header` tag with text relevant to your new section.\n - Remove the demos and pro-tips as needed.\n\n### Demo\n\nAny code that you create for your demo should be added to the 'main-process' or 'renderer-process' directories depending on where it runs.\n\nAll JavaScript files within the 'main-process' directory are run when the app starts but you'll link to the file so that it is displayed within your demo (see below).\n\nThe renderer process code you add will be read and displayed within the demo and then required on the template page so that it runs in that process (see below).\n\n- Start by copying and pasting an existing `<div class=\"demo\">` blocks from the template page.\n- Update the demo button `id`\n - i.e `<button class=\"demo-button\" id=\"information-dialog\">View Demo</button>`\n- If demo includes a response written to the DOM, update that `id`, otherwise delete:\n - i.e. `<span class=\"demo-response\" id=\"info-selection\"></span>`\n- Update the text describing your demo.\n- If you are displaying main or renderer process sample code, include or remove that markup accordingly.\n - Sample code is read and added to the DOM by adding the path to the code in the `data-path`\n   - i.e. `<pre><code data-path=\"renderer-process/native-ui/dialogs/information.js\"></pre></code>`\n - Require your render process code in the script tag at the bottom of the template\n   - i.e  `require('./renderer-process/native-ui/dialogs/information')`\n\n#### Try it out\n\nAt this point you should be able to run the app, `npm start`, and see your section and/or demo. :tada:\n"
  },
  {
    "path": "index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n\n  <link rel=\"stylesheet\" href=\"assets/css/variables.css\">\n  <link rel=\"stylesheet\" href=\"assets/css/nativize.css\">\n  <link rel=\"stylesheet\" href=\"assets/css/global.css\">\n  <link rel=\"stylesheet\" href=\"assets/css/about.css\">\n  <link rel=\"stylesheet\" href=\"assets/css/nav.css\">\n  <link rel=\"stylesheet\" href=\"assets/css/section.css\">\n  <link rel=\"stylesheet\" href=\"assets/css/demo.css\">\n  <link rel=\"stylesheet\" href=\"assets/css/github.css\">\n\n  <link rel=\"import\" href=\"sections/about.html\">\n  <link rel=\"import\" href=\"sections/windows/windows.html\">\n  <link rel=\"import\" href=\"sections/windows/crash-hang.html\">\n  <link rel=\"import\" href=\"sections/menus/menus.html\">\n  <link rel=\"import\" href=\"sections/menus/shortcuts.html\">\n  <link rel=\"import\" href=\"sections/native-ui/ex-links-file-manager.html\">\n  <link rel=\"import\" href=\"sections/native-ui/notifications.html\">\n  <link rel=\"import\" href=\"sections/native-ui/dialogs.html\">\n  <link rel=\"import\" href=\"sections/native-ui/tray.html\">\n  <link rel=\"import\" href=\"sections/native-ui/drag.html\">\n  <link rel=\"import\" href=\"sections/communication/ipc.html\">\n  <link rel=\"import\" href=\"sections/system/app-sys-information.html\">\n  <link rel=\"import\" href=\"sections/system/clipboard.html\">\n  <link rel=\"import\" href=\"sections/system/protocol-handler.html\">\n  <link rel=\"import\" href=\"sections/media/desktop-capturer.html\">\n</head>\n<body>\n\n  <nav class=\"nav js-nav\">\n    <header class=\"nav-header\">\n      <h1 class=\"nav-title\">Electron <strong>API Demos</strong></h1>\n      <svg class=\"nav-header-icon\"><use xlink:href=\"assets/img/icons.svg#icon-electron\"></use></svg>\n    </header>\n\n    <div class=\"nav-item u-category-windows\">\n      <h5 class=\"nav-category\">\n        <svg class=\"nav-icon\"><use xlink:href=\"assets/img/icons.svg#icon-windows\"></use></svg>\n        Windows\n      </h5>\n      <button type=\"button\" id=\"button-windows\" data-section=\"windows\" class=\"nav-button\">Create and manage <em>windows</em></button>\n      <button type=\"button\" id=\"button-crash-hang\" data-section=\"crash-hang\" class=\"nav-button\">Handling window <em>crashes and hangs</em></button>\n    </div>\n\n    <div class=\"nav-item u-category-menu\">\n      <h5 class=\"nav-category\">\n        <svg class=\"nav-icon\"><use xlink:href=\"assets/img/icons.svg#icon-menu\"></use></svg>\n        Menus\n      </h5>\n      <button type=\"button\" id=\"button-menus\" data-section=\"menus\" class=\"nav-button\">Customize <em>menus</em> </button>\n      <button type=\"button\" id=\"button-shortcuts\" data-section=\"shortcuts\" class=\"nav-button\">Register keyboard <em>shortcuts</em></button>\n    </div>\n\n    <div class=\"nav-item u-category-native-ui\">\n      <h5 class=\"nav-category\">\n        <svg class=\"nav-icon\"><use xlink:href=\"assets/img/icons.svg#icon-native-ui\"></use></svg>\n        Native User Interface</h5>\n      <button type=\"button\" id=\"button-ex-links-file-manager\" data-section=\"ex-links-file-manager\" class=\"nav-button\">Open <em>external links</em> or system <em>file manager</em></button>\n      <button type=\"button\" id=\"button-notifications\" data-section=\"notifications\" class=\"nav-button\"> <em>Notifications</em> with and without custom image</button>\n      <button type=\"button\" id=\"button-dialogs\" data-section=\"dialogs\" class=\"nav-button\">Use system <em>dialogs</em></button>\n      <button type=\"button\" id=\"button-tray\" data-section=\"tray\" class=\"nav-button\">Put your app in the <em>tray</em></button>\n      <button type=\"button\" id=\"button-drag\" data-section=\"drag\" class=\"nav-button\"><em>Drag</em> and drop files</button>\n    </div>\n\n    <div class=\"nav-item u-category-communication\">\n      <h5 class=\"nav-category\">\n        <svg class=\"nav-icon\"><use xlink:href=\"assets/img/icons.svg#icon-communication\"></use></svg>\n        Communication\n      </h5>\n      <button type=\"button\" id=\"button-ipc\" data-section=\"ipc\" class=\"nav-button\">Communicate between the <em>two processes</em></button>\n    </div>\n\n    <div class=\"nav-item u-category-system\">\n      <h5 class=\"nav-category\">\n        <svg class=\"nav-icon\"><use xlink:href=\"assets/img/icons.svg#icon-system\"></use></svg>\n        System\n      </h5>\n      <button type=\"button\" id=\"button-app-sys-information\" data-section=\"app-sys-information\" class=\"nav-button\" >Get app or user <em>system information</em></button>\n      <button type=\"button\" id=\"button-clipboard\" data-section=\"clipboard\" class=\"nav-button\">Copy and paste from the <em>clipboard</em></button>\n      <button type=\"button\" id=\"button-protocol\" data-section=\"protocol\" class=\"nav-button\">Launch app from <em>protocol handler</em></button>\n    </div>\n\n    <div class=\"nav-item u-category-media\">\n      <h5 class=\"nav-category\">\n        <svg class=\"nav-icon\"><use xlink:href=\"assets/img/icons.svg#icon-media\"></use></svg>\n        Media\n      </h5>\n      <button type=\"button\" id=\"button-desktop-capturer\" data-section=\"desktop-capturer\" class=\"nav-button\">Take a <em>screenshot</em></button>\n    </div>\n\n    <footer class=\"nav-footer\">\n      <button type=\"button\" id=\"button-about\" data-modal=\"about\" class=\"nav-footer-button\">About</button>\n      <a class=\"nav-footer-logo\" href=\"https://github.com\" aria-label=\"Homepage\">\n        <svg class=\"nav-footer-icon\"><use xlink:href=\"assets/img/icons.svg#icon-love\"></use></svg>\n      </a>\n    </footer>\n  </nav>\n\n  <main class=\"content js-content\"></main>\n\n  <script>\n    require('./assets/imports')\n    require('./assets/ex-links')\n    require('./assets/nav')\n    require('./assets/demo-btns')\n    require('./assets/code-blocks')\n    require('./assets/normalize-shortcuts')\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "license.md",
    "content": "MIT License\n\nCopyright (c) 2016-2018 GitHub Inc.\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": "main-process/communication/async-msg.js",
    "content": "const {ipcMain} = require('electron')\n\nipcMain.on('asynchronous-message', (event, arg) => {\n  event.sender.send('asynchronous-reply', 'pong')\n})\n"
  },
  {
    "path": "main-process/communication/sync-msg.js",
    "content": "const {ipcMain} = require('electron')\n\nipcMain.on('synchronous-message', (event, arg) => {\n  event.returnValue = 'pong'\n})\n"
  },
  {
    "path": "main-process/menus/application-menu.js",
    "content": "const {BrowserWindow, Menu, app, shell, dialog} = require('electron')\n\nlet template = [{\n  label: 'Edit',\n  submenu: [{\n    label: 'Undo',\n    accelerator: 'CmdOrCtrl+Z',\n    role: 'undo'\n  }, {\n    label: 'Redo',\n    accelerator: 'Shift+CmdOrCtrl+Z',\n    role: 'redo'\n  }, {\n    type: 'separator'\n  }, {\n    label: 'Cut',\n    accelerator: 'CmdOrCtrl+X',\n    role: 'cut'\n  }, {\n    label: 'Copy',\n    accelerator: 'CmdOrCtrl+C',\n    role: 'copy'\n  }, {\n    label: 'Paste',\n    accelerator: 'CmdOrCtrl+V',\n    role: 'paste'\n  }, {\n    label: 'Select All',\n    accelerator: 'CmdOrCtrl+A',\n    role: 'selectall'\n  }]\n}, {\n  label: 'View',\n  submenu: [{\n    label: 'Reload',\n    accelerator: 'CmdOrCtrl+R',\n    click: (item, focusedWindow) => {\n      if (focusedWindow) {\n        // on reload, start fresh and close any old\n        // open secondary windows\n        if (focusedWindow.id === 1) {\n          BrowserWindow.getAllWindows().forEach(win => {\n            if (win.id > 1) win.close()\n          })\n        }\n        focusedWindow.reload()\n      }\n    }\n  }, {\n    label: 'Toggle Full Screen',\n    accelerator: (() => {\n      if (process.platform === 'darwin') {\n        return 'Ctrl+Command+F'\n      } else {\n        return 'F11'\n      }\n    })(),\n    click: (item, focusedWindow) => {\n      if (focusedWindow) {\n        focusedWindow.setFullScreen(!focusedWindow.isFullScreen())\n      }\n    }\n  }, {\n    label: 'Toggle Developer Tools',\n    accelerator: (() => {\n      if (process.platform === 'darwin') {\n        return 'Alt+Command+I'\n      } else {\n        return 'Ctrl+Shift+I'\n      }\n    })(),\n    click: (item, focusedWindow) => {\n      if (focusedWindow) {\n        focusedWindow.toggleDevTools()\n      }\n    }\n  }, {\n    type: 'separator'\n  }, {\n    label: 'App Menu Demo',\n    click: function (item, focusedWindow) {\n      if (focusedWindow) {\n        const options = {\n          type: 'info',\n          title: 'Application Menu Demo',\n          buttons: ['Ok'],\n          message: 'This demo is for the Menu section, showing how to create a clickable menu item in the application menu.'\n        }\n        dialog.showMessageBox(focusedWindow, options, function () {})\n      }\n    }\n  }]\n}, {\n  label: 'Window',\n  role: 'window',\n  submenu: [{\n    label: 'Minimize',\n    accelerator: 'CmdOrCtrl+M',\n    role: 'minimize'\n  }, {\n    label: 'Close',\n    accelerator: 'CmdOrCtrl+W',\n    role: 'close'\n  }, {\n    type: 'separator'\n  }, {\n    label: 'Reopen Window',\n    accelerator: 'CmdOrCtrl+Shift+T',\n    enabled: false,\n    key: 'reopenMenuItem',\n    click: () => {\n      app.emit('activate')\n    }\n  }]\n}, {\n  label: 'Help',\n  role: 'help',\n  submenu: [{\n    label: 'Learn More',\n    click: () => {\n      shell.openExternal('http://electron.atom.io')\n    }\n  }]\n}]\n\nfunction addUpdateMenuItems (items, position) {\n  if (process.mas) return\n\n  const version = app.getVersion()\n  let updateItems = [{\n    label: `Version ${version}`,\n    enabled: false\n  }, {\n    label: 'Checking for Update',\n    enabled: false,\n    key: 'checkingForUpdate'\n  }, {\n    label: 'Check for Update',\n    visible: false,\n    key: 'checkForUpdate',\n    click: () => {\n      require('electron').autoUpdater.checkForUpdates()\n    }\n  }, {\n    label: 'Restart and Install Update',\n    enabled: true,\n    visible: false,\n    key: 'restartToUpdate',\n    click: () => {\n      require('electron').autoUpdater.quitAndInstall()\n    }\n  }]\n\n  items.splice.apply(items, [position, 0].concat(updateItems))\n}\n\nfunction findReopenMenuItem () {\n  const menu = Menu.getApplicationMenu()\n  if (!menu) return\n\n  let reopenMenuItem\n  menu.items.forEach(item => {\n    if (item.submenu) {\n      item.submenu.items.forEach(item => {\n        if (item.key === 'reopenMenuItem') {\n          reopenMenuItem = item\n        }\n      })\n    }\n  })\n  return reopenMenuItem\n}\n\nif (process.platform === 'darwin') {\n  const name = app.getName()\n  template.unshift({\n    label: name,\n    submenu: [{\n      label: `About ${name}`,\n      role: 'about'\n    }, {\n      type: 'separator'\n    }, {\n      label: 'Services',\n      role: 'services',\n      submenu: []\n    }, {\n      type: 'separator'\n    }, {\n      label: `Hide ${name}`,\n      accelerator: 'Command+H',\n      role: 'hide'\n    }, {\n      label: 'Hide Others',\n      accelerator: 'Command+Alt+H',\n      role: 'hideothers'\n    }, {\n      label: 'Show All',\n      role: 'unhide'\n    }, {\n      type: 'separator'\n    }, {\n      label: 'Quit',\n      accelerator: 'Command+Q',\n      click: () => {\n        app.quit()\n      }\n    }]\n  })\n\n  // Window menu.\n  template[3].submenu.push({\n    type: 'separator'\n  }, {\n    label: 'Bring All to Front',\n    role: 'front'\n  })\n\n  addUpdateMenuItems(template[0].submenu, 1)\n}\n\nif (process.platform === 'win32') {\n  const helpMenu = template[template.length - 1].submenu\n  addUpdateMenuItems(helpMenu, 0)\n}\n\napp.on('ready', () => {\n  const menu = Menu.buildFromTemplate(template)\n  Menu.setApplicationMenu(menu)\n})\n\napp.on('browser-window-created', () => {\n  let reopenMenuItem = findReopenMenuItem()\n  if (reopenMenuItem) reopenMenuItem.enabled = false\n})\n\napp.on('window-all-closed', () => {\n  let reopenMenuItem = findReopenMenuItem()\n  if (reopenMenuItem) reopenMenuItem.enabled = true\n})\n"
  },
  {
    "path": "main-process/menus/context-menu.js",
    "content": "const {\n  BrowserWindow,\n  Menu,\n  MenuItem,\n  ipcMain,\n  app\n} = require('electron')\n\nconst menu = new Menu()\nmenu.append(new MenuItem({ label: 'Hello' }))\nmenu.append(new MenuItem({ type: 'separator' }))\nmenu.append(new MenuItem({ label: 'Electron', type: 'checkbox', checked: true }))\n\napp.on('browser-window-created', (event, win) => {\n  win.webContents.on('context-menu', (e, params) => {\n    menu.popup(win, params.x, params.y)\n  })\n})\n\nipcMain.on('show-context-menu', (event) => {\n  const win = BrowserWindow.fromWebContents(event.sender)\n  menu.popup(win)\n})\n"
  },
  {
    "path": "main-process/menus/shortcuts.js",
    "content": "const {app, dialog, globalShortcut} = require('electron')\n\napp.on('ready', () => {\n  globalShortcut.register('CommandOrControl+Alt+K', () => {\n    dialog.showMessageBox({\n      type: 'info',\n      message: 'Success!',\n      detail: 'You pressed the registered global shortcut keybinding.',\n      buttons: ['OK']\n    })\n  })\n})\n\napp.on('will-quit', () => {\n  globalShortcut.unregisterAll()\n})\n"
  },
  {
    "path": "main-process/native-ui/dialogs/error.js",
    "content": "const {ipcMain, dialog} = require('electron')\n\nipcMain.on('open-error-dialog', (event) => {\n  dialog.showErrorBox('An Error Message', 'Demonstrating an error message.')\n})\n"
  },
  {
    "path": "main-process/native-ui/dialogs/information.js",
    "content": "const {ipcMain, dialog} = require('electron')\n\nipcMain.on('open-information-dialog', (event) => {\n  const options = {\n    type: 'info',\n    title: 'Information',\n    message: \"This is an information dialog. Isn't it nice?\",\n    buttons: ['Yes', 'No']\n  }\n  dialog.showMessageBox(options, (index) => {\n    event.sender.send('information-dialog-selection', index)\n  })\n})\n"
  },
  {
    "path": "main-process/native-ui/dialogs/open-file.js",
    "content": "const {ipcMain, dialog} = require('electron')\n\nipcMain.on('open-file-dialog', (event) => {\n  dialog.showOpenDialog({\n    properties: ['openFile', 'openDirectory']\n  }, (files) => {\n    if (files) {\n      event.sender.send('selected-directory', files)\n    }\n  })\n})\n"
  },
  {
    "path": "main-process/native-ui/dialogs/save.js",
    "content": "const {ipcMain, dialog} = require('electron')\n\nipcMain.on('save-dialog', (event) => {\n  const options = {\n    title: 'Save an Image',\n    filters: [\n      { name: 'Images', extensions: ['jpg', 'png', 'gif'] }\n    ]\n  }\n  dialog.showSaveDialog(options, (filename) => {\n    event.sender.send('saved-file', filename)\n  })\n})\n"
  },
  {
    "path": "main-process/native-ui/drag/drag.js",
    "content": "const {ipcMain} = require('electron')\nconst path = require('path')\n\nipcMain.on('ondragstart', (event, filepath) => {\n  const iconName = 'codeIcon.png'\n  event.sender.startDrag({\n    file: filepath,\n    icon: path.join(__dirname, iconName)\n  })\n})\n"
  },
  {
    "path": "main-process/native-ui/tray/tray.js",
    "content": "const path = require('path')\nconst {ipcMain, app, Menu, Tray} = require('electron')\n\nlet appIcon = null\n\nipcMain.on('put-in-tray', (event) => {\n  const iconName = process.platform === 'win32' ? 'windows-icon.png' : 'iconTemplate.png'\n  const iconPath = path.join(__dirname, iconName)\n  appIcon = new Tray(iconPath)\n\n  const contextMenu = Menu.buildFromTemplate([{\n    label: 'Remove',\n    click: () => {\n      event.sender.send('tray-removed')\n    }\n  }])\n\n  appIcon.setToolTip('Electron Demo in the tray.')\n  appIcon.setContextMenu(contextMenu)\n})\n\nipcMain.on('remove-tray', () => {\n  appIcon.destroy()\n})\n\napp.on('window-all-closed', () => {\n  if (appIcon) appIcon.destroy()\n})\n"
  },
  {
    "path": "main-process/system/app-information.js",
    "content": "const {app, ipcMain} = require('electron')\n\nipcMain.on('get-app-path', (event) => {\n  event.sender.send('got-app-path', app.getAppPath())\n})\n"
  },
  {
    "path": "main-process/system/protocol-handler.js",
    "content": "const {app, dialog} = require('electron')\nconst path = require('path')\n\nif (process.defaultApp) {\n  if (process.argv.length >= 2) {\n    app.setAsDefaultProtocolClient('electron-api-demos', process.execPath, [path.resolve(process.argv[1])])\n  }\n} else {\n  app.setAsDefaultProtocolClient('electron-api-demos')\n}\n\napp.on('open-url', (event, url) => {\n  dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)\n})\n"
  },
  {
    "path": "main.js",
    "content": "require('update-electron-app')({\n  logger: require('electron-log')\n})\n\nconst path = require('path')\nconst glob = require('glob')\nconst {app, BrowserWindow} = require('electron')\n\nconst debug = /--debug/.test(process.argv[2])\n\nif (process.mas) app.setName('Electron APIs')\n\nlet mainWindow = null\n\nfunction initialize () {\n  makeSingleInstance()\n\n  loadDemos()\n\n  function createWindow () {\n    const windowOptions = {\n      width: 1080,\n      minWidth: 680,\n      height: 840,\n      title: app.getName(),\n      webPreferences: {\n        nodeIntegration: true\n      }\n    }\n\n    if (process.platform === 'linux') {\n      windowOptions.icon = path.join(__dirname, '/assets/app-icon/png/512.png')\n    }\n\n    mainWindow = new BrowserWindow(windowOptions)\n    mainWindow.loadURL(path.join('file://', __dirname, '/index.html'))\n\n    // Launch fullscreen with DevTools open, usage: npm run debug\n    if (debug) {\n      mainWindow.webContents.openDevTools()\n      mainWindow.maximize()\n      require('devtron').install()\n    }\n\n    mainWindow.on('closed', () => {\n      mainWindow = null\n    })\n  }\n\n  app.on('ready', () => {\n    createWindow()\n  })\n\n  app.on('window-all-closed', () => {\n    if (process.platform !== 'darwin') {\n      app.quit()\n    }\n  })\n\n  app.on('activate', () => {\n    if (mainWindow === null) {\n      createWindow()\n    }\n  })\n}\n\n// Make this app a single instance app.\n//\n// The main window will be restored and focused instead of a second window\n// opened when a person attempts to launch a second instance.\n//\n// Returns true if the current version of the app should quit instead of\n// launching.\nfunction makeSingleInstance () {\n  if (process.mas) return\n\n  app.requestSingleInstanceLock()\n\n  app.on('second-instance', () => {\n    if (mainWindow) {\n      if (mainWindow.isMinimized()) mainWindow.restore()\n      mainWindow.focus()\n    }\n  })\n}\n\n// Require each JS file in the main-process dir\nfunction loadDemos () {\n  const files = glob.sync(path.join(__dirname, 'main-process/**/*.js'))\n  files.forEach((file) => { require(file) })\n}\n\ninitialize()\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"electron-api-demos\",\n  \"productName\": \"Electron API Demos\",\n  \"version\": \"2.0.2\",\n  \"description\": \"Electron interactive API demos\",\n  \"main\": \"main.js\",\n  \"bin\": \"cli.js\",\n  \"scripts\": {\n    \"start\": \"electron .\",\n    \"dev\": \"electron . --debug\",\n    \"test\": \"mocha && standard\",\n    \"generate-test-report\": \"mocha --reporter=json > report.json\",\n    \"package\": \"npm-run-all package:*\",\n    \"package:mac\": \"electron-packager . --overwrite --platform=darwin --arch=x64 --out=out --icon=assets/app-icon/mac/app.icns --osx-sign.identity='Developer ID Application: GitHub' --extend-info=assets/mac/info.plist\",\n    \"package:win\": \"electron-packager . --overwrite --platform=win32 --arch=ia32 --out=out --icon=assets/app-icon/win/app.ico\",\n    \"package:linux\": \"electron-packager . --overwrite --platform=linux --arch=x64 --out=out\",\n    \"package:sign-exe\": \"signcode './out/Electron API Demos-win32-ia32/Electron API Demos.exe' --cert ~/electron-api-demos.p12 --prompt --name 'Electron API Demos' --url 'http://electron.atom.io'\",\n    \"package:installer\": \"node ./script/installer.js\",\n    \"package:sign-installer\": \"signcode './out/windows-installer/ElectronAPIDemosSetup.exe' --cert ~/electron-api-demos.p12 --prompt --name 'Electron API Demos' --url 'http://electron.atom.io'\",\n    \"xpackage:mas\": \"./script/mas.sh\",\n    \"windows-store\": \"node ./script/windows-store.js\",\n    \"release\": \"node ./script/release.js\",\n    \"prepack\": \"check-for-leaks\",\n    \"prepush\": \"check-for-leaks\"\n  },\n  \"repository\": \"https://github.com/electron/electron-api-demos\",\n  \"keywords\": [\n    \"Electron\",\n    \"API\",\n    \"demo\"\n  ],\n  \"author\": \"GitHub\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"@octokit/rest\": \"^16.3.2\",\n    \"chai\": \"^3.4.1\",\n    \"chai-as-promised\": \"^6.0.0\",\n    \"check-for-leaks\": \"^1.2.1\",\n    \"devtron\": \"^1.3.0\",\n    \"electron-packager\": \"^16.0.0\",\n    \"electron-winstaller\": \"^2.2.0\",\n    \"husky\": \"^0.14.3\",\n    \"mocha\": \"^5.2.0\",\n    \"npm-run-all\": \"^4.0.2\",\n    \"request\": \"^2.70.0\",\n    \"rimraf\": \"^2.5.2\",\n    \"signcode\": \"^1.0.0\",\n    \"spectron\": \"^5.0.0\",\n    \"standard\": \"^8.2.0\",\n    \"tap\": \"^14.10.6\"\n  },\n  \"dependencies\": {\n    \"electron\": \"^15.5.5\",\n    \"electron-log\": \"^2.2.14\",\n    \"electron-settings\": \"^3.0.7\",\n    \"electron-shortcut-normalizer\": \"^1.0.0\",\n    \"glob\": \"^7.1.0\",\n    \"highlight.js\": \"^10.4.1\",\n    \"update-electron-app\": \"^1.1.1\"\n  },\n  \"standard\": {\n    \"env\": {\n      \"mocha\": true\n    }\n  }\n}\n"
  },
  {
    "path": "renderer-process/communication/async-msg.js",
    "content": "const {ipcRenderer} = require('electron')\n\nconst asyncMsgBtn = document.getElementById('async-msg')\n\nasyncMsgBtn.addEventListener('click', () => {\n  ipcRenderer.send('asynchronous-message', 'ping')\n})\n\nipcRenderer.on('asynchronous-reply', (event, arg) => {\n  const message = `Asynchronous message reply: ${arg}`\n  document.getElementById('async-reply').innerHTML = message\n})\n"
  },
  {
    "path": "renderer-process/communication/invisible-msg.js",
    "content": "const {BrowserWindow} = require('electron').remote\nconst ipcRenderer = require('electron').ipcRenderer\nconst path = require('path')\n\nconst invisMsgBtn = document.getElementById('invis-msg')\nconst invisReply = document.getElementById('invis-reply')\n\ninvisMsgBtn.addEventListener('click', (clickEvent) => {\n  const windowID = BrowserWindow.getFocusedWindow().id\n  const invisPath = `file://${path.join(__dirname, '../../sections/communication/invisible.html')}`\n  let win = new BrowserWindow({\n    width: 400,\n    height: 400,\n    show: false,\n    webPreferences: {\n      nodeIntegration: true\n    }\n  })\n  win.loadURL(invisPath)\n\n  win.webContents.on('did-finish-load', () => {\n    const input = 100\n    win.webContents.send('compute-factorial', input, windowID)\n  })\n})\n\nipcRenderer.on('factorial-computed', (event, input, output) => {\n  const message = `The factorial of ${input} is ${output}`\n  invisReply.textContent = message\n})\n"
  },
  {
    "path": "renderer-process/communication/sync-msg.js",
    "content": "const {ipcRenderer} = require('electron')\n\nconst syncMsgBtn = document.getElementById('sync-msg')\n\nsyncMsgBtn.addEventListener('click', () => {\n  const reply = ipcRenderer.sendSync('synchronous-message', 'ping')\n  const message = `Synchronous message reply: ${reply}`\n  document.getElementById('sync-reply').innerHTML = message\n})\n"
  },
  {
    "path": "renderer-process/media/desktop-capturer.js",
    "content": "const {desktopCapturer, shell} = require('electron')\nconst {screen} = require('electron').remote\n\nconst fs = require('fs')\nconst os = require('os')\nconst path = require('path')\n\nconst screenshot = document.getElementById('screen-shot')\nconst screenshotMsg = document.getElementById('screenshot-path')\n\nscreenshot.addEventListener('click', (event) => {\n  screenshotMsg.textContent = 'Gathering screens...'\n  const thumbSize = determineScreenShotSize()\n  let options = { types: ['screen'], thumbnailSize: thumbSize }\n\n  desktopCapturer.getSources(options, (error, sources) => {\n    if (error) return console.log(error)\n\n    sources.forEach((source) => {\n      if (source.name === 'Entire Screen' || source.name === 'Screen 1') {\n        const screenshotPath = path.join(os.tmpdir(), 'screenshot.png')\n\n        fs.writeFile(screenshotPath, source.thumbnail.toPNG(), (error) => {\n          if (error) return console.log(error)\n          shell.openExternal(`file://${screenshotPath}`)\n\n          const message = `Saved screenshot to: ${screenshotPath}`\n          screenshotMsg.textContent = message\n        })\n      }\n    })\n  })\n})\n\nfunction determineScreenShotSize () {\n  const screenSize = screen.getPrimaryDisplay().workAreaSize\n  const maxDimension = Math.max(screenSize.width, screenSize.height)\n  return {\n    width: maxDimension * window.devicePixelRatio,\n    height: maxDimension * window.devicePixelRatio\n  }\n}\n"
  },
  {
    "path": "renderer-process/menus/context-menu.js",
    "content": "const {ipcRenderer} = require('electron')\n\n// Tell main process to show the menu when demo button is clicked\nconst contextMenuBtn = document.getElementById('context-menu')\n\ncontextMenuBtn.addEventListener('click', () => {\n  ipcRenderer.send('show-context-menu')\n})\n"
  },
  {
    "path": "renderer-process/native-ui/dialogs/error.js",
    "content": "const {ipcRenderer} = require('electron')\n\nconst errorBtn = document.getElementById('error-dialog')\n\nerrorBtn.addEventListener('click', (event) => {\n  ipcRenderer.send('open-error-dialog')\n})\n"
  },
  {
    "path": "renderer-process/native-ui/dialogs/information.js",
    "content": "const {ipcRenderer} = require('electron')\n\nconst informationBtn = document.getElementById('information-dialog')\n\ninformationBtn.addEventListener('click', (event) => {\n  ipcRenderer.send('open-information-dialog')\n})\n\nipcRenderer.on('information-dialog-selection', (event, index) => {\n  let message = 'You selected '\n  if (index === 0) message += 'yes.'\n  else message += 'no.'\n  document.getElementById('info-selection').innerHTML = message\n})\n"
  },
  {
    "path": "renderer-process/native-ui/dialogs/open-file.js",
    "content": "const {ipcRenderer} = require('electron')\n\nconst selectDirBtn = document.getElementById('select-directory')\n\nselectDirBtn.addEventListener('click', (event) => {\n  ipcRenderer.send('open-file-dialog')\n})\n\nipcRenderer.on('selected-directory', (event, path) => {\n  document.getElementById('selected-file').innerHTML = `You selected: ${path}`\n})\n"
  },
  {
    "path": "renderer-process/native-ui/dialogs/save.js",
    "content": "const {ipcRenderer} = require('electron')\n\nconst saveBtn = document.getElementById('save-dialog')\n\nsaveBtn.addEventListener('click', (event) => {\n  ipcRenderer.send('save-dialog')\n})\n\nipcRenderer.on('saved-file', (event, path) => {\n  if (!path) path = 'No path'\n  document.getElementById('file-saved').innerHTML = `Path selected: ${path}`\n})\n"
  },
  {
    "path": "renderer-process/native-ui/drag/drag.js",
    "content": "const {ipcRenderer} = require('electron')\n\nconst dragFileLink = document.getElementById('drag-file-link')\n\ndragFileLink.addEventListener('dragstart', (event) => {\n  event.preventDefault()\n  ipcRenderer.send('ondragstart', __filename)\n})\n"
  },
  {
    "path": "renderer-process/native-ui/ex-links-file-manager/ex-links.js",
    "content": "const {shell} = require('electron')\n\nconst exLinksBtn = document.getElementById('open-ex-links')\n\nexLinksBtn.addEventListener('click', (event) => {\n  shell.openExternal('http://electron.atom.io')\n})\n"
  },
  {
    "path": "renderer-process/native-ui/ex-links-file-manager/file-manager.js",
    "content": "const {shell} = require('electron')\nconst os = require('os')\n\nconst fileManagerBtn = document.getElementById('open-file-manager')\n\nfileManagerBtn.addEventListener('click', (event) => {\n  shell.showItemInFolder(os.homedir())\n})\n"
  },
  {
    "path": "renderer-process/native-ui/notifications/advanced-notification.js",
    "content": "const path = require('path')\n\nconst notification = {\n  title: 'Notification with image',\n  body: 'Short message plus a custom image',\n  icon: path.join(__dirname, '../../../assets/img/programming.png')\n}\nconst notificationButton = document.getElementById('advanced-noti')\n\nnotificationButton.addEventListener('click', () => {\n  const myNotification = new window.Notification(notification.title, notification)\n\n  myNotification.onclick = () => {\n    console.log('Notification clicked')\n  }\n})\n"
  },
  {
    "path": "renderer-process/native-ui/notifications/basic-notification.js",
    "content": "const notification = {\n  title: 'Basic Notification',\n  body: 'Short message part'\n}\n\nconst notificationButton = document.getElementById('basic-noti')\n\nnotificationButton.addEventListener('click', () => {\n  const myNotification = new window.Notification(notification.title, notification)\n\n  myNotification.onclick = () => {\n    console.log('Notification clicked')\n  }\n})\n"
  },
  {
    "path": "renderer-process/native-ui/tray/tray.js",
    "content": "const ipc = require('electron').ipcRenderer\n\nconst trayBtn = document.getElementById('put-in-tray')\nlet trayOn = false\n\ntrayBtn.addEventListener('click', function (event) {\n  if (trayOn) {\n    trayOn = false\n    document.getElementById('tray-countdown').innerHTML = ''\n    ipc.send('remove-tray')\n  } else {\n    trayOn = true\n    const message = 'Click demo again to remove.'\n    document.getElementById('tray-countdown').innerHTML = message\n    ipc.send('put-in-tray')\n  }\n})\n// Tray removed from context menu on icon\nipc.on('tray-removed', function () {\n  ipc.send('remove-tray')\n  trayOn = false\n  document.getElementById('tray-countdown').innerHTML = ''\n})\n"
  },
  {
    "path": "renderer-process/system/app-information.js",
    "content": "const {ipcRenderer} = require('electron')\n\nconst appInfoBtn = document.getElementById('app-info')\n\nappInfoBtn.addEventListener('click', () => {\n  ipcRenderer.send('get-app-path')\n})\n\nipcRenderer.on('got-app-path', (event, path) => {\n  const message = `This app is located at: ${path}`\n  document.getElementById('got-app-info').innerHTML = message\n})\n"
  },
  {
    "path": "renderer-process/system/copy.js",
    "content": "const {clipboard} = require('electron')\n\nconst copyBtn = document.getElementById('copy-to')\nconst copyInput = document.getElementById('copy-to-input')\n\ncopyBtn.addEventListener('click', () => {\n  if (copyInput.value !== '') copyInput.value = ''\n  copyInput.placeholder = 'Copied! Paste here to see.'\n  clipboard.writeText('Electron Demo!')\n})\n"
  },
  {
    "path": "renderer-process/system/paste.js",
    "content": "const {clipboard} = require('electron')\n\nconst pasteBtn = document.getElementById('paste-to')\n\npasteBtn.addEventListener('click', () => {\n  clipboard.writeText('What a demo!')\n  const message = `Clipboard contents: ${clipboard.readText()}`\n  document.getElementById('paste-from').innerHTML = message\n})\n"
  },
  {
    "path": "renderer-process/system/protocol-handler.js",
    "content": "const {shell} = require('electron')\nconst path = require('path')\n\nconst protocolHandlerBtn = document.getElementById('protocol-handler')\n\nprotocolHandlerBtn.addEventListener('click', () => {\n  const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')\n  const pagePath = path.join('file://', pageDirectory, '../../sections/system/protocol-link.html')\n  shell.openExternal(pagePath)\n})\n"
  },
  {
    "path": "renderer-process/system/screen-information.js",
    "content": "const {screen} = require('electron').remote\n\nconst screenInfoBtn = document.getElementById('screen-info')\nconst size = screen.getPrimaryDisplay().size\n\nscreenInfoBtn.addEventListener('click', () => {\n  const message = `Your screen is: ${size.width}px x ${size.height}px`\n  document.getElementById('got-screen-info').innerHTML = message\n})\n"
  },
  {
    "path": "renderer-process/system/sys-information.js",
    "content": "const os = require('os')\nconst homeDir = os.homedir()\n\nconst sysInfoBtn = document.getElementById('sys-info')\n\nsysInfoBtn.addEventListener('click', () => {\n  const message = `Your system home directory is: ${homeDir}`\n  document.getElementById('got-sys-info').innerHTML = message\n})\n"
  },
  {
    "path": "renderer-process/system/version-information.js",
    "content": "const versionInfoBtn = document.getElementById('version-info')\n\nconst electronVersion = process.versions.electron\n\nversionInfoBtn.addEventListener('click', () => {\n  const message = `This app is using Electron version: ${electronVersion}`\n  document.getElementById('got-version-info').innerHTML = message\n})\n"
  },
  {
    "path": "renderer-process/windows/create-window.js",
    "content": "const {BrowserWindow} = require('electron').remote\nconst path = require('path')\n\nconst newWindowBtn = document.getElementById('new-window')\n\nnewWindowBtn.addEventListener('click', (event) => {\n  const modalPath = path.join('file://', __dirname, '../../sections/windows/modal.html')\n  let win = new BrowserWindow({ width: 400, height: 320 })\n\n  win.on('close', () => { win = null })\n  win.loadURL(modalPath)\n  win.show()\n})\n"
  },
  {
    "path": "renderer-process/windows/frameless-window.js",
    "content": "const {BrowserWindow} = require('electron').remote\nconst newWindowBtn = document.getElementById('frameless-window')\n\nconst path = require('path')\n\nnewWindowBtn.addEventListener('click', (event) => {\n  const modalPath = path.join('file://', __dirname, '../../sections/windows/modal.html')\n  let win = new BrowserWindow({ frame: false })\n\n  win.on('close', () => { win = null })\n  win.loadURL(modalPath)\n  win.show()\n})\n"
  },
  {
    "path": "renderer-process/windows/manage-window.js",
    "content": "const {BrowserWindow} = require('electron').remote\nconst path = require('path')\n\nconst manageWindowBtn = document.getElementById('manage-window')\nlet win\n\nmanageWindowBtn.addEventListener('click', (event) => {\n  const modalPath = path.join('file://', __dirname, '../../sections/windows/manage-modal.html')\n  win = new BrowserWindow({ width: 400, height: 275 })\n\n  win.on('resize', updateReply)\n  win.on('move', updateReply)\n  win.on('close', () => { win = null })\n  win.loadURL(modalPath)\n  win.show()\n\n  function updateReply () {\n    const manageWindowReply = document.getElementById('manage-window-reply')\n    const message = `Size: ${win.getSize()} Position: ${win.getPosition()}`\n    manageWindowReply.innerText = message\n  }\n})\n"
  },
  {
    "path": "renderer-process/windows/process-crash.js",
    "content": "const {BrowserWindow, dialog} = require('electron').remote\nconst path = require('path')\n\nconst processCrashBtn = document.getElementById('process-crash')\n\nprocessCrashBtn.addEventListener('click', (event) => {\n  const crashWinPath = path.join('file://', __dirname, '../../sections/windows/process-crash.html')\n  let win = new BrowserWindow({\n    width: 400,\n    height: 320,\n    webPreferences: {\n      nodeIntegration: true\n    }\n  });\n\n  win.webContents.on('crashed', () => {\n    const options = {\n      type: 'info',\n      title: 'Renderer Process Crashed',\n      message: 'This process has crashed.',\n      buttons: ['Reload', 'Close']\n    }\n\n    dialog.showMessageBox(options, (index) => {\n      if (index === 0) win.reload()\n      else win.close()\n    })\n  })\n\n  win.on('close', () => { win = null })\n  win.loadURL(crashWinPath)\n  win.show()\n})\n"
  },
  {
    "path": "renderer-process/windows/process-hang.js",
    "content": "const {BrowserWindow, dialog} = require('electron').remote\nconst path = require('path')\n\nconst processHangBtn = document.getElementById('process-hang')\n\nprocessHangBtn.addEventListener('click', (event) => {\n  const hangWinPath = path.join('file://', __dirname, '../../sections/windows/process-hang.html')\n  let win = new BrowserWindow({\n    width: 400,\n    height: 320,\n    webPreferences: {\n      nodeIntegration: true\n    }\n  });\n\n  win.on('unresponsive', () => {\n    const options = {\n      type: 'info',\n      title: 'Renderer Process Hanging',\n      message: 'This process is hanging.',\n      buttons: ['Reload', 'Close']\n    }\n\n    dialog.showMessageBox(options, (index) => {\n      if (index === 0) win.reload()\n      else win.close()\n    })\n  })\n\n  win.on('close', () => { win = null })\n  win.loadURL(hangWinPath)\n  win.show()\n})\n"
  },
  {
    "path": "renderer-process/windows/using-window-events.js",
    "content": "const {BrowserWindow} = require('electron').remote\nconst path = require('path')\n\nconst manageWindowBtn = document.getElementById('listen-to-window')\nconst focusModalBtn = document.getElementById('focus-on-modal-window')\nlet win\n\nmanageWindowBtn.addEventListener('click', () => {\n  const modalPath = path.join('file://', __dirname, '../../sections/windows/modal-toggle-visibility.html')\n  win = new BrowserWindow({ width: 600, height: 400 })\n\n  const hideFocusBtn = () => {\n    focusModalBtn.classList.add('disappear')\n    focusModalBtn.classList.remove('smooth-appear')\n    focusModalBtn.removeEventListener('click', clickHandler)\n  }\n\n  const showFocusBtn = (btn) => {\n    if (!win) return\n    focusModalBtn.classList.add('smooth-appear')\n    focusModalBtn.classList.remove('disappear')\n    focusModalBtn.addEventListener('click', clickHandler)\n  }\n\n  win.on('focus', hideFocusBtn)\n  win.on('blur', showFocusBtn)\n  win.on('close', () => {\n    hideFocusBtn()\n    win = null\n  })\n  win.loadURL(modalPath)\n  win.show()\n\n  const clickHandler = () => { win.focus() }\n})\n"
  },
  {
    "path": "script/installer.js",
    "content": "#!/usr/bin/env node\n\nconst createWindowsInstaller = require('electron-winstaller').createWindowsInstaller\nconst path = require('path')\nconst rimraf = require('rimraf')\n\ndeleteOutputFolder()\n  .then(getInstallerConfig)\n  .then(createWindowsInstaller)\n  .catch((error) => {\n    console.error(error.message || error)\n    process.exit(1)\n  })\n\nfunction getInstallerConfig () {\n  const rootPath = path.join(__dirname, '..')\n  const outPath = path.join(rootPath, 'out')\n\n  return Promise.resolve({\n    appDirectory: path.join(outPath, 'Electron API Demos-win32-ia32'),\n    exe: 'Electron API Demos.exe',\n    iconUrl: 'https://raw.githubusercontent.com/electron/electron-api-demos/master/assets/app-icon/win/app.ico',\n    loadingGif: path.join(rootPath, 'assets', 'img', 'loading.gif'),\n    noMsi: true,\n    outputDirectory: path.join(outPath, 'windows-installer'),\n    setupExe: 'ElectronAPIDemosSetup.exe',\n    setupIcon: path.join(rootPath, 'assets', 'app-icon', 'win', 'app.ico'),\n    skipUpdateIcon: true\n  })\n}\n\nfunction deleteOutputFolder () {\n  return new Promise((resolve, reject) => {\n    rimraf(path.join(__dirname, '..', 'out', 'windows-installer'), (error) => {\n      error ? reject(error) : resolve()\n    })\n  })\n}\n"
  },
  {
    "path": "script/mas.sh",
    "content": "#!/bin/bash\n\nset -ex\n\n# App Store does not allow the word \"demos\" in the app's name\nAPP=\"Electron APIs\"\n\nelectron-packager . \\\n  \"$APP\" \\\n  --asar \\\n  --asar-unpack=protocol-link.html \\\n  --overwrite \\\n  --platform=mas \\\n  --app-bundle-id=com.github.electron-api-demos \\\n  --app-version=\"$npm_package_version\" \\\n  --build-version=\"1.1.0\" \\\n  --arch=x64 \\\n  --icon=assets/app-icon/mac/app.icns \\\n  --prune=true \\\n  --out=out \\\n  --extend-info=assets/mac/info.plist\n\nAPP_PATH=\"./out/$APP-mas-x64/$APP.app\"\nRESULT_PATH=\"./out/$APP.pkg\"\nAPP_KEY=\"3rd Party Mac Developer Application: GitHub (VEKTX9H2N7)\"\nINSTALLER_KEY=\"3rd Party Mac Developer Installer: GitHub (VEKTX9H2N7)\"\nFRAMEWORKS_PATH=\"$APP_PATH/Contents/Frameworks\"\nCHILD_PLIST=\"./assets/mac/child.plist\"\nPARENT_PLIST=\"./assets/mac/parent.plist\"\n\ncodesign -s \"$APP_KEY\" -f --entitlements \"$CHILD_PLIST\" \"$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Electron Framework\"\ncodesign -s \"$APP_KEY\" -f --entitlements \"$CHILD_PLIST\" \"$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libffmpeg.dylib\"\ncodesign -s \"$APP_KEY\" -f --entitlements \"$CHILD_PLIST\" \"$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libnode.dylib\"\ncodesign -s \"$APP_KEY\" -f --entitlements \"$CHILD_PLIST\" \"$FRAMEWORKS_PATH/Electron Framework.framework\"\ncodesign -s \"$APP_KEY\" -f --entitlements \"$CHILD_PLIST\" \"$FRAMEWORKS_PATH/$APP Helper.app/Contents/MacOS/$APP Helper\"\ncodesign -s \"$APP_KEY\" -f --entitlements \"$CHILD_PLIST\" \"$FRAMEWORKS_PATH/$APP Helper.app/\"\ncodesign -s \"$APP_KEY\" -f --entitlements \"$CHILD_PLIST\" \"$FRAMEWORKS_PATH/$APP Helper EH.app/Contents/MacOS/$APP Helper EH\"\ncodesign -s \"$APP_KEY\" -f --entitlements \"$CHILD_PLIST\" \"$FRAMEWORKS_PATH/$APP Helper EH.app/\"\ncodesign -s \"$APP_KEY\" -f --entitlements \"$CHILD_PLIST\" \"$FRAMEWORKS_PATH/$APP Helper NP.app/Contents/MacOS/$APP Helper NP\"\ncodesign -s \"$APP_KEY\" -f --entitlements \"$CHILD_PLIST\" \"$FRAMEWORKS_PATH/$APP Helper NP.app/\"\ncodesign -s \"$APP_KEY\" -f --entitlements \"$CHILD_PLIST\" \"$APP_PATH/Contents/MacOS/$APP\"\n\ncodesign -s \"$APP_KEY\" -f --entitlements \"$PARENT_PLIST\" \"$APP_PATH\"\n\nproductbuild --component \"$APP_PATH\" /Applications --sign \"$INSTALLER_KEY\" \"$RESULT_PATH\"\n"
  },
  {
    "path": "script/release.js",
    "content": "#!/usr/bin/env node\n\nconst childProcess = require('child_process')\nconst fs = require('fs')\nconst path = require('path')\nconst octokit = require('@octokit/rest')\n\nconst token = process.env.ELECTRON_API_DEMO_GITHUB_TOKEN\nconst version = require('../package').version\nconst github = octokit({\n  timeout: 30 * 1000,\n  'user-agent': `node/${process.versions.node}`\n})\n\nif (!token) {\n  console.error('ELECTRON_API_DEMO_GITHUB_TOKEN environment variable not set\\nSet it to a token with repo scope created from https://github.com/settings/tokens/new')\n  process.exit(1)\n}\n\ngithub.authenticate({\n  type: 'token',\n  token: token\n})\n\nasync function doRelease () {\n  const release = await getOrCreateRelease()\n  const assets = await prepareAssets()\n  await uploadAssets(release, assets)\n  await publishRelease(release)\n  console.log('Done!')\n}\n\ndoRelease().catch(err => {\n  console.error(err.message || err)\n  process.exit(1)\n})\n\nfunction prepareAssets () {\n  const outPath = path.join(__dirname, '..', 'out')\n\n  const zipAssets = [{\n    name: 'electron-api-demos-mac.zip',\n    path: path.join(outPath, 'Electron API Demos-darwin-x64', 'Electron API Demos.app')\n  }, {\n    name: 'electron-api-demos-windows.zip',\n    path: path.join(outPath, 'Electron API Demos-win32-ia32')\n  }, {\n    name: 'electron-api-demos-linux.zip',\n    path: path.join(outPath, 'Electron API Demos-linux-x64')\n  }]\n\n  return Promise.all(zipAssets.map(zipAsset)).then((zipAssets) => {\n    return zipAssets.concat([{\n      name: 'RELEASES',\n      path: path.join(outPath, 'windows-installer', 'RELEASES')\n    }, {\n      name: 'ElectronAPIDemosSetup.exe',\n      path: path.join(outPath, 'windows-installer', 'ElectronAPIDemosSetup.exe')\n    }, {\n      name: `electron-api-demos-${version}-full.nupkg`,\n      path: path.join(outPath, 'windows-installer', `electron-api-demos-${version}-full.nupkg`)\n    }])\n  })\n}\n\nfunction zipAsset (asset) {\n  return new Promise((resolve, reject) => {\n    const assetBase = path.basename(asset.path)\n    const assetDirectory = path.dirname(asset.path)\n    console.log(`Zipping ${assetBase} to ${asset.name}`)\n\n    if (!fs.existsSync(asset.path)) {\n      return reject(new Error(`${asset.path} does not exist`))\n    }\n\n    const zipCommand = `zip --recurse-paths --symlinks '${asset.name}' '${assetBase}'`\n    const options = {cwd: assetDirectory, maxBuffer: Infinity}\n    childProcess.exec(zipCommand, options, (error) => {\n      if (error) {\n        reject(error)\n      } else {\n        asset.path = path.join(assetDirectory, asset.name)\n        resolve(asset)\n      }\n    })\n  })\n}\n\nasync function getOrCreateRelease () {\n  const { data: releases } = await github.repos.listReleases({\n    owner: 'electron',\n    repo: 'electron-api-demos',\n    per_page: 100,\n    page: 1\n  })\n  const existingRelease = releases.find(release => release.tag_name === `v${version}` && release.draft === true)\n  if (existingRelease) {\n    console.log(`Using existing draft release for v${version}`)\n    return existingRelease\n  }\n\n  console.log('Creating new draft release')\n  const { data: release } = await github.repos.createRelease({\n    owner: 'electron',\n    repo: 'electron-api-demos',\n    tag_name: `v${version}`,\n    target_commitish: 'master',\n    name: version,\n    body: 'An awesome new release :tada:',\n    draft: true,\n    prerelease: false\n  })\n  return release\n}\n\nasync function uploadAssets (release, assets) {\n  for (const asset of assets) {\n    if (release.assets.some(ghAsset => ghAsset.name === asset.name)) {\n      console.log(`Skipping already uploaded asset ${asset.name}`)\n    } else {\n      process.stdout.write(`Uploading ${asset.name}... `)\n      try {\n        await uploadAsset(release, asset)\n      } catch (err) {\n        if (err.name === 'HttpError' && err.message.startsWith('network timeout')) {\n          console.error('\\n')\n          console.error(`  There was a network timeout while uploading ${asset.name}.`)\n          console.error('  This likely resulted in a bad asset; please visit the release at')\n          console.error(`  ${release.html_url} and manually remove the bad asset,`)\n          console.error(`  then run this script again to continue where you left off.`)\n          console.error('')\n          process.exit(2)\n        } else {\n          throw err\n        }\n      }\n\n      process.stdout.write('Success!\\n')\n      // [mkt] Waiting a bit between uploads seems to increase success rate\n      await new Promise(resolve => setTimeout(resolve, 5000))\n    }\n  }\n}\n\nfunction uploadAsset (release, asset) {\n  return github.repos.uploadReleaseAsset({\n    headers: {\n      'content-type': 'application/octet-stream',\n      'content-length': fs.statSync(asset.path).size\n    },\n    url: release.upload_url,\n    file: fs.createReadStream(asset.path),\n    name: asset.name\n  })\n}\n\nfunction publishRelease (release) {\n  console.log('Publishing release')\n  return github.repos.updateRelease({\n    owner: 'electron',\n    repo: 'electron-api-demos',\n    release_id: release.id,\n    draft: false\n  })\n}\n"
  },
  {
    "path": "script/windows-store.js",
    "content": "const ChildProcess = require('child_process')\nconst path = require('path')\n\nconst metadata = require('../package')\n\nconst command = path.join(__dirname, '..', 'node_modules', '.bin', 'electron-windows-store.cmd')\nconst args = [\n  '--input-directory',\n  path.join(__dirname, '..', 'out', 'ElectronAPIDemos-win32-ia32'),\n  '--output-directory',\n  path.join(__dirname, '..', 'out', 'windows-store'),\n  '--flatten',\n  true,\n  '--package-version',\n  metadata.version + '.0',\n  '--package-name',\n  metadata.name,\n  '--package-display-name',\n  metadata.productName,\n  '--assets',\n  path.join(__dirname, '..', 'assets', 'tiles'),\n  '--package-description',\n  metadata.description\n]\n\nconst windowsStore = ChildProcess.spawn(command, args, {stdio: 'inherit'})\nwindowsStore.on('close', (code) => {\n  process.exit(code)\n})\n"
  },
  {
    "path": "sections/about.html",
    "content": "<template class=\"task-template\">\n  <div id=\"about-modal\" class=\"about modal\">\n    <div class=\"about-wrapper\">\n      <header class=\"about-header\">\n        <img class=\"about-logo\" src=\"assets/img/about.png\" srcset=\"assets/img/about.png 1x, assets/img/about@2x.png 2x\" alt=\"Electron API Demos\">\n      </header>\n      <main class=\"about-sections\">\n        <section class=\"about-section play-along\">\n          <h2>Play Along</h2>\n            <p>Use the demo snippets in an Electron app of your own. The <a href=\"https://github.com/electron/electron-quick-start\">Electron Quick Start<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> app is a bare-bones setup that pairs with these demos. Follow the instructions here to get it going. You'll need <a href=\"https://desktop.github.com/\">Git<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> and <a href=\"https://nodejs.org/\">Node.js<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> on your computer to do this.</p>\n<pre><code class=\"language-bash\">$ git clone https://github.com/electron/electron-quick-start\n$ cd electron-quick-start\n$ npm install &amp;&amp; npm start\n</code></pre>\n        </section>\n        <section class=\"about-section about-code\">\n          <h2>About the Code</h2>\n            <p>The <a href=\"https://github.com/electron/electron-api-demos\">source code of this app<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> has been organized with ease of navigation in mind.</p>\n\n            <p>Nearly all (over 90%) of <a href=\"http://babeljs.io/docs/learn-es2015/\">ES2015<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> is available to use in Electron <em>without the use of pre-processors</em> because it's a part of <a href=\"https://developers.google.com/v8/\">V8<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> which is built into Electron.</p>\n\n            <p>To illustrate this we've made use of <code>const</code>, for unchanging declarations; <code>let</code> for scoped declarations; and template strings like: <code>`Result is ${output}`</code> in the demo snippets.</p>\n        </section>\n        <footer class=\"about-section footer\">\n          <div class=\"rainbow-button-wrapper\">\n            <button id=\"get-started\" class=\"about-button modal-hide\">Get Started</button>\n          </div>\n        </footer>\n      </main>\n    </div>\n  </div>\n</template>\n"
  },
  {
    "path": "sections/communication/invisible.html",
    "content": "<html>\n  <script type=\"text/javascript\">\n    const ipc = require('electron').ipcRenderer\n    const BrowserWindow = require('electron').remote.BrowserWindow\n\n    ipc.on('compute-factorial', function (event, number, fromWindowId) {\n      const result = factorial(number)\n      const fromWindow = BrowserWindow.fromId(fromWindowId)\n      fromWindow.webContents.send('factorial-computed', number, result)\n      window.close()\n    })\n\n    function factorial (num) {\n      if (num === 0) return 1\n      return num * factorial(num - 1)\n    }\n  </script>\n</html>\n"
  },
  {
    "path": "sections/communication/ipc.html",
    "content": "<template class=\"task-template\">\n  <section id=\"ipc-section\" class=\"section js-section u-category-communication\">\n    <header class=\"communication\">\n      <div class=\"section-wrapper\">\n        <h1>\n          <svg class=\"section-icon\"><use xlink:href=\"assets/img/icons.svg#icon-communication\"></use></svg>\n          Communication between processes\n        </h1>\n        <h3>The <code>ipc</code> (inter-process communication) module allows you to send and receive synchronous and asynchronous messages between the main and renderer processes.</h3>\n\n        <p>There is a version of this module available for both processes: <code>ipcMain</code> and <code>ipcRenderer</code>.</p>\n        <p>Open the full API documentation for the <a href=\"http://electron.atom.io/docs/api/ipc-main\">main process<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> and the <a href=\"http://electron.atom.io/docs/api/ipc-renderer/\">renderer process<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> in your browser.</p>\n      </div>\n    </header>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"async-msg-demo-toggle\" class=\"js-container-target demo-toggle-button\">Asynchronous messages\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Both</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"async-msg\">Ping</button>\n            <span class=\"demo-response\" id=\"async-reply\"></span>\n          </div>\n          <p>Using <code>ipc</code> to send messages between processes asynchronously is the preferred method since it will return when finished without blocking other operations in the same process.</p>\n\n          <p>This example sends a \"ping\" from this process (renderer) to the main process. The main process then replies with \"pong\".</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/communication/async-msg.js\"></code></pre>\n          <h5>Main Process</h5>\n          <pre><code data-path=\"main-process/communication/async-msg.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"sync-msg-demo-toggle\" class=\"js-container-target demo-toggle-button\">Synchronous messages\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Both</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"sync-msg\">Ping</button>\n            <span class=\"demo-response\" id=\"sync-reply\"></span>\n          </div>\n          <p>You can use the <code>ipc</code> module to send synchronous messages between processes as well, but note that the synchronous nature of this method means that it <b>will block</b> other operations while completing its task.</p>\n          <p>This example sends a synchronous message, \"ping\", from this process (renderer) to the main process. The main process then replies with \"pong\".</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/communication/sync-msg.js\"></code></pre>\n          <h5>Main Process</h5>\n          <pre><code data-path=\"main-process/communication/sync-msg.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"invis-msg-demo-toggle\" class=\"js-container-target demo-toggle-button\">Communicate with an invisible window\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Both</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"invis-msg\">Compute Factorial</button>\n            <span class=\"demo-response\" id=\"invis-reply\"></span>\n          </div>\n          <p>It is common practice to create a new invisible browser window (renderer process) in order to run tasks without impacting performance in the main app's window.</p>\n          <p>In this example we use the <code>remote</code> module to create a new invisible browser window from this renderer process. When the new page is loaded we send a message with <code>ipc</code> that the new window is listening for.</p>\n          <p>The new window then computes the factorial and sends the result to be received by this, the original, window and added to the page above.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/communication/invisible-msg.js\"></code></pre>\n          <h5>Invisible Window Page HTML</h5>\n          <pre><code data-path=\"sections/communication/invisible.html\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <script type=\"text/javascript\">\n      require('./renderer-process/communication/sync-msg')\n      require('./renderer-process/communication/async-msg')\n      require('./renderer-process/communication/invisible-msg')\n    </script>\n\n  </section>\n</template>\n"
  },
  {
    "path": "sections/media/desktop-capturer.html",
    "content": "<template class=\"task-template\">\n  <section id=\"desktop-capturer-section\" class=\"section js-section u-category-media\">\n    <header class=\"section-header\">\n      <div class=\"section-wrapper\">\n        <h1>\n          <svg class=\"section-icon\"><use xlink:href=\"assets/img/icons.svg#icon-media\"></use></svg>\n          Take a screenshot\n        </h1>\n        <h3>The <code>desktopCapturer</code> module in Electron can be used to access any media, such as audio, video, screen and window, that is available through the <code>getUserMedia</code> web API in Chromium.</h3>\n\n        <p>Open the <a href=\"http://electron.atom.io/docs/api/desktop-capturer\">full API documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> in your browser.</p>\n      </div>\n    </header>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"print-pdf-demo-toggle\" class=\"js-container-target demo-toggle-button\">Take a Screenshot\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux | Process: Renderer</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"screen-shot\">View Demo</button>\n            <span class=\"demo-response is-selectable\" id=\"screenshot-path\"></span>\n          </div>\n          <p>This demo uses the <code>desktopCapturer</code> module to gather screens in use and select the entire screen and take a snapshot of what is visible.</p>\n          <p>Clicking the demo button will take a screenshot of your current screen and open it in your default viewer.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/media/desktop-capturer.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <script type=\"text/javascript\">\n      require('./renderer-process/media/desktop-capturer')\n    </script>\n\n  </section>\n</template>\n"
  },
  {
    "path": "sections/menus/menus.html",
    "content": "<template class=\"task-template\">\n  <section id=\"menus-section\" class=\"section js-section u-category-menu\">\n    <header class=\"section-header\">\n      <div class=\"section-wrapper\">\n        <h1>\n          <svg class=\"section-icon\"><use xlink:href=\"assets/img/icons.svg#icon-menu\"></use></svg>\n          Customize Menus\n        </h1>\n        <h3>The <code>Menu</code> and <code>MenuItem</code> modules can be used to create custom native menus.</h3>\n\n        <p>There are two kinds of menus: the application (top) menu and context (right-click) menu.</p>\n\n        <p>Open the <a href=\"http://electron.atom.io/docs/api/menu\">full API documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> in your browser.</p>\n      </div>\n    </header>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"application-menu-demo-toggle\" class=\"js-container-target demo-toggle-button\">Create an application menu\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Main</div>\n        </button>\n        <div class=\"demo-box\">\n          <p>The <code>Menu</code> and <code>MenuItem</code> modules allow you to customize your application menu. If you don't set any menu, Electron will generate a minimal menu for your app by default.</p>\n\n          <p>This app uses the code below to set the application menu. If you click the 'View' option in the application menu and then the 'App Menu Demo', you'll see an information box displayed.</p>\n          <h5>Main Process</h5>\n          <pre><code data-path=\"main-process/menus/application-menu.js\"></code></pre>\n\n          <div class=\"demo-protip\">\n            <h2>ProTip</h2>\n            <strong>Know operating system menu differences.</strong>\n            <p>When designing an app for multiple operating systems it's important to be mindful of the ways application menu conventions differ on each operating system.</p>\n            <p>For instance, on Windows, accelerators are set with an <code>&</code>. Naming conventions also vary, like between \"Settings\" or \"Preferences\". Below are resources for learning operating system specific standards.</p>\n            <ul>\n              <li><a href=\"https://developer.apple.com/macos/human-interface-guidelines/menus/menu-anatomy/\">macOS<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a></li>\n              <li><a href=\"https://msdn.microsoft.com/en-us/library/windows/desktop/bb226797(v=vs.85).aspx\">Windows<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a></li>\n              <li><a href=\"https://developer.gnome.org/hig/patterns/controls/menus.html\">Linux<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a></li>\n            </ul>\n          </div>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"context-menu-demo-toggle\" class=\"js-container-target demo-toggle-button\">Create a context menu\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Main</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"context-menu\">View Demo</button>\n          </div>\n          <p>A context, or right-click, menu can be created with the <code>Menu</code> and <code>MenuItem</code> modules as well. You can right-click anywhere in this app or click the demo button to see an example context menu.</p>\n\n          <p>In this demo we use the <code>ipcRenderer</code> module to show the context menu when explicitly calling it from the renderer process.</p>\n          <p>See the full <a href=\"http://electron.atom.io/docs/api/web-contents/#event-context-menu\">context-menu event documentation</a> for all the available properties.</p>\n          <h5>Main Process</h5>\n          <pre><code data-path=\"main-process/menus/context-menu.js\"></code></pre>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/menus/context-menu.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <script type=\"text/javascript\">\n      require('./renderer-process/menus/context-menu')\n    </script>\n\n  </section>\n</template>\n"
  },
  {
    "path": "sections/menus/shortcuts.html",
    "content": "<template class=\"task-template\">\n  <section id=\"shortcuts-section\" class=\"section js-section u-category-menu\">\n    <header class=\"section-header\">\n      <div class=\"section-wrapper\">\n        <h1>\n          <svg class=\"section-icon\"><use xlink:href=\"assets/img/icons.svg#icon-menu\"></use></svg>\n          Keyboard Shortcuts\n        </h1>\n\n        <h3>The <code>globalShortcut</code> and <code>Menu</code> modules can be used to define keyboard shortcuts.</h3>\n\n        <p>\n          In Electron, keyboard shortcuts are called accelerators.\n          They can be assigned to actions in your application's Menu,\n          or they can be assigned globally so they'll be triggered even when\n          your app doesn't have keyboard focus.\n        </p>\n\n        <p>\n          Open the full documentation for the\n          <a class=\"u-exlink\" href=\"http://electron.atom.io/docs/api/menu\">Menu</a>,\n          <a class=\"u-exlink\" href=\"http://electron.atom.io/docs/api/accelerator\">Accelerator</a>,\n          and\n          <a class=\"u-exlink\" href=\"http://electron.atom.io/docs/api/global-shortcut\">globalShortcut</a>\n          APIs in your browser.\n        </p>\n\n      </div>\n    </header>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"shortcuts-demo-toggle\" class=\"js-container-target demo-toggle-button\">Register a global keyboard shortcut\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Main</div>\n        </button>\n        <div class=\"demo-box\">\n          <p>\n            To try this demo, press <kbd class=\"normalize-to-platform\">CommandOrControl+Alt+K</kbd> on your keyboard.\n          </p>\n\n          <p>\n            Global shortcuts are detected even when the app doesn't have\n            keyboard focus, and they must be registered after the app's\n            `ready` event is emitted.\n          </p>\n\n          <h5>Main Process</h5>\n          <pre><code data-path=\"main-process/menus/shortcuts.js\"></code></pre>\n\n          <div class=\"demo-protip\">\n            <h2>ProTip</h2>\n            <strong>Avoid overriding system-wide keyboard shortcuts.</strong>\n            <p>\n              When registering global shortcuts, it's important to be aware of\n              existing defaults in the target operating system, so as not to\n              override any existing behaviors. For an overview of each\n              operating system's keyboard shortcuts, view these documents:\n            </p>\n\n            <ul>\n              <li><a class=\"u-exlink\" href=\"https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/OSXHIGuidelines/Keyboard.html\">macOS</a></li>\n              <li><a class=\"u-exlink\" href=\"http://windows.microsoft.com/en-us/windows-10/keyboard-shortcuts\">Windows</a></li>\n              <li><a class=\"u-exlink\" href=\"https://developer.gnome.org/hig/stable/keyboard-input.html.en\">Linux</a></li>\n            </ul>\n          </div>\n\n        </div>\n      </div>\n    </div>\n\n  </section>\n</template>\n"
  },
  {
    "path": "sections/native-ui/dialogs.html",
    "content": "<template class=\"task-template\">\n  <section id=\"dialogs-section\" class=\"section js-section u-category-native-ui\">\n    <header class=\"section-header\">\n      <div class=\"section-wrapper\">\n        <h1>\n          <svg class=\"section-icon\"><use xlink:href=\"assets/img/icons.svg#icon-native-ui\"></use></svg>\n          Use system dialogs\n        </h1>\n        <h3>The <code>dialog</code> module in Electron allows you to use native system dialogs for opening files or directories, saving a file or displaying informational messages.</h3>\n\n        <p>This is a main process module because this process is more efficient with native utilities and it allows the call to happen without interrupting the visible elements in your page's renderer process.</p>\n\n        <p>Open the <a href=\"http://electron.atom.io/docs/api/dialog/\">full API documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> in your browser.</p>\n      </div>\n    </header>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"open-file-demo-toggle\" class=\"js-container-target demo-toggle-button\">Open a File or Directory\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Main</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"select-directory\">View Demo</button>\n            <span class=\"demo-response\" id=\"selected-file\"></span>\n          </div>\n          <p>In this demo, the <code>ipc</code> module is used to send a message from the renderer process instructing the main process to launch the open file (or directory) dialog. If a file is selected, the main process can send that information back to the renderer process.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/native-ui/dialogs/open-file.js\"></code></pre>\n          <h5>Main Process</h5>\n          <pre><code data-path=\"main-process/native-ui/dialogs/open-file.js\"></code></pre>\n\n          <div class=\"demo-protip\">\n            <h2>ProTip</h2>\n            <strong>The sheet-style dialog on macOS.</strong>\n            <p>On macOS you can choose between a \"sheet\" dialog or a default dialog. The sheet version descends from the top of the window. To use sheet version, pass the <code>window</code> as the first argument in the dialog method.</p>\n            <pre><code class=\"language-js\">const ipc = require('electron').ipcMain\nconst dialog = require('electron').dialog\nconst BrowserWindow = require('electron').BrowserWindow\n\n\nipc.on('open-file-dialog-sheet', function (event) {\n  const window = BrowserWindow.fromWebContents(event.sender)\n  const files = dialog.showOpenDialog(window, { properties: [ 'openFile' ]})\n})</code></pre>\n          </div>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"error-dialog-demo-toggle\" class=\"js-container-target demo-toggle-button\">Error Dialog\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Main</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button id=\"error-dialog\" class=\"demo-button\">View Demo</button>\n          </div>\n          <p>In this demo, the <code>ipc</code> module is used to send a message from the renderer process instructing the main process to launch the error dialog.</p>\n\n          <p>You can use an error dialog before the app's <code>ready</code> event, which is useful for showing errors upon startup.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/native-ui/dialogs/error.js\"></code></pre>\n          <h5>Main Process</h5>\n          <pre><code data-path=\"main-process/native-ui/dialogs/error.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"information-dialog-demo-toggle\" class=\"js-container-target demo-toggle-button\">Information Dialog\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Main</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"information-dialog\">View Demo</button>\n            <span class=\"demo-response\" id=\"info-selection\"></span>\n          </div>\n          <p>In this demo, the <code>ipc</code> module is used to send a message from the renderer process instructing the main process to launch the information dialog. Options may be provided for responses which can then be relayed back to the renderer process.</p>\n\n          <p>Note: The <code>title</code> property is not displayed in macOS.</p>\n\n          <p>An information dialog can contain an icon, your choice of buttons, title and message.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/native-ui/dialogs/information.js\"></code></pre>\n          <h5>Main Process</h5>\n          <pre><code data-path=\"main-process/native-ui/dialogs/information.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"save-dialog-demo-toggle\" class=\"js-container-target demo-toggle-button\">Save Dialog\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Main</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"save-dialog\">View Demo</button>\n            <span class=\"demo-response\" id=\"file-saved\"></span>\n          </div>\n          <p>In this demo, the <code>ipc</code> module is used to send a message from the renderer process instructing the main process to launch the save dialog. It returns the path selected by the user which can be relayed back to the renderer process.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/native-ui/dialogs/save.js\"></code></pre>\n          <h5>Main Process</h5>\n          <pre><code data-path=\"main-process/native-ui/dialogs/save.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <script type=\"text/javascript\">\n      require('./renderer-process/native-ui/dialogs/open-file')\n      require('./renderer-process/native-ui/dialogs/error')\n      require('./renderer-process/native-ui/dialogs/information')\n      require('./renderer-process/native-ui/dialogs/save')\n    </script>\n\n  </section>\n</template>\n"
  },
  {
    "path": "sections/native-ui/drag.html",
    "content": "<template class=\"task-template\">\n  <section id=\"drag-section\" class=\"section js-section u-category-native-ui\">\n    <header class=\"communication\">\n      <div class=\"section-wrapper\">\n        <h1>\n          <svg class=\"section-icon\"><use xlink:href=\"assets/img/icons.svg#icon-native-ui\"></use></svg>\n          Drag and drop files\n        </h1>\n        <h3>Electron supports dragging files and content out from web content into the operating system's world.</h3>\n\n        <p>Open the <a href=\"https://electronjs.org/docs/tutorial/native-file-drag-drop\">full API documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> in your browser.</p>\n      </div>\n    </header>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"dragging-demo-toggle\" class=\"js-container-target demo-toggle-button\">Dragging files\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Both</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <a href=\"#\" id=\"drag-file-link\">Drag Demo</a>\n          </div>\n          <p>Click and drag the link above to copy the renderer process javascript file on to your machine.</p>\n\n          <p>In this demo, the <code>webContents.startDrag()</code> API is called in response to the <code>ondragstart</code> event.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/native-ui/drag/drag.js\"></code></pre>\n          <h5>Main Process</h5>\n          <pre><code data-path=\"main-process/native-ui/drag/drag.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n\n\n    <script type=\"text/javascript\">\n      require('./renderer-process/native-ui/drag/drag')\n    </script>\n\n  </section>\n</template>\n"
  },
  {
    "path": "sections/native-ui/ex-links-file-manager.html",
    "content": "<template class=\"task-template\">\n  <section id=\"ex-links-file-manager-section\" class=\"section js-section u-category-native-ui\">\n    <header class=\"section-header\">\n      <div class=\"section-wrapper\">\n        <h1>\n          <svg class=\"section-icon\"><use xlink:href=\"assets/img/icons.svg#icon-native-ui\"></use></svg>\n          Open external links and the file manager\n        </h1>\n        <h3>The <code>shell</code> module in Electron allows you to access certain native elements like the file manager and default web browser.</h3>\n\n        <p>This module works in both the main and renderer process.</p>\n        <p>Open the <a href=\"http://electron.atom.io/docs/api/shell\">full API documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> in your browser.</p>\n      </div>\n    </header>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"open-file-manager-demo-toggle\" class=\"js-container-target demo-toggle-button\">Open Path in File Manager\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Both</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"open-file-manager\">View Demo</button>\n          </div>\n          <p>This demonstrates using the <code>shell</code> module to open the system file manager at a particular location.</p>\n          <p>Clicking the demo button will open your file manager at the root.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/native-ui/ex-links-file-manager/file-manager.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"open-ex-links-demo-toggle\" class=\"js-container-target demo-toggle-button\">Open External Links\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Both</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"open-ex-links\">View Demo</button>\n          </div>\n          <p>If you do not want your app to open website links <em>within</em> the app, you can use the <code>shell</code> module to open them externally. When clicked, the links will open outside of your app and in the user's default web browser.</p>\n          <p>When the demo button is clicked, the electron website will open in your browser.<p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/native-ui/ex-links-file-manager/ex-links.js\"></code></pre>\n\n          <div class=\"demo-protip\">\n            <h2>ProTip</h2>\n            <strong>Open all outbound links externally.</strong>\n            <p>You may want to open all <code>http</code> and <code>https</code> links outside of your app. To do this, query the document and loop through each link and add a listener. This app uses the code below which is located in <code>assets/ex-links.js</code>.</p>\n            <h5>Renderer Process</h5>\n            <pre><code data-path=\"assets/ex-links.js\"></code></pre>\n          </div>\n        </div>\n      </div>\n    </div>\n\n    <script type=\"text/javascript\">\n      require('./renderer-process/native-ui/ex-links-file-manager/file-manager')\n      require('./renderer-process/native-ui/ex-links-file-manager/ex-links')\n    </script>\n\n  </section>\n</template>\n"
  },
  {
    "path": "sections/native-ui/notifications.html",
    "content": "<template class=\"task-template\">\n  <section id=\"notifications-section\" class=\"section js-section u-category-native-ui\">\n    <header class=\"notifications\">\n      <div class=\"section-wrapper\">\n        <h1>\n          <svg class=\"section-icon\"><use xlink:href=\"assets/img/icons.svg#icon-notification\"></use></svg>\n          Desktop notifications\n        </h1>\n        <h3>The <code>notification</code> module in Electron allows you to add basic desktop notifications.</h3>\n\n        <p>Electron conveniently allows developers to send notifications with the <a href=\"https://notifications.spec.whatwg.org/\">HTML5 Notification API</a>, using the currently running operating system’s native notification APIs to display it.</p>\n\n        <p><b>Note:</b> Since this is an HTML5 API it is only available in the renderer process.</p>\n\n        <p>Open the <a href=\"https://electron.atom.io/docs/all/#notifications-windows-linux-macos\">full API documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> in your browser.</p>\n      </div>\n    </header>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"basic-notification-demo-toggle\" class=\"js-container-target demo-toggle-button\">Basic notification\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win 7+, macOS, Linux (that supports libnotify)<span class=\"demo-meta-divider\">|</span> Process: Renderer</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"basic-noti\">View demo</button>\n          </div>\n          <p>This demo demonstrates a basic notification. Text only.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/native-ui/notifications/basic-notification.js\"></pre></code>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"advanced-notification-demo-toggle\" class=\"js-container-target demo-toggle-button\">Notification with image\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win 7+, macOS, Linux (that supports libnotify) <span class=\"demo-meta-divider\">|</span> Process: Renderer</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"advanced-noti\">View demo</button>\n          </div>\n          <p>This demo demonstrates a basic notification. Both text and a image</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/native-ui/notifications/advanced-notification.js\"></pre></code>\n        </div>\n      </div>\n    </div>\n\n    <script type=\"text/javascript\">\n      require('./renderer-process/native-ui/notifications/basic-notification')\n      require('./renderer-process/native-ui/notifications/advanced-notification')\n    </script>\n\n  </section>\n</template>\n"
  },
  {
    "path": "sections/native-ui/tray.html",
    "content": "<template class=\"task-template\">\n  <section id=\"tray-section\" class=\"section js-section u-category-native-ui\">\n    <header class=\"section-header\">\n      <div class=\"section-wrapper\">\n        <h1>\n          <svg class=\"section-icon\"><use xlink:href=\"assets/img/icons.svg#icon-native-ui\"></use></svg>\n          Tray\n        </h1>\n        <h3>The <code>tray</code> module allows you to create an icon in the operating system's notification area.</h3>\n        <p>This icon can also have a context menu attached.</p>\n\n        <p>Open the <a href=\"http://electron.atom.io/docs/api/tray\">full API documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> in your browser.</p>\n      </div>\n    </header>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"tray-demo-toggle\" class=\"js-container-target demo-toggle-button\">Tray\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux | Process: Main</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"put-in-tray\">View Demo</button>\n            <span class=\"demo-response\" id=\"tray-countdown\"></span>\n          </div>\n          <p>The demo button sends a message to the main process using the <code>ipc</code> module. In the main process the app is told to place an icon, with a context menu, in the tray.</p>\n\n          <p>In this example the tray icon can be removed by clicking 'Remove' in the context menu or selecting the demo button again.</p>\n          <h5>Main Process</h5>\n          <pre><code data-path=\"main-process/native-ui/tray/tray.js\"></code></pre>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/native-ui/tray/tray.js\"></code></pre>\n\n          <div class=\"demo-protip\">\n            <h2>ProTip</h2>\n            <strong>Tray support in Linux.</strong>\n            <p>On Linux distributions that only have app indicator support, users will need to install <code>libappindicator1</code> to make the tray icon work. See the <a href=\"http://electron.atom.io/docs/api/tray\">full API documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> for more details about using Tray on Linux.</p>\n          </div>\n        </div>\n      </div>\n    </div>\n\n    <script type=\"text/javascript\">\n      require('./renderer-process/native-ui/tray/tray')\n    </script>\n\n  </section>\n</template>\n"
  },
  {
    "path": "sections/system/app-sys-information.html",
    "content": "<template class=\"task-template\">\n  <section id=\"app-sys-information-section\" class=\"section js-section u-category-system\">\n    <header class=\"section-header\">\n      <div class=\"section-wrapper\">\n        <h1>\n          <svg class=\"section-icon\"><use xlink:href=\"assets/img/icons.svg#icon-system\"></use></svg>\n          Get app and system information\n        </h1>\n        <h3>With a few Node.js and Electron modules you can gather information about the user's system, app or screen.</h3>\n        <p>Links to the relevant documentation are in the demos below.</p>\n      </div>\n    </header>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"app-info-demo-toggle\" class=\"js-container-target demo-toggle-button\">Get app information\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Both</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"app-info\">View Demo</button>\n            <span class=\"demo-response\" id=\"got-app-info\"></span>\n          </div>\n          <p>The main process <code>app</code> module can be used to get the path at which your app is located on the user's computer.</p>\n          <p>In this example, to get that information from the renderer process, we use the <code>ipc</code> module to send a message to the main process requesting the app's path.</p>\n          <p>See the <a href=\"http://electron.atom.io/docs/api/app\">app module documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> for more.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/system/app-information.js\"></code></pre>\n          <h5>Main Process</h5>\n          <pre><code data-path=\"main-process/system/app-information.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"app-version-demo-toggle\" class=\"js-container-target demo-toggle-button\">Get version information\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Both</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"version-info\">View Demo</button>\n            <span class=\"demo-response\" id=\"got-version-info\"></span>\n          </div>\n          <p>The <code>process</code> module is built into Node.js (therefore you can use this in both the main and renderer processes) and in Electron apps this object has a few more useful properties on it.</p>\n          <p>The example below gets the version of Electron in use by the app.</p>\n          <p>See the <a href=\"http://electron.atom.io/docs/api/process\">process documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> for more.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/system/version-information.js\"></code></pre>\n\n          <div class=\"demo-protip\">\n            <h2>ProTip</h2>\n            <strong>Find versions of Chromium, Node.js and V8.</strong>\n            <p>Electron also includes versions of Chromium, Node.js and V8 within the <code>process.versions</code> object. You can get there quickly by opening up developer tools in an Electron app and typing <code>process.versions</code>.</p>\n            <pre><code class=\"language-js\">// Returns version of Chromium in use\nprocess.versions.chrome\n// Returns version of V8 in use\nprocess.versions.v8\n// Returns version of Node in use\nprocess.versions.node</code></pre>\n          </div>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"sys-info-demo-toggle\" class=\"js-container-target demo-toggle-button\">Get system information\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Both</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"sys-info\">View Demo</button>\n            <span class=\"demo-response\" id=\"got-sys-info\"></span>\n          </div>\n          <p>The Node.js <code>os</code> module provides useful information about the user's operating system. It's built into Node.js and can be used in both the main and renderer proesses.</p>\n          <p>In the example below we require the module and then return the location of the home directory.</p>\n\n          <p>See the full <a href=\"https://nodejs.org/api/os.html\"> os documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> for more.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/system/sys-information.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"screen-info-demo-toggle\" class=\"js-container-target demo-toggle-button\">Get screen information\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Both</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"screen-info\">View Demo</button>\n            <span class=\"demo-response\" id=\"got-screen-info\"></span>\n          </div>\n          <p>The Electron <code>screen</code> module retrieves information about screen size, displays, cursor position, etc. In the example below we retrieve the dimensions of the monitor in use.</p>\n\n          <p>See the full <a href=\"http://electron.atom.io/docs/api/screen\">screen documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> for more.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/system/screen-information.js\"></code></pre>\n\n          <div class=\"demo-protip\">\n            <h2>ProTip</h2>\n            <strong>Differences in dimensions.</strong>\n            <p>The <code>.size</code> method in the example returns the raw dimensions of the screen but because of system menu bars this may not be the actual space available for your app.</p>\n\n            <p>To get the dimensions of the available screen space use the <code>.workAreaSize</code> method. Using <code>.workArea</code> will return the coordinates as well as the dimensions of the available screen space.</p>\n          </div>\n        </div>\n      </div>\n    </div>\n\n    <script type=\"text/javascript\">\n      require('./renderer-process/system/app-information')\n      require('./renderer-process/system/version-information')\n      require('./renderer-process/system/sys-information')\n      require('./renderer-process/system/screen-information')\n    </script>\n\n  </section>\n</template>\n"
  },
  {
    "path": "sections/system/clipboard.html",
    "content": "<template class=\"task-template\">\n  <section id=\"clipboard-section\" class=\"section js-section u-category-system\">\n    <header class=\"section-header\">\n      <div class=\"section-wrapper\">\n        <h1>\n          <svg class=\"section-icon\"><use xlink:href=\"assets/img/icons.svg#icon-system\"></use></svg>\n          Clipboard\n        </h1>\n        <h3>The <code>clipboard</code> module provides methods to perform copy and paste operations.</h3>\n        <p>This module also has methods for copying text as markup (HTML) to the clipboard.</p>\n\n        <p>Open the <a href=\"http://electron.atom.io/docs/api/clipboard\">full API documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> in your browser.</p>\n      </div>\n    </header>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"copy-to-demo-toggle\" class=\"js-container-target demo-toggle-button\">Copy\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Both</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"copy-to\">Copy</button>\n            <input class=\"demo-input\" id=\"copy-to-input\" aria-label=\"Click copy\" placeholder=\"Click copy.\"></input>\n          </div>\n          <p>In this example we copy a phrase to the clipboard. After clicking 'Copy' use the text area to paste (CMD + V or CTRL + V) the phrase from the clipboard.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/system/copy.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"paste-to-demo-toggle\" class=\"js-container-target demo-toggle-button\">Paste\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Both</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"paste-to\">Paste</button>\n            <span class=\"demo-response\" id=\"paste-from\"></span>\n          </div>\n          <p>In this example we copy a string to the clipboard and then paste the results into a message above.</p>\n\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/system/paste.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <script type=\"text/javascript\">\n      require('./renderer-process/system/copy')\n      require('./renderer-process/system/paste')\n    </script>\n\n  </section>\n</template>\n"
  },
  {
    "path": "sections/system/protocol-handler.html",
    "content": "<template class=\"task-template\">\n  <section id=\"protocol-section\" class=\"section js-section u-category-system\">\n    <header class=\"section-header\">\n      <div class=\"section-wrapper\">\n        <h1>\n          <svg class=\"section-icon\"><use xlink:href=\"assets/img/icons.svg#icon-system\"></use></svg>\n          Protocol Handler\n        </h1>\n        <h3>The <code>app</code> module provides methods for handling protocols.</h3>\n        <p>These methods allow you to set and unset the protocols your app should be the default app for. Similar to when a browser asks to be your default for viewing web pages.</p>\n\n        <p>Open the <a href=\"http://electron.atom.io/docs/api/app\">full app API documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> in your browser.</p>\n      </div>\n    </header>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"copy-to-demo-toggle\" class=\"js-container-target demo-toggle-button\">Launch app from URL in another app\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS <span class=\"demo-meta-divider\">|</span> Process: Main</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"protocol-handler\">View Demo</button>\n          </div>\n          <p>You can set your app as the default app to open for a specific protocol. For instance, in this demo we set this app as the default for <code>electron-api-demos://</code>. The demo button above will launch a page in your default browser with a link. Click that link and it will re-launch this app.</p>\n          <h5>Packaging</h5>\n          <p>This feature will only work on macOS when your app is packaged. It will not work when you're launching it in development from the command-line. When you package your app you'll need to make sure the macOS <code>plist</code> for the app is updated to include the new protocol handler. If you're using <code>electron-packager</code> then you can add the flag <code>--extend-info</code> with a path to the <code>plist</code> you've created. The one for this app is below.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/system/protocol-handler.js\"></code></pre>\n          <h5>Main Process</h5>\n          <pre><code data-path=\"main-process/system/protocol-handler.js\"></code></pre>\n          <h5>macOS plist</h5>\n          <pre><code class=\"language-xml\" data-path=\"assets/mac/info.plist\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n\n    <script type=\"text/javascript\">\n      require('./renderer-process/system/protocol-handler')\n    </script>\n\n  </section>\n</template>\n"
  },
  {
    "path": "sections/system/protocol-link.html",
    "content": "<html>\n<style>\n  body {\n    padding: 80px 40px;\n    font-family: system, -apple-system, '.SFNSText-Regular', 'SF UI Text', 'Lucida Grande', 'Segoe UI', Ubuntu, Cantarell, sans-serif;\n    color: #fff;\n    background-color: #8aba87;\n    text-align: center;\n    font-size: 40px;\n  }\n\n  h2 {\n    padding: 0;\n    margin: 0;\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    transform: translate(-50%, -50%);\n  }\n\n  a.protocol {\n    color: #fff;\n  }\n</style>\n<body>\n  <a class=\"protocol\" href=\"electron-api-demos://open\"><h3>electron-api-demos://open</h3></a>\n  <p>Click the link above to return to Electron API Demos.</p>\n</body>\n</html>\n"
  },
  {
    "path": "sections/windows/crash-hang.html",
    "content": "<template class=\"task-template\">\n  <section id=\"crash-hang-section\" class=\"section js-section u-category-windows\">\n    <header class=\"section-header\">\n      <div class=\"section-wrapper\">\n        <h1>\n          <svg class=\"section-icon\"><use xlink:href=\"assets/img/icons.svg#icon-windows\"></use></svg>\n          Handling Window Crashes and Hangs\n        </h1>\n        <h3>The <code>BrowserWindow</code> module will emit events when the renderer process crashes or hangs. You can listen for these events and give users the chance to reload, wait or close that window.</h3>\n\n        <p>Open the <a href=\"http://electron.atom.io/docs/api/browser-window\">full API documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> in your browser.</p>\n      </div>\n    </header>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"new-window-crashes-demo-toggle\" class=\"js-container-target demo-toggle-button\">Relaunch window after the process crashes\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Main</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"process-crash\">View Demo</button>\n          </div>\n          <p>In this demo we create a new window (via the <code>remote</code> module) and provide a link that will force a crash using <code>process.crash()</code>.</p>\n          <p>The window is listening for the crash event and when the event occurs it prompts the user with two options: reload or close.</p>\n\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/windows/process-crash.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"new-window-hangs-demo-toggle\" class=\"js-container-target demo-toggle-button\">Relaunch window after the process hangs\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Main</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"process-hang\">View Demo</button>\n          </div>\n          <p>In this demo we create a new window (via the <code>remote</code> module) and provide a link that will force the process to hang using <code>process.hang()</code>.</p>\n          <p>The window is listening for the process to become officially unresponsive (this can take up to 30 seconds). When this event occurs it prompts the user with two options: reload or close.</p>\n\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/windows/process-hang.js\"></code></pre>\n\n          <div class=\"demo-protip\">\n            <h2>ProTip</h2>\n            <strong>Wait for the process to become responsive again.</strong>\n            <p>A third option in the case of a process that is hanging is to wait and see if the problem resolves, allowing the process to become responsive again. To do this, use the <code>BrowserWindow</code> event 'responsive' as shown below.</p>\n            <pre><code class=\"language-js\">win.on('responsive', function () {\n  // Do something when the window is responsive again\n})</code></pre>\n          </div>\n        </div>\n      </div>\n    </div>\n\n\n\n    <script type=\"text/javascript\">\n      require('./renderer-process/windows/process-crash')\n      require('./renderer-process/windows/process-hang')\n    </script>\n\n  </section>\n</template>\n"
  },
  {
    "path": "sections/windows/manage-modal.html",
    "content": "<style>\nbody {\n  padding: 10px;\n  font-family: system, -apple-system, '.SFNSText-Regular', 'SF UI Text', 'Lucida Grande', 'Segoe UI', Ubuntu, Cantarell, sans-serif;\n  color: #fff;\n  background-color: #8aba87;\n  text-align: center;\n  font-size: 34px;\n}\n\n#close {\n  color: white;\n  opacity: 0.7;\n  position: absolute;\n  bottom: 20px;\n  left: 50%;\n  transform: translateX(-50%);\n  font-size: 12px;\n  text-decoration: none;\n}\n</style>\n<p>Resize or move the window. See the size and position in the main window.</p>\n<a id=\"close\" href=\"javascript:window.close()\">Close this Window</a>\n"
  },
  {
    "path": "sections/windows/modal-toggle-visibility.html",
    "content": "<style>\nbody {\n  padding: 10px;\n  font-family: system, -apple-system, '.SFNSText-Regular', 'SF UI Text', 'Lucida Grande', 'Segoe UI', Ubuntu, Cantarell, sans-serif;\n  color: #fff;\n  background-color: #8aba87;\n  text-align: center;\n  font-size: 34px;\n}\n\n#close {\n  color: white;\n  opacity: 0.7;\n  position: absolute;\n  bottom: 20px;\n  left: 50%;\n  transform: translateX(-50%);\n  font-size: 12px;\n  text-decoration: none;\n}\n</style>\n<p>Click on the parent window to see how the \"focus on demo\" button appears.</p>\n<a id=\"close\" href=\"javascript:window.close()\">Close this Window</a>"
  },
  {
    "path": "sections/windows/modal.html",
    "content": "<style>\nbody {\n  font-family: system, -apple-system, '.SFNSText-Regular', 'SF UI Text', 'Lucida Grande', 'Segoe UI', Ubuntu, Cantarell, sans-serif;\n  color: #fff;\n  background-color: #8aba87;\n  text-align: center;\n  font-size: 40px;\n}\n\nh2 {\n  padding: 0;\n  margin: 0;\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  transform: translate(-50%, -50%);\n}\n\n#close {\n  color: white;\n  opacity: 0.7;\n  position: absolute;\n  bottom: 20px;\n  left: 50%;\n  transform: translateX(-50%);\n  font-size: 12px;\n  text-decoration: none;\n}\n\n</style>\n\n<h2>Hello World!</h2>\n<a id=\"close\" href=\"javascript:window.close()\">Close this Window</a>\n"
  },
  {
    "path": "sections/windows/process-crash.html",
    "content": "<style>\n  body {\n    padding: 20px;\n    font-family: system, -apple-system, '.SFNSText-Regular', 'SF UI Text', 'Lucida Grande', 'Segoe UI', Ubuntu, Cantarell, sans-serif;\n    color: #fff;\n    background-color: #8aba87;\n    text-align: center;\n    font-size: 40px;\n  }\n\n  #crash {\n    color: white;\n    opacity: 0.7;\n    position: absolute;\n    bottom: 20px;\n    left: 50%;\n    transform: translateX(-50%);\n    font-size: 12px;\n    text-decoration: none;\n  }\n</style>\n\n<p>Click the text below to crash and then reload this process.</p>\n<a id=\"crash\" href=\"javascript:process.crash()\">Crash this process</a>\n"
  },
  {
    "path": "sections/windows/process-hang.html",
    "content": "<style>\n  body {\n    padding: 20px;\n    font-family: system, -apple-system, '.SFNSText-Regular', 'SF UI Text', 'Lucida Grande', 'Segoe UI', Ubuntu, Cantarell, sans-serif;\n    color: #fff;\n    background-color: #8aba87;\n    text-align: center;\n  }\n\n  p {\n    font-size: 32px;\n  }\n\n  #crash {\n    color: white;\n    opacity: 0.7;\n    position: absolute;\n    bottom: 20px;\n    left: 50%;\n    transform: translateX(-50%);\n    font-size: 12px;\n    text-decoration: none;\n  }\n</style>\n\n<p>Click the text below to hang and then reload this process.</p>\n<small>(This will take up to 30 seconds.)</small>\n\n<a id=\"crash\" href=\"javascript:process.hang()\">Hang this process</a>\n"
  },
  {
    "path": "sections/windows/windows.html",
    "content": "<template class=\"task-template\">\n  <section id=\"windows-section\" class=\"section js-section u-category-windows\">\n    <header class=\"section-header\">\n      <div class=\"section-wrapper\">\n        <h1>\n          <svg class=\"section-icon\"><use xlink:href=\"assets/img/icons.svg#icon-windows\"></use></svg>\n          Create and Manage Windows\n        </h1>\n        <h3>The <code>BrowserWindow</code> module in Electron allows you to create a new browser window or manage an existing one.</h3>\n\n        <p>Each browser window is a separate process, known as the renderer process. This process, like the main process that controls the life cycle of the app, has full access to the Node.js APIs.\n\n        <p>Open the <a href=\"http://electron.atom.io/docs/api/browser-window\">full API documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> in your browser.</p>\n      </div>\n    </header>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"new-window-demo-toggle\" class=\"js-container-target demo-toggle-button\">Create a new window\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Main</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"new-window\">View Demo</button>\n          </div>\n          <p>The <code>BrowserWindow</code> module gives you the ability to create new windows in your app. This main process module can be used from the renderer process with the <code>remote</code> module, as is shown in this demo.</p>\n\n          <p>There are a lot of options when creating a new window. A few are in this demo, but visit the <a href=\"http://electron.atom.io/docs/api/browser-window\">documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> for the full list.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/windows/create-window.js\"></code></pre>\n\n          <div class=\"demo-protip\">\n            <h2>ProTip</h2>\n            <strong>Use an invisible browser window to run background tasks.</strong>\n            <p>You can set a new browser window to not be shown (be invisible) in order to use that additional renderer process as a kind of new thread in which to run JavaScript in the background of your app. You do this by setting the <code>show</code> property to <code>false</code> when defining the new window.</p>\n            <pre>\n<code class=\"language-js\">var win = new BrowserWindow({\n  width: 400, height: 225, show: false\n})</code></pre>\n          </div>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"manage-window-demo-toggle\" class=\"js-container-target demo-toggle-button\">Manage window state\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Main</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"manage-window\">View Demo</button>\n            <span class=\"demo-response\" id=\"manage-window-reply\"></span>\n          </div>\n           <p>In this demo we create a new window and listen for <code>move</code> and <code>resize</code> events on it. Click the demo button, change the new window and see the dimensions and position update here, above.</p>\n          <p>There are a lot of methods for controlling the state of the window such as the size, location, and focus status as well as events to listen to for window changes. Visit the <a href=\"http://electron.atom.io/docs/api/browser-window\">documentation<span class=\"u-visible-to-screen-reader\">(opens in new window)</span></a> for the full list.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/windows/manage-window.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button id=\"using-window-events-demo-toggle\" class=\"js-container-target demo-toggle-button\">Window events: blur and focus\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Main</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"listen-to-window\">View Demo</button>\n            <button  class=\"demo-button disappear\" id=\"focus-on-modal-window\">Focus on Demo</button>\n          </div>\n          <p>In this demo, we create a new window and listen for <code>blur</code> event on it. Click the demo button to create a new modal window, and switch focus back to the parent window by clicking on it. You can click the <i>Focus on Demo</i> button to switch focus to the modal window again.</p>\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/windows/using-window-events.js\"></code></pre>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"demo\">\n      <div class=\"demo-wrapper\">\n        <button class=\"js-container-target demo-toggle-button\">Create a frameless window\n          <div class=\"demo-meta u-avoid-clicks\">Supports: Win, macOS, Linux <span class=\"demo-meta-divider\">|</span> Process: Main</div>\n        </button>\n        <div class=\"demo-box\">\n          <div class=\"demo-controls\">\n            <button class=\"demo-button\" id=\"frameless-window\">View Demo</button>\n          </div>\n          <p>\n            A frameless window is a window that has no <a href=\"https://developer.mozilla.org/en-US/docs/Glossary/Chrome\">\"chrome\"</a>,\n            such as toolbars, title bars, status bars, borders, etc. You can make a browser window frameless by setting\n            <code>frame</code> to <code>false</code> when creating the window.\n          </p>\n\n          <h5>Renderer Process</h5>\n          <pre><code data-path=\"renderer-process/windows/frameless-window.js\"></code></pre>\n\n          <p>Windows can have a transparent background, too. By setting the <code>transparent</code> option to <code>true</code>, you can also make your frameless window transparent:</p>\n          <pre>\n<code class=\"language-js\">var win = new BrowserWindow({\n  transparent: true,\n  frame: false\n})</code></pre>\n\n        <p>\n          For more details, see the <a href=\"http://electron.atom.io/docs/api/frameless-window/\">Frameless Window</a> documentation.\n        </p>\n\n        </div>\n      </div>\n    </div>\n\n    <script type=\"text/javascript\">\n      require('./renderer-process/windows/create-window')\n      require('./renderer-process/windows/manage-window')\n      require('./renderer-process/windows/using-window-events')\n      require('./renderer-process/windows/frameless-window')\n    </script>\n\n  </section>\n</template>\n"
  },
  {
    "path": "test/index.js",
    "content": "'use strict'\n\nconst Application = require('spectron').Application\nconst electron = require('electron')\nconst chai = require('chai')\nconst chaiAsPromised = require('chai-as-promised')\nconst path = require('path')\nconst setup = require('./setup')\n\nchai.should()\nchai.use(chaiAsPromised)\n\nconst timeout = process.env.CI ? 30000 : 10000\n\ndescribe('demo app', function () {\n  this.timeout(timeout)\n\n  let app\n\n  const startApp = () => {\n    app = new Application({\n      path: electron,\n      args: [\n        path.join(__dirname, '..')\n      ],\n      waitTimeout: timeout\n    })\n\n    return app.start().then((ret) => {\n      setup.setupApp(ret)\n    })\n  }\n\n  const restartApp = () => {\n    return app.restart().then((ret) => {\n      setup.setupApp(ret)\n    })\n  }\n\n  before(() => {\n    setup.removeStoredPreferences()\n    return startApp()\n  })\n\n  after(() => {\n    if (app && app.isRunning()) {\n      return app.stop()\n    }\n  })\n\n  it('checks hardcoded path for userData is correct', function () {\n    return app.client.execute(() => {\n      return require('electron').remote.app.getPath('userData')\n    }).then((result) => {\n      return result.value\n    }).should.eventually.equal(setup.getUserDataPath())\n  })\n\n  it('opens a window displaying the about page', function () {\n    return app.client.getWindowCount().should.eventually.equal(1)\n      .browserWindow.isMinimized().should.eventually.be.false\n      .browserWindow.isDevToolsOpened().should.eventually.be.false\n      .browserWindow.isVisible().should.eventually.be.true\n      .browserWindow.isFocused().should.eventually.be.true\n      .browserWindow.getBounds().should.eventually.have.property('width').and.be.above(0)\n      .browserWindow.getBounds().should.eventually.have.property('height').and.be.above(0)\n      .browserWindow.getTitle().should.eventually.equal('Electron API Demos')\n      .waitForVisible('#about-modal').should.eventually.be.true\n      .isVisible('.js-nav').should.eventually.be.false\n      .click('button[id=\"get-started\"]').pause(500)\n      .isVisible('#about-modal').should.eventually.be.false\n      .isVisible('.js-nav').should.eventually.be.true\n  })\n\n  it('does not contain any accessibility warnings or errors', function () {\n    return app.client.dismissAboutPage()\n      .auditSectionAccessibility('windows')\n      .auditSectionAccessibility('crash-hang')\n      .auditSectionAccessibility('menus')\n      .auditSectionAccessibility('shortcuts')\n      .auditSectionAccessibility('ex-links-file-manager')\n      .auditSectionAccessibility('notifications')\n      .auditSectionAccessibility('dialogs')\n      .auditSectionAccessibility('tray')\n      .auditSectionAccessibility('ipc')\n      .auditSectionAccessibility('app-sys-information')\n      .auditSectionAccessibility('clipboard')\n      .auditSectionAccessibility('protocol')\n      .auditSectionAccessibility('desktop-capturer')\n  })\n\n  describe('when clicking on a section from the nav bar', function () {\n    it('it shows the selected section in the main area', function () {\n      return app.client.dismissAboutPage()\n        .selectSection('windows')\n        .isExisting('button.is-selected[data-section=\"windows\"]').should.eventually.be.true\n        .isVisible('#menus-section').should.eventually.be.false\n        .selectSection('menus')\n        .isVisible('#windows-section').should.eventually.be.false\n        .isExisting('button.is-selected[data-section=\"windows\"]').should.eventually.be.false\n        .isExisting('button.is-selected[data-section=\"menus\"]').should.eventually.be.true\n    })\n  })\n\n  describe('when a demo title is clicked', function () {\n    it('it expands the demo content', function () {\n      let onlyFirstVisible = Array(30).fill(false)\n      onlyFirstVisible[0] = true\n\n      return app.client.dismissAboutPage()\n        .collapseDemos()\n        .selectSection('windows')\n        .click('.js-container-target')\n        .waitForVisible('.demo-box')\n        .isVisible('.demo-box').should.eventually.deep.equal(onlyFirstVisible)\n    })\n  })\n\n  describe('when the app is restarted after use', function () {\n    it('it launches at last visited section & demo', function () {\n      let onlyFirstVisible = Array(30).fill(false)\n      onlyFirstVisible[0] = true\n\n      return app.client.waitForVisible('#windows-section')\n        .then(restartApp)\n        .then(function () {\n          return app.client.waitForVisible('#windows-section')\n            .isVisible('#windows-section').should.eventually.be.true\n            .isVisible('.demo-box').should.eventually.deep.equal(onlyFirstVisible)\n        })\n    })\n  })\n})\n"
  },
  {
    "path": "test/setup.js",
    "content": "'use strict'\n\nconst path = require('path')\nconst fs = require('fs')\nconst chaiAsPromised = require('chai-as-promised')\n\nconst getUserDataPath = function () {\n  const productName = require('../package').productName\n  switch (process.platform) {\n    case 'darwin':\n      return path.join(process.env.HOME, 'Library', 'Application Support', productName)\n    case 'win32':\n      return path.join(process.env.APPDATA, productName)\n    case 'freebsd':\n    case 'linux':\n    case 'sunos':\n      return path.join(process.env.HOME, '.config', productName)\n    default:\n      throw new Error(`Unknown userDataPath path for platform ${process.platform}`)\n  }\n}\n\nconst removeStoredPreferences = () => {\n  const userDataPath = getUserDataPath()\n  try {\n    fs.unlinkSync(path.join(userDataPath, 'Settings'))\n  } catch (error) {\n    if (error.code !== 'ENOENT') throw error\n  }\n}\n\nconst setupApp = function (app) {\n  app.client.addCommand('dismissAboutPage', function () {\n    return this.isVisible('.js-nav').then(function (navVisible) {\n      if (!navVisible) {\n        return this.click('button[id=\"get-started\"]').pause(500)\n      }\n    })\n  })\n\n  app.client.addCommand('selectSection', function (section) {\n    return this.click('button[data-section=\"' + section + '\"]').pause(100)\n      .waitForVisible('#' + section + '-section')\n  })\n\n  app.client.addCommand('expandDemos', function () {\n    return this.execute(function () {\n      for (let demo of document.querySelectorAll('.demo-wrapper')) {\n        demo.classList.add('is-open')\n      }\n    })\n  })\n\n  app.client.addCommand('collapseDemos', function () {\n    return this.execute(function () {\n      for (let demo of document.querySelectorAll('.demo-wrapper')) {\n        demo.classList.remove('is-open')\n      }\n    })\n  })\n\n  app.client.addCommand('auditSectionAccessibility', function (section) {\n    const options = {\n      ignoreRules: ['AX_COLOR_01', 'AX_TITLE_01']\n    }\n    return this.selectSection(section)\n      .expandDemos()\n      .auditAccessibility(options).then(function (audit) {\n        if (audit.failed) {\n          throw Error(section + ' section failed accessibility audit\\n' + audit.message)\n        }\n      })\n  })\n\n  chaiAsPromised.transferPromiseness = app.transferPromiseness\n  return app.client.waitUntilWindowLoaded()\n}\n\nmodule.exports = {\n  removeStoredPreferences,\n  getUserDataPath,\n  setupApp\n}\n"
  }
]