diff --git a/.eslintrc.js b/.eslintrc.js index 2c7f2ed1b4..2023207f74 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -22,14 +22,7 @@ module.exports = { 'arrow-spacing': 2, 'no-inner-declarations': 0, 'require-atomic-updates': 'off', - '@typescript-eslint/indent': [ - 'error', - 'tab', - { - SwitchCase: 1, - ignoredNodes: ['TemplateLiteral'] - } - ], + '@typescript-eslint/indent': 'off', '@typescript-eslint/camelcase': 'off', '@typescript-eslint/no-use-before-define': 'off', '@typescript-eslint/array-type': ['error', 'array-simple'], diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..2488902b24 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,25 @@ +name: CI +on: [push, pull_request] +jobs: + Tests: + runs-on: ${{ matrix.os }} + strategy: + matrix: + node-version: [8, 10, 12] + os: [ubuntu-latest, windows-latest, macOS-latest] + steps: + - run: git config --global core.autocrlf false + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: npm install + - run: npm test + env: + CI: true + Lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + - run: 'npm i && npm run lint' diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a4603a26e2..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -language: node_js -node_js: - - "8" - - "10" - - "12" -env: - global: - - BUILD_TIMEOUT=20000 - -addons: - apt: - packages: - - xvfb - -install: - - export DISPLAY=':99.0' - - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & - - npm ci || npm install - -after_success: npm run codecov diff --git a/CHANGELOG.md b/CHANGELOG.md index 5767a556e4..566fde5005 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,98 @@ # Svelte changelog +## 3.14.1 + +* Deconflict block method names with other variables ([#3900](https://github.com/sveltejs/svelte/issues/3900)) +* Fix entity encoding issue in text nodes with constant expressions ([#3911](https://github.com/sveltejs/svelte/issues/3911)) +* Make code for unknown prop warnings compatible with older js engines ([#3914](https://github.com/sveltejs/svelte/issues/3914)) + +## 3.14.0 + +* Add `loopGuardTimeout` option that augments `for`/`while` loops to prevent infinite loops, primarily for use in the REPL ([#3887](https://github.com/sveltejs/svelte/pull/3887)) +* Keep component bindings in sync when changed in reactive statements ([#3382](https://github.com/sveltejs/svelte/issues/3382)) +* Update attributes before bindings ([#3857](https://github.com/sveltejs/svelte/issues/3857)) +* Prevent variable naming conflict ([#3899](https://github.com/sveltejs/svelte/issues/3899)) + + +## 3.13.0 + +* New structured code generation, which eliminates a number of edge cases and obscure bugs ([#3539](https://github.com/sveltejs/svelte/pull/3539)) + +Also: + +* Fix `{#each}` context not shadowing outer scope when using `bind:` ([#1565](https://github.com/sveltejs/svelte/issues/1565)) +* Fix edge cases in matching selectors against elements ([#1710](https://github.com/sveltejs/svelte/issues/1710)) +* Fix several bugs related to interaction of `{...spread}` attributes with other features ([#2721](https://github.com/sveltejs/svelte/issues/2721), [#2916](https://github.com/sveltejs/svelte/issues/2916), [#3421](https://github.com/sveltejs/svelte/issues/3421), [#3681](https://github.com/sveltejs/svelte/issues/3681), [#3764](https://github.com/sveltejs/svelte/issues/3764), [#3790](https://github.com/sveltejs/svelte/issues/3790)) +* Allow exiting a reactive block early with `break $` ([#2828](https://github.com/sveltejs/svelte/issues/2828)) +* Fix binding to props that have been renamed with `export { ... as ... }` ([#3508](https://github.com/sveltejs/svelte/issues/3508)) +* Fix application of style scoping class in cases of ambiguity ([#3544](https://github.com/sveltejs/svelte/issues/3544)) +* Check attributes have changed before setting them to avoid image flicker ([#3579](https://github.com/sveltejs/svelte/pull/3579)) +* Fix generating malformed code for `{@debug}` tags with no dependencies ([#3588](https://github.com/sveltejs/svelte/issues/3588)) +* Fix generated code in specific case involving compound ifs and child components ([#3595](https://github.com/sveltejs/svelte/issues/3595)) +* Fix `bind:this` binding to a store ([#3591](https://github.com/sveltejs/svelte/issues/3591)) +* Use safer `HTMLElement` check before extending class ([#3608](https://github.com/sveltejs/svelte/issues/3608)) +* Add `location` as a known global ([#3619](https://github.com/sveltejs/svelte/pull/3619)) +* Support `{#await}` with `{:catch}` but no `{:then}` ([#3623](https://github.com/sveltejs/svelte/issues/3623)) +* Clean up dead code emitted for ``s ([#3631](https://github.com/sveltejs/svelte/issues/3631)) +* Fix tracking of dependencies of compound assignments in reactive statements ([#3634](https://github.com/sveltejs/svelte/issues/3634)) +* Flush changes in newly attached block when using `{#await}` ([#3660](https://github.com/sveltejs/svelte/issues/3660)) +* Throw exception immediately when calling `createEventDispatcher()` after component instantiation ([#3667](https://github.com/sveltejs/svelte/pull/3667)) +* Fix globals shadowing contextual template scope ([#3674](https://github.com/sveltejs/svelte/issues/3674)) +* Fix `` bindings to stores ([#3832](https://github.com/sveltejs/svelte/issues/3832)) +* Deconflict generated var names with builtins ([#3724](https://github.com/sveltejs/svelte/issues/3724)) +* Allow spring/tweened values to be initially undefined ([#3761](https://github.com/sveltejs/svelte/issues/3761)) +* Warn if using `` without `customElement: true` option ([#3782](https://github.com/sveltejs/svelte/pull/3782)) +* Add `Event` to list of known globals ([#3810](https://github.com/sveltejs/svelte/pull/3810)) +* Throw helpful error on empty CSS declaration ([#3801](https://github.com/sveltejs/svelte/issues/3801)) +* Support `easing` param on `fade` transition ([#3823](https://github.com/sveltejs/svelte/pull/3823)) +* Generate valid names from filenames with unicode characters ([#3845](https://github.com/sveltejs/svelte/issues/3845)) +* Don't generate any code for markup-less components ([#2200](https://github.com/sveltejs/svelte/issues/2200)) +* Deconflict with internal name `block` ([#3854](https://github.com/sveltejs/svelte/issues/3854)) +* Set attributes before bindings, to prevent erroneous assignments to `input.files` ([#3828](https://github.com/sveltejs/svelte/issues/3828)) +* Smarter unused CSS detection ([#3825](https://github.com/sveltejs/svelte/pull/3825)) +* Allow dynamic event handlers ([#3040](https://github.com/sveltejs/svelte/issues/3040)) +* Prevent erroneous `"undefined"` class name ([#3876](https://github.com/sveltejs/svelte/pull/3876)) +* Prevent resetting of `src` attribute unless changed ([#3579](https://github.com/sveltejs/svelte/pull/3579)) +* Prevent hydration of void element 'children' ([#3882](https://github.com/sveltejs/svelte/issues/3882)) +* Hoist globals even if mentioned in ` ``` +--- + +If the initial value is `undefined` or `null`, the first value change will take effect immediately, just as with `tweened` values (see above). + +```js +const size = spring(); +$: $size = big ? 100 : 10; +``` + ### `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). @@ -532,6 +554,42 @@ You can see the `fade` transition in action in the [transition tutorial](tutoria {/if} ``` +#### `blur` + +```sv +transition:blur={params} +``` +```sv +in:blur={params} +``` +```sv +out:blur={params} +``` + +--- + +Animates a `blur` filter alongside an element's opacity. + +`blur` accepts the following parameters: + +* `delay` (`number`, default 0) — milliseconds before starting +* `duration` (`number`, default 400) — milliseconds the transition lasts +* `easing` (`function`, default `cubicInOut`) — an [easing function](docs#svelte_easing) +* `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 + +```html + + +{#if condition} +
+ fades in and out +
+{/if} +``` + #### `fly` ```sv @@ -660,7 +718,7 @@ out:draw={params} Animates the stroke of an SVG element, like a snake in a tube. `in` transitions begin with the path invisible and draw the path to the screen over time. `out` transitions start in a visible state and gradually erase the path. `draw` only works with elements that have a `getTotalLength` method, like `` and ``. -`scale` accepts the following parameters: +`draw` accepts the following parameters: * `delay` (`number`, default 0) — milliseconds before starting * `speed` (`number`, default undefined) - the speed of the animation, see below. @@ -909,7 +967,7 @@ app.count += 1; --- -Svelte components can also be compiled to custom elements (aka web components) using the `customElements: true` compiler option. You should specify a tag name for the component using the `` [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 `` [element](docs#svelte_options). ```html @@ -983,8 +1041,12 @@ Unlike client-side components, server-side components don't have a lifespan afte A server-side component exposes a `render` method that can be called with optional props. It returns an object with `head`, `html`, and `css` properties, where `head` contains the contents of any `` elements encountered. +You can import a Svelte component directly into Node using [`svelte/register`](docs#svelte_register). + ```js -const App = require('./App.svelte'); +require('svelte/register'); + +const App = require('./App.svelte').default; const { head, html, css } = App.render({ answer: 42 diff --git a/site/content/docs/04-compile-time.md b/site/content/docs/04-compile-time.md index f47fe564af..407b1dfc13 100644 --- a/site/content/docs/04-compile-time.md +++ b/site/content/docs/04-compile-time.md @@ -53,6 +53,7 @@ The following options can be passed to the compiler. None are required: | `tag` | string | null | `accessors` | boolean | `false` | `css` | boolean | `true` +| `loopGuardTimeout` | number | 0 | `preserveComments` | boolean | `false` | `preserveWhitespace` | boolean | `false` | `outputFilename` | string | `null` @@ -73,6 +74,7 @@ The following options can be passed to the compiler. None are required: | `customElement` | `false` | If `true`, tells the compiler to generate a custom element constructor instead of a regular Svelte component. | `tag` | `null` | A `string` that tells Svelte what tag name to register the custom element with. It must be a lowercase alphanumeric string with at least one hyphen, e.g. `"my-element"`. | `css` | `true` | If `true`, styles will be included in the JavaScript class and injected at runtime. It's recommended that you set this to `false` and use the CSS that is statically generated, as it will result in smaller JavaScript bundles and better performance. +| `loopGuardTimeout` | 0 | A `number` that tells Svelte to break the loop if it blocks the thread for more than `loopGuardTimeout` ms. This is useful to prevent infinite loops. **Only available when `dev: true`** | `preserveComments` | `false` | If `true`, your HTML comments will be preserved during server-side rendering. By default, they are stripped out. | `preserveWhitespace` | `false` | If `true`, whitespace inside and between elements is kept as you typed it, rather than optimised by Svelte. | `outputFilename` | `null` | A `string` used for your JavaScript sourcemap. @@ -315,7 +317,7 @@ walk(ast: Node, { --- -The `walk` function provides a way to walk to abstract syntax trees generated by the parser, using the compiler's own built-in instance of [estree-walker](https://github.com/Rich-Harris/estree-walker). +The `walk` function provides a way to walk the abstract syntax trees generated by the parser, using the compiler's own built-in instance of [estree-walker](https://github.com/Rich-Harris/estree-walker). The walker takes an abstract syntax tree to walk and an object with two optional methods: `enter` and `leave`. For each node, `enter` is called (if present). Then, unless `this.skip()` is called during `enter`, each of the children are traversed, and then `leave` is called on the node. diff --git a/site/content/examples/05-bindings/08-media-elements/App.svelte b/site/content/examples/05-bindings/08-media-elements/App.svelte index 2cf819fca0..469e9e12eb 100644 --- a/site/content/examples/05-bindings/08-media-elements/App.svelte +++ b/site/content/examples/05-bindings/08-media-elements/App.svelte @@ -14,7 +14,7 @@ showControlsTimeout = setTimeout(() => showControls = false, 2500); showControls = true; - if (e.which !== 1) return; // mouse not down + if (!(e.buttons & 1)) return; // mouse not down if (!duration) return; // video not loaded yet const { left, right } = this.getBoundingClientRect(); @@ -109,8 +109,8 @@
- \ No newline at end of file + diff --git a/site/content/examples/05-bindings/10-bind-this/App.svelte b/site/content/examples/05-bindings/10-bind-this/App.svelte index b64b6c0cc3..8e4b3c5bef 100644 --- a/site/content/examples/05-bindings/10-bind-this/App.svelte +++ b/site/content/examples/05-bindings/10-bind-this/App.svelte @@ -2,9 +2,6 @@ import { onMount } from 'svelte'; let canvas; - let running = false; - - const r = Math.random(); onMount(() => { const ctx = canvas.getContext('2d'); @@ -46,8 +43,8 @@ width: 100%; height: 100%; background-color: #666; - -webkit-mask: url(logo-mask.svg) 50% 50% no-repeat; - mask: url(logo-mask.svg) 50% 50% no-repeat; + -webkit-mask: url(svelte-logo-mask.svg) 50% 50% no-repeat; + mask: url(svelte-logo-mask.svg) 50% 50% no-repeat; } diff --git a/site/content/examples/09-transitions/06-deferred-transitions/App.svelte b/site/content/examples/09-transitions/06-deferred-transitions/App.svelte index ab4c04a18e..f8c74081fe 100644 --- a/site/content/examples/09-transitions/06-deferred-transitions/App.svelte +++ b/site/content/examples/09-transitions/06-deferred-transitions/App.svelte @@ -10,7 +10,7 @@ let selected = null; let loading = null; - const ASSETS = `https://svelte-assets.surge.sh/crossfade`; + const ASSETS = `https://sveltejs.github.io/assets/crossfade`; const load = image => { const timeout = setTimeout(() => loading = image, 100); diff --git a/site/content/examples/10-animations/00-animate/App.svelte b/site/content/examples/10-animations/00-animate/App.svelte index faba1dd062..279821491b 100644 --- a/site/content/examples/10-animations/00-animate/App.svelte +++ b/site/content/examples/10-animations/00-animate/App.svelte @@ -109,7 +109,11 @@
- +

todo

diff --git a/site/content/examples/12-svg/05-svg-transitions/App.svelte b/site/content/examples/12-svg/05-svg-transitions/App.svelte index 6059b3645f..6e1e636b20 100644 --- a/site/content/examples/12-svg/05-svg-transitions/App.svelte +++ b/site/content/examples/12-svg/05-svg-transitions/App.svelte @@ -33,7 +33,7 @@ font-family: 'Overpass'; letter-spacing: 0.12em; color: #676778; - font-weight: 100; + font-weight: 400; } .centered span { @@ -71,4 +71,4 @@ toggle me - \ No newline at end of file + diff --git a/site/content/examples/15-composition/04-modal/Modal.svelte b/site/content/examples/15-composition/04-modal/Modal.svelte index 5ffa5989a4..4a5329b05b 100644 --- a/site/content/examples/15-composition/04-modal/Modal.svelte +++ b/site/content/examples/15-composition/04-modal/Modal.svelte @@ -1,9 +1,56 @@ + + + + + + - - - - diff --git a/site/content/examples/18-module-context/01-module-exports/App.svelte b/site/content/examples/18-module-context/01-module-exports/App.svelte index cd5ab44b21..1d5d94b5d1 100644 --- a/site/content/examples/18-module-context/01-module-exports/App.svelte +++ b/site/content/examples/18-module-context/01-module-exports/App.svelte @@ -8,7 +8,7 @@ let people = [ - { - first: 'Hans', - last: 'Emil' - }, - { - first: 'Max', - last: 'Mustermann' - }, - { - first: 'Roman', - last: 'Tisch' - } + { first: 'Hans', last: 'Emil' }, + { first: 'Max', last: 'Mustermann' }, + { first: 'Roman', last: 'Tisch' } ]; let prefix = ''; @@ -39,7 +30,9 @@ } function update() { - people[i] = { first, last }; + selected.first = first; + selected.last = last; + people = people; } function remove() { diff --git a/site/content/tutorial/02-reactivity/04-updating-arrays-and-objects/text.md b/site/content/tutorial/02-reactivity/04-updating-arrays-and-objects/text.md index b70b09f728..82e4c91d35 100644 --- a/site/content/tutorial/02-reactivity/04-updating-arrays-and-objects/text.md +++ b/site/content/tutorial/02-reactivity/04-updating-arrays-and-objects/text.md @@ -30,3 +30,12 @@ function addNumber() { numbers[numbers.length] = numbers.length + 1; } ``` + +A simple rule of thumb: the name of the updated variable must appear on the left hand side of the assignment. For example this... + +```js +const foo = obj.foo; +foo.bar = 'baz'; +``` + +...won't update references to `obj.foo.bar`, unless you follow it up with `obj = obj`. \ No newline at end of file diff --git a/site/content/tutorial/04-logic/05-keyed-each-blocks/text.md b/site/content/tutorial/04-logic/05-keyed-each-blocks/text.md index 3c204d1413..4affb89cd6 100644 --- a/site/content/tutorial/04-logic/05-keyed-each-blocks/text.md +++ b/site/content/tutorial/04-logic/05-keyed-each-blocks/text.md @@ -4,13 +4,13 @@ title: Keyed each blocks By default, when you modify the value of an `each` block, it will add and remove items at the *end* of the block, and update any values that have changed. That might not be what you want. -It's easier to show why than to explain. Click the 'Remove first thing' button a few times, and notice that it's removing `` components from the end and updating the `value` for those that remain. Instead, we'd like to remove the first `` component and leave the rest unaffected. +It's easier to show why than to explain. Click the 'Remove first thing' button a few times, and notice that it's removing `` components from the end and updating the `color` for those that remain. Instead, we'd like to remove the first `` component and leave the rest unaffected. To do that, we specify a unique identifier for the `each` block: ```html {#each things as thing (thing.id)} - + {/each} ``` diff --git a/site/content/tutorial/06-bindings/10-media-elements/app-a/App.svelte b/site/content/tutorial/06-bindings/10-media-elements/app-a/App.svelte index ec01cd5476..40276110f4 100644 --- a/site/content/tutorial/06-bindings/10-media-elements/app-a/App.svelte +++ b/site/content/tutorial/06-bindings/10-media-elements/app-a/App.svelte @@ -14,7 +14,7 @@ showControlsTimeout = setTimeout(() => showControls = false, 2500); showControls = true; - if (e.which !== 1) return; // mouse not down + if (!(e.buttons & 1)) return; // mouse not down if (!duration) return; // video not loaded yet const { left, right } = this.getBoundingClientRect(); @@ -109,8 +109,8 @@
@@ -124,4 +124,4 @@ {format(duration)}
-
\ No newline at end of file + diff --git a/site/content/tutorial/06-bindings/10-media-elements/app-b/App.svelte b/site/content/tutorial/06-bindings/10-media-elements/app-b/App.svelte index c304581a77..8712d6718b 100644 --- a/site/content/tutorial/06-bindings/10-media-elements/app-b/App.svelte +++ b/site/content/tutorial/06-bindings/10-media-elements/app-b/App.svelte @@ -14,7 +14,7 @@ showControlsTimeout = setTimeout(() => showControls = false, 2500); showControls = true; - if (e.which !== 1) return; // mouse not down + if (!(e.buttons & 1)) return; // mouse not down if (!duration) return; // video not loaded yet const { left, right } = this.getBoundingClientRect(); @@ -109,8 +109,8 @@