Merge remote-tracking branch 'upstream/master'

* upstream/master: (140 commits)
  support $$props and $$restProps for custom elements (#5608)
  Bump eslint-config to 5.5.0 (#5599)
  update changelog
  add Node and Element as known globals (#5601)
  docs: fix a11y warning in media elements example (#5606)
  Curly braces linting fixes (#5585)
  refactor sourcemap and preprocessor tests (#5583)
  -> v3.29.4
  fix code generation error with nullish coalescing operator and logical operators (#5564)
  -> v3.29.3
  -> v3.29.2
  -> v3.29.1
  docs: fix a11y warning in media elements tutorial (#5523)
  update changelog
  get context at start of {#if} update block instead of at the end (#5531)
  update changelog
  only allow passing functions to lifecycle functions (#5529)
  update changelog
  fix compiler hanging on <slot slot="..."> (#5536)
  Add svelte@next caveat to bug report template (#5561)
  ...
pull/4522/head
hontas 5 years ago
commit 527c14d397

@ -8,10 +8,13 @@ the issue. One way we prioritize issues is by the number of :+1: reactions on
their descriptions. Please DO NOT add `+1` or :+1: comments.
### Feature requests and proposals
We're excited to hear how we can make Svelte better. Please add as much detail
as you can on your use case.
as you can on your use case. To propose an implementation of a large feature or
change, please create an [RFC](https://github.com/sveltejs/rfcs).
### Bugs
If you're filing an issue about a bug please include as much information
as you can including the following.

@ -7,6 +7,8 @@ assignees: ''
---
## Is this about svelte@next? This project is currently in a pre-release stage and breaking changes may occur at any time. Please do not post any kind of bug reports or questions on GitHub about it.
**Describe the bug**
A clear and concise description of what the bug is.

@ -7,6 +7,11 @@ assignees: ''
---
<!--
If you'd like to propose an implementation for a large new feature or change then please create an RFC:
https://github.com/sveltejs/rfcs
-->
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. For example: I'm always frustrated when [...]

@ -1,8 +1,7 @@
### Before submitting the PR, please make sure you do the following
- [ ] It's really useful if your PR relates to an outstanding issue, so please reference it in your PR, or create an explanatory one for discussion. In many cases, features are absent for a reason.
- [ ] This message body should clearly illustrate what problems it solves. If there are related issues, remember to reference them.
- [ ] Ideally, include a test that fails without this PR but passes with it. PRs will only be merged once they pass CI. (Remember to `npm run lint`!)
- [ ] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
- [ ] This message body should clearly illustrate what problems it solves.
- [ ] Ideally, include a test that fails without this PR but passes with it.
### Tests
- [ ] Run the tests with `npm test` or `yarn test`)
- [ ] Run the tests with `npm test` and lint the project with `npm run lint`

4
.gitignore vendored

@ -18,10 +18,6 @@ node_modules
/coverage/
/coverage.lcov
/test/*/samples/_
/test/sourcemaps/samples/*/output.js
/test/sourcemaps/samples/*/output.js.map
/test/sourcemaps/samples/*/output.css
/test/sourcemaps/samples/*/output.css.map
/yarn-error.log
_actual*.*
_output

@ -0,0 +1,14 @@
module.exports = {
file: [
'test/test.ts'
],
require: [
'sucrase/register'
]
};
// add coverage options when running 'npx c8 mocha'
if (process.env.NODE_V8_COVERAGE) {
module.exports.fullTrace = true;
module.exports.require.push('source-map-support/register');
}

@ -2,9 +2,92 @@
## Unreleased
* Fix `$$props` and `$$restProps` when compiling to a custom element ([#5482](https://github.com/sveltejs/svelte/issues/5482))
* Add `Element` and `Node` to known globals ([#5586](https://github.com/sveltejs/svelte/issues/5586))
## 3.29.4
* Fix code generation error with `??` alongside logical operators ([#5558](https://github.com/sveltejs/svelte/issues/5558))
## 3.29.3
* Hopefully actually republish with proper UMD build for use in the REPL
## 3.29.2
* Republish with proper UMD build for use in the REPL
## 3.29.1
* Fix compiler hanging on `<slot slot="...">` ([#5475](https://github.com/sveltejs/svelte/issues/5475))
* Fix types on `get` function in `svelte/store` ([#5483](https://github.com/sveltejs/svelte/pull/5483))
* Add missing `end` field on ASTs for non-top-level `<style>` elements ([#5487](https://github.com/sveltejs/svelte/pull/5487))
* Fix `{#if}` inside `{#await}` with destructuring ([#5508](https://github.com/sveltejs/svelte/issues/5508))
* Fix types on lifecycle hooks ([#5529](https://github.com/sveltejs/svelte/pull/5529))
## 3.29.0
* Support `<slot slot="...">` ([#2079](https://github.com/sveltejs/svelte/issues/2079))
* Fix unmounting components with a bidirectional transition with a delay ([#4954](https://github.com/sveltejs/svelte/issues/4954))
* Add types to `get` function in `svelte/store` ([#5269](https://github.com/sveltejs/svelte/pull/5269))
* Add a warning when a component looks like it's trying to use another component without beginning with a capital letter ([#5302](https://github.com/sveltejs/svelte/pull/5302))
* Add `EventSource` to known globals ([#5463](https://github.com/sveltejs/svelte/issues/5463))
* Fix compiler exception with `~`/`+` combinators and `{...spread}` attributes ([#5465](https://github.com/sveltejs/svelte/issues/5465))
## 3.28.0
* Add `{#key}` block for keying arbitrary content on an expression ([#1469](https://github.com/sveltejs/svelte/issues/1469))
## 3.27.0
* Add `|nonpassive` event modifier, explicitly passing `passive: false` ([#2068](https://github.com/sveltejs/svelte/issues/2068))
* Scope CSS selectors with `~` and `+` combinators ([#3104](https://github.com/sveltejs/svelte/issues/3104))
* Fix keyed `{#each}` not reacting to key changing ([#5444](https://github.com/sveltejs/svelte/issues/5444))
* Fix destructuring into store values ([#5449](https://github.com/sveltejs/svelte/issues/5449))
* Fix erroneous `missing-declaration` warning with `use:obj.method` ([#5451](https://github.com/sveltejs/svelte/issues/5451))
## 3.26.0
* Support `use:obj.method` as actions ([#3935](https://github.com/sveltejs/svelte/issues/3935))
* Support `_` as numeric separator ([#5407](https://github.com/sveltejs/svelte/issues/5407))
* Fix assignments to properties on store values ([#5412](https://github.com/sveltejs/svelte/issues/5412))
* Add special style scoping handling of `[open]` selectors on `<details>` elements ([#5421](https://github.com/sveltejs/svelte/issues/5421))
* Support `import.meta` in template expressions ([#5422](https://github.com/sveltejs/svelte/issues/5422))
## 3.25.1
* Fix specificity of certain styles involving a child selector ([#4795](https://github.com/sveltejs/svelte/issues/4795))
* Fix transitions that are parameterised with stores ([#5244](https://github.com/sveltejs/svelte/issues/5244))
* Fix scoping of styles involving child selector and `*` ([#5370](https://github.com/sveltejs/svelte/issues/5370))
* Fix destructuring which reassigns stores ([#5388](https://github.com/sveltejs/svelte/issues/5388))
* Fix `{#await}`s with no `{:catch}` getting stuck unresolved if the promise rejects ([#5401](https://github.com/sveltejs/svelte/issues/5401))
## 3.25.0
* Use `null` rather than `undefined` for coerced bound value of `<input type="number">` ([#1701](https://github.com/sveltejs/svelte/issues/1701))
* Expose object of which slots have received content in `$$slots` ([#2106](https://github.com/sveltejs/svelte/issues/2106))
* Correctly disallow using lifecycle hooks after synchronous component initialisation ([#4259](https://github.com/sveltejs/svelte/issues/4259), [#4899](https://github.com/sveltejs/svelte/issues/4899))
* Re-throw an unhandled rejection when an `{#await}` block with no `{:catch}` gets a rejection ([#5129](https://github.com/sveltejs/svelte/issues/5129))
* Add types to `createEventDispatcher` ([#5211](https://github.com/sveltejs/svelte/issues/5211))
* In SSR mode, do not automatically declare variables for reactive assignments to member expressions ([#5247](https://github.com/sveltejs/svelte/issues/5247))
* Include selector in message of `unused-css-selector` warning ([#5252](https://github.com/sveltejs/svelte/issues/5252))
* Fix using `<Namespaced.Component/>`s in child `{#await}`/`{#each}` contexts ([#5255](https://github.com/sveltejs/svelte/issues/5255))
* Fix using `<svelte:component>` in `{:catch}` ([#5259](https://github.com/sveltejs/svelte/issues/5259))
* Fix setting one-way bound `<input>` `value` to `undefined` when it has spread attributes ([#5270](https://github.com/sveltejs/svelte/issues/5270))
* Fix deep two-way bindings inside an `{#each}` involving a store ([#5286](https://github.com/sveltejs/svelte/issues/5286))
* Use valid XHTML for elements that are optimised and inserted with `.innerHTML` ([#5315](https://github.com/sveltejs/svelte/issues/5315))
* Fix reactivity of `$$props` in slot fallback content ([#5367](https://github.com/sveltejs/svelte/issues/5367))
## 3.24.1
* Prevent duplicate invalidation with certain two-way component bindings ([#3180](https://github.com/sveltejs/svelte/issues/3180), [#5117](https://github.com/sveltejs/svelte/issues/5117), [#5144](https://github.com/sveltejs/svelte/issues/5144))
* Fix reactivity when passing `$$props` to a `<slot>` ([#3364](https://github.com/sveltejs/svelte/issues/3364))
* Fix transitions on `{#each}` `{:else}` ([#4970](https://github.com/sveltejs/svelte/issues/4970))
* Fix unneeded invalidation of `$$props` and `$$restProps` ([#4993](https://github.com/sveltejs/svelte/issues/4993), [#5118](https://github.com/sveltejs/svelte/issues/5118))
* Provide better compiler error message when mismatched tags are due to autoclosing of tags ([#5049](https://github.com/sveltejs/svelte/issues/5049))
* Add `a11y-label-has-associated-control` warning ([#5074](https://github.com/sveltejs/svelte/pull/5074))
* Add `a11y-media-has-caption` warning ([#5075](https://github.com/sveltejs/svelte/pull/5075))
* Fix `bind:group` when using contextual reference ([#5174](https://github.com/sveltejs/svelte/issues/5174))
## 3.24.0

@ -43,13 +43,16 @@ When [opening a new issue](https://github.com/sveltejs/svelte/issues/new/choose)
- **One issue, one bug:** Please report a single bug per issue.
- **Provide reproduction steps:** List all the steps necessary to reproduce the issue. The person reading your bug report should be able to follow these steps to reproduce your issue with minimal effort. If possible, use the [REPL](https://svelte.dev/repl) to create your reproduction.
## RFCs
If you'd like to propose an implementation for a large new feature or change then please [create an RFC](https://github.com/sveltejs/rfcs) to discuss it up front.
## Installation
1. Ensure you have [npm](https://www.npmjs.com/get-npm) installed.
1. After cloning the repository, run `npm install` in the root of the repository.
1. To start a development server, run `npm run dev`.
## Pull requests
### Your first pull request

@ -2,14 +2,15 @@
<a href="https://svelte.dev">
<img alt="Cybernetically enhanced web apps: Svelte" src="https://sveltejs.github.io/assets/banner.png">
</a>
<a href="https://www.npmjs.com/package/svelte">
<img src="https://img.shields.io/npm/v/svelte.svg" alt="npm version">
</a>
<a href="https://github.com/sveltejs/svelte/blob/master/LICENSE">
<img src="https://img.shields.io/npm/l/svelte.svg" alt="license">
</a>
<a href="https://svelte.dev/chat">
<img src="https://img.shields.io/badge/chat-on%20discord-7289da.svg" alt="Chat">
</a>
</p>
@ -20,6 +21,15 @@ Svelte is a new way to build web applications. It's a compiler that takes your d
Learn more at the [Svelte website](https://svelte.dev), or stop by the [Discord chatroom](https://svelte.dev/chat).
## Supporting Svelte
Svelte is an MIT-licensed open source project with its ongoing development made possible entirely by the support of awesome volunteers. If you'd like to support their efforts, please consider:
- [Becoming a backer on Open Collective](https://opencollective.com/svelte).
Funds donated via Open Collective will be used for compensating expenses related to Svelte's development such as hosting costs. If sufficient donations are received, funds may also be used to support Svelte's development more directly.
## Development
Pull requests are encouraged and always welcome. [Pick an issue](https://github.com/sveltejs/svelte/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) and help us out!

@ -1,4 +0,0 @@
--require source-map-support/register
--full-trace
--recursive
test/test.js

@ -1 +0,0 @@
test/test.js

502
package-lock.json generated

@ -1,6 +1,6 @@
{
"name": "svelte",
"version": "3.24.0",
"version": "3.29.4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -144,8 +144,8 @@
}
},
"@sveltejs/eslint-config": {
"version": "github:sveltejs/eslint-config#e8a9b27cd3f7aa66388474412b1a5c11c5a44ade",
"from": "github:sveltejs/eslint-config#v0.0.1",
"version": "github:sveltejs/eslint-config#54081d752d199dba97db9f578665c87f18469da3",
"from": "github:sveltejs/eslint-config#v5.5.0",
"dev": true
},
"@tootallnate/once": {
@ -197,9 +197,9 @@
"dev": true
},
"@types/mocha": {
"version": "5.2.7",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
"integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==",
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz",
"integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==",
"dev": true
},
"@types/node": {
@ -315,9 +315,9 @@
"dev": true
},
"acorn": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz",
"integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
"integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
"dev": true
},
"acorn-globals": {
@ -422,6 +422,16 @@
"integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=",
"dev": true
},
"anymatch": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
"integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
"dev": true,
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
},
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@ -630,6 +640,12 @@
"tweetnacl": "^0.14.3"
}
},
"binary-extensions": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
"integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -640,6 +656,15 @@
"concat-map": "0.0.1"
}
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"requires": {
"fill-range": "^7.0.1"
}
},
"browser-process-hrtime": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz",
@ -736,6 +761,22 @@
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"dev": true
},
"chokidar": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz",
"integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==",
"dev": true,
"requires": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"fsevents": "~2.1.1",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.2.0"
}
},
"cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
@ -762,16 +803,10 @@
"wrap-ansi": "^5.1.0"
}
},
"code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
"dev": true
},
"code-red": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/code-red/-/code-red-0.1.3.tgz",
"integrity": "sha512-3n9i1Jv0om4+2Aq7pCL8M5xRgc2wTXsblsYUxXJDpgBZ3wJP1zbcNzu4XgUqrG0rjc1to2yh+3n9rwHsJa7qSA==",
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/code-red/-/code-red-0.1.4.tgz",
"integrity": "sha512-NPiLFd1EfonYONCNXCH1oVirQMXk5oAOQ3FanRbjB4HZ09rTU/lZGKjVOOP0FKr4pccGVYE5I4CqtyU6ens2VA==",
"dev": true,
"requires": {
"acorn": "^7.3.1",
@ -1020,23 +1055,36 @@
}
},
"es-abstract": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
"integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
"version": "1.17.6",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
"integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
"dev": true,
"requires": {
"es-to-primitive": "^1.2.0",
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"is-callable": "^1.1.4",
"is-regex": "^1.0.4",
"object-keys": "^1.0.12"
"has-symbols": "^1.0.1",
"is-callable": "^1.2.0",
"is-regex": "^1.1.0",
"object-inspect": "^1.7.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.0",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
},
"dependencies": {
"has-symbols": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
"dev": true
}
}
},
"es-to-primitive": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
"integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
"dev": true,
"requires": {
"is-callable": "^1.1.4",
@ -1722,6 +1770,15 @@
"flat-cache": "^2.0.1"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
},
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
@ -1790,6 +1847,13 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"fsevents": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
"dev": true,
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@ -2204,16 +2268,25 @@
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
"dev": true
},
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"requires": {
"binary-extensions": "^2.0.0"
}
},
"is-buffer": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
"integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
"integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==",
"dev": true
},
"is-callable": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
"integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz",
"integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==",
"dev": true
},
"is-date-object": {
@ -2249,6 +2322,12 @@
"integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=",
"dev": true
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
"is-reference": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
@ -2259,12 +2338,20 @@
}
},
"is-regex": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
"integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
"integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
"dev": true,
"requires": {
"has": "^1.0.1"
"has-symbols": "^1.0.1"
},
"dependencies": {
"has-symbols": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
"dev": true
}
}
},
"is-stream": {
@ -2539,12 +2626,12 @@
"dev": true
},
"log-symbols": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
"integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz",
"integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==",
"dev": true,
"requires": {
"chalk": "^2.0.1"
"chalk": "^2.4.2"
}
},
"lru-cache": {
@ -2662,13 +2749,14 @@
}
},
"mocha": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz",
"integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==",
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz",
"integrity": "sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==",
"dev": true,
"requires": {
"ansi-colors": "3.2.3",
"browser-stdout": "1.3.1",
"chokidar": "3.3.0",
"debug": "3.2.6",
"diff": "3.5.0",
"escape-string-regexp": "1.0.5",
@ -2677,50 +2765,21 @@
"growl": "1.10.5",
"he": "1.2.0",
"js-yaml": "3.13.1",
"log-symbols": "2.2.0",
"log-symbols": "3.0.0",
"minimatch": "3.0.4",
"mkdirp": "0.5.1",
"mkdirp": "0.5.5",
"ms": "2.1.1",
"node-environment-flags": "1.0.5",
"node-environment-flags": "1.0.6",
"object.assign": "4.1.0",
"strip-json-comments": "2.0.1",
"supports-color": "6.0.0",
"which": "1.3.1",
"wide-align": "1.1.3",
"yargs": "13.2.2",
"yargs-parser": "13.0.0",
"yargs-unparser": "1.5.0"
"yargs": "13.3.2",
"yargs-parser": "13.1.2",
"yargs-unparser": "1.6.0"
},
"dependencies": {
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
"dev": true
},
"cliui": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
"integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
"dev": true,
"requires": {
"string-width": "^2.1.1",
"strip-ansi": "^4.0.0",
"wrap-ansi": "^2.0.0"
},
"dependencies": {
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"dev": true,
"requires": {
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^4.0.0"
}
}
}
},
"glob": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
@ -2735,36 +2794,12 @@
"path-is-absolute": "^1.0.0"
}
},
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true
},
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
"requires": {
"minimist": "0.0.8"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true
},
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"dev": true,
"requires": {
"ansi-regex": "^3.0.0"
}
},
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
@ -2780,76 +2815,28 @@
"has-flag": "^3.0.0"
}
},
"wrap-ansi": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
"dev": true,
"requires": {
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1"
},
"dependencies": {
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
"requires": {
"number-is-nan": "^1.0.0"
}
},
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
"strip-ansi": "^3.0.0"
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
}
}
},
"yargs": {
"version": "13.2.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz",
"integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==",
"version": "13.3.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
"integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
"dev": true,
"requires": {
"cliui": "^4.0.0",
"cliui": "^5.0.0",
"find-up": "^3.0.0",
"get-caller-file": "^2.0.1",
"os-locale": "^3.1.0",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^3.0.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^13.0.0"
"yargs-parser": "^13.1.2"
}
},
"yargs-parser": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz",
"integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==",
"version": "13.1.2",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
"integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
"dev": true,
"requires": {
"camelcase": "^5.0.0",
@ -2894,9 +2881,9 @@
"dev": true
},
"node-environment-flags": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz",
"integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==",
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz",
"integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==",
"dev": true,
"requires": {
"object.getownpropertydescriptors": "^2.0.3",
@ -2904,17 +2891,17 @@
},
"dependencies": {
"semver": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
}
}
},
"node-fetch": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==",
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
"dev": true
},
"node-modules-regexp": {
@ -2935,6 +2922,12 @@
"validate-npm-package-license": "^3.0.1"
}
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true
},
"npm-run-path": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
@ -2944,12 +2937,6 @@
"path-key": "^2.0.0"
}
},
"number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
"dev": true
},
"nwsapi": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz",
@ -2993,13 +2980,13 @@
}
},
"object.getownpropertydescriptors": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
"integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz",
"integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==",
"dev": true,
"requires": {
"define-properties": "^1.1.2",
"es-abstract": "^1.5.1"
"define-properties": "^1.1.3",
"es-abstract": "^1.17.0-next.1"
}
},
"object.values": {
@ -3253,6 +3240,12 @@
"is-reference": "^1.1.4"
}
},
"picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
"dev": true
},
"pify": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
@ -3466,6 +3459,15 @@
"util-deprecate": "~1.0.1"
}
},
"readdirp": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz",
"integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==",
"dev": true,
"requires": {
"picomatch": "^2.0.4"
}
},
"regexpp": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
@ -4257,6 +4259,15 @@
"os-tmpdir": "~1.0.2"
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"requires": {
"is-number": "^7.0.0"
}
},
"tough-cookie": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz",
@ -4616,135 +4627,38 @@
}
},
"yargs-unparser": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz",
"integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz",
"integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==",
"dev": true,
"requires": {
"flat": "^4.1.0",
"lodash": "^4.17.11",
"yargs": "^12.0.5"
"lodash": "^4.17.15",
"yargs": "^13.3.0"
},
"dependencies": {
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
"dev": true
},
"cliui": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
"integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
"dev": true,
"requires": {
"string-width": "^2.1.1",
"strip-ansi": "^4.0.0",
"wrap-ansi": "^2.0.0"
}
},
"get-caller-file": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
"dev": true
},
"require-main-filename": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
"dev": true
},
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"dev": true,
"requires": {
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^4.0.0"
}
},
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"dev": true,
"requires": {
"ansi-regex": "^3.0.0"
}
},
"wrap-ansi": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
"dev": true,
"requires": {
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1"
},
"dependencies": {
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
"requires": {
"number-is-nan": "^1.0.0"
}
},
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
"strip-ansi": "^3.0.0"
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
}
}
},
"yargs": {
"version": "12.0.5",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
"integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
"version": "13.3.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
"integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
"dev": true,
"requires": {
"cliui": "^4.0.0",
"decamelize": "^1.2.0",
"cliui": "^5.0.0",
"find-up": "^3.0.0",
"get-caller-file": "^1.0.1",
"os-locale": "^3.0.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^1.0.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^2.0.0",
"string-width": "^3.0.0",
"which-module": "^2.0.0",
"y18n": "^3.2.1 || ^4.0.0",
"yargs-parser": "^11.1.1"
"y18n": "^4.0.0",
"yargs-parser": "^13.1.2"
}
},
"yargs-parser": {
"version": "11.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
"integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
"version": "13.1.2",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
"integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
"dev": true,
"requires": {
"camelcase": "^5.0.0",

@ -1,6 +1,6 @@
{
"name": "svelte",
"version": "3.24.0",
"version": "3.29.4",
"description": "Cybernetically enhanced web apps",
"module": "index.mjs",
"main": "index",
@ -23,10 +23,10 @@
},
"types": "types/runtime/index.d.ts",
"scripts": {
"test": "mocha --opts mocha.opts",
"test": "mocha",
"test:unit": "mocha --require sucrase/register --recursive src/**/__test__.ts",
"quicktest": "mocha --opts mocha.opts",
"precoverage": "c8 mocha --opts mocha.coverage.opts",
"quicktest": "mocha",
"precoverage": "c8 mocha",
"coverage": "c8 report --reporter=text-lcov > coverage.lcov && c8 report --reporter=html",
"codecov": "codecov",
"precodecov": "npm run coverage",
@ -63,15 +63,15 @@
"@rollup/plugin-sucrase": "^3.0.0",
"@rollup/plugin-typescript": "^2.0.1",
"@rollup/plugin-virtual": "^2.0.0",
"@sveltejs/eslint-config": "github:sveltejs/eslint-config#v0.0.1",
"@types/mocha": "^5.2.7",
"@sveltejs/eslint-config": "github:sveltejs/eslint-config#v5.5.0",
"@types/mocha": "^7.0.0",
"@types/node": "^8.10.53",
"@typescript-eslint/eslint-plugin": "^3.0.2",
"@typescript-eslint/parser": "^3.0.2",
"acorn": "^7.3.1",
"acorn": "^7.4.0",
"agadoo": "^1.1.0",
"c8": "^5.0.1",
"code-red": "^0.1.3",
"code-red": "^0.1.4",
"codecov": "^3.5.0",
"css-tree": "1.0.0-alpha22",
"eslint": "^7.1.0",
@ -83,7 +83,7 @@
"kleur": "^3.0.3",
"locate-character": "^2.0.5",
"magic-string": "^0.25.3",
"mocha": "^6.2.0",
"mocha": "^7.0.0",
"periscopic": "^2.0.1",
"puppeteer": "^2.1.1",
"rollup": "^1.27.14",

@ -99,12 +99,20 @@ export default [
json(),
ts_plugin
],
output: {
file: 'compiler.js',
format: is_publish ? 'umd' : 'cjs',
name: 'svelte',
sourcemap: true,
},
output: [
{
file: 'compiler.js',
format: is_publish ? 'umd' : 'cjs',
name: 'svelte',
sourcemap: true,
},
{
file: 'compiler.mjs',
format: 'esm',
name: 'svelte',
sourcemap: true,
}
],
external: is_publish
? []
: id => id === 'acorn' || id === 'magic-string' || id.startsWith('css-tree')

@ -9,7 +9,7 @@ sapper:
@echo "\n~> updating template & contributors list"
@npm run update
@echo "\n~> building Sapper app"
@npm run sapper
@npm run build
docker:

@ -47,12 +47,32 @@ In order for the REPL's GitHub integration to work properly when running locally
## Building the site
To build the website, run `npm run sapper`. The output can be found in `__sapper__/build`.
To build the website, run `npm run build`. The output can be found in `__sapper__/build`.
## Testing
Tests can be run using `npm run test`.
## Linking `@sveltejs/site-kit` and `@sveltejs/site-repl`
This site depends on `@sveltejs/site-kit`, a collection of styles, components and icons used in common by *.svelte.dev websites, and `@sveltejs/site-repl`.
In order to work on features that depend on those packages, you need to [link](https://docs.npmjs.com/cli/link) their repositories:
- `cd <somewhere>`
- `git clone https://github.com/sveltejs/site-kit`
- `git clone https://github.com/sveltejs/svelte-repl`
- `cd <somewhere>/site-kit`
- `npm link`
- `cd <somewhere>/svelte-repl`
- `npm link`
- `cd <svelte-repo>/site`
- `npm link @sveltejs/site-kit`
- `npm link @sveltejs/svelte-repl`
## Translating the API docs
Anchors are automatically generated using headings in the documentation and by default (for the english language) they are latinised to make sure the URL is always conforming to RFC3986.

@ -5,7 +5,7 @@ author: Rich Harris
authorURL: https://twitter.com/Rich_Harris
---
> Quickstart for the impatient: [the Sapper docs](https://sapper.svelte.technology), and the [starter template](https://github.com/sveltejs/sapper-template)
> Quickstart for the impatient: [the Sapper docs](https://sapper.svelte.dev), and the [starter template](https://github.com/sveltejs/sapper-template)
If you had to list the characteristics of the perfect Node.js web application framework, you'd probably come up with something like this:
@ -47,9 +47,9 @@ What happens if we use the new model as a starting point?
## Introducing Sapper
<aside><p>The <a href="https://sapper.svelte.technology/docs#why-the-name-">name comes from</a> the term for combat engineers, and is also short for Svelte app maker</p></aside>
<aside><p>The <a href="https://sapper.svelte.dev/docs#Why_the_name">name comes from</a> the term for combat engineers, and is also short for Svelte app maker</p></aside>
[Sapper](https://sapper.svelte.technology) is the answer to that question. **Sapper is a Next.js-style framework that aims to meet the eleven criteria at the top of this article while dramatically reducing the amount of code that gets sent to the browser.** It's implemented as Express-compatible middleware, meaning it's easy to understand and customise.
[Sapper](https://sapper.svelte.dev) is the answer to that question. **Sapper is a Next.js-style framework that aims to meet the eleven criteria at the top of this article while dramatically reducing the amount of code that gets sent to the browser.** It's implemented as Express-compatible middleware, meaning it's easy to understand and customise.
The same 'hello world' app that took 204kb with React and Next weighs just 7kb with Sapper. That number is likely to fall further in the future as we explore the space of optimisation possibilities, such as not shipping any JavaScript *at all* for pages that aren't interactive, beyond the tiny Sapper runtime that handles client-side routing.

@ -30,7 +30,9 @@ To treat `*.svelte` files as HTML, open *__Edit → Config...__* and add the fol
## Vim/Neovim
To treat all `*.svelte` files as HTML, add the following line to your `init.vim`:
You can use the [coc-svelte extension](https://github.com/coc-extensions/coc-svelte) which utilises the official language-server.
As an alternative you can treat all `*.svelte` files as HTML. Add the following line to your `init.vim`:
```
au! BufNewFile,BufRead *.svelte set ft=html
@ -50,13 +52,7 @@ To set the filetype for a single file, use a [modeline](https://vim.fandom.com/w
## Visual Studio Code
To treat `*.svelte` files as HTML, add the following lines to your `settings.json` file:
```cson
"files.associations": {
"*.svelte": "html"
}
```
We recommend using the official [Svelte for VS Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).
## JetBrains WebStorm

@ -51,7 +51,7 @@ Once installed, you'll have access to three new commands:
## Installing a text editor
To write code, you need a good editor. The most popular choice is [Visual Studio Code](https://code.visualstudio.com/) or VSCode, and justifiably so — it's well-designed and fully-featured, and has a wealth of extensions ([including one for Svelte](https://marketplace.visualstudio.com/items?itemName=JamesBirtles.svelte-vscode), which provides syntax highlighting and diagnostic messages when you're writing components).
To write code, you need a good editor. The most popular choice is [Visual Studio Code](https://code.visualstudio.com/) or VSCode, and justifiably so — it's well-designed and fully-featured, and has a wealth of extensions ([including one for Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode), which provides syntax highlighting and diagnostic messages when you're writing components).
## Creating a project

@ -0,0 +1,141 @@
---
title: Svelte <3 TypeScript
description: Typernetically enhanced web apps
author: Orta Therox
authorURL: https://twitter.com/orta
---
It's been by far the most requested feature for a while, and it's finally here: Svelte officially supports TypeScript.
We think it'll give you a much nicer development experience — one that also scales beautifully to larger Svelte code bases — regardless of whether you use TypeScript or JavaScript.
<figure>
<img alt="Screenshot of TypeScript in Svelte" src="media/svelte-ts.png">
<figcaption>Image of TypeScript + Svelte in VS Code (theme is <a href="https://marketplace.visualstudio.com/items?itemName=karyfoundation.theme-karyfoundation-themes">Kary Pro</a>.)</figcaption>
</figure>
## Try it now
You can start a new Svelte TypeScript project using the [normal template](https://github.com/sveltejs/template) and by running `node scripts/setupTypeScript.js` before you do anything else:
```bash
npx degit sveltejs/template svelte-typescript-app
cd svelte-typescript-app
node scripts/setupTypeScript.js
```
If you're a VS Code user, make sure you're using the (new) [official extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode), which replaces the popular extension by James Birtles.
Later in this blog post, we'll detail the individual steps involved in using TypeScript in an existing Svelte project.
## What does it mean to support TypeScript in Svelte?
TypeScript support in Svelte has been possible for a long time, but you had to mix a lot of disparate tools together and each project ran independently. Today, nearly all of these tools live under the Svelte organization and are maintained by a set of people who take responsibility over the whole pipeline and have common goals.
A week before COVID was declared a pandemic, [I pitched a consolidation](https://github.com/sveltejs/svelte/issues/4518) of the best Svelte tools and ideas from similar dev-ecosystems and provided a set of steps to get first class TypeScript support. Since then, many people have pitched in and written the code to get us there.
When we say that Svelte now supports TypeScript, we mean a few different things:
* You can use TypeScript inside your `<script>` blocks — just add the `lang="ts"` attribute
* Components with TypeScript can be type-checked with the `svelte-check` command
* You get autocompletion hints and type-checking as you're writing components, even in expressions inside markup
* TypeScript files understand the Svelte component API — no more red squiggles when you import a `.svelte` file into a `.ts` module
#### How does it work?
To understand the two main parts of TypeScript support, we'll compare it to the technique TypeScript uses to provide dev tools. There is a compiler `tsc` which you run on the command-line to convert `*.ts` to `*.js`, then there is a `TSServer` which is a node API that responds to requests from text editors. The `TSServer` is what provides all the JavaScript and TypeScript realtime introspection for editors while coding, and it has most of the compiler's code inside it.
For Svelte, we have the Svelte compiler, and now we have the [`svelte-language-server`](https://github.com/sveltejs/language-tools/tree/master/packages/language-server#svelte-language-server) which responds to text editor calls via the [Language Server Protocol standard](https://microsoft.github.io//language-server-protocol/overviews/lsp/overview/). First class TypeScript support means that _both_ of these two systems do a good job of handling TypeScript code.
The Svelte compiler support for TypeScript is handled by [Christian Kaisermann](https://github.com/kaisermann)'s [`svelte-preprocess`](https://github.com/sveltejs/svelte-preprocess#svelte-preprocess) which is now an official Svelte project.
For the editor level, we took inspiration from [Pine's](https://github.com/octref) work in the [Vue](https://vuejs.org) ecosystem via [Vetur](https://github.com/vuejs/vetur). Vetur provides an [LSP](https://github.com/vuejs/vetur/blob/master/server), a VS Code extension and a [CLI](https://github.com/vuejs/vetur/blob/master/vti). Svelte now also has an [LSP](https://github.com/sveltejs/language-tools/blob/master/packages/language-server), a [VS Code extension](https://github.com/sveltejs/language-tools/blob/master/packages/svelte-vscode) and a [CLI](https://github.com/sveltejs/language-tools/blob/master/packages/svelte-check).
#### `*.svelte` Introspection
For the official Svelte VS Code extension, we built off the foundations which [James Birtles](https://github.com/UnwrittenFun) has created in [`UnwrittenFun/svelte-vscode`](https://github.com/UnwrittenFun/svelte-vscode) and [`UnwrittenFun/svelte-language-server`](https://github.com/UnwrittenFun/svelte-language-server/).
[Simon Holthausen](https://github.com/dummdidumm) and [Lyu, Wei-Da](https://github.com/jasonlyu123) have done great work improving the JavaScript and TypeScript introspection, including integrating [@halfnelson](https://github.com/halfnelson)'s [svelte2tsx](https://github.com/sveltejs/language-tools/tree/master/packages/svelte2tsx#svelte2tsx) which powers understanding the props on components in your codebase.
## Adding TypeScript to an existing project
Before getting started, add the dependencies:
```bash
npm install --save-dev @tsconfig/svelte typescript svelte-preprocess svelte-check
```
##### 1. Compiling TypeScript
You first need to set up [`svelte-preprocess`](https://github.com/sveltejs/svelte-preprocess#svelte-preprocess), which passes the contents of your `<script lang="ts">` blocks through the TypeScript compiler.
In a Rollup project, that would look like this — note that we also need to install `@rollup/plugin-typescript` so that Rollup can handle `.ts` files:
```diff
+ import autoPreprocess from 'svelte-preprocess';
+ import typescript from '@rollup/plugin-typescript';
export default {
...,
plugins: [
svelte({
+ preprocess: autoPreprocess()
}),
+ typescript({ sourceMap: !production })
]
}
```
[Full instructions for other environments here](https://github.com/sveltejs/svelte-preprocess#usage).
To configure TypeScript, you will need to create a `tsconfig.json` in the root of your project:
```json
{
"extends": "@tsconfig/svelte/tsconfig.json",
"include": ["src/**/*", "src/node_modules"],
"exclude": ["node_modules/*", "__sapper__/*", "public/*"],
}
```
Your `include`/`exclude` may differ per project — these are defaults that should work across most Svelte projects.
##### 2. Editor Support
Any editor [using an LSP](https://langserver.org/#implementations-client) can be supported. The [VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) extension has been our primary focus, but there is work in progress [on Atom](https://github.com/sveltejs/language-tools/pull/160), and Vim via [coc-svelte](https://github.com/coc-extensions/coc-svelte) has been updated with the latest LSP.
These editor extensions will improve your coding experience even if you only use JavaScript. The editor won't offer errors, but it will offer inference and refactoring tools. You can [add `// @ts-check`](https://www.staging-typescript.org/docs/handbook/intro-to-js-ts.html) to the top of a `<script>` tag using JavaScript to get better error messages with no infra changes.
To switch a `<script>` to use TypeScript, use `<script lang="ts">` and that should be it. Hopefully you won't be seeing an ocean of red squiggles.
##### 3. CI Checks
Having red squiggles is great, well, kinda. On the long run though, you want to be able to verify that there are no errors in your code. To verify your project is error free, you can use the CLI tool [`svelte-check`](https://www.npmjs.com/package/svelte-check). It acts like an editor asking for errors against all of your `.svelte` files.
You can add the dependency to your project and then add it to CI.
```bash
npx svelte-check
Loading svelte-check in workspace: /Users/ortatherox/dev/svelte/example-app
Getting Svelte diagnostics...
====================================
/Users/ortatherox/dev/svelte/example-app/src/App.svelte:3:2
Error: Type '123' is not assignable to type 'string'. (ts)
====================================
svelte-check found 1 error
error Command failed with exit code 1.
```
## What about TypeScript in Sapper projects?
TypeScript support was added to Sapper in 0.28, so if you're using an older version be sure to [upgrade](https://sapper.svelte.dev/migrating#0_27_to_0_28).
## How can I contribute?
We're so glad you asked. The work is happening in the [sveltejs/language-tools](https://github.com/sveltejs/language-tools) repo and in the [#language-tools](https://discord.gg/enV6v8K) channel in the Svelte Discord. If you'd like to report issues, submit fixes, or help out with extensions for new editors and so on, that's where you can find us. See you there!

@ -0,0 +1,85 @@
---
title: What's new in Svelte: October 2020
description: New object methods, in-depth learning resources and tons of integration examples!
author: Daniel Sandoval
authorURL: https://desandoval.net
---
Welcome to the first edition of our "What's new in Svelte" series! We'll try to make this a monthly blog post in which you'll find out about new features, bug fixes, and a showcase of Svelte projects from around the community.
## New features
1. `use:obj.method` allows functions defined within objects to be used within actions ([Example](https://svelte.dev/repl/c305722adb4a4545b27b198ea8ff9bde?version=3.27.0), **3.26.0**, warning removed in **3.27.0**)
2. `_` is now supported as a "numerical separator", similar to a `.` or `,` ([Example](https://svelte.dev/repl/844c39e91d1248649fe54af839fab570?version=3.26.0), **3.26.0**)
3. `import.meta` now works in template expressions ([Example](https://svelte.dev/repl/9630de41957a4c80a4fce264360a6bc7?version=3.26.0), **3.26.0**)
4. CSS Selectors with `~` and `+` combinators are now supported ([Example](https://svelte.dev/repl/91ad9257d2d1430185a504a18cc60172?version=3.29.0), **3.27.0**, with a compiler fix in **3.29.0**)
5. The `{#key}` block is now available to key arbitrary content on an expression. Whever the expression changes, the contents inside the `{#key}` block will be destroyed and recreated. For an in-depth explanation and to find out how it's implemented, check out the [new blog post](https://lihautan.com/contributing-to-svelte-implement-key-block/) of Svelte Team member Tan Li Hau. ([More info](https://github.com/sveltejs/svelte/issues/1469), **3.29.0**)
6. Slots can now be forwarded through child components! This used to only be possible by adding extra wrapper `<div>`s ([More info](https://github.com/sveltejs/svelte/issues/2079), **3.29.0**)
7. When using TypeScript, you can now type the `createEventDispatcher` method:
```html
<script lang="ts">
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher<{
/**
* you can also add docs
*/
checked: boolean; // Will translate to `CustomEvent<boolean>`
hello: string;
}>();
// ...
</script>
```
This will make sure that you can invoke dispatch only with the specified event names and its types. The Svelte for VS Code extension was also updated to deal with this new feature. It will provide strong typings for these events as well as autocompletion and hover information.
**New from Sapper!**
Sapper 0.28.9 just came out. The highlights from it include much better support for CSP nonces, asset preload support for exported pages, and error details are now available in the `$page` store on error pages.
In addition, Sapper's CSS handling has been rewritten over the course of recent releases in order to fix existing CSS handling bugs, refactor the CSS handling to occur entirely within a Rollup plugin, and remove the need internally to register CSS in the routing system. Congrats and thank you to the folks working on Sapper for all their solid work!
## Impactful bug fixes
- CSS compilation will no longer remove rules for the `open` attribute on `<details>` elements ([Example](https://svelte.dev/repl/ab4c0c177d1f4fab92f46eb8539cea9a?version=3.26.0), **3.26.0**)
- `prettier-plugin-svelte` will do a better job now at dealing with whitespaces, especially around inline elements. It will also preserve formatting inside `<pre>` tags and will no longer format languages which are not supported by Prettier, like SASS, Pug or Stylus.
## Coming up
- [Svelte Summit](https://sveltesummit.com/), Svelte's second global online conference, is taking place on October 18! Sign up for free to get reminders and talk updates!
For all the features and bugfixes see the CHANGELOG for [Svelte](https://github.com/sveltejs/svelte/blob/master/CHANGELOG.md) and [Sapper](https://github.com/sveltejs/sapper/blob/master/CHANGELOG.md).
---
## Svelte Showcase
- [This CustomMenu example](https://svelte.dev/repl/3a33725c3adb4f57b46b597f9dade0c1?version=3.25.0) demos how to replace the OS right-click menu
- [Github Tetris](https://svelte.dev/repl/cc1eaa7c66964fedb5e70e3ecbbaa0e1?version=3.25.1) lets you play a Tetris-like game in a git commit history
- [Who are my representatives?](https://whoaremyrepresentatives.us/) is a website built with Svelte to help US residents get more info on their congressional representatives
- [Pick Palette](https://github.com/bluwy/pick-palette) is a color palette manager made with Svelte!
#### In-depth learning:
- [Svelte 3 Up and Running](https://www.amazon.com/dp/B08D6T6BKS/ref=cm_sw_r_tw_dp_x_OQMtFb3GPQCB2) is a new book about building production-ready static web apps with Svelte 3
- [Sapper Tutorial (Crash Course)](https://www.youtube.com/playlist?list=PL4cUxeGkcC9gdr4Qhx83gBBcID-KMe-PQ) walks through the ins-and-outs of Sapper, the Svelte-powered application framework
- [Svelte Society Day France](https://france.sveltesociety.dev/) happened September 27th featuring a wide variety of topics all in French! You can find the full recording [here](https://www.youtube.com/watch?v=aS1TQ155JK4).
#### Plug-and-play components:
- [svelte-zoom](https://github.com/vaheqelyan/svelte-zoom) brings "nearly native" pan-and-zoom to images on desktop and mobile
- [svelte-materialify](https://github.com/TheComputerM/svelte-materialify) is a Material component library for Svelte with over 50 components
- [svelte-undoable](https://github.com/macfja/svelte-undoable) makes it easy to introduce undo and redo functionality using `bind:`
- [This Tilt component](https://svelte.dev/repl/7b23ad9d2693424482cd411b0378b55b?version=3.24.1) implements a common UX pattern where the hovered element tilts to follow the mouse
#### Lots of examples of how use JS tech came out this month:
- [Sapper with PostCSS and Tailwind](https://codechips.me/sapper-with-postcss-and-tailwind/)
- [PrismJS (Code block syntax highlighting)](https://github.com/phptuts/Svelte-PrismJS)
- [Filepond (Drag-and-drop file upload)](https://github.com/pqina/svelte-filepond)
- [Ionic (UI Components)](https://github.com/Tommertom/svelte-ionic-app)
- [Pell (WYSIWYG Editor)](https://github.com/Demonicious/svelte-pell/)
- [Leaflet (Mapping)](https://github.com/anoram/leaflet-svelte)
**Reminder**: There's a [Svelte integrations repo](https://github.com/sveltejs/integrations) that demonstrates ways to incorporate Svelte into your stack (and vice versa). If you've got questions on how to use a particular piece of tech with Svelte, you may find your answer there... and if you've gotten something to work with Svelte, consider contributing!
For more amazing Svelte projects, check out the [Svelte Society](https://sveltesociety.dev/), [Reddit](https://www.reddit.com/r/sveltejs/) and [Discord](https://discord.com/invite/yy75DKs)… and be sure to post your own!
## See you next month!
By the way, Svelte now has an [OpenCollective](https://opencollective.com/svelte)! All contributions and all expenses are published in our transparent public ledger. Learn who is donating, how much, where that money is going, submit expenses, get reimbursed and more!

@ -107,7 +107,7 @@ An element or component can have multiple spread attributes, interspersed with r
---
*`$$props`* references all props that are passed to a component including ones that are not declared with `export`. It is useful in rare cases, but not generally recommended, as it is difficult for Svelte to optimise.
*`$$props`* references all props that are passed to a component, including ones that are not declared with `export`. It is not generally recommended, as it is difficult for Svelte to optimise. But it can be useful in rare cases for example, when you don't know at compile time what props might be passed to a component.
```sv
<Widget {...$$props}/>
@ -115,7 +115,7 @@ An element or component can have multiple spread attributes, interspersed with r
---
*`$$restProps`* contains only the props which are *not* declared with `export`. It can be used to pass down other unknown attributes to an element in a component.
*`$$restProps`* contains only the props which are *not* declared with `export`. It can be used to pass down other unknown attributes to an element in a component. It shares the same optimisation problems as *`$$props`*, and is likewise not recommended.
```html
<input {...$$restProps}>
@ -342,6 +342,33 @@ If you don't care about the pending state, you can also omit the initial block.
{/await}
```
### {#key ...}
```sv
{#key expression}...{/key}
```
Key blocks destroy and recreate their contents when the value of an expression changes.
---
This is useful if you want an element to play its transition whenever a value changes.
```sv
{#key value}
<div transition:fade>{value}</div>
{/key}
```
---
When used around components, this will cause them to be reinstantiated and reinitialised.
```sv
{#key value}
<Component />
{/key}
```
### {@html ...}
@ -471,6 +498,7 @@ The following modifiers are available:
* `preventDefault` — calls `event.preventDefault()` before running the handler
* `stopPropagation` — calls `event.stopPropagation()`, preventing the event reaching the next element
* `passive` — improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so)
* `nonpassive` — explicitly set `passive: false`
* `capture` — fires the handler during the *capture* phase instead of the *bubbling* phase
* `once` — remove the handler after the first time it runs
* `self` — only trigger handler if event.target is the element itself
@ -544,6 +572,21 @@ Numeric input values are coerced; even though `input.value` is a string as far a
<input type="range" bind:value={num}>
```
---
On `<input>` elements with `type="file"`, you can use `bind:files` to get the [`FileList` of selected files](https://developer.mozilla.org/en-US/docs/Web/API/FileList).
```sv
<label for="avatar">Upload a picture:</label>
<input
accept="image/png, image/jpeg"
bind:files
id="avatar"
name="avatar"
type="file"
/>
```
##### Binding `<select>` value
@ -773,7 +816,7 @@ Actions are functions that are called when an element is created. They can retur
---
An action can have parameters. If the returned value has an `update` method, it will be called whenever those parameters change, immediately after Svelte has applied updates to the markup.
An action can have a parameter. If the returned value has an `update` method, it will be called whenever that parameter changes, immediately after Svelte has applied updates to the markup.
> Don't worry about the fact that we're redeclaring the `foo` function for every component instance — Svelte will hoist any functions that don't depend on local state out of the component definition.

@ -547,6 +547,7 @@ Animates the opacity of an element from 0 to the current opacity for `in` transi
* `delay` (`number`, default 0) — milliseconds before starting
* `duration` (`number`, default 400) — milliseconds the transition lasts
* `easing` (`function`, default `linear`) — an [easing function](docs#svelte_easing)
You can see the `fade` transition in action in the [transition tutorial](tutorial/transition).

@ -0,0 +1,37 @@
<script>
let files;
$: if (files) {
// Note that `files` is of type `FileList`, not an Array:
// https://developer.mozilla.org/en-US/docs/Web/API/FileList
console.log(files);
for (const file of files) {
console.log(`${file.name}: ${file.size} bytes`);
}
}
</script>
<label for="avatar">Upload a picture:</label>
<input
accept="image/png, image/jpeg"
bind:files
id="avatar"
name="avatar"
type="file"
/>
<label for="many">Upload multiple files of any type:</label>
<input
bind:files
id="many"
multiple
type="file"
/>
{#if files}
<h2>Selected files:</h2>
{#each Array.from(files) as file}
<p>{file.name} ({file.size} bytes) </p>
{/each}
{/if}

@ -115,8 +115,9 @@
on:mousedown={handleMousedown}
bind:currentTime={time}
bind:duration
bind:paused
></video>
bind:paused>
<track kind="captions"/>
</video>
<div class="controls" style="opacity: {duration && showControls ? 1 : 0}">
<progress value="{(time / duration) || 0}"/>

@ -2,6 +2,6 @@
question: I'm new to Svelte. Where should I start?
---
We think the best way to get started is playing through the interactive [Tutorial](https://svelte.dev/tutorial). Each step there is mainly focused on one specific aspect and is easy to follow. You'll be editing and running real Svelte components right in your browser.
We think the best way to get started is playing through the interactive [Tutorial](tutorial). Each step there is mainly focused on one specific aspect and is easy to follow. You'll be editing and running real Svelte components right in your browser.
Five to ten minutes should be enough to get you up and running. An hour and a half should get you through the entire tutorial.

@ -2,9 +2,17 @@
question: Are there any video courses?
---
There are no official ones, but here are a couple of third-part ones that we know of.
Rich Harris, the creator of Svelte, taught a course:
- [Egghead](https://egghead.io/playlists/getting-started-with-svelte-3-05a8541a)
- [Udemy](https://www.udemy.com/sveltejs-the-complete-guide/)
- [Frontend Masters](https://frontendmasters.com/courses/svelte/)
Note that Udemy very frequently has discounts over 90%.
There are also a number of third-party courses:
- [Egghead](https://egghead.io/browse/frameworks/svelte)
- [Udemy](https://www.udemy.com/courses/search/?q=sveltejs+svelte) (Note: Udemy frequently has discounts over 90%)
- [Pluralsight](https://www.pluralsight.com/search?q=svelte)
Finally, there are also YouTube channels and playlists that teach Svelte:
- [Svelte Master](https://www.youtube.com/channel/UCg6SQd5jnWo5Y70rZD9SQFA)
- [Svelte Tutorial for Beginners](https://www.youtube.com/watch?v=zojEMeQGGHs&list=PL4cUxeGkcC9hlbrVO_2QFVqVPhlZmz7tO) by The Net Ninja

@ -0,0 +1,9 @@
---
question: Are there any books?
---
There are a few books:
- [Svelte Handbook](https://flaviocopes.com/page/download-svelte-handbook/) by Flavio Copes
- [Svelte 3 Up and Running](https://www.amazon.com/dp/B08D6T6BKS/) by Alessandro Segala
- [Svelte and Sapper in Action](https://www.manning.com/books/svelte-and-sapper-in-action) by R. Mark Volkmann

@ -10,3 +10,11 @@ To declare the type of a reactive variable in a Svelte template, you should use
let x: number;
$: x = count + 1;
```
To import a type or interface make sure to use [TypeScript's `type` modifier](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export):
```
import type { SomeInterface } from './SomeFile';
```
You must use the `type` modifier because `svelte-preprocess` doesn't know whether an import is a type or a value — it only transpiles one file at a time without knowledge of the other files and therefore can't safely erase imports which only contain types without this modifier present.

@ -13,7 +13,7 @@ First, you'll need to integrate Svelte with a build tool. There are officially m
Don't worry if you're relatively new to web development and haven't used these tools before. We've prepared a simple step-by-step guide, [Svelte for new developers](blog/svelte-for-new-developers), which walks you through the process.
You'll also want to configure your text editor to treat `.svelte` files the same as `.html` for the sake of syntax highlighting. [Read this guide to learn how](blog/setting-up-your-editor).
You'll also want to configure your text editor. If you're using VS Code, install the [Svelte extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode), otherwise follow [this guide](blog/setting-up-your-editor) to configure your text editor to treat `.svelte` files the same as `.html` for the sake of syntax highlighting.
Then, once you've got your project set up, using Svelte components is easy. The compiler turns each component into a regular JavaScript class — just import it and instantiate with `new`:

@ -2,10 +2,10 @@
title: Spread props
---
If you have an object of properties, you can 'spread' them on to a component instead of specifying each one:
If you have an object of properties, you can 'spread' them onto a component instead of specifying each one:
```html
<Info {...pkg}/>
```
> Conversely, if you need to reference all the props that were passed into a component, including ones that weren't declared with `export`, you can do so by accessing `$$props` directly. It's not generally recommended, as it's difficult for Svelte to optimise, but it's useful in rare cases.
> Conversely, if you need to reference all the props that were passed into a component, including ones that weren't declared with `export`, you can do so by accessing `$$props` directly. It's not generally recommended, as it's difficult for Svelte to optimise, but it's useful in rare cases.

@ -1,6 +1,4 @@
<script>
let promise = getRandomNumber();
async function getRandomNumber() {
const res = await fetch(`tutorial/random-number`);
const text = await res.text();
@ -12,6 +10,8 @@
}
}
let promise = getRandomNumber();
function handleClick() {
promise = getRandomNumber();
}
@ -22,4 +22,4 @@
</button>
<!-- replace this element -->
<p>{promise}</p>
<p>{promise}</p>

@ -1,6 +1,4 @@
<script>
let promise = getRandomNumber();
async function getRandomNumber() {
const res = await fetch(`tutorial/random-number`);
const text = await res.text();
@ -11,6 +9,8 @@
throw new Error(text);
}
}
let promise = getRandomNumber();
function handleClick() {
promise = getRandomNumber();
@ -27,4 +27,4 @@
<p>The number is {number}</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}
{/await}

@ -21,6 +21,7 @@ The full list of modifiers:
* `preventDefault` — calls `event.preventDefault()` before running the handler. Useful for client-side form handling, for example.
* `stopPropagation` — calls `event.stopPropagation()`, preventing the event reaching the next element
* `passive` — improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so)
* `nonpassive` — explicitly set `passive: false`
* `capture` — fires the handler during the *capture* phase instead of the *bubbling* phase ([MDN docs](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture))
* `once` — remove the handler after the first time it runs
* `self` — only trigger handler if event.target is the element itself

@ -112,8 +112,9 @@
poster="https://sveltejs.github.io/assets/caminandes-llamigos.jpg"
src="https://sveltejs.github.io/assets/caminandes-llamigos.mp4"
on:mousemove={handleMousemove}
on:mousedown={handleMousedown}
></video>
on:mousedown={handleMousedown}>
<track kind="captions">
</video>
<div class="controls" style="opacity: {duration && showControls ? 1 : 0}">
<progress value="{(time / duration) || 0}"/>

@ -115,8 +115,9 @@
on:mousedown={handleMousedown}
bind:currentTime={time}
bind:duration
bind:paused
></video>
bind:paused>
<track kind="captions">
</video>
<div class="controls" style="opacity: {duration && showControls ? 1 : 0}">
<progress value="{(time / duration) || 0}"/>

@ -7,23 +7,23 @@
display: block;
}
.active {
.selected {
background-color: #ff3e00;
color: white;
}
</style>
<button
class="{current === 'foo' ? 'active' : ''}"
class="{current === 'foo' ? 'selected' : ''}"
on:click="{() => current = 'foo'}"
>foo</button>
<button
class="{current === 'bar' ? 'active' : ''}"
class="{current === 'bar' ? 'selected' : ''}"
on:click="{() => current = 'bar'}"
>bar</button>
<button
class="{current === 'baz' ? 'active' : ''}"
class="{current === 'baz' ? 'selected' : ''}"
on:click="{() => current = 'baz'}"
>baz</button>

@ -7,23 +7,23 @@
display: block;
}
.active {
.selected {
background-color: #ff3e00;
color: white;
}
</style>
<button
class:active="{current === 'foo'}"
class:selected="{current === 'foo'}"
on:click="{() => current = 'foo'}"
>foo</button>
<button
class:active="{current === 'bar'}"
class:selected="{current === 'bar'}"
on:click="{() => current = 'bar'}"
>bar</button>
<button
class:active="{current === 'baz'}"
class:selected="{current === 'baz'}"
on:click="{() => current = 'baz'}"
>baz</button>

@ -6,7 +6,7 @@ Like any other attribute, you can specify classes with a JavaScript attribute, s
```html
<button
class="{current === 'foo' ? 'active' : ''}"
class="{current === 'foo' ? 'selected' : ''}"
on:click="{() => current = 'foo'}"
>foo</button>
```
@ -15,9 +15,9 @@ This is such a common pattern in UI development that Svelte includes a special d
```html
<button
class:active="{current === 'foo'}"
class:selected="{current === 'foo'}"
on:click="{() => current = 'foo'}"
>foo</button>
```
The `active` class is added to the element whenever the value of the expression is truthy, and removed when it's falsy.
The `selected` class is added to the element whenever the value of the expression is truthy, and removed when it's falsy.

@ -14,7 +14,7 @@ It's useful for things like this folder tree view, where folders can contain *ot
{/if}
```
...but that's impossible, because a file can't import itself. Instead, we use `<svelte:self>`:
...but that's impossible, because a module can't import itself. Instead, we use `<svelte:self>`:
```html
{#if file.type === 'folder'}
@ -22,4 +22,4 @@ It's useful for things like this folder tree view, where folders can contain *ot
{:else}
<File {...file}/>
{/if}
```
```

@ -315,6 +315,12 @@
"@babel/types": "^7.4.4"
}
},
"@babel/helper-validator-identifier": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
"integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
"dev": true
},
"@babel/helper-wrap-function": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz",
@ -1270,6 +1276,168 @@
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.9.tgz",
"integrity": "sha512-VZqSaulg2kVQYMulmuZcvapPwH5/y81YHANiFIKz1GNZoG/F4o1JSeLlrvXJ8tC+RPUjxdrebfT3Qn+bnMi0bA=="
},
"@rollup/plugin-babel": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.2.0.tgz",
"integrity": "sha512-CPABsajaKjINgBQ3it+yMnfVO3ibsrMBxRzbUOUw2cL1hsZJ7aogU8mgglQm3S2hHJgjnAmxPz0Rq7DVdmHsTw==",
"dev": true,
"requires": {
"@babel/helper-module-imports": "^7.10.4",
"@rollup/pluginutils": "^3.1.0"
},
"dependencies": {
"@babel/helper-module-imports": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz",
"integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==",
"dev": true,
"requires": {
"@babel/types": "^7.10.4"
}
},
"@babel/types": {
"version": "7.11.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
"integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.10.4",
"lodash": "^4.17.19",
"to-fast-properties": "^2.0.0"
}
}
}
},
"@rollup/plugin-commonjs": {
"version": "15.0.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-15.0.0.tgz",
"integrity": "sha512-8uAdikHqVyrT32w1zB9VhW6uGwGjhKgnDNP4pQJsjdnyF4FgCj6/bmv24c7v2CuKhq32CcyCwRzMPEElaKkn0w==",
"dev": true,
"requires": {
"@rollup/pluginutils": "^3.1.0",
"commondir": "^1.0.1",
"estree-walker": "^2.0.1",
"glob": "^7.1.6",
"is-reference": "^1.2.1",
"magic-string": "^0.25.7",
"resolve": "^1.17.0"
},
"dependencies": {
"estree-walker": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.1.tgz",
"integrity": "sha512-tF0hv+Yi2Ot1cwj9eYHtxC0jB9bmjacjQs6ZBTj82H8JwUywFuc+7E83NWfNMwHXZc11mjfFcVXPe9gEP4B8dg==",
"dev": true
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"is-reference": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
"integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
"dev": true,
"requires": {
"@types/estree": "*"
}
},
"magic-string": {
"version": "0.25.7",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
"integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
"dev": true,
"requires": {
"sourcemap-codec": "^1.4.4"
}
},
"resolve": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
"integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
"dev": true,
"requires": {
"path-parse": "^1.0.6"
}
}
}
},
"@rollup/plugin-json": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-4.1.0.tgz",
"integrity": "sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==",
"dev": true,
"requires": {
"@rollup/pluginutils": "^3.0.8"
}
},
"@rollup/plugin-node-resolve": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-9.0.0.tgz",
"integrity": "sha512-gPz+utFHLRrd41WMP13Jq5mqqzHL3OXrfj3/MkSyB6UBIcuNt9j60GCbarzMzdf1VHFpOxfQh/ez7wyadLMqkg==",
"dev": true,
"requires": {
"@rollup/pluginutils": "^3.1.0",
"@types/resolve": "1.17.1",
"builtin-modules": "^3.1.0",
"deepmerge": "^4.2.2",
"is-module": "^1.0.0",
"resolve": "^1.17.0"
},
"dependencies": {
"resolve": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
"integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
"dev": true,
"requires": {
"path-parse": "^1.0.6"
}
}
}
},
"@rollup/plugin-replace": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.3.3.tgz",
"integrity": "sha512-XPmVXZ7IlaoWaJLkSCDaa0Y6uVo5XQYHhiMFzOd5qSv5rE+t/UJToPIOE56flKIxBFQI27ONsxb7dqHnwSsjKQ==",
"dev": true,
"requires": {
"@rollup/pluginutils": "^3.0.8",
"magic-string": "^0.25.5"
},
"dependencies": {
"magic-string": {
"version": "0.25.7",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
"integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
"dev": true,
"requires": {
"sourcemap-codec": "^1.4.4"
}
}
}
},
"@rollup/pluginutils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
"integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
"dev": true,
"requires": {
"@types/estree": "0.0.39",
"estree-walker": "^1.0.1",
"picomatch": "^2.2.2"
}
},
"@sindresorhus/slugify": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-0.9.1.tgz",
@ -1281,9 +1449,9 @@
}
},
"@sveltejs/site-kit": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@sveltejs/site-kit/-/site-kit-1.2.0.tgz",
"integrity": "sha512-C7puq+1so3fKPPZAnQJQlKfyCG6FsnSSFSS2LRIhWD8VK2FL5j8Eq7DIKSxUvWbGw1AsxnzO3dIHJWPB7fwjKg==",
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/@sveltejs/site-kit/-/site-kit-1.2.5.tgz",
"integrity": "sha512-fA1YWW4tYOxPRVocx+jF4S2LGamku8xeKx/+J5aY7ZCbwuo/c4VF+T0K7WuQRI8U6Dw3pJqdiCra+xH4TnCGRw==",
"dev": true,
"requires": {
"@sindresorhus/slugify": "^0.9.1",
@ -1291,9 +1459,9 @@
}
},
"@sveltejs/svelte-repl": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.2.0.tgz",
"integrity": "sha512-2vLQnOVrsmn2d2K4a6urGm8OulGGSPhZCGNySSb1H8nOPsgKrdcTt5qoaxNYXgcyVp55Yow2SvXYXsyJKd4KEQ==",
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.2.1.tgz",
"integrity": "sha512-ShNjMdsEAzGLu2PoogJEuWcV47E+1CsO8dNJ2wZcs7xyPsvuswp6KV1jFsBQmWZ+jLqtnRhlo6w2Mf43XOS/Dg==",
"dev": true,
"requires": {
"codemirror": "^5.49.2",
@ -1356,20 +1524,14 @@
}
},
"@types/resolve": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz",
"integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==",
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
"integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"acorn": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
"integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==",
"dev": true
},
"ansi-colors": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
@ -1556,9 +1718,9 @@
"dev": true
},
"clean-css": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
"integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
"integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==",
"dev": true,
"requires": {
"source-map": "~0.6.0"
@ -1573,9 +1735,9 @@
}
},
"clipboard": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz",
"integrity": "sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==",
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz",
"integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==",
"optional": true,
"requires": {
"good-listener": "^1.2.2",
@ -1601,9 +1763,9 @@
"dev": true
},
"codemirror": {
"version": "5.55.0",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.55.0.tgz",
"integrity": "sha512-TumikSANlwiGkdF/Blnu/rqovZ0Y3Jh8yy9TqrPbSM0xxSucq3RgnpVDQ+mD9q6JERJEIT2FMuF/fBGfkhIR/g==",
"version": "5.57.0",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.57.0.tgz",
"integrity": "sha512-WGc6UL7Hqt+8a6ZAsj/f1ApQl3NPvHY/UQSzG6fB6l4BjExgVdhFaxd7mRTw1UCiYe/6q86zHP+kfvBQcZGvUg==",
"dev": true
},
"color-convert": {
@ -1622,9 +1784,15 @@
"dev": true
},
"commander": {
"version": "2.20.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
"integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
"dev": true
},
"concat-map": {
@ -1693,12 +1861,6 @@
}
}
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"dev": true
},
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
@ -1727,6 +1889,12 @@
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
"dev": true
},
"deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
"dev": true
},
"define-properties": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
@ -1865,9 +2033,9 @@
"dev": true
},
"estree-walker": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
"integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
"integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
"dev": true
},
"esutils": {
@ -1950,6 +2118,13 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"fsevents": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
"dev": true,
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@ -2178,15 +2353,6 @@
"integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=",
"dev": true
},
"is-reference": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.3.tgz",
"integrity": "sha512-W1iHHv/oyBb2pPxkBxtaewxa1BC58Pn5J0hogyCdefwUIvb6R+TGbAcIa4qPNYLqLhb3EnOgUf2MQkkF76BcKw==",
"dev": true,
"requires": {
"@types/estree": "0.0.39"
}
},
"is-regex": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
@ -2211,12 +2377,6 @@
"has-symbols": "^1.0.0"
}
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"dev": true
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@ -2224,22 +2384,29 @@
"dev": true
},
"jest-worker": {
"version": "24.6.0",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.6.0.tgz",
"integrity": "sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ==",
"version": "26.3.0",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.3.0.tgz",
"integrity": "sha512-Vmpn2F6IASefL+DVBhPzI2J9/GJUsqzomdeN+P+dK8/jKxbh8R3BtFnx3FIta7wYlPU62cpJMJQo4kuOowcMnw==",
"dev": true,
"requires": {
"merge-stream": "^1.0.1",
"supports-color": "^6.1.0"
"@types/node": "*",
"merge-stream": "^2.0.0",
"supports-color": "^7.0.0"
},
"dependencies": {
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"supports-color": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
"has-flag": "^4.0.0"
}
}
}
@ -2474,15 +2641,6 @@
"integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=",
"dev": true
},
"magic-string": {
"version": "0.25.2",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.2.tgz",
"integrity": "sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg==",
"dev": true,
"requires": {
"sourcemap-codec": "^1.4.4"
}
},
"map-age-cleaner": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
@ -2493,9 +2651,9 @@
}
},
"marked": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz",
"integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg=="
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/marked/-/marked-1.1.1.tgz",
"integrity": "sha512-mJzT8D2yPxoPh7h0UXkB+dBj4FykPJ2OIfxAWeIHrvoHDkFxukV/29QxoFQoPM6RLEwhIFdJpmKBlqVM3s2ZIw=="
},
"mem": {
"version": "4.3.0",
@ -2515,18 +2673,15 @@
"dev": true
},
"merge-stream": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz",
"integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=",
"dev": true,
"requires": {
"readable-stream": "^2.0.1"
}
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
"dev": true
},
"mime": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
"integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
"version": "2.4.6",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz",
"integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA=="
},
"mimic-fn": {
"version": "2.1.0",
@ -2702,9 +2857,9 @@
}
},
"node-fetch": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==",
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
"dev": true
},
"node-pg-migrate": {
@ -3105,6 +3260,12 @@
"integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==",
"dev": true
},
"picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
"dev": true
},
"pidtree": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz",
@ -3170,9 +3331,9 @@
"integrity": "sha512-plS7uY0WWiTBwWZs9KM3M88ZxHWKbrbMUDf52CPum6BqAxiLmKROmaTnmhXtv0krQ0l0HRLcFS8JDwOFyPt/OQ=="
},
"prismjs": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.17.1.tgz",
"integrity": "sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q==",
"version": "1.21.0",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.21.0.tgz",
"integrity": "sha512-uGdSIu1nk3kej2iZsLyDoJ7e9bnPzIgY0naW/HdknGj61zScaprVEVGHrPoXqI+M9sP0NDnTK2jpkvmldpuqDw==",
"requires": {
"clipboard": "^2.0.0"
}
@ -3189,12 +3350,6 @@
"integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=",
"dev": true
},
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true
},
"pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
@ -3205,6 +3360,15 @@
"once": "^1.3.1"
}
},
"randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
"requires": {
"safe-buffer": "^5.1.0"
}
},
"read-pkg": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
@ -3216,21 +3380,6 @@
"path-type": "^3.0.0"
}
},
"readable-stream": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"dev": true,
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"rechoir": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
@ -3361,121 +3510,74 @@
}
},
"rollup": {
"version": "1.21.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-1.21.2.tgz",
"integrity": "sha512-sCAHlcQ/PExU5t/kRwkEWHdhGmQrZ2IgdQzbjPVNfhWbKHMMZGYqkASVTpQqRPLtQKg15xzEscc+BnIK/TE7/Q==",
"dev": true,
"requires": {
"@types/estree": "0.0.39",
"@types/node": "^12.7.4",
"acorn": "^7.0.0"
},
"dependencies": {
"@types/node": {
"version": "12.7.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.4.tgz",
"integrity": "sha512-W0+n1Y+gK/8G2P/piTkBBN38Qc5Q1ZSO6B5H3QmPCUewaiXOo2GCAWZ4ElZCcNhjJuBSUSLGFUJnmlCn5+nxOQ==",
"dev": true
}
}
},
"rollup-plugin-babel": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.3.3.tgz",
"integrity": "sha512-tKzWOCmIJD/6aKNz0H1GMM+lW1q9KyFubbWzGiOG540zxPPifnEAHTZwjo0g991Y+DyOZcLqBgqOdqazYE5fkw==",
"dev": true,
"requires": {
"@babel/helper-module-imports": "^7.0.0",
"rollup-pluginutils": "^2.8.1"
}
},
"rollup-plugin-commonjs": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz",
"integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==",
"version": "2.26.10",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.26.10.tgz",
"integrity": "sha512-dUnjCWOA0h9qNX6qtcHidyatz8FAFZxVxt1dbcGtKdlJkpSxGK3G9+DLCYvtZr9v94D129ij9zUhG+xbRoqepw==",
"dev": true,
"requires": {
"estree-walker": "^0.6.1",
"is-reference": "^1.1.2",
"magic-string": "^0.25.2",
"resolve": "^1.11.0",
"rollup-pluginutils": "^2.8.1"
"fsevents": "~2.1.2"
}
},
"rollup-plugin-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz",
"integrity": "sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==",
"rollup-plugin-svelte": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-6.0.0.tgz",
"integrity": "sha512-y9qtWa+iNYwXdOZqaEqz3i6k3gzofC9JXzv+WVKDOt0DLiJxJaSrlKKf4YkKG91RzTK5Lo+0fW8in9QH/DxEhA==",
"dev": true,
"requires": {
"rollup-pluginutils": "^2.5.0"
"require-relative": "^0.8.7",
"rollup-pluginutils": "^2.8.2",
"sourcemap-codec": "^1.4.8"
}
},
"rollup-plugin-node-resolve": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz",
"integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==",
"rollup-plugin-terser": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.1.tgz",
"integrity": "sha512-HL0dgzSxBYG/Ly9i/E5Sc+PuKKZ0zBzk11VmLCfdUtpqH4yYqkLclPkTqRy85FU9246yetImOClaQ/ufnj08vg==",
"dev": true,
"requires": {
"@types/resolve": "0.0.8",
"builtin-modules": "^3.1.0",
"is-module": "^1.0.0",
"resolve": "^1.11.1",
"rollup-pluginutils": "^2.8.1"
"@babel/code-frame": "^7.10.4",
"jest-worker": "^26.2.1",
"serialize-javascript": "^4.0.0",
"terser": "^5.0.0"
},
"dependencies": {
"resolve": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz",
"integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==",
"@babel/code-frame": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
"integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
"dev": true,
"requires": {
"path-parse": "^1.0.6"
"@babel/highlight": "^7.10.4"
}
},
"@babel/highlight": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
"integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.10.4",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
}
}
}
},
"rollup-plugin-replace": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-replace/-/rollup-plugin-replace-2.2.0.tgz",
"integrity": "sha512-/5bxtUPkDHyBJAKketb4NfaeZjL5yLZdeUihSfbF2PQMz+rSTEb8ARKoOl3UBT4m7/X+QOXJo3sLTcq+yMMYTA==",
"dev": true,
"requires": {
"magic-string": "^0.25.2",
"rollup-pluginutils": "^2.6.0"
}
},
"rollup-plugin-svelte": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-5.1.0.tgz",
"integrity": "sha512-4MRZG29dAWDpoxEs5uIHzDnYafQEOLaKIJAuDYUtFIzEm1F1IGSTlFyjd8/qk4wltlHdu6V7YfZY53+CKryhMg==",
"dev": true,
"requires": {
"require-relative": "^0.8.7",
"rollup-pluginutils": "^2.3.3",
"sourcemap-codec": "^1.4.4"
}
},
"rollup-plugin-terser": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.1.1.tgz",
"integrity": "sha512-McIMCDEY8EU6Y839C09UopeRR56wXHGdvKKjlfiZG/GrP6wvZQ62u2ko/Xh1MNH2M9WDL+obAAHySljIZYCuPQ==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"jest-worker": "^24.6.0",
"rollup-pluginutils": "^2.8.1",
"serialize-javascript": "^1.7.0",
"terser": "^4.1.0"
}
},
"rollup-pluginutils": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.1.tgz",
"integrity": "sha512-J5oAoysWar6GuZo0s+3bZ6sVZAC0pfqKz68De7ZgDi5z63jOVZn1uJL/+z1jeKHNbGII8kAyHF5q8LnxSX5lQg==",
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
"integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
"dev": true,
"requires": {
"estree-walker": "^0.6.1"
},
"dependencies": {
"estree-walker": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
"integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
"dev": true
}
}
},
"safe-buffer": {
@ -3495,9 +3597,9 @@
}
},
"sapper": {
"version": "0.27.11",
"resolved": "https://registry.npmjs.org/sapper/-/sapper-0.27.11.tgz",
"integrity": "sha512-5EaPZhlc8OnyN3UCI6dRSM1Gz5sxyzLZG/1z5nMvZhg9Ng+rSvEvJx/rW/tSHcnQPa8or7+YcbfvQHKS5oPHiw==",
"version": "0.27.16",
"resolved": "https://registry.npmjs.org/sapper/-/sapper-0.27.16.tgz",
"integrity": "sha512-q8dohkbhga6xO+0a8h84odFyoilQ0D0vJtF8NHra/DQmSeN2R2MXUfwhw3EyvLms3T1x8H3v+qw642Qf5JXA9g==",
"dev": true,
"requires": {
"html-minifier": "^4.0.0",
@ -3505,14 +3607,6 @@
"shimport": "^1.0.1",
"sourcemap-codec": "^1.4.6",
"string-hash": "^1.1.3"
},
"dependencies": {
"sourcemap-codec": {
"version": "1.4.6",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz",
"integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==",
"dev": true
}
}
},
"sax": {
@ -3533,10 +3627,13 @@
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA=="
},
"serialize-javascript": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz",
"integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==",
"dev": true
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
"dev": true,
"requires": {
"randombytes": "^2.1.0"
}
},
"set-blocking": {
"version": "2.0.0",
@ -3595,9 +3692,9 @@
"dev": true
},
"sirv": {
"version": "1.0.0-next.2",
"resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.0-next.2.tgz",
"integrity": "sha512-hWp0todr4jSb1BFBiANRmqYRXzX02l36/X4tyHPYKqMZ+e1hrDZKUjIIXrAOBRWlAE/G5cGImUciMrUcU8DeOg==",
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.6.tgz",
"integrity": "sha512-LRGu7Op4Xl9hhigOy2kcB53zAYTjNDdpooey49dIU0cMdpOv9ithVf7nstk3jvs8EhMiT/VORoyazZYGgw4vnA==",
"requires": {
"@polka/url": "^1.0.0-next.9",
"mime": "^2.3.1",
@ -3611,9 +3708,9 @@
"dev": true
},
"source-map-support": {
"version": "0.5.12",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz",
"integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==",
"version": "0.5.19",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
"dev": true,
"requires": {
"buffer-from": "^1.0.0",
@ -3629,9 +3726,9 @@
}
},
"sourcemap-codec": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz",
"integrity": "sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg==",
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
"dev": true
},
"spdx-correct": {
@ -3718,15 +3815,6 @@
"function-bind": "^1.1.1"
}
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"requires": {
"safe-buffer": "~5.1.0"
}
},
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
@ -3791,9 +3879,9 @@
}
},
"terser": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-4.1.2.tgz",
"integrity": "sha512-jvNoEQSPXJdssFwqPSgWjsOrb+ELoE+ILpHPKXC83tIxOlh2U75F1KuB2luLD/3a6/7K3Vw5pDn+hvu0C4AzSw==",
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.3.0.tgz",
"integrity": "sha512-XTT3D3AwxC54KywJijmY2mxZ8nJiEjBHVYzq8l9OaYuRFWeQNBwvipuzzYEP4e+/AVcd1hqG/CqgsdIRyT45Fg==",
"dev": true,
"requires": {
"commander": "^2.20.0",
@ -3839,9 +3927,9 @@
"dev": true
},
"totalist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/totalist/-/totalist-1.0.1.tgz",
"integrity": "sha512-HuAt9bWDCdLkebrIQr+i63NgQSvjeD2VTNUIEBqof/4pG4Gb6omuBOMUX0vF371cbfImXQzmb4Ue/0c9MUWGew=="
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz",
"integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g=="
},
"trim-right": {
"version": "1.0.1",
@ -3858,22 +3946,10 @@
}
},
"uglify-js": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz",
"integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==",
"dev": true,
"requires": {
"commander": "~2.20.0",
"source-map": "~0.6.1"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}
}
"version": "3.10.4",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.4.tgz",
"integrity": "sha512-kBFT3U4Dcj4/pJ52vfjCSfyLyvG9VYYuGYPmrPvAxRw/i7xHiT4VvCev+uiEMcEEiu6UNB6KgWmGtSUYIWScbw==",
"dev": true
},
"unicode-canonical-property-names-ecmascript": {
"version": "1.0.4",
@ -3918,12 +3994,6 @@
"pako": "^1.0.5"
}
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true
},
"util.promisify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",

@ -4,9 +4,9 @@
"description": "Docs and examples for Svelte",
"scripts": {
"dev": "npm run copy-workers && sapper dev",
"copy-workers": "rm -rf static/workers && cp -r node_modules/@sveltejs/svelte-repl/workers static",
"copy-workers": "node scripts/copy-workers.js",
"migrate": "node-pg-migrate -r dotenv/config",
"sapper": "npm run copy-workers && sapper build --legacy",
"build": "npm run copy-workers && sapper build --legacy",
"update": "node scripts/update_template.js && node scripts/get-contributors.js && node scripts/update_whos_using.js",
"start": "node __sapper__/build",
"test": "mocha -r esm test/**",
@ -21,12 +21,12 @@
"flru": "^1.0.2",
"httpie": "^1.1.2",
"jsonwebtoken": "^8.5.1",
"marked": "^0.7.0",
"marked": "^1.0.0",
"pg": "^7.12.1",
"polka": "^1.0.0-next.9",
"prism-svelte": "^0.4.3",
"prismjs": "^1.17.1",
"sirv": "^1.0.0-next.2",
"prismjs": "^1.21.0",
"sirv": "^1.0.0",
"yootils": "0.0.16"
},
"devDependencies": {
@ -35,26 +35,26 @@
"@babel/plugin-transform-runtime": "^7.6.0",
"@babel/preset-env": "^7.6.0",
"@babel/runtime": "^7.6.0",
"@rollup/plugin-babel": "^5.0.0",
"@rollup/plugin-commonjs": "^15.0.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^9.0.0",
"@rollup/plugin-replace": "^2.2.0",
"@sindresorhus/slugify": "^0.9.1",
"@sveltejs/site-kit": "^1.2.0",
"@sveltejs/svelte-repl": "^0.2.0",
"@sveltejs/site-kit": "^1.2.5",
"@sveltejs/svelte-repl": "^0.2.1",
"degit": "^2.1.4",
"dotenv": "^8.1.0",
"esm": "^3.2.25",
"jimp": "^0.8.0",
"mocha": "^6.2.0",
"node-fetch": "^2.6.0",
"node-fetch": "^2.6.1",
"node-pg-migrate": "^3.22.0",
"npm-run-all": "^4.1.5",
"rollup": "^1.21.2",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-json": "^4.0.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-svelte": "^5.1.0",
"rollup-plugin-terser": "^5.1.1",
"sapper": "^0.27.11",
"rollup": "^2.26.10",
"rollup-plugin-svelte": "^6.0.0",
"rollup-plugin-terser": "^7.0.0",
"sapper": "^0.27.16",
"shelljs": "^0.8.3",
"svelte": "^3.12.0"
},

@ -1,10 +1,10 @@
import 'dotenv/config';
import resolve from 'rollup-plugin-node-resolve';
import replace from 'rollup-plugin-replace';
import commonjs from 'rollup-plugin-commonjs';
import babel from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import replace from '@rollup/plugin-replace';
import resolve from '@rollup/plugin-node-resolve';
import svelte from 'rollup-plugin-svelte';
import babel from 'rollup-plugin-babel';
import json from 'rollup-plugin-json';
import { terser } from 'rollup-plugin-terser';
import config from 'sapper/config/rollup.js';
import pkg from './package.json';
@ -44,7 +44,7 @@ export default {
legacy && babel({
extensions: ['.js', '.mjs', '.html', '.svelte'],
runtimeHelpers: true,
babelHelpers: 'runtime',
exclude: ['node_modules/@babel/**'],
presets: [
['@babel/preset-env', {
@ -63,6 +63,8 @@ export default {
module: true
})
],
preserveEntrySignatures: false,
onwarn
},
@ -91,6 +93,8 @@ export default {
require('module').builtinModules || Object.keys(process.binding('natives'))
)
],
preserveEntrySignatures: 'strict',
onwarn
},
@ -105,6 +109,9 @@ export default {
}),
commonjs(),
!dev && terser()
]
],
preserveEntrySignatures: false,
onwarn
}
};

@ -0,0 +1,4 @@
const sh = require('shelljs');
sh.rm('-rf', 'static/workers');
sh.cp('-r', 'node_modules/@sveltejs/svelte-repl/workers', 'static');

@ -5,8 +5,8 @@
<style>
.input-output-toggle {
display: grid;
position: absolute;
user-select: none;
flex: 0;
grid-template-columns: 1fr 40px 1fr;
grid-gap: 0.5em;
align-items: center;

@ -89,6 +89,8 @@
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
background-color: var(--back);
overflow: hidden;
box-sizing: border-box;
@ -98,6 +100,7 @@
.viewport {
width: 100%;
height: 100%;
flex: 1;
}
.mobile .viewport {

@ -137,6 +137,15 @@
top: calc((var(--h3) - 24px) / 2);
}
.post :global(a) {
padding: 0;
transition: none;
}
.post :global(a):not(:hover) {
border: none;
}
@media (max-width: 768px) {
.post :global(.anchor) {
transform: scale(0.6);

@ -8,6 +8,18 @@ function formatPubdate(str) {
return `${d} ${months[+m]} ${y} 12:00 +0000`;
}
function escapeHTML(html) {
const chars = {
'"' : 'quot',
"'": '#39',
'&': 'amp',
'<' : 'lt',
'>' : 'gt'
};
return html.replace(/["'&<>]/g, c => `&${chars[c]};`);
}
const rss = `
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
@ -23,9 +35,9 @@ const rss = `
</image>
${get_posts().filter(post => !post.metadata.draft).map(post => `
<item>
<title>${post.metadata.title}</title>
<title>${escapeHTML(post.metadata.title)}</title>
<link>https://svelte.dev/blog/${post.slug}</link>
<description>${post.metadata.description}</description>
<description>${escapeHTML(post.metadata.description)}</description>
<pubDate>${formatPubdate(post.metadata.pubdate)}</pubDate>
</item>
`).join('')}

@ -228,6 +228,7 @@ export default app;` });
background-color: var(--second);
color: white;
white-space: nowrap;
flex: 0;
}
.icon {

@ -125,6 +125,8 @@
padding: var(--app-controls-h) 0 0 0;
/* margin: 0 calc(var(--side-nav) * -1); */
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.viewport {
@ -136,6 +138,7 @@
width: 200%;
height: calc(100% - 42px);
transition: transform 0.3s;
flex: 1;
}
.mobile .offset {

@ -27,6 +27,8 @@
overflow: hidden;
box-sizing: border-box;
--pane-controls-h: 4.2rem;
display: flex;
flex-direction: column;
}
</style>

@ -1,6 +1,7 @@
import { langs } from '@sveltejs/site-kit/utils/markdown.js';
import PrismJS from 'prismjs';
import 'prismjs/components/prism-bash';
import 'prismjs/components/prism-diff';
import 'prism-svelte';
export function highlight(source, lang) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

@ -8,7 +8,7 @@ import {
create_scopes,
extract_names,
Scope,
extract_identifiers,
extract_identifiers
} from './utils/scope';
import Stylesheet from './css/Stylesheet';
import { test } from '../config';
@ -29,6 +29,7 @@ import add_to_set from './utils/add_to_set';
import check_graph_for_cycles from './utils/check_graph_for_cycles';
import { print, x, b } from 'code-red';
import { is_reserved_keyword } from './utils/reserved_keywords';
import Element from './nodes/Element';
interface ComponentOptions {
namespace?: string;
@ -85,6 +86,7 @@ export default class Component {
file: string;
locate: (c: number) => { line: number; column: number };
elements: Element[] = [];
stylesheet: Stylesheet;
aliases: Map<string, Identifier> = new Map();
@ -155,7 +157,7 @@ export default class Component {
) || { start: 0, end: 0 };
this.warn(svelteOptions, {
code: 'custom-element-no-tag',
message: `No custom element 'tag' option was specified. To automatically register a custom element, specify a name with a hyphen in it, e.g. <svelte:options tag="my-thing"/>. To hide this warning, use <svelte:options tag={null}/>`,
message: 'No custom element \'tag\' option was specified. To automatically register a custom element, specify a name with a hyphen in it, e.g. <svelte:options tag="my-thing"/>. To hide this warning, use <svelte:options tag={null}/>'
});
}
this.tag = this.component_options.tag || compile_options.tag;
@ -171,8 +173,8 @@ export default class Component {
this.walk_instance_js_post_template();
this.elements.forEach(element => this.stylesheet.apply(element));
if (!compile_options.customElement) this.stylesheet.reify();
this.stylesheet.warn_on_unused_selectors(this);
}
@ -190,7 +192,7 @@ export default class Component {
this.add_var({
name,
injected: true,
referenced: true,
referenced: true
});
} else if (name[0] === '$') {
this.add_var({
@ -198,7 +200,7 @@ export default class Component {
injected: true,
referenced: true,
mutated: true,
writable: true,
writable: true
});
const subscribable_name = name.slice(1);
@ -221,6 +223,10 @@ export default class Component {
return this.aliases.get(name);
}
apply_stylesheet(element: Element) {
this.elements.push(element);
}
global(name: string) {
const alias = this.alias(name);
this.globals.set(name, alias);
@ -235,7 +241,7 @@ export default class Component {
const { compile_options, name } = this;
const { format = 'esm' } = compile_options;
const banner = `${this.file ? `${this.file} ` : ``}generated by Svelte v${'__VERSION__'}`;
const banner = `${this.file ? `${this.file} ` : ''}generated by Svelte v${'__VERSION__'}`;
const program: any = { type: 'Program', body: result.js };
@ -289,7 +295,7 @@ export default class Component {
}
const imported_helpers = Array.from(this.helpers, ([name, alias]) => ({
name,
alias,
alias
}));
create_module(
@ -305,7 +311,7 @@ export default class Component {
.filter(variable => variable.module && variable.export_name)
.map(variable => ({
name: variable.name,
as: variable.export_name,
as: variable.export_name
}))
);
@ -342,9 +348,9 @@ export default class Component {
reassigned: v.reassigned || false,
referenced: v.referenced || false,
writable: v.writable || false,
referenced_from_script: v.referenced_from_script || false,
referenced_from_script: v.referenced_from_script || false
})),
stats: this.stats.render(),
stats: this.stats.render()
};
}
@ -409,7 +415,7 @@ export default class Component {
source: this.source,
start: pos.start,
end: pos.end,
filename: this.compile_options.filename,
filename: this.compile_options.filename
});
}
@ -441,7 +447,7 @@ export default class Component {
pos: pos.start,
filename: this.compile_options.filename,
toString: () =>
`${warning.message} (${start.line}:${start.column})\n${frame}`,
`${warning.message} (${start.line}:${start.column})\n${frame}`
});
}
@ -452,16 +458,16 @@ export default class Component {
extract_exports(node) {
if (node.type === 'ExportDefaultDeclaration') {
this.error(node, {
code: `default-export`,
message: `A component cannot have a default export`,
code: 'default-export',
message: 'A component cannot have a default export'
});
}
if (node.type === 'ExportNamedDeclaration') {
if (node.source) {
this.error(node, {
code: `not-implemented`,
message: `A component currently cannot have an export ... from`,
code: 'not-implemented',
message: 'A component currently cannot have an export ... from'
});
}
if (node.declaration) {
@ -472,7 +478,7 @@ export default class Component {
variable.export_name = name;
if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
this.warn(declarator, {
code: `unused-export-let`,
code: 'unused-export-let',
message: `${this.name.name} has unused export property '${name}'. If it is for external reference only, please consider using \`export const ${name}\``
});
}
@ -495,7 +501,7 @@ export default class Component {
if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
this.warn(specifier, {
code: `unused-export-let`,
code: 'unused-export-let',
message: `${this.name.name} has unused export property '${specifier.exported.name}'. If it is for external reference only, please consider using \`export const ${specifier.exported.name}\``
});
}
@ -515,8 +521,7 @@ export default class Component {
if (this.hoistable_nodes.has(node)) return false;
if (this.reactive_declaration_nodes.has(node)) return false;
if (node.type === 'ImportDeclaration') return false;
if (node.type === 'ExportDeclaration' && node.specifiers.length > 0)
return false;
if (node.type === 'ExportDeclaration' && node.specifiers.length > 0) return false;
return true;
});
}
@ -531,10 +536,10 @@ export default class Component {
if (node.type === 'LabeledStatement' && node.label.name === '$') {
component.warn(node as any, {
code: 'module-script-reactive-declaration',
message: '$: has no effect in a module script',
message: '$: has no effect in a module script'
});
}
},
}
});
const { scope, globals } = create_scopes(script.content);
@ -544,7 +549,7 @@ export default class Component {
if (name[0] === '$') {
this.error(node as any, {
code: 'illegal-declaration',
message: `The $ prefix is reserved, and cannot be used for variable and import names`,
message: 'The $ prefix is reserved, and cannot be used for variable and import names'
});
}
@ -562,7 +567,7 @@ export default class Component {
if (name[0] === '$') {
this.error(node as any, {
code: 'illegal-subscription',
message: `Cannot reference store value inside <script context="module">`,
message: 'Cannot reference store value inside <script context="module">'
});
} else {
this.add_var({
@ -623,16 +628,18 @@ export default class Component {
if (name[0] === '$') {
this.error(node as any, {
code: 'illegal-declaration',
message: `The $ prefix is reserved, and cannot be used for variable and import names`,
message: 'The $ prefix is reserved, and cannot be used for variable and import names'
});
}
const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
const imported = node.type.startsWith('Import');
this.add_var({
name,
initialised: instance_scope.initialised_declarations.has(name),
writable
writable,
imported
});
this.node_for_declaration.set(name, node);
@ -647,12 +654,12 @@ export default class Component {
injected: true,
writable: true,
reassigned: true,
initialised: true,
initialised: true
});
} else if (is_reserved_keyword(name)) {
this.add_var({
name,
injected: true,
injected: true
});
} else if (name[0] === '$') {
if (name === '$' || name[1] === '$') {
@ -666,7 +673,7 @@ export default class Component {
name,
injected: true,
mutated: true,
writable: true,
writable: true
});
this.add_reference(name.slice(1));
@ -764,7 +771,7 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
},
}
});
for (const [parent, prop, index] of to_remove) {
@ -832,7 +839,7 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
},
}
});
}
@ -844,7 +851,7 @@ export default class Component {
) {
this.warn(node as any, {
code: 'non-top-level-reactive-declaration',
message: '$: has no effect outside of the top-level',
message: '$: has no effect outside of the top-level'
});
}
@ -859,8 +866,8 @@ export default class Component {
if (name[1] !== '$' && scope.has(name.slice(1)) && scope.find_owner(name.slice(1)) !== this.instance_scope) {
this.error(node, {
code: `contextual-store`,
message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
code: 'contextual-store',
message: 'Stores must be declared at the top level of the component (this may change in a future version of Svelte)'
});
}
}
@ -881,7 +888,7 @@ export default class Component {
if (node.body.type !== 'BlockStatement') {
node.body = {
type: 'BlockStatement',
body: [node.body],
body: [node.body]
};
}
node.body.body.push(inside[0]);
@ -890,8 +897,8 @@ export default class Component {
type: 'BlockStatement',
body: [
before[0],
node,
],
node
]
};
}
return null;
@ -927,7 +934,7 @@ export default class Component {
// TODO is this still true post-#3539?
component.error(declarator as any, {
code: 'destructured-prop',
message: `Cannot declare props in destructured declaration`,
message: 'Cannot declare props in destructured declaration'
});
}
@ -947,12 +954,6 @@ export default class Component {
const variable = component.var_lookup.get(name);
if (variable.export_name && variable.writable) {
const insert = variable.subscribable
? get_insert(variable)
: null;
parent[key].splice(index + 1, 0, insert);
declarator.id = {
type: 'ObjectPattern',
properties: [{
@ -973,7 +974,9 @@ export default class Component {
};
declarator.init = x`$$props`;
} else if (variable.subscribable) {
}
if (variable.subscribable && declarator.init) {
const insert = get_insert(variable);
parent[key].splice(index + 1, 0, ...insert);
}
@ -990,7 +993,7 @@ export default class Component {
if (node.type === 'ExportNamedDeclaration' && node.declaration) {
(parent as Program).body[index] = node.declaration;
}
},
}
});
}
@ -1004,7 +1007,7 @@ export default class Component {
hoistable_nodes,
var_lookup,
injected_reactive_declaration_vars,
imports,
imports
} = this;
const top_level_function_declarations = new Map();
@ -1034,8 +1037,9 @@ export default class Component {
this.vars.find(
variable => variable.name === name && variable.module
)
)
) {
return false;
}
return true;
});
@ -1136,7 +1140,7 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
},
}
});
checked.add(fn_declaration);
@ -1229,7 +1233,7 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
},
}
});
const { expression } = node.body as ExpressionStatement;
@ -1239,7 +1243,7 @@ export default class Component {
assignees,
dependencies,
node,
declaration,
declaration
});
}
});
@ -1284,8 +1288,9 @@ export default class Component {
declaration.dependencies.forEach(name => {
if (declaration.assignees.has(name)) return;
const earlier_declarations = lookup.get(name);
if (earlier_declarations)
if (earlier_declarations) {
earlier_declarations.forEach(add_declaration);
}
});
this.reactive_declarations.push(declaration);
@ -1315,12 +1320,13 @@ export default class Component {
if (globals.has(name) && node.type !== 'InlineComponent') return;
let message = `'${name}' is not defined`;
if (!this.ast.instance)
if (!this.ast.instance) {
message += `. Consider adding a <script> block with 'export let ${name}' to declare a prop`;
}
this.warn(node, {
code: 'missing-declaration',
message,
message
});
}
@ -1343,7 +1349,7 @@ function process_component_options(component: Component, nodes) {
'accessors' in component.compile_options
? component.compile_options.accessors
: !!component.compile_options.customElement,
preserveWhitespace: !!component.compile_options.preserveWhitespace,
preserveWhitespace: !!component.compile_options.preserveWhitespace
};
const node = nodes.find(node => node.name === 'svelte:options');
@ -1375,23 +1381,24 @@ function process_component_options(component: Component, nodes) {
switch (name) {
case 'tag': {
const code = 'invalid-tag-attribute';
const message = `'tag' must be a string literal`;
const message = "'tag' must be a string literal";
const tag = get_value(attribute, code, message);
if (typeof tag !== 'string' && tag !== null)
if (typeof tag !== 'string' && tag !== null) {
component.error(attribute, { code, message });
}
if (tag && !/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) {
component.error(attribute, {
code: `invalid-tag-property`,
message: `tag name must be two or more words joined by the '-' character`,
code: 'invalid-tag-property',
message: "tag name must be two or more words joined by the '-' character"
});
}
if (tag && !component.compile_options.customElement) {
component.warn(attribute, {
code: 'missing-custom-element-compile-options',
message: `The 'tag' option is used when generating a custom element. Did you forget the 'customElement: true' compile option?`
message: "The 'tag' option is used when generating a custom element. Did you forget the 'customElement: true' compile option?"
});
}
@ -1401,23 +1408,24 @@ function process_component_options(component: Component, nodes) {
case 'namespace': {
const code = 'invalid-namespace-attribute';
const message = `The 'namespace' attribute must be a string literal representing a valid namespace`;
const message = "The 'namespace' attribute must be a string literal representing a valid namespace";
const ns = get_value(attribute, code, message);
if (typeof ns !== 'string')
if (typeof ns !== 'string') {
component.error(attribute, { code, message });
}
if (valid_namespaces.indexOf(ns) === -1) {
const match = fuzzymatch(ns, valid_namespaces);
if (match) {
component.error(attribute, {
code: `invalid-namespace-property`,
message: `Invalid namespace '${ns}' (did you mean '${match}'?)`,
code: 'invalid-namespace-property',
message: `Invalid namespace '${ns}' (did you mean '${match}'?)`
});
} else {
component.error(attribute, {
code: `invalid-namespace-property`,
message: `Invalid namespace '${ns}'`,
code: 'invalid-namespace-property',
message: `Invalid namespace '${ns}'`
});
}
}
@ -1433,8 +1441,9 @@ function process_component_options(component: Component, nodes) {
const message = `${name} attribute must be true or false`;
const value = get_value(attribute, code, message);
if (typeof value !== 'boolean')
if (typeof value !== 'boolean') {
component.error(attribute, { code, message });
}
component_options[name] = value;
break;
@ -1442,14 +1451,14 @@ function process_component_options(component: Component, nodes) {
default:
component.error(attribute, {
code: `invalid-options-attribute`,
message: `<svelte:options> unknown attribute`,
code: 'invalid-options-attribute',
message: '<svelte:options> unknown attribute'
});
}
} else {
component.error(attribute, {
code: `invalid-options-attribute`,
message: `<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes`,
code: 'invalid-options-attribute',
message: "<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes"
});
}
});

@ -4,12 +4,24 @@ import { gather_possible_values, UNKNOWN } from './gather_possible_values';
import { CssNode } from './interfaces';
import Component from '../Component';
import Element from '../nodes/Element';
import { INode } from '../nodes/interfaces';
import EachBlock from '../nodes/EachBlock';
import IfBlock from '../nodes/IfBlock';
import AwaitBlock from '../nodes/AwaitBlock';
enum BlockAppliesToNode {
NotPossible,
Possible,
UnknownSelectorType
}
enum NodeExist {
Probably = 1,
Definitely = 2,
}
const whitelist_attribute_selector = new Map([
['details', new Set(['open'])]
]);
export default class Selector {
node: CssNode;
@ -35,10 +47,10 @@ export default class Selector {
this.used = this.local_blocks.length === 0;
}
apply(node: Element, stack: Element[]) {
apply(node: Element) {
const to_encapsulate: any[] = [];
apply_selector(this.local_blocks.slice(), node, stack.slice(), to_encapsulate);
apply_selector(this.local_blocks.slice(), node, to_encapsulate);
if (to_encapsulate.length > 0) {
to_encapsulate.forEach(({ node, block }) => {
@ -65,9 +77,8 @@ export default class Selector {
transform(code: MagicString, attr: string, max_amount_class_specificity_increased: number) {
const amount_class_specificity_to_increase = max_amount_class_specificity_increased - this.blocks.filter(block => block.should_encapsulate).length;
attr = attr.repeat(amount_class_specificity_to_increase + 1);
function encapsulate_block(block: Block) {
function encapsulate_block(block: Block, attr: string) {
let i = block.selectors.length;
while (i--) {
@ -89,15 +100,14 @@ export default class Selector {
}
}
this.blocks.forEach((block) => {
this.blocks.forEach((block, index) => {
if (block.global) {
const selector = block.selectors[0];
const first = selector.children[0];
const last = selector.children[selector.children.length - 1];
code.remove(selector.start, first.start).remove(last.end, selector.end);
}
if (block.should_encapsulate) encapsulate_block(block);
if (block.should_encapsulate) encapsulate_block(block, index === this.blocks.length - 1 ? attr.repeat(amount_class_specificity_to_increase + 1) : attr);
});
}
@ -108,8 +118,8 @@ export default class Selector {
const selector = block.selectors[i];
if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
component.error(selector, {
code: `css-invalid-global`,
message: `:global(...) must be the first element in a compound selector`
code: 'css-invalid-global',
message: ':global(...) must be the first element in a compound selector'
});
}
}
@ -129,8 +139,8 @@ export default class Selector {
for (let i = start; i < end; i += 1) {
if (this.blocks[i].global) {
component.error(this.blocks[i].selectors[0], {
code: `css-invalid-global`,
message: `:global(...) can be at the start or end of a selector sequence, but not in the middle`
code: 'css-invalid-global',
message: ':global(...) can be at the start or end of a selector sequence, but not in the middle'
});
}
}
@ -147,12 +157,12 @@ export default class Selector {
}
}
function apply_selector(blocks: Block[], node: Element, stack: Element[], to_encapsulate: any[]): boolean {
function apply_selector(blocks: Block[], node: Element, to_encapsulate: any[]): boolean {
const block = blocks.pop();
if (!block) return false;
if (!node) {
return blocks.every(block => block.global);
return block.global && blocks.every(block => block.global);
}
switch (block_might_apply_to_node(block, node)) {
@ -160,7 +170,7 @@ function apply_selector(blocks: Block[], node: Element, stack: Element[], to_enc
return false;
case BlockAppliesToNode.UnknownSelectorType:
// bail. TODO figure out what these could be
// bail. TODO figure out what these could be
to_encapsulate.push({ node, block });
return true;
}
@ -172,9 +182,10 @@ function apply_selector(blocks: Block[], node: Element, stack: Element[], to_enc
continue;
}
for (const stack_node of stack) {
if (block_might_apply_to_node(ancestor_block, stack_node) !== BlockAppliesToNode.NotPossible) {
to_encapsulate.push({ node: stack_node, block: ancestor_block });
let parent = node;
while (parent = get_element_parent(parent)) {
if (block_might_apply_to_node(ancestor_block, parent) !== BlockAppliesToNode.NotPossible) {
to_encapsulate.push({ node: parent, block: ancestor_block });
}
}
@ -191,12 +202,22 @@ function apply_selector(blocks: Block[], node: Element, stack: Element[], to_enc
return false;
} else if (block.combinator.name === '>') {
if (apply_selector(blocks, stack.pop(), stack, to_encapsulate)) {
if (apply_selector(blocks, get_element_parent(node), to_encapsulate)) {
to_encapsulate.push({ node, block });
return true;
}
return false;
} else if (block.combinator.name === '+' || block.combinator.name === '~') {
const siblings = get_possible_element_siblings(node, block.combinator.name === '+');
let has_match = false;
for (const possible_sibling of siblings.keys()) {
if (apply_selector(blocks.slice(), possible_sibling, to_encapsulate)) {
to_encapsulate.push({ node, block });
has_match = true;
}
}
return has_match;
}
// TODO other combinators
@ -208,7 +229,7 @@ function apply_selector(blocks: Block[], node: Element, stack: Element[], to_enc
return true;
}
function block_might_apply_to_node(block, node): BlockAppliesToNode {
function block_might_apply_to_node(block: Block, node: Element): BlockAppliesToNode {
let i = block.selectors.length;
while (i--) {
@ -234,7 +255,11 @@ function block_might_apply_to_node(block, node): BlockAppliesToNode {
}
else if (selector.type === 'AttributeSelector') {
if (!attribute_matches(node, selector.name.name, selector.value && unquote(selector.value), selector.matcher, selector.flags)) return BlockAppliesToNode.NotPossible;
if (
!(whitelist_attribute_selector.has(node.name.toLowerCase()) && whitelist_attribute_selector.get(node.name.toLowerCase()).has(selector.name.name.toLowerCase())) &&
!attribute_matches(node, selector.name.name, selector.value && unquote(selector.value), selector.matcher, selector.flags)) {
return BlockAppliesToNode.NotPossible;
}
}
else if (selector.type === 'TypeSelector') {
@ -261,7 +286,7 @@ function test_attribute(operator, expected_value, case_insensitive, value) {
case '^=': return value.startsWith(expected_value);
case '$=': return value.endsWith(expected_value);
case '*=': return value.includes(expected_value);
default: throw new Error(`this shouldn't happen`);
default: throw new Error("this shouldn't happen");
}
}
@ -370,6 +395,158 @@ function unquote(value: CssNode) {
return str;
}
function get_element_parent(node: Element): Element | null {
let parent: INode = node;
while ((parent = parent.parent) && parent.type !== 'Element');
return parent as Element | null;
}
function get_possible_element_siblings(node: INode, adjacent_only: boolean): Map<Element, NodeExist> {
const result: Map<Element, NodeExist> = new Map();
let prev: INode = node;
while (prev = prev.prev) {
if (prev.type === 'Element') {
if (!prev.attributes.find(attr => attr.type === 'Attribute' && attr.name.toLowerCase() === 'slot')) {
result.set(prev, NodeExist.Definitely);
}
if (adjacent_only) {
break;
}
} else if (prev.type === 'EachBlock' || prev.type === 'IfBlock' || prev.type === 'AwaitBlock') {
const possible_last_child = get_possible_last_child(prev, adjacent_only);
add_to_map(possible_last_child, result);
if (adjacent_only && has_definite_elements(possible_last_child)) {
return result;
}
}
}
if (!prev || !adjacent_only) {
let parent: INode = node;
let skip_each_for_last_child = node.type === 'ElseBlock';
while ((parent = parent.parent) && (parent.type === 'EachBlock' || parent.type === 'IfBlock' || parent.type === 'ElseBlock' || parent.type === 'AwaitBlock')) {
const possible_siblings = get_possible_element_siblings(parent, adjacent_only);
add_to_map(possible_siblings, result);
if (parent.type === 'EachBlock') {
// first child of each block can select the last child of each block as previous sibling
if (skip_each_for_last_child) {
skip_each_for_last_child = false;
} else {
add_to_map(get_possible_last_child(parent, adjacent_only), result);
}
} else if (parent.type === 'ElseBlock') {
skip_each_for_last_child = true;
parent = parent.parent;
}
if (adjacent_only && has_definite_elements(possible_siblings)) {
break;
}
}
}
return result;
}
function get_possible_last_child(block: EachBlock | IfBlock | AwaitBlock, adjacent_only: boolean): Map<Element, NodeExist> {
const result: Map<Element, NodeExist> = new Map();
if (block.type === 'EachBlock') {
const each_result: Map<Element, NodeExist> = loop_child(block.children, adjacent_only);
const else_result: Map<Element, NodeExist> = block.else ? loop_child(block.else.children, adjacent_only) : new Map();
const not_exhaustive = !has_definite_elements(else_result);
if (not_exhaustive) {
mark_as_probably(each_result);
mark_as_probably(else_result);
}
add_to_map(each_result, result);
add_to_map(else_result, result);
} else if (block.type === 'IfBlock') {
const if_result: Map<Element, NodeExist> = loop_child(block.children, adjacent_only);
const else_result: Map<Element, NodeExist> = block.else ? loop_child(block.else.children, adjacent_only) : new Map();
const not_exhaustive = !has_definite_elements(if_result) || !has_definite_elements(else_result);
if (not_exhaustive) {
mark_as_probably(if_result);
mark_as_probably(else_result);
}
add_to_map(if_result, result);
add_to_map(else_result, result);
} else if (block.type === 'AwaitBlock') {
const pending_result: Map<Element, NodeExist> = block.pending ? loop_child(block.pending.children, adjacent_only) : new Map();
const then_result: Map<Element, NodeExist> = block.then ? loop_child(block.then.children, adjacent_only) : new Map();
const catch_result: Map<Element, NodeExist> = block.catch ? loop_child(block.catch.children, adjacent_only) : new Map();
const not_exhaustive = !has_definite_elements(pending_result) || !has_definite_elements(then_result) || !has_definite_elements(catch_result);
if (not_exhaustive) {
mark_as_probably(pending_result);
mark_as_probably(then_result);
mark_as_probably(catch_result);
}
add_to_map(pending_result, result);
add_to_map(then_result, result);
add_to_map(catch_result, result);
}
return result;
}
function has_definite_elements(result: Map<Element, NodeExist>): boolean {
if (result.size === 0) return false;
for (const exist of result.values()) {
if (exist === NodeExist.Definitely) {
return true;
}
}
return false;
}
function add_to_map(from: Map<Element, NodeExist>, to: Map<Element, NodeExist>) {
from.forEach((exist, element) => {
to.set(element, higher_existance(exist, to.get(element)));
});
}
function higher_existance(exist1: NodeExist | null, exist2: NodeExist | null): NodeExist {
if (exist1 === undefined || exist2 === undefined) return exist1 || exist2;
return exist1 > exist2 ? exist1 : exist2;
}
function mark_as_probably(result: Map<Element, NodeExist>) {
for (const key of result.keys()) {
result.set(key, NodeExist.Probably);
}
}
function loop_child(children: INode[], adjacent_only: boolean) {
const result: Map<Element, NodeExist> = new Map();
for (let i = children.length - 1; i >= 0; i--) {
const child = children[i];
if (child.type === 'Element') {
result.set(child, NodeExist.Definitely);
if (adjacent_only) {
break;
}
} else if (child.type === 'EachBlock' || child.type === 'IfBlock' || child.type === 'AwaitBlock') {
const child_result = get_possible_last_child(child, adjacent_only);
add_to_map(child_result, result);
if (adjacent_only && has_definite_elements(child_result)) {
break;
}
}
}
return result;
}
class Block {
global: boolean;
combinator: CssNode;

@ -2,10 +2,10 @@ import MagicString from 'magic-string';
import { walk } from 'estree-walker';
import Selector from './Selector';
import Element from '../nodes/Element';
import { Ast, TemplateNode } from '../../interfaces';
import { Ast } from '../../interfaces';
import Component from '../Component';
import { CssNode } from './interfaces';
import hash from "../utils/hash";
import hash from '../utils/hash';
function remove_css_prefix(name: string): string {
return name.replace(/^-((webkit)|(moz)|(o)|(ms))-/, '');
@ -51,8 +51,8 @@ class Rule {
this.declarations = node.block.children.map((node: CssNode) => new Declaration(node));
}
apply(node: Element, stack: Element[]) {
this.selectors.forEach(selector => selector.apply(node, stack)); // TODO move the logic in here?
apply(node: Element) {
this.selectors.forEach(selector => selector.apply(node)); // TODO move the logic in here?
}
is_used(dev: boolean) {
@ -162,10 +162,10 @@ class Atrule {
this.declarations = [];
}
apply(node: Element, stack: Element[]) {
apply(node: Element) {
if (this.node.name === 'media' || this.node.name === 'supports') {
this.children.forEach(child => {
child.apply(node, stack);
child.apply(node);
});
}
@ -364,15 +364,9 @@ export default class Stylesheet {
apply(node: Element) {
if (!this.has_styles) return;
const stack: Element[] = [];
let parent: TemplateNode = node;
while (parent = parent.parent) {
if (parent.type === 'Element') stack.unshift(parent as Element);
}
for (let i = 0; i < this.children.length; i += 1) {
const child = this.children[i];
child.apply(node, stack);
child.apply(node);
}
}
@ -434,8 +428,8 @@ export default class Stylesheet {
this.children.forEach(child => {
child.warn_on_unused_selector((selector: Selector) => {
component.warn(selector.node, {
code: `css-unused-selector`,
message: `Unused CSS selector`
code: 'css-unused-selector',
message: `Unused CSS selector "${this.source.slice(selector.node.start, selector.node.end)}"`
});
});
});

@ -15,4 +15,4 @@ export function gather_possible_values(node: Node, set: Set<string|{}>) {
else {
set.add(UNKNOWN);
}
}
}

@ -3,4 +3,4 @@ export interface CssNode {
start: number;
end: number;
[prop_name: string]: any;
}
}

@ -1,4 +1,3 @@
import { assign } from '../../runtime/internal/utils';
import Stats from '../Stats';
import parse from '../parse/index';
import render_dom from './render_dom/index';
@ -47,28 +46,28 @@ function validate_options(options: CompileOptions, warnings: Warning[]) {
}
if (name && /^[a-z]/.test(name)) {
const message = `options.name should be capitalised`;
const message = 'options.name should be capitalised';
warnings.push({
code: `options-lowercase-name`,
code: 'options-lowercase-name',
message,
filename,
toString: () => message,
toString: () => message
});
}
if (loopGuardTimeout && !dev) {
const message = 'options.loopGuardTimeout is for options.dev = true only';
warnings.push({
code: `options-loop-guard-timeout`,
code: 'options-loop-guard-timeout',
message,
filename,
toString: () => message,
toString: () => message
});
}
}
export default function compile(source: string, options: CompileOptions = {}) {
options = assign({ generate: 'dom', dev: false }, options);
options = Object.assign({ generate: 'dom', dev: false }, options);
const stats = new Stats();
const warnings = [];

@ -11,10 +11,11 @@ export default class Action extends Node {
constructor(component: Component, parent, scope, info) {
super(component, parent, scope, info);
component.warn_if_undefined(info.name, info, scope);
const object = info.name.split('.')[0];
component.warn_if_undefined(object, info, scope);
this.name = info.name;
component.add_reference(info.name.split('.')[0]);
component.add_reference(object);
this.expression = info.expression
? new Expression(component, this, scope, info.expression)
@ -22,4 +23,4 @@ export default class Action extends Node {
this.uses_context = this.expression && this.expression.uses_context;
}
}
}

@ -17,8 +17,8 @@ export default class Animation extends Node {
if (parent.animation) {
component.error(this, {
code: `duplicate-animation`,
message: `An element can only have one 'animate' directive`
code: 'duplicate-animation',
message: "An element can only have one 'animate' directive"
});
}
@ -26,8 +26,8 @@ export default class Animation extends Node {
if (!block || block.type !== 'EachBlock' || !block.key) {
// TODO can we relax the 'immediate child' rule?
component.error(this, {
code: `invalid-animation`,
message: `An element that use the animate directive must be the immediate child of a keyed each block`
code: 'invalid-animation',
message: 'An element that use the animate directive must be the immediate child of a keyed each block'
});
}
@ -37,4 +37,4 @@ export default class Animation extends Node {
? new Expression(component, this, scope, info.expression, true)
: null;
}
}
}

@ -3,7 +3,7 @@ import get_object from '../utils/get_object';
import Expression from './shared/Expression';
import Component from '../Component';
import TemplateScope from './shared/TemplateScope';
import {dimensions} from "../../utils/patterns";
import {dimensions} from '../../utils/patterns';
import { Node as ESTreeNode } from 'estree';
// TODO this should live in a specific binding
@ -41,7 +41,8 @@ export default class Binding extends Node {
this.raw_expression = JSON.parse(JSON.stringify(info.expression));
const { name } = get_object(this.expression.node);
this.is_contextual = scope.names.has(name);
this.is_contextual = Array.from(this.expression.references).some(name => scope.names.has(name));
// make sure we track this as a mutable ref
if (scope.is_let(name)) {
@ -49,7 +50,7 @@ export default class Binding extends Node {
code: 'invalid-binding',
message: 'Cannot bind to a variable declared with the let: directive'
});
} else if (this.is_contextual) {
} else if (scope.names.has(name)) {
if (scope.is_await(name)) {
component.error(this, {
code: 'invalid-binding',
@ -66,17 +67,21 @@ export default class Binding extends Node {
} else {
const variable = component.var_lookup.get(name);
if (!variable || variable.global) component.error(this.expression.node, {
code: 'binding-undeclared',
message: `${name} is not declared`
});
if (!variable || variable.global) {
component.error(this.expression.node, {
code: 'binding-undeclared',
message: `${name} is not declared`
});
}
variable[this.expression.node.type === 'MemberExpression' ? 'mutated' : 'reassigned'] = true;
if (info.expression.type === 'Identifier' && !variable.writable) component.error(this.expression.node, {
code: 'invalid-binding',
message: 'Cannot bind to a variable which is not writable',
});
if (info.expression.type === 'Identifier' && !variable.writable) {
component.error(this.expression.node, {
code: 'invalid-binding',
message: 'Cannot bind to a variable which is not writable'
});
}
}
const type = parent.get_static_attribute_value('type');

@ -15,4 +15,4 @@ export default class Class extends Node {
? new Expression(component, this, scope, info.expression)
: null;
}
}
}

@ -14,4 +14,4 @@ export default class Comment extends Node {
const match = pattern.exec(this.data);
this.ignores = match ? match[1].split(/[^\S]/).map(x => x.trim()).filter(Boolean) : [];
}
}
}

@ -60,8 +60,8 @@ export default class EachBlock extends AbstractBlock {
if (this.children.length !== 1) {
const child = this.children.find(child => !!(child as Element).animation);
component.error((child as Element).animation, {
code: `invalid-animation`,
message: `An element that use the animate directive must be the sole child of a keyed each block`
code: 'invalid-animation',
message: 'An element that use the animate directive must be the sole child of a keyed each block'
});
}
}

@ -16,6 +16,7 @@ import list from '../../utils/list';
import Let from './Let';
import TemplateScope from './shared/TemplateScope';
import { INode } from './interfaces';
import Component from '../Component';
const svg = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|svg|switch|symbol|text|textPath|tref|tspan|unknown|use|view|vkern)$/;
@ -61,6 +62,17 @@ const a11y_no_onchange = new Set([
'option'
]);
const a11y_labelable = new Set([
'button',
'input',
'keygen',
'meter',
'output',
'progress',
'select',
'textarea'
]);
const invisible_elements = new Set(['meta', 'html', 'script', 'style']);
const valid_modifiers = new Set([
@ -69,6 +81,7 @@ const valid_modifiers = new Set([
'capture',
'once',
'passive',
'nonpassive',
'self'
]);
@ -112,7 +125,7 @@ export default class Element extends Node {
namespace: string;
needs_manual_style_scoping: boolean;
constructor(component, parent, scope, info: any) {
constructor(component: Component, parent, scope, info: any) {
super(component, parent, scope, info);
this.name = info.name;
@ -123,8 +136,8 @@ export default class Element extends Node {
const value_attribute = info.attributes.find(node => node.name === 'value');
if (value_attribute) {
component.error(value_attribute, {
code: `textarea-duplicate-value`,
message: `A <textarea> can have either a value attribute or (equivalently) child content, but not both`
code: 'textarea-duplicate-value',
message: 'A <textarea> can have either a value attribute or (equivalently) child content, but not both'
});
}
@ -224,14 +237,21 @@ export default class Element extends Node {
this.validate();
component.stylesheet.apply(this);
component.apply_stylesheet(this);
}
validate() {
if (this.component.var_lookup.has(this.name) && this.component.var_lookup.get(this.name).imported) {
this.component.warn(this, {
code: 'component-name-lowercase',
message: `<${this.name}> will be treated as an HTML element unless it begins with a capital letter`
});
}
if (a11y_distracting_elements.has(this.name)) {
// no-distracting-elements
this.component.warn(this, {
code: `a11y-distracting-elements`,
code: 'a11y-distracting-elements',
message: `A11y: Avoid <${this.name}> elements`
});
}
@ -253,8 +273,8 @@ export default class Element extends Node {
if (!is_figure_parent) {
this.component.warn(this, {
code: `a11y-structure`,
message: `A11y: <figcaption> must be an immediate child of <figure>`
code: 'a11y-structure',
message: 'A11y: <figcaption> must be an immediate child of <figure>'
});
}
}
@ -270,8 +290,8 @@ export default class Element extends Node {
if (index !== -1 && (index !== 0 && index !== children.length - 1)) {
this.component.warn(children[index], {
code: `a11y-structure`,
message: `A11y: <figcaption> must be first or last child of <figure>`
code: 'a11y-structure',
message: 'A11y: <figcaption> must be first or last child of <figure>'
});
}
}
@ -298,7 +318,7 @@ export default class Element extends Node {
if (invisible_elements.has(this.name)) {
// aria-unsupported-elements
component.warn(attribute, {
code: `a11y-aria-attributes`,
code: 'a11y-aria-attributes',
message: `A11y: <${this.name}> should not have aria-* attributes`
});
}
@ -310,14 +330,14 @@ export default class Element extends Node {
if (match) message += ` (did you mean '${match}'?)`;
component.warn(attribute, {
code: `a11y-unknown-aria-attribute`,
code: 'a11y-unknown-aria-attribute',
message
});
}
if (name === 'aria-hidden' && /^h[1-6]$/.test(this.name)) {
component.warn(attribute, {
code: `a11y-hidden`,
code: 'a11y-hidden',
message: `A11y: <${this.name}> element should not be hidden`
});
}
@ -328,7 +348,7 @@ export default class Element extends Node {
if (invisible_elements.has(this.name)) {
// aria-unsupported-elements
component.warn(attribute, {
code: `a11y-misplaced-role`,
code: 'a11y-misplaced-role',
message: `A11y: <${this.name}> should not have role attribute`
});
}
@ -342,7 +362,7 @@ export default class Element extends Node {
if (match) message += ` (did you mean '${match}'?)`;
component.warn(attribute, {
code: `a11y-unknown-role`,
code: 'a11y-unknown-role',
message
});
}
@ -351,24 +371,24 @@ export default class Element extends Node {
// no-access-key
if (name === 'accesskey') {
component.warn(attribute, {
code: `a11y-accesskey`,
message: `A11y: Avoid using accesskey`
code: 'a11y-accesskey',
message: 'A11y: Avoid using accesskey'
});
}
// no-autofocus
if (name === 'autofocus') {
component.warn(attribute, {
code: `a11y-autofocus`,
message: `A11y: Avoid using autofocus`
code: 'a11y-autofocus',
message: 'A11y: Avoid using autofocus'
});
}
// scope
if (name === 'scope' && this.name !== 'th') {
component.warn(attribute, {
code: `a11y-misplaced-scope`,
message: `A11y: The scope attribute should only be used with <th> elements`
code: 'a11y-misplaced-scope',
message: 'A11y: The scope attribute should only be used with <th> elements'
});
}
@ -378,8 +398,8 @@ export default class Element extends Node {
// @ts-ignore todo is tabindex=true correct case?
if (!isNaN(value) && +value > 0) {
component.warn(attribute, {
code: `a11y-positive-tabindex`,
message: `A11y: avoid tabindex values above zero`
code: 'a11y-positive-tabindex',
message: 'A11y: avoid tabindex values above zero'
});
}
}
@ -387,22 +407,22 @@ export default class Element extends Node {
if (/(^[0-9-.])|[\^$@%&#?!|()[\]{}^*+~;]/.test(name)) {
component.error(attribute, {
code: `illegal-attribute`,
message: `'${name}' is not a valid attribute name`,
code: 'illegal-attribute',
message: `'${name}' is not a valid attribute name`
});
}
if (name === 'slot') {
if (!attribute.is_static) {
component.error(attribute, {
code: `invalid-slot-attribute`,
message: `slot attribute cannot have a dynamic value`
code: 'invalid-slot-attribute',
message: 'slot attribute cannot have a dynamic value'
});
}
if (component.slot_outlets.has(name)) {
component.error(attribute, {
code: `duplicate-slot-attribute`,
code: 'duplicate-slot-attribute',
message: `Duplicate '${name}' slot`
});
@ -411,8 +431,8 @@ export default class Element extends Node {
if (!(parent.type === 'InlineComponent' || within_custom_element(parent))) {
component.error(attribute, {
code: `invalid-slotted-content`,
message: `Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`,
code: 'invalid-slotted-content',
message: 'Element with a slot=\'...\' attribute must be a child of a component or a descendant of a custom element'
});
}
}
@ -420,7 +440,7 @@ export default class Element extends Node {
if (name === 'is') {
component.warn(attribute, {
code: 'avoid-is',
message: `The 'is' attribute is not supported cross-browser and should be avoided`
message: 'The \'is\' attribute is not supported cross-browser and should be avoided'
});
}
@ -451,7 +471,7 @@ export default class Element extends Node {
if (href_value === '' || href_value === '#' || /^\W*javascript:/i.test(href_value)) {
component.warn(href_attribute, {
code: `a11y-invalid-attribute`,
code: 'a11y-invalid-attribute',
message: `A11y: '${href_value}' is not a valid ${href_attribute.name} attribute`
});
}
@ -461,8 +481,8 @@ export default class Element extends Node {
if (!id_attribute_valid && !name_attribute_valid) {
component.warn(this, {
code: `a11y-missing-attribute`,
message: `A11y: <a> element should have an href attribute`
code: 'a11y-missing-attribute',
message: 'A11y: <a> element should have an href attribute'
});
}
}
@ -500,18 +520,47 @@ export default class Element extends Node {
if (/\b(image|picture|photo)\b/i.test(alt_value)) {
component.warn(this, {
code: `a11y-img-redundant-alt`,
message: `A11y: Screenreaders already announce <img> elements as an image.`
code: 'a11y-img-redundant-alt',
message: 'A11y: Screenreaders already announce <img> elements as an image.'
});
}
}
}
if (this.name === 'label') {
const has_input_child = this.children.some(i => (i instanceof Element && a11y_labelable.has(i.name) ));
if (!attribute_map.has('for') && !has_input_child) {
component.warn(this, {
code: 'a11y-label-has-associated-control',
message: 'A11y: A form label must be associated with a control.'
});
}
}
if (this.is_media_node()) {
if (attribute_map.has('muted')) {
return;
}
let has_caption;
const track = this.children.find((i: Element) => i.name === 'track');
if (track) {
has_caption = track.attributes.find(a => a.name === 'kind' && a.get_static_value() === 'captions');
}
if (!has_caption) {
component.warn(this, {
code: 'a11y-media-has-caption',
message: 'A11y: Media elements must have a <track kind="captions">'
});
}
}
if (a11y_no_onchange.has(this.name)) {
if (handlers_map.has('change') && !handlers_map.has('blur')) {
component.warn(this, {
code: `a11y-no-onchange`,
message: `A11y: on:blur must be used instead of on:change, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.`
code: 'a11y-no-onchange',
message: 'A11y: on:blur must be used instead of on:change, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.'
});
}
}
@ -529,8 +578,8 @@ export default class Element extends Node {
if (!attribute.is_static) {
component.error(attribute, {
code: `invalid-type`,
message: `'type' attribute cannot be dynamic if input uses two-way binding`
code: 'invalid-type',
message: '\'type\' attribute cannot be dynamic if input uses two-way binding'
});
}
@ -538,8 +587,8 @@ export default class Element extends Node {
if (value === true) {
component.error(attribute, {
code: `missing-type`,
message: `'type' attribute must be specified`
code: 'missing-type',
message: '\'type\' attribute must be specified'
});
}
@ -556,7 +605,7 @@ export default class Element extends Node {
this.name !== 'select'
) {
component.error(binding, {
code: `invalid-binding`,
code: 'invalid-binding',
message: `'value' is not a valid binding on <${this.name}> elements`
});
}
@ -568,8 +617,8 @@ export default class Element extends Node {
if (attribute && !attribute.is_static) {
component.error(attribute, {
code: `dynamic-multiple-attribute`,
message: `'multiple' attribute cannot be dynamic if select uses two-way binding`
code: 'dynamic-multiple-attribute',
message: '\'multiple\' attribute cannot be dynamic if select uses two-way binding'
});
}
} else {
@ -578,7 +627,7 @@ export default class Element extends Node {
} else if (name === 'checked' || name === 'indeterminate') {
if (this.name !== 'input') {
component.error(binding, {
code: `invalid-binding`,
code: 'invalid-binding',
message: `'${name}' is not a valid binding on <${this.name}> elements`
});
}
@ -587,13 +636,13 @@ export default class Element extends Node {
if (type !== 'checkbox') {
let message = `'${name}' binding can only be used with <input type="checkbox">`;
if (type === 'radio') message += ` — for <input type="radio">, use 'group' binding`;
component.error(binding, { code: `invalid-binding`, message });
if (type === 'radio') message += ' — for <input type="radio">, use \'group\' binding';
component.error(binding, { code: 'invalid-binding', message });
}
} else if (name === 'group') {
if (this.name !== 'input') {
component.error(binding, {
code: `invalid-binding`,
code: 'invalid-binding',
message: `'group' is not a valid binding on <${this.name}> elements`
});
}
@ -602,14 +651,14 @@ export default class Element extends Node {
if (type !== 'checkbox' && type !== 'radio') {
component.error(binding, {
code: `invalid-binding`,
message: `'group' binding can only be used with <input type="checkbox"> or <input type="radio">`
code: 'invalid-binding',
message: '\'group\' binding can only be used with <input type="checkbox"> or <input type="radio">'
});
}
} else if (name === 'files') {
if (this.name !== 'input') {
component.error(binding, {
code: `invalid-binding`,
code: 'invalid-binding',
message: `'files' is not a valid binding on <${this.name}> elements`
});
}
@ -618,15 +667,15 @@ export default class Element extends Node {
if (type !== 'file') {
component.error(binding, {
code: `invalid-binding`,
message: `'files' binding can only be used with <input type="file">`
code: 'invalid-binding',
message: '\'files\' binding can only be used with <input type="file">'
});
}
} else if (name === 'open') {
if (this.name !== 'details') {
component.error(binding, {
code: `invalid-binding`,
code: 'invalid-binding',
message: `'${name}' binding can only be used with <details>`
});
}
@ -645,7 +694,7 @@ export default class Element extends Node {
) {
if (this.name !== 'audio' && this.name !== 'video') {
component.error(binding, {
code: `invalid-binding`,
code: 'invalid-binding',
message: `'${name}' binding can only be used with <audio> or <video>`
});
}
@ -655,7 +704,7 @@ export default class Element extends Node {
) {
if (this.name !== 'video') {
component.error(binding, {
code: `invalid-binding`,
code: 'invalid-binding',
message: `'${name}' binding can only be used with <video>`
});
}
@ -686,18 +735,18 @@ export default class Element extends Node {
if (!contenteditable) {
component.error(binding, {
code: `missing-contenteditable-attribute`,
message: `'contenteditable' attribute is required for textContent and innerHTML two-way bindings`
code: 'missing-contenteditable-attribute',
message: '\'contenteditable\' attribute is required for textContent and innerHTML two-way bindings'
});
} else if (contenteditable && !contenteditable.is_static) {
component.error(contenteditable, {
code: `dynamic-contenteditable-attribute`,
message: `'contenteditable' attribute cannot be dynamic if element uses two-way binding`
code: 'dynamic-contenteditable-attribute',
message: '\'contenteditable\' attribute cannot be dynamic if element uses two-way binding'
});
}
} else if (name !== 'this') {
component.error(binding, {
code: `invalid-binding`,
code: 'invalid-binding',
message: `'${binding.name}' is not a valid binding`
});
}
@ -713,7 +762,7 @@ export default class Element extends Node {
if (this.children.length === 0) {
this.component.warn(this, {
code: `a11y-missing-content`,
code: 'a11y-missing-content',
message: `A11y: <${this.name}> element should have child content`
});
}
@ -726,7 +775,14 @@ export default class Element extends Node {
if (handler.modifiers.has('passive') && handler.modifiers.has('preventDefault')) {
component.error(handler, {
code: 'invalid-event-modifier',
message: `The 'passive' and 'preventDefault' modifiers cannot be used together`
message: 'The \'passive\' and \'preventDefault\' modifiers cannot be used together'
});
}
if (handler.modifiers.has('passive') && handler.modifiers.has('nonpassive')) {
component.error(handler, {
code: 'invalid-event-modifier',
message: 'The \'passive\' and \'nonpassive\' modifiers cannot be used together'
});
}
@ -743,13 +799,13 @@ export default class Element extends Node {
if (handler.can_make_passive) {
component.warn(handler, {
code: 'redundant-event-modifier',
message: `Touch event handlers that don't use the 'event' object are passive by default`
message: 'Touch event handlers that don\'t use the \'event\' object are passive by default'
});
}
} else {
component.warn(handler, {
code: 'redundant-event-modifier',
message: `The passive modifier only works with wheel and touch events`
message: 'The passive modifier only works with wheel and touch events'
});
}
}
@ -764,7 +820,7 @@ export default class Element extends Node {
}
});
if (passive_events.has(handler.name) && handler.can_make_passive && !handler.modifiers.has('preventDefault')) {
if (passive_events.has(handler.name) && handler.can_make_passive && !handler.modifiers.has('preventDefault') && !handler.modifiers.has('nonpassive')) {
// touch/wheel events should be passive by default
handler.modifiers.add('passive');
}
@ -820,7 +876,7 @@ function should_have_attribute(
attributes[0];
node.component.warn(node, {
code: `a11y-missing-attribute`,
code: 'a11y-missing-attribute',
message: `A11y: <${name}> element should have ${article} ${sequence} attribute`
});
}

@ -12,8 +12,8 @@ export default class Head extends Node {
if (info.attributes.length) {
component.error(info.attributes[0], {
code: `invalid-attribute`,
message: `<svelte:head> should not have any attributes or directives`
code: 'invalid-attribute',
message: '<svelte:head> should not have any attributes or directives'
});
}

@ -40,15 +40,15 @@ export default class InlineComponent extends Node {
switch (node.type) {
case 'Action':
component.error(node, {
code: `invalid-action`,
message: `Actions can only be applied to DOM elements, not components`
code: 'invalid-action',
message: 'Actions can only be applied to DOM elements, not components'
});
case 'Attribute':
if (node.name === 'slot') {
component.error(node, {
code: `invalid-prop`,
message: `'slot' is reserved for future use in named slots`
code: 'invalid-prop',
message: "'slot' is reserved for future use in named slots"
});
}
// fallthrough
@ -62,8 +62,8 @@ export default class InlineComponent extends Node {
case 'Class':
component.error(node, {
code: `invalid-class`,
message: `Classes can only be applied to DOM elements, not components`
code: 'invalid-class',
message: 'Classes can only be applied to DOM elements, not components'
});
case 'EventHandler':
@ -76,8 +76,8 @@ export default class InlineComponent extends Node {
case 'Transition':
component.error(node, {
code: `invalid-transition`,
message: `Transitions can only be applied to DOM elements, not components`
code: 'invalid-transition',
message: 'Transitions can only be applied to DOM elements, not components'
});
default:
@ -105,7 +105,7 @@ export default class InlineComponent extends Node {
if (modifier !== 'once') {
component.error(handler, {
code: 'invalid-event-modifier',
message: `Event modifiers other than 'once' can only be used on DOM elements`
message: "Event modifiers other than 'once' can only be used on DOM elements"
});
}
});

@ -0,0 +1,19 @@
import Expression from './shared/Expression';
import map_children from './shared/map_children';
import AbstractBlock from './shared/AbstractBlock';
export default class KeyBlock extends AbstractBlock {
type: 'KeyBlock';
expression: Expression;
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.expression = new Expression(component, this, scope, info.expression);
this.children = map_children(component, this, scope, info.children);
this.warn_if_empty_block();
}
}

@ -26,7 +26,7 @@ export default class Let extends Node {
if (!applicable.has(node.type)) {
component.error(node as any, {
code: 'invalid-let',
message: `let directive value must be an identifier or an object/array pattern`
message: 'let directive value must be an identifier or an object/array pattern'
});
}

@ -17,24 +17,24 @@ export default class Slot extends Element {
info.attributes.forEach(attr => {
if (attr.type !== 'Attribute') {
component.error(attr, {
code: `invalid-slot-directive`,
message: `<slot> cannot have directives`
code: 'invalid-slot-directive',
message: '<slot> cannot have directives'
});
}
if (attr.name === 'name') {
if (attr.value.length !== 1 || attr.value[0].type !== 'Text') {
component.error(attr, {
code: `dynamic-slot-name`,
message: `<slot> name cannot be dynamic`
code: 'dynamic-slot-name',
message: '<slot> name cannot be dynamic'
});
}
this.slot_name = attr.value[0].data;
if (this.slot_name === 'default') {
component.error(attr, {
code: `invalid-slot-name`,
message: `default is a reserved word — it cannot be used as a slot name`
code: 'invalid-slot-name',
message: 'default is a reserved word — it cannot be used as a slot name'
});
}
}

@ -12,7 +12,7 @@ const elements_without_text = new Set([
'dl',
'optgroup',
'select',
'video',
'video'
]);
export default class Text extends Node {
@ -37,7 +37,7 @@ export default class Text extends Node {
// svg namespace exclusions
if (/svg$/.test(parent_element.namespace)) {
if (this.prev && this.prev.type === "Element" && this.prev.name === "tspan") return false;
if (this.prev && this.prev.type === 'Element' && this.prev.name === 'tspan') return false;
}
return parent_element.namespace || elements_without_text.has(parent_element.name);

@ -13,8 +13,8 @@ export default class Title extends Node {
if (info.attributes.length > 0) {
component.error(info.attributes[0], {
code: `illegal-attribute`,
message: `<title> cannot have attributes`
code: 'illegal-attribute',
message: '<title> cannot have attributes'
});
}
@ -22,7 +22,7 @@ export default class Title extends Node {
if (child.type !== 'Text' && child.type !== 'MustacheTag') {
component.error(child, {
code: 'illegal-structure',
message: `<title> can only contain text and {tags}`
message: '<title> can only contain text and {tags}'
});
}
});

@ -28,19 +28,19 @@ export default class Transition extends Node {
: `An element cannot have both ${describe(parent_transition)} directive and ${describe(this)} directive`;
component.error(info, {
code: `duplicate-transition`,
code: 'duplicate-transition',
message
});
}
this.expression = info.expression
? new Expression(component, this, scope, info.expression, true)
? new Expression(component, this, scope, info.expression)
: null;
}
}
function describe(transition: Transition) {
return transition.directive === 'transition'
? `a 'transition'`
? "a 'transition'"
: `an '${transition.directive}'`;
}
}

@ -36,7 +36,7 @@ export default class Window extends Node {
// TODO is this constraint necessary?
component.error(node.expression, {
code: `invalid-binding`,
code: 'invalid-binding',
message: `Bindings on <svelte:window> must be to top-level properties, e.g. '${parts[parts.length - 1]}' rather than '${parts.join('.')}'`
});
}
@ -52,12 +52,12 @@ export default class Window extends Node {
if (match) {
component.error(node, {
code: `invalid-binding`,
code: 'invalid-binding',
message: `${message} (did you mean '${match}'?)`
});
} else {
component.error(node, {
code: `invalid-binding`,
code: 'invalid-binding',
message: `${message} — valid bindings are ${list(valid_bindings)}`
});
}

@ -18,6 +18,7 @@ import Fragment from './Fragment';
import Head from './Head';
import IfBlock from './IfBlock';
import InlineComponent from './InlineComponent';
import KeyBlock from './KeyBlock';
import Let from './Let';
import MustacheTag from './MustacheTag';
import Options from './Options';
@ -31,7 +32,7 @@ import Transition from './Transition';
import Window from './Window';
// note: to write less types each of types in union below should have type defined as literal
// https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions
// https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unions
export type INode = Action
| Animation
| Attribute
@ -50,6 +51,7 @@ export type INode = Action
| Head
| IfBlock
| InlineComponent
| KeyBlock
| Let
| MustacheTag
| Options

@ -24,7 +24,7 @@ export default class Expression {
component: Component;
owner: Owner;
node: any;
references: Set<string>;
references: Set<string> = new Set();
dependencies: Set<string> = new Set();
contextual_dependencies: Set<string> = new Set();
@ -50,7 +50,7 @@ export default class Expression {
this.template_scope = template_scope;
this.owner = owner;
const { dependencies, contextual_dependencies } = this;
const { dependencies, contextual_dependencies, references } = this;
let { map, scope } = create_scopes(info);
this.scope = scope;
@ -64,6 +64,8 @@ export default class Expression {
enter(node: any, parent: any, key: string) {
// don't manipulate shorthand props twice
if (key === 'value' && parent.shorthand) return;
// don't manipulate `import.meta`, `new.target`
if (node.type === 'MetaProperty') return this.skip();
if (map.has(node)) {
scope = map.get(node);
@ -75,6 +77,7 @@ export default class Expression {
if (is_reference(node, parent)) {
const { name, nodes } = flatten_reference(node);
references.add(name);
if (scope.has(name)) return;
@ -82,8 +85,8 @@ export default class Expression {
const store_name = name.slice(1);
if (template_scope.names.has(store_name) || scope.has(store_name)) {
component.error(node, {
code: `contextual-store`,
message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
code: 'contextual-store',
message: 'Stores must be declared at the top level of the component (this may change in a future version of Svelte)'
});
}
}

@ -6,6 +6,7 @@ import Element from '../Element';
import Head from '../Head';
import IfBlock from '../IfBlock';
import InlineComponent from '../InlineComponent';
import KeyBlock from '../KeyBlock';
import MustacheTag from '../MustacheTag';
import Options from '../Options';
import RawMustacheTag from '../RawMustacheTag';
@ -28,6 +29,7 @@ function get_constructor(type) {
case 'Head': return Head;
case 'IfBlock': return IfBlock;
case 'InlineComponent': return InlineComponent;
case 'KeyBlock': return KeyBlock;
case 'MustacheTag': return MustacheTag;
case 'Options': return Options;
case 'RawMustacheTag': return RawMustacheTag;

@ -4,6 +4,15 @@ import { b, x } from 'code-red';
import { Node, Identifier, ArrayPattern } from 'estree';
import { is_head } from './wrappers/shared/is_head';
export interface Bindings {
object: Identifier;
property: Identifier;
snippet: Node;
store: string;
tail: Node;
modifier: (node: Node) => Node;
}
export interface BlockOptions {
parent?: Block;
name: Identifier;
@ -11,14 +20,7 @@ export interface BlockOptions {
renderer?: Renderer;
comment?: string;
key?: Identifier;
bindings?: Map<string, {
object: Identifier;
property: Identifier;
snippet: Node;
store: string;
tail: Node;
modifier: (node: Node) => Node;
}>;
bindings?: Map<string, Bindings>;
dependencies?: Set<string>;
}
@ -36,14 +38,7 @@ export default class Block {
dependencies: Set<string> = new Set();
bindings: Map<string, {
object: Identifier;
property: Identifier;
snippet: Node;
store: string;
tail: Node;
modifier: (node: Node) => Node;
}>;
bindings: Map<string, Bindings>;
chunks: {
declarations: Array<Node | Node[]>;
@ -106,7 +101,7 @@ export default class Block {
intro: [],
update: [],
outro: [],
destroy: [],
destroy: []
};
this.has_animation = false;
@ -491,4 +486,4 @@ export default class Block {
}
}
}
}
}

@ -60,7 +60,7 @@ export default class Renderer {
if (component.slots.size > 0) {
this.add_to_context('$$scope');
this.add_to_context('$$slots');
this.add_to_context('#slots');
}
if (this.binding_groups.size > 0) {
@ -76,7 +76,7 @@ export default class Renderer {
bindings: new Map(),
dependencies: new Set(),
dependencies: new Set()
});
this.block.has_update_method = true;
@ -160,19 +160,20 @@ export default class Renderer {
member.is_contextual = true;
} else {
member.is_non_contextual = true;
const variable = this.component.var_lookup.get(name);
member.variable = variable;
member.variable = this.component.var_lookup.get(name);
}
return member;
}
invalidate(name: string, value?) {
invalidate(name: string, value?, main_execution_context: boolean = false) {
const variable = this.component.var_lookup.get(name);
const member = this.context_lookup.get(name);
if (variable && (variable.subscribable && (variable.reassigned || variable.export_name))) {
return x`${`$$subscribe_${name}`}($$invalidate(${member.index}, ${value || name}))`;
return main_execution_context
? x`${`$$subscribe_${name}`}(${value || name})`
: x`${`$$subscribe_${name}`}($$invalidate(${member.index}, ${value || name}))`;
}
if (name[0] === '$' && name[1] !== '$') {
@ -234,7 +235,7 @@ export default class Renderer {
if (!member) return;
if (member.index.value === -1) {
throw new Error(`unset index`);
throw new Error('unset index');
}
const value = member.index.value as number;

@ -70,9 +70,18 @@ export default function dom(
);
}
const uses_slots = component.var_lookup.has('$$slots');
let compute_slots;
if (uses_slots) {
compute_slots = b`
const $$slots = @compute_slots(#slots);
`;
}
const uses_props = component.var_lookup.has('$$props');
const uses_rest = component.var_lookup.has('$$restProps');
const $$props = uses_props || uses_rest ? `$$new_props` : `$$props`;
const $$props = uses_props || uses_rest ? '$$new_props' : '$$props';
const props = component.vars.filter(variable => !variable.module && variable.export_name);
const writable_props = props.filter(variable => variable.writable);
@ -293,8 +302,7 @@ export default function dom(
const variable = component.var_lookup.get(prop.name);
if (variable.hoistable) return false;
if (prop.name[0] === '$') return false;
return true;
return prop.name[0] !== '$';
});
const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
@ -409,13 +417,14 @@ export default function dom(
${resubscribable_reactive_store_unsubscribers}
${component.slots.size || component.compile_options.dev || uses_slots ? b`let { $$slots: #slots = {}, $$scope } = $$props;` : null}
${component.compile_options.dev && b`@validate_slots('${component.tag}', #slots, [${[...component.slots.keys()].map(key => `'${key}'`).join(',')}]);`}
${compute_slots}
${instance_javascript}
${unknown_props_check}
${component.slots.size || component.compile_options.dev ? b`let { $$slots = {}, $$scope } = $$props;` : null}
${component.compile_options.dev && b`@validate_slots('${component.tag}', $$slots, [${[...component.slots.keys()].map(key => `'${key}'`).join(',')}]);`}
${renderer.binding_groups.size > 0 && b`const $$binding_groups = [${[...renderer.binding_groups.keys()].map(_ => x`[]`)}];`}
${component.partly_hoisted}
@ -465,7 +474,7 @@ export default function dom(
${css.code && b`this.shadowRoot.innerHTML = \`<style>${css.code.replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`}
@init(this, { target: this.shadowRoot }, ${definition}, ${has_create_fragment ? 'create_fragment': 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
@init(this, { target: this.shadowRoot, props: @attribute_to_object(this.attributes) }, ${definition}, ${has_create_fragment ? 'create_fragment': 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
${dev_props_check}
@ -515,7 +524,7 @@ export default function dom(
const declaration = b`
class ${name} extends ${superclass} {
constructor(options) {
super(${options.dev && `options`});
super(${options.dev && 'options'});
${should_add_css && b`if (!@_document.getElementById("${component.stylesheet.id}-style")) ${add_css}();`}
@init(this, options, ${definition}, ${has_create_fragment ? 'create_fragment': 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
${options.dev && b`@dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "${name.name}", options, id: create_fragment.name });`}

@ -31,48 +31,51 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names:
function get_invalidated(variable: Var, node?: Expression) {
if (main_execution_context && !variable.subscribable && variable.name[0] !== '$') {
return node || x`${variable.name}`;
return node;
}
return renderer.invalidate(variable.name);
return renderer.invalidate(variable.name, undefined, main_execution_context);
}
if (head) {
component.has_reactive_assignments = true;
if (node.type === 'AssignmentExpression' && node.operator === '=' && nodes_match(node.left, node.right) && tail.length === 0) {
return get_invalidated(head, node);
} else {
const is_store_value = head.name[0] === '$' && head.name[1] !== '$';
const extra_args = tail.map(variable => get_invalidated(variable));
const pass_value = (
extra_args.length > 0 ||
(node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') ||
(node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier'))
);
if (!head) {
return node;
}
if (pass_value) {
extra_args.unshift({
type: 'Identifier',
name: head.name
});
}
component.has_reactive_assignments = true;
let invalidate = is_store_value
? x`@set_store_value(${head.name.slice(1)}, ${node}, ${extra_args})`
: !main_execution_context
? x`$$invalidate(${renderer.context_lookup.get(head.name).index}, ${node}, ${extra_args})`
: node;
if (node.type === 'AssignmentExpression' && node.operator === '=' && nodes_match(node.left, node.right) && tail.length === 0) {
return get_invalidated(head, node);
}
if (head.subscribable && head.reassigned) {
const subscribe = `$$subscribe_${head.name}`;
invalidate = x`${subscribe}(${invalidate})`;
}
const is_store_value = head.name[0] === '$' && head.name[1] !== '$';
const extra_args = tail.map(variable => get_invalidated(variable)).filter(Boolean);
return invalidate;
if (is_store_value) {
return x`@set_store_value(${head.name.slice(1)}, ${node}, ${head.name}, ${extra_args})`;
}
let invalidate;
if (!main_execution_context) {
const pass_value = (
extra_args.length > 0 ||
(node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') ||
(node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier'))
);
if (pass_value) {
extra_args.unshift({
type: 'Identifier',
name: head.name
});
}
invalidate = x`$$invalidate(${renderer.context_lookup.get(head.name).index}, ${node}, ${extra_args})`;
} else {
// skip `$$invalidate` if it is in the main execution context
invalidate = extra_args.length ? [node, ...extra_args] : node;
}
if (head.subscribable && head.reassigned) {
const subscribe = `$$subscribe_${head.name}`;
invalidate = x`${subscribe}(${invalidate})`;
}
return node;
}
return invalidate;
}

@ -96,7 +96,7 @@ class AwaitBlockBranch extends Wrapper {
`);
this.block.chunks.declarations.push(b`${get_context}(#ctx)`);
if (this.block.has_update_method) {
this.block.chunks.update.push(b`${get_context}(#ctx)`);
this.block.chunks.update.unshift(b`${get_context}(#ctx)`);
}
}
}
@ -177,8 +177,8 @@ export default class AwaitBlockWrapper extends Wrapper {
const snippet = this.node.expression.manipulate(block);
const info = block.get_unique_name(`info`);
const promise = block.get_unique_name(`promise`);
const info = block.get_unique_name('info');
const promise = block.get_unique_name('promise');
block.add_variable(promise);
@ -188,6 +188,7 @@ export default class AwaitBlockWrapper extends Wrapper {
ctx: #ctx,
current: null,
token: null,
hasCatch: ${this.catch.node.start !== null ? 'true' : 'false'},
pending: ${this.pending.block.name},
then: ${this.then.block.name},
catch: ${this.catch.block.name},
@ -231,6 +232,15 @@ export default class AwaitBlockWrapper extends Wrapper {
const dependencies = this.node.expression.dynamic_dependencies();
let update_child_context;
if (this.then.value && this.catch.value) {
update_child_context = b`#child_ctx[${this.then.value_index}] = #child_ctx[${this.catch.value_index}] = ${info}.resolved;`;
} else if (this.then.value) {
update_child_context = b`#child_ctx[${this.then.value_index}] = ${info}.resolved;`;
} else if (this.catch.value) {
update_child_context = b`#child_ctx[${this.catch.value_index}] = ${info}.resolved;`;
}
if (dependencies.length > 0) {
const condition = x`
${block.renderer.dirty(dependencies)} &&
@ -247,7 +257,7 @@ export default class AwaitBlockWrapper extends Wrapper {
} else {
const #child_ctx = #ctx.slice();
${this.then.value && b`#child_ctx[${this.then.value_index}] = ${info}.resolved;`}
${update_child_context}
${info}.block.p(#child_ctx, #dirty);
}
`);
@ -261,7 +271,7 @@ export default class AwaitBlockWrapper extends Wrapper {
block.chunks.update.push(b`
{
const #child_ctx = #ctx.slice();
${this.then.value && b`#child_ctx[${this.then.value_index}] = ${info}.resolved;`}
${update_child_context}
${info}.block.p(#child_ctx, #dirty);
}
`);

@ -7,6 +7,7 @@ import FragmentWrapper from './Fragment';
import { b, x } from 'code-red';
import ElseBlock from '../../nodes/ElseBlock';
import { Identifier, Node } from 'estree';
import get_object from '../../utils/get_object';
export class ElseBlockWrapper extends Wrapper {
node: ElseBlock;
@ -28,7 +29,7 @@ export class ElseBlockWrapper extends Wrapper {
this.block = block.child({
comment: create_debugging_comment(node, this.renderer.component),
name: this.renderer.component.get_unique_name(`create_else_block`),
name: this.renderer.component.get_unique_name('create_else_block'),
type: 'else'
});
@ -139,11 +140,8 @@ export default class EachBlockWrapper extends Wrapper {
view_length: fixed_length === null ? x`${iterations}.length` : fixed_length
};
const store =
node.expression.node.type === 'Identifier' &&
node.expression.node.name[0] === '$'
? node.expression.node.name.slice(1)
: null;
const object = get_object(node.expression.node);
const store = object.type === 'Identifier' && object.name[0] === '$' ? object.name.slice(1) : null;
node.contexts.forEach(prop => {
this.block.bindings.set(prop.key.name, {
@ -241,6 +239,11 @@ export default class EachBlockWrapper extends Wrapper {
this.node.expression.dynamic_dependencies().forEach((dependency: string) => {
all_dependencies.add(dependency);
});
if (this.node.key) {
this.node.key.dynamic_dependencies().forEach((dependency: string) => {
all_dependencies.add(dependency);
});
}
this.dependencies = all_dependencies;
if (this.node.key) {
@ -298,6 +301,19 @@ export default class EachBlockWrapper extends Wrapper {
}
`);
const has_transitions = !!(this.else.block.has_intro_method || this.else.block.has_outro_method);
const destroy_block_else = this.else.block.has_outro_method
? b`
@group_outros();
@transition_out(${each_block_else}, 1, 1, () => {
${each_block_else} = null;
});
@check_outros();`
: b`
${each_block_else}.d(1);
${each_block_else} = null;`;
if (this.else.block.has_update_method) {
this.updates.push(b`
if (!${this.vars.data_length} && ${each_block_else}) {
@ -305,22 +321,22 @@ export default class EachBlockWrapper extends Wrapper {
} else if (!${this.vars.data_length}) {
${each_block_else} = ${this.else.block.name}(#ctx);
${each_block_else}.c();
${has_transitions && b`@transition_in(${each_block_else}, 1);`}
${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
} else if (${each_block_else}) {
${each_block_else}.d(1);
${each_block_else} = null;
${destroy_block_else};
}
`);
} else {
this.updates.push(b`
if (${this.vars.data_length}) {
if (${each_block_else}) {
${each_block_else}.d(1);
${each_block_else} = null;
${destroy_block_else};
}
} else if (!${each_block_else}) {
${each_block_else} = ${this.else.block.name}(#ctx);
${each_block_else}.c();
${has_transitions && b`@transition_in(${each_block_else}, 1);`}
${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
}
`);
@ -425,11 +441,11 @@ export default class EachBlockWrapper extends Wrapper {
const destroy = this.node.has_animation
? (this.block.has_outros
? `@fix_and_outro_and_destroy_block`
: `@fix_and_destroy_block`)
? '@fix_and_outro_and_destroy_block'
: '@fix_and_destroy_block')
: this.block.has_outros
? `@outro_and_destroy_block`
: `@destroy_block`;
? '@outro_and_destroy_block'
: '@destroy_block';
if (this.dependencies.size) {
this.updates.push(b`
@ -547,7 +563,7 @@ export default class EachBlockWrapper extends Wrapper {
}
`;
const start = this.block.has_update_method ? 0 : `#old_length`;
const start = this.block.has_update_method ? 0 : '#old_length';
let remove_old_blocks;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save