[
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  push:\n    branches:\n      - main\n    paths:\n      - \"src/**\"\n  pull_request:\n    branches:\n      - main\n    paths:\n      - \"src**\"\n      - \".github/workflows/ci.yml\"\n  workflow_dispatch:\n\njobs:\n  check:\n    name: Typecheck\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        node-version:\n          - 16\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n\n      - name: Setup node ${{ matrix.node-version }}\n        uses: actions/setup-node@v2\n        with:\n          node-version: ${{ matrix.node-version }}\n\n      - name: Install dependencies\n        uses: bahmutov/npm-install@v1\n\n      - name: Typecheck\n        uses: gozala/typescript-error-reporter-action@v1.0.8\n        with:\n          project: ./tsconfig.json\n  test-node:\n    name: Test Node\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      matrix:\n        node-version:\n          - 16\n        os:\n          - ubuntu-latest\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n\n      - name: Setup Node\n        uses: actions/setup-node@v2\n        with:\n          node-version: ${{ matrix.node-version }}\n\n      - name: Install dependencies\n        uses: bahmutov/npm-install@v1\n\n      - name: Test\n        run: yarn test:node\n  test-web:\n    name: Test Web\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        node-version:\n          - 16\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n\n      - name: Setup Node\n        uses: actions/setup-node@v2\n        with:\n          node-version: 16\n\n      - name: Install dependencies\n        uses: bahmutov/npm-install@v1\n\n      - name: Test\n        run: yarn test:web\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "on:\n  push:\n    branches:\n      - main\n  workflow_dispatch:\n\nname: release\njobs:\n  release-please:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: google-github-actions/release-please-action@v3\n        id: release\n        with:\n          token: ${{ secrets.GITHUB_TOKEN }}\n          release-type: node\n          bump-minor-pre-major: true\n      # The logic below handles the npm publication:\n      - uses: actions/checkout@v2\n        # these if statements ensure that a publication only occurs when\n        # a new release is created:\n        if: ${{ steps.release.outputs.release_created }}\n      - uses: actions/setup-node@v2\n        with:\n          node-version: \"16\"\n          registry-url: https://registry.npmjs.org/\n        if: ${{ steps.release.outputs.release_created }}\n      - name: Install\n        uses: bahmutov/npm-install@v1\n        if: ${{ steps.release.outputs.release_created }}\n      - name: Publish\n        run: npm publish --access=public\n        env:\n          NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}\n        if: ${{ steps.release.outputs.release_created }}\n"
  },
  {
    "path": ".gitignore",
    "content": "dist\n.nyc_output\ntmp\nnode_modules\n"
  },
  {
    "path": "Readme.md",
    "content": "# reflex [![Gitter][gitter.icon]][gitter.url] [![styled with prettier][prettier.icon]][prettier.url]\n\nReflex is a reactive UI library that is heavily inspired by (pretty much is a port of) [elm][] and it's amazingly simple yet powerful [architecture][elm architecture] where \"[flux][]\" (in [react][] terms) is simply a byproduct of a pattern. In order to keep a major attraction of [elm][] &mdash; [algebraic data types][] & type safety &mdash; the library uses [flow][], a static type checker, that being said it's your call whether you want to use [flow][] yourself or just happer a pure JS either way this library has things to offer.\n\nLibrary is authored as pure ES modules and can be used with [import syntax][].\n\n```js\nimport * as Reflex from \"//reflex.hashbase.io/lib.js\"\n```\n\n[elm]: http://elm-lang.org\n[elm architecture]: http://elm-lang.org/guide/architecture\n[react]: http://facebook.github.io/react/\n[immutable.js]: https://facebook.github.io/immutable-js/\n[flux]: https://facebook.github.io/flux/\n[algebraic data types]: https://en.wikipedia.org/wiki/Algebraic_data_type\n[flow]: http://flowtype.org\n[gitter.url]: https://gitter.im/mozilla/reflex?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge\n[gitter.icon]: https://badges.gitter.im/Join%20Chat.svg\n[prettier.url]: https://github.com/prettier/prettier\n[prettier.icon]: https://img.shields.io/badge/styled_with-prettier-ff69b4.svg\n[import syntax]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"reflex\",\n  \"version\": \"2.0.0\",\n  \"description\": \"Functional reactive UI library\",\n  \"keywords\": [\n    \"reflex\",\n    \"reactive\",\n    \"functional\",\n    \"UI\"\n  ],\n  \"author\": \"Irakli Gozalishvili <dev@gozala.io>\",\n  \"scripts\": {\n    \"prepare\": \"tsc --build\",\n    \"test:web\": \"playwright-test test/**/*.spec.js --cov && nyc report\",\n    \"test:node\": \"c8 --check-coverage --branches 85 --functions 70 --lines 80 mocha test/**/*.spec.js\",\n    \"test\": \"npm run test:node\",\n    \"typecheck\": \"tsc --build\",\n    \"precommit\": \"lint-staged\"\n  },\n  \"type\": \"module\",\n  \"main\": \"src/lib.js\",\n  \"types\": \"./dist/src/lib.d.ts\",\n  \"devDependencies\": {\n    \"typescript\": \"^4.6.3\",\n    \"@types/mocha\": \"^9.1.0\",\n    \"@types/chai\": \"^4.3.0\",\n    \"mocha\": \"^9.2.2\",\n    \"chai\": \"^4.3.6\",\n    \"husky\": \"^7.0.4\",\n    \"lint-staged\": \"^12.4.0\",\n    \"prettier\": \"^2.6.2\"\n  },\n  \"typesVersions\": {\n    \"*\": {\n      \"*\": [\n        \"dist/*\"\n      ],\n      \"dist/src/lib.d.ts\": [\n        \"dist/src/lib.d.ts\"\n      ]\n    }\n  },\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/src/lib.d.ts\",\n      \"import\": \"./src/lib.js\"\n    },\n    \"./src/lib.js\": {\n      \"types\": \"./dist/src/lib.d.ts\",\n      \"import\": \"./src/lib.js\"\n    }\n  },\n  \"files\": [\n    \"src\",\n    \"dist/src\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/gozala/reflex.git\"\n  },\n  \"homepage\": \"https://github.com/gozala/reflex\",\n  \"c8\": {\n    \"exclude\": [\n      \"test/**\",\n      \"dist/**\"\n    ]\n  },\n  \"lint-staged\": {\n    \"*.js\": [\n      \"prettier --parser flow --no-semi --write\",\n      \"git add\"\n    ]\n  },\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "src/Application.js",
    "content": "import { DocumentWidget } from \"./Document.js\"\n\n/**\n * @template T\n * @typedef {import('./Program').DocumentView<T>} DocumentView\n */\n/**\n * @template Message, State\n * @extends {DocumentWidget<Message, State>}\n */\nclass ApplicationWidget extends DocumentWidget {\n  /**\n   *\n   * @param {import('./Program').Router<Message>} router\n   */\n  constructor(router) {\n    super()\n    this.onExternalURLRequest = router.onExternalURLRequest\n    this.onInternalURLRequest = router.onInternalURLRequest\n    this.onURLChange = router.onURLChange\n  }\n  getURL() {\n    return new URL(this.root.location.href)\n  }\n  /**\n   * @param {MouseEvent} event\n   */\n  handleEvent(event) {\n    switch (event.type) {\n      case \"navigate\": // manually notify when we do pushState replaceState\n      case \"popstate\":\n      case \"hashchange\":\n        return this.thread.send(this.onURLChange(this.getURL()))\n      case \"click\": {\n        if (\n          !event.ctrlKey &&\n          !event.metaKey &&\n          !event.shiftKey &&\n          event.button < 1 &&\n          // @ts-ignore\n          !event.target.target &&\n          // @ts-ignore\n          !event.target.download\n        ) {\n          event.preventDefault()\n          const current = this.getURL()\n          // @ts-ignore\n          const next = new URL(event.currentTarget.href, current.href)\n\n          const isInternal =\n            current.protocol === next.protocol &&\n            current.host === next.host &&\n            current.port === next.port\n\n          const message = isInternal\n            ? this.onInternalURLRequest(next)\n            : this.onExternalURLRequest(next)\n\n          return this.thread.send(message)\n        }\n      }\n    }\n    return undefined\n  }\n\n  /**\n   * @param {Document} document\n   */\n  addListeners(document) {\n    const top = document.defaultView\n    if (top) {\n      top.addEventListener(\"popstate\", this)\n      top.addEventListener(\"hashchange\", this)\n      // @ts-ignore\n      top.onnavigate = this\n    } else {\n      throw new Error(\"document.defaultView is not defined\")\n    }\n  }\n}\n\n/**\n * @template {{url?:URL}} Options\n * @template Message, State\n * @param {import('./Program').Application<Message, State, DocumentView<Message>, Options>} application\n * @param {Options} options\n * @param {Document} document\n * @returns {ApplicationWidget<Message, State>}\n */\nexport const spawn = (\n  application,\n  options,\n  document\n) /*: ApplicationWidget<a, model, config> */ => {\n  const self = new ApplicationWidget(application)\n  const root = DocumentWidget.root(document)\n  self.update = application.update\n  self.view = application.view\n  self.root = root\n  self.node = root.widget ? root.widget.node : self.mount(root)\n  self.thread = self.fork(root)\n  root.widget = self\n  self.addListeners(document)\n  options.url = self.getURL()\n  self.transact(application.init(options))\n\n  return self\n}\n"
  },
  {
    "path": "src/Attribute.js",
    "content": "// @flow strict\n\nimport { attribute, property, style, on } from \"./VirtualDOM.js\"\n\nexport { style, attribute, property, on }\n// // TODO: defaultValue, defaultChecked, innerHTML, suppressContentEditableWarning, suppressHydrationWarning, style\n\n/**\n * @template {string|number|boolean} T\n * @param {T} value\n */\nexport const defaultValue = value => property(\"defaultValue\", value)\n\n/**\n * @template {string|number|boolean} T\n * @param {T} value\n */\nexport const value = value => property(\"value\", value)\n\n/**\n * @template {string} T\n * @param {T} value\n */\nexport const acceptCharset = value => property(\"accept-charset\", value)\n\n/**\n * @template {string} T\n * @param {T} value\n */\nexport const className = value => attribute(\"class\", value)\n\n/**\n * @param  {string[]} values\n */\nexport const classList = (...values) => attribute(\"class\", values.join(\" \"))\n\n/**\n *\n * @param {string} value\n */\nexport const textContent = value => property(\"textContent\", value)\n\n/**\n * @param {string} value\n */\nexport const For = value => attribute(\"for\", value)\n\n/**\n * @param {string} value\n */\nexport const Equiv = value => attribute(\"equiv\", value)\n\n/**\n * @param {string} name\n * @param {string} value\n */\nexport const data = (name, value) => attribute(`data-${name}`, value)\n\n/**\n * @param {string} name\n */\nconst setHTMLAttribute = name =>\n  /**\n   * @param {string} [value]\n   */\n  (value = \"\") => attribute(name, value)\n\nexport const src = setHTMLAttribute(\"src\")\nexport const srcset = setHTMLAttribute(\"srcset\")\nexport const alt = setHTMLAttribute(\"alt\")\nexport const href = setHTMLAttribute(\"href\")\nexport const id = setHTMLAttribute(\"id\")\nexport const accept = setHTMLAttribute(\"accept\")\nexport const type = setHTMLAttribute(\"type\")\nexport const placeholder = setHTMLAttribute(\"placeholder\")\nexport const title = setHTMLAttribute(\"title\")\n\n/**\n * @param {string} name\n */\nconst setBooleanHTMLAttribute = name =>\n  /**\n   * @param {boolean} value\n   */\n  value => attribute(name, value ? \"true\" : \"false\")\n\nexport const contentEditable = setBooleanHTMLAttribute(\"contenteditable\")\nexport const draggable = setBooleanHTMLAttribute(\"draggable\")\nexport const spellCheck = setBooleanHTMLAttribute(\"spellcheck\")\n\n/**\n * @param {string} name\n */\nconst setBooleanSVGAttribute = name =>\n  /**\n   * @param {boolean} value\n   */\n  value => attribute(name, value ? \"true\" : \"false\")\n\nexport const autoReverse = setBooleanSVGAttribute(\"autoReverse\")\nexport const externalResourcesRequired = setBooleanSVGAttribute(\n  \"externalResourcesRequired\"\n)\nexport const preserveAlpha = setBooleanSVGAttribute(\"preserveAlpha\")\n\n/**\n *\n * @param {string} name\n */\nconst setModalHTMLAttribute = name =>\n  /**\n   *\n   * @param {boolean} [value]\n   */\n  (value = true) => attribute(name, value ? \"\" : null)\n\nexport const allowFullScreen = setModalHTMLAttribute(\"allowfullscreen\")\nexport const async = setModalHTMLAttribute(\"async\")\nexport const autoFocus = setModalHTMLAttribute(\"autofocus\")\nexport const autoPlay = setModalHTMLAttribute(\"autoplay\")\nexport const controls = setModalHTMLAttribute(\"controls\")\nexport const htmlDefault = setModalHTMLAttribute(\"default\")\nexport const defer = setModalHTMLAttribute(\"defer\")\nexport const disabled = setModalHTMLAttribute(\"disabled\")\nexport const formNoValidate = setModalHTMLAttribute(\"formnovalidate\")\nexport const hidden = setModalHTMLAttribute(\"hidden\")\nexport const loop = setModalHTMLAttribute(\"loop\")\nexport const noValidate = setModalHTMLAttribute(\"novalidate\")\nexport const open = setModalHTMLAttribute(\"open\")\nexport const playsInline = setModalHTMLAttribute(\"playsinline\")\nexport const readOnly = setModalHTMLAttribute(\"readonly\")\nexport const required = setModalHTMLAttribute(\"required\")\nexport const reversed = setModalHTMLAttribute(\"reversed\")\nexport const scoped = setModalHTMLAttribute(\"scoped\")\nexport const seamless = setModalHTMLAttribute(\"seamless\")\nexport const itemScope = setModalHTMLAttribute(\"itemscope\")\n\n/**\n * @param {string} name\n */\nconst setBooleanProperty = name =>\n  /**\n   *\n   * @param {boolean} value\n   */\n  value => property(name, value)\n\nexport const checked = setBooleanProperty(\"checked\")\nexport const multiple = setBooleanProperty(\"multiple\")\nexport const muted = setBooleanProperty(\"muted\")\nexport const selected = setBooleanProperty(\"selected\")\n\n/**\n * @param {string} name\n */\nconst setOptionalStringAttribute = name =>\n  /**\n   *\n   * @param {string} [value]\n   */\n  (value = \"\") => attribute(name, value)\n\nexport const capture = setOptionalStringAttribute(\"capture\")\nexport const download = setOptionalStringAttribute(\"download\")\n\n/**\n * @param {string} name\n */\nconst setNumberAttribute = name =>\n  /**\n   * @param {number} value\n   */\n  value => attribute(name, `${value}`)\n\nexport const cols = setNumberAttribute(\"cols\")\nexport const rows = setNumberAttribute(\"rows\")\nexport const size = setNumberAttribute(\"size\")\nexport const span = setNumberAttribute(\"span\")\nexport const tabIndex = setNumberAttribute(\"tabindex\")\n\nexport const rowSpan = setNumberAttribute(\"rowSpan\")\nexport const start = setNumberAttribute(\"start\")\n"
  },
  {
    "path": "src/Basics.js",
    "content": "/**\n * @template T\n * @param {T} value\n * @returns {T}\n */\nexport const identity = value => value\n\n/**\n * @template T\n * @param {T} value\n * @returns {() => T}\n */\nexport const always = value => () => value\n\nexport const True = always(/** @type {true}*/ true)\nexport const False = always(/** @type {false}*/ false)\nexport const Null = always(null)\nexport const Void = always(/** @type {undefined} */ undefined)\nexport const EmptyString = always(/** @type {\"\"} */ \"\")\nexport const EmptyObject = always(Object.freeze({}))\n/** @type {readonly any[]} */\nconst anyArray = Object.freeze(/** @type {any[]}*/ [])\nexport const EmptyArray /*: <$, a>($) => a[] */ = always(anyArray)\n\n/** @type {Record<any, any>} */\nconst table = Object.freeze(Object.create(null))\nexport const EmptyTable = always(table)\n\n/**\n * @param {never} value\n * @returns {any}\n */\nexport const unreachable = value => {\n  console.error(`value passed to never`, value)\n  throw TypeError(\n    `unreachable was supposed to be unreachable but it was called with ${value}`\n  )\n}\n\n/**\n * @template T\n * @param {T} [value]\n */\nexport const nothing = value => void value\n\nconst defaultReason =\n  \"Typesystem established invariant was broken at runtime, likely due to incorrect call from untyped JS.\"\n\n/**\n * @param {Error} reason\n * @returns {never}\n */\nexport const panic = /*:: <error> */(reason = new Error(defaultReason)) => {\n  throw reason\n}\n"
  },
  {
    "path": "src/Document.js",
    "content": "// @flow strict\n\nimport { virtualize, diff, patch, doc } from \"./VirtualDOM.js\"\nimport { Widget, MainThread } from \"./Widget.js\"\n\n/**\n * @template Message\n * @typedef {import('./Program').DocumentView<Message>} DocumentView\n */\n\n/**\n * @template Message\n * @typedef {{\n *  body: Element\n *  title: string\n *  location: Location\n *  widget?: {\n *    node: DocumentView<Message>\n *    thread: MainThread<Message>\n *  }\n * }} RenderedDocument\n */\n\n/**\n * @template Message, State\n * @extends {Widget<Message, State, DocumentView<Message>, RenderedDocument<Message>>}\n */\nexport class DocumentWidget extends Widget {\n  /**\n   * @template Message\n   * @param {Document} document\n   * @returns {RenderedDocument<Message>}\n   */\n  static root(document) {\n    const root = document\n    if (!document.body) {\n      document.appendChild(document.createElement(\"body\"))\n    }\n    return root\n  }\n  /**\n   * @param {RenderedDocument<Message>} root\n   * @returns {DocumentView<Message>}\n   */\n  mount(root) {\n    return root.widget\n      ? root.widget.node\n      : doc(root.title, virtualize(root.body))\n  }\n  /**\n   *\n   * @param {RenderedDocument<Message>} root\n   * @returns {MainThread<Message>}\n   */\n  fork(root) {\n    const thread = root.widget ? root.widget.thread : Widget.fork(this)\n    thread.root = this\n    return thread\n  }\n  /**\n   *\n   * @param {State} state\n   */\n  render(state) {\n    const newDocument = this.view(state)\n    const renderedDocument = this.node\n    const delta = diff(renderedDocument.body, newDocument.body)\n    patch(this.root.body, renderedDocument.body, delta, this.thread)\n    this.node = newDocument\n    if (renderedDocument.title !== newDocument.title) {\n      this.root.title = newDocument.title\n    }\n  }\n}\n\n/**\n * @template Message, State, Options\n * @param {import('./Program').Program<Message, State, DocumentView<Message>, Options>} program\n * @param {Options} options\n * @param {Document} document\n * @returns {Widget<Message, State, DocumentView<Message>, RenderedDocument<Message>>}\n */\nexport const spawn = ({ init, update, view }, options, document) => {\n  const self = new DocumentWidget()\n  const root = DocumentWidget.root(document)\n  self.update = update\n  self.view = view\n  self.root = root\n  self.node = self.mount(root)\n  self.thread = self.fork(root)\n  root.widget = self\n  self.transact(init(options))\n  return self\n}\n"
  },
  {
    "path": "src/Effect.js",
    "content": "import { nothing } from \"./Basics.js\"\n\n/**\n * @template T\n * @typedef {import('./Task').Effect<T>} Effect<T>\n */\n\n/**\n * @implements {Effect<any>}\n */\nclass None {\n  perform() {}\n  map() {\n    return this\n  }\n}\n\nconst none = new None()\n\n/**\n * @template T\n * @typedef {import('./Task').Main<T>} Main\n */\n/**\n * @template T\n * @implements {Effect<T>}\n */\nclass Send {\n  /**\n   *\n   * @param {T} message\n   */\n  constructor(message) {\n    /**\n     * @private\n     */\n    this.message = message\n  }\n  /**\n   * @param {Main<T>} main\n   */\n  perform(main) {\n    main.send(this.message)\n  }\n  /**\n   * @template U\n   * @param {(value:T) => U} tag\n   * @returns {Effect<U>}\n   */\n  map(tag) {\n    return new Tagged(this, tag)\n  }\n}\n\n/**\n * @template X, I, O\n */\nclass FX {\n  /**\n   * @param {import('./Task').Task<X, I>} task\n   * @param {(value:I) => void|O} success\n   * @param {(error:X) => void|O} failure\n   */\n  constructor(task, success, failure) {\n    /**\n     * @private\n     */\n    this.task = task\n    /**\n     * @private\n     */\n    this.success = success\n    /**\n     * @private\n     */\n    this.failure = failure\n  }\n\n  /**\n   * @private\n   * @param {Main<O>} main\n   */\n  async execute(main) {\n    try {\n      const value = await this.task()\n      const message = this.success(value)\n      if (message != null) {\n        main.send(message)\n      }\n    } catch (error) {\n      const message = this.failure(/** @type {X} */(error))\n      if (message != null) {\n        main.send(message)\n      }\n    }\n  }\n\n  /**\n   * @param {Main<O>} main\n   */\n  perform(main) {\n    this.execute(main)\n  }\n\n  /**\n   * @template U\n   * @param {(value:O) => U} tag\n   * @returns {Effect<U>}\n   */\n  map(tag) {\n    return new Tagged(this, tag)\n  }\n}\n\n/**\n * @template T\n * @implements {Effect<T>}\n */\nclass Batch {\n  /**\n   *\n   * @param {Effect<T>[]} effects\n   */\n  constructor(effects) {\n    /**\n     * @private\n     */\n    this.effects = effects\n  }\n\n  /**\n   * @param {Main<T>} main\n   */\n  perform(main) {\n    for (const fx of this.effects) {\n      fx.perform(main)\n    }\n  }\n\n  /**\n   * @template U\n   * @param {(value:T) => U} tag\n   * @returns {Effect<U>}\n   */\n  map(tag) {\n    return new Tagged(this, tag)\n  }\n}\n\n/**\n * @typedef {import('./Task').Thread} Thread\n * @typedef {import('./Task').ThreadID} ThreadID\n */\n\n/**\n * @template T, U\n * @implements {Effect<U>}\n * @implements {Main<T>}\n */\nexport class Tagged {\n  /**\n   * @param {Effect<T>} fx\n   * @param {(value:T) => U} tag\n   */\n  constructor(fx, tag) {\n    /**\n     * @private\n     */\n    this.fx = fx\n    /**\n     * @private\n     */\n    this.tag = tag\n    /**\n     * @private\n     * @type {Main<U>}\n     */\n    this.port\n  }\n  /**\n   *\n   * @param {Main<U>} main\n   */\n  perform(main) {\n    this.port = main\n    this.fx.perform(this)\n  }\n\n  /**\n   * @param {Thread} thread\n   */\n  link(thread) {\n    return this.port.link(thread)\n  }\n  /**\n   * @param {Thread} thread\n   */\n  unlink(thread) {\n    return this.port.unlink(thread)\n  }\n  /**\n   * @param {ThreadID} id\n   */\n  linked(id) {\n    return this.port.linked(id)\n  }\n  /**\n   * @param {T} message\n   */\n  send(message) {\n    return this.port.send(this.tag(message))\n  }\n  /**\n   * @template E\n   * @param {(value:U) => E} tag\n   * @returns {Effect<E>}\n   */\n  map(tag) {\n    return new Tagged(this, tag)\n  }\n}\n\nexport const nofx = none\n\n/**\n * Creates an effect that will execute a given task and send\n * a message back to program. Provided handlers are used to turn task\n * result into message\n *\n * @template X, I, O\n * @param {import('./Task').Task<X, I>} task\n * @param {(value:I) => O|void} [ok]\n * @param {(error:X) => O|void} [error]\n */\nexport const fx = (task, ok = nothing, error = warn) /*: Effect<message> */ =>\n  new FX(task, ok, error)\n\n/**\n * Sends a given message to the program\n *\n * @template T\n * @param {T} message\n */\nexport const send = message => new Send(message)\n\n/**\n * @template T\n * @param  {Effect<T>[]} fx\n */\nexport const batch = (...fx) => new Batch(fx)\n\n/**\n * @param {unknown} error\n */\nconst warn = error => {\n  console.warn(\"Task failed but error was not handled\", error)\n}\n"
  },
  {
    "path": "src/Element.js",
    "content": "import { node, text, doc, keyedNode, customElement } from \"./VirtualDOM.js\"\n\n/**\n * @param {string} tag\n */\nconst factory = tag =>\n  /**\n   * @template T\n   * @param {import('./VirtualDOM').Attribute<T>[]} [settings]\n   * @param {import('./VirtualDOM').Node<T>[]} [children]\n   */\n  (settings, children) => node(tag, settings, children)\n\nexport { text, node, doc, customElement, keyedNode }\nexport const html = factory(\"html\")\nexport const link = factory(\"link\")\nexport const meta = factory(\"meta\")\nexport const style = factory(\"style\")\nexport const body = factory(\"body\")\nexport const address = factory(\"address\")\nexport const article = factory(\"article\")\nexport const aside = factory(\"aside\")\nexport const footer = factory(\"footer\")\nexport const header = factory(\"header\")\nexport const h1 = factory(\"h1\")\nexport const h2 = factory(\"h2\")\nexport const h3 = factory(\"h3\")\nexport const h4 = factory(\"h4\")\nexport const h5 = factory(\"h5\")\nexport const h6 = factory(\"h6\")\nexport const hgroup = factory(\"hgroup\")\nexport const nav = factory(\"nav\")\nexport const section = factory(\"section\")\nexport const blockquote = factory(\"blockquote\")\nexport const dd = factory(\"dd\")\nexport const dir = factory(\"dir\")\nexport const div = factory(\"div\")\nexport const dl = factory(\"dl\")\nexport const dt = factory(\"dt\")\nexport const figcaption = factory(\"figcaption\")\nexport const figure = factory(\"figure\")\nexport const hr = factory(\"hr\")\nexport const li = factory(\"li\")\nexport const main = factory(\"main\")\nexport const ol = factory(\"ol\")\nexport const p = factory(\"p\")\nexport const pre = factory(\"pre\")\nexport const ul = factory(\"ul\")\nexport const a = factory(\"a\")\nexport const abbr = factory(\"abbr\")\nexport const b = factory(\"b\")\nexport const bdi = factory(\"bdi\")\nexport const bdo = factory(\"bdo\")\nexport const br = factory(\"br\")\nexport const cite = factory(\"cite\")\nexport const code = factory(\"code\")\nexport const data = factory(\"data\")\nexport const dfn = factory(\"dfn\")\nexport const em = factory(\"em\")\nexport const i = factory(\"i\")\nexport const kbd = factory(\"kbd\")\nexport const mark = factory(\"mark\")\nexport const nobr = factory(\"nobr\")\nexport const q = factory(\"q\")\nexport const rp = factory(\"rp\")\nexport const rt = factory(\"rt\")\nexport const rtc = factory(\"rtc\")\nexport const ruby = factory(\"ruby\")\nexport const s = factory(\"s\")\nexport const samp = factory(\"samp\")\nexport const small = factory(\"small\")\nexport const span = factory(\"span\")\nexport const strong = factory(\"strong\")\nexport const sub = factory(\"sub\")\nexport const sup = factory(\"sup\")\nexport const time = factory(\"time\")\nexport const u = factory(\"u\")\nexport const Var = factory(\"var\")\nexport const wbr = factory(\"wbr\")\nexport const area = factory(\"area\")\nexport const audio = factory(\"audio\")\nexport const img = factory(\"img\")\nexport const map = factory(\"map\")\nexport const track = factory(\"track\")\nexport const video = factory(\"video\")\nexport const applet = factory(\"applet\")\nexport const embed = factory(\"embed\")\nexport const noembed = factory(\"noembed\")\nexport const object = factory(\"object\")\nexport const param = factory(\"param\")\nexport const picture = factory(\"picture\")\nexport const source = factory(\"source\")\nexport const canvas = factory(\"canvas\")\nexport const noscript = factory(\"noscript\")\nexport const script = factory(\"script\")\nexport const del = factory(\"del\")\nexport const ins = factory(\"ins\")\nexport const caption = factory(\"caption\")\nexport const col = factory(\"col\")\nexport const colgroup = factory(\"colgroup\")\nexport const table = factory(\"table\")\nexport const tbody = factory(\"tbody\")\nexport const td = factory(\"td\")\nexport const tfoot = factory(\"tfoot\")\nexport const th = factory(\"th\")\nexport const thead = factory(\"thead\")\nexport const tr = factory(\"tr\")\nexport const button = factory(\"button\")\nexport const datalist = factory(\"datalist\")\nexport const fieldset = factory(\"fieldset\")\nexport const form = factory(\"form\")\nexport const input = factory(\"input\")\nexport const label = factory(\"label\")\nexport const legend = factory(\"legend\")\nexport const meter = factory(\"meter\")\nexport const optgroup = factory(\"optgroup\")\nexport const option = factory(\"option\")\nexport const output = factory(\"output\")\nexport const progress = factory(\"progress\")\nexport const select = factory(\"select\")\nexport const textarea = factory(\"textarea\")\nexport const details = factory(\"details\")\nexport const dialog = factory(\"dialog\")\nexport const menu = factory(\"menu\")\nexport const menuitem = factory(\"menuitem\")\nexport const summary = factory(\"summary\")\nexport const content = factory(\"content\")\nexport const element = factory(\"element\")\nexport const shadow = factory(\"shadow\")\nexport const slot = factory(\"slot\")\nexport const template = factory(\"template\")\nexport const acronym = factory(\"acronym\")\nexport const basefont = factory(\"basefont\")\nexport const bgsound = factory(\"bgsound\")\nexport const big = factory(\"big\")\nexport const blink = factory(\"blink\")\nexport const center = factory(\"center\")\nexport const command = factory(\"command\")\nexport const font = factory(\"font\")\nexport const frame = factory(\"frame\")\nexport const frameset = factory(\"frameset\")\nexport const image = factory(\"image\")\nexport const isindex = factory(\"isindex\")\nexport const keygen = factory(\"keygen\")\nexport const listing = factory(\"listing\")\nexport const marquee = factory(\"marquee\")\nexport const multicol = factory(\"multicol\")\nexport const nextid = factory(\"nextid\")\nexport const noframes = factory(\"noframes\")\nexport const plaintext = factory(\"plaintext\")\nexport const spacer = factory(\"spacer\")\nexport const strike = factory(\"strike\")\nexport const tt = factory(\"tt\")\nexport const xmp = factory(\"xmp\")\n"
  },
  {
    "path": "src/Program.ts",
    "content": "import { Transaction, Main } from \"./Task\"\nimport { Node } from \"./VirtualDOM\"\nexport interface Program<Message, State, View, Options> {\n  init(options: Options): Transaction<Message, State>\n  update(message: Message, state: State): Transaction<Message, State>\n  view(state: State): View\n}\n\nexport interface Router<Message> {\n  onExternalURLRequest(url: URL): Message\n  onInternalURLRequest(url: URL): Message\n  onURLChange(url: URL): Message\n}\nexport interface Application<Message, State, View, Options>\n  extends Router<Message>,\n    Program<Message, State, View, Options> {}\n\nexport interface DocumentView<T> {\n  title: string\n  body: Node<T>\n}\n\nexport interface RenderedDocument<T> {\n  body: Element\n  title: string\n  location: Location\n  widget?: {\n    node: DocumentView<T>\n    thread: Main<T>\n  }\n}\n"
  },
  {
    "path": "src/Task.ts",
    "content": "export type Phantom<T> = T & { readonly kind: unique symbol }\n\nexport type ThreadID = Phantom<string>\n\nexport interface Thread {\n  exit(reason?: Error): void\n}\n\nexport interface Port<T> {\n  send(message: T): unknown\n}\n\nexport interface Main<message> extends Port<message> {\n  link(thread: Thread): ThreadID\n  unlink(thread: Thread): void\n  linked(thread: ThreadID): Thread | undefined | null\n}\n\nexport interface IO<T> {\n  perform(thread: Main<T>): unknown\n}\nexport type Transaction<message, state> = [state, IO<message>]\n\nexport interface Sync<T> {\n  sync(value: T): void\n}\n\nexport interface Effect<T> extends IO<T> {\n  map<U>(tag: (value: T) => U): Effect<U>\n}\n\nexport interface AsyncResult<X, T> {\n  then(succeed: (value: T) => void, fail: (error: X) => void): unknown\n}\n\nexport interface Task<X, T> {\n  (): AsyncResult<X, T>\n}\n"
  },
  {
    "path": "src/VirtualDOM.d.ts",
    "content": "import { Port } from \"./Task\"\nexport interface Doc<T> {\n  title: string\n  body: Node<T>\n\n  map<U>(f: (inn: T) => U): Doc<U>\n}\n\nexport declare class Node<T> {\n  settings(): Attribute<T>[]\n  children(): Node<T>[]\n  map<U>(f: (inn: T) => U): Node<U>\n}\nexport declare class Attribute<T> {\n  map<U>(f: (inn: T) => U): Attribute<U>\n}\nexport type Keyed<T> = [string, T]\n\nexport declare function node<\n  A extends Attribute<unknown>,\n  C extends Node<unknown>\n>(localName: string, attributes?: A[], children?: C[]): EventNode<A | C>\n\ntype EventSource<T> = Attribute<T> | Node<T>\n\ntype EventNode<E extends EventSource<unknown>> = E extends EventSource<infer T>\n  ? Node<T>\n  : never\nexport declare function customElement<A extends Attribute<unknown>>(\n  localName: string,\n  constructor: { new (): HTMLElement },\n  attributes?: A[]\n): EventNode<A>\n\nexport declare function keyedNode<\n  A extends Attribute<unknown>,\n  C extends Node<unknown>\n>(localName: string, attributes?: A[], children?: Keyed<C>[]): EventNode<A | C>\n\nexport declare function keyedNodeNS<\n  A extends Attribute<unknown>,\n  C extends Node<unknown>\n>(\n  namespace: string,\n  localName: string,\n  attributes?: A[],\n  children?: Keyed<C>[]\n): EventNode<A | C>\n\nexport declare function nodeNS<\n  A extends Attribute<unknown>,\n  C extends Node<unknown>\n>(\n  namespace: string,\n  localName: string,\n  attributes?: A[],\n  children?: C[]\n): EventNode<A | C>\n\nexport declare function text(value: string): Node<never>\nexport declare function doc<T>(title: string, body: Node<T>): Doc<T>\n\nexport declare function property<T>(name: string, value: T): Attribute<never>\nexport declare function attribute(\n  name: string,\n  value: null | string\n): Attribute<never>\n\nexport declare function attributeNS(\n  namespace: string,\n  name: string,\n  value: string | boolean | number | null | void\n): Attribute<never>\nexport declare function style(string, string): Attribute<never>\n\nexport interface Decoder<In, Out> {\n  decode(inn): Out | Error\n}\n\nexport type EncodedEvent =\n  | Event\n  | DragEvent\n  | MouseEvent\n  | KeyboardEvent\n  | UIEvent\n\nexport interface DecodedEvent<T> {\n  message: T\n  preventDefault?: boolean\n  stopPropagation?: boolean\n}\n\nexport interface EventDecoder<T>\n  extends Decoder<EncodedEvent, DecodedEvent<T>> {}\n\nexport declare function on<T>(\n  type: string,\n  decoder: EventDecoder<T>\n): Attribute<T>\n\ndeclare class Delta {}\n\nexport type { Delta }\n\nexport declare function diff<T>(before: Node<T>, after: Node<T>): Delta\nexport declare function patch<T>(\n  root: EventTarget,\n  current: Node<T>,\n  delta: Delta,\n  port: Port<T>\n): void\nexport declare function virtualize<T>(EventTarget): Node<T>\n"
  },
  {
    "path": "src/VirtualDOM.js",
    "content": "// @ts-nocheck\n\nconst TEXT = \"VirtualDOM.Text\"\nconst NODE = \"VirtualDOM.Node\"\nconst KEYED_NODE = \"VirtualDOM.Keyed.Node\"\nconst CUSTOM_NODE = \"VirtualDOM.Custom\"\nconst CUSTOM_ELEMENT = \"VirtualDOM.CustomElement\"\nconst TAGGED_NODE = \"VirtualDOM.Tagger\"\nconst THUNK_NODE = \"VirtualDOM.Thunk\"\n\nconst OP_REDRAW = \"VirtualDOM.OP.Redraw\"\nconst OP_THUNK = \"VirtualDOM.OP.Thunk\"\nconst OP_TAGGER = \"VirtualDOM.OP.Tagger\"\nconst OP_TEXT = \"VirtualDOM.OP.Text\"\nconst OP_FACTS = \"VirtualDOM.OP.Facts\"\nconst OP_CUSTOM = \"VirtualDOM.OP.Custom\"\nconst OP_REMOVE_LAST = \"VirtualDOM.OP.RemoveLast\"\nconst OP_APPEND = \"VirtualDOM.OP.Append\"\nconst OP_REORDER = \"VirtualDOM.OP.Reorder\"\nconst OP_REMOVE = \"VirtualDOM.OP.Remove\"\nconst OP_DELETE = \"VirtualDOM.OP.Delete\"\nconst OP_INSERT = \"VirtualDOM.OP.Insert\"\nconst OP_MOVE = \"VirtualDOM.OP.Move\"\n\nconst SETTING_EVENT = \"VirtualDOM.Setting.Event\"\nconst SETTING_STYLE = \"VirtualDOM.Setting.Style\"\nconst SETTING_PROPERTY = \"VirtualDOM.Setting.Property\"\nconst SETTING_ATTRIBUTE = \"VirtualDOM.Setting.Attribute\"\nconst SETTING_ATTRIBUTE_NS = \"VirtualDOM.Setting.AttributeNS\"\n\n// HELPERS\n\nfunction appendChild(parent, child) {\n  parent.appendChild(child)\n}\n\nvar init = function(virtualNode, flagDecoder, debugMetadata, args) {\n  const { node } = args\n\n  node.parentNode.replaceChild(\n    render(node.ownerDocument, virtualNode, function() {}),\n    node\n  )\n\n  return {}\n}\n\n// TEXT\n\nclass Text {\n  constructor(content) {\n    this.nodeType = TEXT\n    this.text = content\n  }\n  map(tagger) {\n    return this\n  }\n  toInnerHTML() {\n    return \"\"\n  }\n  toOuterHTML(indent) {\n    return `${indent}${this.text}`\n  }\n  get innerHTML() {\n    return this.toInnerHTML()\n  }\n  get outerHTML() {\n    return this.toOuterHTML()\n  }\n}\n\nexport const text = content => new Text(content)\n\n// NODE\n\nconst noKids = Object.freeze([])\nconst noFacts = Object.freeze([])\n\nclass CustomElement {\n  constructor(localName, elementConstructor, options, settings) {\n    this.nodeType = CUSTOM_ELEMENT\n    this.localName = localName\n    this.elementConstructor = elementConstructor\n    this.options = options\n    this.settings = settings\n    this.children = noKids\n  }\n  map(tagger) {\n    return new TaggerNode(tagger, this)\n  }\n  serializeSettings(key = \"\") {\n    return Node.prototype.serializeSettings.call(this, key)\n  }\n  toOuterHTML(indent = \"\", key = \"\") {\n    return Node.prototype.toOuterHTML.call(this, indent, key)\n  }\n  toInnerHTML(indent = \"\") {\n    return Node.prototype.toInnerHTML.call(this, indent)\n  }\n  get outerHTML() {\n    return this.toOuterHTML()\n  }\n  get innerHTML() {\n    return this.toInnerHTML()\n  }\n}\n\nexport const customElement = (localName, constructor, settings) =>\n  new CustomElement(localName, constructor, undefined, organizeFacts(settings))\n\nclass Node {\n  constructor(localName, settings, children, namespace, descendantsCount) {\n    this.nodeType = NODE\n    this.localName = localName\n    this.settings = settings\n    this.children = children\n    this.namespace = namespace\n    this.descendantsCount = descendantsCount\n  }\n  map(tagger) {\n    return new TaggerNode(tagger, this)\n  }\n  toInnerHTML(indent = \"\") {\n    const { children } = this\n    let html = \"\"\n    if (children.length > 0) {\n      const childIndent = `${indent}  `\n      for (const child of children) {\n        html += `\\n${child.toOuterHTML(indent, \"\")}`\n      }\n    }\n    return html\n  }\n  serializeSettings(key) {\n    let buffer = \"\"\n\n    if (key !== \"\") {\n      buffer += ` key=${key}`\n    }\n\n    const { settings } = this\n    for (const type in settings) {\n      const group = settings[type]\n      for (const name in group) {\n        const value = group[name]\n        switch (type) {\n          case SETTING_ATTRIBUTE: {\n            buffer += ` ${name}=\"${value}\"`\n            break\n          }\n          case SETTING_EVENT: {\n            buffer += ` on${name}`\n            break\n          }\n          case SETTING_PROPERTY: {\n            buffer += ` ${name}=${value}`\n          }\n        }\n      }\n    }\n\n    if (this.namespace) {\n      buffer += ` xmlns=\"${namespace}\"`\n    }\n\n    return buffer\n  }\n  toOuterHTML(indent = \"\", key = \"\") {\n    const { localName } = this\n    const open = `<${localName}${this.serializeSettings(key)}>`\n    const close = `</${localName}>`\n    const innerHTML = this.toInnerHTML(`${indent}  `)\n\n    if (innerHTML === \"\") {\n      return `${indent}${open}${close}`\n    } else {\n      return `${indent}${open}${innerHTML}\\n${indent}${close}`\n    }\n  }\n  get innerHTML() {\n    return this.toInnerHTML()\n  }\n  get outerHTML() {\n    return this.toOuterHTML()\n  }\n}\n\nexport const nodeNS = (\n  namespace,\n  localName,\n  factList = noFacts,\n  kidList = noKids\n) => {\n  for (\n    var kids = [], descendantsCount = 0, index = 0;\n    kidList.length > index;\n    index++\n  ) {\n    var kid = kidList[index]\n    descendantsCount += kid.descendantsCount || 0\n    kids.push(kid)\n  }\n  descendantsCount += kids.length\n\n  return new Node(\n    localName,\n    organizeFacts(factList),\n    kids,\n    namespace,\n    descendantsCount\n  )\n}\n\nexport var node = nodeNS.bind(null, null)\n\n// KEYED NODE\n\nclass KeyedNode {\n  constructor(localName, facts, kids, namespace, descendantsCount) {\n    this.nodeType = KEYED_NODE\n    this.localName = localName\n    this.settings = facts\n    this.children = kids\n    this.namespace = namespace\n    this.descendantsCount = descendantsCount\n  }\n  map(tagger) {\n    return new TaggerNode(tagger, this)\n  }\n  serializeSettings(key = \"\") {\n    return Node.prototype.serializeSettings.call(this, key)\n  }\n  toOuterHTML(indent = \"\", key = \"\") {\n    return Node.prototype.toOuterHTML.call(this, indent, key)\n  }\n  toInnerHTML(indent = \"\") {\n    let html = \"\"\n    const { children } = this\n    if (children.length > 0) {\n      for (const [key, child] of children) {\n        html += `\\n${child.toOuterHTML(indent, key)}`\n      }\n    }\n    return html\n  }\n  get outerHTML() {\n    return this.toOuterHTML()\n  }\n  get innerHTML() {\n    return this.toInnerHTML()\n  }\n}\n\nexport const keyedNodeNS = (namespace, localName, factList, kidList) => {\n  for (\n    var kids = [], descendantsCount = 0, index = 0;\n    kidList.length > index;\n    index++\n  ) {\n    var kid = kidList[index]\n    descendantsCount += kid[1].descendantsCount || 0\n    kids.push(kid)\n  }\n  descendantsCount += kids.length\n\n  return new KeyedNode(\n    localName,\n    organizeFacts(factList),\n    kids,\n    namespace,\n    descendantsCount\n  )\n}\n\nexport var keyedNode = keyedNodeNS.bind(null, null)\n\n// CUSTOM\n\nclass CustomNode {\n  constructor(facts, model, render, diff) {\n    this.nodeType = CUSTOM_NODE\n    this.settings = facts\n    this.model = model\n    this.render = render\n    this.diff = diff\n  }\n  map(tagger) {\n    return new TaggerNode(tagger, this)\n  }\n  serializeSettings(key = \"\") {\n    return Node.prototype.serializeSettings.call(this, key)\n  }\n  toOuterHTML(indent = \"\", key = \"\") {\n    const settings = key === \"\" ? ` key=${key}` : \"\"\n    return `${indent}<custom-element${settings}><custom-element>`\n  }\n  toInnerHTML(indent = \"\") {\n    return \"\"\n  }\n  get outerHTML() {\n    return this.toOuterHTML()\n  }\n  get innerHTML() {\n    return this.toInnerHTML()\n  }\n}\n\nexport const custom = (factList, model, render, diff) =>\n  new CustomNode(organizeFacts(factList), model, render, diff)\n\nclass Doc {\n  constructor(title, body) {\n    this.title = title\n    this.body = body\n  }\n  map(tagger) {\n    return new Doc(this.title, this.body.map(tagger))\n  }\n  toOuterHTML(indent = \"\", key = \"\") {\n    const innerHTML = this.toInnerHTML(`${indent}  `)\n    return `${indent}<html>\\n${innerHTML}\\n${indent}<\\html>`\n  }\n  toInnerHTML(indent = \"\") {\n    const head = `<head><title>${this.title}</title></head>`\n    const body = this.body.toOuterHTML(indent)\n    if (body === \"\") {\n      return `${indent}${head}`\n    } else {\n      return `${indent}${head}\\n${body}`\n    }\n  }\n  get outerHTML() {\n    return this.toOuterHTML()\n  }\n  get innerHTML() {\n    return this.toInnerHTML()\n  }\n}\n\nexport const doc = (title, body) => new Doc(title, body)\n\n// MAP\n\nclass TaggerNode {\n  constructor(tagger, node) {\n    this.nodeType = TAGGED_NODE\n    this.tagger = tagger\n    this.node = node\n    this.descendantsCount = 1 + (node.descendantsCount || 0)\n  }\n  map(tagger) {\n    return new TaggerNode(tagger, this)\n  }\n  toOuterHTML(indent = \"\", key = \"\") {\n    return this.node.toOuterHTML(indent, key)\n  }\n  toInnerHTML(indent = \"\") {\n    return this.node.toInnerHTML(indent)\n  }\n  get outerHTML() {\n    return this.toOuterHTML()\n  }\n  get innerHTML() {\n    return this.toInnerHTML()\n  }\n}\n\nexport const map = (tagger, node) => new TaggerNode(tagger, node)\n\n// LAZY\n\nclass Thunk {\n  constructor(refs, thunk) {\n    this.nodeType = THUNK_NODE\n    this.refs = refs\n    this.force = thunk\n    this.node = undefined\n  }\n  map(tagger) {\n    return new TaggerNode(tagger, this)\n  }\n  toNode() {\n    const { node } = this\n    if (node) {\n      return node\n    } else {\n      const node = this.force()\n      this.node = node\n      return node\n    }\n  }\n  toOuterHTML(indent = \"\", key = \"\") {\n    return this.toNode().toOuterHTML(indent, key)\n  }\n  toInnerHTML(indent = \"\") {\n    const node = (vNode.node = vNode.force())\n    return this.toNode().toInnerHTML(indent)\n  }\n  get outerHTML() {\n    return this.toOuterHTML()\n  }\n  get innerHTML() {\n    return this.toInnerHTML()\n  }\n}\n\nconst thunk = (refs, thunk) => new Thunk(refs, thunk)\n\nexport var lazy = function(func, a) {\n  return thunk([func, a], function() {\n    return func(a)\n  })\n}\n\nexport var lazy2 = function(func, a, b) {\n  return thunk([func, a, b], function() {\n    return func(a, b)\n  })\n}\n\nexport var lazy3 = function(func, a, b, c) {\n  return thunk([func, a, b, c], function() {\n    return func(a, b, c)\n  })\n}\n\nexport var lazy4 = function(func, a, b, c, d) {\n  return thunk([func, a, b, c, d], function() {\n    return func(a, b, c, d)\n  })\n}\n\nexport var lazy5 = function(func, a, b, c, d, e) {\n  return thunk([func, a, b, c, d, e], function() {\n    return func(a, b, c, d, e)\n  })\n}\n\nexport var lazy6 = function(func, a, b, c, d, e, f) {\n  return thunk([func, a, b, c, d, e, f], function() {\n    return func(a, b, c, d, e, f)\n  })\n}\n\nexport var lazy7 = function(func, a, b, c, d, e, f, g) {\n  return thunk([func, a, b, c, d, e, f, g], function() {\n    return func(a, b, c, d, e, f, g)\n  })\n}\n\nexport var lazy8 = function(func, a, b, c, d, e, f, g, h) {\n  return thunk([func, a, b, c, d, e, f, g, h], function() {\n    return func(a, b, c, d, e, f, g, h)\n  })\n}\n\n// FACTS\n\nconst notaggers = Object.freeze([])\nexport const on = function(key, handler) {\n  return new EventHandler(key, handler, Normal, notaggers)\n}\n\nclass VirtualDOMStyle {\n  constructor(key, value) {\n    this.nodeType = SETTING_STYLE\n    this.key = key\n    this.value = value\n  }\n  map(tag) {\n    return this\n  }\n}\n\nexport var style = function(key, value) {\n  return new VirtualDOMStyle(key, value)\n}\n\nclass VirtualDOMProperty {\n  constructor(key, value) {\n    this.nodeType = SETTING_PROPERTY\n    this.key = key\n    this.value = value\n  }\n  map(tag) {\n    return this\n  }\n}\n\nexport var property = function(key, value) {\n  return new VirtualDOMProperty(key, value)\n}\n\nclass VirtualDOMAttribute {\n  constructor(key, value) {\n    this.nodeType = SETTING_ATTRIBUTE\n    this.key = key\n    this.value = value\n  }\n  map(tag) {\n    return this\n  }\n}\n\nexport const attribute = (key, value) => new VirtualDOMAttribute(key, value)\n\nclass VirtualDOMAttributeNS {\n  constructor(namespace, key, value) {\n    this.nodeType = SETTING_ATTRIBUTE_NS\n    this.key = key\n    this.value = { namespace: namespace, value: value }\n  }\n  map(tag) {\n    return this\n  }\n}\n\nexport const attributeNS = (namespace, key, value) =>\n  new VirtualDOMAttributeNS(namespace, key, value)\n\n// XSS ATTACK VECTOR CHECKS\n\nexport function noScript(localName) {\n  return localName == \"script\" ? \"p\" : localName\n}\n\nexport function noOnOrFormAction(key) {\n  return /^(on|formAction$)/i.test(key) ? \"data-\" + key : key\n}\n\nexport function noInnerHtmlOrFormAction(key) {\n  return key == \"innerHTML\" || key == \"formAction\" ? \"data-\" + key : key\n}\n\nexport function noJavaScriptUri__PROD(value) {\n  return /^javascript:/i.test(value.replace(/\\s/g, \"\")) ? \"\" : value\n}\n\nexport function noJavaScriptUri__DEBUG(value) {\n  return /^javascript:/i.test(value.replace(/\\s/g, \"\"))\n    ? 'javascript:alert(\"This is an XSS vector. Please use ports or web components instead.\")'\n    : value\n}\n\nexport function noJavaScriptOrHtmlUri__PROD(value) {\n  return /^\\s*(javascript:|data:text\\/html)/i.test(value) ? \"\" : value\n}\n\nexport function noJavaScriptOrHtmlUri__DEBUG(value) {\n  return /^\\s*(javascript:|data:text\\/html)/i.test(value)\n    ? 'javascript:alert(\"This is an XSS vector. Please use ports or web components instead.\")'\n    : value\n}\n\n// MAP FACTS\n\nclass EventHandler {\n  constructor(type, decoder, eventPhase, taggers) {\n    this.nodeType = SETTING_EVENT\n    this.type = type\n    this.decoder = decoder\n    this.eventPhase = eventPhase\n    this.taggers = taggers\n  }\n  map(tag) {\n    const { type, decoder, eventPhase, taggers } = this\n    return new EventHandler(type, decoder, eventPhase, [tag, ...taggers])\n  }\n  forwardEvent(event, eventTarget) {\n    const { eventPhase, taggers } = this\n    const result = this.decoder.decode(event)\n\n    if (result instanceof Error) {\n      return\n    }\n\n    const tag = this.eventPhase\n\n    // 0 = Normal\n    // 1 = MayStopPropagation\n    // 2 = MayPreventDefault\n    // 3 = Custom\n\n    const { stopPropagation, preventDefault } = result\n    if (stopPropagation) {\n      event.stopPropagation()\n    }\n\n    if (preventDefault) {\n      event.preventDefault()\n    }\n\n    let message = result.message\n    for (let tag of this.taggers) {\n      message = tag(message)\n    }\n\n    let currentTarget = eventTarget\n    while (currentTarget.tagger) {\n      const { tagger } = currentTarget\n      if (typeof tagger == \"function\") {\n        message = tagger(message)\n      } else {\n        for (let i = tagger.length; i--; ) {\n          message = tagger[i](message)\n        }\n      }\n\n      currentTarget = currentTarget.parent\n    }\n\n    if (stopPropagation) {\n      currentTarget.sync(message) // stopPropagation implies isSync\n    } else {\n      currentTarget.send(message)\n    }\n  }\n  equal(other) {\n    return (\n      this.type === other.type &&\n      this.eventPhase === other.eventPhase &&\n      this.decoder === other.decoder &&\n      pairwiseRefEqual(this.taggers, other.taggers)\n    )\n  }\n}\n\n// ORGANIZE FACTS\n\nfunction organizeFacts(factList) {\n  for (\n    var facts = {}, index = 0;\n    factList.length > index;\n    index++ // WHILE_CONS\n  ) {\n    var fact = factList[index]\n\n    var nodeType = fact.nodeType\n\n    switch (nodeType) {\n      case SETTING_PROPERTY: {\n        const { key, value } = fact\n        if (key === \"className\") {\n          addClass(facts, key, value)\n        } else {\n          facts[key] = value\n        }\n        break\n      }\n      case SETTING_STYLE: {\n        const { key, value } = fact\n        var subFacts = facts[nodeType] || (facts[nodeType] = {})\n        subFacts[key] = value\n        break\n      }\n      case SETTING_EVENT: {\n        const { type, handler } = fact\n        var subFacts = facts[nodeType] || (facts[nodeType] = {})\n        subFacts[type] = fact\n        break\n      }\n      case SETTING_ATTRIBUTE: {\n        const { key, value } = fact\n        var subFacts = facts[nodeType] || (facts[nodeType] = {})\n        if (key === \"class\") {\n          addClass(subFacts, key, value)\n        } else {\n          subFacts[key] = value\n        }\n        break\n      }\n      case SETTING_ATTRIBUTE_NS: {\n        const { key, value } = fact\n        var subFacts = facts[nodeType] || (facts[nodeType] = {})\n        if (key === \"class\") {\n          addClass(subFacts, key, value)\n        } else {\n          subFacts[key] = value\n        }\n        break\n      }\n    }\n  }\n\n  return facts\n}\n\nfunction addClass(object, key, newClass) {\n  var classes = object[key]\n  object[key] = classes ? classes + \" \" + newClass : newClass\n}\n\n// RENDER\n\nfunction render(doc, vNode, eventNode) {\n  var nodeType = vNode.nodeType\n\n  if (nodeType === THUNK_NODE) {\n    return render(doc, vNode.node || (vNode.node = vNode.force()), eventNode)\n  }\n\n  if (nodeType === TEXT) {\n    return doc.createTextNode(vNode.text)\n  }\n\n  if (nodeType === TAGGED_NODE) {\n    var subNode = vNode.node\n    var tagger = vNode.tagger\n\n    while (subNode.nodeType === TAGGED_NODE) {\n      typeof tagger !== \"object\"\n        ? (tagger = [tagger, subNode.tagger])\n        : tagger.push(subNode.tagger)\n\n      subNode = subNode.node\n    }\n\n    var subEventRoot = { tagger: tagger, parent: eventNode }\n    var domNode = render(doc, subNode, subEventRoot)\n    domNode.elm_event_node_ref = subEventRoot\n    return domNode\n  }\n\n  if (nodeType === CUSTOM_NODE) {\n    var domNode = vNode.render(doc, vNode.model)\n    applyFacts(domNode, eventNode, vNode.settings)\n    return domNode\n  }\n\n  if (nodeType === CUSTOM_ELEMENT) {\n    const { elementConstructor, localName, options } = vNode\n    const { customElements } = document.defaultView\n    const registration = customElements.get(localName)\n    if (registration) {\n      if (registration !== elementConstructor.registration) {\n        Object.setPrototypeOf(\n          registration.prototype,\n          elementConstructor.prototype\n        )\n        elementConstructor.registration = registration\n        registration.proto = elementConstructor.prototype\n      }\n    } else {\n      const registration = class extends vNode.elementConstructor {\n        constructor(...args) {\n          super(...args)\n        }\n        connectedCallback(...args) {\n          if (registration.proto.connectedCallback) {\n            super.connectedCallback(...args)\n          }\n        }\n        disconnectedCallback(...args) {\n          if (registration.proto.disconnectedCallback) {\n            super.disconnectedCallback(...args)\n          }\n        }\n        adoptedCallback(...args) {\n          if (registration.proto.adoptedCallback) {\n            super.adoptedCallback(...args)\n          }\n        }\n        attributeChangedCallback(...args) {\n          if (registration.proto.attributeChangedCallback) {\n            super.attributeChangedCallback(...args)\n          }\n        }\n      }\n      registration.proto = vNode.elementConstructor.prototype\n      elementConstructor.registration = registration\n      customElements.define(localName, registration, options)\n    }\n  }\n\n  // at this point `nodeType` must be NODE or KEYED_NODE\n\n  var domNode = vNode.namespace\n    ? doc.createElementNS(vNode.namespace, vNode.localName)\n    : doc.createElement(vNode.localName)\n\n  const { onnavigate } = doc.defaultView\n  if (onnavigate && vNode.localName == \"a\") {\n    domNode.addEventListener(\"click\", onnavigate)\n  }\n\n  applyFacts(domNode, eventNode, vNode.settings)\n\n  for (var kids = vNode.children, i = 0; i < kids.length; i++) {\n    appendChild(\n      domNode,\n      render(doc, nodeType === NODE ? kids[i] : kids[i][1], eventNode)\n    )\n  }\n\n  return domNode\n}\n\n// APPLY FACTS\n\nfunction applyFacts(domNode, eventNode, facts) {\n  for (var key in facts) {\n    var value = facts[key]\n\n    switch (key) {\n      case SETTING_STYLE: {\n        applyStyles(domNode, value)\n        break\n      }\n      case SETTING_EVENT: {\n        applyEvents(domNode, eventNode, value)\n        break\n      }\n      case SETTING_ATTRIBUTE: {\n        applyAttrs(domNode, value)\n        break\n      }\n      case SETTING_ATTRIBUTE_NS: {\n        applyAttrsNS(domNode, value)\n        break\n      }\n      default: {\n        switch (key) {\n          case \"value\": {\n            if (domNode.value !== value) {\n              domNode.value = value\n            }\n            break\n          }\n          case \"checked\":\n            break\n          case domNode[key]:\n            break\n          default: {\n            domNode[key] = value\n            break\n          }\n        }\n      }\n    }\n  }\n}\n\n// APPLY STYLES\n\nfunction applyStyles(domNode, styles) {\n  var domNodeStyle = domNode.style\n\n  for (var key in styles) {\n    domNodeStyle[key] = styles[key]\n  }\n}\n\n// APPLY ATTRS\n\nfunction applyAttrs(domNode, attrs) {\n  for (var key in attrs) {\n    var value = attrs[key]\n    value != null\n      ? domNode.setAttribute(key, value)\n      : domNode.removeAttribute(key)\n  }\n}\n\n// APPLY NAMESPACED ATTRS\n\nfunction applyAttrsNS(domNode, nsAttrs) {\n  for (var key in nsAttrs) {\n    var pair = nsAttrs[key]\n    var namespace = pair.namespace\n    var value = pair.value\n\n    value\n      ? domNode.setAttributeNS(namespace, key, value)\n      : domNode.removeAttributeNS(namespace, key)\n  }\n}\n\n// APPLY EVENTS\n\nclass EventRouter {\n  constructor() {\n    this.handlers = {}\n    this.handleEvent = this.handleEvent.bind(this)\n    this.target = null\n  }\n  handleEvent(event) {\n    this.handlers[event.type].forwardEvent(event, this.target)\n  }\n}\n\nfunction applyEvents(domNode, eventNode, events) {\n  const router =\n    domNode.eventRouter || (domNode.eventRouter = new EventRouter())\n  router.target = eventNode\n  const { handlers, handleEvent } = router\n\n  for (var key in events) {\n    const oldHandler = handlers[key]\n    const newHandler = events[key]\n\n    if (!newHandler) {\n      domNode.removeEventListener(key, handleEvent)\n      handlers[key] = null\n      continue\n    }\n\n    if (oldHandler) {\n      if (oldHandler.type === newHandler.type) {\n        handlers[key] = newHandler\n        continue\n      } else {\n        domNode.removeEventListener(key, handleEvent)\n      }\n    }\n\n    const { eventPhase } = newHandler\n    handlers[key] = newHandler\n    const passive = eventPhase == Normal || eventPhase == MayStopPropagation\n    domNode.addEventListener(key, handleEvent, passiveSupported && { passive })\n  }\n}\n\n// PASSIVE EVENTS\n\nvar passiveSupported\n\ntry {\n  window.addEventListener(\n    \"t\",\n    null,\n    Object.defineProperty({}, \"passive\", {\n      get: function() {\n        passiveSupported = true\n      }\n    })\n  )\n} catch (e) {}\n\n// EVENT HANDLERS\n\nconst Normal = 0\nconst MayStopPropagation = 1\nconst MayPreventDefault = 2\nconst Custom = 3\n\n// DIFF\n\n// TODO: Should we do patches like in iOS?\n//\n// type Patch\n//   = At Int Patch\n//   | Batch (List Patch)\n//   | Change ...\n//\n// How could it not be better?\n//\nexport function diff(x, y) {\n  var patches = []\n  diffHelp(x, y, patches, 0)\n  return patches\n}\n\nfunction pushPatch(patches, op, index, data) {\n  var patch = {\n    op: op,\n    index: index,\n    changes: data,\n    domNode: undefined,\n    eventNode: undefined\n  }\n  patches.push(patch)\n  return patch\n}\n\nfunction diffHelp(x, y, patches, index) {\n  if (x === y) {\n    return\n  }\n\n  var xType = x.nodeType\n  var yType = y.nodeType\n\n  // Bail if you run into different types of nodes. Implies that the\n  // structure has changed significantly and it's not worth a diff.\n  if (xType !== yType) {\n    if (xType === NODE && yType === KEYED_NODE) {\n      y = dekey(y)\n      yType = NODE\n    } else {\n      pushPatch(patches, OP_REDRAW, index, y)\n      return\n    }\n  }\n\n  // Now we know that both nodes are the same type.\n  switch (yType) {\n    case THUNK_NODE: {\n      var xRefs = x.refs\n      var yRefs = y.refs\n      var i = xRefs.length\n      var same = i === yRefs.length\n      while (same && i--) {\n        same = xRefs[i] === yRefs[i]\n      }\n      if (same) {\n        y.node = x.node\n        return\n      }\n      y.node = y.force()\n      var subPatches = []\n      diffHelp(x.node, y.node, subPatches, 0)\n      subPatches.length > 0 && pushPatch(patches, OP_THUNK, index, subPatches)\n      return\n    }\n    case TAGGED_NODE: {\n      // gather nested taggers\n      var xTaggers = x.tagger\n      var yTaggers = y.tagger\n      var nesting = false\n\n      var xSubNode = x.node\n      while (xSubNode.nodeType === TAGGED_NODE) {\n        nesting = true\n\n        typeof xTaggers !== \"object\"\n          ? (xTaggers = [xTaggers, xSubNode.tagger])\n          : xTaggers.push(xSubNode.tagger)\n\n        xSubNode = xSubNode.node\n      }\n\n      var ySubNode = y.node\n      while (ySubNode.nodeType === TAGGED_NODE) {\n        nesting = true\n\n        typeof yTaggers !== \"object\"\n          ? (yTaggers = [yTaggers, ySubNode.tagger])\n          : yTaggers.push(ySubNode.tagger)\n\n        ySubNode = ySubNode.node\n      }\n\n      // Just bail if different numbers of taggers. This implies the\n      // structure of the virtual DOM has changed.\n      if (nesting && xTaggers.length !== yTaggers.length) {\n        pushPatch(patches, OP_REDRAW, index, y)\n        return\n      }\n\n      // check if taggers are \"the same\"\n      if (\n        nesting ? !pairwiseRefEqual(xTaggers, yTaggers) : xTaggers !== yTaggers\n      ) {\n        pushPatch(patches, OP_TAGGER, index, yTaggers)\n      }\n\n      // diff everything below the taggers\n      diffHelp(xSubNode, ySubNode, patches, index + 1)\n      return\n    }\n    case TEXT: {\n      if (x.text !== y.text) {\n        pushPatch(patches, OP_TEXT, index, y.text)\n      }\n      return\n    }\n    case NODE: {\n      diffNodes(x, y, patches, index, diffKids)\n      return\n    }\n    case KEYED_NODE: {\n      diffNodes(x, y, patches, index, diffKeyedKids)\n      return\n    }\n    case CUSTOM_ELEMENT: {\n      if (x.elementConstructor !== y.elementConstructor) {\n        pushPatch(patches, OP_REDRAW, index, y)\n        return\n      } else {\n        diffNodes(x, y, patches, index, diffKids)\n        return\n      }\n    }\n\n    case CUSTOM_NODE:\n      if (x.render !== y.render) {\n        pushPatch(patches, OP_REDRAW, index, y)\n        return\n      }\n\n      var factsDiff = diffFacts(x.settings, y.settings)\n      factsDiff && pushPatch(patches, OP_FACTS, index, factsDiff)\n\n      var patch = y.diff(x.model, y.model)\n      patch && pushPatch(patches, OP_CUSTOM, index, patch)\n\n      return\n  }\n}\n\n// assumes the incoming arrays are the same length\nfunction pairwiseRefEqual(as, bs) {\n  for (var i = 0; i < as.length; i++) {\n    if (as[i] !== bs[i]) {\n      return false\n    }\n  }\n\n  return true\n}\n\nfunction diffNodes(x, y, patches, index, diffKids) {\n  // Bail if obvious indicators have changed. Implies more serious\n  // structural changes such that it's not worth it to diff.\n  if (x.localName !== y.localName || x.namespace !== y.namespace) {\n    pushPatch(patches, OP_REDRAW, index, y)\n    return\n  }\n\n  var factsDiff = diffFacts(x.settings, y.settings)\n  factsDiff && pushPatch(patches, OP_FACTS, index, factsDiff)\n\n  diffKids(x, y, patches, index)\n}\n\n// DIFF FACTS\n\n// TODO Instead of creating a new diff object, it's possible to just test if\n// there *is* a diff. During the actual patch, do the diff again and make the\n// modifications directly. This way, there's no new allocations. Worth it?\nfunction diffFacts(x, y, category) {\n  var diff\n\n  // look for changes and removals\n  for (var xKey in x) {\n    if (\n      xKey === SETTING_STYLE ||\n      xKey === SETTING_EVENT ||\n      xKey === SETTING_ATTRIBUTE ||\n      xKey === SETTING_ATTRIBUTE_NS\n    ) {\n      var subDiff = diffFacts(x[xKey], y[xKey] || {}, xKey)\n      if (subDiff) {\n        diff = diff || {}\n        diff[xKey] = subDiff\n      }\n      continue\n    }\n\n    // remove if not in the new facts\n    if (!(xKey in y)) {\n      diff = diff || {}\n      diff[xKey] = !category\n        ? typeof x[xKey] === \"string\"\n          ? \"\"\n          : null\n        : category === SETTING_STYLE\n        ? \"\"\n        : category === SETTING_EVENT || category === SETTING_ATTRIBUTE\n        ? undefined\n        : { namespace: x[xKey].namespace, value: undefined }\n\n      continue\n    }\n\n    var xValue = x[xKey]\n    var yValue = y[xKey]\n\n    // reference equal, so don't worry about it\n    if (\n      (xValue === yValue && xKey !== \"value\" && xKey !== \"checked\") ||\n      (category === SETTING_EVENT && xValue.equal(yValue))\n    ) {\n      continue\n    }\n\n    diff = diff || {}\n    diff[xKey] = yValue\n  }\n\n  // add new stuff\n  for (var yKey in y) {\n    if (!(yKey in x)) {\n      diff = diff || {}\n      diff[yKey] = y[yKey]\n    }\n  }\n\n  return diff\n}\n\n// DIFF KIDS\n\nfunction diffKids(xParent, yParent, patches, index) {\n  var xKids = xParent.children\n  var yKids = yParent.children\n\n  var xLen = xKids.length\n  var yLen = yKids.length\n\n  // FIGURE OUT IF THERE ARE INSERTS OR REMOVALS\n\n  if (xLen > yLen) {\n    pushPatch(patches, OP_REMOVE_LAST, index, {\n      offset: yLen,\n      diff: xLen - yLen\n    })\n  } else if (xLen < yLen) {\n    pushPatch(patches, OP_APPEND, index, {\n      offset: xLen,\n      children: yKids\n    })\n  }\n\n  // PAIRWISE DIFF EVERYTHING ELSE\n\n  for (var minLen = xLen < yLen ? xLen : yLen, i = 0; i < minLen; i++) {\n    var xKid = xKids[i]\n    diffHelp(xKid, yKids[i], patches, ++index)\n    index += xKid.descendantsCount || 0\n  }\n}\n\n// KEYED DIFF\n\nfunction diffKeyedKids(xParent, yParent, patches, rootIndex) {\n  var localPatches = []\n\n  var changes = {} // Dict String Entry\n  var inserts = [] // Array { index : Int, entry : Entry }\n  // type Entry = { tag : String, vnode : VNode, index : Int, data : _ }\n\n  var xKids = xParent.children\n  var yKids = yParent.children\n  var xLen = xKids.length\n  var yLen = yKids.length\n  var xIndex = 0\n  var yIndex = 0\n\n  var index = rootIndex\n\n  while (xIndex < xLen && yIndex < yLen) {\n    var x = xKids[xIndex]\n    var y = yKids[yIndex]\n\n    var [xKey, xNode] = x\n    var [yKey, yNode] = y\n\n    // check if keys match\n\n    if (xKey === yKey) {\n      index++\n      diffHelp(xNode, yNode, localPatches, index)\n      index += xNode.descendantsCount || 0\n\n      xIndex++\n      yIndex++\n      continue\n    }\n\n    // look ahead 1 to detect insertions and removals.\n\n    var xNext = xKids[xIndex + 1]\n    var yNext = yKids[yIndex + 1]\n\n    if (xNext) {\n      var xNextKey = xNext[0]\n      var xNextNode = xNext[1]\n      var oldMatch = yKey === xNextKey\n    }\n\n    if (yNext) {\n      var yNextKey = yNext[0]\n      var yNextNode = yNext[1]\n      var newMatch = xKey === yNextKey\n    }\n\n    // swap x and y\n    if (newMatch && oldMatch) {\n      index++\n      diffHelp(xNode, yNextNode, localPatches, index)\n      insertNode(changes, localPatches, xKey, yNode, yIndex, inserts)\n      index += xNode.descendantsCount || 0\n\n      index++\n      removeNode(changes, localPatches, xKey, xNextNode, index)\n      index += xNextNode.descendantsCount || 0\n\n      xIndex += 2\n      yIndex += 2\n      continue\n    }\n\n    // insert y\n    if (newMatch) {\n      index++\n      insertNode(changes, localPatches, yKey, yNode, yIndex, inserts)\n      diffHelp(xNode, yNextNode, localPatches, index)\n      index += xNode.descendantsCount || 0\n\n      xIndex += 1\n      yIndex += 2\n      continue\n    }\n\n    // remove x\n    if (oldMatch) {\n      index++\n      removeNode(changes, localPatches, xKey, xNode, index)\n      index += xNode.descendantsCount || 0\n\n      index++\n      diffHelp(xNextNode, yNode, localPatches, index)\n      index += xNextNode.descendantsCount || 0\n\n      xIndex += 2\n      yIndex += 1\n      continue\n    }\n\n    // remove x, insert y\n    if (xNext && xNextKey === yNextKey) {\n      index++\n      removeNode(changes, localPatches, xKey, xNode, index)\n      insertNode(changes, localPatches, yKey, yNode, yIndex, inserts)\n      index += xNode.descendantsCount || 0\n\n      index++\n      diffHelp(xNextNode, yNextNode, localPatches, index)\n      index += xNextNode.descendantsCount || 0\n\n      xIndex += 2\n      yIndex += 2\n      continue\n    }\n\n    break\n  }\n\n  // eat up any remaining nodes with removeNode and insertNode\n\n  while (xIndex < xLen) {\n    index++\n    var x = xKids[xIndex]\n    var xNode = x[1]\n    removeNode(changes, localPatches, x[0], xNode, index)\n    index += xNode.descendantsCount || 0\n    xIndex++\n  }\n\n  while (yIndex < yLen) {\n    var endInserts = endInserts || []\n    var y = yKids[yIndex]\n    insertNode(changes, localPatches, y[0], y[1], undefined, endInserts)\n    yIndex++\n  }\n\n  if (localPatches.length > 0 || inserts.length > 0 || endInserts) {\n    pushPatch(patches, OP_REORDER, rootIndex, {\n      subPatches: localPatches,\n      inserts: inserts,\n      endInserts: endInserts\n    })\n  }\n}\n\n// CHANGES FROM KEYED DIFF\n\nvar POSTFIX = \"_elmW6BL\"\n\nfunction insertNode(changes, localPatches, key, vnode, yIndex, inserts) {\n  var entry = changes[key]\n\n  // never seen this key before\n  if (!entry) {\n    entry = {\n      op: OP_INSERT,\n      vnode: vnode,\n      index: yIndex,\n      changes: undefined\n    }\n\n    inserts.push({ index: yIndex, entry: entry })\n    changes[key] = entry\n\n    return\n  }\n\n  // this key was removed earlier, a match!\n  if (entry.op === OP_DELETE) {\n    inserts.push({ index: yIndex, entry: entry })\n\n    entry.op = OP_MOVE\n    var subPatches = []\n    diffHelp(entry.vnode, vnode, subPatches, entry.index)\n    entry.index = yIndex\n    entry.changes.changes = {\n      subPatches: subPatches,\n      entry: entry\n    }\n\n    return\n  }\n\n  // this key has already been inserted or moved, a duplicate!\n  insertNode(changes, localPatches, key + POSTFIX, vnode, yIndex, inserts)\n}\n\nfunction removeNode(changes, localPatches, key, vnode, index) {\n  var entry = changes[key]\n\n  // never seen this key before\n  if (!entry) {\n    var patch = pushPatch(localPatches, OP_REMOVE, index, undefined)\n\n    changes[key] = {\n      op: OP_DELETE,\n      vnode: vnode,\n      index: index,\n      changes: patch\n    }\n\n    return\n  }\n\n  // this key was inserted earlier, a match!\n  if (entry.op === OP_INSERT) {\n    entry.op = OP_MOVE\n    var subPatches = []\n    diffHelp(vnode, entry.vnode, subPatches, index)\n\n    pushPatch(localPatches, OP_REMOVE, index, {\n      subPatches: subPatches,\n      entry: entry\n    })\n\n    return\n  }\n\n  // this key has already been removed or moved, a duplicate!\n  removeNode(changes, localPatches, key + POSTFIX, vnode, index)\n}\n\n// ADD DOM NODES\n//\n// Each DOM node has an \"index\" assigned in order of traversal. It is important\n// to minimize our crawl over the actual DOM, so these indexes (along with the\n// descendantsCount of virtual nodes) let us skip touching entire subtrees of\n// the DOM if we know there are no patches there.\n\nfunction addDomNodes(domNode, vNode, patches, eventNode) {\n  addDomNodesHelp(\n    domNode,\n    vNode,\n    patches,\n    0,\n    0,\n    vNode.descendantsCount,\n    eventNode\n  )\n}\n\n// assumes `patches` is non-empty and indexes increase monotonically.\nfunction addDomNodesHelp(domNode, vNode, patches, i, low, high, eventNode) {\n  var patch = patches[i]\n  var index = patch.index\n\n  while (index === low) {\n    var patchType = patch.op\n\n    if (patchType === OP_THUNK) {\n      addDomNodes(domNode, vNode.node, patch.changes, eventNode)\n    } else if (patchType === OP_REORDER) {\n      patch.domNode = domNode\n      patch.eventNode = eventNode\n\n      var subPatches = patch.changes.subPatches\n      if (subPatches.length > 0) {\n        addDomNodesHelp(domNode, vNode, subPatches, 0, low, high, eventNode)\n      }\n    } else if (patchType === OP_REMOVE) {\n      patch.domNode = domNode\n      patch.eventNode = eventNode\n\n      var data = patch.changes\n      if (data) {\n        data.entry.changes = domNode\n        var subPatches = data.subPatches\n        if (subPatches.length > 0) {\n          addDomNodesHelp(domNode, vNode, subPatches, 0, low, high, eventNode)\n        }\n      }\n    } else {\n      patch.domNode = domNode\n      patch.eventNode = eventNode\n    }\n\n    i++\n\n    if (!(patch = patches[i]) || (index = patch.index) > high) {\n      return i\n    }\n  }\n\n  var nodeType = vNode.nodeType\n\n  if (nodeType === TAGGED_NODE) {\n    var subNode = vNode.node\n\n    while (subNode.nodeType === TAGGED_NODE) {\n      subNode = subNode.node\n    }\n\n    return addDomNodesHelp(\n      domNode,\n      subNode,\n      patches,\n      i,\n      low + 1,\n      high,\n      domNode.elm_event_node_ref\n    )\n  }\n\n  // tag must be NODE or KEYED_NODE at this point\n\n  var vKids = vNode.children\n  var childNodes = domNode.childNodes\n  for (var j = 0; j < vKids.length; j++) {\n    low++\n    var vKid = nodeType === NODE ? vKids[j] : vKids[j][1]\n    var nextLow = low + (vKid.descendantsCount || 0)\n    if (low <= index && index <= nextLow) {\n      i = addDomNodesHelp(\n        childNodes[j],\n        vKid,\n        patches,\n        i,\n        low,\n        nextLow,\n        eventNode\n      )\n      if (!(patch = patches[i]) || (index = patch.index) > high) {\n        return i\n      }\n    }\n    low = nextLow\n  }\n  return i\n}\n\n// APPLY PATCHES\n\nexport const patch = (rootDomNode, oldVirtualNode, patches, eventNode) => {\n  if (patches.length === 0) {\n    return rootDomNode\n  }\n\n  addDomNodes(rootDomNode, oldVirtualNode, patches, eventNode)\n  return applyPatchesHelp(rootDomNode, patches)\n}\n\nfunction applyPatchesHelp(rootDomNode, patches) {\n  for (var i = 0; i < patches.length; i++) {\n    var patch = patches[i]\n    var localDomNode = patch.domNode\n    var newNode = applyPatch(localDomNode, patch)\n    if (localDomNode === rootDomNode) {\n      rootDomNode = newNode\n    }\n  }\n  return rootDomNode\n}\n\nfunction applyPatch(domNode, patch) {\n  const doc = domNode.ownerDocument\n  switch (patch.op) {\n    case OP_REDRAW: {\n      return applyPatchRedraw(domNode, patch.changes, patch.eventNode)\n    }\n    case OP_FACTS: {\n      applyFacts(domNode, patch.eventNode, patch.changes)\n      return domNode\n    }\n    case OP_TEXT: {\n      domNode.replaceData(0, domNode.length, patch.changes)\n      return domNode\n    }\n    case OP_THUNK: {\n      return applyPatchesHelp(domNode, patch.changes)\n    }\n    case OP_TAGGER: {\n      if (domNode.elm_event_node_ref) {\n        domNode.elm_event_node_ref.tagger = patch.changes\n      } else {\n        domNode.elm_event_node_ref = {\n          tagger: patch.changes,\n          parent: patch.eventNode\n        }\n      }\n      return domNode\n    }\n    case OP_REMOVE_LAST: {\n      var data = patch.changes\n      for (var i = 0; i < data.diff; i++) {\n        domNode.removeChild(domNode.childNodes[data.offset])\n      }\n      return domNode\n    }\n    case OP_APPEND: {\n      var data = patch.changes\n      var kids = data.children\n      var i = data.offset\n      var theEnd = domNode.childNodes[i]\n      for (; i < kids.length; i++) {\n        domNode.insertBefore(render(doc, kids[i], patch.eventNode), theEnd)\n      }\n      return domNode\n    }\n    case OP_REMOVE: {\n      var data = patch.changes\n      if (!data) {\n        domNode.parentNode.removeChild(domNode)\n        return domNode\n      }\n      var entry = data.entry\n      if (typeof entry.index !== \"undefined\") {\n        domNode.parentNode.removeChild(domNode)\n      }\n      entry.changes = applyPatchesHelp(domNode, data.subPatches)\n      return domNode\n    }\n    case OP_REORDER: {\n      return applyPatchReorder(domNode, patch)\n    }\n    case OP_CUSTOM: {\n      return patch.changes(domNode)\n    }\n    default: {\n      throw TypeError(\"Unknown operation\")\n    }\n  }\n}\n\nfunction applyPatchRedraw(domNode, vNode, eventNode) {\n  const doc = domNode.ownerDocument\n  var parentNode = domNode.parentNode\n  var newNode = render(doc, vNode, eventNode)\n\n  if (!newNode.elm_event_node_ref) {\n    newNode.elm_event_node_ref = domNode.elm_event_node_ref\n  }\n\n  if (parentNode && newNode !== domNode) {\n    parentNode.replaceChild(newNode, domNode)\n  }\n  return newNode\n}\n\nfunction applyPatchReorder(domNode, patch) {\n  const doc = domNode.ownerDocument\n  var data = patch.changes\n\n  // remove end inserts\n  var frag = applyPatchReorderEndInsertsHelp(doc, data.endInserts, patch)\n\n  // removals\n  domNode = applyPatchesHelp(domNode, data.subPatches)\n\n  // inserts\n  var inserts = data.inserts\n  for (var i = 0; i < inserts.length; i++) {\n    var insert = inserts[i]\n    var entry = insert.entry\n    var node =\n      entry.op === OP_MOVE\n        ? entry.changes\n        : render(doc, entry.vnode, patch.eventNode)\n    domNode.insertBefore(node, domNode.childNodes[insert.index])\n  }\n\n  // add end inserts\n  if (frag) {\n    appendChild(domNode, frag)\n  }\n\n  return domNode\n}\n\nfunction applyPatchReorderEndInsertsHelp(doc, endInserts, patch) {\n  if (!endInserts) {\n    return\n  }\n\n  var frag = doc.createDocumentFragment()\n  for (var i = 0; i < endInserts.length; i++) {\n    var insert = endInserts[i]\n    var entry = insert.entry\n    appendChild(\n      frag,\n      entry.op === OP_MOVE\n        ? entry.changes\n        : render(doc, entry.vnode, patch.eventNode)\n    )\n  }\n  return frag\n}\n\nexport function virtualize(root) {\n  // TEXT NODES\n\n  if (root.nodeType === 3) {\n    return text(root.textContent)\n  }\n\n  // WEIRD NODES\n\n  if (root.nodeType !== 1) {\n    return text(\"\")\n  }\n\n  // ELEMENT NODES\n\n  var factList = []\n  var attrs = root.attributes\n  for (var i = attrs.length; i--; ) {\n    var attr = attrs[i]\n    var name = attr.name\n    var value = attr.value\n\n    switch (name) {\n      case \"style\":\n        break\n      default:\n        factList.push(attribute(name, value))\n    }\n  }\n\n  const rules = root.style\n  for (var i = rules.length; i--; ) {\n    var name = rules[i]\n    var value = rules[name]\n    factList.push(style(name, value))\n  }\n\n  var localName = root.localName\n  var kidList = []\n  var kids = root.childNodes\n\n  for (var i = kids.length; i--; ) {\n    kidList.unshift(virtualize(kids[i]))\n  }\n  return node(localName, factList, kidList)\n}\n\nfunction dekey(keyedNode) {\n  var keyedKids = keyedNode.children\n  var len = keyedKids.length\n  var kids = new Array(len)\n  for (var i = 0; i < len; i++) {\n    kids[i] = keyedKids[i][1]\n  }\n\n  return {\n    nodeType: NODE,\n    localName: keyedNode.localName,\n    settings: keyedNode.settings,\n    children: kids,\n    namespace: keyedNode.namespace,\n    descendantsCount: keyedNode.descendantsCount\n  }\n}\n"
  },
  {
    "path": "src/Widget.js",
    "content": "import { diff, patch, virtualize } from \"./VirtualDOM.js\"\n\n/**\n * @typedef {import('./Task').ThreadID} ThreadID\n * @typedef {import('./Task').Thread} Thread\n */\n\n/**\n * @template T\n * @typedef {import('./Task').Main<T>} Main\n */\n\n/**\n * @template T\n * @typedef {import('./Task').Sync<T>} Sync\n */\n\n/**\n * @template T\n * @implements {Main<T>}\n */\nexport class MainThread {\n  /**\n   * @param {import('./Task').Sync<T>} root\n   */\n  constructor(root) {\n    this.root = root\n    /**\n     * @private\n     * @type {Record<string, Thread>}\n     */\n    this.threads\n    /**\n     * @private\n     * @type {number}\n     */\n    this.threadID\n  }\n\n  /**\n   * Sends a message to this program\n   *\n   * @param {T} message\n   */\n  async send(message) {\n    await 0\n    this.root.sync(message)\n  }\n\n  /**\n   * @param {T} message\n   */\n  sync(message) {\n    this.root.sync(message)\n  }\n\n  /**\n   * @param {Thread} thread\n   * @returns {ThreadID}\n   */\n  link(thread) {\n    if (this.threadID == null) {\n      this.threadID = 0\n      this.threads = {}\n    }\n\n    const id = `@${++this.threadID}`\n    this.threads[id] = thread\n    // @ts-expect-error - string isn't ThreadID\n    return id\n  }\n\n  /**\n   * @param {Thread} thread\n   */\n  unlink(thread) {\n    const { threads } = this\n    if (threads) {\n      for (const id in threads) {\n        if (thread === threads[id]) {\n          delete threads[id]\n          break\n        }\n      }\n    }\n  }\n\n  /**\n   * @param {ThreadID} threadID\n   */\n  linked(threadID) {\n    const { threads } = this\n    if (threads) {\n      return threads[threadID]\n    }\n    return undefined\n  }\n}\n\n/**\n * @template Message, State\n * @typedef {import('./Task').Transaction<Message, State>} Transaction\n */\n\n/**\n * @template T, State, View, Target\n */\nexport class Widget {\n  constructor() {\n    /** @type {MainThread<T>} */\n    this.thread\n    /** @type {State} */\n    this.state\n    /** @type {(message:T, state:State) => Transaction<T, State>} */\n    this.update\n    /** @type {(state:State) => View} */\n    this.view\n    /** @type {Target} */\n    this.root\n    /** @type {View} */\n    this.node\n  }\n  get version() {\n    const stack = new Error().stack || \"\"\n    const start = stack.indexOf(\"+\")\n    const end = stack.indexOf(\"/\", start)\n    return stack.slice(start, end)\n  }\n\n  /**\n   * @template T\n   * @param {Sync<T>} self\n   * @returns {MainThread<T>}\n   */\n  static fork(self /*: Sync<a> */) /*: MainThread<a> */ {\n    return new MainThread(self)\n  }\n\n  /**\n   *\n   * @param {T} message\n   */\n  sync(message) {\n    this.transact(this.update(message, this.state))\n  }\n\n  /**\n   * @param {Transaction<T, State>} transaction\n   */\n  transact([state, fx] /*: Transaction<a, model> */) {\n    this.state = state\n    this.render(state)\n    fx.perform(this.thread)\n  }\n\n  /**\n   * @param {State} _state\n   */\n  render(_state) {}\n\n  /**\n   * @param {Target} _root\n   * @returns {View}\n   */\n  mount(_root) {\n    return this.node\n  }\n  toJSON() {\n    return this.state\n  }\n}\n\n/**\n * @template T\n * @typedef {import('./VirtualDOM').Node<T>} Node\n */\n\n/**\n * @template T, State\n * @extends {Widget<T, State, Node<T>, Element>}\n */\nclass ElementWidget extends Widget {\n  /**\n   * @param {Element} root\n   * @returns {Node<T>}\n   */\n  mount(root) {\n    return virtualize(root)\n  }\n\n  /**\n   * @param {State} state\n   */\n  render(state) {\n    const newNode = this.view(state)\n    const renderedNode = this.node\n    const delta = diff(renderedNode, newNode)\n    patch(this.root, renderedNode, delta, this.thread)\n    this.node = newNode\n  }\n}\n\n/**\n * @template Message, State, View, Options\n * @typedef {import('./Program').Program<Message, State, View, Options>} Program\n */\n/**\n * @template Message, State, Options\n * @param {Program<Message, State, Node<Message>, Options>} program\n * @param {Options} options\n * @param {Element} root\n * @returns {Widget<Message, State, Node<Message>, Element>}\n */\nexport const spawn = ({ init, update, view }, options, root) => {\n  const self = new ElementWidget()\n  self.thread = Widget.fork(self)\n  self.update = update\n  self.view = view\n  self.root = root\n  self.node = self.mount(root)\n  self.transact(init(options))\n  return self\n}\n"
  },
  {
    "path": "src/lib.js",
    "content": "import * as DOM from \"./VirtualDOM.js\"\nimport * as Element from \"./Element.js\"\nimport * as Attribute from \"./Attribute.js\"\n\nimport * as Widget from \"./Widget.js\"\nimport * as Document from \"./Document.js\"\nimport * as Application from \"./Application.js\"\n\nimport * as Effect from \"./Effect.js\"\nimport { identity, unreachable, always, nothing } from \"./Basics.js\"\n\nexport {\n  // DOM\n  DOM,\n  Element,\n  Attribute,\n  // Spawnining VirtualDOM\n  Widget,\n  Document,\n  Application,\n  // Effect System\n  Effect,\n  // Utilities\n  identity,\n  unreachable,\n  always,\n  nothing\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    /* Visit https://aka.ms/tsconfig.json to read more about this file */\n\n    /* Projects */\n    \"incremental\": true,                              /* Enable incremental compilation */\n    \"composite\": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */\n    // \"tsBuildInfoFile\": \"./dist\",                          /* Specify the folder for .tsbuildinfo incremental compilation files. */\n    // \"disableSourceOfProjectReferenceRedirect\": true,  /* Disable preferring source files instead of declaration files when referencing composite projects */\n    // \"disableSolutionSearching\": true,                 /* Opt a project out of multi-project reference checking when editing. */\n    // \"disableReferencedProjectLoad\": true,             /* Reduce the number of projects loaded automatically by TypeScript. */\n\n    /* Language and Environment */\n    \"target\": \"ES2020\",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */\n    // \"lib\": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */\n    // \"jsx\": \"preserve\",                                /* Specify what JSX code is generated. */\n    // \"experimentalDecorators\": true,                   /* Enable experimental support for TC39 stage 2 draft decorators. */\n    // \"emitDecoratorMetadata\": true,                    /* Emit design-type metadata for decorated declarations in source files. */\n    // \"jsxFactory\": \"\",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */\n    // \"jsxFragmentFactory\": \"\",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */\n    // \"jsxImportSource\": \"\",                            /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */\n    // \"reactNamespace\": \"\",                             /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */\n    // \"noLib\": true,                                    /* Disable including any library files, including the default lib.d.ts. */\n    // \"useDefineForClassFields\": true,                  /* Emit ECMAScript-standard-compliant class fields. */\n\n    /* Modules */\n    \"module\": \"ES2020\",                                /* Specify what module code is generated. */\n    // \"rootDir\": \"./\",                                  /* Specify the root folder within your source files. */\n    \"moduleResolution\": \"node\",                       /* Specify how TypeScript looks up a file from a given module specifier. */\n    \"baseUrl\": \"./\",                                  /* Specify the base directory to resolve non-relative module names. */\n    // \"paths\": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */\n    // \"rootDirs\": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */\n    // \"typeRoots\": [],                                  /* Specify multiple folders that act like `./node_modules/@types`. */\n    // \"types\": [],                                      /* Specify type package names to be included without being referenced in a source file. */\n    // \"allowUmdGlobalAccess\": true,                     /* Allow accessing UMD globals from modules. */\n    // \"resolveJsonModule\": true,                        /* Enable importing .json files */\n    // \"noResolve\": true,                                /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */\n\n    /* JavaScript Support */\n    \"allowJs\": true,                                  /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */\n    \"checkJs\": true,                                  /* Enable error reporting in type-checked JavaScript files. */\n    // \"maxNodeModuleJsDepth\": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */\n\n    /* Emit */\n    // \"declaration\": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */\n    \"declarationMap\": true,                           /* Create sourcemaps for d.ts files. */\n    \"emitDeclarationOnly\": true,                      /* Only output d.ts files and not JavaScript files. */\n    // \"sourceMap\": true,                                /* Create source map files for emitted JavaScript files. */\n    // \"outFile\": \"./\",                                  /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */\n    \"outDir\": \"./dist/\",                                   /* Specify an output folder for all emitted files. */\n    // \"removeComments\": true,                           /* Disable emitting comments. */\n    // \"noEmit\": true,                                   /* Disable emitting files from a compilation. */\n    // \"importHelpers\": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */\n    // \"importsNotUsedAsValues\": \"remove\",               /* Specify emit/checking behavior for imports that are only used for types */\n    // \"downlevelIteration\": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */\n    // \"sourceRoot\": \"\",                                 /* Specify the root path for debuggers to find the reference source code. */\n    // \"mapRoot\": \"\",                                    /* Specify the location where debugger should locate map files instead of generated locations. */\n    // \"inlineSourceMap\": true,                          /* Include sourcemap files inside the emitted JavaScript. */\n    // \"inlineSources\": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */\n    // \"emitBOM\": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */\n    // \"newLine\": \"crlf\",                                /* Set the newline character for emitting files. */\n    // \"stripInternal\": true,                            /* Disable emitting declarations that have `@internal` in their JSDoc comments. */\n    // \"noEmitHelpers\": true,                            /* Disable generating custom helper functions like `__extends` in compiled output. */\n    // \"noEmitOnError\": true,                            /* Disable emitting files if any type checking errors are reported. */\n    // \"preserveConstEnums\": true,                       /* Disable erasing `const enum` declarations in generated code. */\n    // \"declarationDir\": \"./\",                           /* Specify the output directory for generated declaration files. */\n    // \"preserveValueImports\": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */\n\n    /* Interop Constraints */\n    // \"isolatedModules\": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */\n    // \"allowSyntheticDefaultImports\": true,             /* Allow 'import x from y' when a module doesn't have a default export. */\n    \"esModuleInterop\": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */\n    // \"preserveSymlinks\": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */\n    \"forceConsistentCasingInFileNames\": true,            /* Ensure that casing is correct in imports. */\n\n    /* Type Checking */\n    \"strict\": true,                                      /* Enable all strict type-checking options. */\n    // \"noImplicitAny\": true,                            /* Enable error reporting for expressions and declarations with an implied `any` type.. */\n    // \"strictNullChecks\": true,                         /* When type checking, take into account `null` and `undefined`. */\n    // \"strictFunctionTypes\": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */\n    // \"strictBindCallApply\": true,                      /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */\n    // \"strictPropertyInitialization\": true,             /* Check for class properties that are declared but not set in the constructor. */\n    // \"noImplicitThis\": true,                           /* Enable error reporting when `this` is given the type `any`. */\n    // \"useUnknownInCatchVariables\": true,               /* Type catch clause variables as 'unknown' instead of 'any'. */\n    // \"alwaysStrict\": true,                             /* Ensure 'use strict' is always emitted. */\n    // \"noUnusedLocals\": true,                           /* Enable error reporting when a local variables aren't read. */\n    // \"noUnusedParameters\": true,                       /* Raise an error when a function parameter isn't read */\n    // \"exactOptionalPropertyTypes\": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */\n    // \"noImplicitReturns\": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */\n    // \"noFallthroughCasesInSwitch\": true,               /* Enable error reporting for fallthrough cases in switch statements. */\n    // \"noUncheckedIndexedAccess\": true,                 /* Include 'undefined' in index signature results */\n    // \"noImplicitOverride\": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */\n    // \"noPropertyAccessFromIndexSignature\": true,       /* Enforces using indexed accessors for keys declared using an indexed type */\n    // \"allowUnusedLabels\": true,                        /* Disable error reporting for unused labels. */\n    // \"allowUnreachableCode\": true,                     /* Disable error reporting for unreachable code. */\n\n    /* Completeness */\n    // \"skipDefaultLibCheck\": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */\n    \"skipLibCheck\": true                                 /* Skip type checking all .d.ts files. */\n  },\n  \"include\": [\n    \"src\",\n    \"test\"\n  ]\n}\n"
  }
]