Merge branch 'master' into pr/4493

pull/4493/head
Conduitry 6 years ago
commit 76bcb602db

@ -2,8 +2,23 @@
## Unreleased
* 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 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))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

8
package-lock.json generated

@ -1,6 +1,6 @@
{
"name": "svelte",
"version": "3.19.1",
"version": "3.19.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -280,9 +280,9 @@
"dev": true
},
"acorn": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz",
"integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==",
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
"integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==",
"dev": true
},
"acorn-globals": {

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

@ -58,6 +58,17 @@ Or they can *be* JavaScript expressions.
---
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
<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:
```html
@ -102,6 +113,15 @@ An element or component can have multiple spread attributes, interspersed with r
<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}>
```
---
### Text expressions

@ -974,7 +974,7 @@ 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).
```html
<svelte:options tag="my-element">
<svelte:options tag="my-element" />
<script>
export let name = 'world';

@ -1358,9 +1358,9 @@
}
},
"acorn": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.0.0.tgz",
"integrity": "sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==",
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
"integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==",
"dev": true
},
"ansi-colors": {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 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,7 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 275 B

After

Width:  |  Height:  |  Size: 184 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 229 B

After

Width:  |  Height:  |  Size: 168 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 221 B

After

Width:  |  Height:  |  Size: 161 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 405 B

After

Width:  |  Height:  |  Size: 320 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 212 B

After

Width:  |  Height:  |  Size: 155 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 213 B

After

Width:  |  Height:  |  Size: 155 B

@ -1,7 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 333 B

After

Width:  |  Height:  |  Size: 256 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 411 B

After

Width:  |  Height:  |  Size: 315 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 415 B

After

Width:  |  Height:  |  Size: 344 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 356 B

After

Width:  |  Height:  |  Size: 258 B

@ -1,8 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 215 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

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"?>
<!-- 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>
<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>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -1,20 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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>
<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>

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">
<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>
<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>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

@ -1,20 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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>
<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>

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 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>
<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>

Before

Width:  |  Height:  |  Size: 280 B

After

Width:  |  Height:  |  Size: 221 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 303 B

After

Width:  |  Height:  |  Size: 242 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 260 B

After

Width:  |  Height:  |  Size: 200 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 354 B

After

Width:  |  Height:  |  Size: 311 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 334 B

After

Width:  |  Height:  |  Size: 280 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

Before

Width:  |  Height:  |  Size: 262 B

After

Width:  |  Height:  |  Size: 193 B

@ -1,4 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<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>

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 check_graph_for_cycles from './utils/check_graph_for_cycles';
import { print, x, b } from 'code-red';
import { is_reserved_keyword } from './utils/reserved_keywords';
interface ComponentOptions {
namespace?: string;
@ -185,7 +186,7 @@ export default class Component {
if (variable) {
variable.referenced = true;
} else if (name === '$$props') {
} else if (is_reserved_keyword(name)) {
this.add_var({
name,
injected: true,
@ -649,7 +650,7 @@ export default class Component {
reassigned: true,
initialised: true,
});
} else if (name === '$$props') {
} else if (is_reserved_keyword(name)) {
this.add_var({
name,
injected: true,
@ -1276,7 +1277,7 @@ export default class Component {
warn_if_undefined(name: string, node, template_scope: TemplateScope) {
if (name[0] === '$') {
if (name === '$' || name[1] === '$' && name !== '$$props') {
if (name === '$' || name[1] === '$' && !is_reserved_keyword(name)) {
this.error(node, {
code: 'illegal-global',
message: `${name} is an illegal variable name`
@ -1285,7 +1286,7 @@ export default class Component {
this.has_reactive_assignments = true; // TODO does this belong here?
if (name === '$$props') return;
if (is_reserved_keyword(name)) return;
name = name.slice(1);
}

@ -3,27 +3,45 @@ import PendingBlock from './PendingBlock';
import ThenBlock from './ThenBlock';
import CatchBlock from './CatchBlock';
import Expression from './shared/Expression';
import { Pattern } from 'estree';
import Component from '../Component';
import TemplateScope from './shared/TemplateScope';
import { TemplateNode } from '../../interfaces';
import traverse_destructure_pattern from '../utils/traverse_destructure_pattern';
export default class AwaitBlock extends Node {
type: 'AwaitBlock';
expression: Expression;
value: string;
error: string;
value: DestructurePattern;
error: DestructurePattern;
pending: PendingBlock;
then: ThenBlock;
catch: CatchBlock;
constructor(component, parent, scope, info) {
constructor(component: Component, parent, scope: TemplateScope, info: TemplateNode) {
super(component, parent, scope, info);
this.expression = new Expression(component, this, scope, info.expression);
this.value = info.value;
this.error = info.error;
this.value = info.value && new DestructurePattern(info.value);
this.error = info.error && new DestructurePattern(info.error);
this.pending = new PendingBlock(component, this, scope, info.pending);
this.then = new ThenBlock(component, this, scope, info.then);
this.catch = new CatchBlock(component, this, scope, info.catch);
}
}
export class DestructurePattern {
pattern: Pattern;
expressions: string[];
identifier_name: string | undefined;
constructor(pattern: Pattern) {
this.pattern = pattern;
this.expressions = [];
traverse_destructure_pattern(pattern, (node) => this.expressions.push(node.name));
this.identifier_name = this.pattern.type === 'Identifier' ? this.pattern.name : undefined;
}
}

@ -72,6 +72,11 @@ export default class Binding extends Node {
});
variable[this.expression.node.type === 'MemberExpression' ? 'mutated' : 'reassigned'] = true;
if (info.expression.type === 'Identifier' && !variable.writable) component.error(this.expression.node, {
code: 'invalid-binding',
message: 'Cannot bind to a variable which is not writable',
});
}
const type = parent.get_static_attribute_value('type');

@ -1,16 +1,23 @@
import map_children from './shared/map_children';
import TemplateScope from './shared/TemplateScope';
import AbstractBlock from './shared/AbstractBlock';
import AwaitBlock from './AwaitBlock';
import Component from '../Component';
import { TemplateNode } from '../../interfaces';
export default class CatchBlock extends AbstractBlock {
type: 'CatchBlock';
scope: TemplateScope;
constructor(component, parent, scope, info) {
constructor(component: Component, parent: AwaitBlock, scope: TemplateScope, info: TemplateNode) {
super(component, parent, scope, info);
this.scope = scope.child();
this.scope.add(parent.error, parent.expression.dependencies, this);
if (parent.error) {
parent.error.expressions.forEach(expression => {
this.scope.add(expression, parent.expression.dependencies, this);
});
}
this.children = map_children(component, parent, this.scope, info.children);
if (!info.skip) {

@ -278,7 +278,7 @@ export default class Element extends Node {
}
validate_attributes() {
const { component } = this;
const { component, parent } = this;
const attribute_map = new Map();
@ -395,26 +395,10 @@ export default class Element extends Node {
component.slot_outlets.add(name);
}
let ancestor = this.parent;
do {
if (ancestor.type === 'InlineComponent') break;
if (ancestor.type === 'Element' && /-/.test(ancestor.name)) break;
if (ancestor.type === 'IfBlock' || ancestor.type === 'EachBlock') {
const type = ancestor.type === 'IfBlock' ? 'if' : 'each';
const message = `Cannot place slotted elements inside an ${type}-block`;
component.error(attribute, {
code: `invalid-slotted-content`,
message
});
}
} while (ancestor = ancestor.parent);
if (!ancestor) {
if (!(parent.type === 'InlineComponent' || within_custom_element(parent))) {
component.error(attribute, {
code: `invalid-slotted-content`,
message: `Element with a slot='...' attribute must be a descendant of a component or custom element`
message: `Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`,
});
}
}
@ -776,3 +760,12 @@ function should_have_attribute(
message: `A11y: <${name}> element should have ${article} ${sequence} attribute`
});
}
function within_custom_element(parent: INode) {
while (parent) {
if (parent.type === 'InlineComponent') return false;
if (parent.type === 'Element' && /-/.test(parent.name)) return true;
parent = parent.parent;
}
return false;
}

@ -3,6 +3,18 @@ import Component from '../Component';
import TemplateScope from './shared/TemplateScope';
import { INode } from './interfaces';
// Whitespace inside one of these elements will not result in
// a whitespace node being created in any circumstances. (This
// list is almost certainly very incomplete)
const elements_without_text = new Set([
'audio',
'datalist',
'dl',
'optgroup',
'select',
'video',
]);
export default class Text extends Node {
type: 'Text';
data: string;
@ -13,4 +25,21 @@ export default class Text extends Node {
this.data = info.data;
this.synthetic = info.synthetic || false;
}
should_skip() {
if (/\S/.test(this.data)) return false;
const parent_element = this.find_nearest(/(?:Element|InlineComponent|Head)/);
if (!parent_element) return false;
if (parent_element.type === 'Head') return true;
if (parent_element.type === 'InlineComponent') return parent_element.children.length === 1 && this === parent_element.children[0];
// svg namespace exclusions
if (/svg$/.test(parent_element.namespace)) {
if (this.prev && this.prev.type === "Element" && this.prev.name === "tspan") return false;
}
return parent_element.namespace || elements_without_text.has(parent_element.name);
}
}

@ -1,16 +1,23 @@
import map_children from './shared/map_children';
import TemplateScope from './shared/TemplateScope';
import AbstractBlock from './shared/AbstractBlock';
import AwaitBlock from './AwaitBlock';
import Component from '../Component';
import { TemplateNode } from '../../interfaces';
export default class ThenBlock extends AbstractBlock {
type: 'ThenBlock';
scope: TemplateScope;
constructor(component, parent, scope, info) {
constructor(component: Component, parent: AwaitBlock, scope: TemplateScope, info: TemplateNode) {
super(component, parent, scope, info);
this.scope = scope.child();
this.scope.add(parent.value, parent.expression.dependencies, this);
if (parent.value) {
parent.value.expressions.forEach(expression => {
this.scope.add(expression, parent.expression.dependencies, this);
});
}
this.children = map_children(component, parent, this.scope, info.children);
if (!info.skip) {

@ -13,6 +13,7 @@ import { b } from 'code-red';
import { invalidate } from '../../render_dom/invalidate';
import { Node, FunctionExpression, Identifier } from 'estree';
import { TemplateNode } from '../../../interfaces';
import { is_reserved_keyword } from '../../utils/reserved_keywords';
type Owner = Wrapper | TemplateNode;
@ -158,7 +159,7 @@ export default class Expression {
dynamic_dependencies() {
return Array.from(this.dependencies).filter(name => {
if (this.template_scope.is_let(name)) return true;
if (name === '$$props') return true;
if (is_reserved_keyword(name)) return true;
const variable = this.component.var_lookup.get(name);
return is_dynamic(variable);
@ -355,7 +356,7 @@ function get_function_name(_node, parent) {
}
function is_contextual(component: Component, scope: TemplateScope, name: string) {
if (name === '$$props') return true;
if (is_reserved_keyword(name)) return true;
// if it's a name below root scope, it's contextual
if (!scope.is_top_level(name)) return true;

@ -46,6 +46,7 @@ export default class Block {
}>;
chunks: {
declarations: Array<Node | Node[]>;
init: Array<Node | Node[]>;
create: Array<Node | Node[]>;
claim: Array<Node | Node[]>;
@ -93,6 +94,7 @@ export default class Block {
this.bindings = options.bindings;
this.chunks = {
declarations: [],
init: [],
create: [],
claim: [],
@ -388,6 +390,8 @@ export default class Block {
const block = dev && this.get_unique_name('block');
const body = b`
${this.chunks.declarations}
${Array.from(this.variables.values()).map(({ id, init }) => {
return init
? b`let ${id} = ${init}`
@ -416,8 +420,7 @@ export default class Block {
}
has_content() {
return this.renderer.options.dev ||
this.first ||
return this.first ||
this.event_listeners.length > 0 ||
this.chunks.intro.length > 0 ||
this.chunks.outro.length > 0 ||

@ -5,6 +5,7 @@ import FragmentWrapper from './wrappers/Fragment';
import { x } from 'code-red';
import { Node, Identifier, MemberExpression, Literal, Expression, BinaryExpression } from 'estree';
import flatten_reference from '../utils/flatten_reference';
import { reserved_keywords } from '../utils/reserved_keywords';
interface ContextMember {
name: string;
@ -50,9 +51,11 @@ export default class Renderer {
// ensure store values are included in context
component.vars.filter(v => v.subscribable).forEach(v => this.add_to_context(`$${v.name}`));
if (component.var_lookup.has('$$props')) {
this.add_to_context('$$props');
}
reserved_keywords.forEach(keyword => {
if (component.var_lookup.has(keyword)) {
this.add_to_context(keyword);
}
});
if (component.slots.size > 0) {
this.add_to_context('$$scope');
@ -230,6 +233,7 @@ export default class Renderer {
return bitmask;
};
// TODO: context-overflow make it less gross
return {
// Using a ParenthesizedExpression allows us to create
// the expression lazily. TODO would be better if

@ -71,14 +71,24 @@ export default function dom(
}
const uses_props = component.var_lookup.has('$$props');
const $$props = uses_props ? `$$new_props` : `$$props`;
const uses_rest = component.var_lookup.has('$$restProps');
const $$props = uses_props || uses_rest ? `$$new_props` : `$$props`;
const props = component.vars.filter(variable => !variable.module && variable.export_name);
const writable_props = props.filter(variable => variable.writable);
const set = (uses_props || writable_props.length > 0 || component.slots.size > 0)
const omit_props_names = component.get_unique_name('omit_props_names');
const compute_rest = x`@compute_rest_props($$props, ${omit_props_names.name})`;
const rest = uses_rest ? b`
const ${omit_props_names.name} = [${props.map(prop => `"${prop.export_name}"`).join(',')}];
let $$restProps = ${compute_rest};
` : null;
const set = (uses_props || uses_rest || writable_props.length > 0 || component.slots.size > 0)
? x`
${$$props} => {
${uses_props && renderer.invalidate('$$props', x`$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`)}
${uses_rest && !uses_props && x`$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`}
${uses_rest && renderer.invalidate('$$restProps', x`$$restProps = ${compute_rest}`)}
${writable_props.map(prop =>
b`if ('${prop.export_name}' in ${$$props}) ${renderer.invalidate(prop.name, x`${prop.name} = ${$$props}.${prop.export_name}`)};`
)}
@ -264,7 +274,7 @@ export default function dom(
args.push(x`$$props`);
}
const has_create_fragment = block.has_content();
const has_create_fragment = component.compile_options.dev || block.has_content();
if (has_create_fragment) {
body.push(b`
function create_fragment(#ctx) {
@ -341,20 +351,20 @@ export default function dom(
component.reactive_declarations.forEach(d => {
const dependencies = Array.from(d.dependencies);
const uses_props = !!dependencies.find(n => n === '$$props');
const uses_rest_or_props = !!dependencies.find(n => n === '$$props' || n === '$$restProps');
const writable = dependencies.filter(n => {
const variable = component.var_lookup.get(n);
return variable && (variable.export_name || variable.mutated || variable.reassigned);
});
const condition = !uses_props && writable.length > 0 && renderer.dirty(writable, true);
const condition = !uses_rest_or_props && writable.length > 0 && renderer.dirty(writable, true);
let statement = d.node; // TODO remove label (use d.node.body) if it's not referenced
if (condition) statement = b`if (${condition}) { ${statement} }`[0] as Statement;
if (condition || uses_props) {
if (condition || uses_rest_or_props) {
reactive_declarations.push(statement);
} else {
fixed_reactive_declarations.push(statement);
@ -383,7 +393,7 @@ export default function dom(
});
let unknown_props_check;
if (component.compile_options.dev && !component.var_lookup.has('$$props')) {
if (component.compile_options.dev && !(uses_props || uses_rest)) {
unknown_props_check = b`
const writable_props = [${writable_props.map(prop => x`'${prop.export_name}'`)}];
@_Object.keys($$props).forEach(key => {
@ -402,6 +412,8 @@ export default function dom(
body.push(b`
function ${definition}(${args}) {
${rest}
${reactive_store_declarations}
${reactive_store_subscriptions}
@ -412,7 +424,8 @@ export default function dom(
${unknown_props_check}
${component.slots.size ? b`let { $$slots = {}, $$scope } = $$props;` : null}
${component.slots.size || component.compile_options.dev ? b`let { $$slots = {}, $$scope } = $$props;` : null}
${component.compile_options.dev && b`@validate_slots('${component.tag}', $$slots, [${[...component.slots.keys()].map(key => `'${key}'`).join(',')}]);`}
${renderer.binding_groups.length > 0 && b`const $$binding_groups = [${renderer.binding_groups.map(_ => x`[]`)}];`}
@ -472,7 +485,7 @@ export default function dom(
@insert(options.target, this, options.anchor);
}
${(props.length > 0 || uses_props) && b`
${(props.length > 0 || uses_props || uses_rest) && b`
if (options.props) {
this.$set(options.props);
@flush();

@ -9,6 +9,7 @@ import PendingBlock from '../../nodes/PendingBlock';
import ThenBlock from '../../nodes/ThenBlock';
import CatchBlock from '../../nodes/CatchBlock';
import { Identifier } from 'estree';
import traverse_destructure_pattern from '../../utils/traverse_destructure_pattern';
class AwaitBlockBranch extends Wrapper {
node: PendingBlock | ThenBlock | CatchBlock;
@ -46,6 +47,23 @@ class AwaitBlockBranch extends Wrapper {
this.is_dynamic = this.block.dependencies.size > 0;
}
render(block: Block, parent_node: Identifier, parent_nodes: Identifier) {
this.fragment.render(block, parent_node, parent_nodes);
}
render_destructure(block: Block, value, node, index) {
if (value && node.pattern.type !== 'Identifier') {
traverse_destructure_pattern(node.pattern, (node, parent, index) => {
parent[index] = x`#ctx[${block.renderer.context_lookup.get(node.name).index}]`;
});
this.block.chunks.declarations.push(b`(${node.pattern} = #ctx[${index}])`);
if (this.block.has_update_method) {
this.block.chunks.update.push(b`(${node.pattern} = #ctx[${index}])`);
}
}
}
}
export default class AwaitBlockWrapper extends Wrapper {
@ -55,6 +73,9 @@ export default class AwaitBlockWrapper extends Wrapper {
then: AwaitBlockBranch;
catch: AwaitBlockBranch;
value: string;
error: string;
var: Identifier = { type: 'Identifier', name: 'await_block' };
constructor(
@ -71,8 +92,20 @@ export default class AwaitBlockWrapper extends Wrapper {
this.not_static_content();
block.add_dependencies(this.node.expression.dependencies);
if (this.node.value) block.renderer.add_to_context(this.node.value, true);
if (this.node.error) block.renderer.add_to_context(this.node.error, true);
if (this.node.value) {
for (const ctx of this.node.value.expressions) {
block.renderer.add_to_context(ctx, true);
}
this.value = this.node.value.identifier_name || block.get_unique_name('value').name;
block.renderer.add_to_context(this.value, true);
}
if (this.node.error) {
for (const ctx of this.node.error.expressions) {
block.renderer.add_to_context(ctx, true);
}
this.error = this.node.error.identifier_name || block.get_unique_name('error').name;
block.renderer.add_to_context(this.error, true);
}
let is_dynamic = false;
let has_intros = false;
@ -105,17 +138,11 @@ export default class AwaitBlockWrapper extends Wrapper {
this[status] = branch;
});
this.pending.block.has_update_method = is_dynamic;
this.then.block.has_update_method = is_dynamic;
this.catch.block.has_update_method = is_dynamic;
this.pending.block.has_intro_method = has_intros;
this.then.block.has_intro_method = has_intros;
this.catch.block.has_intro_method = has_intros;
this.pending.block.has_outro_method = has_outros;
this.then.block.has_outro_method = has_outros;
this.catch.block.has_outro_method = has_outros;
['pending', 'then', 'catch'].forEach(status => {
this[status].block.has_update_method = is_dynamic;
this[status].block.has_intro_method = has_intros;
this[status].block.has_outro_method = has_outros;
});
if (has_outros) {
block.add_outro();
@ -139,8 +166,8 @@ export default class AwaitBlockWrapper extends Wrapper {
block.maintain_context = true;
const value_index = this.node.value && block.renderer.context_lookup.get(this.node.value).index;
const error_index = this.node.error && block.renderer.context_lookup.get(this.node.error).index;
const value_index = this.value && block.renderer.context_lookup.get(this.value).index;
const error_index = this.error && block.renderer.context_lookup.get(this.error).index;
const info_props: any = x`{
ctx: #ctx,
@ -205,7 +232,7 @@ export default class AwaitBlockWrapper extends Wrapper {
} else {
const #child_ctx = #ctx.slice();
${this.node.value && b`#child_ctx[${value_index}] = ${info}.resolved;`}
${this.value && b`#child_ctx[${value_index}] = ${info}.resolved;`}
${info}.block.p(#child_ctx, #dirty);
}
`);
@ -219,7 +246,7 @@ export default class AwaitBlockWrapper extends Wrapper {
block.chunks.update.push(b`
{
const #child_ctx = #ctx.slice();
${this.node.value && b`#child_ctx[${value_index}] = ${info}.resolved;`}
${this.value && b`#child_ctx[${value_index}] = ${info}.resolved;`}
${info}.block.p(#child_ctx, #dirty);
}
`);
@ -242,7 +269,9 @@ export default class AwaitBlockWrapper extends Wrapper {
`);
[this.pending, this.then, this.catch].forEach(branch => {
branch.fragment.render(branch.block, null, x`#nodes` as Identifier);
branch.render(branch.block, null, x`#nodes` as Identifier);
});
this.then.render_destructure(block, this.value, this.node.value, value_index);
this.catch.render_destructure(block, this.error, this.node.error, error_index);
}
}

@ -62,6 +62,8 @@ export default class EachBlockWrapper extends Wrapper {
context_props: Array<Node | Node[]>;
index_name: Identifier;
updates: Array<Node | Node[]> = [];
dependencies: Set<string>;
var: Identifier = { type: 'Identifier', name: 'each' };
@ -235,6 +237,12 @@ export default class EachBlockWrapper extends Wrapper {
update_mount_node
};
const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only
this.node.expression.dynamic_dependencies().forEach((dependency: string) => {
all_dependencies.add(dependency);
});
this.dependencies = all_dependencies;
if (this.node.key) {
this.render_keyed(args);
} else {
@ -291,7 +299,7 @@ export default class EachBlockWrapper extends Wrapper {
`);
if (this.else.block.has_update_method) {
block.chunks.update.push(b`
this.updates.push(b`
if (!${this.vars.data_length} && ${each_block_else}) {
${each_block_else}.p(#ctx, #dirty);
} else if (!${this.vars.data_length}) {
@ -304,7 +312,7 @@ export default class EachBlockWrapper extends Wrapper {
}
`);
} else {
block.chunks.update.push(b`
this.updates.push(b`
if (${this.vars.data_length}) {
if (${each_block_else}) {
${each_block_else}.d(1);
@ -323,6 +331,14 @@ export default class EachBlockWrapper extends Wrapper {
`);
}
if (this.updates.length) {
block.chunks.update.push(b`
if (${block.renderer.dirty(Array.from(all_dependencies))}) {
${this.updates}
}
`);
}
this.fragment.render(this.block, null, x`#nodes` as Identifier);
if (this.else) {
@ -415,24 +431,17 @@ export default class EachBlockWrapper extends Wrapper {
? `@outro_and_destroy_block`
: `@destroy_block`;
const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only
this.node.expression.dynamic_dependencies().forEach((dependency: string) => {
all_dependencies.add(dependency);
});
if (this.dependencies.size) {
this.updates.push(b`
const ${this.vars.each_block_value} = ${snippet};
${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`}
if (all_dependencies.size) {
block.chunks.update.push(b`
if (${block.renderer.dirty(Array.from(all_dependencies))}) {
const ${this.vars.each_block_value} = ${snippet};
${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`}
${this.block.has_outros && b`@group_outros();`}
${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].r();`}
${this.renderer.options.dev && b`@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
${iterations} = @update_keyed_each(${iterations}, #dirty, ${get_key}, ${dynamic ? 1 : 0}, #ctx, ${this.vars.each_block_value}, ${lookup}, ${update_mount_node}, ${destroy}, ${create_each_block}, ${update_anchor_node}, ${this.vars.get_each_context});
${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`}
${this.block.has_outros && b`@check_outros();`}
}
${this.block.has_outros && b`@group_outros();`}
${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].r();`}
${this.renderer.options.dev && b`@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
${iterations} = @update_keyed_each(${iterations}, #dirty, ${get_key}, ${dynamic ? 1 : 0}, #ctx, ${this.vars.each_block_value}, ${lookup}, ${update_mount_node}, ${destroy}, ${create_each_block}, ${update_anchor_node}, ${this.vars.get_each_context});
${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`}
${this.block.has_outros && b`@check_outros();`}
`);
}
@ -504,12 +513,7 @@ export default class EachBlockWrapper extends Wrapper {
}
`);
const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only
this.node.expression.dynamic_dependencies().forEach((dependency: string) => {
all_dependencies.add(dependency);
});
if (all_dependencies.size) {
if (this.dependencies.size) {
const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method);
const for_loop_body = this.block.has_update_method
@ -588,11 +592,7 @@ export default class EachBlockWrapper extends Wrapper {
${remove_old_blocks}
`;
block.chunks.update.push(b`
if (${block.renderer.dirty(Array.from(all_dependencies))}) {
${update}
}
`);
this.updates.push(update);
}
if (this.block.has_outros) {

@ -17,6 +17,7 @@ import { INode } from '../../nodes/interfaces';
import Renderer from '../Renderer';
import Block from '../Block';
import { trim_start, trim_end } from '../../../utils/trim';
import { link } from '../../../utils/link';
import { Identifier } from 'estree';
const wrappers = {
@ -38,11 +39,6 @@ const wrappers = {
Window
};
function link(next: Wrapper, prev: Wrapper) {
prev.next = next;
if (next) next.prev = prev;
}
function trimmable_at(child: INode, next_sibling: Wrapper): boolean {
// Whitespace is trimmable if one of the following is true:
// The child and its sibling share a common nearest each block (not at an each block boundary)

@ -9,7 +9,7 @@ import FragmentWrapper from './Fragment';
import { b, x } from 'code-red';
import { walk } from 'estree-walker';
import { is_head } from './shared/is_head';
import { Identifier, Node } from 'estree';
import { Identifier, Node, UnaryExpression } from 'estree';
function is_else_if(node: ElseBlock) {
return (
@ -288,7 +288,7 @@ export default class IfBlockWrapper extends Wrapper {
}
block.chunks.init.push(b`
let ${current_block_type} = ${select_block_type}(#ctx, -1);
let ${current_block_type} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()});
let ${name} = ${get_block};
`);
@ -407,12 +407,12 @@ export default class IfBlockWrapper extends Wrapper {
if (has_else) {
block.chunks.init.push(b`
${current_block_type_index} = ${select_block_type}(#ctx, -1);
${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()});
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
`);
} else {
block.chunks.init.push(b`
if (~(${current_block_type_index} = ${select_block_type}(#ctx, -1))) {
if (~(${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()}))) {
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
}
`);
@ -587,4 +587,21 @@ export default class IfBlockWrapper extends Wrapper {
`);
}
}
get_initial_dirty_bit() {
const _this = this;
// TODO: context-overflow make it less gross
const val: UnaryExpression = x`-1` as UnaryExpression;
return {
get type() {
return _this.renderer.context_overflow ? 'ArrayExpression' : 'UnaryExpression';
},
// as [-1]
elements: [val],
// as -1
operator: val.operator,
prefix: val.prefix,
argument: val.argument,
};
}
}

@ -138,11 +138,27 @@ export default class InlineComponentWrapper extends Wrapper {
const statements: Array<Node | Node[]> = [];
const updates: Array<Node | Node[]> = [];
if (this.fragment) {
this.renderer.add_to_context('$$scope', true);
const default_slot = this.slots.get('default');
this.fragment.nodes.forEach((child) => {
child.render(default_slot.block, null, x`#nodes` as unknown as Identifier);
});
}
let props;
const name_changes = block.get_unique_name(`${name.name}_changes`);
const uses_spread = !!this.node.attributes.find(a => a.is_spread);
// removing empty slot
for (const slot of this.slots.keys()) {
if (!this.slots.get(slot).block.has_content()) {
this.slots.delete(slot);
}
}
const initial_props = this.slots.size > 0
? [
p`$$slots: {
@ -172,15 +188,6 @@ export default class InlineComponentWrapper extends Wrapper {
}
}
if (this.fragment) {
this.renderer.add_to_context('$$scope', true);
const default_slot = this.slots.get('default');
this.fragment.nodes.forEach((child) => {
child.render(default_slot.block, null, x`#nodes` as unknown as Identifier);
});
}
if (component.compile_options.dev) {
// TODO this is a terrible hack, but without it the component
// will complain that options.target is missing. This would

@ -10,10 +10,12 @@ import get_slot_data from '../../utils/get_slot_data';
import Expression from '../../nodes/shared/Expression';
import is_dynamic from './shared/is_dynamic';
import { Identifier, ObjectExpression } from 'estree';
import create_debugging_comment from './shared/create_debugging_comment';
export default class SlotWrapper extends Wrapper {
node: Slot;
fragment: FragmentWrapper;
fallback: Block | null = null;
var: Identifier = { type: 'Identifier', name: 'slot' };
dependencies: Set<string> = new Set(['$$scope']);
@ -30,9 +32,17 @@ export default class SlotWrapper extends Wrapper {
this.cannot_use_innerhtml();
this.not_static_content();
if (this.node.children.length) {
this.fallback = block.child({
comment: create_debugging_comment(this.node.children[0], this.renderer.component),
name: this.renderer.component.get_unique_name(`fallback_block`),
type: 'fallback'
});
}
this.fragment = new FragmentWrapper(
renderer,
block,
this.fallback,
node.children,
parent,
strip_whitespace,
@ -103,86 +113,90 @@ export default class SlotWrapper extends Wrapper {
get_slot_context_fn = 'null';
}
if (this.fallback) {
this.fragment.render(this.fallback, null, x`#nodes` as Identifier);
renderer.blocks.push(this.fallback);
}
const slot = block.get_unique_name(`${sanitize(slot_name)}_slot`);
const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`);
const slot_or_fallback = this.fallback ? block.get_unique_name(`${sanitize(slot_name)}_slot_or_fallback`) : slot;
block.chunks.init.push(b`
const ${slot_definition} = ${renderer.reference('$$slots')}.${slot_name};
const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn});
${this.fallback ? b`const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null}
`);
// TODO this is a dreadful hack! Should probably make this nicer
const { create, claim, hydrate, mount, update, destroy } = block.chunks;
block.chunks.create = [];
block.chunks.claim = [];
block.chunks.hydrate = [];
block.chunks.mount = [];
block.chunks.update = [];
block.chunks.destroy = [];
const listeners = block.event_listeners;
block.event_listeners = [];
this.fragment.render(block, parent_node, parent_nodes);
block.render_listeners(`_${slot.name}`);
block.event_listeners = listeners;
if (block.chunks.create.length) create.push(b`if (!${slot}) { ${block.chunks.create} }`);
if (block.chunks.claim.length) claim.push(b`if (!${slot}) { ${block.chunks.claim} }`);
if (block.chunks.hydrate.length) hydrate.push(b`if (!${slot}) { ${block.chunks.hydrate} }`);
if (block.chunks.mount.length) mount.push(b`if (!${slot}) { ${block.chunks.mount} }`);
if (block.chunks.update.length) update.push(b`if (!${slot}) { ${block.chunks.update} }`);
if (block.chunks.destroy.length) destroy.push(b`if (!${slot}) { ${block.chunks.destroy} }`);
block.chunks.create = create;
block.chunks.claim = claim;
block.chunks.hydrate = hydrate;
block.chunks.mount = mount;
block.chunks.update = update;
block.chunks.destroy = destroy;
block.chunks.create.push(
b`if (${slot}) ${slot}.c();`
b`if (${slot_or_fallback}) ${slot_or_fallback}.c();`
);
if (renderer.options.hydratable) {
block.chunks.claim.push(
b`if (${slot}) ${slot}.l(${parent_nodes});`
b`if (${slot_or_fallback}) ${slot_or_fallback}.l(${parent_nodes});`
);
}
block.chunks.mount.push(b`
if (${slot}) {
${slot}.m(${parent_node || '#target'}, ${parent_node ? 'null' : 'anchor'});
if (${slot_or_fallback}) {
${slot_or_fallback}.m(${parent_node || '#target'}, ${parent_node ? 'null' : 'anchor'});
}
`);
block.chunks.intro.push(
b`@transition_in(${slot}, #local);`
b`@transition_in(${slot_or_fallback}, #local);`
);
block.chunks.outro.push(
b`@transition_out(${slot}, #local);`
b`@transition_out(${slot_or_fallback}, #local);`
);
const dynamic_dependencies = Array.from(this.dependencies).filter(name => {
const is_dependency_dynamic = name => {
if (name === '$$scope') return true;
if (this.node.scope.is_let(name)) return true;
const variable = renderer.component.var_lookup.get(name);
return is_dynamic(variable);
});
};
const dynamic_dependencies = Array.from(this.dependencies).filter(is_dependency_dynamic);
const fallback_dynamic_dependencies = this.fallback
? Array.from(this.fallback.dependencies).filter(is_dependency_dynamic)
: [];
block.chunks.update.push(b`
if (${slot} && ${slot}.p && ${renderer.dirty(dynamic_dependencies)}) {
const slot_update = b`
if (${slot}.p && ${renderer.dirty(dynamic_dependencies)}) {
${slot}.p(
@get_slot_context(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn}),
@get_slot_changes(${slot_definition}, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn})
);
}
`);
`;
const fallback_update = this.fallback && fallback_dynamic_dependencies.length > 0 && b`
if (${slot_or_fallback} && ${slot_or_fallback}.p && ${renderer.dirty(fallback_dynamic_dependencies)}) {
${slot_or_fallback}.p(#ctx, #dirty);
}
`;
if (fallback_update) {
block.chunks.update.push(b`
if (${slot}) {
${slot_update}
} else {
${fallback_update}
}
`);
} else {
block.chunks.update.push(b`
if (${slot}) {
${slot_update}
}
`);
}
block.chunks.destroy.push(
b`if (${slot}) ${slot}.d(detaching);`
b`if (${slot_or_fallback}) ${slot_or_fallback}.d(detaching);`
);
}
}

@ -5,36 +5,6 @@ import Wrapper from './shared/Wrapper';
import { x } from 'code-red';
import { Identifier } from 'estree';
// Whitespace inside one of these elements will not result in
// a whitespace node being created in any circumstances. (This
// list is almost certainly very incomplete)
const elements_without_text = new Set([
'audio',
'datalist',
'dl',
'optgroup',
'select',
'video',
]);
// TODO this should probably be in Fragment
function should_skip(node: Text) {
if (/\S/.test(node.data)) return false;
const parent_element = node.find_nearest(/(?:Element|InlineComponent|Head)/);
if (!parent_element) return false;
if (parent_element.type === 'Head') return true;
if (parent_element.type === 'InlineComponent') return parent_element.children.length === 1 && node === parent_element.children[0];
// svg namespace exclusions
if (/svg$/.test(parent_element.namespace)) {
if (node.prev && node.prev.type === "Element" && node.prev.name === "tspan") return false;
}
return parent_element.namespace || elements_without_text.has(parent_element.name);
}
export default class TextWrapper extends Wrapper {
node: Text;
data: string;
@ -50,7 +20,7 @@ export default class TextWrapper extends Wrapper {
) {
super(renderer, block, parent, node);
this.skip = should_skip(this.node);
this.skip = this.node.should_skip();
this.data = data;
this.var = (this.skip ? null : x`t`) as unknown as Identifier;
}

@ -16,8 +16,16 @@ export default function create_debugging_comment(
let d;
if (node.type === 'InlineComponent' || node.type === 'Element') {
d = node.children.length ? node.children[0].start : node.start;
while (source[d - 1] !== '>') d -= 1;
if (node.children.length) {
d = node.children[0].start;
while (source[d - 1] !== '>') d -= 1;
} else {
d = node.start;
while (source[d] !== '>') d += 1;
d += 1;
}
} else if (node.type === 'Text') {
d = node.end;
} else {
// @ts-ignore
d = node.expression ? node.expression.node.end : c;

@ -63,7 +63,7 @@ export function get_slot_definition(block: Block, scope: TemplateScope, lets: Le
const { context_lookup } = block.renderer;
// i am well aware that this code is gross
// TODO make it less gross
// TODO: context-overflow make it less gross
const changes = {
type: 'ParenthesizedExpression',
get expression() {

@ -14,7 +14,7 @@ export default function(node: AwaitBlock, renderer: Renderer, options: RenderOpt
renderer.add_expression(x`
function(__value) {
if (@is_promise(__value)) return ${pending};
return (function(${node.value}) { return ${then}; }(__value));
return (function(${node.value ? node.value.pattern : ''}) { return ${then}; }(__value));
}(${node.expression.node})
`);
}

@ -6,10 +6,14 @@ import Renderer, { RenderOptions } from '../Renderer';
import Element from '../../nodes/Element';
import { x } from 'code-red';
import Expression from '../../nodes/shared/Expression';
import remove_whitespace_children from './utils/remove_whitespace_children';
export default function(node: Element, renderer: Renderer, options: RenderOptions & {
slot_scopes: Map<any, any>;
}) {
const children = remove_whitespace_children(node.children, node.next);
// awkward special case
let node_contents;
@ -133,7 +137,7 @@ export default function(node: Element, renderer: Renderer, options: RenderOption
if (node_contents !== undefined) {
if (contenteditable) {
renderer.push();
renderer.render(node.children, options);
renderer.render(children, options);
const result = renderer.pop();
renderer.add_expression(x`($$value => $$value === void 0 ? ${result} : $$value)(${node_contents})`);
@ -145,7 +149,7 @@ export default function(node: Element, renderer: Renderer, options: RenderOption
renderer.add_string(`</${node.name}>`);
}
} else if (slot && nearest_inline_component) {
renderer.render(node.children, options);
renderer.render(children, options);
if (!is_void(node.name)) {
renderer.add_string(`</${node.name}>`);
@ -163,10 +167,11 @@ export default function(node: Element, renderer: Renderer, options: RenderOption
output: renderer.pop()
});
} else {
renderer.render(node.children, options);
renderer.render(children, options);
if (!is_void(node.name)) {
renderer.add_string(`</${node.name}>`);
}
}
}

@ -2,6 +2,7 @@ import { string_literal } from '../../utils/stringify';
import Renderer, { RenderOptions } from '../Renderer';
import { get_slot_scope } from './shared/get_slot_scope';
import InlineComponent from '../../nodes/InlineComponent';
import remove_whitespace_children from './utils/remove_whitespace_children';
import { p, x } from 'code-red';
function get_prop_value(attribute) {
@ -67,12 +68,14 @@ export default function(node: InlineComponent, renderer: Renderer, options: Rend
const slot_fns = [];
if (node.children.length) {
const children = remove_whitespace_children(node.children, node.next);
if (children.length) {
const slot_scopes = new Map();
renderer.push();
renderer.render(node.children, Object.assign({}, options, {
renderer.render(children, Object.assign({}, options, {
slot_scopes
}));
@ -82,9 +85,11 @@ export default function(node: InlineComponent, renderer: Renderer, options: Rend
});
slot_scopes.forEach(({ input, output }, name) => {
slot_fns.push(
p`${name}: (${input}) => ${output}`
);
if (!is_empty_template_literal(output)) {
slot_fns.push(
p`${name}: (${input}) => ${output}`
);
}
});
}
@ -94,3 +99,11 @@ export default function(node: InlineComponent, renderer: Renderer, options: Rend
renderer.add_expression(x`@validate_component(${expression}, "${node.name}").$$render($$result, ${props}, ${bindings}, ${slots})`);
}
function is_empty_template_literal(template_literal) {
return (
template_literal.expressions.length === 0 &&
template_literal.quasis.length === 1 &&
template_literal.quasis[0].value.raw === ""
);
}

@ -0,0 +1,73 @@
import { INode } from '../../../nodes/interfaces';
import { trim_end, trim_start } from '../../../../utils/trim';
import { link } from '../../../../utils/link';
// similar logic from `compile/render_dom/wrappers/Fragment`
// We want to remove trailing whitespace inside an element/component/block,
// *unless* there is no whitespace between this node and its next sibling
export default function remove_whitespace_children(children: INode[], next?: INode): INode[] {
const nodes: INode[] = [];
let last_child: INode;
let i = children.length;
while (i--) {
const child = children[i];
if (child.type === 'Text') {
if (child.should_skip()) {
continue;
}
let { data } = child;
if (nodes.length === 0) {
const should_trim = next
? next.type === 'Text' &&
/^\s/.test(next.data) &&
trimmable_at(child, next)
: !child.has_ancestor('EachBlock');
if (should_trim) {
data = trim_end(data);
if (!data) continue;
}
}
// glue text nodes (which could e.g. be separated by comments) together
if (last_child && last_child.type === 'Text') {
last_child.data = data + last_child.data;
continue;
}
nodes.unshift(child);
link(last_child, last_child = child);
} else {
nodes.unshift(child);
link(last_child, last_child = child);
}
}
const first = nodes[0];
if (first && first.type === 'Text') {
first.data = trim_start(first.data);
if (!first.data) {
first.var = null;
nodes.shift();
if (nodes[0]) {
nodes[0].prev = null;
}
}
}
return nodes;
}
function trimmable_at(child: INode, next_sibling: INode): boolean {
// Whitespace is trimmable if one of the following is true:
// The child and its sibling share a common nearest each block (not at an each block boundary)
// The next sibling's previous node is an each block
return (
next_sibling.find_nearest(/EachBlock/) ===
child.find_nearest(/EachBlock/) || next_sibling.prev.type === 'EachBlock'
);
}

@ -31,6 +31,10 @@ export default function ssr(
{ code: null, map: null } :
component.stylesheet.render(options.filename, true);
const uses_rest = component.var_lookup.has('$$restProps');
const props = component.vars.filter(variable => !variable.module && variable.export_name);
const rest = uses_rest ? b`let $$restProps = @compute_rest_props($$props, [${props.map(prop => `"${prop.export_name}"`).join(',')}]);` : null;
const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
const reactive_store_values = reactive_stores
.map(({ name }) => {
@ -130,6 +134,7 @@ export default function ssr(
return ${literal};`;
const blocks = [
rest,
...reactive_stores.map(({ name }) => {
const store_name = name.slice(1);
const store = component.var_lookup.get(store_name);

@ -0,0 +1,5 @@
export const reserved_keywords = new Set(["$$props", "$$restProps"]);
export function is_reserved_keyword(name) {
return reserved_keywords.has(name);
}

@ -0,0 +1,35 @@
import { Pattern, Identifier, RestElement } from "estree";
import { Node } from "acorn";
export default function traverse_destructure_pattern(
node: Pattern,
callback: (node: Identifier, parent: Node, key: string | number) => void
) {
function traverse(node: Pattern, parent, key) {
switch (node.type) {
case "Identifier":
return callback(node, parent, key);
case "ArrayPattern":
for (let i = 0; i < node.elements.length; i++) {
const element = node.elements[i];
traverse(element, node.elements, i);
}
break;
case "ObjectPattern":
for (let i = 0; i < node.properties.length; i++) {
const property = node.properties[i];
if (property.type === "Property") {
traverse(property.value, property, "value");
} else {
traverse((property as any) as RestElement, node.properties, i);
}
}
break;
case "RestElement":
return traverse(node.argument, node, 'argument');
case "AssignmentPattern":
return traverse(node.left, node, 'left');
}
}
traverse(node, null, null);
}

@ -5,6 +5,9 @@ import { reserved } from '../utils/names';
import full_char_code_at from '../utils/full_char_code_at';
import { TemplateNode, Ast, ParserOptions, Fragment, Style, Script } from '../interfaces';
import error from '../utils/error';
import { is_bracket_open, is_bracket_close, is_bracket_pair, get_bracket_close } from './utils/bracket';
import { parse_expression_at } from './acorn';
import { Pattern } from 'estree';
type ParserState = (parser: Parser) => (ParserState | void);
@ -170,6 +173,51 @@ export class Parser {
return identifier;
}
read_destructure_pattern(): Pattern {
const start = this.index;
let i = this.index;
const code = full_char_code_at(this.template, i);
if (isIdentifierStart(code, true)) {
return { type: 'Identifier', name: this.read_identifier() };
}
if (!is_bracket_open(code)) {
this.error({
code: 'unexpected-token',
message: 'Expected identifier or destructure pattern',
});
}
const bracket_stack = [code];
i += code <= 0xffff ? 1 : 2;
while (i < this.template.length) {
const code = full_char_code_at(this.template, i);
if (is_bracket_open(code)) {
bracket_stack.push(code);
} else if (is_bracket_close(code)) {
if (!is_bracket_pair(bracket_stack[bracket_stack.length - 1], code)) {
this.error({
code: 'unexpected-token',
message: `Expected ${String.fromCharCode(get_bracket_close(bracket_stack[bracket_stack.length - 1]))}`
});
}
bracket_stack.pop();
if (bracket_stack.length === 0) {
i += code <= 0xffff ? 1 : 2;
break;
}
}
i += code <= 0xffff ? 1 : 2;
}
this.index = i;
const pattern_string = this.template.slice(start, i);
return (parse_expression_at(`(${pattern_string} = 1)`, 0) as any).left as Pattern;
}
read_until(pattern: RegExp) {
if (this.index >= this.template.length)
this.error({

@ -196,7 +196,7 @@ export default function mustache(parser: Parser) {
if (!parser.eat('}')) {
parser.require_whitespace();
await_block[is_then ? 'value': 'error'] = parser.read_identifier();
await_block[is_then ? 'value': 'error'] = parser.read_destructure_pattern();
parser.allow_whitespace();
parser.eat('}', true);
}
@ -305,7 +305,7 @@ export default function mustache(parser: Parser) {
const await_block_shorthand = type === 'AwaitBlock' && parser.eat('then');
if (await_block_shorthand) {
parser.require_whitespace();
block.value = parser.read_identifier();
block.value = parser.read_destructure_pattern();
parser.allow_whitespace();
}

@ -241,7 +241,7 @@ function read_tag_name(parser: Parser) {
while (i--) {
const fragment = parser.stack[i];
if (fragment.type === 'IfBlock' || fragment.type === 'EachBlock') {
if (fragment.type === 'IfBlock' || fragment.type === 'EachBlock' || fragment.type === 'InlineComponent') {
legal = true;
break;
}
@ -250,7 +250,7 @@ function read_tag_name(parser: Parser) {
if (!legal) {
parser.error({
code: `invalid-self-placement`,
message: `<svelte:self> components can only exist inside if-blocks or each-blocks`
message: `<svelte:self> components can only exist inside {#if} blocks, {#each} blocks, or slots passed to components`
}, start);
}

@ -0,0 +1,28 @@
const SQUARE_BRACKET_OPEN = "[".charCodeAt(0);
const SQUARE_BRACKET_CLOSE = "]".charCodeAt(0);
const CURLY_BRACKET_OPEN = "{".charCodeAt(0);
const CURLY_BRACKET_CLOSE = "}".charCodeAt(0);
export function is_bracket_open(code) {
return code === SQUARE_BRACKET_OPEN || code === CURLY_BRACKET_OPEN;
}
export function is_bracket_close(code) {
return code === SQUARE_BRACKET_CLOSE || code === CURLY_BRACKET_CLOSE;
}
export function is_bracket_pair(open, close) {
return (
(open === SQUARE_BRACKET_OPEN && close === SQUARE_BRACKET_CLOSE) ||
(open === CURLY_BRACKET_OPEN && close === CURLY_BRACKET_CLOSE)
);
}
export function get_bracket_close(open) {
if (open === SQUARE_BRACKET_OPEN) {
return SQUARE_BRACKET_CLOSE;
}
if (open === CURLY_BRACKET_OPEN) {
return CURLY_BRACKET_CLOSE;
}
}

@ -21,7 +21,7 @@ export default function error(message: string, props: {
filename: string;
start: number;
end?: number;
}) {
}): never {
const error = new CompileError(message);
error.name = props.name;

@ -0,0 +1,4 @@
export function link<T extends { next?: T; prev?: T }>(next: T, prev: T) {
prev.next = next;
if (next) next.prev = prev;
}

@ -1,7 +1,7 @@
import { add_render_callback, flush, schedule_update, dirty_components } from './scheduler';
import { current_component, set_current_component } from './lifecycle';
import { blank_object, is_function, run, run_all, noop } from './utils';
import { children } from './dom';
import { children, detach } from './dom';
import { transition_in } from './transitions';
interface Fragment {
@ -146,8 +146,10 @@ export function init(component, options, instance, create_fragment, not_equal, p
if (options.target) {
if (options.hydrate) {
const nodes = children(options.target);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
$$.fragment && $$.fragment!.l(children(options.target));
$$.fragment && $$.fragment!.l(nodes);
nodes.forEach(detach);
} else {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
$$.fragment && $$.fragment!.c();

@ -89,6 +89,13 @@ export function validate_each_argument(arg) {
}
}
export function validate_slots(name, slot, keys) {
for (const slot_key of Object.keys(slot)) {
if (!~keys.indexOf(slot_key)) {
console.warn(`<${name}> received an unexpected slot "${slot_key}".`);
}
}
}
type Props = Record<string, any>;
export interface SvelteComponentDev {

@ -1,9 +1,13 @@
import { element } from './dom';
import { raf } from './environment';
let stylesheet;
interface ExtendedDoc extends Document {
__svelte_stylesheet: CSSStyleSheet;
__svelte_rules: Record<string, true>;
}
const active_docs = new Set<ExtendedDoc>();
let active = 0;
let current_rules = {};
// https://github.com/darkskyapp/string-hash/blob/master/index.js
function hash(str: string) {
@ -25,14 +29,12 @@ export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b:
const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`;
const name = `__svelte_${hash(rule)}_${uid}`;
const doc = node.ownerDocument as ExtendedDoc;
active_docs.add(doc);
const stylesheet = doc.__svelte_stylesheet || (doc.__svelte_stylesheet = doc.head.appendChild(element('style') as HTMLStyleElement).sheet as CSSStyleSheet);
const current_rules = doc.__svelte_rules || (doc.__svelte_rules = {});
if (!current_rules[name]) {
if (!stylesheet) {
const style = element('style');
document.head.appendChild(style);
stylesheet = style.sheet;
}
current_rules[name] = true;
stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length);
}
@ -45,22 +47,28 @@ export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b:
}
export function delete_rule(node: Element & ElementCSSInlineStyle, name?: string) {
node.style.animation = (node.style.animation || '')
.split(', ')
.filter(name
? anim => anim.indexOf(name) < 0 // remove specific animation
: anim => anim.indexOf('__svelte') === -1 // remove all Svelte animations
)
.join(', ');
if (name && !--active) clear_rules();
const previous = (node.style.animation || '').split(', ');
const next = previous.filter(name
? anim => anim.indexOf(name) < 0 // remove specific animation
: anim => anim.indexOf('__svelte') === -1 // remove all Svelte animations
);
const deleted = previous.length - next.length;
if (deleted) {
node.style.animation = next.join(', ');
active -= deleted;
if (!active) clear_rules();
}
}
export function clear_rules() {
raf(() => {
if (active) return;
let i = stylesheet.cssRules.length;
while (i--) stylesheet.deleteRule(i);
current_rules = {};
active_docs.forEach(doc => {
const stylesheet = doc.__svelte_stylesheet;
let i = stylesheet.cssRules.length;
while (i--) stylesheet.deleteRule(i);
doc.__svelte_rules = {};
});
active_docs.clear();
});
}

@ -109,6 +109,13 @@ export function exclude_internal_props(props) {
return result;
}
export function compute_rest_props(props, keys) {
const rest = {};
keys = new Set(keys);
for (const k in props) if (!keys.has(k) && k[0] !== '$') rest[k] = props[k];
return rest;
}
export function once(fn) {
let ran = false;
return function(this: any, ...args) {

@ -0,0 +1,2 @@
<main>This should be thrown away</main>
<div>hello</div>

@ -0,0 +1 @@
<main>This should be thrown away</main>

@ -14,6 +14,7 @@ import {
space,
subscribe,
text,
validate_slots,
validate_store
} from "svelte/internal";
@ -114,6 +115,9 @@ function instance($$self, $$props, $$invalidate) {
if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<Component> was created with unknown prop '${key}'`);
});
let { $$slots = {}, $$scope } = $$props;
validate_slots("Component", $$slots, []);
$$self.$set = $$props => {
if ("prop" in $$props) $$subscribe_prop($$invalidate(0, prop = $$props.prop));
if ("alias" in $$props) $$invalidate(1, realName = $$props.alias);

@ -12,7 +12,8 @@ import {
safe_not_equal,
set_data_dev,
space,
text
text,
validate_slots
} from "svelte/internal";
const file = undefined;
@ -75,6 +76,9 @@ function instance($$self, $$props, $$invalidate) {
if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<Component> was created with unknown prop '${key}'`);
});
let { $$slots = {}, $$scope } = $$props;
validate_slots("Component", $$slots, []);
$$self.$set = $$props => {
if ("name" in $$props) $$invalidate(0, name = $$props.name);
};

@ -14,7 +14,8 @@ import {
set_data_dev,
space,
text,
validate_each_argument
validate_each_argument,
validate_slots
} from "svelte/internal";
const file = undefined;
@ -179,6 +180,9 @@ function instance($$self, $$props, $$invalidate) {
if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<Component> was created with unknown prop '${key}'`);
});
let { $$slots = {}, $$scope } = $$props;
validate_slots("Component", $$slots, []);
$$self.$set = $$props => {
if ("things" in $$props) $$invalidate(0, things = $$props.things);
if ("foo" in $$props) $$invalidate(1, foo = $$props.foo);

@ -14,7 +14,8 @@ import {
set_data_dev,
space,
text,
validate_each_argument
validate_each_argument,
validate_slots
} from "svelte/internal";
const file = undefined;
@ -171,6 +172,9 @@ function instance($$self, $$props, $$invalidate) {
if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<Component> was created with unknown prop '${key}'`);
});
let { $$slots = {}, $$scope } = $$props;
validate_slots("Component", $$slots, []);
$$self.$set = $$props => {
if ("things" in $$props) $$invalidate(0, things = $$props.things);
if ("foo" in $$props) $$invalidate(1, foo = $$props.foo);

@ -4,7 +4,8 @@ import {
dispatch_dev,
init,
noop,
safe_not_equal
safe_not_equal,
validate_slots
} from "svelte/internal";
const file = undefined;
@ -56,6 +57,8 @@ function instance($$self, $$props, $$invalidate) {
if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<Component> was created with unknown prop '${key}'`);
});
let { $$slots = {}, $$scope } = $$props;
validate_slots("Component", $$slots, []);
$$self.$capture_state = () => ({ obj, kobzol });
$$self.$inject_state = $$props => {

@ -11,7 +11,8 @@ import {
safe_not_equal,
space,
text,
validate_each_argument
validate_each_argument,
validate_slots
} from "svelte/internal";
const file = undefined;
@ -141,6 +142,8 @@ function instance($$self, $$props) {
if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<Component> was created with unknown prop '${key}'`);
});
let { $$slots = {}, $$scope } = $$props;
validate_slots("Component", $$slots, []);
return [];
}

@ -12,7 +12,8 @@ import {
safe_not_equal,
set_data_dev,
space,
text
text,
validate_slots
} from "svelte/internal";
const file = undefined;
@ -72,6 +73,9 @@ function instance($$self, $$props, $$invalidate) {
if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<Component> was created with unknown prop '${key}'`);
});
let { $$slots = {}, $$scope } = $$props;
validate_slots("Component", $$slots, []);
$$self.$set = $$props => {
if ("foo" in $$props) $$invalidate(0, foo = $$props.foo);
};

@ -11,7 +11,8 @@ import {
insert_dev,
loop_guard,
noop,
safe_not_equal
safe_not_equal,
validate_slots
} from "svelte/internal";
const { console: console_1 } = globals;
@ -110,6 +111,9 @@ function instance($$self, $$props, $$invalidate) {
if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console_1.warn(`<Component> was created with unknown prop '${key}'`);
});
let { $$slots = {}, $$scope } = $$props;
validate_slots("Component", $$slots, []);
function div_binding($$value) {
binding_callbacks[$$value ? "unshift" : "push"](() => {
$$invalidate(0, node = $$value);

@ -25,7 +25,10 @@
"name": "thePromise"
},
"value": null,
"error": "theError",
"error": {
"type": "Identifier",
"name": "theError"
},
"pending": {
"start": 19,
"end": 39,

@ -24,8 +24,14 @@
},
"name": "thePromise"
},
"value": "theValue",
"error": "theError",
"value": {
"type": "Identifier",
"name": "theValue"
},
"error": {
"type": "Identifier",
"name": "theError"
},
"pending": {
"start": 19,
"end": 39,

@ -1,6 +1,6 @@
{
"code": "invalid-self-placement",
"message": "<svelte:self> components can only exist inside if-blocks or each-blocks",
"message": "<svelte:self> components can only exist inside {#if} blocks, {#each} blocks, or slots passed to components",
"start": {
"line": 1,
"column": 1,

@ -115,7 +115,10 @@
"value": true,
"raw": "true"
},
"value": "f",
"value": {
"type": "Identifier",
"name": "f"
},
"error": null,
"pending": {
"start": 80,
@ -198,7 +201,10 @@
"value": true,
"raw": "true"
},
"value": "f",
"value": {
"type": "Identifier",
"name": "f"
},
"error": null,
"pending": {
"start": 123,

@ -0,0 +1,12 @@
<script>
export let a;
export function b() {}
export let c = 1;
$: length = Object.keys($$restProps).length;
$: values = Object.values($$restProps);
</script>
<div>Length: {length}</div>
<div>Values: {values.join(',')}</div>
<div {...$$restProps} />

@ -0,0 +1,54 @@
export default {
props: {
a: 3,
b: 4,
c: 5,
d: 6
},
html: `
<div>Length: 3</div>
<div>Values: 4,5,1</div>
<div d="4" e="5" foo="1"></div>
<button></button><button></button><button></button><button></button>
`,
async test({ assert, target, window, }) {
const [btn1, btn2, btn3, btn4] = target.querySelectorAll('button');
const clickEvent = new window.MouseEvent('click');
await btn1.dispatchEvent(clickEvent);
assert.htmlEqual(target.innerHTML, `
<div>Length: 3</div>
<div>Values: 4,5,1</div>
<div d="4" e="5" foo="1"></div>
<button></button><button></button><button></button><button></button>
`);
await btn2.dispatchEvent(clickEvent);
assert.htmlEqual(target.innerHTML, `
<div>Length: 3</div>
<div>Values: 34,5,1</div>
<div d="34" e="5" foo="1"></div>
<button></button><button></button><button></button><button></button>
`);
await btn3.dispatchEvent(clickEvent);
assert.htmlEqual(target.innerHTML, `
<div>Length: 3</div>
<div>Values: 34,5,31</div>
<div d="34" e="5" foo="31"></div>
<button></button><button></button><button></button><button></button>
`);
await btn4.dispatchEvent(clickEvent);
assert.htmlEqual(target.innerHTML, `
<div>Length: 4</div>
<div>Values: 34,5,31,2</div>
<div d="34" e="5" foo="31" bar="2"></div>
<button></button><button></button><button></button><button></button>
`);
}
};

@ -0,0 +1,25 @@
<script>
import App from './App.svelte';
let a = 1, b = 2, c = 3, d = 4, e = 5;
let f = { foo: 1 };
function updateProps() {
a = 31;
b = 32;
}
function updateRest() {
d = 34;
}
function updateSpread() {
f.foo = 31;
}
function updateSpread2() {
f.bar = 2;
}
</script>
<App {a} {b} {c} {d} {e} {...f} />
<button on:click={updateProps}></button>
<button on:click={updateRest}></button>
<button on:click={updateSpread}></button>
<button on:click={updateSpread2}></button>

@ -0,0 +1,13 @@
<script>
export let a;
export function b() {}
export let c = 1;
$: length = Object.keys($$restProps).length;
$: values = Object.values($$restProps);
</script>
<div>Length: {length}</div>
<div>Values: {values.join(',')}</div>
<div {...$$restProps} />
<div {...$$props} />

@ -0,0 +1,60 @@
export default {
props: {
a: 3,
b: 4,
c: 5,
d: 6
},
html: `
<div>Length: 3</div>
<div>Values: 4,5,1</div>
<div d="4" e="5" foo="1"></div>
<div a="1" b="2" c="3" d="4" e="5" foo="1"></div>
<button></button><button></button><button></button><button></button>
`,
async test({ assert, target, window, }) {
const [btn1, btn2, btn3, btn4] = target.querySelectorAll('button');
const clickEvent = new window.MouseEvent('click');
await btn1.dispatchEvent(clickEvent);
assert.htmlEqual(target.innerHTML, `
<div>Length: 3</div>
<div>Values: 4,5,1</div>
<div d="4" e="5" foo="1"></div>
<div a="31" b="32" c="3" d="4" e="5" foo="1"></div>
<button></button><button></button><button></button><button></button>
`);
await btn2.dispatchEvent(clickEvent);
assert.htmlEqual(target.innerHTML, `
<div>Length: 3</div>
<div>Values: 34,5,1</div>
<div d="34" e="5" foo="1"></div>
<div a="31" b="32" c="3" d="34" e="5" foo="1"></div>
<button></button><button></button><button></button><button></button>
`);
await btn3.dispatchEvent(clickEvent);
assert.htmlEqual(target.innerHTML, `
<div>Length: 3</div>
<div>Values: 34,5,31</div>
<div d="34" e="5" foo="31"></div>
<div a="31" b="32" c="3" d="34" e="5" foo="31"></div>
<button></button><button></button><button></button><button></button>
`);
await btn4.dispatchEvent(clickEvent);
assert.htmlEqual(target.innerHTML, `
<div>Length: 4</div>
<div>Values: 34,5,31,2</div>
<div d="34" e="5" foo="31" bar="2"></div>
<div a="31" b="32" c="3" d="34" e="5" foo="31" bar="2"></div>
<button></button><button></button><button></button><button></button>
`);
}
};

@ -0,0 +1,25 @@
<script>
import App from './App.svelte';
let a = 1, b = 2, c = 3, d = 4, e = 5;
let f = { foo: 1 };
function updateProps() {
a = 31;
b = 32;
}
function updateRest() {
d = 34;
}
function updateSpread() {
f.foo = 31;
}
function updateSpread2() {
f.bar = 2;
}
</script>
<App {a} {b} {c} {d} {e} {...f} />
<button on:click={updateProps}></button>
<button on:click={updateRest}></button>
<button on:click={updateSpread}></button>
<button on:click={updateSpread2}></button>

@ -0,0 +1,61 @@
export default {
props: {
thePromise: new Promise(resolve => {})
},
html: `
loading...
`,
async test({ assert, component, target }) {
await (component.thePromise = Promise.resolve([1, 2]));
assert.htmlEqual(
target.innerHTML,
`
<p>a: 1</p>
<p>b: 2</p>
`
);
await (component.thePromise = Promise.resolve([4, 5]));
assert.htmlEqual(
target.innerHTML,
`
<p>a: 4</p>
<p>b: 5</p>
`
);
try {
await (component.thePromise = Promise.reject(['a', [6, 7]]));
} catch (e) {
// do nothing
}
assert.htmlEqual(
target.innerHTML,
`
<p>c: a</p>
<p>d: 6</p>
<p>e: 7</p>
`
);
try {
await (component.thePromise = Promise.reject(['b', [8, 9]]));
} catch (e) {
// do nothing
}
assert.htmlEqual(
target.innerHTML,
`
<p>c: b</p>
<p>d: 8</p>
<p>e: 9</p>
`
);
}
};

@ -0,0 +1,14 @@
<script>
export let thePromise;
</script>
{#await thePromise}
loading...
{:then [ a, b ]}
<p>a: {a}</p>
<p>b: {b}</p>
{:catch [c, [d, e]]}
<p>c: {c}</p>
<p>d: {d}</p>
<p>e: {e}</p>
{/await}

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

Loading…
Cancel
Save