Merge branch 'master' into blog-anchors-2609

pull/2610/head
Rich Harris 5 years ago committed by GitHub
commit de31170a40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -54,7 +54,7 @@ npm run test -- -g transition
## svelte.dev
The source code for https://svelte.dev, including all the documentation, lives in the [site](site) directory. The site is built with [Sapper](https://sapper.svelte.technology). To develop locally:
The source code for https://svelte.dev, including all the documentation, lives in the [site](site) directory. The site is built with [Sapper](https://sapper.svelte.dev). To develop locally:
```bash
cd site

2
package-lock.json generated

@ -1,6 +1,6 @@
{
"name": "svelte",
"version": "3.0.0-beta.25",
"version": "3.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

@ -92,5 +92,6 @@
],
"sourceMap": true,
"instrument": true
}
},
"dependencies": {}
}

@ -92,6 +92,6 @@ We don't take this lightly: hopefully once you've experienced Svelte 3 you'll un
## Still to come
As grueling as this release has been, we're nowhere near finished. We have a ton of ideas for generating smarter, more compact code, and a long feature wish-list. [Sapper](https://sapper.svelte.technology), our Next.js-style app framework, is still in the middle of being updated to use Svelte 3. The [Svelte Native](https://svelte-native.technology/) community project, which allows you to write Android and iOS apps in Svelte, is making solid progress but deserves more complete support from core. We don't yet have the bounty of editor extensions, syntax highlighters, component kits, devtools and so on that other frameworks have, and we should fix that. We *really* want to add first-class TypeScript support.
As grueling as this release has been, we're nowhere near finished. We have a ton of ideas for generating smarter, more compact code, and a long feature wish-list. [Sapper](https://sapper.svelte.dev), our Next.js-style app framework, is still in the middle of being updated to use Svelte 3. The [Svelte Native](https://svelte-native.technology/) community project, which allows you to write Android and iOS apps in Svelte, is making solid progress but deserves more complete support from core. We don't yet have the bounty of editor extensions, syntax highlighters, component kits, devtools and so on that other frameworks have, and we should fix that. We *really* want to add first-class TypeScript support.
But in the meantime we think Svelte 3 is the best way to build web apps yet. Take an hour to go through the [tutorial](tutorial) and we hope to convince you of the same. Either way, we'd love to see you in our [Discord chatroom](https://discord.gg/yy75DKs) and on [GitHub](https://github.com/sveltejs/svelte) — everyone is welcome, especially you.

@ -2,7 +2,7 @@
title: Before we begin
---
> Temporary note: This document is a work-in-progress. Please forgive any missing or misleading parts, and don't be shy about asking for help in the [Discord chatroom](https://discord.gg/yy75DKs). The [tutorial](tutorial) is more complete; start there.
> Temporary note: This document is a work-in-progress. Please forgive any missing or misleading parts, and don't be shy about asking for help in the [Discord chatroom](https://discord.gg/yy75DKs). The [tutorial](tutorial) is more complete; start there.
This page contains detailed API reference documentation. It's intended to be a resource for people who already have some familiarity with Svelte.

@ -56,6 +56,8 @@ To change component state and trigger a re-render, just assign to a locally decl
Update expressions (`count += 1`) and property assignments (`obj.x = y`) have the same effect.
Because Svelte's reactivity is based on assignments, using array methods like `.push()` and `.splice()` won't automatically trigger updates. Options for getting around this can be found in the [tutorial](tutorial/updating-arrays-and-objects).
```html
<script>
let count = 0;

@ -366,7 +366,13 @@ Components can emit events using [createEventDispatcher](docs#createEventDispatc
<SomeComponent on:whatever={handler}/>
```
---
As with DOM events, if the `on:` directive is used without a value, the component will *forward* the event, meaning that a consumer of the component can listen for it.
```html
<SomeComponent on:whatever/>
```
### Element bindings
@ -749,6 +755,8 @@ The `in:` and `out:` directives are not bidirectional. An in transition will con
{/if}
```
> By default intro transitions will not play on first render. You can modify this behaviour by setting `intro: true` when you [create a component](docs#Client-side_component_API).
#### Transition parameters
---

@ -176,8 +176,39 @@ Retrieves the context that belongs to the closest parent component with the spec
#### `createEventDispatcher`
TODO
```js
dispatch: ((name: string, detail?: any) => void) = createEventDispatcher();
```
---
Creates an event dispatcher that can be used to dispatch [component events](docs#Component_events). Event dispatchers are functions that can take two arguments: `name` and `detail`.
Component events created with `createEventDispatcher` create a [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent). These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture) and are not cancellable with `event.preventDefault()`. The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail) property and can contain any type of data.
```html
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
</script>
<button on:click="{() => dispatch('notify', 'detail value')}">Fire Event</button>
```
---
Events dispatched from child components can be listened to in their parent. Any data provided when the event was dispatched is available on the `detail` property of the event object.
```html
<script>
function callbackFunction(event) {
console.log(`Notify fired! Detail: ${event.detail}`)
}
</script>
<Child on:notify="{callbackFunction}"/>
```
### `svelte/store`
@ -475,21 +506,81 @@ TODO
* fade, fly, slide, scale, draw
* crossfade...
### `svelte/animation`
### `svelte/animate`
TODO
The `svelte/animate` module exports one function for use with svelte [animations](docs#Animations).
#### `flip`
```sv
animate:flip={params}
```
The `flip` function calculates the start and end position of an element and animates between them, translating the `x` and `y` values. `flip` stands for [First, Last, Invert, Play](https://aerotwist.com/blog/flip-your-animations/).
`flip` accepts the following parameters:
* `delay` (`number`, default 0) — milliseconds before starting
* `duration` (`number` | `function`, default `d => Math.sqrt(d) * 120`) — see below
* `easing` (`function`, default [`cubicOut`](docs#cubicOut)) — an [easing function](docs#svelte_easing)
`duration` can be be provided as either:
- a `number`, in milliseconds.
- a function, `distance: number => duration: number`, receiving the distance the element will travel in pixels and returning the duration in milliseconds. This allows you to assign a duration that is relative to the distance travelled by each element.
---
You can see a full example on the [animations tutorial](tutorial/animate)
```html
<script>
import { flip } from 'svelte/animate';
import { quintOut } from 'svelte/easing';
let list = [1, 2, 3];
</script>
{#each list as n (n)}
<div animate:flip="{{delay: 250, duration: 250, easing: quintOut}}">
{n}
</div>
{/each}
```
* TODO this doesn't even exist yet
TODO
### `svelte/easing`
* TODO could have nice little interactive widgets showing the different functions, maybe
### `svelte/register`
TODO
To render Svelte components in Node.js without bundling, use `require('svelte/register')`. After that, you can use `require` to include any `.svelte` file.
```js
require('svelte/register');
const App = require('./App.svelte').default;
...
const { html, css, head } = App.render({ answer: 42 });
```
> The `.default` is necessary because we're converting from native JavaScript modules to the CommonJS modules recognised by Node. Note that if your component imports JavaScript modules, they will fail to load in Node and you will need to use a bundler instead.
To set compile options, or to use a custom file extension, call the `register` hook as a function:
```js
require('svelte/register')({
extensions: ['.customextension'], // defaults to ['.html', '.svelte']
preserveComments: true
});
```
### Client-side component API
@ -500,8 +591,6 @@ TODO
const component = new Component(options)
```
---
A client-side component — that is, a component compiled with `generate: 'dom'` (or the `generate` option left unspecified) is a JavaScript class.
```js

@ -29,4 +29,4 @@ Each tutorial chapter will have a 'Show me' button that you can click if you get
## Understanding components
In Svelte, an application is composed from one or more *components*. A component is a reusable self-contained block of code that encapsulates HTML, CSS and JavaScript that belong together, written into a `.svelte` file. The 'hello world' example on the right is a simple component.
In Svelte, an application is composed from one or more *components*. A component is a reusable self-contained block of code that encapsulates HTML, CSS and JavaScript that belong together, written into a `.svelte` file. The 'hello world' example in the code editor is a simple component.

@ -12,4 +12,4 @@ In Svelte, you do this with the special `{@html ...}` tag:
<p>{@html string}</p>
```
> Svelte doesn't perform any sanitization of the data before it gets inserted into the DOM. In other words, it's critical that you manually escape HTML that comes from sources you don't trust, otherwise you risk exposing your users to XSS attacks.
> Svelte doesn't perform any sanitization of the expression inside `{@html ...}` before it gets inserted into the DOM. In other words, if you use this feature it's critical that you manually escape HTML that comes from sources you don't trust, otherwise you risk exposing your users to XSS attacks.

@ -39,6 +39,8 @@ It starts to get a bit boilerplatey though, especially if your component subscri
<h1>The count is {$count}</h1>
```
> Auto-subscription only works with store variables that are declared (or imported) at the top-level scope of a component.
You're not limited to using `$count` inside the markup, either — you can use it anywhere in the `<script>` as well, such as in event handlers or reactive declarations.
> Any name beginning with `$` is assumed to refer to a store value. It's effectively a reserved character — Svelte will prevent you from declaring your own variables with a `$` prefix.

@ -6,6 +6,6 @@ You've now finished the Svelte tutorial and are ready to start building apps. Yo
To get set up in your local development environment, check out [the quickstart guide](blog/the-easiest-way-to-get-started).
If you're looking for a more expansive framework that includes routing, server-side rendering and everything else, take a look at [Sapper](https://sapper.svelte.technology).
If you're looking for a more expansive framework that includes routing, server-side rendering and everything else, take a look at [Sapper](https://sapper.svelte.dev).
Most importantly: since you're now a member of the Svelte community, you should [join our friendly Discord chatroom](https://discord.gg/yy75DKs). That's where you'll find fellow Svelte users, and it's where we plan the future of the framework.

1055
site/package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -4,8 +4,7 @@
"description": "Docs and examples for Svelte",
"scripts": {
"dev": "sapper dev",
"sapper": "sapper build --legacy && npm run update_shimport",
"update_shimport": "cp node_modules/shimport/index.js __sapper__/build/client/shimport@0.0.14.js",
"sapper": "sapper build --legacy",
"update": "node scripts/update_template.js && node scripts/get-contributors.js",
"start": "node __sapper__/build",
"cy:run": "cypress run",
@ -38,6 +37,7 @@
"@babel/preset-env": "^7.3.1",
"@babel/runtime": "^7.3.1",
"@sindresorhus/slugify": "^0.9.1",
"@sveltejs/site-kit": "^1.0.3",
"@sveltejs/svelte-repl": "0.0.10",
"chokidar": "^2.1.2",
"degit": "^2.1.3",
@ -55,9 +55,8 @@
"rollup-plugin-replace": "^2.1.0",
"rollup-plugin-svelte": "^5.0.3",
"rollup-plugin-terser": "^4.0.4",
"sapper": "^0.26.0-alpha.12",
"shimport": "0.0.16",
"svelte": "^3.0.0-beta.28"
"sapper": "^0.26.0",
"svelte": "^3.1.0"
},
"engines": {
"node": ">=10.0.0"

@ -1,3 +1,4 @@
import '@sveltejs/site-kit/base.css';
import * as sapper from '@sapper/app';
sapper.start({

@ -1,39 +0,0 @@
<!--
-----------------------------------------------
svg icon
- https://github.com/jacobmischka/svelte-feather-icon
- https://feathericons.com/
-----------------------------------------------
-->
<script>
export let clas = '';
export let name;
export let size = 20;
</script>
<!-- style="--color: {color ? color : 'currentColor'}" -->
<svg class="{'icon ' + clas}" width={size} height={size}>
<use xlink:href='#{name}' />
</svg>
<style>
.icon {
position: relative;
/* width: 1.2em;
height: 1.2em;
top: -0.123em; */
overflow: hidden;
vertical-align: middle;
-o-object-fit: contain;
object-fit: contain;
-webkit-transform-origin: center center;
transform-origin: center center;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
fill: none;
}
</style>

Before

Width:  |  Height:  |  Size: 828 B

@ -1,115 +0,0 @@
<!--
-----------------------------------------------
inline-svg sprite
- common used svg-stuff (feather-icons)
- advantage of css-styling
- https://github.com/jacobmischka/svelte-feather-icon
- https://feathericons.com/
- if required we can split out app-controls to REPL only
-----------------------------------------------
-->
<svg style='display:none'>
<symbol id='arrow-left' class='icon' viewBox='0 0 24 24'>
<line x1='19' y1='12' x2='5' y2='12' />
<polyline points='12 19 5 12 12 5' />
</symbol>
<symbol id='arrow-right' class='icon' viewBox='0 0 24 24'>
<line x1='5' y1='12' x2='19' y2='12' />
<polyline points='12 5 19 12 12 19' />
</symbol>
<symbol id='arrow-up' class='icon' viewBox='0 0 24 24'>
<line x1='12' y1='19' x2='12' y2='5' />
<polyline points='5 12 12 5 19 12' />
</symbol>
<symbol id='arrow-down' class='icon' viewBox='0 0 24 24'>
<line x1='12' y1='5' x2='12' y2='19' />
<polyline points='19 12 12 19 5 12' />
</symbol>
<symbol id='check' class='icon' viewBox='0 0 24 24'>
<polyline points='20 6 9 17 4 12' />
</symbol>
<symbol id='close' class='icon' viewBox='0 0 24 24'>
<line x1='18' y1='6' x2='6' y2='18' />
<line x1='6' y1='6' x2='18' y2='18' />
</symbol>
<symbol id='download' class='icon' viewBox='0 0 24 24'>
<path d='M21 15V19A2 2 0 0 1 19 21H5A2 2 0 0 1 3 19V15' />
<polyline points='7 10 12 15 17 10' />
<line x1='12' y1='15' x2='12' y2='3' />
</symbol>
<symbol id='edit' class='icon' viewBox='0 0 24 24'>
<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' />
</symbol>
<symbol id='github' class='icon' viewBox='0 0 24 24'>
<path d='M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22' />
</symbol>
<symbol id='git-branch' class='icon' viewBox='0 0 24 24'>
<line x1='6' y1='3' x2='6' y2='15' />
<circle cx='18' cy='6' r='3' />
<circle cx='6' cy='18' r='3' />
<path d='M18 9a9 9 0 0 1-9 9' />
</symbol>
<symbol id='log-in' class='icon' viewBox='0 0 24 24'>
<path d='M15 3H19A2 2 0 0 1 21 5V19A2 2 0 0 1 19 21H15' />
<polyline points='10 17 15 12 10 7' />
<line x1='15' y1='12' x2='3' y2='12' />
</symbol>
<symbol id='maximize' class='icon' viewBox='0 0 24 24'>
<path d='M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3' />
</symbol>
<symbol id='maximize-2' class='icon' viewBox='0 0 24 24'>
<polyline points='15 3 21 3 21 9' />
<polyline points='9 21 3 21 3 15' />
<line x1='21' y1='3' x2='14' y2='10' />
<line x1='3' y1='21' x2='10' y2='14' />
</symbol>
<symbol id='menu' class='icon' viewBox='0 0 24 24'>
<line x1='3' y1='12' x2='21' y2='12' />
<line x1='3' y1='6' x2='21' y2='6' />
<line x1='3' y1='18' x2='21' y2='18' />
</symbol>
<symbol id='message-square' class='icon' viewBox='0 0 24 24'>
<path d='M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z' />
</symbol>
<symbol id='minus' class='icon' viewBox='0 0 24 24'>
<line x1='5' y1='12' x2='19' y2='12' />
</symbol>
<symbol id='plus' class='icon' viewBox='0 0 24 24'>
<line x1='12' y1='5' x2='12' y2='19' />
<line x1='5' y1='12' x2='19' y2='12' />
</symbol>
<symbol id='save' class='icon' viewBox='0 0 24 24'>
<path d='M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z' />
<polyline points='17 21 17 13 7 13 7 21' />
<polyline points='7 3 7 8 15 8' />
</symbol>
<symbol id="link" class="icon" viewBox="0 0 24 24">
<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"/>
</symbol>
<symbol id="chevron" class="icon" viewBox="0 0 24 24">
<path d="M2,7 L12,17 L20,7"/>
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 3.9 KiB

@ -1,277 +0,0 @@
<script>
import { onMount } from 'svelte';
import Icon from './Icon.svelte';
import { page } from '@sapper/app';
export let segment;
let open = false;
let visible = true;
// hide nav whenever we navigate
page.subscribe(() => {
open = false;
});
// TODO remove this post-https://github.com/sveltejs/svelte/issues/1914
let ul;
onMount(() => {
function handler(event) {
if (!open) {
event.preventDefault();
event.stopPropagation();
open = true;
}
}
ul.addEventListener('touchstart', handler, {
capture: true
});
return () => {
ul.removeEventListener('touchstart', handler, {
capture: true
});
};
});
// Prevents navbar to show/hide when clicking in docs sidebar
let hash_changed = false;
function handle_hashchange() {
hash_changed = true;
}
let last_scroll = 0;
function handle_scroll() {
const scroll = window.pageYOffset;
if (!hash_changed) {
visible = (scroll < 50 || scroll < last_scroll);
}
last_scroll = scroll;
hash_changed = false;
}
</script>
<style>
header {
position: fixed;
display: flex;
align-items: center;
justify-content: space-between;
width: 100vw;
height: var(--nav-h);
padding: 0 var(--side-nav);
margin: 0 auto;
background-color: white;
box-shadow: 0 -0.4rem 0.9rem 0.2rem rgba(0,0,0,.5);
font-family: var(--font);
z-index: 100;
user-select: none;
transform: translate(0,calc(-100% - 1rem));
transition: transform 0.2s;
}
header.visible {
transform: none;
}
nav {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: var(--nav-h);
padding: 0 var(--side-nav) 0 var(--side-nav);
display: flex;
align-items: center;
justify-content: space-between;
background-color: transparent;
transform: none;
transition: none;
box-shadow: none;
}
.primary {
list-style: none;
font-family: var(--font);
margin: 0;
line-height: 1;
}
li {
display: block;
display: none;
}
li.active {
display: block;
}
ul {
position: relative;
padding: 0 3rem 0 0;
background: url(/icons/chevron.svg) calc(100% - 1em) 0.05em no-repeat;
background-size: 1em 1em;
}
ul::after {
/* prevent clicks from registering if nav is closed */
position: absolute;
content: '';
width: 100%;
height: 100%;
left: 0;
top: 0;
}
ul.open {
padding: 0 0 1em 0;
background: white;
border-left: 1px solid #eee;
border-right: 1px solid #eee;
border-bottom: 1px solid #eee;
border-radius: 0 0 var(--border-r) var(--border-r);
align-self: start;
}
ul.open li {
display: block;
text-align: right
}
ul.open::after {
display: none;
}
ul li a {
font-size: var(--h5);
padding: 0 .8rem;
}
ul.open li a {
padding: 1.5rem 3.7rem 1.5rem 4rem;
display: block;
}
ul.open li:first-child a {
padding-top: 2.3rem;
}
.primary :global(svg) {
width: 2rem;
height: 2rem;
}
.home {
position: relative;
top: -.1rem;
width: 18rem;
height: 4.2rem;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
background: url(/svelte-logo-horizontal.svg) 0 50% no-repeat;
background-size: auto 100%;
/* z-index: 11; */
}
.active {
color: var(--prime)
}
.modal-background {
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
background-color: rgba(255, 255, 255, 0.9);
}
a {
color: inherit;
border-bottom: none;
transition: none;
}
li:not(.active) a:hover {
color: var(--flash);
}
@media (min-width: 840px) {
ul {
padding: 0;
background: none;
}
ul.open {
padding: 0;
background: white;
border: none;
align-self: initial;
}
ul.open li {
display: inline;
text-align: left;
}
ul.open li a {
font-size: var(--h5);
padding: 0 .8rem;
display: inline;
}
ul::after {
display: none;
}
li {
display: inline !important;
}
.hide-if-desktop {
display: none !important;
}
}
</style>
<svelte:window on:hashchange={handle_hashchange} on:scroll={handle_scroll} />
<header class:visible="{visible || open}">
<nav>
<a rel="prefetch" href='.' class="home" title='Homepage'></a>
{#if open}
<div class="modal-background hide-if-desktop" on:click="{() => open = false}"></div>
{/if}
<ul
bind:this={ul}
class="primary"
class:open
on:mouseenter="{() => open = true}"
on:mouseleave="{() => open = false}"
>
<li class="hide-if-desktop" class:active="{!segment}"><a rel="prefetch" href=".">Home</a></li>
<li class:active="{segment === 'tutorial'}"><a rel="prefetch" href="tutorial">Tutorial</a></li>
<li class:active="{segment === 'docs'}"><a rel="prefetch" href="docs">API Docs</a></li>
<li class:active="{segment === 'examples'}"><a rel="prefetch" href="examples">Examples</a></li>
<li class:active="{segment === 'repl'}"><a rel="prefetch" href="repl">REPL</a></li>
<li class:active="{segment === 'blog'}"><a rel="prefetch" href="blog">Blog</a></li>
<li><a href="https://sapper.svelte.technology">Sapper</a></li>
<li>
<a href="https://discord.gg/yy75DKs" title="Discord Chat">
<Icon name="message-square" />
</a>
</li>
<li>
<a href="https://github.com/sveltejs/svelte" title="Github Repo">
<Icon name="github" />
</a>
</li>
</ul>
</nav>
</header>

@ -1,28 +0,0 @@
<!--
-----------------------------------------------
svg svelte-logo 1.0
- style doesn't like var(--xxx)???
-----------------------------------------------
-->
<script>
export let outer = '';
export let inner = '';
export let size;
</script>
<svg class='logo' viewBox='0 0 103 124' width={size} height={size}>
<path style='{outer === "none" ? "fill:none; stroke:none;" : outer || "fill:var(--prime)"}' d='M96.33,20.61C85.38,4.93,63.74.28,48.09,10.25L20.61,27.77A31.46,31.46,0,0,0,6.37,48.88,33.22,33.22,0,0,0,9.64,70.2,31.52,31.52,0,0,0,4.93,82a33.61,33.61,0,0,0,5.73,25.41c11,15.68,32.6,20.33,48.25,10.36l27.48-17.52a31.48,31.48,0,0,0,14.24-21.11A33.22,33.22,0,0,0,97.36,57.8,31.52,31.52,0,0,0,102.07,46a33.57,33.57,0,0,0-5.74-25.41' />
<path style='{(inner === "none") ? "fill:none; stroke:none;" : inner || "fill:white"}' d='M45.41,108.86A21.81,21.81,0,0,1,22,100.18,20.2,20.2,0,0,1,18.53,84.9a19,19,0,0,1,.65-2.57l.52-1.58,1.41,1a35.32,35.32,0,0,0,10.75,5.37l1,.31-.1,1a6.2,6.2,0,0,0,1.11,4.08A6.57,6.57,0,0,0,41,95.19a6,6,0,0,0,1.68-.74L70.11,76.94a5.76,5.76,0,0,0,2.59-3.83,6.09,6.09,0,0,0-1-4.6,6.58,6.58,0,0,0-7.06-2.62,6.21,6.21,0,0,0-1.69.74L52.43,73.31a19.88,19.88,0,0,1-5.58,2.45,21.82,21.82,0,0,1-23.43-8.68A20.2,20.2,0,0,1,20,51.8a19,19,0,0,1,8.56-12.7L56,21.59a19.88,19.88,0,0,1,5.58-2.45A21.81,21.81,0,0,1,85,27.82,20.2,20.2,0,0,1,88.47,43.1a19,19,0,0,1-.65,2.57l-.52,1.58-1.41-1a35.32,35.32,0,0,0-10.75-5.37l-1-.31.1-1a6.2,6.2,0,0,0-1.11-4.08,6.57,6.57,0,0,0-7.06-2.62,6,6,0,0,0-1.68.74L36.89,51.06a5.71,5.71,0,0,0-2.58,3.83,6,6,0,0,0,1,4.6,6.58,6.58,0,0,0,7.06,2.62,6.21,6.21,0,0,0,1.69-.74l10.48-6.68a19.88,19.88,0,0,1,5.58-2.45,21.82,21.82,0,0,1,23.43,8.68A20.2,20.2,0,0,1,87,76.2a19,19,0,0,1-8.56,12.7L51,106.41a19.88,19.88,0,0,1-5.58,2.45' />
</svg>
<style>
.logo {
position: relative;
vertical-align: middle;
stroke-miterlimit: 10;
stroke-width: 3.5;
stroke-linecap: round;
stroke-linejoin: round;
}
</style>

@ -1,68 +0,0 @@
<script>
export let style;
let show = false;
$: if (typeof document !== 'undefined') {
if (show) document.body.classList.add('css-debug')
else document.body.classList.remove('css-debug')
}
</script>
<!--
-----------------------------------------------
simple css-debug
-----------------------------------------------
-->
<label {style}>
<input type="checkbox" bind:checked={show}> grid
</label>
{#if show}
<div class='guide horizontal' style='top: calc(var(--nav-h) + var(--top-offset))' />
<div class='guide vertical' style='left: var(--side-page)' />
<div class='guide vertical' style='right: var(--side-page)' />
<div class='guide vertical' style='left: var(--side-nav)' />
<div class='guide vertical' style='right: var(--side-nav)' />
{/if}
<style>
label {
position: fixed;
padding: 0.3rem 1rem;
font-size: 1.2rem;
cursor: pointer;
user-select: none;
opacity: 0.5;
font: 300 1rem/1.7 var(--font-ui);
z-index: 30;
}
label:hover {
opacity: 1
}
input {
display: none
}
.guide {
position: fixed;
opacity: .5;
z-index: 30
}
.horizontal {
width: 100%;
height: 0
}
.vertical {
width: 0;
height: 100vh
}
:global(.css-debug *) {
outline: 1px solid rgba(73, 177, 238, 0.25);
}
</style>

@ -1,28 +0,0 @@
<!--
-----------------------------------------------
svg svelte-isometry 1.0
- first simple try to simplify iso-grafics
-----------------------------------------------
-->
<script>
export let style = '';
export let size = '';
</script>
<svg class='svelte-iso' viewBox='0 0 128 128' width={size} height={size}>
<polygon {style} points="107.94 92 107.94 36 64.01 8 20.06 35.99 20.06 92.01 64 120 107.94 92" />
<polyline {style} points="107.94 36 64.01 64 64 120" />
<line {style} x1="64.01" y1="64" x2="20.06" y2="35.99" />
</svg>
<style>
.svelte-iso {
position: relative;
vertical-align: middle;
stroke-miterlimit: 10;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}
</style>

@ -1,81 +0,0 @@
<!--
NOTE
from time to time <input type="color"> is crashing on chrome!
no idea why?
even with all extensions off
-->
{#if color}
<input ref:prop class="color" on:input="change(this)" type="color" name={color} /> {/if}
{#if text}
<input ref:prop on:input="change(this)" type="text" name={text} />
{/if}
<style>
input,
input:active,
input:focus {
border: none;
outline: none;
cursor: pointer;
}
input[type=text] {
border: .1rem solid var(--text);
padding: .8rem 1.4rem;
font: 300 var(--code-fs)/1.7 var(--font-mono);
color: var(--second);
text-indent: 0;
transition: all .2s var(--out-back);
}
input[type=text]:focus {
border-color: var(--flash);
color: var(--flash);
text-indent: .8rem;
}
.color {
position: relative;
top: 0;
width: 100%;
height: 100%;
}
/* input-color-reset */
::-webkit-color-swatch {
border: none
}
::-webkit-color-swatch-wrapper {
padding: 0
}
::-moz-color-swatch,
::-moz-focus-inner {
border: none
}
::-moz-focus-inner {
padding: 0
}
</style>
<script>
import CustomProps from '../utils/css-custom-properties.js';
export default {
oncreate() {
this.cssprop = new CustomProps();
let prop = this.refs.prop;
prop.value = this.cssprop.get(prop.name);
},
methods: {
change(prop) {
return this.cssprop.set(prop.name, prop.value)
}
}
};
</script>

@ -1,49 +0,0 @@
<button class='toast' on:click='reload()'>
Site has been updated — tap to reload
</button>
<style>
.toast {
position: fixed;
left: 0;
bottom: 0;
margin: 0;
border-radius: 0;
width: 100%;
background-color: var(--prime);
cursor: pointer;
color: white;
padding: 3.2rem 4rem;
text-align: left;
font: 300 var(--h6) var(--font-ui);
z-index: 99;
animation: slide-up 0.4s ease-out;
}
@keyframes slide-up {
0% {
transform: translate(0, 100%);
}
100% {
transform: translate(0, 0);
}
}
</style>
<script>
export default {
methods: {
reload() {
window.location.reload();
}
},
setup(Toast) {
Toast.show = () => {
const target = document.createDocumentFragment();
new Toast({ target });
document.body.appendChild(target);
Toast.show = () => {};
};
}
};
</script>

@ -0,0 +1,52 @@
<script>
import { Section } from '@sveltejs/site-kit';
import IntersectionObserver from '../../components/IntersectionObserver.svelte';
import ReplWidget from '../../components/Repl/ReplWidget.svelte';
export let id;
</script>
<style>
.example {
width: 100%;
}
.example :global(a) {
color: inherit;
}
.example > :global(p) {
margin: 4.4rem 2.4rem 2.4rem 0;
}
.repl-container {
width: 100%;
height: 420px;
border-radius: var(--border-r);
overflow: hidden;
}
@media (min-width: 920px) {
.example {
display: grid;
grid-template-columns: 1fr 3fr;
grid-gap: 0.5em;
align-items: start;
}
}
</style>
<Section>
<div class="example">
<slot></slot>
<div class="repl-container">
<IntersectionObserver once let:intersecting top={400}>
{#if intersecting}
<!-- <Lazy this={loadReplWidget} example={id}/> -->
<ReplWidget example={id}/>
{/if}
</IntersectionObserver>
</div>
</div>
</Section>

@ -1,19 +1,37 @@
<script>
import { page, preloading } from '@sapper/app';
import InlineSvg from '../components/InlineSvg.svelte';
import { stores } from '@sapper/app';
import { Icon, Icons, Nav, NavItem } from '@sveltejs/site-kit';
import PreloadingIndicator from '../components/PreloadingIndicator.svelte';
import Nav from '../components/TopNav.svelte';
const { page, preloading } = stores();
export let segment;
</script>
<Icons/>
{#if $preloading}
<PreloadingIndicator/>
{/if}
<InlineSvg />
{#if $page.path !== '/repl/embed'}
<Nav {segment}/>
<Nav {segment} {page} logo="svelte-logo-horizontal.svg">
<NavItem segment="tutorial">Tutorial</NavItem>
<NavItem segment="docs">API</NavItem>
<NavItem segment="examples">Examples</NavItem>
<NavItem segment="repl">REPL</NavItem>
<NavItem segment="blog">Blog</NavItem>
<NavItem external="https://sapper.svelte.dev">Sapper</NavItem>
<NavItem external="https://discord.gg/yy75DKs" title="Discord Chat">
<Icon name="message-square"/>
</NavItem>
<NavItem external="https://github.com/sveltejs/svelte" title="GitHub Repo">
<Icon name="github"/>
</NavItem>
</Nav>
{/if}
<main>

@ -1,5 +1,6 @@
import fs from 'fs';
import path from 'path';
import { extract_frontmatter, langs, link_renderer } from '@sveltejs/site-kit/utils/markdown.js';
import marked from 'marked';
import PrismJS from 'prismjs';
import 'prismjs/components/prism-bash';

@ -48,19 +48,12 @@
a {
position: relative;
opacity: 0.75;
transition: opacity 0.2s;
transition: color 0.2s;
border-bottom: none;
padding: 0;
color: var(--second);
}
@media (min-width: 832px) {
a {
color: white;
}
}
.section {
display: block;
padding: 0 0 .8rem 0;
@ -78,22 +71,33 @@
}
.section:hover,
.subsection:hover {
.subsection:hover,
.active {
color: var(--flash);
opacity: 1
}
.subsection[data-level="4"] {
padding-left: 1.2rem;
}
.active { opacity: 1 }
.icon-container {
position: absolute;
top: -.2rem;
right: 2.4rem;
}
@media (min-width: 832px) {
a {
color: var(--sidebar-text);
}
a:hover,
.section:hover,
.subsection:hover,
.active {
color: white
}
}
</style>
<ul

@ -1,8 +1,8 @@
import fs from 'fs';
import path from 'path';
import { SLUG_PRESERVE_UNICODE } from '../../../config';
import { extract_frontmatter, extract_metadata, langs, link_renderer } from '../../utils/markdown.js';
import { makeSessionSlugProcessor } from '../../utils/slug';
import { SLUG_PRESERVE_UNICODE, SLUG_SEPARATOR } from '../../../config';
import { extract_frontmatter, extract_metadata, langs, link_renderer } from '@sveltejs/site-kit/utils/markdown.js';
import { make_session_slug_processor } from '@sveltejs/site-kit/utils/slug';
import marked from 'marked';
import PrismJS from 'prismjs';
import 'prismjs/components/prism-bash';
@ -38,7 +38,10 @@ const blockTypes = [
];
export default function() {
const makeSlug = makeSessionSlugProcessor(SLUG_PRESERVE_UNICODE);
const makeSlug = make_session_slug_processor({
preserve_unicode: SLUG_PRESERVE_UNICODE,
separator: SLUG_SEPARATOR
});
return fs
.readdirSync(`content/docs`)

@ -6,359 +6,11 @@
</script>
<script>
import { onMount } from 'svelte';
import GuideContents from './_GuideContents.svelte';
import Icon from '../../components/Icon.svelte';
import { getFragment } from '../../utils/navigation';
import { Docs } from '@sveltejs/site-kit'
export let sections;
let active_section;
let container;
let aside;
let show_contents = false;
onMount(() => {
// don't update `active_section` for headings above level 4, see _sections.js
const anchors = container.querySelectorAll('[id]:not([data-scrollignore])');
let positions;
const onresize = () => {
const { top } = container.getBoundingClientRect();
positions = [].map.call(anchors, anchor => {
return anchor.getBoundingClientRect().top - top;
});
}
let last_id = getFragment();
const onscroll = () => {
const top = -window.scrollY;
let i = anchors.length;
while (i--) {
if (positions[i] + top < 40) {
const anchor = anchors[i];
const { id } = anchor;
if (id !== last_id) {
active_section = id;
last_id = id;
}
return;
}
}
};
window.addEventListener('scroll', onscroll, true);
window.addEventListener('resize', onresize, true);
// wait for fonts to load...
const timeouts = [
setTimeout(onresize, 1000),
setTimeout(onscroll, 5000)
];
onresize();
onscroll();
return () => {
window.removeEventListener('scroll', onscroll, true);
window.removeEventListener('resize', onresize, true);
timeouts.forEach(timeout => clearTimeout(timeout));
};
});
</script>
<style>
aside {
position: fixed;
background-color: white;
left: 0.8rem;
bottom: 0.8rem;
width: 2em;
height: 2em;
overflow: hidden;
border: 1px solid #eee;
box-shadow: 1px 1px 6px rgba(0,0,0,0.1);
transition: width 0.2s, height 0.2s;
}
aside button {
position: absolute;
bottom: 0;
left: 0;
width: 3.4rem;
height: 3.4rem;
}
aside.open {
width: calc(100vw - 3rem);
height: calc(100vh - var(--nav-h));
}
aside.open::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: calc(100% - 2rem);
height: 2em;
background: linear-gradient(to top, rgba(255,255,255,0) 0%, rgba(255,255,255,0.7) 50%, rgba(255,255,255,1) 100%);
pointer-events: none;
z-index: 2;
}
aside::after {
content: '';
position: absolute;
left: 0;
bottom: 1.9em;
width: calc(100% - 2rem);
height: 2em;
background: linear-gradient(to bottom, rgba(255,255,255,0) 0%, rgba(255,255,255,0.7) 50%, rgba(255,255,255,1) 100%);
pointer-events: none;
}
.sidebar {
position: absolute;
font-family: var(--font);
overflow-y: auto;
width: 100%;
height: 100%;
padding: 4em 1.6rem 2em 3.2rem;
bottom: 2em;
}
.content {
width: 100%;
margin: 0;
padding: var(--top-offset) var(--side-nav);
tab-size: 2;
-moz-tab-size: 2;
}
@media (min-width: 832px) { /* can't use vars in @media :( */
aside {
display: block;
width: var(--sidebar-w);
height: 100vh;
top: 0;
left: 0;
overflow: hidden;
box-shadow: none;
border: none;
overflow: hidden;
background-color: var(--second);
color: white;
}
aside.open::before {
display: none;
}
aside::after {
content: '';
bottom: 0;
height: var(--top-offset);
background: linear-gradient(to bottom, rgba(103,103,120,0) 0%, rgba(103,103,120,0.7) 50%, rgba(103,103,120,1) 100%);
}
aside button {
display: none;
}
.sidebar {
padding: var(--top-offset) 0 6.4rem 3.2rem;
font-family: var(--font);
overflow-y: auto;
height: 100%;
bottom: auto;
width: 100%;
}
.content {
padding-left: calc(var(--sidebar-w) + var(--side-nav));
}
.content :global(.side-by-side) {
display: grid;
grid-template-columns: calc(50% - 0.5em) calc(50% - 0.5em);
grid-gap: 1em;
}
}
.content h2 {
margin-top: 8rem;
padding: 2rem 1.6rem 4rem 0.2rem;
border-top: var(--border-w) solid #6767785b; /* based on --second */
color: var(--text);
line-height: 1;
font-size: var(--h3);
letter-spacing: .05em;
text-transform: uppercase;
}
.content section:first-of-type > h2 {
margin-top: 0;
}
.content :global(h4) {
margin: 2em 0 1em 0;
}
.content :global(.offset-anchor) {
position: relative;
display: block;
top: calc(-1 * (var(--nav-h) + var(--top-offset) - 1rem));
width: 0;
height: 0;
}
.content :global(.anchor) {
position: absolute;
display: block;
background: url(/icons/link.svg) 0 50% no-repeat;
background-size: 1em 1em;
width: 1.4em;
height: 1em;
left: -1.3em;
opacity: 0;
transition: opacity 0.2s;
border: none !important; /* TODO get rid of linkify */
}
@media (min-width: 768px) {
.content :global(h2):hover :global(.anchor),
.content :global(h3):hover :global(.anchor),
.content :global(h4):hover :global(.anchor),
.content :global(h5):hover :global(.anchor),
.content :global(h6):hover :global(.anchor) {
opacity: 1;
}
.content :global(h5) :global(.anchor),
.content :global(h6) :global(.anchor) {
top: 0.5em;
}
}
.content :global(h3),
.content :global(h3 > code) {
margin: 6.4rem 0 0 0;
padding: 2rem 1.6rem 5.6rem .2rem;
color: var(--text);
border-top: var(--border-w) solid #6767781f; /* based on --second */
background: transparent;
line-height: 1;
}
.content :global(h3):first-of-type {
border: none;
margin: 0;
}
/* avoid doubled border-top */
.content :global(h3 > code) {
border-radius: 0 0 0 0;
border: none;
font-size: var(--h4);
line-height: 1.2;
}
.content :global(h4),
.content :global(h4 > code) {
font-weight: 600;
font-size: var(--h4);
color: var(--second);
margin: 6.4rem 0 1.6rem 0;
padding-left: 0;
background: transparent;
line-height: 1;
padding: 0;
}
.content :global(h5) {
font-size: 2rem;
}
.content :global(code) {
padding: .3rem .8rem .3rem;
margin: 0 0.2rem;
top: -.1rem;
background: var(--back-api);
}
.content :global(pre) :global(code) {
padding: 0;
margin: 0;
top: 0;
background: transparent;
}
.content :global(pre) {
margin: 0 0 2em 0;
}
.content :global(.icon) {
width: 2rem;
height: 2rem;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
fill: none;
}
.content :global(table) {
margin: 0 0 2em 0;
}
section > :global(.code-block) > :global(pre) {
display: inline-block;
background: var(--back-api);
color: white;
padding: .3rem .8rem;
margin: 0;
max-width: 100%;
}
section > :global(.code-block)> :global(pre.language-markup) {
padding: .3rem .8rem .2rem;
background: var(--back-api);
}
section > :global(p) {
max-width: var(--linemax)
}
small {
font-size: var(--h5);
float: right;
pointer-events: all;
color: var(--prime);
cursor: pointer;
}
/* no linkify on these */
small a { all: unset }
small a:before { all: unset }
section :global(blockquote) {
color: hsl(204, 100%, 50%);
border: 2px solid var(--flash);
}
section :global(blockquote) :global(code) {
background: hsl(204, 100%, 95%) !important;
color: hsl(204, 100%, 50%);
}
</style>
<svelte:head>
<title>API Docs • Svelte</title>
@ -367,31 +19,4 @@
<meta name="Description" content="Cybernetically enhanced web apps">
</svelte:head>
<div bind:this={container} class='content listify'>
{#each sections as section}
<section data-id={section.slug}>
<h2>
<span class="offset-anchor" id={section.slug}></span>
<a href="docs#{section.slug}" class="anchor" aria-hidden></a>
{section.metadata.title}
<small>
<a href='https://github.com/sveltejs/svelte/edit/master/site/content/docs/{section.file}' title='edit this section'>
<Icon name='edit' /></a>
</small>
</h2>
{@html section.html}
</section>
{/each}
</div>
<aside bind:this={aside} class="sidebar-container" class:open={show_contents}>
<div class="sidebar" on:click="{() => show_contents = false}"> <!-- scroll container -->
<GuideContents {sections} {active_section} {show_contents} />
</div>
<button on:click="{() => show_contents = !show_contents}">
<Icon name="{show_contents? 'close' : 'menu'}"/>
</button>
</aside>
<Docs {sections}/>

@ -22,7 +22,7 @@
.section-title {
display: block;
padding: 0 0 .8rem 0;
padding: 0 0 0.8rem 0;
font: 400 var(--h6) var(--font);
text-transform: uppercase;
letter-spacing: 0.12em;
@ -32,7 +32,7 @@
a {
display: flex;
position: relative;
color: white;
color: var(--sidebar-text);
border-bottom: none;
padding: 0.2rem 3rem;
margin: 0 -3rem;
@ -42,17 +42,19 @@
}
a:hover {
color: var(--flash);
color: white;
}
a.active {
background: rgba(255, 255, 255, 0.1) calc(100% - 3rem) 50% no-repeat url(/icons/arrow-right.svg);
background: rgba(0, 0, 0, 0.15) calc(100% - 3rem) 50% no-repeat
url(/icons/arrow-right.svg);
background-size: 1em 1em;
color: white;
}
a.active.loading {
background: rgba(255, 255, 255, 0.1) calc(100% - 3rem) 50% no-repeat url(/icons/loading.svg);
background: rgba(0, 0, 0, 0.1) calc(100% - 3rem) 50% no-repeat
url(/icons/loading.svg);
background-size: 1em 1em;
color: white;
}
@ -63,34 +65,34 @@
width: 5rem;
height: 5rem;
border-radius: 2px;
box-shadow: 1px 1px 3px rgba(0,0,0,0.13);
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.13);
margin: 0.2em 0.5em 0.2em 0;
}
</style>
<ul class="examples-toc">
{#each sections as section}
<li>
<span class="section-title">
{section.title}
</span>
<li>
<span class="section-title">
{section.title}
</span>
{#each section.examples as example}
<a
href="examples#{example.slug}"
class="row"
class:active="{example.slug === active_section}"
class:loading="{isLoading}"
>
<img
class="thumbnail"
alt="{example.title} thumbnail"
src="examples/thumbnails/{example.slug}.jpg"
>
{#each section.examples as example}
<a
href="examples#{example.slug}"
class="row"
class:active="{example.slug === active_section}"
class:loading="{isLoading}"
>
<img
class="thumbnail"
alt="{example.title} thumbnail"
src="examples/thumbnails/{example.slug}.jpg"
/>
<span>{example.title}</span>
</a>
{/each}
</li>
<span>{example.title}</span>
</a>
{/each}
</li>
{/each}
</ul>

@ -26,7 +26,7 @@
svelteUrl
} from '../../config';
import { process_example } from '../../utils/examples';
import { getFragment } from '../../utils/navigation';
import { getFragment } from '@sveltejs/site-kit/utils/navigation';
import TableOfContents from './_TableOfContents.svelte';
export let sections;

@ -1,13 +1,11 @@
<script>
import Blurb from './_components/Blurb.svelte';
import { Blurb, Hero, Section } from '@sveltejs/site-kit';
// import Blurb from './_components/Blurb.svelte';
import Example from './_components/Example.svelte';
import WhosUsingSvelte from './_components/WhosUsingSvelte.svelte';
import IntersectionObserver from '../components/IntersectionObserver.svelte';
// import Lazy from '../components/Lazy.svelte';
import ReplWidget from '../components/Repl/ReplWidget.svelte';
import contributors from './_contributors.js';
let sy = 0;
// TODO this causes a Sapper CSS bug...
// function loadReplWidget() {
// console.log('lazy loading');
@ -16,77 +14,18 @@
</script>
<style>
.container {
position: relative;
margin: 10rem auto;
padding: 0 var(--side-nav);
max-width: 120rem;
}
.container h3 { color: var(--text) }
.container ul { list-style: none }
/* max line-length ~60 chars */
li:not(.box) > p {
max-width: var(--linemax)
}
/* darken text for accesibility */
/* TODO does this belong elsewhere? */
:global(.back-light) {
--text: hsl(36, 3%, 44%);
}
.hero {
margin: 10rem auto;
}
.hero h3, .logotype {
position: relative;
left: 1.6rem;
}
.hero h3 {
font-size: 2rem;
}
.logotype {
height: 4rem;
}
.logo {
position: absolute;
top: -4rem;
right: 0rem;
width: 52rem;
will-change: transform;
display: none;
}
.examples {
background: var(--second);
color: white;
overflow: hidden;
}
.example {
width: 100%;
}
.example a {
color: inherit;
}
.example > p {
margin: 4.4rem 2.4rem 2.4rem 0;
}
.repl-container {
width: 100%;
height: 420px;
border-radius: var(--border-r);
overflow: hidden;
}
.contributor {
width: 2.4em;
height: 2.4em;
@ -98,45 +37,6 @@
margin: 0 0.5em 0.5em 0;
border: 2px solid var(--second);
}
@media (min-width: 640px) {
.logotype {
height: 6rem;
}
.hero h3 {
font-size: var(--h3);
}
}
@media (min-width: 800px) {
.logo {
display: block;
}
.hero {
margin: 15rem auto;
}
.hero h3, .logotype {
left: 3rem;
}
}
@media (min-width: 920px) {
.example {
display: grid;
grid-template-columns: 1fr 3fr;
grid-gap: 0.5em;
align-items: start;
}
}
@media (min-width: 1200px) {
.logo {
right: calc(50vw - 60rem);
}
}
</style>
<svelte:head>
@ -147,78 +47,83 @@
<meta name="Description" content="Cybernetically enhanced web apps">
</svelte:head>
<svelte:window bind:scrollY={sy}/>
<Hero
title="Svelte"
tagline="Cybernetically enhanced web apps"
outline="svelte-logo-outline.svg"
logotype="svelte-logotype.svg"
/>
<img alt="Svelte logo" class="logo" src="svelte-logo-outline.svg" style="transform: translate(0, {sy * .2}px)">
<Blurb>
<a href="blog/write-less-code" slot="one">
<h2>Write less code</h2>
<p>Build boilerplate-free components using languages you already know — HTML, CSS and JavaScript</p>
<section class="hero container">
<img alt="Svelte logotype" class="logotype" src="svelte-logotype.svg">
<h3>Cybernetically enhanced web apps</h3>
</section>
<span class="learn-more">learn more</span>
</a>
<Blurb/>
<a href="blog/virtual-dom-is-pure-overhead" slot="two">
<h2>No virtual DOM</h2>
<p>Svelte compiles your code to tiny, framework-less vanilla JS — your app starts fast and stays fast</p>
<span class="learn-more">learn more</span>
</a>
<a href="blog/svelte-3-rethinking-reactivity" slot="three">
<h2>Truly reactive</h2>
<p>No more complex state management libraries — Svelte brings reactivity to JavaScript itself</p>
<span class="learn-more">learn more</span>
</a>
<div class="description" slot="what">
<p>Svelte is a radical new approach to building user interfaces. Whereas traditional frameworks like React and Vue do the bulk of their work in the <em>browser</em>, Svelte shifts that work into a <em>compile step</em> that happens when you build your app.</p>
<p>Instead of using techniques like virtual DOM diffing, Svelte writes code that surgically updates the DOM when the state of your app changes.</p>
<p><a href="blog/svelte-3-rethinking-reactivity">Read the introductory blog post</a> to learn more.</p>
</div>
<div style="grid-area: start; display: flex; flex-direction: column; min-width: 0" slot="how">
<pre class="language-bash" style="margin: 0 0 1em 0; min-width: 0; min-height: 0">
npx degit sveltejs/template my-svelte-project
cd my-svelte-project
npm install
npm run dev & open http://localhost:5000
</pre>
<p style="flex: 1">See the <a href="blog/the-easiest-way-to-get-started">quickstart guide</a> for more information.</p>
<p class="cta"><a rel="prefetch" href="tutorial">Learn Svelte</a></p>
</div>
</Blurb>
<div class="examples">
<section class="container example">
<Example id="hello-world">
<p>Svelte components are built on top of HTML. Just add data.</p>
</Example>
<div class="repl-container">
<IntersectionObserver once let:intersecting top={400}>
{#if intersecting}
<!-- <Lazy this={loadReplWidget} example="hello-world"/> -->
<ReplWidget example="hello-world"/>
{/if}
</IntersectionObserver>
</div>
</section>
<section class="container example">
<Example id="nested-components">
<p>CSS is component-scoped by default — no more style collisions or specificity wars. Or you can <a href="/blog/svelte-css-in-js">use your favourite CSS-in-JS library</a>.</p>
</Example>
<div class="repl-container">
<IntersectionObserver once let:intersecting top={400}>
{#if intersecting}
<!-- <Lazy this={loadReplWidget} example="nested-components"/> -->
<ReplWidget example="nested-components"/>
{/if}
</IntersectionObserver>
</div>
</section>
<section class="container example">
<Example id="reactive-assignments">
<p>Trigger efficient, granular updates by assigning to local variables. The compiler does the rest.</p>
</Example>
<div class="repl-container">
<IntersectionObserver once let:intersecting top={400}>
{#if intersecting}
<!-- <Lazy this={loadReplWidget} example="reactive-assignments"/> -->
<ReplWidget example="reactive-assignments"/>
{/if}
</IntersectionObserver>
</div>
</section>
<section class="container example">
<Example id="svg-transitions">
<p>Build beautiful UIs with a powerful, performant transition engine built right into the framework.</p>
<div class="repl-container">
<IntersectionObserver once let:intersecting top={400}>
{#if intersecting}
<!-- <Lazy this={loadReplWidget} example="svg-transitions"/> -->
<ReplWidget example="svg-transitions"/>
{/if}
</IntersectionObserver>
</div>
</section>
</Example>
</div>
<section class="container">
<Section>
<h3>Who's using Svelte?</h3>
<WhosUsingSvelte/>
</section>
</Section>
<section class="container">
<Section>
<h3>Contributors</h3>
<p>Svelte is free and open source software, made possible by the work of dozens of volunteers. <a href="https://github.com/sveltejs/svelte">Join us!</a></p>
@ -230,4 +135,4 @@
href="https://github.com/{contributor}"
>{contributor}</a>
{/each}
</section>
</Section>

@ -1,7 +1,7 @@
<script>
import { createEventDispatcher } from 'svelte';
import UserMenu from './UserMenu.svelte';
import Icon from '../../../../components/Icon.svelte';
import { Icon } from '@sveltejs/site-kit';
import * as doNotZip from 'do-not-zip';
import downloadBlob from '../../_utils/downloadBlob.js';
import { user } from '../../../../user.js';

@ -1,6 +1,6 @@
<script>
import { goto } from '@sapper/app';
import Icon from '../../../components/Icon.svelte';
import { Icon } from '@sveltejs/site-kit';
export let sections;
export let slug;
@ -30,13 +30,17 @@
display: block;
padding: 0.7em 0;
text-align: center;
opacity: 0.7;
opacity: 0.75;
color: white;
}
a:hover {
opacity: 1;
}
a.disabled, a.disabled:hover, a.disabled:active {
color: white;
opacity: 0.4;
opacity: 0.3;
}
span {

@ -3,7 +3,7 @@ import * as path from 'path';
import marked from 'marked';
import PrismJS from 'prismjs';
import send from '@polka/send';
import { extract_frontmatter, extract_metadata, langs, link_renderer } from '../../../utils/markdown';
import { extract_frontmatter, extract_metadata, langs, link_renderer } from '@sveltejs/site-kit/utils/markdown';
const cache = new Map();

@ -18,7 +18,7 @@
import { getContext } from 'svelte';
import ScreenToggle from '../../../components/ScreenToggle.svelte';
import Icon from '../../../components/Icon.svelte';
import { Icon } from '@sveltejs/site-kit';
import TableOfContents from './_TableOfContents.svelte';
import {
@ -151,7 +151,7 @@
height: 100%;
border-right: 1px solid var(--second);
background-color: var(--second);
color: white;
color: var(--sidebar-text);
}
.chapter-markup {
@ -165,6 +165,7 @@
margin: 4rem 0 1.6rem 0;
font-size: var(--h3);
line-height: 1;
font-weight: 400;
color: white;
}
@ -173,16 +174,21 @@
}
.chapter-markup :global(a) {
color: var(--sidebar-text);
}
.chapter-markup :global(a:hover) {
color: white;
}
.chapter-markup :global(ul) {
padding: 0 0 0 2em;
}
.chapter-markup :global(blockquote) {
background-color: rgba(255,255,255,.1);
color: white;
background-color: rgba(0,0,0,.17);
color: var(--sidebar-text);
}
.chapter-markup::-webkit-scrollbar {
@ -198,22 +204,22 @@
.chapter-markup :global(p) > :global(code),
.chapter-markup :global(ul) :global(code) {
color: white;
background: rgba(255,255,255,.1);
padding: .2em .4em;
color: var(--sidebar-text);
background: rgba(0,0,0,.12);
padding: .2em .4em .3em;
white-space: nowrap;
position: relative;
top: -0.1em;
}
.controls {
border-top: 1px solid rgba(255,255,255,.1);
border-top: 1px solid rgba(255,255,255,.15);
padding: 1em 0 0 0;
display: flex;
}
.show {
background: rgba(255,255,255,.1);
background: rgba(0,0,0,.4);
padding: .2em .7em .3em;
border-radius: var(--border-r);
top: .1em;
@ -223,22 +229,17 @@
}
.show:hover {
background: rgba(255,255,255,.2);
background: rgba(0,0,0,.65);
color: white;
}
a.next {
/* border-bottom: none; */
padding-right: 1.2em;
background: no-repeat 100% 50% url(/icons/arrow-right.svg);
background-size: 1em 1em;
margin-left: auto;
}
a.next:hover {
/* border-bottom: 2px solid currentColor; */
/* text-decoration: underline; */
}
.improve-chapter {
padding: 1em 0 .5em 0;
}

@ -1,6 +1,6 @@
import * as fs from 'fs';
import send from '@polka/send';
import { extract_frontmatter } from '../../utils/markdown';
import { extract_frontmatter } from '@sveltejs/site-kit/utils/markdown';
let json;

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

@ -1,61 +0,0 @@
import * as fleece from 'golden-fleece';
export function extract_frontmatter(markdown) {
const match = /---\r?\n([\s\S]+?)\r?\n---/.exec(markdown);
const frontMatter = match[1];
const content = markdown.slice(match[0].length);
const metadata = {};
frontMatter.split('\n').forEach(pair => {
const colonIndex = pair.indexOf(':');
metadata[pair.slice(0, colonIndex).trim()] = pair
.slice(colonIndex + 1)
.trim();
});
return { metadata, content };
}
export function extract_metadata(line, lang) {
try {
if (lang === 'html' && line.startsWith('<!--') && line.endsWith('-->')) {
return fleece.evaluate(line.slice(4, -3).trim());
}
if (
lang === 'js' ||
(lang === 'json' && line.startsWith('/*') && line.endsWith('*/'))
) {
return fleece.evaluate(line.slice(2, -2).trim());
}
} catch (err) {
// TODO report these errors, don't just squelch them
return null;
}
}
// map lang to prism-language-attr
export const langs = {
bash: 'bash',
html: 'markup',
sv: 'markup',
js: 'javascript',
css: 'css'
};
// links renderer
export function link_renderer (href, title, text) {
let target_attr = '';
let title_attr = '';
if (href.startsWith("http")) {
target_attr = ' target="_blank"';
}
if (title !== null) {
title_attr = ` title="${title}"`;
}
return `<a href="${href}"${target_attr}${title_attr}>${text}</a>`;
}

@ -1 +0,0 @@
export const getFragment = () => window.location.hash.slice(1);

@ -46,6 +46,7 @@
--flash: #40b3ff;
--heading: var(--second);
--text: #444;
--sidebar-text: rgba(255, 255, 255, .75);
--border-w: .3rem; /* border-width */
--border-r: .4rem; /* border-radius */
}
@ -469,7 +470,6 @@ input[type="checkbox"]::before {
top: 0;
left: 0;
background: var(--second);
-webkit-transition: .25s ease-out;
/* box-sizing: border-box; */
box-sizing: content-box;
}
@ -489,7 +489,7 @@ input[type="checkbox"]::after {
border-radius: 1em;
background: white;
box-shadow: 0 0px 1px rgba(0,0,0,.4), 0 4px 2px rgba(0,0,0,.1);
-webkit-transition: .2s ease-out;
-webkit-transition: background .2s ease-out, left .2s ease-out;
}
input[type="checkbox"]:checked::after {

@ -1,5 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 103 124">
<path fill="black" d='M96.33,20.61C85.38,4.93,63.74.28,48.09,10.25L20.61,27.77A31.46,31.46,0,0,0,6.37,48.88,33.22,33.22,0,0,0,9.64,70.2,31.52,31.52,0,0,0,4.93,82a33.61,33.61,0,0,0,5.73,25.41c11,15.68,32.6,20.33,48.25,10.36l27.48-17.52a31.48,31.48,0,0,0,14.24-21.11A33.22,33.22,0,0,0,97.36,57.8,31.52,31.52,0,0,0,102.07,46a33.57,33.57,0,0,0-5.74-25.41
M45.41,108.86A21.81,21.81,0,0,1,22,100.18,20.2,20.2,0,0,1,18.53,84.9a19,19,0,0,1,.65-2.57l.52-1.58,1.41,1a35.32,35.32,0,0,0,10.75,5.37l1,.31-.1,1a6.2,6.2,0,0,0,1.11,4.08A6.57,6.57,0,0,0,41,95.19a6,6,0,0,0,1.68-.74L70.11,76.94a5.76,5.76,0,0,0,2.59-3.83,6.09,6.09,0,0,0-1-4.6,6.58,6.58,0,0,0-7.06-2.62,6.21,6.21,0,0,0-1.69.74L52.43,73.31a19.88,19.88,0,0,1-5.58,2.45,21.82,21.82,0,0,1-23.43-8.68A20.2,20.2,0,0,1,20,51.8a19,19,0,0,1,8.56-12.7L56,21.59a19.88,19.88,0,0,1,5.58-2.45A21.81,21.81,0,0,1,85,27.82,20.2,20.2,0,0,1,88.47,43.1a19,19,0,0,1-.65,2.57l-.52,1.58-1.41-1a35.32,35.32,0,0,0-10.75-5.37l-1-.31.1-1a6.2,6.2,0,0,0-1.11-4.08,6.57,6.57,0,0,0-7.06-2.62,6,6,0,0,0-1.68.74L36.89,51.06a5.71,5.71,0,0,0-2.58,3.83,6,6,0,0,0,1,4.6,6.58,6.58,0,0,0,7.06,2.62,6.21,6.21,0,0,0,1.69-.74l10.48-6.68a19.88,19.88,0,0,1,5.58-2.45,21.82,21.82,0,0,1,23.43,8.68A20.2,20.2,0,0,1,87,76.2a19,19,0,0,1-8.56,12.7L51,106.41a19.88,19.88,0,0,1-5.58,2.45' />
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 98.2 118" style="enable-background:new 0 0 98.2 118;" xml:space="preserve">
<path d="M91.9,15.6C81-0.1,59.3-4.7,43.7,5.3L16.2,22.8C8.7,27.5,3.5,35.2,2,43.9c-1.3,7.3-0.2,14.8,3.3,21.3
c-2.4,3.6-4,7.6-4.7,11.8c-1.6,8.9,0.5,18.1,5.7,25.4c11,15.7,32.6,20.3,48.2,10.4L82,95.3c7.5-4.7,12.7-12.4,14.2-21.1
c1.3-7.3,0.2-14.8-3.3-21.3c2.4-3.6,4-7.6,4.7-11.8C99.2,32.1,97.2,22.9,91.9,15.6 M41,103.9c-8.9,2.3-18.2-1.2-23.4-8.7
c-3.2-4.4-4.4-9.9-3.5-15.3c0.2-0.9,0.4-1.7,0.6-2.6l0.5-1.6l1.4,1c3.3,2.4,6.9,4.2,10.8,5.4l1,0.3l-0.1,1c-0.1,1.4,0.3,2.9,1.1,4.1
c1.6,2.3,4.4,3.4,7.1,2.7c0.6-0.2,1.2-0.4,1.7-0.7l27.4-17.5c1.4-0.9,2.3-2.2,2.6-3.8c0.3-1.6-0.1-3.3-1-4.6
c-1.6-2.3-4.4-3.3-7.1-2.6c-0.6,0.2-1.2,0.4-1.7,0.7L48,68.3c-1.7,1.1-3.6,1.9-5.6,2.4c-8.9,2.3-18.2-1.2-23.4-8.7
c-3.1-4.4-4.4-9.9-3.4-15.3c0.9-5.2,4.1-9.9,8.6-12.7l27.4-17.5c1.7-1.1,3.6-1.9,5.6-2.5c8.9-2.3,18.2,1.2,23.4,8.7
c3.2,4.4,4.4,9.9,3.5,15.3c-0.2,0.9-0.4,1.7-0.7,2.6l-0.5,1.6l-1.4-1c-3.3-2.4-6.9-4.2-10.8-5.4l-1-0.3l0.1-1
c0.1-1.4-0.3-2.9-1.1-4.1c-1.6-2.3-4.4-3.3-7.1-2.6c-0.6,0.2-1.2,0.4-1.7,0.7L32.5,46.1c-1.4,0.9-2.3,2.2-2.6,3.8
c-0.3,1.6,0.1,3.3,1,4.6c1.6,2.3,4.4,3.3,7.1,2.6c0.6-0.2,1.2-0.4,1.7-0.7l10.5-6.7c1.7-1.1,3.6-1.9,5.6-2.5
c8.9-2.3,18.2,1.2,23.4,8.7c3.2,4.4,4.4,9.9,3.5,15.3c-0.9,5.2-4.1,9.9-8.6,12.7l-27.4,17.5C44.9,102.5,43,103.3,41,103.9"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -1,5 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 103 124">
<path fill="none" stroke="#ff3e00" stroke-width=".25" d='M96.33,20.61C85.38,4.93,63.74.28,48.09,10.25L20.61,27.77A31.46,31.46,0,0,0,6.37,48.88,33.22,33.22,0,0,0,9.64,70.2,31.52,31.52,0,0,0,4.93,82a33.61,33.61,0,0,0,5.73,25.41c11,15.68,32.6,20.33,48.25,10.36l27.48-17.52a31.48,31.48,0,0,0,14.24-21.11A33.22,33.22,0,0,0,97.36,57.8,31.52,31.52,0,0,0,102.07,46a33.57,33.57,0,0,0-5.74-25.41' />
<path fill="none" stroke="#ff3e00" stroke-width=".25" d='M45.41,108.86A21.81,21.81,0,0,1,22,100.18,20.2,20.2,0,0,1,18.53,84.9a19,19,0,0,1,.65-2.57l.52-1.58,1.41,1a35.32,35.32,0,0,0,10.75,5.37l1,.31-.1,1a6.2,6.2,0,0,0,1.11,4.08A6.57,6.57,0,0,0,41,95.19a6,6,0,0,0,1.68-.74L70.11,76.94a5.76,5.76,0,0,0,2.59-3.83,6.09,6.09,0,0,0-1-4.6,6.58,6.58,0,0,0-7.06-2.62,6.21,6.21,0,0,0-1.69.74L52.43,73.31a19.88,19.88,0,0,1-5.58,2.45,21.82,21.82,0,0,1-23.43-8.68A20.2,20.2,0,0,1,20,51.8a19,19,0,0,1,8.56-12.7L56,21.59a19.88,19.88,0,0,1,5.58-2.45A21.81,21.81,0,0,1,85,27.82,20.2,20.2,0,0,1,88.47,43.1a19,19,0,0,1-.65,2.57l-.52,1.58-1.41-1a35.32,35.32,0,0,0-10.75-5.37l-1-.31.1-1a6.2,6.2,0,0,0-1.11-4.08,6.57,6.57,0,0,0-7.06-2.62,6,6,0,0,0-1.68.74L36.89,51.06a5.71,5.71,0,0,0-2.58,3.83,6,6,0,0,0,1,4.6,6.58,6.58,0,0,0,7.06,2.62,6.21,6.21,0,0,0,1.69-.74l10.48-6.68a19.88,19.88,0,0,1,5.58-2.45,21.82,21.82,0,0,1,23.43,8.68A20.2,20.2,0,0,1,87,76.2a19,19,0,0,1-8.56,12.7L51,106.41a19.88,19.88,0,0,1-5.58,2.45' />
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 98.4 118.3" style="enable-background:new 0 0 98.4 118.3;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#FF3E00;stroke-width:0.25;}
</style>
<path class="st0" d="M92,15.7C81.1,0.1,59.5-4.6,43.8,5.4L16.3,22.9C8.8,27.6,3.6,35.3,2.1,44c-1.3,7.3-0.2,14.8,3.3,21.3
c-2.4,3.6-4,7.6-4.7,11.8c-1.6,8.9,0.5,18.1,5.7,25.4c11,15.7,32.6,20.3,48.2,10.4l27.5-17.5c7.5-4.7,12.7-12.4,14.2-21.1
c1.3-7.3,0.2-14.8-3.3-21.3c2.4-3.6,4-7.6,4.7-11.8C99.4,32.2,97.3,23.1,92,15.7"/>
<path class="st0" d="M41.1,104c-8.9,2.3-18.2-1.2-23.4-8.7c-3.2-4.4-4.4-9.9-3.5-15.3c0.2-0.9,0.4-1.7,0.6-2.6l0.5-1.6l1.4,1
c3.3,2.4,6.9,4.2,10.8,5.4l1,0.3l-0.1,1c-0.1,1.4,0.3,2.9,1.1,4.1c1.6,2.3,4.4,3.4,7.1,2.7c0.6-0.2,1.2-0.4,1.7-0.7l27.4-17.5
c1.4-0.9,2.3-2.2,2.6-3.8c0.3-1.6-0.1-3.3-1-4.6c-1.6-2.3-4.4-3.3-7.1-2.6c-0.6,0.2-1.2,0.4-1.7,0.7l-10.5,6.7
c-1.7,1.1-3.6,1.9-5.6,2.4c-8.9,2.3-18.2-1.2-23.4-8.7c-3.1-4.4-4.4-9.9-3.4-15.3c0.9-5.2,4.1-9.9,8.6-12.7l27.4-17.5
c1.7-1.1,3.6-1.9,5.6-2.5c8.9-2.3,18.2,1.2,23.4,8.7c3.2,4.4,4.4,9.9,3.5,15.3c-0.2,0.9-0.4,1.7-0.7,2.6L83,42.4l-1.4-1
c-3.3-2.4-6.9-4.2-10.8-5.4l-1-0.3l0.1-1c0.1-1.4-0.3-2.9-1.1-4.1c-1.6-2.3-4.4-3.3-7.1-2.6c-0.6,0.2-1.2,0.4-1.7,0.7L32.6,46.2
C31.2,47,30.3,48.4,30,50c-0.3,1.6,0.1,3.3,1,4.6c1.6,2.3,4.4,3.3,7.1,2.6c0.6-0.2,1.2-0.4,1.7-0.7l10.5-6.7
c1.7-1.1,3.6-1.9,5.6-2.5c8.9-2.3,18.2,1.2,23.4,8.7c3.2,4.4,4.4,9.9,3.5,15.3c-0.9,5.2-4.1,9.9-8.6,12.7l-27.4,17.5
C45,102.6,43.1,103.5,41.1,104"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

@ -1,5 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 103 124">
<path fill="#ff3e00" d='M96.33,20.61C85.38,4.93,63.74.28,48.09,10.25L20.61,27.77A31.46,31.46,0,0,0,6.37,48.88,33.22,33.22,0,0,0,9.64,70.2,31.52,31.52,0,0,0,4.93,82a33.61,33.61,0,0,0,5.73,25.41c11,15.68,32.6,20.33,48.25,10.36l27.48-17.52a31.48,31.48,0,0,0,14.24-21.11A33.22,33.22,0,0,0,97.36,57.8,31.52,31.52,0,0,0,102.07,46a33.57,33.57,0,0,0-5.74-25.41' />
<path fill="white" d='M45.41,108.86A21.81,21.81,0,0,1,22,100.18,20.2,20.2,0,0,1,18.53,84.9a19,19,0,0,1,.65-2.57l.52-1.58,1.41,1a35.32,35.32,0,0,0,10.75,5.37l1,.31-.1,1a6.2,6.2,0,0,0,1.11,4.08A6.57,6.57,0,0,0,41,95.19a6,6,0,0,0,1.68-.74L70.11,76.94a5.76,5.76,0,0,0,2.59-3.83,6.09,6.09,0,0,0-1-4.6,6.58,6.58,0,0,0-7.06-2.62,6.21,6.21,0,0,0-1.69.74L52.43,73.31a19.88,19.88,0,0,1-5.58,2.45,21.82,21.82,0,0,1-23.43-8.68A20.2,20.2,0,0,1,20,51.8a19,19,0,0,1,8.56-12.7L56,21.59a19.88,19.88,0,0,1,5.58-2.45A21.81,21.81,0,0,1,85,27.82,20.2,20.2,0,0,1,88.47,43.1a19,19,0,0,1-.65,2.57l-.52,1.58-1.41-1a35.32,35.32,0,0,0-10.75-5.37l-1-.31.1-1a6.2,6.2,0,0,0-1.11-4.08,6.57,6.57,0,0,0-7.06-2.62,6,6,0,0,0-1.68.74L36.89,51.06a5.71,5.71,0,0,0-2.58,3.83,6,6,0,0,0,1,4.6,6.58,6.58,0,0,0,7.06,2.62,6.21,6.21,0,0,0,1.69-.74l10.48-6.68a19.88,19.88,0,0,1,5.58-2.45,21.82,21.82,0,0,1,23.43,8.68A20.2,20.2,0,0,1,87,76.2a19,19,0,0,1-8.56,12.7L51,106.41a19.88,19.88,0,0,1-5.58,2.45' />
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 98.1 118" style="enable-background:new 0 0 98.1 118;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FF3E00;}
.st1{fill:#FFFFFF;}
</style>
<path class="st0" d="M91.8,15.6C80.9-0.1,59.2-4.7,43.6,5.2L16.1,22.8C8.6,27.5,3.4,35.2,1.9,43.9c-1.3,7.3-0.2,14.8,3.3,21.3
c-2.4,3.6-4,7.6-4.7,11.8c-1.6,8.9,0.5,18.1,5.7,25.4c11,15.7,32.6,20.3,48.2,10.4l27.5-17.5c7.5-4.7,12.7-12.4,14.2-21.1
c1.3-7.3,0.2-14.8-3.3-21.3c2.4-3.6,4-7.6,4.7-11.8C99.2,32.1,97.1,22.9,91.8,15.6"/>
<path class="st1" d="M40.9,103.9c-8.9,2.3-18.2-1.2-23.4-8.7c-3.2-4.4-4.4-9.9-3.5-15.3c0.2-0.9,0.4-1.7,0.6-2.6l0.5-1.6l1.4,1
c3.3,2.4,6.9,4.2,10.8,5.4l1,0.3l-0.1,1c-0.1,1.4,0.3,2.9,1.1,4.1c1.6,2.3,4.4,3.4,7.1,2.7c0.6-0.2,1.2-0.4,1.7-0.7L65.5,72
c1.4-0.9,2.3-2.2,2.6-3.8c0.3-1.6-0.1-3.3-1-4.6c-1.6-2.3-4.4-3.3-7.1-2.6c-0.6,0.2-1.2,0.4-1.7,0.7l-10.5,6.7
c-1.7,1.1-3.6,1.9-5.6,2.4c-8.9,2.3-18.2-1.2-23.4-8.7c-3.1-4.4-4.4-9.9-3.4-15.3c0.9-5.2,4.1-9.9,8.6-12.7l27.5-17.5
c1.7-1.1,3.6-1.9,5.6-2.5c8.9-2.3,18.2,1.2,23.4,8.7c3.2,4.4,4.4,9.9,3.5,15.3c-0.2,0.9-0.4,1.7-0.7,2.6l-0.5,1.6l-1.4-1
c-3.3-2.4-6.9-4.2-10.8-5.4l-1-0.3l0.1-1c0.1-1.4-0.3-2.9-1.1-4.1c-1.6-2.3-4.4-3.3-7.1-2.6c-0.6,0.2-1.2,0.4-1.7,0.7L32.4,46.1
c-1.4,0.9-2.3,2.2-2.6,3.8s0.1,3.3,1,4.6c1.6,2.3,4.4,3.3,7.1,2.6c0.6-0.2,1.2-0.4,1.7-0.7l10.5-6.7c1.7-1.1,3.6-1.9,5.6-2.5
c8.9-2.3,18.2,1.2,23.4,8.7c3.2,4.4,4.4,9.9,3.5,15.3c-0.9,5.2-4.1,9.9-8.6,12.7l-27.5,17.5C44.8,102.5,42.9,103.3,40.9,103.9"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

@ -169,14 +169,15 @@ export default function dom(
scope = scope.parent;
}
if (node.type === 'AssignmentExpression') {
if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
let names = [];
if (node.left.type === 'MemberExpression') {
const left_object_name = get_object(node.left).name;
if (assignee.type === 'MemberExpression') {
const left_object_name = get_object(assignee).name;
left_object_name && (names = [left_object_name]);
} else {
names = extract_names(node.left);
names = extract_names(assignee);
}
if (node.operator === '=' && nodes_match(node.left, node.right)) {
@ -189,9 +190,10 @@ export default function dom(
code.overwrite(node.start, node.end, dirty.map(n => component.invalidate(n)).join('; '));
} else {
const single = (
node.left.type === 'Identifier' &&
node.type === 'AssignmentExpression' &&
assignee.type === 'Identifier' &&
parent.type === 'ExpressionStatement' &&
node.left.name[0] !== '$'
assignee.name[0] !== '$'
);
names.forEach(name => {
@ -201,7 +203,7 @@ export default function dom(
const variable = component.var_lookup.get(name);
if (variable && (variable.hoistable || variable.global || variable.module)) return;
if (single) {
if (single && !(variable.subscribable && variable.reassigned)) {
code.prependRight(node.start, `$$invalidate('${name}', `);
code.appendLeft(node.end, `)`);
} else {
@ -213,18 +215,6 @@ export default function dom(
}
}
else if (node.type === 'UpdateExpression') {
const { name } = get_object(node.argument);
if (scope.find_owner(name) !== component.instance_scope) return;
const variable = component.var_lookup.get(name);
if (variable && variable.hoistable) return;
pending_assignments.add(name);
component.has_reactive_assignments = true;
}
if (pending_assignments.size > 0) {
if (node.type === 'ArrowFunctionExpression') {
const insert = Array.from(pending_assignments).map(name => component.invalidate(name)).join('; ');
@ -423,14 +413,15 @@ export default function dom(
${set && `$$self.$set = ${set};`}
${reactive_declarations.length > 0 && deindent`
${injected.length && `let ${injected.join(', ')};`}
${reactive_declarations.length > 0 && deindent`
$$self.$$.update = ($$dirty = { ${Array.from(all_reactive_dependencies).map(n => `${n}: 1`).join(', ')} }) => {
${reactive_declarations}
};
`}
${fixed_reactive_declarations}
`}
return ${stringify_props(filtered_declarations)};
}

@ -75,12 +75,10 @@ export class Scope {
if (node.kind === 'var' && this.block && this.parent) {
this.parent.add_declaration(node);
} else if (node.type === 'VariableDeclaration') {
const initialised = !!node.init;
node.declarations.forEach((declarator: Node) => {
extract_names(declarator.id).forEach(name => {
this.declarations.set(name, node);
if (initialised) this.initialised_declarations.add(name);
if (declarator.init) this.initialised_declarations.add(name);
});
});
} else {

@ -3,7 +3,7 @@ export function append(target, node) {
}
export function insert(target, node, anchor) {
target.insertBefore(node, anchor);
target.insertBefore(node, anchor || null);
}
export function detach(node) {

@ -2,7 +2,7 @@ export function get_spread_update(levels, updates) {
const update = {};
const to_null_out = {};
const accounted_for = {};
const accounted_for = { $$scope: 1 };
let i = levels.length;
while (i--) {
@ -34,4 +34,4 @@ export function get_spread_update(levels, updates) {
}
return update;
}
}

@ -36,7 +36,7 @@ export default function mustache(parser: Parser) {
parser.allow_whitespace();
// {/if} or {/each}
// {/if}, {/each} or {/await}
if (parser.eat('/')) {
let block = parser.current();
let expected;
@ -287,13 +287,6 @@ export default function mustache(parser: Parser) {
parser.allow_whitespace();
parser.eat(')', true);
parser.allow_whitespace();
} else if (parser.eat('@')) {
block.key = parser.read_identifier();
if (!block.key) parser.error({
code: `expected-name`,
message: `Expected name`
});
parser.allow_whitespace();
}
}

@ -2,8 +2,10 @@ import { isIdentifierStart, isIdentifierChar } from 'acorn';
import full_char_code_at from './full_char_code_at';
export const globals = new Set([
'alert',
'Array',
'Boolean',
'confirm',
'console',
'Date',
'decodeURI',
@ -24,6 +26,7 @@ export const globals = new Set([
'parseInt',
'process',
'Promise',
'prompt',
'RegExp',
'Set',
'String',

@ -0,0 +1,4 @@
<div>
<slot />
<div {...$$props}></div>
</div>

@ -0,0 +1,19 @@
export default {
html: `
<div>
<input />
<div class="foo"></div>
</div>
`,
async test({ assert, component, target }) {
component.value = 'foo';
assert.htmlEqual(target.innerHTML, `
<div>
<input />
<div class="foo"></div>
</div>
`);
}
};

@ -0,0 +1,8 @@
<script>
import Nested from './Nested.svelte';
export let value = '';
</script>
<Nested class="foo">
<input bind:value />
</Nested>

@ -1,5 +1,6 @@
<script>
export let value;
export let value_with_default = undefined;
</script>
<input bind:value>

@ -1,6 +1,7 @@
<script>
export let x;
export let y;
export let z = undefined;
</script>
<div>{x} {y}</div>

@ -0,0 +1,11 @@
export default {
html: `
<p>4</p>
`,
test({ assert, component, target }) {
assert.htmlEqual(target.innerHTML, `
<p>4</p>
`);
}
};

@ -0,0 +1,6 @@
<script>
const num = 2;
$: squared = num * num;
</script>
<p>{squared}</p>

@ -0,0 +1,8 @@
export default {
html: `0`,
async test({ assert, component, target }) {
await component.increment();
assert.htmlEqual(target.innerHTML, `1`);
}
};

@ -0,0 +1,11 @@
<script>
import { writable } from '../../../../store.js';
const foo = writable(0);
export function increment() {
$foo++;
}
</script>
{$foo}

@ -0,0 +1,3 @@
export default {
html: `42`,
};

@ -0,0 +1,7 @@
<script>
import { writable } from 'svelte/store';
let foo = writable(0);
foo = writable(42);
</script>
{$foo}
Loading…
Cancel
Save