{"_id":"@dblechoc/open-wc-scoped-elements","_rev":"2-1ed174244ddd9952a03ebf727778c127","name":"@dblechoc/open-wc-scoped-elements","dist-tags":{"latest":"1.3.5"},"versions":{"1.3.4":{"name":"@dblechoc/open-wc-scoped-elements","version":"1.3.4","publishConfig":{"access":"public"},"description":"Allows to auto define custom elements scoping them","license":"MIT","repository":{"type":"git","url":"git+https://github.com/open-wc/open-wc.git","directory":"packages/scoped-elements"},"author":{"name":"open-wc"},"homepage":"https://github.com/open-wc/open-wc/tree/master/packages/scoped-elements","module":"index.js","scripts":{"demo-build:before-nesting":"rollup -c demo/before-nesting/rollup.config.js","demo-build:no-scope":"rollup -c demo/no-scope/rollup.config.js","demo-build:with-scope":"rollup -c demo/with-scope/rollup.config.js","site:build":"run-p demo-build:*","start:before-nesting":"es-dev-server -c demo/before-nesting/server.js","start:no-scope":"es-dev-server -c demo/no-scope/server.js","start:with-scope":"es-dev-server -c demo/with-scope/server.js","test":"cd ../../ && yarn test:browser --grep \"packages/scoped-elements/test/*.test.js\"","test:watch":"cd ../../ && yarn test:browser:watch --grep \"packages/scoped-elements/test/*.test.js\"","types:copy":"copyfiles \"./src/**/*.d.ts\" \"./*.d.ts\" types"},"keywords":["lit-html","lit-element","web components","utils","helpers"],"dependencies":{"@open-wc/dedupe-mixin":"^1.3.0","lit-html":"^1.0.0"},"types":"types/index.d.ts","sideEffects":false,"bugs":{"url":"https://github.com/open-wc/open-wc/issues"},"_id":"@dblechoc/open-wc-scoped-elements@1.3.4","_nodeVersion":"12.19.1","_npmVersion":"6.14.11","dist":{"integrity":"sha512-lXy2aX9A+3TH6VKjQ0dZBqUHEbDEBr18fxcR7V3z9O7ZOp/I43fmRbXEmS+aPp53lrIXmuXCiFI2aOkC1V+FJQ==","shasum":"406f8c3397aa29eaa2dc86a4494c25ac9e61bceb","tarball":"https://registry.npmjs.org/@dblechoc/open-wc-scoped-elements/-/open-wc-scoped-elements-1.3.4.tgz","fileCount":31,"unpackedSize":86142,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgPcfiCRA9TVsSAnZWagAAvnUP/2q1AuUsKr3hgRABYKI0\nzWAMN8GTIYFnPYrg8qAa95ojU2CJgMv02RLEs73Avr5G56d58YUZ87edFj1w\nSMT3Arq0dmV5GnYGB9T33Fknv1km5QzDjpZxYvIjgDrfxeAH9PYEW+qvKmUG\nX3gsk71l58FBdic5W3xCMGuxgokVZOm5BD0ALvwFNhxO9KfAay7PHGi/Nt7C\nhI7cehMAI4C8jItFaweMm9oFxXE1qLOf/U0eawt2CSSP5q6UhSkGF5tutJ5E\nHVbXNxWwBZG/lrisryQZZ/wmQHpYKU6DGceyoxf4RZietaYpKr3WaPkd6qe5\nfAB1mDEzsD9qY90Kd346STDmYPA95py4YQrQhf1R2P18zr7H/KGRgIGeXkZW\nTDPYM09PliiPqlczvxOn8+jn1JjsKaRSbCW/odBmqbvq/zX3c+WNCwRTb7O7\n80/OSlIRpmVCR+RGzipmuYupFQ0oWNasZz/Y/AGAPGZQRh9Z0A34+HIqSeyv\ntZfkYyrMOR2MFdkTtklUBVfO06QJjZtBQtDb/nAPA1VHD28VhP7FY0SN7UAG\ntVb/Ufni2N2xLTXP0jR/NN//AU0VGxuHVbLSR5oGHkmoc06uWHSOxy7lvRpT\nfQefVehY5oFNJcm3INuRMdTymii59tV3zz055BBEwxEclf8/wzN4DHoEPj0u\nrPXw\r\n=Xxlc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCMAjM0yykN/y9NmU4ALsFkHgLEWu01fmAmTLnQvJXHCgIhAIHkRAFHGWiLmgzkgWRjjy4j3MG/SWKl7zCLfT0JwUfV"}]},"_npmUser":{"name":"dblechoc","email":"sync@me.com"},"directories":{},"maintainers":[{"name":"dblechoc","email":"sync@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/open-wc-scoped-elements_1.3.4_1614661601760_0.4415867644329168"},"_hasShrinkwrap":false},"1.3.5":{"name":"@dblechoc/open-wc-scoped-elements","version":"1.3.5","publishConfig":{"access":"public"},"description":"Allows to auto define custom elements scoping them","license":"MIT","repository":{"type":"git","url":"git+https://github.com/open-wc/open-wc.git","directory":"packages/scoped-elements"},"author":{"name":"open-wc"},"homepage":"https://github.com/open-wc/open-wc/tree/master/packages/scoped-elements","module":"index.js","scripts":{"demo-build:before-nesting":"rollup -c demo/before-nesting/rollup.config.js","demo-build:no-scope":"rollup -c demo/no-scope/rollup.config.js","demo-build:with-scope":"rollup -c demo/with-scope/rollup.config.js","site:build":"run-p demo-build:*","start:before-nesting":"es-dev-server -c demo/before-nesting/server.js","start:no-scope":"es-dev-server -c demo/no-scope/server.js","start:with-scope":"es-dev-server -c demo/with-scope/server.js","test":"cd ../../ && yarn test:browser --grep \"packages/scoped-elements/test/*.test.js\"","test:watch":"cd ../../ && yarn test:browser:watch --grep \"packages/scoped-elements/test/*.test.js\"","types:copy":"copyfiles \"./src/**/*.d.ts\" \"./*.d.ts\" types"},"keywords":["lit-html","lit-element","web components","utils","helpers"],"dependencies":{"@open-wc/dedupe-mixin":"^1.3.0","lit-html":"^2.0.0-pre.6"},"types":"types/index.d.ts","sideEffects":false,"bugs":{"url":"https://github.com/open-wc/open-wc/issues"},"_id":"@dblechoc/open-wc-scoped-elements@1.3.5","_nodeVersion":"12.19.1","_npmVersion":"6.14.11","dist":{"integrity":"sha512-OapMmybpLVALIR2PkocnEYP3jgrskIi5xmOqIDqrsyaDbseyVox4EkD6gw2JsfqCleMLt6EUKquOrVvCUHkN8w==","shasum":"7677ea449671a2115147957b2056d20646466054","tarball":"https://registry.npmjs.org/@dblechoc/open-wc-scoped-elements/-/open-wc-scoped-elements-1.3.5.tgz","fileCount":31,"unpackedSize":86148,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgRYwZCRA9TVsSAnZWagAAAdEP/2jc1kc3I92QezYswQ0D\nBzS8KyG2qzcJHomu7rq3D7dVihW7sYnSPeW9jIrin4TXDATC+siLFfIdrPMB\nDBV6dCpC/k/O8IYLwnT/3lWl9hXyixzAtLTweJJJF44Y/Utw1A/IimWxU0Vf\ntC+pgVtViHlIdhL6I/m7iyr4CxVtrMSgOcLM6RXZxJv9luy4nq2lz/6gj25C\neX+VvGEBXMTgNZFY7CSXFLVig0fGVMnoiY9iPrQuyr/ZK3u3Jv0tlYqPf65c\n15xhO0mkuKPjmlkrh/x1jrRlTt89puBLKkxwRmNJ4LbL2xC/f1uIiRU3kfKO\nvlI7YP26WmzjogTt0o0xLY86VmoLetRAFgaTddv6SrzkMfaHORkTISRlYjUL\n8A1xNhatQXf4vPQpC0NqESt/r+L9tKixSIyelqUjEwtYWPt5NfXQIQvCxIAW\nXi7b6SAarpVw6FCAWGTCcj6+4JntzJvY/x1M9pZJQGaK/4WwadC75YLlVweT\nNQfyLIOtUjXb+Zjnz0ySGzXH/I1oh0YM2xASekFOZOLteeI5xa+cLK2/SGqf\nHDJVAWQmLvv0skVGfg4y2SX3cwAOWmvdaTARFcYF6MLp6rfWaCLHH27wl7d/\njVfcJHZWJZsO3DgHVZAnz0kUqZ1X4a0gWjqoZPBeLwKnAokL5F/rdnDYqnlo\nBAzl\r\n=3VBR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEpKcVtW710qMjY4z2A09Ct1HcJYfFhYn7H9mgp2RrOOAiA/Sx+lFyrbvBn8D8rRcrDl9jwz1LSdtnIBDqxUnUai8Q=="}]},"_npmUser":{"name":"dblechoc","email":"sync@me.com"},"directories":{},"maintainers":[{"name":"dblechoc","email":"sync@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/open-wc-scoped-elements_1.3.5_1615170584129_0.7496762092250235"},"_hasShrinkwrap":false}},"time":{"created":"2021-03-02T05:06:41.725Z","1.3.4":"2021-03-02T05:06:41.882Z","modified":"2022-04-05T03:17:42.079Z","1.3.5":"2021-03-08T02:29:44.584Z"},"maintainers":[{"name":"dblechoc","email":"sync@me.com"}],"description":"Allows to auto define custom elements scoping them","homepage":"https://github.com/open-wc/open-wc/tree/master/packages/scoped-elements","keywords":["lit-html","lit-element","web components","utils","helpers"],"repository":{"type":"git","url":"git+https://github.com/open-wc/open-wc.git","directory":"packages/scoped-elements"},"author":{"name":"open-wc"},"bugs":{"url":"https://github.com/open-wc/open-wc/issues"},"license":"MIT","readme":"---\npermalink: 'scoped-elements/index.html'\ntitle: Scoped elements\nsection: guides\ntags:\n  - guides\n---\n\n# Scoped elements\n\n> Part of [Open Web Components](https://github.com/open-wc/open-wc/): guides, tools and libraries for modern web development and web components\n\n[![CircleCI](https://circleci.com/gh/open-wc/open-wc.svg?style=shield)](https://circleci.com/gh/open-wc/open-wc)\n[![BrowserStack Status](https://www.browserstack.com/automate/badge.svg?badge_key=M2UrSFVRang2OWNuZXlWSlhVc3FUVlJtTDkxMnp6eGFDb2pNakl4bGxnbz0tLUE5RjhCU0NUT1ZWa0NuQ3MySFFWWnc9PQ==--86f7fac07cdbd01dd2b26ae84dc6c8ca49e45b50)](https://www.browserstack.com/automate/public-build/M2UrSFVRang2OWNuZXlWSlhVc3FUVlJtTDkxMnp6eGFDb2pNakl4bGxnbz0tLUE5RjhCU0NUT1ZWa0NuQ3MySFFWWnc9PQ==--86f7fac07cdbd01dd2b26ae84dc6c8ca49e45b50)\n[![Renovate enabled](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://renovatebot.com/)\n\nScope element tag names avoiding naming collision and allowing to use different versions of the same web component in your code.\n\n## Installation\n\n```bash\nnpm i --save @open-wc/scoped-elements\n```\n\n## Usage\n\n1. Import `ScopedElementsMixin` from `@open-wc/scoped-elements`.\n\n   ```js\n   import { ScopedElementsMixin } from '@open-wc/scoped-elements';\n   ```\n\n2. Import the classes of the components you want to use.\n\n   ```js\n   import { MyButton } from './MyButton.js';\n   import { MyPanel } from './MyPanel.js';\n   ```\n\n3. Apply `ScopedElementsMixin` and define the tags you want to use for your components.\n\n   ```js\n   class MyElement extends ScopedElementsMixin(LitElement) {\n     static get scopedElements() {\n       return {\n         'my-button': MyButton,\n         'my-panel': MyPanel,\n       };\n     }\n   }\n   ```\n\n   > WARNING: If you are going to use elements that are globally defined you have to declare them in `scopedElements` as well. This is required because we are trying to work as close as possible to the future Scoped Custom Element Registries feature and, by the moment, there is not going ot be inheritance between registries.\n   >\n   > You can declare them like in the following example:\n   >\n   > ```js\n   >  static get scopedElements() {\n   >    return {\n   >      'old-button': customElements.get('old-button'),\n   >      'my-panel': MyPanel,\n   >    };\n   >  }\n   > ```\n   >\n   > If you try to register the same element globally AND locally with the exact same name AND class instance it will reuse the global tag name and NOT scope it.\n\n4. Use your components in your html.\n\n   ```js\n   render() {\n     return html`\n       <my-panel class=\"panel\">\n         <my-button>${this.text}</my-button>\n       </my-panel>\n     `;\n   }\n   ```\n\n### Complete example\n\n```js\nimport { css, LitElement } from 'lit-element';\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements';\nimport { MyButton } from './MyButton.js';\nimport { MyPanel } from './MyPanel.js';\n\nexport class MyElement extends ScopedElementsMixin(LitElement) {\n  static get scopedElements() {\n    return {\n      'my-button': MyButton,\n      'my-panel': MyPanel,\n    };\n  }\n\n  static get styles() {\n    return css`\n      .panel {\n        padding: 10px;\n        background-color: grey;\n      }\n    `;\n  }\n\n  static get properties() {\n    return {\n      text: String,\n    };\n  }\n\n  render() {\n    return html`\n      <my-panel class=\"panel\">\n        <my-button>${this.text}</my-button>\n      </my-panel}>\n    `;\n  }\n}\n```\n\n### Lazy scoped components\n\nIn some situations may happen that you want to use a component in your templates that is not already loaded at the moment of defining the scoped elements map. The `ScopedElementsMixin` provides the `defineScopedElement` method to define scoped elements at any time.\n\n```js\nimport { LitElement } from 'lit-element';\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements';\nimport { MyPanel } from './MyPanel.js';\n\nexport class MyElement extends ScopedElementsMixin(LitElement) {\n  static get scopedElements() {\n    return {\n      'my-panel': MyPanel,\n    };\n  }\n\n  constructor() {\n    super();\n\n    import('./MyButton.js').then(({ MyButton }) => this.defineScopedElement('my-button', MyButton));\n  }\n\n  render() {\n    return html`\n      <my-panel class=\"panel\">\n        <my-button>${this.text}</my-button>\n      </my-panel>\n    `;\n  }\n}\n```\n\n### Obtaining a scoped tag name\n\nMaybe you want to create a scoped element programmatically and don't know which one is the scoped tag name? No problem, there is a method called `getScopedTagName` that would help you for that.\n\n```js\nimport { LitElement } from 'lit-element';\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements';\nimport { MyButton } from './MyButton.js';\nimport { MyPanel } from './MyPanel.js';\n\nexport class MyElement extends ScopedElementsMixin(LitElement) {\n  static get scopedElements() {\n    return {\n      'my-panel': MyPanel,\n      'my-button': MyButton,\n    };\n  }\n\n  constructor() {\n    super();\n\n    const scopedTagName = this.getScopedTagName('my-button');\n\n    // do whatever you need with the scopedTagName\n  }\n\n  // ...\n}\n```\n\n## Motivation\n\nComplex Web Component applications are often developed by several teams across organizations. In that scenario it is common that shared component libraries are used by teams to create a homogeneous look and feel or just to avoid creating the same components multiple times, but as those libraries evolve problems between different versions of the same library may appear, as teams may not be able to evolve and update their code at the same velocity. This causes bottlenecks in software delivery that should be managed by the teams and complex build systems, to try to alleviate the problem.\n\n[Scoped Custom Element Registries](https://github.com/w3c/webcomponents/issues/716) is a proposal that will solve this problem, but until it is ready, or a polyfill becomes available, we have to _scope_ custom element tag names if we want to use different versions of those custom elements in our code. This package allows you to forget about how custom elements are defined, registered and scopes their tag names if it is necessary, and avoids the name collision problem.\n\n## Use case and demos\n\nConsider the following setup\n\n- **Team Blue** owns **Page A**\n- **Team Green** owns **Page B**\n- **Team Black** owns **Feature A & B**\n\n1. Everything is good and [your app is live](https://open-wc.org/scoped-elements/demo/before-nesting/) [[code](https://github.com/open-wc/open-wc/tree/master/packages/scoped-elements/demo/before-nesting)] with both pages.\n2. **Team Black** releases a new version (**2.x**) of **Feature B** which unfortunately needs to be breaking in order to support new use-cases.\n3. **Team Blue** (on **Page A**) does not use any of those new use cases, and they have a tight deadline to meet, so they cannot update right now.\n4. **Team Green** (on **Page B**) has to deliver an important functionality to your end users, but they need to upgrade to **Feature B 2.x** since it can only be solved with this new version.\n5. Since **Feature A 1.x & 2.x** are both used in the same app, this will lead to nested dependencies, which then will lead to [catastrophic failure, and errors](https://open-wc.org/scoped-elements/demo/no-scope/) [[code](https://github.com/open-wc/open-wc/tree/master/packages/scoped-elements/demo/no-scope)].\n\nTwo possible solutions come to mind:\n\n1.  Temporarily (!) allow shipping similar source code (most breaking releases are not a total rewrite) and scope them via `@open-wc/scoped-elements`; see the \"fixed\" example [with-scope](https://open-wc.org/scoped-elements/demo/with-scope/) [[code](https://github.com/open-wc/open-wc/tree/master/packages/scoped-elements/demo/with-scope)] running with nested dependencies.\n2.  Synchronizing updates of shared dependencies - e.g. make sure **Team Blue** & **Team Green** always use the same version when releasing. This can be a viable solution however it comes with a high organizational overhead and is hard to scale up (for 10+ teams)\n\n#### Technical explanation of scenario\n\nThe simplified app has the following dependencies\n\n- app\n  - page-a\n    - feature-a 1.x\n    - feature-b 1.x\n  - page-b\n    - feature-a 2.x\n    - feature-b 1.x\n\nwhich leads to the following node_modules tree\n\n```\n├── node_modules\n│   ├── feature-a\n│   ├── feature-b\n│   ├── page-a\n│   └── page-b\n│       └── node_modules\n│           └── feature-a\n├── demo-app.js\n└── index.html\n```\n\nTo demonstrate, we made three demos:\n\n1. [before-nesting](https://open-wc.org/scoped-elements/demo/before-nesting/) [[code](https://github.com/open-wc/open-wc/tree/master/packages/scoped-elements/demo/before-nesting)] In this demo, everything works fine as **Page A and B** both are using the same version of **Feature A**\n\n2. [no-scope](https://open-wc.org/scoped-elements/demo/no-scope/) [[code](https://github.com/open-wc/open-wc/tree/master/packages/scoped-elements/demo/no-scope)] **Feature A** version **1.x** and **2.x** are imported via self registering entry points which leads to the following error message, because the `feature-a` component tries to register multiple times:\n\n   ```\n   Uncaught DOMException: Failed to execute 'define' on 'CustomElementRegistry': the name \"feature-a\" has already been used with this registry\n     at [...]/node_modules/page-b/node_modules/feature-a/feature-a.js:3:16\n   ```\n\n3. [with-scope](https://open-wc.org/scoped-elements/demo/with-scope/) [[code](https://github.com/open-wc/open-wc/tree/master/packages/scoped-elements/demo/with-scope)] This example successfully fixes the problem by using `ScopedElementsMixin` on both **Page A** and **Page B**.\n\n## How it works\n\n`ScopedElementsMixin` is mixed into your LitElement and via `static get scopedElements()` you define the tags and classes you wanna use in your elements template.\nUnder the hood it changes your template so `<my-button>${this.text}</my-button>` becomes `<my-button-2748 data-tag-name=\"my-button\">${this.text}</my-button-2748>`.\n\nEvery auto-defined scoped elements gets a random\\* 4 digits number suffix. This suffix changes every time to make sure developers are not inclined to use it the generated tag name as a styling hook. Additionally the suffix allows scoped-elements and traditional self-defined elements to coexist, avoiding name collision.\n\n\\* it is actually a global counter that gets initialized with a random starting number on load\n\n## Limitations\n\n1. Components imported via npm **SHOULD NOT** be self registering components. If a shared component (installed from npm) does not offer an export to the class alone, without the registration side effect, then this component may not be used. E.g. every component that calls `customElement.define`.\n\n   ```js\n   export class MyEl { ... }\n   customElement.define('my-el', MyEl);\n   ```\n\n   Or uses the `customElement` typescript decorator\n\n   ```ts\n   @customElement('my-el')\n   export class MyEl { ... }\n   ```\n\n   Only side effects free class exports may be used\n\n   ```js\n   export class MyEl { ... }\n   ```\n\n2. Every component that uses sub components should use `scoped-elements`. Any import to a self registering component can potentially result in a browser exception - completely breaking the whole application.\n\n3. Imported elements should be fully side effect free (not only element registration)\n\n4. Currently, only `lit-element` is supported (though other elements/rendering engines could be incorporated in the future).\n\n5. You cannot use tag selectors in css, but you could use an id, a class name or even a property instead.\n\n   ```css\n   🚫 my-panel {\n     width: 300px;\n   }\n   ✅ .panel {\n     width: 300px;\n   }\n   ```\n\n6. You cannot use tag names using javascript querySelectors, but you could use an id, a class name or even a property instead.\n\n   ```js\n   🚫 this.shadowRoot.querySelector('my-panel');\n   ✅ this.shadowRoot.querySelector('.panel');\n   ```\n\n7. Using `scoped-elements` may result in a performance degradation of up to 8%.\n8. Loading of duplicate/similar source code (most breaking releases are not a total rewrite) should always be a temporary solution.\n9. Often, temporary solutions tend to become more permanent. Be sure to focus on keeping the lifecycle of nested dependencies short.\n\n## Performance\n\nWe are using [Tachometer](https://github.com/Polymer/tachometer) to measure the performance penalty of using the scoped elements feature. The chosen test application is a slight variation of the [Polymer Shop Application](https://shop.polymer-project.org).\n\nThis is an example of the results obtained running the performance test.\n\n```\n⠋ Auto-sample 560 (timeout in 16m27s)\n┌─────────────┬───────────────┐\n│     Version │ <none>        │\n├─────────────┼───────────────┤\n│     Browser │ chrome        │\n│             │ 80.0.3987.106 │\n├─────────────┼───────────────┤\n│ Sample size │ 610           │\n└─────────────┴───────────────┘\n┌─────────────────────────────┬────────────┬─────────────────────┬─────────────────┬──────────────────────────┐\n│ Benchmark                   │ Bytes      │            Avg time │  vs lit-element │ vs scoped-elements-mixin │\n├─────────────────────────────┼────────────┼─────────────────────┼─────────────────┼──────────────────────────┤\n│ lit-element                 │ 281.24 KiB │ 285.72ms - 286.69ms │                 │                   faster │\n│                             │            │                     │        -        │                  2% - 2% │\n│                             │            │                     │                 │           5.68ms - 7.1ms │\n├─────────────────────────────┼────────────┼─────────────────────┼─────────────────┼──────────────────────────┤\n│ scoped-elements-mixin       │ 283.21 KiB │ 292.08ms - 293.11ms │          slower │                          │\n│                             │            │                     │         2% - 2% │                 -        │\n│                             │            │                     │ 5.68ms - 7.10ms │                          │\n└─────────────────────────────┴────────────┴─────────────────────┴─────────────────┴──────────────────────────┘\n```\n\n## Special thanks\n\nThis package was initially inspired by [carehtml](https://github.com/bashmish/carehtml) and we would like to thank [@bashmish](https://github.com/bashmish) for his work on it.\n","readmeFilename":"README.md"}