Merge pull request #2 from sveltejs/master

pull/4957/head
swyx 5 years ago committed by GitHub
commit 8af69c264f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -5,10 +5,9 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
node-version: [8, 10, 12] node-version: [8, 10, 12, 14]
os: [ubuntu-latest, windows-latest, macOS-latest] os: [ubuntu-latest, windows-latest, macOS-latest]
steps: steps:
- run: git config --global core.autocrlf false
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: actions/setup-node@v1 - uses: actions/setup-node@v1
with: with:
@ -24,7 +23,10 @@ jobs:
- uses: actions/setup-node@v1 - uses: actions/setup-node@v1
- run: 'npm i && npm run lint' - run: 'npm i && npm run lint'
Unit: Unit:
runs-on: ubuntu-latest runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: actions/setup-node@v1 - uses: actions/setup-node@v1

1
.gitignore vendored

@ -1,6 +1,7 @@
.idea .idea
.DS_Store .DS_Store
.nyc_output .nyc_output
.vscode
node_modules node_modules
*.map *.map
/src/compiler/compile/internal_exports.ts /src/compiler/compile/internal_exports.ts

@ -1,9 +1,101 @@
# Svelte changelog # Svelte changelog
## Unreleased ## 3.23.0
* Update `<select>` with `bind:value` when the available `<option>`s change ([#1764](https://github.com/sveltejs/svelte/issues/1764))
* Add `muted` binding for media elements ([#2998](https://github.com/sveltejs/svelte/issues/2998))
* Fix inconsistencies when setting a two-way bound `<input>` to `undefined` ([#3569](https://github.com/sveltejs/svelte/issues/3569))
* Fix setting `<select multiple>` when there are spread attributes ([#4392](https://github.com/sveltejs/svelte/issues/4392))
* Fix let-less `<slot>` with context overflow ([#4624](https://github.com/sveltejs/svelte/issues/4624))
* Fix resize listening on certain older browsers ([#4752](https://github.com/sveltejs/svelte/issues/4752))
* Add `a11y-no-onchange` warning ([#4788](https://github.com/sveltejs/svelte/pull/4788))
* Fix `use:` actions being recreated when a keyed `{#each}` is reordered ([#4693](https://github.com/sveltejs/svelte/issues/4693))
* Fix `{@html}` when using tags that can only appear inside certain tags ([#4852](https://github.com/sveltejs/svelte/issues/4852))
* Fix reactivity when binding directly to `{#each}` context ([#4879](https://github.com/sveltejs/svelte/issues/4879))
## 3.22.3
* Support default values and trailing commas in destructuring `{#await}` ([#4560](https://github.com/sveltejs/svelte/issues/4560), [#4810](https://github.com/sveltejs/svelte/issues/4810))
* Fix handling of `tweened` store when set using `duration: 0` ([#4799](https://github.com/sveltejs/svelte/issues/4799), [#4846](https://github.com/sveltejs/svelte/issues/4846))
* Fix setting `value` attribute with `bind:group` and attribute spread ([#4803](https://github.com/sveltejs/svelte/issues/4803))
* Fix issue with compound `{#if}` block involving static condition, dynamic condition, and inline component ([#4840](https://github.com/sveltejs/svelte/issues/4840))
* Update a11y warnings per ARIA 1.2 working draft ([#4844](https://github.com/sveltejs/svelte/issues/4844))
## 3.22.2
* Fix compiler exception with `a11y-img-redundant-alt` and value-less `alt` attribute ([#4777](https://github.com/sveltejs/svelte/issues/4777))
## 3.22.1
* Fix compiler exception with `a11y-img-redundant-alt` and dynamic `alt` attribute ([#4770](https://github.com/sveltejs/svelte/issues/4770))
## 3.22.0
* Fix misaligned line numbers in source maps ([#3906](https://github.com/sveltejs/svelte/issues/3906))
* Make setting a `tweened` store using `duration: 0` instantly update the value ([#4399](https://github.com/sveltejs/svelte/issues/4399))
* Fix reactivity with imported values that are then mutated ([#4555](https://github.com/sveltejs/svelte/issues/4555))
* Fix contextual dynamic `bind:this` inside `{#each}` block ([#4686](https://github.com/sveltejs/svelte/issues/4686))
* Do not display a11y warning about missing `href` for `<a>` with `name` or `id` ([#4697](https://github.com/sveltejs/svelte/issues/4697))
* Disable infinite loop guard inside generators ([#4698](https://github.com/sveltejs/svelte/issues/4698))
* Display `a11y-invalid-attribute` warning for `href="javascript:..."` ([#4733](https://github.com/sveltejs/svelte/pull/4733))
* Implement `a11y-img-redundant-alt` warning ([#4750](https://github.com/sveltejs/svelte/pull/4750))
* Fix variable name conflict with component called `<Anchor>` ([#4768](https://github.com/sveltejs/svelte/issues/4768))
## 3.21.0
* Support dimension bindings in cross-origin environments ([#2147](https://github.com/sveltejs/svelte/issues/2147))
* Fix several related outro bugs ([#3202](https://github.com/sveltejs/svelte/issues/3202), [#3410](https://github.com/sveltejs/svelte/issues/3410), [#3685](https://github.com/sveltejs/svelte/issues/3685), [#4620](https://github.com/sveltejs/svelte/issues/4620), [#4630](https://github.com/sveltejs/svelte/issues/4630))
* Try using `globalThis` rather than `globals` for the benefit of non-Node servers and web workers ([#3561](https://github.com/sveltejs/svelte/issues/3561), [#4545](https://github.com/sveltejs/svelte/issues/4545))
* Support `{#await ... catch ...}` syntax shorthand ([#3623](https://github.com/sveltejs/svelte/issues/3623))
* Fix attaching of JS debugging comments to HTML comments ([#4565](https://github.com/sveltejs/svelte/issues/4565))
* Fix `<svelte:component/>` within `<slot/>` ([#4597](https://github.com/sveltejs/svelte/issues/4597))
* Fix bug with updating simple `{#if}` blocks ([#4629](https://github.com/sveltejs/svelte/issues/4629))
* Fix issues with `<input type="number">` updates ([#4631](https://github.com/sveltejs/svelte/issues/4631), [#4687](https://github.com/sveltejs/svelte/issues/4687))
* Prevent illegal attribute names ([#4648](https://github.com/sveltejs/svelte/issues/4648))
* Fix `{#if}` block directly within `<slot/>` ([#4703](https://github.com/sveltejs/svelte/issues/4703))
## 3.20.1
* Fix compiler regression with slots ([#4562](https://github.com/sveltejs/svelte/issues/4562))
## 3.20.0
* Allow destructuring in `{#await}` blocks ([#1851](https://github.com/sveltejs/svelte/issues/1851))
* Allow `<svelte:self>` to be used in a slot ([#2798](https://github.com/sveltejs/svelte/issues/2798))
* Expose object of unknown props in `$$restProps` ([#2930](https://github.com/sveltejs/svelte/issues/2930))
* Prevent passing named slots other than from the top level within a component ([#3385](https://github.com/sveltejs/svelte/issues/3385))
* Allow transitions and animations to work within iframes ([#3624](https://github.com/sveltejs/svelte/issues/3624))
* Fix initialising slot fallbacks when unnecessary ([#3763](https://github.com/sveltejs/svelte/issues/3763))
* Disallow binding directly to `const` variables ([#4479](https://github.com/sveltejs/svelte/issues/4479))
* Fix re-attaching event handlers on keyed `{#each}` blocks ([#4491](https://github.com/sveltejs/svelte/issues/4491))
* Fix updating keyed `{#each}` blocks with `{:else}` ([#4536](https://github.com/sveltejs/svelte/issues/4536), [#4549](https://github.com/sveltejs/svelte/issues/4549))
* Fix hydration of top-level content ([#4542](https://github.com/sveltejs/svelte/issues/4542))
## 3.19.2
* In `dev` mode, display a runtime warning when a component is passed an unexpected slot ([#1020](https://github.com/sveltejs/svelte/issues/1020), [#1447](https://github.com/sveltejs/svelte/issues/1447))
* In `vars` array, correctly indicate whether `module` variables are `mutated` or `reassigned` ([#3215](https://github.com/sveltejs/svelte/issues/3215))
* Fix spread props not updating in certain situations ([#3521](https://github.com/sveltejs/svelte/issues/3521), [#4480](https://github.com/sveltejs/svelte/issues/4480))
* Use the fallback content for slots if they are passed only whitespace ([#4092](https://github.com/sveltejs/svelte/issues/4092))
* Fix bitmask overflow for `{#if}` blocks ([#4263](https://github.com/sveltejs/svelte/issues/4263))
* In `dev` mode, check for unknown props even if the component has no writable props ([#4323](https://github.com/sveltejs/svelte/issues/4323))
* Exclude global variables from `$capture_state` ([#4463](https://github.com/sveltejs/svelte/issues/4463))
* Fix bitmask overflow for slots ([#4481](https://github.com/sveltejs/svelte/issues/4481))
## 3.19.1
* Do not treat modifications to `$$props` as updates to a store called `$props` ([#4368](https://github.com/sveltejs/svelte/issues/4368))
* Deconflict `value` parameter name used in contextual bindings ([#4445](https://github.com/sveltejs/svelte/issues/4445))
* Fix dev mode validation of `{#each}` blocks using strings ([#4450](https://github.com/sveltejs/svelte/issues/4450))
## 3.19.0
* Fix indirect bindings involving elements with spreads ([#3680](https://github.com/sveltejs/svelte/issues/3680)) * Fix indirect bindings involving elements with spreads ([#3680](https://github.com/sveltejs/svelte/issues/3680))
* `$capture_state`/`$inject_state` now act on the component's entire state, rather than its props ([#3822](https://github.com/sveltejs/svelte/pull/3822))
* Warn when using `<Foo/>` and `Foo` is dynamic ([#4331](https://github.com/sveltejs/svelte/issues/4331))
* Display compilation warnings in `svelte/register` in dev mode ([#4364](https://github.com/sveltejs/svelte/issues/4364))
* Fix unneeded updating of keyed each blocks ([#4373](https://github.com/sveltejs/svelte/issues/4373)) * Fix unneeded updating of keyed each blocks ([#4373](https://github.com/sveltejs/svelte/issues/4373))
* Throw runtime error in dev mode for non-array-like values in `{#each}` blocks ([#4408](https://github.com/sveltejs/svelte/issues/4408))
## 3.18.2 ## 3.18.2

@ -93,7 +93,7 @@ Test samples are kept in `/test/xxx/samples` folder.
#### Running tests #### Running tests
1. To run test, run `npm run test` 1. To run test, run `npm run test`.
1. To run test for a specific feature, you can use the `-g` (aka `--grep`) option. For example, to only run test involving transitions, run `npm run test -- -g transition`. 1. To run test for a specific feature, you can use the `-g` (aka `--grep`) option. For example, to only run test involving transitions, run `npm run test -- -g transition`.
##### Running solo test ##### Running solo test
@ -130,7 +130,7 @@ The core Svelte team will be monitoring for pull requests. Do help us by making
### Code conventions ### Code conventions
- `snake_case` for internal variable names and methods - `snake_case` for internal variable names and methods.
- `camelCase` for public variable names and methods. - `camelCase` for public variable names and methods.
## License ## License

@ -7,11 +7,6 @@
<img src="https://img.shields.io/npm/v/svelte.svg" alt="npm version"> <img src="https://img.shields.io/npm/v/svelte.svg" alt="npm version">
</a> </a>
<a href="https://github.com/sveltejs/svelte/actions">
<img src="https://github.com/sveltejs/svelte/workflows/CI/badge.svg?branch=master"
alt="build status">
</a>
<a href="https://github.com/sveltejs/svelte/blob/master/LICENSE"> <a href="https://github.com/sveltejs/svelte/blob/master/LICENSE">
<img src="https://img.shields.io/npm/l/svelte.svg" alt="license"> <img src="https://img.shields.io/npm/l/svelte.svg" alt="license">
</a> </a>
@ -37,10 +32,7 @@ cd svelte
npm install npm install
``` ```
> Many tests depend on newlines being preserved as `<LF>`. On Windows, you can ensure this by cloning with: > Do not use Yarn to install the dependencies, as the specific package versions in `package-lock.json` are used to build and test Svelte.
> ```bash
> git -c core.autocrlf=false clone https://github.com/sveltejs/svelte.git
> ```
To build the compiler, and all the other modules included in the package: To build the compiler, and all the other modules included in the package:
@ -80,6 +72,9 @@ npm install && npm run update
npm run dev npm run dev
``` ```
### Is svelte.dev down?
Probably not, but it's possible. If you can't seem to access any `.dev` sites, check out [this SuperUser question and answer](https://superuser.com/q/1413402).
## License ## License

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

285
package-lock.json generated

@ -1,6 +1,6 @@
{ {
"name": "svelte", "name": "svelte",
"version": "3.18.2", "version": "3.23.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -137,6 +137,12 @@
} }
} }
}, },
"@tootallnate/once": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.0.0.tgz",
"integrity": "sha512-KYyTT/T6ALPkIRd2Ge080X/BsXvy9O0hcWTtMWkPvwAwF99+vn6Dv4GzrFT/Nn1LePr+FFDbRXXlqmsy9lw2zA==",
"dev": true
},
"@types/eslint-visitor-keys": { "@types/eslint-visitor-keys": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
@ -274,9 +280,9 @@
"dev": true "dev": true
}, },
"acorn": { "acorn": {
"version": "7.1.0", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
"integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==",
"dev": true "dev": true
}, },
"acorn-globals": { "acorn-globals": {
@ -290,9 +296,9 @@
}, },
"dependencies": { "dependencies": {
"acorn": { "acorn": {
"version": "6.3.0", "version": "6.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
"integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
"dev": true "dev": true
} }
} }
@ -486,6 +492,12 @@
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
"dev": true "dev": true
}, },
"buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
"dev": true
},
"buffer-from": { "buffer-from": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
@ -609,16 +621,16 @@
} }
}, },
"codecov": { "codecov": {
"version": "3.5.0", "version": "3.6.5",
"resolved": "https://registry.npmjs.org/codecov/-/codecov-3.5.0.tgz", "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.6.5.tgz",
"integrity": "sha512-/OsWOfIHaQIr7aeZ4pY0UC1PZT6kimoKFOFYFNb6wxo3iw12nRrh+mNGH72rnXxNsq6SGfesVPizm/6Q3XqcFQ==", "integrity": "sha512-v48WuDMUug6JXwmmfsMzhCHRnhUf8O3duqXvltaYJKrO1OekZWpB/eH6iIoaxMl8Qli0+u3OxptdsBOYiD7VAQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"argv": "^0.0.2", "argv": "0.0.2",
"ignore-walk": "^3.0.1", "ignore-walk": "3.0.3",
"js-yaml": "^3.13.1", "js-yaml": "3.13.1",
"teeny-request": "^3.11.3", "teeny-request": "6.0.1",
"urlgrey": "^0.4.4" "urlgrey": "0.4.4"
} }
}, },
"color-convert": { "color-convert": {
@ -1346,15 +1358,15 @@
} }
}, },
"extract-zip": { "extract-zip": {
"version": "1.6.7", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz",
"integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==",
"dev": true, "dev": true,
"requires": { "requires": {
"concat-stream": "1.6.2", "concat-stream": "^1.6.2",
"debug": "2.6.9", "debug": "^2.6.9",
"mkdirp": "0.5.1", "mkdirp": "^0.5.4",
"yauzl": "2.4.1" "yauzl": "^2.10.0"
}, },
"dependencies": { "dependencies": {
"debug": { "debug": {
@ -1399,9 +1411,9 @@
"dev": true "dev": true
}, },
"fd-slicer": { "fd-slicer": {
"version": "1.0.1", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
"integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
"dev": true, "dev": true,
"requires": { "requires": {
"pend": "~1.2.0" "pend": "~1.2.0"
@ -1592,26 +1604,6 @@
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
"dev": true "dev": true
}, },
"handlebars": {
"version": "4.5.3",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
"integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
"dev": true,
"requires": {
"neo-async": "^2.6.0",
"optimist": "^0.6.1",
"source-map": "^0.6.1",
"uglify-js": "^3.1.4"
},
"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
}
}
},
"har-schema": { "har-schema": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
@ -1670,6 +1662,43 @@
"whatwg-encoding": "^1.0.1" "whatwg-encoding": "^1.0.1"
} }
}, },
"html-escaper": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"dev": true
},
"http-proxy-agent": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
"integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
"dev": true,
"requires": {
"@tootallnate/once": "1",
"agent-base": "6",
"debug": "4"
},
"dependencies": {
"agent-base": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz",
"integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==",
"dev": true,
"requires": {
"debug": "4"
}
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
}
}
},
"http-signature": { "http-signature": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
@ -1707,9 +1736,9 @@
"dev": true "dev": true
}, },
"ignore-walk": { "ignore-walk": {
"version": "3.0.1", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
"integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
"dev": true, "dev": true,
"requires": { "requires": {
"minimatch": "^3.0.4" "minimatch": "^3.0.4"
@ -1947,12 +1976,12 @@
} }
}, },
"istanbul-reports": { "istanbul-reports": {
"version": "2.2.6", "version": "2.2.7",
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz",
"integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==",
"dev": true, "dev": true,
"requires": { "requires": {
"handlebars": "^4.1.2" "html-escaper": "^2.0.0"
} }
}, },
"js-tokens": { "js-tokens": {
@ -2012,9 +2041,9 @@
}, },
"dependencies": { "dependencies": {
"acorn": { "acorn": {
"version": "6.3.0", "version": "6.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
"integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
"dev": true "dev": true
}, },
"ws": { "ws": {
@ -2264,26 +2293,18 @@
} }
}, },
"minimist": { "minimist": {
"version": "0.0.10", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true "dev": true
}, },
"mkdirp": { "mkdirp": {
"version": "0.5.1", "version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "^1.2.5"
},
"dependencies": {
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true
}
} }
}, },
"mocha": { "mocha": {
@ -2360,6 +2381,21 @@
"path-is-absolute": "^1.0.0" "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": { "ms": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
@ -2497,12 +2533,6 @@
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
"dev": true "dev": true
}, },
"neo-async": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
"integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
"dev": true
},
"nice-try": { "nice-try": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
@ -2650,16 +2680,6 @@
} }
} }
}, },
"optimist": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
"integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
"dev": true,
"requires": {
"minimist": "~0.0.1",
"wordwrap": "~0.0.2"
}
},
"optionator": { "optionator": {
"version": "0.8.2", "version": "0.8.2",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
@ -3010,9 +3030,9 @@
} }
}, },
"readable-stream": { "readable-stream": {
"version": "2.3.6", "version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"dev": true, "dev": true,
"requires": { "requires": {
"core-util-is": "~1.0.0", "core-util-is": "~1.0.0",
@ -3362,6 +3382,15 @@
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=",
"dev": true "dev": true
}, },
"stream-events": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz",
"integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==",
"dev": true,
"requires": {
"stubs": "^3.0.0"
}
},
"string-width": { "string-width": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
@ -3409,6 +3438,12 @@
"integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==",
"dev": true "dev": true
}, },
"stubs": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz",
"integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=",
"dev": true
},
"sucrase": { "sucrase": {
"version": "3.10.1", "version": "3.10.1",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.10.1.tgz", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.10.1.tgz",
@ -3449,14 +3484,43 @@
} }
}, },
"teeny-request": { "teeny-request": {
"version": "3.11.3", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-3.11.3.tgz", "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.1.tgz",
"integrity": "sha512-CKncqSF7sH6p4rzCgkb/z/Pcos5efl0DmolzvlqRQUNcpRIruOhY9+T1FsIlyEbfWd7MsFpodROOwHYh2BaXzw==", "integrity": "sha512-TAK0c9a00ELOqLrZ49cFxvPVogMUFaWY8dUsQc/0CuQPGF+BOxOQzXfE413BAk2kLomwNplvdtMpeaeGWmoc2g==",
"dev": true, "dev": true,
"requires": { "requires": {
"https-proxy-agent": "^2.2.1", "http-proxy-agent": "^4.0.0",
"https-proxy-agent": "^4.0.0",
"node-fetch": "^2.2.0", "node-fetch": "^2.2.0",
"stream-events": "^1.0.5",
"uuid": "^3.3.2" "uuid": "^3.3.2"
},
"dependencies": {
"agent-base": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz",
"integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==",
"dev": true
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"https-proxy-agent": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz",
"integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==",
"dev": true,
"requires": {
"agent-base": "5",
"debug": "4"
}
}
} }
}, },
"test-exclude": { "test-exclude": {
@ -3591,26 +3655,6 @@
"integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==", "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==",
"dev": true "dev": true
}, },
"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,
"optional": 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,
"optional": true
}
}
},
"uri-js": { "uri-js": {
"version": "4.2.2", "version": "4.2.2",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
@ -3779,12 +3823,6 @@
} }
} }
}, },
"wordwrap": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
"dev": true
},
"wrap-ansi": { "wrap-ansi": {
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
@ -4031,12 +4069,13 @@
} }
}, },
"yauzl": { "yauzl": {
"version": "2.4.1", "version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
"integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
"dev": true, "dev": true,
"requires": { "requires": {
"fd-slicer": "~1.0.1" "buffer-crc32": "~0.2.3",
"fd-slicer": "~1.1.0"
} }
} }
} }

@ -1,6 +1,6 @@
{ {
"name": "svelte", "name": "svelte",
"version": "3.18.2", "version": "3.23.0",
"description": "Cybernetically enhanced web apps", "description": "Cybernetically enhanced web apps",
"module": "index.mjs", "module": "index.mjs",
"main": "index", "main": "index",

@ -36,7 +36,15 @@ function registerExtension(extension) {
format: 'cjs' format: 'cjs'
}); });
const { js } = compile(fs.readFileSync(filename, 'utf-8'), options); const { js, warnings } = compile(fs.readFileSync(filename, 'utf-8'), options);
if (options.dev) {
warnings.forEach(warning => {
console.warn(`\nSvelte Warning in ${warning.filename}:`);
console.warn(warning.message);
console.warn(warning.frame);
})
}
return module._compile(js.code, filename); return module._compile(js.code, filename);
}; };

@ -18,7 +18,7 @@ You'll be using the *command line*, also known as the terminal. On Windows, you
The command line is a way to interact with your computer (or another computer! but that's a topic for another time) with more power and control than the GUI (graphical user interface) that most people use day-to-day. The command line is a way to interact with your computer (or another computer! but that's a topic for another time) with more power and control than the GUI (graphical user interface) that most people use day-to-day.
Once on the command line, you can navigate the filesystem using `ls` to list the contents of your current directory, and `cd` to change the current directory. For example, if you had a `Development` directory of your projects inside your home directory, you would type Once on the command line, you can navigate the filesystem using `ls` (`dir` on Windows) to list the contents of your current directory, and `cd` to change the current directory. For example, if you had a `Development` directory of your projects inside your home directory, you would type
```bash ```bash
cd Development cd Development
@ -34,7 +34,7 @@ cd svelte-projects
A full introduction to the command line is out of the scope of this guide, but here are a few more useful commands: A full introduction to the command line is out of the scope of this guide, but here are a few more useful commands:
* `cd ..` — navigates to the parent of the current directory * `cd ..` — navigates to the parent of the current directory
* `cat my-file.txt` — on Mac/Linux, lists the contents of `my-file.txt` * `cat my-file.txt` — on Mac/Linux (`type my-file.txt` on Windows), lists the contents of `my-file.txt`
* `open .` (or `start .` on Windows) — opens the current directory in Finder or File Explorer * `open .` (or `start .` on Windows) — opens the current directory in Finder or File Explorer

@ -6,4 +6,6 @@ This page contains detailed API reference documentation. It's intended to be a r
If that's not you (yet), you may prefer to visit the [interactive tutorial](tutorial) or the [examples](examples) before consulting this reference. If that's not you (yet), you may prefer to visit the [interactive tutorial](tutorial) or the [examples](examples) before consulting this reference.
Don't be shy about asking for help in the [Discord chatroom](chat). Don't be shy about asking for help in the [Discord chatroom](chat).
Using an older version of Svelte? Have a look at the [v2 docs](https://v2.svelte.dev).

@ -8,7 +8,7 @@ Components are the building blocks of Svelte applications. They are written into
All three sections — script, styles and markup — are optional. All three sections — script, styles and markup — are optional.
```html ```sv
<script> <script>
// logic goes here // logic goes here
</script> </script>
@ -30,7 +30,7 @@ A `<script>` block contains JavaScript that runs when a component instance is cr
Svelte uses the `export` keyword to mark a variable declaration as a *property* or *prop*, which means it becomes accessible to consumers of the component (see the section on [attributes and props](docs#Attributes_and_props) for more information). Svelte uses the `export` keyword to mark a variable declaration as a *property* or *prop*, which means it becomes accessible to consumers of the component (see the section on [attributes and props](docs#Attributes_and_props) for more information).
```html ```sv
<script> <script>
export let foo; export let foo;
@ -42,13 +42,13 @@ Svelte uses the `export` keyword to mark a variable declaration as a *property*
--- ---
You can specify a default value, which will be used if the component's consumer doesn't specify a prop. You can specify a default initial value for a prop. It will be used if the component's consumer doesn't specify the prop on the component (or if its initial value is `undefined`) when instantiating the component. Note that whenever a prop is removed by the consumer, its value is set to `undefined` rather than the initial value.
In development mode (see the [compiler options](docs#svelte_compile)), a warning will be printed if no default is provided and the consumer does not specify a value. To squelch this warning, ensure that a default is specified, even if it is `undefined`. In development mode (see the [compiler options](docs#svelte_compile)), a warning will be printed if no default initial value is provided and the consumer does not specify a value. To squelch this warning, ensure that a default initial value is specified, even if it is `undefined`.
```html ```sv
<script> <script>
export let bar = 'optional default value'; export let bar = 'optional default initial value';
export let baz = undefined; export let baz = undefined;
</script> </script>
``` ```
@ -57,7 +57,7 @@ In development mode (see the [compiler options](docs#svelte_compile)), a warning
If you export a `const`, `class` or `function`, it is readonly from outside the component. Function *expressions* are valid props, however. If you export a `const`, `class` or `function`, it is readonly from outside the component. Function *expressions* are valid props, however.
```html ```sv
<script> <script>
// these are readonly // these are readonly
export const thisIs = 'readonly'; export const thisIs = 'readonly';
@ -75,7 +75,7 @@ If you export a `const`, `class` or `function`, it is readonly from outside the
You can use reserved words as prop names. You can use reserved words as prop names.
```html ```sv
<script> <script>
let className; let className;
@ -95,7 +95,7 @@ Update expressions (`count += 1`) and property assignments (`obj.x = y`) have th
Because Svelte's reactivity is based on assignments, using array methods like `.push()` and `.splice()` won't automatically trigger updates. Options for getting around this can be found in the [tutorial](tutorial/updating-arrays-and-objects). Because Svelte's reactivity is based on assignments, using array methods like `.push()` and `.splice()` won't automatically trigger updates. Options for getting around this can be found in the [tutorial](tutorial/updating-arrays-and-objects).
```html ```sv
<script> <script>
let count = 0; let count = 0;
@ -113,7 +113,7 @@ Because Svelte's reactivity is based on assignments, using array methods like `.
Any top-level statement (i.e. not inside a block or a function) can be made reactive by prefixing it with the `$:` [JS label syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label). Reactive statements run immediately before the component updates, whenever the values that they depend on have changed. Any top-level statement (i.e. not inside a block or a function) can be made reactive by prefixing it with the `$:` [JS label syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label). Reactive statements run immediately before the component updates, whenever the values that they depend on have changed.
```html ```sv
<script> <script>
export let title; export let title;
@ -132,7 +132,7 @@ Any top-level statement (i.e. not inside a block or a function) can be made reac
If a statement consists entirely of an assignment to an undeclared variable, Svelte will inject a `let` declaration on your behalf. If a statement consists entirely of an assignment to an undeclared variable, Svelte will inject a `let` declaration on your behalf.
```html ```sv
<script> <script>
export let num; export let num;
@ -157,7 +157,7 @@ Note that the store must be declared at the top level of the component — not i
Local variables (that do not represent store values) must *not* have a `$` prefix. Local variables (that do not represent store values) must *not* have a `$` prefix.
```html ```sv
<script> <script>
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
@ -175,7 +175,7 @@ Local variables (that do not represent store values) must *not* have a `$` prefi
##### Store contract ##### Store contract
```js ```js
store = { subscribe: (subscription: (value: any) => void) => () => void, set?: (value: any) => void } store = { subscribe: (subscription: (value: any) => void) => (() => void), set?: (value: any) => void }
``` ```
You can create your own stores without relying on [`svelte/store`](docs#svelte_store), by implementing the *store contract*: You can create your own stores without relying on [`svelte/store`](docs#svelte_store), by implementing the *store contract*:
@ -199,7 +199,7 @@ You cannot `export default`, since the default export is the component itself.
> Variables defined in `module` scripts are not reactive — reassigning them will not trigger a rerender even though the variable itself will update. For values shared between multiple components, consider using a [store](docs#svelte_store). > Variables defined in `module` scripts are not reactive — reassigning them will not trigger a rerender even though the variable itself will update. For values shared between multiple components, consider using a [store](docs#svelte_store).
```html ```sv
<script context="module"> <script context="module">
let totalComponents = 0; let totalComponents = 0;
@ -225,7 +225,7 @@ CSS inside a `<style>` block will be scoped to that component.
This works by adding a class to affected elements, which is based on a hash of the component styles (e.g. `svelte-123xyz`). This works by adding a class to affected elements, which is based on a hash of the component styles (e.g. `svelte-123xyz`).
```html ```sv
<style> <style>
p { p {
/* this will only affect <p> elements in this component */ /* this will only affect <p> elements in this component */
@ -238,7 +238,7 @@ This works by adding a class to affected elements, which is based on a hash of t
To apply styles to a selector globally, use the `:global(...)` modifier. To apply styles to a selector globally, use the `:global(...)` modifier.
```html ```sv
<style> <style>
:global(body) { :global(body) {
/* this will apply to <body> */ /* this will apply to <body> */

@ -9,7 +9,7 @@ title: Template syntax
A lowercase tag, like `<div>`, denotes a regular HTML element. A capitalised tag, such as `<Widget>` or `<Namespace.Widget>`, indicates a *component*. A lowercase tag, like `<div>`, denotes a regular HTML element. A capitalised tag, such as `<Widget>` or `<Namespace.Widget>`, indicates a *component*.
```html ```sv
<script> <script>
import Widget from './Widget.svelte'; import Widget from './Widget.svelte';
</script> </script>
@ -26,7 +26,7 @@ A lowercase tag, like `<div>`, denotes a regular HTML element. A capitalised tag
By default, attributes work exactly like their HTML counterparts. By default, attributes work exactly like their HTML counterparts.
```html ```sv
<div class="foo"> <div class="foo">
<button disabled>can't touch this</button> <button disabled>can't touch this</button>
</div> </div>
@ -36,7 +36,7 @@ By default, attributes work exactly like their HTML counterparts.
As in HTML, values may be unquoted. As in HTML, values may be unquoted.
```html ```sv
<input type=checkbox> <input type=checkbox>
``` ```
@ -44,7 +44,7 @@ As in HTML, values may be unquoted.
Attribute values can contain JavaScript expressions. Attribute values can contain JavaScript expressions.
```html ```sv
<a href="page/{p}">page {p}</a> <a href="page/{p}">page {p}</a>
``` ```
@ -52,15 +52,26 @@ Attribute values can contain JavaScript expressions.
Or they can *be* JavaScript expressions. Or they can *be* JavaScript expressions.
```html ```sv
<button disabled={!clickable}>...</button> <button disabled={!clickable}>...</button>
``` ```
--- ---
An expression might include characters that would cause syntax highlighting to fail in regular HTML, so quoting the value is permitted. The quotes do not affect how the value is parsed: Boolean attributes are included on the element if their value is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) and excluded if it's [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy).
All other attributes are included unless their value is [nullish](https://developer.mozilla.org/en-US/docs/Glossary/Nullish) (`null` or `undefined`).
```html ```html
<input required={false} placeholder="This input field is not required">
<div title={null}>This div has no title attribute</div>
```
---
An expression might include characters that would cause syntax highlighting to fail in regular HTML, so quoting the value is permitted. The quotes do not affect how the value is parsed:
```sv
<button disabled="{number !== 42}">...</button> <button disabled="{number !== 42}">...</button>
``` ```
@ -68,7 +79,7 @@ An expression might include characters that would cause syntax highlighting to f
When the attribute name and value match (`name={name}`), they can be replaced with `{name}`. When the attribute name and value match (`name={name}`), they can be replaced with `{name}`.
```html ```sv
<!-- These are equivalent --> <!-- These are equivalent -->
<button disabled={disabled}>...</button> <button disabled={disabled}>...</button>
<button {disabled}>...</button> <button {disabled}>...</button>
@ -80,7 +91,7 @@ By convention, values passed to components are referred to as *properties* or *p
As with elements, `name={name}` can be replaced with the `{name}` shorthand. As with elements, `name={name}` can be replaced with the `{name}` shorthand.
```html ```sv
<Widget foo={bar} answer={42} text="hello"/> <Widget foo={bar} answer={42} text="hello"/>
``` ```
@ -90,7 +101,7 @@ As with elements, `name={name}` can be replaced with the `{name}` shorthand.
An element or component can have multiple spread attributes, interspersed with regular ones. An element or component can have multiple spread attributes, interspersed with regular ones.
```html ```sv
<Widget {...things}/> <Widget {...things}/>
``` ```
@ -98,10 +109,22 @@ 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 useful in rare cases, but not generally recommended, as it is difficult for Svelte to optimise.
```html ```sv
<Widget {...$$props}/> <Widget {...$$props}/>
``` ```
---
*`$$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.
```html
<input {...$$restProps}>
```
> The `value` attribute of an `input` element or its children `option` elements must not be set with spread attributes when using `bind:group` or `bind:checked`. Svelte needs to be able to see the element's `value` directly in the markup in these cases so that it can link it to the bound variable.
---
### Text expressions ### Text expressions
@ -113,7 +136,7 @@ An element or component can have multiple spread attributes, interspersed with r
Text can also contain JavaScript expressions: Text can also contain JavaScript expressions:
```html ```sv
<h1>Hello {name}!</h1> <h1>Hello {name}!</h1>
<p>{a} + {b} = {a + b}.</p> <p>{a} + {b} = {a + b}.</p>
``` ```
@ -125,7 +148,7 @@ Text can also contain JavaScript expressions:
You can use HTML comments inside components. You can use HTML comments inside components.
```html ```sv
<!-- this is a comment! --> <!-- this is a comment! -->
<h1>Hello world</h1> <h1>Hello world</h1>
``` ```
@ -134,7 +157,7 @@ You can use HTML comments inside components.
Comments beginning with `svelte-ignore` disable warnings for the next block of markup. Usually these are accessibility warnings; make sure that you're disabling them for a good reason. Comments beginning with `svelte-ignore` disable warnings for the next block of markup. Usually these are accessibility warnings; make sure that you're disabling them for a good reason.
```html ```sv
<!-- svelte-ignore a11y-autofocus --> <!-- svelte-ignore a11y-autofocus -->
<input bind:value={name} autofocus> <input bind:value={name} autofocus>
``` ```
@ -156,7 +179,7 @@ Comments beginning with `svelte-ignore` disable warnings for the next block of m
Content that is conditionally rendered can be wrapped in an if block. Content that is conditionally rendered can be wrapped in an if block.
```html ```sv
{#if answer === 42} {#if answer === 42}
<p>what was the question?</p> <p>what was the question?</p>
{/if} {/if}
@ -166,7 +189,7 @@ Content that is conditionally rendered can be wrapped in an if block.
Additional conditions can be added with `{:else if expression}`, optionally ending in an `{:else}` clause. Additional conditions can be added with `{:else if expression}`, optionally ending in an `{:else}` clause.
```html ```sv
{#if porridge.temperature > 100} {#if porridge.temperature > 100}
<p>too hot!</p> <p>too hot!</p>
{:else if 80 > porridge.temperature} {:else if 80 > porridge.temperature}
@ -186,6 +209,9 @@ Additional conditions can be added with `{:else if expression}`, optionally endi
{#each expression as name, index}...{/each} {#each expression as name, index}...{/each}
``` ```
```sv ```sv
{#each expression as name (key)}...{/each}
```
```sv
{#each expression as name, index (key)}...{/each} {#each expression as name, index (key)}...{/each}
``` ```
```sv ```sv
@ -196,7 +222,7 @@ Additional conditions can be added with `{:else if expression}`, optionally endi
Iterating over lists of values can be done with an each block. Iterating over lists of values can be done with an each block.
```html ```sv
<h1>Shopping list</h1> <h1>Shopping list</h1>
<ul> <ul>
{#each items as item} {#each items as item}
@ -211,7 +237,7 @@ You can use each blocks to iterate over any array or array-like value — that i
An each block can also specify an *index*, equivalent to the second argument in an `array.map(...)` callback: An each block can also specify an *index*, equivalent to the second argument in an `array.map(...)` callback:
```html ```sv
{#each items as item, i} {#each items as item, i}
<li>{i + 1}: {item.name} x {item.qty}</li> <li>{i + 1}: {item.name} x {item.qty}</li>
{/each} {/each}
@ -221,7 +247,12 @@ An each block can also specify an *index*, equivalent to the second argument in
If a *key* expression is provided — which must uniquely identify each list item — Svelte will use it to diff the list when data changes, rather than adding or removing items at the end. The key can be any object, but strings and numbers are recommended since they allow identity to persist when the objects themselves change. If a *key* expression is provided — which must uniquely identify each list item — Svelte will use it to diff the list when data changes, rather than adding or removing items at the end. The key can be any object, but strings and numbers are recommended since they allow identity to persist when the objects themselves change.
```html ```sv
{#each items as item (item.id)}
<li>{item.name} x {item.qty}</li>
{/each}
<!-- or with additional index value -->
{#each items as item, i (item.id)} {#each items as item, i (item.id)}
<li>{i + 1}: {item.name} x {item.qty}</li> <li>{i + 1}: {item.name} x {item.qty}</li>
{/each} {/each}
@ -231,7 +262,7 @@ If a *key* expression is provided — which must uniquely identify each list ite
You can freely use destructuring and rest patterns in each blocks. You can freely use destructuring and rest patterns in each blocks.
```html ```sv
{#each items as { id, name, qty }, i (id)} {#each items as { id, name, qty }, i (id)}
<li>{i + 1}: {name} x {qty}</li> <li>{i + 1}: {name} x {qty}</li>
{/each} {/each}
@ -249,7 +280,7 @@ You can freely use destructuring and rest patterns in each blocks.
An each block can also have an `{:else}` clause, which is rendered if the list is empty. An each block can also have an `{:else}` clause, which is rendered if the list is empty.
```html ```sv
{#each todos as todo} {#each todos as todo}
<p>{todo.text}</p> <p>{todo.text}</p>
{:else} {:else}
@ -274,7 +305,7 @@ An each block can also have an `{:else}` clause, which is rendered if the list i
Await blocks allow you to branch on the three possible states of a Promise — pending, fulfilled or rejected. Await blocks allow you to branch on the three possible states of a Promise — pending, fulfilled or rejected.
```html ```sv
{#await promise} {#await promise}
<!-- promise is pending --> <!-- promise is pending -->
<p>waiting for the promise to resolve...</p> <p>waiting for the promise to resolve...</p>
@ -291,7 +322,7 @@ Await blocks allow you to branch on the three possible states of a Promise — p
The `catch` block can be omitted if you don't need to render anything when the promise rejects (or no error is possible). The `catch` block can be omitted if you don't need to render anything when the promise rejects (or no error is possible).
```html ```sv
{#await promise} {#await promise}
<!-- promise is pending --> <!-- promise is pending -->
<p>waiting for the promise to resolve...</p> <p>waiting for the promise to resolve...</p>
@ -305,7 +336,7 @@ The `catch` block can be omitted if you don't need to render anything when the p
If you don't care about the pending state, you can also omit the initial block. If you don't care about the pending state, you can also omit the initial block.
```html ```sv
{#await promise then value} {#await promise then value}
<p>The value is {value}</p> <p>The value is {value}</p>
{/await} {/await}
@ -326,7 +357,7 @@ The expression should be valid standalone HTML — `{@html "<div>"}content{@html
> Svelte does not sanitize expressions before injecting HTML. If the data comes from an untrusted source, you must sanitize it, or you are exposing your users to an XSS vulnerability. > Svelte does not sanitize expressions before injecting HTML. If the data comes from an untrusted source, you must sanitize it, or you are exposing your users to an XSS vulnerability.
```html ```sv
<div class="blog-post"> <div class="blog-post">
<h1>{post.title}</h1> <h1>{post.title}</h1>
{@html post.content} {@html post.content}
@ -349,7 +380,7 @@ The `{@debug ...}` tag offers an alternative to `console.log(...)`. It logs the
It accepts a comma-separated list of variable names (not arbitrary expressions). It accepts a comma-separated list of variable names (not arbitrary expressions).
```html ```sv
<script> <script>
let user = { let user = {
firstname: 'Ada', firstname: 'Ada',
@ -366,7 +397,7 @@ It accepts a comma-separated list of variable names (not arbitrary expressions).
`{@debug ...}` accepts a comma-separated list of variable names (not arbitrary expressions). `{@debug ...}` accepts a comma-separated list of variable names (not arbitrary expressions).
```html ```sv
<!-- Compiles --> <!-- Compiles -->
{@debug user} {@debug user}
{@debug user1, user2, user3} {@debug user1, user2, user3}
@ -400,7 +431,7 @@ on:eventname|modifiers={handler}
Use the `on:` directive to listen to DOM events. Use the `on:` directive to listen to DOM events.
```html ```sv
<script> <script>
let count = 0; let count = 0;
@ -418,7 +449,7 @@ Use the `on:` directive to listen to DOM events.
Handlers can be declared inline with no performance penalty. As with attributes, directive values may be quoted for the sake of syntax highlighters. Handlers can be declared inline with no performance penalty. As with attributes, directive values may be quoted for the sake of syntax highlighters.
```html ```sv
<button on:click="{() => count += 1}"> <button on:click="{() => count += 1}">
count: {count} count: {count}
</button> </button>
@ -428,7 +459,7 @@ Handlers can be declared inline with no performance penalty. As with attributes,
Add *modifiers* to DOM events with the `|` character. Add *modifiers* to DOM events with the `|` character.
```html ```sv
<form on:submit|preventDefault={handleSubmit}> <form on:submit|preventDefault={handleSubmit}>
<!-- the `submit` event's default is prevented, <!-- the `submit` event's default is prevented,
so the page won't reload --> so the page won't reload -->
@ -442,6 +473,7 @@ The following modifiers are available:
* `passive` — improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so) * `passive` — improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so)
* `capture` — fires the handler during the *capture* phase instead of the *bubbling* phase * `capture` — fires the handler during the *capture* phase instead of the *bubbling* phase
* `once` — remove the handler after the first time it runs * `once` — remove the handler after the first time it runs
* `self` — only trigger handler if event.target is the element itself
Modifiers can be chained together, e.g. `on:click|once|capture={...}`. Modifiers can be chained together, e.g. `on:click|once|capture={...}`.
@ -449,7 +481,7 @@ Modifiers can be chained together, e.g. `on:click|once|capture={...}`.
If the `on:` directive is used without a value, the component will *forward* the event, meaning that a consumer of the component can listen for it. If the `on:` directive is used without a value, the component will *forward* the event, meaning that a consumer of the component can listen for it.
```html ```sv
<button on:click> <button on:click>
The component itself will emit the click event The component itself will emit the click event
</button> </button>
@ -459,7 +491,7 @@ If the `on:` directive is used without a value, the component will *forward* the
It's possible to have multiple event listeners for the same event: It's possible to have multiple event listeners for the same event:
```html ```sv
<script> <script>
let counter = 0; let counter = 0;
function increment() { function increment() {
@ -486,7 +518,7 @@ Data ordinarily flows down, from parent to child. The `bind:` directive allows d
The simplest bindings reflect the value of a property, such as `input.value`. The simplest bindings reflect the value of a property, such as `input.value`.
```html ```sv
<input bind:value={name}> <input bind:value={name}>
<textarea bind:value={text}></textarea> <textarea bind:value={text}></textarea>
@ -497,7 +529,7 @@ The simplest bindings reflect the value of a property, such as `input.value`.
If the name matches the value, you can use a shorthand. If the name matches the value, you can use a shorthand.
```html ```sv
<!-- These are equivalent --> <!-- These are equivalent -->
<input bind:value={value}> <input bind:value={value}>
<input bind:value> <input bind:value>
@ -507,7 +539,7 @@ If the name matches the value, you can use a shorthand.
Numeric input values are coerced; even though `input.value` is a string as far as the DOM is concerned, Svelte will treat it as a number. If the input is empty or invalid (in the case of `type="number"`), the value is `undefined`. Numeric input values are coerced; even though `input.value` is a string as far as the DOM is concerned, Svelte will treat it as a number. If the input is empty or invalid (in the case of `type="number"`), the value is `undefined`.
```html ```sv
<input type="number" bind:value={num}> <input type="number" bind:value={num}>
<input type="range" bind:value={num}> <input type="range" bind:value={num}>
``` ```
@ -519,7 +551,7 @@ Numeric input values are coerced; even though `input.value` is a string as far a
A `<select>` value binding corresponds to the `value` property on the selected `<option>`, which can be any value (not just strings, as is normally the case in the DOM). A `<select>` value binding corresponds to the `value` property on the selected `<option>`, which can be any value (not just strings, as is normally the case in the DOM).
```html ```sv
<select bind:value={selected}> <select bind:value={selected}>
<option value={a}>a</option> <option value={a}>a</option>
<option value={b}>b</option> <option value={b}>b</option>
@ -531,7 +563,7 @@ A `<select>` value binding corresponds to the `value` property on the selected `
A `<select multiple>` element behaves similarly to a checkbox group. A `<select multiple>` element behaves similarly to a checkbox group.
```html ```sv
<select multiple bind:value={fillings}> <select multiple bind:value={fillings}>
<option value="Rice">Rice</option> <option value="Rice">Rice</option>
<option value="Beans">Beans</option> <option value="Beans">Beans</option>
@ -544,7 +576,7 @@ A `<select multiple>` element behaves similarly to a checkbox group.
When the value of an `<option>` matches its text content, the attribute can be omitted. When the value of an `<option>` matches its text content, the attribute can be omitted.
```html ```sv
<select multiple bind:value={fillings}> <select multiple bind:value={fillings}>
<option>Rice</option> <option>Rice</option>
<option>Beans</option> <option>Beans</option>
@ -557,7 +589,7 @@ When the value of an `<option>` matches its text content, the attribute can be o
Elements with the `contenteditable` attribute support `innerHTML` and `textContent` bindings. Elements with the `contenteditable` attribute support `innerHTML` and `textContent` bindings.
```html ```sv
<div contenteditable="true" bind:innerHTML={html}></div> <div contenteditable="true" bind:innerHTML={html}></div>
``` ```
@ -574,16 +606,17 @@ Media elements (`<audio>` and `<video>`) have their own set of bindings — six
* `seeking` (readonly) — boolean * `seeking` (readonly) — boolean
* `ended` (readonly) — boolean * `ended` (readonly) — boolean
...and four *two-way* bindings: ...and five *two-way* bindings:
* `currentTime` — the current point in the video, in seconds * `currentTime` — the current point in the video, in seconds
* `playbackRate` — how fast to play the video, where 1 is 'normal' * `playbackRate` — how fast to play the video, where 1 is 'normal'
* `paused` — this one should be self-explanatory * `paused` — this one should be self-explanatory
* `volume` — a value between 0 and 1 * `volume` — a value between 0 and 1
* `muted` — a boolean value where true is muted
Videos additionally have readonly `videoWidth` and `videoHeight` bindings. Videos additionally have readonly `videoWidth` and `videoHeight` bindings.
```html ```sv
<video <video
src={clip} src={clip}
bind:duration bind:duration
@ -595,6 +628,7 @@ Videos additionally have readonly `videoWidth` and `videoHeight` bindings.
bind:currentTime bind:currentTime
bind:paused bind:paused
bind:volume bind:volume
bind:muted
bind:videoWidth bind:videoWidth
bind:videoHeight bind:videoHeight
></video> ></video>
@ -611,7 +645,7 @@ Block-level elements have 4 readonly bindings, measured using a technique simila
* `offsetWidth` * `offsetWidth`
* `offsetHeight` * `offsetHeight`
```html ```sv
<div <div
bind:offsetWidth={width} bind:offsetWidth={width}
bind:offsetHeight={height} bind:offsetHeight={height}
@ -630,7 +664,7 @@ bind:group={variable}
Inputs that work together can use `bind:group`. Inputs that work together can use `bind:group`.
```html ```sv
<script> <script>
let tortilla = 'Plain'; let tortilla = 'Plain';
let fillings = []; let fillings = [];
@ -658,7 +692,7 @@ bind:this={dom_node}
To get a reference to a DOM node, use `bind:this`. To get a reference to a DOM node, use `bind:this`.
```html ```sv
<script> <script>
import { onMount } from 'svelte'; import { onMount } from 'svelte';
@ -687,7 +721,7 @@ class:name
A `class:` directive provides a shorter way of toggling a class on an element. A `class:` directive provides a shorter way of toggling a class on an element.
```html ```sv
<!-- These are equivalent --> <!-- These are equivalent -->
<div class="{active ? 'active' : ''}">...</div> <div class="{active ? 'active' : ''}">...</div>
<div class:active={active}>...</div> <div class:active={active}>...</div>
@ -720,7 +754,7 @@ action = (node: HTMLElement, parameters: any) => {
Actions are functions that are called when an element is created. They can return an object with a `destroy` method that is called after the element is unmounted: Actions are functions that are called when an element is created. They can return an object with a `destroy` method that is called after the element is unmounted:
```html ```sv
<script> <script>
function foo(node) { function foo(node) {
// the node has been mounted in the DOM // the node has been mounted in the DOM
@ -742,7 +776,7 @@ An action can have parameters. If the returned value has an `update` method, it
> 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. > 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.
```html ```sv
<script> <script>
export let bar; export let bar;
@ -795,11 +829,11 @@ transition = (node: HTMLElement, params: any) => {
A transition is triggered by an element entering or leaving the DOM as a result of a state change. A transition is triggered by an element entering or leaving the DOM as a result of a state change.
Elements inside an *outroing* block are kept in the DOM until all current transitions have completed. When a block is transitioning out, all elements inside the block, including those that do not have their own transitions, are kept in the DOM until every transition in the block has completed.
The `transition:` directive indicates a *bidirectional* transition, which means it can be smoothly reversed while the transition is in progress. The `transition:` directive indicates a *bidirectional* transition, which means it can be smoothly reversed while the transition is in progress.
```html ```sv
{#if visible} {#if visible}
<div transition:fade> <div transition:fade>
fades in and out fades in and out
@ -817,7 +851,7 @@ Like actions, transitions can have parameters.
(The double `{{curlies}}` aren't a special syntax; this is an object literal inside an expression tag.) (The double `{{curlies}}` aren't a special syntax; this is an object literal inside an expression tag.)
```html ```sv
{#if visible} {#if visible}
<div transition:fade="{{ duration: 2000 }}"> <div transition:fade="{{ duration: 2000 }}">
flies in, fades out over two seconds flies in, fades out over two seconds
@ -835,7 +869,7 @@ The `t` argument passed to `css` is a value between `0` and `1` after the `easin
The function is called repeatedly *before* the transition begins, with different `t` and `u` arguments. The function is called repeatedly *before* the transition begins, with different `t` and `u` arguments.
```html ```sv
<script> <script>
import { elasticOut } from 'svelte/easing'; import { elasticOut } from 'svelte/easing';
@ -866,14 +900,14 @@ A custom transition function can also return a `tick` function, which is called
> If it's possible to use `css` instead of `tick`, do so — CSS animations can run off the main thread, preventing jank on slower devices. > If it's possible to use `css` instead of `tick`, do so — CSS animations can run off the main thread, preventing jank on slower devices.
```html ```sv
<script> <script>
export let visible = false; export let visible = false;
function typewriter(node, { speed = 50 }) { function typewriter(node, { speed = 50 }) {
const valid = ( const valid = (
node.childNodes.length === 1 && node.childNodes.length === 1 &&
node.childNodes[0].nodeType === 3 node.childNodes[0].nodeType === Node.TEXT_NODE
); );
if (!valid) return {}; if (!valid) return {};
@ -912,7 +946,7 @@ An element with transitions will dispatch the following events in addition to an
* `outrostart` * `outrostart`
* `outroend` * `outroend`
```html ```sv
{#if visible} {#if visible}
<p <p
transition:fly="{{ y: 200, duration: 2000 }}" transition:fly="{{ y: 200, duration: 2000 }}"
@ -930,7 +964,7 @@ An element with transitions will dispatch the following events in addition to an
Local transitions only play when the block they belong to is created or destroyed, *not* when parent blocks are created or destroyed. Local transitions only play when the block they belong to is created or destroyed, *not* when parent blocks are created or destroyed.
```html ```sv
{#if x} {#if x}
{#if y} {#if y}
<p transition:fade> <p transition:fade>
@ -979,7 +1013,7 @@ Similar to `transition:`, but only applies to elements entering (`in:`) or leavi
Unlike with `transition:`, transitions applied with `in:` and `out:` are not bidirectional — an in transition will continue to 'play' alongside the out transition, rather than reversing, if the block is outroed while the transition is in progress. If an out transition is aborted, transitions will restart from scratch. Unlike with `transition:`, transitions applied with `in:` and `out:` are not bidirectional — an in transition will continue to 'play' alongside the out transition, rather than reversing, if the block is outroed while the transition is in progress. If an out transition is aborted, transitions will restart from scratch.
```html ```sv
{#if visible} {#if visible}
<div in:fly out:fade> <div in:fly out:fade>
flies in, fades out flies in, fades out
@ -1028,7 +1062,7 @@ An animation is triggered when the contents of a [keyed each block](docs#each) a
Animations can be used with Svelte's [built-in animation functions](docs#svelte_animate) or [custom animation functions](docs#Custom_animation_functions). Animations can be used with Svelte's [built-in animation functions](docs#svelte_animate) or [custom animation functions](docs#Custom_animation_functions).
```html ```sv
<!-- When `list` is reordered the animation will run--> <!-- When `list` is reordered the animation will run-->
{#each list as item, index (item)} {#each list as item, index (item)}
<li animate:flip>{item}</li> <li animate:flip>{item}</li>
@ -1043,7 +1077,7 @@ As with actions and transitions, animations can have parameters.
(The double `{{curlies}}` aren't a special syntax; this is an object literal inside an expression tag.) (The double `{{curlies}}` aren't a special syntax; this is an object literal inside an expression tag.)
```html ```sv
{#each list as item, index (item)} {#each list as item, index (item)}
<li animate:flip="{{ delay: 500 }}">{item}</li> <li animate:flip="{{ delay: 500 }}">{item}</li>
{/each} {/each}
@ -1062,7 +1096,7 @@ The `t` argument passed to `css` is a value that goes from `0` and `1` after the
The function is called repeatedly *before* the animation begins, with different `t` and `u` arguments. The function is called repeatedly *before* the animation begins, with different `t` and `u` arguments.
```html ```sv
<script> <script>
import { cubicOut } from 'svelte/easing'; import { cubicOut } from 'svelte/easing';
@ -1095,7 +1129,7 @@ A custom animation function can also return a `tick` function, which is called *
> If it's possible to use `css` instead of `tick`, do so — CSS animations can run off the main thread, preventing jank on slower devices. > If it's possible to use `css` instead of `tick`, do so — CSS animations can run off the main thread, preventing jank on slower devices.
```html ```sv
<script> <script>
import { cubicOut } from 'svelte/easing'; import { cubicOut } from 'svelte/easing';
@ -1135,7 +1169,7 @@ on:eventname={handler}
Components can emit events using [createEventDispatcher](docs#createEventDispatcher), or by forwarding DOM events. Listening for component events looks the same as listening for DOM events: Components can emit events using [createEventDispatcher](docs#createEventDispatcher), or by forwarding DOM events. Listening for component events looks the same as listening for DOM events:
```html ```sv
<SomeComponent on:whatever={handler}/> <SomeComponent on:whatever={handler}/>
``` ```
@ -1143,7 +1177,7 @@ Components can emit events using [createEventDispatcher](docs#createEventDispatc
As with DOM events, if the `on:` directive is used without a value, the component will *forward* the event, meaning that a consumer of the component can listen for it. As with DOM events, if the `on:` directive is used without a value, the component will *forward* the event, meaning that a consumer of the component can listen for it.
```html ```sv
<SomeComponent on:whatever/> <SomeComponent on:whatever/>
``` ```
@ -1158,7 +1192,7 @@ bind:property={variable}
You can bind to component props using the same syntax as for elements. You can bind to component props using the same syntax as for elements.
```html ```sv
<Keypad bind:value={pin}/> <Keypad bind:value={pin}/>
``` ```
@ -1174,7 +1208,7 @@ Components also support `bind:this`, allowing you to interact with component ins
> Note that we can't do `{cart.empty}` since `cart` is `undefined` when the button is first rendered and throws an error. > Note that we can't do `{cart.empty}` since `cart` is `undefined` when the button is first rendered and throws an error.
```html ```sv
<ShoppingCart bind:this={cart}/> <ShoppingCart bind:this={cart}/>
<button on:click={() => cart.empty()}> <button on:click={() => cart.empty()}>
@ -1202,7 +1236,7 @@ Components can have child content, in the same way that elements can.
The content is exposed in the child component using the `<slot>` element, which can contain fallback content that is rendered if no children are provided. The content is exposed in the child component using the `<slot>` element, which can contain fallback content that is rendered if no children are provided.
```html ```sv
<!-- App.svelte --> <!-- App.svelte -->
<Widget></Widget> <Widget></Widget>
@ -1224,7 +1258,7 @@ The content is exposed in the child component using the `<slot>` element, which
Named slots allow consumers to target specific areas. They can also have fallback content. Named slots allow consumers to target specific areas. They can also have fallback content.
```html ```sv
<!-- App.svelte --> <!-- App.svelte -->
<Widget> <Widget>
<h1 slot="header">Hello</h1> <h1 slot="header">Hello</h1>
@ -1247,17 +1281,17 @@ Slots can be rendered zero or more times, and can pass values *back* to the pare
The usual shorthand rules apply — `let:item` is equivalent to `let:item={item}`, and `<slot {item}>` is equivalent to `<slot item={item}>`. The usual shorthand rules apply — `let:item` is equivalent to `let:item={item}`, and `<slot {item}>` is equivalent to `<slot item={item}>`.
```html ```sv
<!-- App.svelte --> <!-- App.svelte -->
<FancyList {items} let:item={item}> <FancyList {items} let:prop={thing}>
<div>{item.text}</div> <div>{thing.text}</div>
</FancyList> </FancyList>
<!-- FancyList.svelte --> <!-- FancyList.svelte -->
<ul> <ul>
{#each items as item} {#each items as item}
<li class="fancy"> <li class="fancy">
<slot item={item}></slot> <slot prop={item}></slot>
</li> </li>
{/each} {/each}
</ul> </ul>
@ -1267,10 +1301,10 @@ The usual shorthand rules apply — `let:item` is equivalent to `let:item={item}
Named slots can also expose values. The `let:` directive goes on the element with the `slot` attribute. Named slots can also expose values. The `let:` directive goes on the element with the `slot` attribute.
```html ```sv
<!-- App.svelte --> <!-- App.svelte -->
<FancyList {items}> <FancyList {items}>
<div slot="item" let:item={item}>{item.text}</div> <div slot="item" let:item>{item.text}</div>
<p slot="footer">Copyright (c) 2019 Svelte Industries</p> <p slot="footer">Copyright (c) 2019 Svelte Industries</p>
</FancyList> </FancyList>
@ -1278,7 +1312,7 @@ Named slots can also expose values. The `let:` directive goes on the element wit
<ul> <ul>
{#each items as item} {#each items as item}
<li class="fancy"> <li class="fancy">
<slot name="item" item={item}></slot> <slot name="item" {item}></slot>
</li> </li>
{/each} {/each}
</ul> </ul>
@ -1295,7 +1329,7 @@ The `<svelte:self>` element allows a component to include itself, recursively.
It cannot appear at the top level of your markup; it must be inside an if or each block to prevent an infinite loop. It cannot appear at the top level of your markup; it must be inside an if or each block to prevent an infinite loop.
```html ```sv
<script> <script>
export let count; export let count;
</script> </script>
@ -1320,7 +1354,7 @@ The `<svelte:component>` element renders a component dynamically, using the comp
If `this` is falsy, no component is rendered. If `this` is falsy, no component is rendered.
```html ```sv
<svelte:component this={currentSelection.component} foo={bar}/> <svelte:component this={currentSelection.component} foo={bar}/>
``` ```
@ -1338,7 +1372,7 @@ If `this` is falsy, no component is rendered.
The `<svelte:window>` element allows you to add event listeners to the `window` object without worrying about removing them when the component is destroyed, or checking for the existence of `window` when server-side rendering. The `<svelte:window>` element allows you to add event listeners to the `window` object without worrying about removing them when the component is destroyed, or checking for the existence of `window` when server-side rendering.
```html ```sv
<script> <script>
function handleKeydown(event) { function handleKeydown(event) {
alert(`pressed the ${event.key} key`); alert(`pressed the ${event.key} key`);
@ -1362,7 +1396,7 @@ You can also bind to the following properties:
All except `scrollX` and `scrollY` are readonly. All except `scrollX` and `scrollY` are readonly.
```html ```sv
<svelte:window bind:scrollY={y}/> <svelte:window bind:scrollY={y}/>
``` ```
@ -1377,7 +1411,7 @@ All except `scrollX` and `scrollY` are readonly.
As with `<svelte:window>`, this element allows you to add listeners to events on `document.body`, such as `mouseenter` and `mouseleave` which don't fire on `window`. As with `<svelte:window>`, this element allows you to add listeners to events on `document.body`, such as `mouseenter` and `mouseleave` which don't fire on `window`.
```html ```sv
<svelte:body <svelte:body
on:mouseenter={handleMouseenter} on:mouseenter={handleMouseenter}
on:mouseleave={handleMouseleave} on:mouseleave={handleMouseleave}
@ -1395,7 +1429,7 @@ As with `<svelte:window>`, this element allows you to add listeners to events on
This element makes it possible to insert elements into `document.head`. During server-side rendering, `head` content is exposed separately to the main `html` content. This element makes it possible to insert elements into `document.head`. During server-side rendering, `head` content is exposed separately to the main `html` content.
```html ```sv
<svelte:head> <svelte:head>
<link rel="stylesheet" href="tutorial/dark-theme.css"> <link rel="stylesheet" href="tutorial/dark-theme.css">
</svelte:head> </svelte:head>
@ -1419,6 +1453,6 @@ The `<svelte:options>` element provides a place to specify per-component compile
* `namespace="..."` — the namespace where this component will be used, most commonly "svg" * `namespace="..."` — the namespace where this component will be used, most commonly "svg"
* `tag="..."` — the name to use when compiling this component as a custom element * `tag="..."` — the name to use when compiling this component as a custom element
```html ```sv
<svelte:options tag="my-custom-element"/> <svelte:options tag="my-custom-element"/>
``` ```

@ -22,7 +22,7 @@ The `onMount` function schedules a callback to run as soon as the component has
`onMount` does not run inside a [server-side component](docs#Server-side_component_API). `onMount` does not run inside a [server-side component](docs#Server-side_component_API).
```html ```sv
<script> <script>
import { onMount } from 'svelte'; import { onMount } from 'svelte';
@ -36,7 +36,7 @@ The `onMount` function schedules a callback to run as soon as the component has
If a function is returned from `onMount`, it will be called when the component is unmounted. If a function is returned from `onMount`, it will be called when the component is unmounted.
```html ```sv
<script> <script>
import { onMount } from 'svelte'; import { onMount } from 'svelte';
@ -62,7 +62,7 @@ Schedules a callback to run immediately before the component is updated after an
> The first time the callback runs will be before the initial `onMount` > The first time the callback runs will be before the initial `onMount`
```html ```sv
<script> <script>
import { beforeUpdate } from 'svelte'; import { beforeUpdate } from 'svelte';
@ -82,7 +82,7 @@ afterUpdate(callback: () => void)
Schedules a callback to run immediately after the component has been updated. Schedules a callback to run immediately after the component has been updated.
```html ```sv
<script> <script>
import { afterUpdate } from 'svelte'; import { afterUpdate } from 'svelte';
@ -104,7 +104,7 @@ Schedules a callback to run once the component is unmounted.
Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the only one that runs inside a server-side component. Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the only one that runs inside a server-side component.
```html ```sv
<script> <script>
import { onDestroy } from 'svelte'; import { onDestroy } from 'svelte';
@ -124,7 +124,7 @@ promise: Promise = tick()
Returns a promise that resolves once any pending state changes have been applied, or in the next microtask if there are none. Returns a promise that resolves once any pending state changes have been applied, or in the next microtask if there are none.
```html ```sv
<script> <script>
import { beforeUpdate, tick } from 'svelte'; import { beforeUpdate, tick } from 'svelte';
@ -148,7 +148,7 @@ Associates an arbitrary `context` object with the current component and the spec
Like lifecycle functions, this must be called during component initialisation. Like lifecycle functions, this must be called during component initialisation.
```html ```sv
<script> <script>
import { setContext } from 'svelte'; import { setContext } from 'svelte';
@ -168,7 +168,7 @@ context: any = getContext(key: any)
Retrieves the context that belongs to the closest parent component with the specified `key`. Must be called during component initialisation. Retrieves the context that belongs to the closest parent component with the specified `key`. Must be called during component initialisation.
```html ```sv
<script> <script>
import { getContext } from 'svelte'; import { getContext } from 'svelte';
@ -188,7 +188,7 @@ Creates an event dispatcher that can be used to dispatch [component events](docs
Component events created with `createEventDispatcher` create a [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent). These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture) and are not cancellable with `event.preventDefault()`. The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail) property and can contain any type of data. Component events created with `createEventDispatcher` create a [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent). These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture) and are not cancellable with `event.preventDefault()`. The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail) property and can contain any type of data.
```html ```sv
<script> <script>
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
@ -202,7 +202,7 @@ Component events created with `createEventDispatcher` create a [CustomEvent](htt
Events dispatched from child components can be listened to in their parent. Any data provided when the event was dispatched is available on the `detail` property of the event object. Events dispatched from child components can be listened to in their parent. Any data provided when the event was dispatched is available on the `detail` property of the event object.
```html ```sv
<script> <script>
function callbackFunction(event) { function callbackFunction(event) {
console.log(`Notify fired! Detail: ${event.detail}`) console.log(`Notify fired! Detail: ${event.detail}`)
@ -287,7 +287,9 @@ The second argument to `readable` is the same as the second argument to `writabl
```js ```js
import { readable } from 'svelte/store'; import { readable } from 'svelte/store';
const time = readable(new Date(), set => { const time = readable(null, set => {
set(new Date());
const interval = setInterval(() => { const interval = setInterval(() => {
set(new Date()); set(new Date());
}, 1000); }, 1000);
@ -413,7 +415,7 @@ Both functions return a Promise that resolves when the tween completes. If the t
Out of the box, Svelte will interpolate between two numbers, two arrays or two objects (as long as the arrays and objects are the same 'shape', and their 'leaf' properties are also numbers). Out of the box, Svelte will interpolate between two numbers, two arrays or two objects (as long as the arrays and objects are the same 'shape', and their 'leaf' properties are also numbers).
```html ```sv
<script> <script>
import { tweened } from 'svelte/motion'; import { tweened } from 'svelte/motion';
import { cubicOut } from 'svelte/easing'; import { cubicOut } from 'svelte/easing';
@ -452,7 +454,7 @@ $: $size = big ? 100 : 10;
The `interpolate` option allows you to tween between *any* arbitrary values. It must be an `(a, b) => t => value` function, where `a` is the starting value, `b` is the target value, `t` is a number between 0 and 1, and `value` is the result. For example, we can use the [d3-interpolate](https://github.com/d3/d3-interpolate) package to smoothly interpolate between two colours. The `interpolate` option allows you to tween between *any* arbitrary values. It must be an `(a, b) => t => value` function, where `a` is the starting value, `b` is the target value, `t` is a number between 0 and 1, and `value` is the result. For example, we can use the [d3-interpolate](https://github.com/d3/d3-interpolate) package to smoothly interpolate between two colours.
```html ```sv
<script> <script>
import { interpolateLab } from 'd3-interpolate'; import { interpolateLab } from 'd3-interpolate';
import { tweened } from 'svelte/motion'; import { tweened } from 'svelte/motion';
@ -499,7 +501,7 @@ Both `set` and `update` can take a second argument — an object with `hard` or
[See a full example on the spring tutorial.](tutorial/spring) [See a full example on the spring tutorial.](tutorial/spring)
```html ```sv
<script> <script>
import { spring } from 'svelte/motion'; import { spring } from 'svelte/motion';
@ -521,7 +523,7 @@ $: $size = big ? 100 : 10;
### `svelte/transition` ### `svelte/transition`
The `svelte/transition` module exports six functions: `fade`, `fly`, `slide`, `scale`, `draw` and `crossfade`. They are for use with svelte [`transitions`](docs#Transitions). The `svelte/transition` module exports seven functions: `fade`, `blur`, `fly`, `slide`, `scale`, `draw` and `crossfade`. They are for use with Svelte [`transitions`](docs#transition_fn).
#### `fade` #### `fade`
@ -546,7 +548,7 @@ Animates the opacity of an element from 0 to the current opacity for `in` transi
You can see the `fade` transition in action in the [transition tutorial](tutorial/transition). You can see the `fade` transition in action in the [transition tutorial](tutorial/transition).
```html ```sv
<script> <script>
import { fade } from 'svelte/transition'; import { fade } from 'svelte/transition';
</script> </script>
@ -582,7 +584,7 @@ Animates a `blur` filter alongside an element's opacity.
* `opacity` (`number`, default 0) - the opacity value to animate out to and in from * `opacity` (`number`, default 0) - the opacity value to animate out to and in from
* `amount` (`number`, default 5) - the size of the blur in pixels * `amount` (`number`, default 5) - the size of the blur in pixels
```html ```sv
<script> <script>
import { blur } from 'svelte/transition'; import { blur } from 'svelte/transition';
</script> </script>
@ -621,7 +623,7 @@ Animates the x and y positions and the opacity of an element. `in` transitions a
You can see the `fly` transition in action in the [transition tutorial](tutorial/adding-parameters-to-transitions). You can see the `fly` transition in action in the [transition tutorial](tutorial/adding-parameters-to-transitions).
```html ```sv
<script> <script>
import { fly } from 'svelte/transition'; import { fly } from 'svelte/transition';
import { quintOut } from 'svelte/easing'; import { quintOut } from 'svelte/easing';
@ -656,7 +658,7 @@ Slides an element in and out.
* `duration` (`number`, default 400) — milliseconds the transition lasts * `duration` (`number`, default 400) — milliseconds the transition lasts
* `easing` (`function`, default `cubicOut`) — an [easing function](docs#svelte_easing) * `easing` (`function`, default `cubicOut`) — an [easing function](docs#svelte_easing)
```html ```sv
<script> <script>
import { slide } from 'svelte/transition'; import { slide } from 'svelte/transition';
import { quintOut } from 'svelte/easing'; import { quintOut } from 'svelte/easing';
@ -693,7 +695,7 @@ Animates the opacity and scale of an element. `in` transitions animate from an e
* `start` (`number`, default 0) - the scale value to animate out to and in from * `start` (`number`, default 0) - the scale value to animate out to and in from
* `opacity` (`number`, default 0) - the opacity value to animate out to and in from * `opacity` (`number`, default 0) - the opacity value to animate out to and in from
```html ```sv
<script> <script>
import { scale } from 'svelte/transition'; import { scale } from 'svelte/transition';
import { quintOut } from 'svelte/easing'; import { quintOut } from 'svelte/easing';
@ -731,7 +733,7 @@ Animates the stroke of an SVG element, like a snake in a tube. `in` transitions
The `speed` parameter is a means of setting the duration of the transition relative to the path's length. It is modifier that is applied to the length of the path: `duration = length / speed`. A path that is 1000 pixels with a speed of 1 will have a duration of `1000ms`, setting the speed to `0.5` will double that duration and setting it to `2` will halve it. The `speed` parameter is a means of setting the duration of the transition relative to the path's length. It is modifier that is applied to the length of the path: `duration = length / speed`. A path that is 1000 pixels with a speed of 1 will have a duration of `1000ms`, setting the speed to `0.5` will double that duration and setting it to `2` will halve it.
```html ```sv
<script> <script>
import { draw } from 'svelte/transition'; import { draw } from 'svelte/transition';
import { quintOut } from 'svelte/easing'; import { quintOut } from 'svelte/easing';
@ -758,7 +760,7 @@ The `speed` parameter is a means of setting the duration of the transition relat
### `svelte/animate` ### `svelte/animate`
The `svelte/animate` module exports one function for use with svelte [animations](docs#Animations). The `svelte/animate` module exports one function for use with Svelte [animations](docs#animate_fn).
#### `flip` #### `flip`
@ -785,7 +787,7 @@ The `flip` function calculates the start and end position of an element and anim
You can see a full example on the [animations tutorial](tutorial/animate) You can see a full example on the [animations tutorial](tutorial/animate)
```html ```sv
<script> <script>
import { flip } from 'svelte/animate'; import { flip } from 'svelte/animate';
import { quintOut } from 'svelte/easing'; import { quintOut } from 'svelte/easing';
@ -804,7 +806,7 @@ You can see a full example on the [animations tutorial](tutorial/animate)
### `svelte/easing` ### `svelte/easing`
Easing functions specificy the rate of change over time and are useful when working with Svelte's built-in transitions and animations as well as the tweened and spring utilities. `svelte/easing` contains 31 named exports, a `linear` ease and 3 variants of 10 different easing functions: `in`, `out` and `inOut`. Easing functions specify the rate of change over time and are useful when working with Svelte's built-in transitions and animations as well as the tweened and spring utilities. `svelte/easing` contains 31 named exports, a `linear` ease and 3 variants of 10 different easing functions: `in`, `out` and `inOut`.
You can explore the various eases using the [ease visualiser](examples#easing) in the [examples section](examples). You can explore the various eases using the [ease visualiser](examples#easing) in the [examples section](examples).
@ -973,8 +975,8 @@ app.count += 1;
Svelte components can also be compiled to custom elements (aka web components) using the `customElement: true` compiler option. You should specify a tag name for the component using the `<svelte:options>` [element](docs#svelte_options). Svelte components can also be compiled to custom elements (aka web components) using the `customElement: true` compiler option. You should specify a tag name for the component using the `<svelte:options>` [element](docs#svelte_options).
```html ```sv
<svelte:options tag="my-element"> <svelte:options tag="my-element" />
<script> <script>
export let name = 'world'; export let name = 'world';

@ -113,7 +113,8 @@ const {
* `module` is `true` if the value is declared in a `context="module"` script * `module` is `true` if the value is declared in a `context="module"` script
* `mutated` is `true` if the value's properties are assigned to inside the component * `mutated` is `true` if the value's properties are assigned to inside the component
* `reassigned` is `true` if the value is reassigned inside the component * `reassigned` is `true` if the value is reassigned inside the component
* `referenced` is `true` if the value is used outside the declaration * `referenced` is `true` if the value is used in the template
* `referenced_from_script` is `true` if the value is used in the `<script>` outside the declaration
* `writable` is `true` if the value was declared with `let` or `var` (but not `const`, `class` or `function`) * `writable` is `true` if the value was declared with `let` or `var` (but not `const`, `class` or `function`)
* `stats` is an object used by the Svelte developer team for diagnosing the compiler. Avoid relying on it to stay the same! * `stats` is an object used by the Svelte developer team for diagnosing the compiler. Avoid relying on it to stay the same!
@ -144,6 +145,7 @@ compiled: {
mutated: boolean, mutated: boolean,
reassigned: boolean, reassigned: boolean,
referenced: boolean, referenced: boolean,
referenced_from_script: boolean,
writable: boolean writable: boolean
}>, }>,
stats: { stats: {
@ -181,6 +183,10 @@ const ast = svelte.parse(source, { filename: 'App.svelte' });
### `svelte.preprocess` ### `svelte.preprocess`
A number of [community-maintained preprocessing plugins](https://github.com/sveltejs/integrations#preprocessors) are available to allow you to use Svelte with tools like TypeScript, PostCSS, SCSS, and Less.
You can write your own preprocessor using the `svelte.preprocess` API.
```js ```js
result: { result: {
code: string, code: string,

@ -18,7 +18,7 @@
Remove first thing Remove first thing
</button> </button>
<div style="display: grid; grid-template-columns: 1fr 1fr; grip-gap: 1em"> <div style="display: grid; grid-template-columns: 1fr 1fr; grid-gap: 1em">
<div> <div>
<h2>Keyed</h2> <h2>Keyed</h2>
{#each things as thing (thing.id)} {#each things as thing (thing.id)}
@ -32,4 +32,4 @@
<Thing current={thing.color}/> <Thing current={thing.color}/>
{/each} {/each}
</div> </div>
</div> </div>

@ -1,9 +1,9 @@
<script> <script>
import FancyButton from './FancyButton.svelte'; import CustomButton from './CustomButton.svelte';
function handleClick() { function handleClick() {
alert('clicked'); alert('clicked');
} }
</script> </script>
<FancyButton on:click={handleClick}/> <CustomButton on:click={handleClick}/>

@ -0,0 +1,22 @@
<style>
button {
height: 4rem;
width: 8rem;
background-color: #aaa;
border-color: #f1c40f;
color: #f1c40f;
font-size: 1.25rem;
background-image: linear-gradient(45deg, #f1c40f 50%, transparent 50%);
background-position: 100%;
background-size: 400%;
transition: background 300ms ease-in-out;
}
button:hover {
background-position: 0;
color: #aaa;
}
</style>
<button on:click>
Click me
</button>

@ -1,15 +0,0 @@
<style>
button {
font-family: 'Comic Sans MS', cursive;
font-size: 2em;
padding: 0.5em 1em;
color: royalblue;
background: gold;
border-radius: 1em;
box-shadow: 2px 2px 4px rgba(0,0,0,0.5);
}
</style>
<button on:click>
Click me
</button>

@ -109,8 +109,8 @@
<div> <div>
<video <video
poster="http://sveltejs.github.io/assets/caminandes-llamigos.jpg" poster="https://sveltejs.github.io/assets/caminandes-llamigos.jpg"
src="http://sveltejs.github.io/assets/caminandes-llamigos.mp4" src="https://sveltejs.github.io/assets/caminandes-llamigos.mp4"
on:mousemove={handleMousemove} on:mousemove={handleMousemove}
on:mousedown={handleMousedown} on:mousedown={handleMousedown}
bind:currentTime={time} bind:currentTime={time}

@ -20,7 +20,7 @@
]; ];
function handleKeydown(event) { function handleKeydown(event) {
if (event.which === 13) { if (event.key === 'Enter') {
const text = event.target.value; const text = event.target.value;
if (!text) return; if (!text) return;
@ -103,4 +103,4 @@
</div> </div>
<input on:keydown={handleKeydown}> <input on:keydown={handleKeydown}>
</div> </div>

@ -4,7 +4,7 @@
let text = `Select some text and hit the tab key to toggle uppercase`; let text = `Select some text and hit the tab key to toggle uppercase`;
async function handleKeydown(event) { async function handleKeydown(event) {
if (event.which !== 9) return; if (event.key !== 'Tab') return;
event.preventDefault(); event.preventDefault();
@ -34,4 +34,4 @@
} }
</style> </style>
<textarea value={text} on:keydown={handleKeydown}></textarea> <textarea value={text} on:keydown={handleKeydown}></textarea>

@ -4,7 +4,7 @@
function typewriter(node, { speed = 50 }) { function typewriter(node, { speed = 50 }) {
const valid = ( const valid = (
node.childNodes.length === 1 && node.childNodes.length === 1 &&
node.childNodes[0].nodeType === 3 node.childNodes[0].nodeType === Node.TEXT_NODE
); );
if (!valid) { if (!valid) {
@ -33,4 +33,4 @@
<p in:typewriter> <p in:typewriter>
The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog
</p> </p>
{/if} {/if}

@ -112,7 +112,7 @@
<input <input
class="new-todo" class="new-todo"
placeholder="what needs to be done?" placeholder="what needs to be done?"
on:keydown="{event => event.which === 13 && add(event.target)}" on:keydown="{event => event.key === 'Enter' && add(event.target)}"
> >
<div class='left'> <div class='left'>

@ -3,6 +3,8 @@
export let item; export let item;
export let returnTo; export let returnTo;
$: url = !item.domain ? `https://news.ycombinator.com/${item.url}` : item.url;
</script> </script>
<style> <style>
@ -24,9 +26,11 @@
<a href={returnTo}>&laquo; back</a> <a href={returnTo}>&laquo; back</a>
<article> <article>
<a href="{item.url}"> <a href="{url}">
<h1>{item.title}</h1> <h1>{item.title}</h1>
<small>{item.domain}</small> {#if item.domain}
<small>{item.domain}</small>
{/if}
</a> </a>
<p class="meta">submitted by {item.user} {item.time_ago} <p class="meta">submitted by {item.user} {item.time_ago}
@ -36,4 +40,4 @@
{#each item.comments as comment} {#each item.comments as comment}
<Comment {comment}/> <Comment {comment}/>
{/each} {/each}
</div> </div>

@ -7,6 +7,8 @@
const c = item.comments_count; const c = item.comments_count;
return `${c} ${c === 1 ? 'comment' : 'comments'}`; return `${c} ${c === 1 ? 'comment' : 'comments'}`;
} }
$: url = item.type === "ask" ? `https://news.ycombinator.com/${item.url}` : item.url;
</script> </script>
<style> <style>
@ -33,6 +35,6 @@
<article> <article>
<span>{i + offset + 1}</span> <span>{i + offset + 1}</span>
<h2><a target="_blank" href={item.url}>{item.title}</a></h2> <h2><a target="_blank" href={url}>{item.title}</a></h2>
<p class="meta"><a href="#/item/{item.id}">{comment_text()}</a> by {item.user} {item.time_ago}</p> <p class="meta"><a href="#/item/{item.id}">{comment_text()}</a> by {item.user} {item.time_ago}</p>
</article> </article>

@ -0,0 +1,7 @@
---
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.
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.

@ -0,0 +1,5 @@
---
question: How can I update my components written in Svelte v2?
---
svelte-upgrade isn't fully working for v2->v3 yet, [but it's close](https://github.com/sveltejs/svelte-upgrade/pull/12).

@ -0,0 +1,7 @@
---
question: Is Svelte v2 still available?
---
New features aren't being added to it, and bugs will probably only be fixed if they are extremely nasty or present some sort of security vulnerability.
The documentation is still available [here](https://v2.svelte.dev/guide).

@ -0,0 +1,5 @@
---
question: How do I do hot module reloading?
---
Use the community plugins for [rollup](https://github.com/rixo/rollup-plugin-svelte-hot) and [webpack](https://github.com/rixo/svelte-loader-hot).

@ -0,0 +1,10 @@
---
question: Are there any video courses?
---
There are no official ones, but here are a couple of third-part ones that we know of.
- [Egghead](https://egghead.io/playlists/getting-started-with-svelte-3-05a8541a)
- [Udemy](https://www.udemy.com/sveltejs-the-complete-guide/)
Note that Udemy very frequently has discounts over 90%.

@ -0,0 +1,5 @@
---
question: How can I get VSCode to syntax-highlight my .svelte files?
---
There is an [official VSCode extension for Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode), however it is still in the **beta** testing stage, and not all issues have been ironed out.

@ -0,0 +1,5 @@
---
question: What about Typescript support?
---
You need to install a [community supported preprocessor](https://github.com/sveltejs/integrations#preprocessors) such as [svelte-preprocess](https://github.com/kaisermann/svelte-preprocess). Work is ongoing to improve [IDE support](https://github.com/sveltejs/language-tools/issues/83). You can also run type checking from command line with [svelte-check](https://www.npmjs.com/package/svelte-check).

@ -0,0 +1,5 @@
---
question: Does Svelte scale?
---
There will be a blog post about this eventually, but in the meantime, check out [this issue](https://github.com/sveltejs/svelte/issues/2546).

@ -0,0 +1,5 @@
---
question: Is there a UI component library?
---
There are several UI component libraries. Find them under the [code section](https://svelte-community.netlify.com/code) of the Svelte Community website.

@ -0,0 +1,6 @@
---
question: How do I test Svelte apps?
---
We don't have a good answer to this yet, but it is a priority. There are a few approaches that people take when testing, but it generally involves compiling the component and mounting it to something and then performing the tests.
You essentially need to create a bundle for each component you're testing (since svelte is a compiler and not a normal library) and then mount them. You can mount to a JSDOM instance, or you can use Puppeteer if you need a real browser, or you can use a tool like Cypress. There is an example of this in the Sapper starter template.

@ -0,0 +1,13 @@
---
question: Is there a router?
---
You can use any router lib you want. A lot of people use [page.js](https://github.com/visionmedia/page.js). There's also [navaid](https://github.com/lukeed/navaid), which is very similar.
If you prefer a declarative HTML approach, there's [svelte-routing](https://github.com/EmilTholin/svelte-routing).
If you need hash-based routing on the client side, check out [svelte-spa-router](https://github.com/ItalyPaleAle/svelte-spa-router), or [abstract-state-router](https://github.com/TehShrike/abstract-state-router/), a mature router for business software.
For filesystem-based routing, you can take a look at [Routify](https://routify.dev).
For an official solution, there's nothing that's simply a routing library. There is, however, the official [Sapper](https://sapper.svelte.dev/) framework, a Next.js-style application framework built on Svelte, which includes its own filesystem-based routing.

@ -19,4 +19,6 @@ Add a `<script>` tag that imports `Nested.svelte`...
<Nested/> <Nested/>
``` ```
Notice that even though `Nested.svelte` has a `<p>` element, the styles from `App.svelte` don't leak in. Notice that even though `Nested.svelte` has a `<p>` element, the styles from `App.svelte` don't leak in.
Also notice that the component name `Nested` is capitalised. This convention has been adopted to allow us to differentiate between user-defined components and regular HTML tags.

@ -2,7 +2,7 @@
title: Default values title: Default values
--- ---
We can easily specify default values for props: We can easily specify default values for props in `Nested.svelte`:
```html ```html
<script> <script>

@ -1,9 +1,9 @@
<script> <script>
import FancyButton from './FancyButton.svelte'; import CustomButton from './CustomButton.svelte';
function handleClick() { function handleClick() {
alert('clicked'); alert('clicked');
} }
</script> </script>
<FancyButton on:click={handleClick}/> <CustomButton on:click={handleClick}/>

@ -0,0 +1,22 @@
<style>
button {
height: 4rem;
width: 8rem;
background-color: #aaa;
border-color: #f1c40f;
color: #f1c40f;
font-size: 1.25rem;
background-image: linear-gradient(45deg, #f1c40f 50%, transparent 50%);
background-position: 100%;
background-size: 400%;
transition: background 300ms ease-in-out;
}
button:hover {
background-position: 0;
color: #aaa;
}
</style>
<button>
Click me
</button>

@ -1,15 +0,0 @@
<style>
button {
font-family: 'Comic Sans MS', cursive;
font-size: 2em;
padding: 0.5em 1em;
color: royalblue;
background: gold;
border-radius: 1em;
box-shadow: 2px 2px 4px rgba(0,0,0,0.5);
}
</style>
<button>
Click me
</button>

@ -1,9 +1,9 @@
<script> <script>
import FancyButton from './FancyButton.svelte'; import CustomButton from './CustomButton.svelte';
function handleClick() { function handleClick() {
alert('clicked'); alert('clicked');
} }
</script> </script>
<FancyButton on:click={handleClick}/> <CustomButton on:click={handleClick}/>

@ -0,0 +1,22 @@
<style>
button {
height: 4rem;
width: 8rem;
background-color: #aaa;
border-color: #f1c40f;
color: #f1c40f;
font-size: 1.25rem;
background-image: linear-gradient(45deg, #f1c40f 50%, transparent 50%);
background-position: 100%;
background-size: 400%;
transition: background 300ms ease-in-out;
}
button:hover {
background-position: 0;
color: #aaa;
}
</style>
<button on:click>
Click me
</button>

@ -1,15 +0,0 @@
<style>
button {
font-family: 'Comic Sans MS', cursive;
font-size: 2em;
padding: 0.5em 1em;
color: royalblue;
background: gold;
border-radius: 1em;
box-shadow: 2px 2px 4px rgba(0,0,0,0.5);
}
</style>
<button on:click>
Click me
</button>

@ -4,7 +4,7 @@ title: DOM event forwarding
Event forwarding works for DOM events too. Event forwarding works for DOM events too.
We want to get notified of clicks on our `<FancyButton>` — to do that, we just need to forward `click` events on the `<button>` element in `FancyButton.svelte`: We want to get notified of clicks on our `<CustomButton>` — to do that, we just need to forward `click` events on the `<button>` element in `CustomButton.svelte`:
```html ```html
<button on:click> <button on:click>

@ -33,11 +33,12 @@ The complete set of bindings for `<audio>` and `<video>` is as follows — six *
* `seeking` (readonly) — boolean * `seeking` (readonly) — boolean
* `ended` (readonly) — boolean * `ended` (readonly) — boolean
...and four *two-way* bindings: ...and five *two-way* bindings:
* `currentTime` — the current point in the video, in seconds * `currentTime` — the current point in the video, in seconds
* `playbackRate` — how fast to play the video, where `1` is 'normal' * `playbackRate` — how fast to play the video, where `1` is 'normal'
* `paused` — this one should be self-explanatory * `paused` — this one should be self-explanatory
* `volume` — a value between 0 and 1 * `volume` — a value between 0 and 1
* `muted` — a boolean value where true is muted
Videos additionally have readonly `videoWidth` and `videoHeight` bindings. Videos additionally have readonly `videoWidth` and `videoHeight` bindings.

@ -20,7 +20,7 @@
]; ];
function handleKeydown(event) { function handleKeydown(event) {
if (event.which === 13) { if (event.key === 'Enter') {
const text = event.target.value; const text = event.target.value;
if (!text) return; if (!text) return;
@ -104,4 +104,4 @@
</div> </div>
<input on:keydown={handleKeydown}> <input on:keydown={handleKeydown}>
</div> </div>

@ -20,7 +20,7 @@
]; ];
function handleKeydown(event) { function handleKeydown(event) {
if (event.which === 13) { if (event.key === 'Enter') {
const text = event.target.value; const text = event.target.value;
if (!text) return; if (!text) return;
@ -104,4 +104,4 @@
</div> </div>
<input on:keydown={handleKeydown}> <input on:keydown={handleKeydown}>
</div> </div>

@ -2,7 +2,7 @@
let text = `Select some text and hit the tab key to toggle uppercase`; let text = `Select some text and hit the tab key to toggle uppercase`;
async function handleKeydown(event) { async function handleKeydown(event) {
if (event.which !== 9) return; if (event.key !== 'Tab') return;
event.preventDefault(); event.preventDefault();
@ -32,4 +32,4 @@
} }
</style> </style>
<textarea value={text} on:keydown={handleKeydown}></textarea> <textarea value={text} on:keydown={handleKeydown}></textarea>

@ -4,7 +4,7 @@
let text = `Select some text and hit the tab key to toggle uppercase`; let text = `Select some text and hit the tab key to toggle uppercase`;
async function handleKeydown(event) { async function handleKeydown(event) {
if (event.which !== 9) return; if (event.key !== 'Tab') return;
event.preventDefault(); event.preventDefault();
@ -34,4 +34,4 @@
} }
</style> </style>
<textarea value={text} on:keydown={handleKeydown}></textarea> <textarea value={text} on:keydown={handleKeydown}></textarea>

@ -4,7 +4,7 @@ title: tick
The `tick` function is unlike other lifecycle functions in that you can call it any time, not just when the component first initialises. It returns a promise that resolves as soon as any pending state changes have been applied to the DOM (or immediately, if there are no pending state changes). The `tick` function is unlike other lifecycle functions in that you can call it any time, not just when the component first initialises. It returns a promise that resolves as soon as any pending state changes have been applied to the DOM (or immediately, if there are no pending state changes).
When you invalidate component state in Svelte, it doesn't update the DOM immediately. Instead, it waits until the next *microtask* to see if there are any other changes that need to be applied, including in other components. Doing so avoids unnecessary work and allows the browser to batch things more effectively. When you update component state in Svelte, it doesn't update the DOM immediately. Instead, it waits until the next *microtask* to see if there are any other changes that need to be applied, including in other components. Doing so avoids unnecessary work and allows the browser to batch things more effectively.
You can see that behaviour in this example. Select a range of text and hit the tab key. Because the `<textarea>` value changes, the current selection is cleared and the cursor jumps, annoyingly, to the end. We can fix this by importing `tick`... You can see that behaviour in this example. Select a range of text and hit the tab key. Because the `<textarea>` value changes, the current selection is cleared and the cursor jumps, annoyingly, to the end. We can fix this by importing `tick`...

@ -4,7 +4,7 @@
function typewriter(node, { speed = 50 }) { function typewriter(node, { speed = 50 }) {
const valid = ( const valid = (
node.childNodes.length === 1 && node.childNodes.length === 1 &&
node.childNodes[0].nodeType === 3 node.childNodes[0].nodeType === Node.TEXT_NODE
); );
if (!valid) { if (!valid) {
@ -33,4 +33,4 @@
<p in:typewriter> <p in:typewriter>
The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog
</p> </p>
{/if} {/if}

@ -8,7 +8,7 @@ While you should generally use CSS for transitions as much as possible, there ar
function typewriter(node, { speed = 50 }) { function typewriter(node, { speed = 50 }) {
const valid = ( const valid = (
node.childNodes.length === 1 && node.childNodes.length === 1 &&
node.childNodes[0].nodeType === 3 node.childNodes[0].nodeType === Node.TEXT_NODE
); );
if (!valid) { if (!valid) {
@ -26,4 +26,4 @@ function typewriter(node, { speed = 50 }) {
} }
}; };
} }
``` ```

@ -56,7 +56,7 @@
<div class='board'> <div class='board'>
<input <input
placeholder="what needs to be done?" placeholder="what needs to be done?"
on:keydown={e => e.which === 13 && add(e.target)} on:keydown={e => e.key === 'Enter' && add(e.target)}
> >
<div class='left'> <div class='left'>
@ -145,4 +145,4 @@
label:hover button { label:hover button {
opacity: 1; opacity: 1;
} }
</style> </style>

@ -56,7 +56,7 @@
<div class='board'> <div class='board'>
<input <input
placeholder="what needs to be done?" placeholder="what needs to be done?"
on:keydown={e => e.which === 13 && add(e.target)} on:keydown={e => e.key === 'Enter' && add(e.target)}
> >
<div class='left'> <div class='left'>
@ -152,4 +152,4 @@
label:hover button { label:hover button {
opacity: 1; opacity: 1;
} }
</style> </style>

@ -56,7 +56,7 @@
<div class='board'> <div class='board'>
<input <input
placeholder="what needs to be done?" placeholder="what needs to be done?"
on:keydown={e => e.which === 13 && add(e.target)} on:keydown={e => e.key === 'Enter' && add(e.target)}
> >
<div class='left'> <div class='left'>
@ -152,4 +152,4 @@
label:hover button { label:hover button {
opacity: 1; opacity: 1;
} }
</style> </style>

@ -57,7 +57,7 @@
<div class='board'> <div class='board'>
<input <input
placeholder="what needs to be done?" placeholder="what needs to be done?"
on:keydown={e => e.which === 13 && add(e.target)} on:keydown={e => e.key === 'Enter' && add(e.target)}
> >
<div class='left'> <div class='left'>
@ -155,4 +155,4 @@
label:hover button { label:hover button {
opacity: 1; opacity: 1;
} }
</style> </style>

@ -1281,9 +1281,9 @@
} }
}, },
"@sveltejs/site-kit": { "@sveltejs/site-kit": {
"version": "1.1.4", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/@sveltejs/site-kit/-/site-kit-1.1.4.tgz", "resolved": "https://registry.npmjs.org/@sveltejs/site-kit/-/site-kit-1.1.5.tgz",
"integrity": "sha512-PsFUX1C/fhV0ODdCJaEQ8OwzgmaPJVmdefiSYA+i6zttBeV19d/ow+l7SPMXxBkux+vUIl5can4BwValCukCsw==", "integrity": "sha512-Rs2quQ/H00DAN/ZTFa+unLefL335UW3Yo4I2rTocW5JwW73Kvi5++d7BcY8LsjhMCbG1PkwQmJE2RVrIIxQcOw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@sindresorhus/slugify": "^0.9.1", "@sindresorhus/slugify": "^0.9.1",
@ -1291,13 +1291,14 @@
} }
}, },
"@sveltejs/svelte-repl": { "@sveltejs/svelte-repl": {
"version": "0.1.17", "version": "0.1.19",
"resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.1.17.tgz", "resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.1.19.tgz",
"integrity": "sha512-rM0DC+pZnqwH6PiuxXUmFRwYZ9XNkexxTNt+prR91Qs7ssxGgf0QkH6kGivSNLbrOtOvcgJbt1nUDybWra5HKA==", "integrity": "sha512-35R94X6uYgy6PHLQnQCsKcZ4zb6rGGQXjBYqjuCkoCykIlSLx8/avq6BGqudmE5pzVWDP3kk4063cHgccy1xYg==",
"dev": true, "dev": true,
"requires": { "requires": {
"codemirror": "^5.49.2", "codemirror": "^5.49.2",
"estree-walker": "^0.9.0", "estree-walker": "^0.9.0",
"marked": "^0.8.2",
"sourcemap-codec": "^1.4.6", "sourcemap-codec": "^1.4.6",
"svelte-json-tree": "0.0.5", "svelte-json-tree": "0.0.5",
"yootils": "0.0.16" "yootils": "0.0.16"
@ -1309,10 +1310,16 @@
"integrity": "sha512-12U47o7XHUX329+x3FzNVjCx3SHEzMF0nkDv7r/HnBzX/xNTKxajBk6gyygaxrAFtLj39219oMfbtxv4KpaOiA==", "integrity": "sha512-12U47o7XHUX329+x3FzNVjCx3SHEzMF0nkDv7r/HnBzX/xNTKxajBk6gyygaxrAFtLj39219oMfbtxv4KpaOiA==",
"dev": true "dev": true
}, },
"marked": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz",
"integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==",
"dev": true
},
"sourcemap-codec": { "sourcemap-codec": {
"version": "1.4.6", "version": "1.4.8",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
"integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==", "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
"dev": true "dev": true
} }
} }
@ -1358,9 +1365,9 @@
} }
}, },
"acorn": { "acorn": {
"version": "7.0.0", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.0.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
"integrity": "sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==", "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==",
"dev": true "dev": true
}, },
"ansi-colors": { "ansi-colors": {
@ -1594,9 +1601,9 @@
"dev": true "dev": true
}, },
"codemirror": { "codemirror": {
"version": "5.49.2", "version": "5.53.2",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.49.2.tgz", "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.53.2.tgz",
"integrity": "sha512-dwJ2HRPHm8w51WB5YTF9J7m6Z5dtkqbU9ntMZ1dqXyFB9IpjoUFDj80ahRVEoVanfIp6pfASJbOlbWdEf8FOzQ==", "integrity": "sha512-wvSQKS4E+P8Fxn/AQ+tQtJnF1qH5UOlxtugFLpubEZ5jcdH2iXTVinb+Xc/4QjshuOxRm4fUsU2QPF1JJKiyXA==",
"dev": true "dev": true
}, },
"color-convert": { "color-convert": {
@ -3157,6 +3164,11 @@
"xtend": "^4.0.0" "xtend": "^4.0.0"
} }
}, },
"prism-svelte": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/prism-svelte/-/prism-svelte-0.4.3.tgz",
"integrity": "sha512-plS7uY0WWiTBwWZs9KM3M88ZxHWKbrbMUDf52CPum6BqAxiLmKROmaTnmhXtv0krQ0l0HRLcFS8JDwOFyPt/OQ=="
},
"prismjs": { "prismjs": {
"version": "1.17.1", "version": "1.17.1",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.17.1.tgz", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.17.1.tgz",
@ -3483,9 +3495,9 @@
} }
}, },
"sapper": { "sapper": {
"version": "0.27.8", "version": "0.27.11",
"resolved": "https://registry.npmjs.org/sapper/-/sapper-0.27.8.tgz", "resolved": "https://registry.npmjs.org/sapper/-/sapper-0.27.11.tgz",
"integrity": "sha512-78K+56yu9nGOEU0B0XjBvNchRuPEv4aHbAKK4D874S4aoapMAkHCT0bHtPK12S3P7JPxvvT8GzHaq/8NetMmbg==", "integrity": "sha512-5EaPZhlc8OnyN3UCI6dRSM1Gz5sxyzLZG/1z5nMvZhg9Ng+rSvEvJx/rW/tSHcnQPa8or7+YcbfvQHKS5oPHiw==",
"dev": true, "dev": true,
"requires": { "requires": {
"html-minifier": "^4.0.0", "html-minifier": "^4.0.0",

@ -24,6 +24,7 @@
"marked": "^0.7.0", "marked": "^0.7.0",
"pg": "^7.12.1", "pg": "^7.12.1",
"polka": "^1.0.0-next.9", "polka": "^1.0.0-next.9",
"prism-svelte": "^0.4.3",
"prismjs": "^1.17.1", "prismjs": "^1.17.1",
"sirv": "^1.0.0-next.2", "sirv": "^1.0.0-next.2",
"yootils": "0.0.16" "yootils": "0.0.16"
@ -35,8 +36,8 @@
"@babel/preset-env": "^7.6.0", "@babel/preset-env": "^7.6.0",
"@babel/runtime": "^7.6.0", "@babel/runtime": "^7.6.0",
"@sindresorhus/slugify": "^0.9.1", "@sindresorhus/slugify": "^0.9.1",
"@sveltejs/site-kit": "^1.1.4", "@sveltejs/site-kit": "^1.1.5",
"@sveltejs/svelte-repl": "^0.1.17", "@sveltejs/svelte-repl": "^0.1.19",
"degit": "^2.1.4", "degit": "^2.1.4",
"dotenv": "^8.1.0", "dotenv": "^8.1.0",
"esm": "^3.2.25", "esm": "^3.2.25",
@ -53,7 +54,7 @@
"rollup-plugin-replace": "^2.2.0", "rollup-plugin-replace": "^2.2.0",
"rollup-plugin-svelte": "^5.1.0", "rollup-plugin-svelte": "^5.1.0",
"rollup-plugin-terser": "^5.1.1", "rollup-plugin-terser": "^5.1.1",
"sapper": "^0.27.8", "sapper": "^0.27.11",
"shelljs": "^0.8.3", "shelljs": "^0.8.3",
"svelte": "^3.12.0" "svelte": "^3.12.0"
}, },

@ -45,7 +45,7 @@ async function main() {
image.autocrop(); image.autocrop();
// image.scale(0.25); // image.scale(0.25);
if (image.bitmap.width > 200 || image.bitmap.width > 200) { if (image.bitmap.width > 200 || image.bitmap.height > 200) {
const scale = Math.min( const scale = Math.min(
200 / image.bitmap.width, 200 / image.bitmap.width,
200 / image.bitmap.height 200 / image.bitmap.height

@ -133,44 +133,14 @@
border: 0.8rem solid var(--second); border: 0.8rem solid var(--second);
} }
/* headers anchors */
.post :global(.offset-anchor) {
position: relative;
display: block;
top: calc(-1 * (var(--nav-h) + var(--top-offset) - 1rem));
width: 0;
height: 0;
}
.post :global(.anchor) { .post :global(.anchor) {
position: absolute;
display: block;
background: url(/icons/link.svg) 0 50% no-repeat;
background-size: 1em 1em;
width: 1.4em;
height: 1em;
top: calc((var(--h3) - 24px) / 2); top: calc((var(--h3) - 24px) / 2);
left: -1.4em;
opacity: 0;
transition: opacity 0.2s;
border: none !important; /* TODO get rid of linkify */
} }
.post :global(h2):hover :global(.anchor),
.post :global(h3):hover :global(.anchor),
.post :global(h4):hover :global(.anchor),
.post :global(h5):hover :global(.anchor),
.post :global(h6):hover :global(.anchor) {
opacity: 1;
}
@media (max-width: 768px) { @media (max-width: 768px) {
.post :global(.anchor) { .post :global(.anchor) {
transform: scale(0.6); transform: scale(0.6);
opacity: 1; opacity: 1;
top: calc((1em - 0.6 * 24px) / 2);
left: -1.0em; left: -1.0em;
} }
} }

@ -1,4 +0,0 @@
export function get(req, res) {
res.writeHead(302, { Location: 'https://github.com/sveltejs/svelte/wiki/FAQ' });
res.end();
}

@ -0,0 +1,58 @@
import fs from 'fs';
import path from 'path';
import { extract_frontmatter, link_renderer } from '@sveltejs/site-kit/utils/markdown.js';
import marked from 'marked';
import { makeSlugProcessor } from '../../utils/slug';
import { highlight } from '../../utils/highlight';
import { SLUG_PRESERVE_UNICODE } from '../../../config';
const makeSlug = makeSlugProcessor(SLUG_PRESERVE_UNICODE);
export default function get_faqs() {
return fs
.readdirSync('content/faq')
.map(file => {
if (path.extname(file) !== '.md') return;
const match = /^([0-9]+)-(.+)\.md$/.exec(file);
if (!match) throw new Error(`Invalid filename '${file}'`);
const [, order, slug] = match;
const markdown = fs.readFileSync(`content/faq/${file}`, 'utf-8');
const { content, metadata } = extract_frontmatter(markdown);
const renderer = new marked.Renderer();
renderer.link = link_renderer;
renderer.code = highlight;
renderer.heading = (text, level, rawtext) => {
const fragment = makeSlug(rawtext);
return `
<h${level}>
<span id="${fragment}" class="offset-anchor"></span>
<a href="faq#${fragment}" class="anchor" aria-hidden="true"></a>
${text}
</h${level}>`;
};
const answer = marked(
content.replace(/^\t+/gm, match => match.split('\t').join(' ')),
{ renderer }
);
const fragment = makeSlug(slug);
return {
fragment,
order,
answer,
metadata
};
})
.sort((a, b) => a.order - b.order);
}

@ -0,0 +1,24 @@
import send from '@polka/send';
import get_faqs from './_faqs.js';
let json;
export function get(req, res) {
if (!json || process.env.NODE_ENV !== 'production') {
const faqs = get_faqs()
.map(faq => {
return {
fragment: faq.fragment,
answer: faq.answer,
metadata: faq.metadata
};
});
json = JSON.stringify(faqs);
}
send(res, 200, json, {
'Content-Type': 'application/json',
'Cache-Control': `max-age=${5 * 60 * 1e3}` // 5 minutes
});
}

@ -0,0 +1,89 @@
<script context="module">
export async function preload() {
const faqs = await this.fetch(`faq.json`).then(r => r.json());
return { faqs };
}
</script>
<script>
const description = "Frequently Asked Questions about Svelte"
export let faqs;
</script>
<svelte:head>
<title>Frequently Asked Questions • Svelte</title>
<meta name="twitter:title" content="Svelte FAQ">
<meta name="twitter:description" content={description}>
<meta name="Description" content={description}>
</svelte:head>
<div class='faqs stretch'>
<h1>Frequently Asked Questions</h1>
{#each faqs as faq}
<article class='faq'>
<h2>
<span id={faq.fragment} class="offset-anchor"></span>
<a class="anchor" rel='prefetch' href='faq#{faq.fragment}' title='{faq.question}'>&nbsp;</a>
{faq.metadata.question}
</h2>
<p>{@html faq.answer}</p>
</article>
{/each}
</div>
<style>
.faqs {
grid-template-columns: 1fr 1fr;
grid-gap: 1em;
min-height: calc(100vh - var(--nav-h));
padding: var(--top-offset) var(--side-nav) 6rem var(--side-nav);
max-width: var(--main-width);
margin: 0 auto;
}
h2 {
display: inline-block;
margin: 3.2rem 0 1rem 0;
color: var(--text);
max-width: 18em;
font-size: var(--h3);
font-weight: 400;
}
.faq:first-child {
margin: 0 0 2rem 0;
padding: 0 0 4rem 0;
border-bottom: var(--border-w) solid #6767785b; /* based on --second */
}
.faq:first-child h2 {
font-size: 4rem;
font-weight: 400;
color: var(--second);
}
.faq p {
font-size: var(--h5);
max-width: 30em;
color: var(--second);
}
:global(.faqs .faq ul) {
margin-left: 3.2rem;
}
.faqs :global(.anchor) {
top: calc((var(--h3) - 24px) / 2);
}
@media (max-width: 768px) {
.faqs :global(.anchor) {
transform: scale(0.6);
opacity: 1;
left: -1.0em;
}
}
</style>

@ -30,7 +30,7 @@
$: canSave = $session.user && gist && gist.owner === $session.user.uid; $: canSave = $session.user && gist && gist.owner === $session.user.uid;
function handleKeydown(event) { function handleKeydown(event) {
if (event.which === 83 && (isMac ? event.metaKey : event.ctrlKey)) { if (event.key === 's' && (isMac ? event.metaKey : event.ctrlKey)) {
event.preventDefault(); event.preventDefault();
save(); save();
} }

@ -57,7 +57,10 @@
is_relaxed_gist = data.relaxed; is_relaxed_gist = data.relaxed;
const components = data.files.map(file => { const components = data.files.map(file => {
let [name, type] = file.name.split('.'); const dot = file.name.lastIndexOf(".");
let name = file.name.slice(0, dot);
let type = file.name.slice(dot + 1);
if (type === 'html') type = 'svelte'; // TODO do this on the server if (type === 'html') type = 'svelte'; // TODO do this on the server
return { name, type, source: file.source }; return { name, type, source: file.source };
}); });

@ -7,6 +7,7 @@
%sapper.base% %sapper.base%
<link href=global.css rel=stylesheet>
<link href=prism.css rel=stylesheet> <link href=prism.css rel=stylesheet>
<link rel='manifest' href='manifest.json'> <link rel='manifest' href='manifest.json'>
<link rel='icon' type='image/png' href='favicon.png'> <link rel='icon' type='image/png' href='favicon.png'>

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -1,500 +1,31 @@
/* /* headers anchors */
-----------------------------------------------
vars css custom-properties
NOTE .offset-anchor {
- some vars change inside media-queries!
- under normal conditions, there's no need to touch these
-----------------------------------------------
*/
:root {
--nav-h: 6rem;
--top-offset: 6rem;
--sidebar-w: 30rem;
--sidebar-mid-w: 36rem;
--sidebar-large-w: 48rem;
--main-width: 80rem;
--code-w: 72em;
--side-nav: 3.2rem;
--side-page: var(--side-nav);
/* easings */
--in-cubic: cubic-bezier(0.55, 0.055, 0.675, 0.19);
--out-cubic: cubic-bezier(0.215, 0.61, 0.355, 1);
--inout-cubic: cubic-bezier(0.645, 0.045, 0.355, 1);
--in-back: cubic-bezier(0.6, -0.28, 0.735, 0.045);
--out-back: cubic-bezier(0.175, 0.885, 0.32, 1.275);
--inout-back: cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
@media screen and (min-width: 768px) {
:root {
--side-page: 14vw;
--top-offset: 10rem;
--side-nav: 4.8rem;
}
}
/* theme vars */
.theme-default {
--back: #ffffff;
--back-light: #f6fafd;
--back-api: #eff8ff;
--prime: #ff3e00;
--second: #676778;
--flash: #40b3ff;
--heading: var(--second);
--text: #444;
--sidebar-text: rgba(255, 255, 255, .75);
--border-w: .3rem; /* border-width */
--border-r: .4rem; /* border-radius */
}
/* typo vars */
.typo-default {
--unit: .8rem;
--code-fs: 1.3rem;
--h6: 1.4rem;
--h5: 1.6rem;
--h4: 1.8rem; /* default font-size */
--h3: 2.6rem;
--h2: 3rem;
--h1: 3.2rem;
--linemax: 42em; /* max line-length */
--lh: 1.5; /* base line-height */
}
body {
--font: 'Overpass', sans-serif;
--font-mono: 'Fira Mono', monospace;
--font-ui: var(--font-mono);
--font-system: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
}
/* fonts ---------------------------------- */
/* overpass-300normal - latin */
@font-face {
font-family: 'Overpass';
font-style: normal;
font-weight: 300;
font-display: fallback;
src:
local('Overpass Light '),
local('Overpass-Light'),
url('fonts/overpass/overpass-latin-300.woff2') format('woff2');
}
/* overpass-600normal - latin */
@font-face {
font-family: 'Overpass';
font-style: normal;
font-weight: 600;
font-display: fallback;
src:
local('Overpass Bold '),
local('Overpass-Bold'),
url('fonts/overpass/overpass-latin-600.woff2') format('woff2');
}
/* fira-mono-400normal - latin */
@font-face {
font-family: 'Fira Mono';
font-style: normal;
font-weight: 400;
font-display: fallback;
src:
local('Fira Mono Regular '),
local('Fira Mono-Regular'),
url('fonts/fira-mono/fira-mono-latin-400.woff2') format('woff2');
}
/* base reset ----------------------------- */
html {
font-size: 62.5%;
-ms-text-size-adjust: 62.5%;
-webkit-text-size-adjust: 62.5%;
-ms-overflow-style: -ms-autohiding-scrollbar;
box-sizing: border-box;
border-collapse: collapse;
}
html,
body,
#sapper {
width: 100%;
height: 100%;
}
* {
box-sizing: inherit;
margin: 0;
padding: 0;
}
/* link reset ----------------------------- */
a {
text-decoration: none;
cursor: pointer;
color: inherit;
}
a:hover, a:active { color: var(--flash) }
a:focus { outline: none }
/*
-----------------------------------------------
global styles
-----------------------------------------------
*/
/* typography ----------------------------- */
body {
font: 300 var(--h4)/var(--lh) var(--font);
background-color: var(--back);
color: var(--text);
/* default spacing of Overpass is a bit too airy */
/* letter-spacing: -.013em; */
}
h1, h2, h3, h4, h5, h6, blockquote {
position: relative;
margin: 0;
color: var(--heading);
}
/* h1, h2, h3, h4, h5, h6 { font-weight: 600 } */
h6 { font-size: var(--h6) }
h5 { font-size: var(--h5) }
h4 { font-size: var(--h4) }
h3 { font-size: var(--h3) }
h2 { font-size: var(--h2) }
h1 { font-size: var(--h1) }
h1, h2 {
font-family: var(--font);
line-height: 1.25;
}
h3 { font-weight: 300 }
p, ol, ul {
margin: 0 0 1em 0;
}
.b, b, strong { font-weight: 600 }
tt, code, kbd, samp {
font: 400 var(--code-fs)/1.7 var(--font-mono);
}
code {
position: relative;
border-radius: .3em;
white-space: nowrap;
color: #444;
-webkit-font-smoothing: initial;
}
pre code {
top: 0;
white-space: inherit;
background-color: none;
}
/* sync CodeMirror with prism */
.CodeMirror {
font-size: var(--code-fs) !important;
}
::selection {
background: var(--flash);
color: white;
}
/* opinionated styles --------------------- */
li:not(.white) > h2 {
color: var(--second)
}
blockquote {
position: relative;
margin: 1.6rem 0 2.4rem;
padding: 2rem 2.4rem 1.8rem 2.4rem;
border-radius: var(--border-r);
font-family: var(--font);
max-width: var(--linemax);
}
blockquote p {
font-size: var(--h5);
}
blockquote :last-child {
margin: 0;
}
/* buttons -------------------------------- */
button {
font-family: inherit;
font-size: inherit;
background-color: transparent;
border: none;
color: currentColor;
cursor: pointer;
}
button:focus,
.btn:focus { outline: 0 }
button[disabled],
.btn[disabled],
.btn:hover[disabled] {
opacity: .55;
pointer-events: none;
}
button > svg,
.btn > svg {
position: relative;
top: -.1rem;
width: 2rem !important;
height: 2rem !important;
stroke: currentColor !important;
}
/* reset ------- */
.btn {
--btn-h: 4rem;
--btn-outline: .2rem;
--btn-font: var(--font);
--btn-calc-h: calc(var(--btn-h) - var(--btn-outline) * 2);
--btn-hover: linear-gradient(to top, rgba(0,0,0,.07), rgba(0,0,0,.07));
position: relative;
margin: 0 .8rem .8rem 0;
vertical-align: middle;
white-space: nowrap;
display: inline-block;
zoom: 1;
border: none transparent;
font: var(--h4) var(--btn-font);
border-radius: var(--border-r);
color: currentColor;
cursor: pointer;
}
/* default */
.btn {
line-height: var(--btn-h);
height: var(--btn-h);
padding: 0 1.6rem;
transition: all .1s;
}
.btn:hover {
transform: scale(.98);
mix-blend-mode: multiply;
background-image: var(--btn-hover);
}
/* optional */
.btn[outline] {
line-height: var(--btn-calc-h);
height: var(--btn-calc-h);
border: var(--btn-outline) solid currentColor;
background-color: white;
color: currentColor;
}
/* links ------------------------------------- */
a {
position: relative;
padding: 0 0 1px 0;
border-bottom: 1px solid currentColor;
user-select: none;
color: var(--prime);
transition: color .2s, border .2s, padding .2s;
}
a:hover {
color: var(--flash);
}
a:hover {
padding: 0;
border-bottom: 2px solid currentColor;
}
a.no-underline {
border-bottom: none;
padding: 0;
}
/* a:hover:not(.disabled) > .icon { stroke: var(--flash) } */
/* lists ---------------------------------- */
.listify ol,
.listify ul {
--list-padding: 2.9rem;
list-style: none;
color: currentColor;
margin-left: var(--list-padding);
}
.listify ol > li,
.listify ul > li {
max-width: calc(var(--linemax) - var(--list-padding));
line-height: 1.5;
margin: 0 0 0.4rem 0;
}
.listify ul > li:before {
content: '';
position: absolute;
margin-top: 1.1rem;
margin-left: -1.8rem;
background-color: var(--second);
width: .6rem;
height: .6rem;
border-radius: 2px;
opacity: 0.7;
}
.listify ol { list-style: decimal }
/* tables --------------------------------- */
table {
width: 100%;
font-size: var(--h5);
}
td, th {
text-align: left;
border-bottom: 1px solid #eee;
padding: 0.4rem 0.8rem 0.4rem 0;
}
table code, table span {
white-space: pre;
}
/* grid ----------------------------------- */
.grid, .grid.half {
display: grid;
grid-gap: 2.4rem;
grid-template-columns: 1fr;
align-items: center;
}
.grid.stretch { align-items: stretch }
.grid > .cols-2,
.grid > .cols-3 { grid-column: span 1 }
@media screen and (min-width: 840px) {
.grid.half,
.grid { grid-template-columns: repeat(2, 1fr) }
.grid > .cols-2,
.grid > .cols-3 { grid-column: span 2 }
}
@media screen and (min-width: 1100px) {
.grid { grid-template-columns: repeat(3, 1fr) }
.grid > .cols-2 { grid-column: span 2 }
.grid > .cols-3 { grid-column: span 3 }
}
/* helper styles -------------------------- */
.flex-auto { flex: 1 0 auto }
.py0 {
padding-top: 0 !important;
padding-bottom: 0 !important;
}
.legend, figcaption, .post aside {
max-width: none;
margin: 0 auto;
padding: 1.6rem 0 0 .8rem;
font: 1.2rem/1.6 var(--font-ui);
}
.filename {
display: inline-block;
padding: 1.6rem 0 0 1rem;
font: var(--h6) var(--font-ui);
}
.box {
padding: 2.4rem 3.2rem;
border-radius: var(--border-r);
}
/* theme colors --------------------------- */
.prime { color: var(--prime) !important }
.second { color: var(--second) !important }
.flash { color: var(--flash) !important }
.black { color: black !important }
.white { color: white !important }
.back { background-color: var(--back) !important }
.back-light { background-color: var(--back-light) !important }
.bg-prime { background-color: var(--prime) !important }
.bg-second { background-color: var(--second) !important }
.bg-flash { background-color: var(--flash) !important }
/* inputs --------------------------------- */
input[type="checkbox"] {
/* display: block; */
position: relative; position: relative;
height: 1em;
width: calc(100% - 0.6em);
max-width: 2em;
top: -2px;
border-radius: 0.5em;
-webkit-appearance: none;
outline: none;
margin: 0 0.6em 0 0;
}
input[type="checkbox"]::before {
content: "";
position: absolute;
display: block; display: block;
height: 100%; top: calc(-1 * (var(--nav-h) + var(--top-offset)) + 11rem);
width: 100%; width: 0;
padding: 2px; height: 0;
border-radius: 1em;
top: 0;
left: 0;
background: var(--second);
/* box-sizing: border-box; */
box-sizing: content-box;
} }
input[type="checkbox"]:checked::before { .anchor {
background: var(--prime);
}
input[type="checkbox"]::after {
content: "";
position: absolute; position: absolute;
display: block; display: block;
background: url(/icons/link.svg) 0 50% no-repeat;
background-size: 1em 1em;
width: 1.4em;
height: 1em; height: 1em;
width: 1em; top: calc(((var(--h3) - 24px) / 2) + 0.6em);
top: 2px; left: -1.4em;
left: 2px; opacity: 0;
border-radius: 1em; transition: opacity 0.2s;
background: white; border: none !important; /* TODO get rid of linkify */
box-shadow: 0 0px 1px rgba(0,0,0,.4), 0 4px 2px rgba(0,0,0,.1); }
-webkit-transition: background .2s ease-out, left .2s ease-out;
} h2:hover .anchor,
h3:hover .anchor,
input[type="checkbox"]:checked::after { h4:hover .anchor,
left: calc(100% - 9px); h5:hover .anchor,
h6:hover .anchor {
opacity: 1;
} }

@ -1,7 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#fff" stroke-width="2"><path d="m5 12h14"/><path d="m12 5 7 7-7 7"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<g fill="none" stroke="white" stroke-width="2">
<line x1='5' y1='12' x2='19' y2='12' />
<polyline points='12 5 19 12 12 19' />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 275 B

After

Width:  |  Height:  |  Size: 184 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m21 7-12 12-5.5-5.5 1.41-1.41 4.09 4.08 10.59-10.58z" fill="#aa1e1e"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path style="fill: #aa1e1e" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z" />
</svg>

Before

Width:  |  Height:  |  Size: 229 B

After

Width:  |  Height:  |  Size: 168 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m2 8 10 8 10-8" fill="none" stroke="#676778" stroke-width="2"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path style="stroke: #676778; stroke-width: 2; fill: none" d="M2,8 L12,16 L22,8"/>
</svg>

Before

Width:  |  Height:  |  Size: 221 B

After

Width:  |  Height:  |  Size: 161 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m19.5 3.09 1.41 1.41-4.5 4.5h3.59v2h-7v-7h2v3.59zm1.41 16.41-1.41 1.41-4.5-4.5v3.59h-2v-7h7v2h-3.59zm-16.41-16.41 4.5 4.5v-3.59h2v7h-7v-2h3.59l-4.5-4.5zm-1.41 16.41 4.5-4.5h-3.59v-2h7v7h-2v-3.59l-4.5 4.5z" fill="#aa1e1e"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path style="fill: #aa1e1e" d="M19.5,3.09L20.91,4.5L16.41,9H20V11H13V4H15V7.59L19.5,3.09M20.91,19.5L19.5,20.91L15,16.41V20H13V13H20V15H16.41L20.91,19.5M4.5,3.09L9,7.59V4H11V11H4V9H7.59L3.09,4.5L4.5,3.09M3.09,19.5L7.59,15H4V13H11V20H9V16.41L4.5,20.91L3.09,19.5Z" />
</svg>

Before

Width:  |  Height:  |  Size: 405 B

After

Width:  |  Height:  |  Size: 320 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m5 20h14v-2h-14m14-9h-4v-6h-6v6h-4l7 7z" fill="#aa1e1e"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#aa1e1e" d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" />
</svg>

Before

Width:  |  Height:  |  Size: 212 B

After

Width:  |  Height:  |  Size: 155 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m3 6h18v2h-18zm0 5h18v2h-18zm0 5h18v2h-18z" fill="#999"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#999" d="M3,6H21V8H3V6M3,11H21V13H3V11M3,16H21V18H3V16Z" />
</svg>

Before

Width:  |  Height:  |  Size: 213 B

After

Width:  |  Height:  |  Size: 155 B

@ -1,7 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#fff" stroke-width="2"><path d="m20 14.66v5.34a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2-2v-14a2 2 0 0 1 2-2h5.34"/><path d="m18 2 4 4-10 10h-4v-4z"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<g style="fill: none; stroke: white; stroke-width: 2;">
<path d='M20 14.66V20a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h5.34' />
<polygon points='18 2 22 6 12 16 8 16 8 12 18 2' />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 333 B

After

Width:  |  Height:  |  Size: 256 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m9.5 13.09 1.41 1.41-4.5 4.5h3.59v2h-7v-7h2v3.59zm1.41-3.59-1.41 1.41-4.5-4.5v3.59h-2v-7h7v2h-3.59zm3.59 3.59 4.5 4.5v-3.59h2v7h-7v-2h3.59l-4.5-4.5zm-1.41-3.59 4.5-4.5h-3.59v-2h7v7h-2v-3.59l-4.5 4.5z" fill="#aa1e1e"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path style="fill: #aa1e1e" d="M9.5,13.09L10.91,14.5L6.41,19H10V21H3V14H5V17.59L9.5,13.09M10.91,9.5L9.5,10.91L5,6.41V10H3V3H10V5H6.41L10.91,9.5M14.5,13.09L19,17.59V14H21V21H14V19H17.59L13.09,14.5L14.5,13.09M13.09,9.5L17.59,5H14V3H21V10H19V6.41L14.5,10.91L13.09,9.5Z" />
</svg>

Before

Width:  |  Height:  |  Size: 411 B

After

Width:  |  Height:  |  Size: 315 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m12 5c4.97 0 9 2.69 9 6 0 1.68-1.04 3.2-2.71 4.29 1.07-.87 1.71-1.97 1.71-3.16 0-2.84-3.58-5.13-8-5.13v3l-4-4 4-4zm0 14c-4.97 0-9-2.69-9-6 0-1.68 1.04-3.2 2.71-4.29-1.07.87-1.71 1.97-1.71 3.17 0 2.83 3.58 5.12 8 5.12v-3l4 4-4 4z" fill="#aa1e1e"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#aa1e1e" d="M12,5C16.97,5 21,7.69 21,11C21,12.68 19.96,14.2 18.29,15.29C19.36,14.42 20,13.32 20,12.13C20,9.29 16.42,7 12,7V10L8,6L12,2V5M12,19C7.03,19 3,16.31 3,13C3,11.32 4.04,9.8 5.71,8.71C4.64,9.58 4,10.68 4,11.88C4,14.71 7.58,17 12,17V14L16,18L12,22V19Z" />
</svg>

Before

Width:  |  Height:  |  Size: 415 B

After

Width:  |  Height:  |  Size: 344 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m3 4v8.5l3-3 3 3.5c1 1 1 2 1 2v6h4v-7s0-1-.53-2-1.47-2-1.47-2l-3-3.42 2.5-2.58m6.5 0-4.46 4.47.46.53s.93 1 1.47 2c.21.4.33.79.4 1.13l5.13-5.13" fill="#aa1e1e"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#aa1e1e" d="M3,4V12.5L6,9.5L9,13C10,14 10,15 10,15V21H14V14C14,14 14,13 13.47,12C12.94,11 12,10 12,10L9,6.58L11.5,4M18,4L13.54,8.47L14,9C14,9 14.93,10 15.47,11C15.68,11.4 15.8,11.79 15.87,12.13L21,7" />
</svg>

Before

Width:  |  Height:  |  Size: 356 B

After

Width:  |  Height:  |  Size: 258 B

@ -1,8 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#333"><path d="m9 7h-3a2 2 0 0 0 0 10h3"/><path d="m15 7h3a2 2 0 0 1 0 10h-3"/><path d="m7 12h10"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<g fill="none" stroke="#333">
<path d="M9,7L6,7A2 2 0 0 0 6,17L9,17"/>
<path d="M15,7L18,7A2 2 0 0 1 18,17L15,17"/>
<path d="M7,12L17,12"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 215 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m15 9h-10v-4h10m-3 14a3 3 0 0 1 -3-3 3 3 0 0 1 3-3 3 3 0 0 1 3 3 3 3 0 0 1 -3 3m5-16h-12c-1.11 0-2 .9-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-12z" fill="#aa1e1e"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#aa1e1e" d="M15,9H5V5H15M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M17,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3Z" />
</svg>

Before

Width:  |  Height:  |  Size: 320 B

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

@ -1,16 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg enable-background="new 0 0 98.2 118" viewBox="0 0 98.2 118" xmlns="http://www.w3.org/2000/svg"><path d="m91.9 15.6c-10.9-15.7-32.6-20.3-48.2-10.3l-27.5 17.5c-7.5 4.7-12.7 12.4-14.2 21.1-1.3 7.3-.2 14.8 3.3 21.3-2.4 3.6-4 7.6-4.7 11.8-1.6 8.9.5 18.1 5.7 25.4 11 15.7 32.6 20.3 48.2 10.4l27.5-17.5c7.5-4.7 12.7-12.4 14.2-21.1 1.3-7.3.2-14.8-3.3-21.3 2.4-3.6 4-7.6 4.7-11.8 1.6-9-.4-18.2-5.7-25.5m-50.9 88.3c-8.9 2.3-18.2-1.2-23.4-8.7-3.2-4.4-4.4-9.9-3.5-15.3.2-.9.4-1.7.6-2.6l.5-1.6 1.4 1c3.3 2.4 6.9 4.2 10.8 5.4l1 .3-.1 1c-.1 1.4.3 2.9 1.1 4.1 1.6 2.3 4.4 3.4 7.1 2.7.6-.2 1.2-.4 1.7-.7l27.4-17.5c1.4-.9 2.3-2.2 2.6-3.8s-.1-3.3-1-4.6c-1.6-2.3-4.4-3.3-7.1-2.6-.6.2-1.2.4-1.7.7l-10.4 6.6c-1.7 1.1-3.6 1.9-5.6 2.4-8.9 2.3-18.2-1.2-23.4-8.7-3.1-4.4-4.4-9.9-3.4-15.3.9-5.2 4.1-9.9 8.6-12.7l27.4-17.5c1.7-1.1 3.6-1.9 5.6-2.5 8.9-2.3 18.2 1.2 23.4 8.7 3.2 4.4 4.4 9.9 3.5 15.3-.2.9-.4 1.7-.7 2.6l-.5 1.6-1.4-1c-3.3-2.4-6.9-4.2-10.8-5.4l-1-.3.1-1c.1-1.4-.3-2.9-1.1-4.1-1.6-2.3-4.4-3.3-7.1-2.6-.6.2-1.2.4-1.7.7l-27.4 17.6c-1.4.9-2.3 2.2-2.6 3.8s.1 3.3 1 4.6c1.6 2.3 4.4 3.3 7.1 2.6.6-.2 1.2-.4 1.7-.7l10.5-6.7c1.7-1.1 3.6-1.9 5.6-2.5 8.9-2.3 18.2 1.2 23.4 8.7 3.2 4.4 4.4 9.9 3.5 15.3-.9 5.2-4.1 9.9-8.6 12.7l-27.4 17.5c-1.8 1.1-3.7 1.9-5.7 2.5"/></svg>
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 98.2 118" style="enable-background:new 0 0 98.2 118;" xml:space="preserve">
<path d="M91.9,15.6C81-0.1,59.3-4.7,43.7,5.3L16.2,22.8C8.7,27.5,3.5,35.2,2,43.9c-1.3,7.3-0.2,14.8,3.3,21.3
c-2.4,3.6-4,7.6-4.7,11.8c-1.6,8.9,0.5,18.1,5.7,25.4c11,15.7,32.6,20.3,48.2,10.4L82,95.3c7.5-4.7,12.7-12.4,14.2-21.1
c1.3-7.3,0.2-14.8-3.3-21.3c2.4-3.6,4-7.6,4.7-11.8C99.2,32.1,97.2,22.9,91.9,15.6 M41,103.9c-8.9,2.3-18.2-1.2-23.4-8.7
c-3.2-4.4-4.4-9.9-3.5-15.3c0.2-0.9,0.4-1.7,0.6-2.6l0.5-1.6l1.4,1c3.3,2.4,6.9,4.2,10.8,5.4l1,0.3l-0.1,1c-0.1,1.4,0.3,2.9,1.1,4.1
c1.6,2.3,4.4,3.4,7.1,2.7c0.6-0.2,1.2-0.4,1.7-0.7l27.4-17.5c1.4-0.9,2.3-2.2,2.6-3.8c0.3-1.6-0.1-3.3-1-4.6
c-1.6-2.3-4.4-3.3-7.1-2.6c-0.6,0.2-1.2,0.4-1.7,0.7L48,68.3c-1.7,1.1-3.6,1.9-5.6,2.4c-8.9,2.3-18.2-1.2-23.4-8.7
c-3.1-4.4-4.4-9.9-3.4-15.3c0.9-5.2,4.1-9.9,8.6-12.7l27.4-17.5c1.7-1.1,3.6-1.9,5.6-2.5c8.9-2.3,18.2,1.2,23.4,8.7
c3.2,4.4,4.4,9.9,3.5,15.3c-0.2,0.9-0.4,1.7-0.7,2.6l-0.5,1.6l-1.4-1c-3.3-2.4-6.9-4.2-10.8-5.4l-1-0.3l0.1-1
c0.1-1.4-0.3-2.9-1.1-4.1c-1.6-2.3-4.4-3.3-7.1-2.6c-0.6,0.2-1.2,0.4-1.7,0.7L32.5,46.1c-1.4,0.9-2.3,2.2-2.6,3.8
c-0.3,1.6,0.1,3.3,1,4.6c1.6,2.3,4.4,3.3,7.1,2.6c0.6-0.2,1.2-0.4,1.7-0.7l10.5-6.7c1.7-1.1,3.6-1.9,5.6-2.5
c8.9-2.3,18.2,1.2,23.4,8.7c3.2,4.4,4.4,9.9,3.5,15.3c-0.9,5.2-4.1,9.9-8.6,12.7l-27.4,17.5C44.9,102.5,43,103.3,41,103.9"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -1,20 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg enable-background="new 0 0 98.4 118.3" viewBox="0 0 98.4 118.3" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#ff3e00" stroke-width=".25"><path d="m92 15.7c-10.9-15.6-32.5-20.3-48.2-10.3l-27.5 17.5c-7.5 4.7-12.7 12.4-14.2 21.1-1.3 7.3-.2 14.8 3.3 21.3-2.4 3.6-4 7.6-4.7 11.8-1.6 8.9.5 18.1 5.7 25.4 11 15.7 32.6 20.3 48.2 10.4l27.5-17.5c7.5-4.7 12.7-12.4 14.2-21.1 1.3-7.3.2-14.8-3.3-21.3 2.4-3.6 4-7.6 4.7-11.8 1.7-9-.4-18.1-5.7-25.5"/><path d="m41.1 104c-8.9 2.3-18.2-1.2-23.4-8.7-3.2-4.4-4.4-9.9-3.5-15.3.2-.9.4-1.7.6-2.6l.5-1.6 1.4 1c3.3 2.4 6.9 4.2 10.8 5.4l1 .3-.1 1c-.1 1.4.3 2.9 1.1 4.1 1.6 2.3 4.4 3.4 7.1 2.7.6-.2 1.2-.4 1.7-.7l27.4-17.5c1.4-.9 2.3-2.2 2.6-3.8s-.1-3.3-1-4.6c-1.6-2.3-4.4-3.3-7.1-2.6-.6.2-1.2.4-1.7.7l-10.5 6.7c-1.7 1.1-3.6 1.9-5.6 2.4-8.9 2.3-18.2-1.2-23.4-8.7-3.1-4.4-4.4-9.9-3.4-15.3.9-5.2 4.1-9.9 8.6-12.7l27.4-17.5c1.7-1.1 3.6-1.9 5.6-2.5 8.9-2.3 18.2 1.2 23.4 8.7 3.2 4.4 4.4 9.9 3.5 15.3-.2.9-.4 1.7-.7 2.6l-.4 1.6-1.4-1c-3.3-2.4-6.9-4.2-10.8-5.4l-1-.3.1-1c.1-1.4-.3-2.9-1.1-4.1-1.6-2.3-4.4-3.3-7.1-2.6-.6.2-1.2.4-1.7.7l-27.4 17.5c-1.4.8-2.3 2.2-2.6 3.8s.1 3.3 1 4.6c1.6 2.3 4.4 3.3 7.1 2.6.6-.2 1.2-.4 1.7-.7l10.5-6.7c1.7-1.1 3.6-1.9 5.6-2.5 8.9-2.3 18.2 1.2 23.4 8.7 3.2 4.4 4.4 9.9 3.5 15.3-.9 5.2-4.1 9.9-8.6 12.7l-27.4 17.5c-1.8 1.1-3.7 2-5.7 2.5"/></g></svg>
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 98.4 118.3" style="enable-background:new 0 0 98.4 118.3;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#FF3E00;stroke-width:0.25;}
</style>
<path class="st0" d="M92,15.7C81.1,0.1,59.5-4.6,43.8,5.4L16.3,22.9C8.8,27.6,3.6,35.3,2.1,44c-1.3,7.3-0.2,14.8,3.3,21.3
c-2.4,3.6-4,7.6-4.7,11.8c-1.6,8.9,0.5,18.1,5.7,25.4c11,15.7,32.6,20.3,48.2,10.4l27.5-17.5c7.5-4.7,12.7-12.4,14.2-21.1
c1.3-7.3,0.2-14.8-3.3-21.3c2.4-3.6,4-7.6,4.7-11.8C99.4,32.2,97.3,23.1,92,15.7"/>
<path class="st0" d="M41.1,104c-8.9,2.3-18.2-1.2-23.4-8.7c-3.2-4.4-4.4-9.9-3.5-15.3c0.2-0.9,0.4-1.7,0.6-2.6l0.5-1.6l1.4,1
c3.3,2.4,6.9,4.2,10.8,5.4l1,0.3l-0.1,1c-0.1,1.4,0.3,2.9,1.1,4.1c1.6,2.3,4.4,3.4,7.1,2.7c0.6-0.2,1.2-0.4,1.7-0.7l27.4-17.5
c1.4-0.9,2.3-2.2,2.6-3.8c0.3-1.6-0.1-3.3-1-4.6c-1.6-2.3-4.4-3.3-7.1-2.6c-0.6,0.2-1.2,0.4-1.7,0.7l-10.5,6.7
c-1.7,1.1-3.6,1.9-5.6,2.4c-8.9,2.3-18.2-1.2-23.4-8.7c-3.1-4.4-4.4-9.9-3.4-15.3c0.9-5.2,4.1-9.9,8.6-12.7l27.4-17.5
c1.7-1.1,3.6-1.9,5.6-2.5c8.9-2.3,18.2,1.2,23.4,8.7c3.2,4.4,4.4,9.9,3.5,15.3c-0.2,0.9-0.4,1.7-0.7,2.6L83,42.4l-1.4-1
c-3.3-2.4-6.9-4.2-10.8-5.4l-1-0.3l0.1-1c0.1-1.4-0.3-2.9-1.1-4.1c-1.6-2.3-4.4-3.3-7.1-2.6c-0.6,0.2-1.2,0.4-1.7,0.7L32.6,46.2
C31.2,47,30.3,48.4,30,50c-0.3,1.6,0.1,3.3,1,4.6c1.6,2.3,4.4,3.3,7.1,2.6c0.6-0.2,1.2-0.4,1.7-0.7l10.5-6.7
c1.7-1.1,3.6-1.9,5.6-2.5c8.9-2.3,18.2,1.2,23.4,8.7c3.2,4.4,4.4,9.9,3.5,15.3c-0.9,5.2-4.1,9.9-8.6,12.7l-27.4,17.5
C45,102.6,43.1,103.5,41.1,104"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -1,4 +1 @@
<svg id="svelte" xmlns="http://www.w3.org/2000/svg" width="256" height="300" viewBox="0 0 256 300"> <svg height="300" viewBox="0 0 256 300" width="256" xmlns="http://www.w3.org/2000/svg"><path d="m44.41 265.87a14 14 0 0 1 -8-2.26 11.53 11.53 0 0 1 -4.66-6.18l4.86-1.78a9 9 0 0 0 3.18 3.84 8.31 8.31 0 0 0 4.81 1.42 7 7 0 0 0 4.59-1.39 4.83 4.83 0 0 0 1.71-4 4.25 4.25 0 0 0 -.47-2 5.93 5.93 0 0 0 -1.05-1.52 7 7 0 0 0 -1.84-1.22c-.83-.41-1.51-.73-2.06-.94s-1.35-.51-2.41-.87c-1.32-.46-2.31-.83-3-1.09a23.69 23.69 0 0 1 -2.61-1.32 9.63 9.63 0 0 1 -2.43-1.83 8.76 8.76 0 0 1 -1.46-2.41 8.11 8.11 0 0 1 -.57-3.32 8.29 8.29 0 0 1 3-6.45 11.79 11.79 0 0 1 8-2.61 12.16 12.16 0 0 1 7 1.89 9.11 9.11 0 0 1 3.69 5l-4.69 1.6a5.53 5.53 0 0 0 -2.31-2.56 7.77 7.77 0 0 0 -4-1 6.23 6.23 0 0 0 -3.9 1.09 3.66 3.66 0 0 0 -1.41 3.07 3.22 3.22 0 0 0 1.09 2.39 7.61 7.61 0 0 0 2.21 1.58c.8.34 2 .78 3.63 1.34l2.2.82c.48.19 1.19.49 2.11.92a14.36 14.36 0 0 1 2.14 1.17 19.05 19.05 0 0 1 1.73 1.41 7.66 7.66 0 0 1 1.51 1.8 10.77 10.77 0 0 1 .89 2.24 10.13 10.13 0 0 1 .37 2.8 9.38 9.38 0 0 1 -3.26 7.62 13 13 0 0 1 -8.59 2.75zm31.81-.6-11.91-34.73h5.56l7.89 24.21a39.48 39.48 0 0 1 1.09 4 39.48 39.48 0 0 1 1.09-4l7.79-24.21h5.51l-11.86 34.73zm27.54 0v-34.73h21.54v4.86h-16.38v9.53h10.57v4.86h-10.57v10.62h17.47v4.86zm35.78 0v-34.73h5.16v29.77h17v5zm41.58-29.77v29.77h-5.12v-29.77h-9.83v-5h24.81v5zm20.49 29.77v-34.73h21.54v4.86h-16.38v9.53h10.57v4.86h-10.57v10.62h17.47v4.86z" fill="#4a4a55"/><path d="m191.87 52.11c-16.34-23.39-48.61-30.32-71.94-15.45l-40.93 26.11a47 47 0 0 0 -21.28 31.49 49.49 49.49 0 0 0 4.88 31.74 47.16 47.16 0 0 0 -7 17.57 50.1 50.1 0 0 0 8.56 37.89c16.34 23.38 48.61 30.31 71.94 15.45l41-26.12a47 47 0 0 0 21.24-31.49 49.51 49.51 0 0 0 -4.88-31.78 47.16 47.16 0 0 0 7-17.57 50.07 50.07 0 0 0 -8.56-37.88" fill="#ff3e00"/><path d="m115.93 183.7a32.55 32.55 0 0 1 -34.93-12.95 30.11 30.11 0 0 1 -5.15-22.75 29.12 29.12 0 0 1 1-3.83l.77-2.35 2.1 1.54a52.87 52.87 0 0 0 16 8l1.52.46-.14 1.52a9.17 9.17 0 0 0 1.65 6.09 9.79 9.79 0 0 0 10.52 3.9 9 9 0 0 0 2.52-1.1l41-26.11a8.53 8.53 0 0 0 3.85-5.71 9 9 0 0 0 -1.55-6.87 9.82 9.82 0 0 0 -10.52-3.9 9.08 9.08 0 0 0 -2.51 1.1l-15.64 10a30.08 30.08 0 0 1 -8.32 3.66 32.55 32.55 0 0 1 -34.95-13 30.15 30.15 0 0 1 -5.15-22.79 28.24 28.24 0 0 1 12.77-18.93l41-26.12a30 30 0 0 1 8.33-3.65 32.54 32.54 0 0 1 34.93 13 30.11 30.11 0 0 1 5.15 22.78 29.12 29.12 0 0 1 -1 3.83l-.77 2.35-2.1-1.54a52.64 52.64 0 0 0 -16-8l-1.52-.46.14-1.52a9.2 9.2 0 0 0 -1.65-6.1 9.82 9.82 0 0 0 -10.52-3.9 9 9 0 0 0 -2.52 1.11l-41 26.11a8.49 8.49 0 0 0 -3.85 5.7 9 9 0 0 0 1.55 6.87 9.81 9.81 0 0 0 10.51 3.86 9 9 0 0 0 2.52-1.11l15.63-10a29.5 29.5 0 0 1 8.32-3.66 32.54 32.54 0 0 1 34.93 12.95 30.11 30.11 0 0 1 5.15 22.82 28.26 28.26 0 0 1 -12.77 18.94l-41 26.11a30.27 30.27 0 0 1 -8.33 3.66" fill="#fff"/></svg>
<path id="logotype" fill="#4a4a55" d="M44.41,265.87a14,14,0,0,1-8-2.26,11.53,11.53,0,0,1-4.66-6.18l4.86-1.78a9,9,0,0,0,3.18,3.84,8.31,8.31,0,0,0,4.81,1.42,7,7,0,0,0,4.59-1.39,4.83,4.83,0,0,0,1.71-4,4.25,4.25,0,0,0-.47-2A5.93,5.93,0,0,0,49.38,252a7,7,0,0,0-1.84-1.22c-.83-.41-1.51-.73-2.06-.94s-1.35-.51-2.41-.87c-1.32-.46-2.31-.83-3-1.09a23.69,23.69,0,0,1-2.61-1.32,9.63,9.63,0,0,1-2.43-1.83,8.76,8.76,0,0,1-1.46-2.41A8.11,8.11,0,0,1,33,239a8.29,8.29,0,0,1,3-6.45A11.79,11.79,0,0,1,44,229.94a12.16,12.16,0,0,1,7,1.89,9.11,9.11,0,0,1,3.69,5L50,238.43a5.53,5.53,0,0,0-2.31-2.56,7.77,7.77,0,0,0-4-1,6.23,6.23,0,0,0-3.9,1.09,3.66,3.66,0,0,0-1.41,3.07,3.22,3.22,0,0,0,1.09,2.39A7.61,7.61,0,0,0,41.68,243c.8.34,2,.78,3.63,1.34l2.2.82c.48.19,1.19.49,2.11.92a14.36,14.36,0,0,1,2.14,1.17,19.05,19.05,0,0,1,1.73,1.41A7.66,7.66,0,0,1,55,250.46a10.77,10.77,0,0,1,.89,2.24,10.13,10.13,0,0,1,.37,2.8A9.38,9.38,0,0,1,53,263.12,13,13,0,0,1,44.41,265.87Zm31.81-.6L64.31,230.54h5.56l7.89,24.21a39.48,39.48,0,0,1,1.09,4,39.48,39.48,0,0,1,1.09-4l7.79-24.21h5.51L81.38,265.27Zm27.54,0V230.54H125.3v4.86H108.92v9.53h10.57v4.86H108.92v10.62h17.47v4.86Zm35.78,0V230.54h5.16v29.77h17v5Zm41.58-29.77v29.77H176V235.5h-9.83v-5h24.81v5Zm20.49,29.77V230.54h21.54v4.86H206.77v9.53h10.57v4.86H206.77v10.62h17.47v4.86Z"/>
<path id="back" fill="#ff3e00" d="M191.87,52.11c-16.34-23.39-48.61-30.32-71.94-15.45L79,62.77A47,47,0,0,0,57.72,94.26,49.49,49.49,0,0,0,62.6,126a47.16,47.16,0,0,0-7,17.57,50.1,50.1,0,0,0,8.56,37.89c16.34,23.38,48.61,30.31,71.94,15.45l41-26.12a47,47,0,0,0,21.24-31.49,49.51,49.51,0,0,0-4.88-31.78,47.16,47.16,0,0,0,7-17.57,50.07,50.07,0,0,0-8.56-37.88"/>
<path id="front" fill="#fff" d="M115.93,183.7A32.55,32.55,0,0,1,81,170.75,30.11,30.11,0,0,1,75.85,148a29.12,29.12,0,0,1,1-3.83l.77-2.35,2.1,1.54a52.87,52.87,0,0,0,16,8l1.52.46-.14,1.52a9.17,9.17,0,0,0,1.65,6.09,9.79,9.79,0,0,0,10.52,3.9,9,9,0,0,0,2.52-1.1l41-26.11a8.53,8.53,0,0,0,3.85-5.71,9,9,0,0,0-1.55-6.87,9.82,9.82,0,0,0-10.52-3.9,9.08,9.08,0,0,0-2.51,1.1l-15.64,10a30.08,30.08,0,0,1-8.32,3.66A32.55,32.55,0,0,1,83.15,121.4,30.15,30.15,0,0,1,78,98.61,28.24,28.24,0,0,1,90.77,79.68l41-26.12a30,30,0,0,1,8.33-3.65,32.54,32.54,0,0,1,34.93,13,30.11,30.11,0,0,1,5.15,22.78,29.12,29.12,0,0,1-1,3.83l-.77,2.35-2.1-1.54a52.64,52.64,0,0,0-16-8l-1.52-.46.14-1.52a9.2,9.2,0,0,0-1.65-6.1,9.82,9.82,0,0,0-10.52-3.9,9,9,0,0,0-2.52,1.11l-41,26.11a8.49,8.49,0,0,0-3.85,5.7,9,9,0,0,0,1.55,6.87A9.81,9.81,0,0,0,111.45,114a9,9,0,0,0,2.52-1.11l15.63-10a29.5,29.5,0,0,1,8.32-3.66,32.54,32.54,0,0,1,34.93,12.95A30.11,30.11,0,0,1,178,135a28.26,28.26,0,0,1-12.77,18.94l-41,26.11a30.27,30.27,0,0,1-8.33,3.66"/></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

@ -1,20 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg enable-background="new 0 0 98.1 118" viewBox="0 0 98.1 118" xmlns="http://www.w3.org/2000/svg"><path d="m91.8 15.6c-10.9-15.7-32.6-20.3-48.2-10.4l-27.5 17.6c-7.5 4.7-12.7 12.4-14.2 21.1-1.3 7.3-.2 14.8 3.3 21.3-2.4 3.6-4 7.6-4.7 11.8-1.6 8.9.5 18.1 5.7 25.4 11 15.7 32.6 20.3 48.2 10.4l27.5-17.5c7.5-4.7 12.7-12.4 14.2-21.1 1.3-7.3.2-14.8-3.3-21.3 2.4-3.6 4-7.6 4.7-11.8 1.7-9-.4-18.2-5.7-25.5" fill="#ff3e00"/><path d="m40.9 103.9c-8.9 2.3-18.2-1.2-23.4-8.7-3.2-4.4-4.4-9.9-3.5-15.3.2-.9.4-1.7.6-2.6l.5-1.6 1.4 1c3.3 2.4 6.9 4.2 10.8 5.4l1 .3-.1 1c-.1 1.4.3 2.9 1.1 4.1 1.6 2.3 4.4 3.4 7.1 2.7.6-.2 1.2-.4 1.7-.7l27.4-17.5c1.4-.9 2.3-2.2 2.6-3.8s-.1-3.3-1-4.6c-1.6-2.3-4.4-3.3-7.1-2.6-.6.2-1.2.4-1.7.7l-10.5 6.7c-1.7 1.1-3.6 1.9-5.6 2.4-8.9 2.3-18.2-1.2-23.4-8.7-3.1-4.4-4.4-9.9-3.4-15.3.9-5.2 4.1-9.9 8.6-12.7l27.5-17.5c1.7-1.1 3.6-1.9 5.6-2.5 8.9-2.3 18.2 1.2 23.4 8.7 3.2 4.4 4.4 9.9 3.5 15.3-.2.9-.4 1.7-.7 2.6l-.5 1.6-1.4-1c-3.3-2.4-6.9-4.2-10.8-5.4l-1-.3.1-1c.1-1.4-.3-2.9-1.1-4.1-1.6-2.3-4.4-3.3-7.1-2.6-.6.2-1.2.4-1.7.7l-27.4 17.5c-1.4.9-2.3 2.2-2.6 3.8s.1 3.3 1 4.6c1.6 2.3 4.4 3.3 7.1 2.6.6-.2 1.2-.4 1.7-.7l10.5-6.7c1.7-1.1 3.6-1.9 5.6-2.5 8.9-2.3 18.2 1.2 23.4 8.7 3.2 4.4 4.4 9.9 3.5 15.3-.9 5.2-4.1 9.9-8.6 12.7l-27.5 17.5c-1.7 1.1-3.6 1.9-5.6 2.5" fill="#fff"/></svg>
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 98.1 118" style="enable-background:new 0 0 98.1 118;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FF3E00;}
.st1{fill:#FFFFFF;}
</style>
<path class="st0" d="M91.8,15.6C80.9-0.1,59.2-4.7,43.6,5.2L16.1,22.8C8.6,27.5,3.4,35.2,1.9,43.9c-1.3,7.3-0.2,14.8,3.3,21.3
c-2.4,3.6-4,7.6-4.7,11.8c-1.6,8.9,0.5,18.1,5.7,25.4c11,15.7,32.6,20.3,48.2,10.4l27.5-17.5c7.5-4.7,12.7-12.4,14.2-21.1
c1.3-7.3,0.2-14.8-3.3-21.3c2.4-3.6,4-7.6,4.7-11.8C99.2,32.1,97.1,22.9,91.8,15.6"/>
<path class="st1" d="M40.9,103.9c-8.9,2.3-18.2-1.2-23.4-8.7c-3.2-4.4-4.4-9.9-3.5-15.3c0.2-0.9,0.4-1.7,0.6-2.6l0.5-1.6l1.4,1
c3.3,2.4,6.9,4.2,10.8,5.4l1,0.3l-0.1,1c-0.1,1.4,0.3,2.9,1.1,4.1c1.6,2.3,4.4,3.4,7.1,2.7c0.6-0.2,1.2-0.4,1.7-0.7L65.5,72
c1.4-0.9,2.3-2.2,2.6-3.8c0.3-1.6-0.1-3.3-1-4.6c-1.6-2.3-4.4-3.3-7.1-2.6c-0.6,0.2-1.2,0.4-1.7,0.7l-10.5,6.7
c-1.7,1.1-3.6,1.9-5.6,2.4c-8.9,2.3-18.2-1.2-23.4-8.7c-3.1-4.4-4.4-9.9-3.4-15.3c0.9-5.2,4.1-9.9,8.6-12.7l27.5-17.5
c1.7-1.1,3.6-1.9,5.6-2.5c8.9-2.3,18.2,1.2,23.4,8.7c3.2,4.4,4.4,9.9,3.5,15.3c-0.2,0.9-0.4,1.7-0.7,2.6l-0.5,1.6l-1.4-1
c-3.3-2.4-6.9-4.2-10.8-5.4l-1-0.3l0.1-1c0.1-1.4-0.3-2.9-1.1-4.1c-1.6-2.3-4.4-3.3-7.1-2.6c-0.6,0.2-1.2,0.4-1.7,0.7L32.4,46.1
c-1.4,0.9-2.3,2.2-2.6,3.8s0.1,3.3,1,4.6c1.6,2.3,4.4,3.3,7.1,2.6c0.6-0.2,1.2-0.4,1.7-0.7l10.5-6.7c1.7-1.1,3.6-1.9,5.6-2.5
c8.9-2.3,18.2,1.2,23.4,8.7c3.2,4.4,4.4,9.9,3.5,15.3c-0.9,5.2-4.1,9.9-8.6,12.7l-27.5,17.5C44.8,102.5,42.9,103.3,40.9,103.9"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m20 8-8 5-8-5v-2l8 5 8-5m0-2h-16c-1.11 0-2 .89-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-12c0-1.11-.9-2-2-2z" fill="#ff3e00"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#ff3e00" d="M20,8L12,13L4,8V6L12,11L20,6M20,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V6C22,4.89 21.1,4 20,4Z" />
</svg>

Before

Width:  |  Height:  |  Size: 280 B

After

Width:  |  Height:  |  Size: 221 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m19 20h-15c-1.11 0-2-.9-2-2v-12c0-1.11.89-2 2-2h6l2 2h7a2 2 0 0 1 2 2h-17v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ff3e00"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#ff3e00" d="M19,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10L12,6H19A2,2 0 0,1 21,8H21L4,8V18L6.14,10H23.21L20.93,18.5C20.7,19.37 19.92,20 19,20Z" />
</svg>

Before

Width:  |  Height:  |  Size: 303 B

After

Width:  |  Height:  |  Size: 242 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m10 4h-6c-1.11 0-2 .89-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-10c0-1.11-.9-2-2-2h-8z" fill="#ff3e00"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#ff3e00" d="M10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6H12L10,4Z" />
</svg>

Before

Width:  |  Height:  |  Size: 260 B

After

Width:  |  Height:  |  Size: 200 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m11 8h2v8h-2zm-3.33 0h-3.34c-.8 0-1.33.67-1.33 1.33v5.34c0 .66.53 1.33 1.33 1.33h3.34c.8 0 1.33-.67 1.33-1.33v-2.67h-2v2h-2v-4h4v-.67c0-.66-.53-1.33-1.33-1.33m13.33 2v-2h-6v8h2v-2h2.5v-2h-2.5v-2z" fill="#ff3e00"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#ff3e00" d="M11,8H13V16H11V8M7.67,8H4.33C3.53,8 3,8.67 3,9.33V14.67C3,15.33 3.53,16 4.33,16H7.67C8.47,16 9,15.33 9,14.67V12H7V14H5V10H9V9.33C9,8.67 8.47,8 7.67,8M21,10V8H15V16H17V14H19.5V12H17V10H21Z" />
</svg>

Before

Width:  |  Height:  |  Size: 354 B

After

Width:  |  Height:  |  Size: 311 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m12 11.5a2.5 2.5 0 0 1 -2.5-2.5 2.5 2.5 0 0 1 2.5-2.5 2.5 2.5 0 0 1 2.5 2.5 2.5 2.5 0 0 1 -2.5 2.5m0-9.5a7 7 0 0 0 -7 7c0 5.25 7 13 7 13s7-7.75 7-13a7 7 0 0 0 -7-7z" fill="#ff3e00"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#ff3e00" d="M12,11.5A2.5,2.5 0 0,1 9.5,9A2.5,2.5 0 0,1 12,6.5A2.5,2.5 0 0,1 14.5,9A2.5,2.5 0 0,1 12,11.5M12,2A7,7 0 0,0 5,9C5,14.25 12,22 12,22C12,22 19,14.25 19,9A7,7 0 0,0 12,2Z" />
</svg>

Before

Width:  |  Height:  |  Size: 334 B

After

Width:  |  Height:  |  Size: 280 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m2 16v-8h2l3 3 3-3h2v8h-2v-5.17l-3 3-3-3v5.17zm14-8h3v4h2.5l-4 4.5-4-4.5h2.5z" fill="#ff3e00"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#ff3e00" d="M2,16V8H4L7,11L10,8H12V16H10V10.83L7,13.83L4,10.83V16H2M16,8H19V12H21.5L17.5,16.5L13.5,12H16V8Z" />
</svg>

Before

Width:  |  Height:  |  Size: 262 B

After

Width:  |  Height:  |  Size: 193 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?> <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m14 17h-7v-2h7m3-2h-10v-2h10m0-2h-10v-2h10m2-4h-14c-1.11 0-2 .89-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-14c0-1.11-.9-2-2-2z" fill="#ff3e00"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#ff3e00" d="M14,17H7V15H14M17,13H7V11H17M17,9H7V7H17M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3Z" />
</svg>

Before

Width:  |  Height:  |  Size: 292 B

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

After

Width:  |  Height:  |  Size: 108 KiB

@ -28,6 +28,7 @@ import { Node, ImportDeclaration, Identifier, Program, ExpressionStatement, Assi
import add_to_set from './utils/add_to_set'; import add_to_set from './utils/add_to_set';
import check_graph_for_cycles from './utils/check_graph_for_cycles'; import check_graph_for_cycles from './utils/check_graph_for_cycles';
import { print, x, b } from 'code-red'; import { print, x, b } from 'code-red';
import { is_reserved_keyword } from './utils/reserved_keywords';
interface ComponentOptions { interface ComponentOptions {
namespace?: string; namespace?: string;
@ -185,7 +186,7 @@ export default class Component {
if (variable) { if (variable) {
variable.referenced = true; variable.referenced = true;
} else if (name === '$$props') { } else if (is_reserved_keyword(name)) {
this.add_var({ this.add_var({
name, name,
injected: true, injected: true,
@ -204,7 +205,7 @@ export default class Component {
const variable = this.var_lookup.get(subscribable_name); const variable = this.var_lookup.get(subscribable_name);
if (variable) { if (variable) {
variable.referenced = true; variable.referenced = true;
variable.subscribable = true; variable.subscribable = true;
} }
} else { } else {
@ -239,7 +240,7 @@ export default class Component {
const program: any = { type: 'Program', body: result.js }; const program: any = { type: 'Program', body: result.js };
walk(program, { walk(program, {
enter: (node, parent, key) => { enter: (node: Node, parent: Node, key) => {
if (node.type === 'Identifier') { if (node.type === 'Identifier') {
if (node.name[0] === '@') { if (node.name[0] === '@') {
if (node.name[1] === '_') { if (node.name[1] === '_') {
@ -526,7 +527,7 @@ export default class Component {
if (!script) return; if (!script) return;
walk(script.content, { walk(script.content, {
enter(node) { enter(node: Node) {
if (node.type === 'LabeledStatement' && node.label.name === '$') { if (node.type === 'LabeledStatement' && node.label.name === '$') {
component.warn(node as any, { component.warn(node as any, {
code: 'module-script-reactive-declaration', code: 'module-script-reactive-declaration',
@ -631,7 +632,6 @@ export default class Component {
this.add_var({ this.add_var({
name, name,
initialised: instance_scope.initialised_declarations.has(name), initialised: instance_scope.initialised_declarations.has(name),
hoistable: /^Import/.test(node.type),
writable writable
}); });
@ -649,7 +649,7 @@ export default class Component {
reassigned: true, reassigned: true,
initialised: true, initialised: true,
}); });
} else if (name === '$$props') { } else if (is_reserved_keyword(name)) {
this.add_var({ this.add_var({
name, name,
injected: true, injected: true,
@ -714,8 +714,14 @@ export default class Component {
}; };
let scope_updated = false; let scope_updated = false;
let generator_count = 0;
walk(content, { walk(content, {
enter(node, parent, prop, index) { enter(node: Node, parent, prop, index) {
if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) {
generator_count++;
}
if (map.has(node)) { if (map.has(node)) {
scope = map.get(node); scope = map.get(node);
} }
@ -741,9 +747,13 @@ export default class Component {
component.warn_on_undefined_store_value_references(node, parent, scope); component.warn_on_undefined_store_value_references(node, parent, scope);
}, },
leave(node) { leave(node: Node) {
if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) {
generator_count--;
}
// do it on leave, to prevent infinite loop // do it on leave, to prevent infinite loop
if (component.compile_options.dev && component.compile_options.loopGuardTimeout > 0) { if (component.compile_options.dev && component.compile_options.loopGuardTimeout > 0 && generator_count <= 0) {
const to_replace_for_loop_protect = component.loop_protect(node, scope, component.compile_options.loopGuardTimeout); const to_replace_for_loop_protect = component.loop_protect(node, scope, component.compile_options.loopGuardTimeout);
if (to_replace_for_loop_protect) { if (to_replace_for_loop_protect) {
this.replace(to_replace_for_loop_protect); this.replace(to_replace_for_loop_protect);
@ -780,12 +790,12 @@ export default class Component {
const component = this; const component = this;
const { content } = script; const { content } = script;
const { instance_scope, instance_scope_map: map } = this; const { instance_scope, module_scope, instance_scope_map: map } = this;
let scope = instance_scope; let scope = instance_scope;
walk(content, { walk(content, {
enter(node, parent) { enter(node: Node, parent: Node) {
if (map.has(node)) { if (map.has(node)) {
scope = map.get(node); scope = map.get(node);
} }
@ -797,7 +807,12 @@ export default class Component {
const deep = assignee.type === 'MemberExpression'; const deep = assignee.type === 'MemberExpression';
names.forEach(name => { names.forEach(name => {
if (scope.find_owner(name) === instance_scope) { const scope_owner = scope.find_owner(name);
if (
scope_owner !== null
? scope_owner === instance_scope
: module_scope && module_scope.has(name)
) {
const variable = component.var_lookup.get(name); const variable = component.var_lookup.get(name);
variable[deep ? 'mutated' : 'reassigned'] = true; variable[deep ? 'mutated' : 'reassigned'] = true;
} }
@ -813,7 +828,7 @@ export default class Component {
} }
}, },
leave(node) { leave(node: Node) {
if (map.has(node)) { if (map.has(node)) {
scope = scope.parent; scope = scope.parent;
} }
@ -881,7 +896,7 @@ export default class Component {
let scope = instance_scope; let scope = instance_scope;
walk(this.ast.instance.content, { walk(this.ast.instance.content, {
enter(node, parent, key, index) { enter(node: Node, parent, key, index) {
if (/Function/.test(node.type)) { if (/Function/.test(node.type)) {
return this.skip(); return this.skip();
} }
@ -958,7 +973,7 @@ export default class Component {
} }
}, },
leave(node, parent, _key, index) { leave(node: Node, parent, _key, index) {
if (map.has(node)) { if (map.has(node)) {
scope = scope.parent; scope = scope.parent;
} }
@ -980,6 +995,7 @@ export default class Component {
hoistable_nodes, hoistable_nodes,
var_lookup, var_lookup,
injected_reactive_declaration_vars, injected_reactive_declaration_vars,
imports,
} = this; } = this;
const top_level_function_declarations = new Map(); const top_level_function_declarations = new Map();
@ -1059,7 +1075,7 @@ export default class Component {
walking.add(fn_declaration); walking.add(fn_declaration);
walk(fn_declaration, { walk(fn_declaration, {
enter(node, parent) { enter(node: Node, parent) {
if (!hoistable) return this.skip(); if (!hoistable) return this.skip();
if (map.has(node)) { if (map.has(node)) {
@ -1107,7 +1123,7 @@ export default class Component {
} }
}, },
leave(node) { leave(node: Node) {
if (map.has(node)) { if (map.has(node)) {
scope = scope.parent; scope = scope.parent;
} }
@ -1131,6 +1147,14 @@ export default class Component {
this.fully_hoisted.push(node); this.fully_hoisted.push(node);
} }
} }
for (const { specifiers } of imports) {
for (const specifier of specifiers) {
const variable = var_lookup.get(specifier.local.name);
if (!variable.mutated) variable.hoistable = true;
}
}
} }
extract_reactive_declarations() { extract_reactive_declarations() {
@ -1150,7 +1174,7 @@ export default class Component {
const map = this.instance_scope_map; const map = this.instance_scope_map;
walk(node.body, { walk(node.body, {
enter(node, parent) { enter(node: Node, parent) {
if (map.has(node)) { if (map.has(node)) {
scope = map.get(node); scope = map.get(node);
} }
@ -1190,7 +1214,7 @@ export default class Component {
} }
}, },
leave(node) { leave(node: Node) {
if (map.has(node)) { if (map.has(node)) {
scope = scope.parent; scope = scope.parent;
} }
@ -1210,7 +1234,6 @@ export default class Component {
}); });
const lookup = new Map(); const lookup = new Map();
let seen;
unsorted_reactive_declarations.forEach(declaration => { unsorted_reactive_declarations.forEach(declaration => {
declaration.assignees.forEach(name => { declaration.assignees.forEach(name => {
@ -1245,33 +1268,24 @@ export default class Component {
} }
const add_declaration = declaration => { const add_declaration = declaration => {
if (this.reactive_declarations.indexOf(declaration) !== -1) { if (this.reactive_declarations.includes(declaration)) return;
return;
}
seen.add(declaration);
declaration.dependencies.forEach(name => { declaration.dependencies.forEach(name => {
if (declaration.assignees.has(name)) return; if (declaration.assignees.has(name)) return;
const earlier_declarations = lookup.get(name); const earlier_declarations = lookup.get(name);
if (earlier_declarations) if (earlier_declarations)
earlier_declarations.forEach(declaration => { earlier_declarations.forEach(add_declaration);
add_declaration(declaration);
});
}); });
this.reactive_declarations.push(declaration); this.reactive_declarations.push(declaration);
}; };
unsorted_reactive_declarations.forEach(declaration => { unsorted_reactive_declarations.forEach(add_declaration);
seen = new Set();
add_declaration(declaration);
});
} }
warn_if_undefined(name: string, node, template_scope: TemplateScope) { warn_if_undefined(name: string, node, template_scope: TemplateScope) {
if (name[0] === '$') { if (name[0] === '$') {
if (name === '$' || name[1] === '$' && name !== '$$props') { if (name === '$' || name[1] === '$' && !is_reserved_keyword(name)) {
this.error(node, { this.error(node, {
code: 'illegal-global', code: 'illegal-global',
message: `${name} is an illegal variable name` message: `${name} is an illegal variable name`
@ -1280,7 +1294,7 @@ export default class Component {
this.has_reactive_assignments = true; // TODO does this belong here? this.has_reactive_assignments = true; // TODO does this belong here?
if (name === '$$props') return; if (is_reserved_keyword(name)) return;
name = name.slice(1); name = name.slice(1);
} }
@ -1450,4 +1464,4 @@ function get_relative_path(from: string, to: string) {
} }
return from_parts.concat(to_parts).join('/'); return from_parts.concat(to_parts).join('/');
} }

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

Loading…
Cancel
Save