Revert "Update Changes"

pull/4856/head
Dominus Vilicus 5 years ago committed by GitHub
parent 738f7652a4
commit a18096a81a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -2,6 +2,7 @@
**/expected.js
_output
test/*/samples/*/output.js
node_modules
# automatically generated
internal_exports.ts

@ -1,6 +1,65 @@
module.exports = {
root: true,
extends: '@sveltejs',
rules: {
indent: 'off',
'no-unused-vars': 'off',
semi: [2, 'always'],
'keyword-spacing': [2, { before: true, after: true }],
'space-before-blocks': [2, 'always'],
'no-mixed-spaces-and-tabs': [2, 'smart-tabs'],
'no-cond-assign': 0,
'object-shorthand': [2, 'always'],
'no-const-assign': 2,
'no-class-assign': 2,
'no-this-before-super': 2,
'no-var': 2,
'no-unreachable': 2,
'valid-typeof': 2,
'quote-props': [2, 'as-needed'],
'one-var': [2, 'never'],
'prefer-arrow-callback': 2,
'prefer-const': [2, { destructuring: 'all' }],
'arrow-spacing': 2,
'no-inner-declarations': 0,
'require-atomic-updates': 'off',
'@typescript-eslint/indent': 'off',
'@typescript-eslint/camelcase': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/array-type': ['error', 'array-simple'],
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/explicit-member-accessibility': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_'
}
],
'@typescript-eslint/no-object-literal-type-assertion': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/prefer-interface': 'off'
},
globals: {
globalThis: false
},
env: {
es6: true,
browser: true,
node: true,
mocha: true
},
extends: [
'eslint:recommended',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:import/typescript',
'plugin:@typescript-eslint/recommended'
],
parserOptions: {
ecmaVersion: 9,
sourceType: 'module'
},
plugins: ['svelte3'],
settings: {
'import/core-modules': [
'svelte',
@ -10,5 +69,20 @@ module.exports = {
'estree'
],
'svelte3/compiler': require('./compiler')
}
},
overrides: [
{
files: ['*.js'],
rules: {
'@typescript-eslint/no-var-requires': 'off'
}
},
{
files: ['*.svelte'],
processor: 'svelte3/svelte3',
rules: {
'@typescript-eslint/indent': 'off'
}
}
]
};

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

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

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

@ -3,12 +3,12 @@ on: [push, pull_request]
jobs:
Tests:
runs-on: ${{ matrix.os }}
timeout-minutes: 10
strategy:
matrix:
node-version: [8, 10, 12, 14]
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- run: git config --global core.autocrlf false
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
@ -19,17 +19,12 @@ jobs:
CI: true
Lint:
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
- run: 'npm i && npm run lint'
Unit:
runs-on: ${{ matrix.os }}
timeout-minutes: 5
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1

@ -2,72 +2,11 @@
## Unreleased
* Expose object of which slots have received content in `$$slots` ([#2106](https://github.com/sveltejs/svelte/issues/2106))
* Re-throw an unhandled rejection when an `{#await}` block with no `{:catch}` gets a rejection ([#5129](https://github.com/sveltejs/svelte/issues/5129))
* Add types to `createEventDispatcher` ([#5211](https://github.com/sveltejs/svelte/issues/5211))
* In SSR mode, do not automatically declare variables for reactive assignments to member expressions ([#5247](https://github.com/sveltejs/svelte/issues/5247))
* Include selector in message of `unused-css-selector` warning ([#5252](https://github.com/sveltejs/svelte/issues/5252))
* Fix using `<Namespaced.Component/>`s in child `{#await}`/`{#each}` contexts ([#5255](https://github.com/sveltejs/svelte/issues/5255))
* Fix using `<svelte:component>` in `{:catch}` ([#5259](https://github.com/sveltejs/svelte/issues/5259))
* Fix setting one-way bound `<input>` `value` to `undefined` when it has spread attributes ([#5270](https://github.com/sveltejs/svelte/issues/5270))
* Fix deep two-way bindings inside an `{#each}` involving a store ([#5286](https://github.com/sveltejs/svelte/issues/5286))
## 3.24.1
* Prevent duplicate invalidation with certain two-way component bindings ([#3180](https://github.com/sveltejs/svelte/issues/3180), [#5117](https://github.com/sveltejs/svelte/issues/5117), [#5144](https://github.com/sveltejs/svelte/issues/5144))
* Fix reactivity when passing `$$props` to a `<slot>` ([#3364](https://github.com/sveltejs/svelte/issues/3364))
* Fix transitions on `{#each}` `{:else}` ([#4970](https://github.com/sveltejs/svelte/issues/4970))
* Fix unneeded invalidation of `$$props` and `$$restProps` ([#4993](https://github.com/sveltejs/svelte/issues/4993), [#5118](https://github.com/sveltejs/svelte/issues/5118))
* Provide better compiler error message when mismatched tags are due to autoclosing of tags ([#5049](https://github.com/sveltejs/svelte/issues/5049))
* Add `a11y-label-has-associated-control` warning ([#5074](https://github.com/sveltejs/svelte/pull/5074))
* Add `a11y-media-has-caption` warning ([#5075](https://github.com/sveltejs/svelte/pull/5075))
* Fix `bind:group` when using contextual reference ([#5174](https://github.com/sveltejs/svelte/issues/5174))
## 3.24.0
* Support nullish coalescing (`??`) and optional chaining (`?.`) operators ([#1972](https://github.com/sveltejs/svelte/issues/1972))
* Support `import.meta` ([#4379](https://github.com/sveltejs/svelte/issues/4379))
* Fix only setting `<input>` values when they're changed when there are spread attributes ([#4418](https://github.com/sveltejs/svelte/issues/4418))
* Fix placement of `{@html}` when used at the root of a slot, at the root of a component, or in `<svelte:head>` ([#5012](https://github.com/sveltejs/svelte/issues/5012), [#5071](https://github.com/sveltejs/svelte/pull/5071))
* Fix certain handling of two-way bound `contenteditable` elements ([#5018](https://github.com/sveltejs/svelte/issues/5018))
* Fix handling of `import`ed value that is used as a store and is also mutated ([#5019](https://github.com/sveltejs/svelte/issues/5019))
* Do not display `a11y-missing-content` warning on elements with `contenteditable` bindings ([#5020](https://github.com/sveltejs/svelte/issues/5020))
* Fix handling of `this` in inline function expressions in the template ([#5033](https://github.com/sveltejs/svelte/issues/5033))
* Fix collapsing HTML with static content ([#5040](https://github.com/sveltejs/svelte/issues/5040))
* Prevent use of `$store` at compile time when top-level `store` has been shadowed ([#5048](https://github.com/sveltejs/svelte/issues/5048))
* Update `<select>` with one-way `value` binding when the available `<option>`s change ([#5051](https://github.com/sveltejs/svelte/issues/5051))
* Fix published `tweened` types so the `.set()` and `.update()` options are optional ([#5062](https://github.com/sveltejs/svelte/issues/5062))
* Fix contextual `bind:this` inside `{#each}` block ([#5067](https://github.com/sveltejs/svelte/issues/5067))
* Preprocess self-closing `<script>` and `<style>` tags ([#5080](https://github.com/sveltejs/svelte/issues/5080))
* Fix types for animation- and transition-related param objects so each param is optional ([#5083](https://github.com/sveltejs/svelte/pull/5083))
## 3.23.2
* Fix `bind:group` inside `{#each}` ([#3243](https://github.com/sveltejs/svelte/issues/3243))
* Don't crash when using an arrow function as a statement ([#4617](https://github.com/sveltejs/svelte/issues/4617))
* Deconflict `bind:this` variable ([#4636](https://github.com/sveltejs/svelte/issues/4636))
## 3.23.1
* Fix checkbox `bind:group` when multiple options have the same value ([#4397](https://github.com/sveltejs/svelte/issues/4397))
* Fix `bind:this` to the value of an `{#each}` block ([#4517](https://github.com/sveltejs/svelte/issues/4517))
* Fix reactivity when assigning to contextual `{#each}` variable ([#4574](https://github.com/sveltejs/svelte/issues/4574), [#4744](https://github.com/sveltejs/svelte/issues/4744))
* Fix binding to contextual `{#each}` values that shadow outer names ([#4757](https://github.com/sveltejs/svelte/issues/4757))
* Work around EdgeHTML DOM issue when removing attributes during hydration ([#4911](https://github.com/sveltejs/svelte/pull/4911))
* Throw CSS parser error when `:global()` does not contain a selector ([#4930](https://github.com/sveltejs/svelte/issues/4930))
## 3.23.0
* Update `<select>` with `bind:value` when the available `<option>`s change ([#1764](https://github.com/sveltejs/svelte/issues/1764))
* Add `muted` binding for media elements ([#2998](https://github.com/sveltejs/svelte/issues/2998))
* Fix inconsistencies when setting a two-way bound `<input>` to `undefined` ([#3569](https://github.com/sveltejs/svelte/issues/3569))
* Fix setting `<select multiple>` when there are spread attributes ([#4392](https://github.com/sveltejs/svelte/issues/4392))
* Fix let-less `<slot>` with context overflow ([#4624](https://github.com/sveltejs/svelte/issues/4624))
* Fix resize listening on certain older browsers ([#4752](https://github.com/sveltejs/svelte/issues/4752))
* Add `a11y-no-onchange` warning ([#4788](https://github.com/sveltejs/svelte/pull/4788))
* Fix `use:` actions being recreated when a keyed `{#each}` is reordered ([#4693](https://github.com/sveltejs/svelte/issues/4693))
* Fix `{@html}` when using tags that can only appear inside certain tags ([#4852](https://github.com/sveltejs/svelte/issues/4852))
* Fix reactivity when binding directly to `{#each}` context ([#4879](https://github.com/sveltejs/svelte/issues/4879))
* Add `muted` binding for media elements ([#2998](https://github.com/sveltejs/svelte/issues/2998))
* Fix let-less `<slot>` with context overflow ([#4624](https://github.com/sveltejs/svelte/issues/4624))
## 3.22.3

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

@ -20,15 +20,6 @@ Svelte is a new way to build web applications. It's a compiler that takes your d
Learn more at the [Svelte website](https://svelte.dev), or stop by the [Discord chatroom](https://svelte.dev/chat).
## Supporting Svelte
Svelte is an MIT-licensed open source project with its ongoing development made possible entirely by the support of awesome volunteers. If you'd like to support their efforts, please consider:
- [Becoming a backer on Open Collective](https://opencollective.com/svelte).
Funds donated via Open Collective will be used for compensating expenses related to Svelte's development such as hosting costs. If sufficient donations are received, funds may also be used to support Svelte's development more directly.
## Development
Pull requests are encouraged and always welcome. [Pick an issue](https://github.com/sveltejs/svelte/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) and help us out!
@ -43,6 +34,11 @@ npm install
> Do not use Yarn to install the dependencies, as the specific package versions in `package-lock.json` are used to build and test Svelte.
> Many tests depend on newlines being preserved as `<LF>`. On Windows, you can ensure this by cloning with:
> ```bash
> git -c core.autocrlf=false clone https://github.com/sveltejs/svelte.git
> ```
To build the compiler, and all the other modules included in the package:
```bash
@ -73,11 +69,14 @@ 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.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.dev). To develop locally:
### Is svelte.dev down?
```bash
cd site
npm install && npm run update
npm run dev
```
Probably not, but it's possible. If you can't seem to access any `.dev` sites, check out [this SuperUser question and answer](https://superuser.com/q/1413402).
## License

1293
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
{
"name": "svelte",
"version": "3.24.1",
"version": "3.22.3",
"description": "Cybernetically enhanced web apps",
"module": "index.mjs",
"main": "index",
@ -63,19 +63,18 @@
"@rollup/plugin-sucrase": "^3.0.0",
"@rollup/plugin-typescript": "^2.0.1",
"@rollup/plugin-virtual": "^2.0.0",
"@sveltejs/eslint-config": "github:sveltejs/eslint-config#v5.0.0",
"@types/mocha": "^5.2.7",
"@types/node": "^8.10.53",
"@typescript-eslint/eslint-plugin": "^3.0.2",
"@typescript-eslint/parser": "^3.0.2",
"acorn": "^7.3.1",
"@typescript-eslint/eslint-plugin": "^1.13.0",
"@typescript-eslint/parser": "^2.1.0",
"acorn": "^7.1.0",
"agadoo": "^1.1.0",
"c8": "^5.0.1",
"code-red": "^0.1.3",
"code-red": "0.1.1",
"codecov": "^3.5.0",
"css-tree": "1.0.0-alpha22",
"eslint": "^7.1.0",
"eslint-plugin-import": "^2.20.2",
"eslint": "^6.3.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-svelte3": "^2.7.3",
"estree-walker": "^1.0.0",
"is-reference": "^1.1.4",
@ -85,7 +84,7 @@
"magic-string": "^0.25.3",
"mocha": "^6.2.0",
"periscopic": "^2.0.1",
"puppeteer": "^2.1.1",
"puppeteer": "^1.19.0",
"rollup": "^1.27.14",
"source-map": "^0.7.3",
"source-map-support": "^0.5.13",

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

@ -1,33 +1,24 @@
## Running locally
Set up the site sub-project:
Set up the project:
```bash
git clone https://github.com/sveltejs/svelte.git
cd svelte
npm ci
PUBLISH=1 npm run build
cd site
npm ci
npm run update
npm run dev
```
and navigate to [localhost:3000](http://localhost:3000).
Start the server with `npm run dev`, and navigate to [localhost:3000](http://localhost:3000).
## Running using the local copy of Svelte
## Using a local copy of Svelte
By default, the REPL will fetch the most recent version of Svelte from https://unpkg.com/svelte. When running the site locally, you can also use your local copy of Svelte.
To produce the proper browser-compatible UMD build of the compiler, you will need to run `npm run build` (or `npm run dev`) in the root of this repository with the `PUBLISH` environment variable set to any non-empty string:
```bash
git clone https://github.com/sveltejs/svelte.git
cd svelte
npm ci
PUBLISH=1 npm run build
cd site
npm ci
npm run update
npm run dev
```
To produce the proper browser-compatible UMD build of the compiler, you will need to run `npm run build` (or `npm run dev`) in the root of this repository with the `PUBLISH` environment variable set to any non-empty string.
Then visit the REPL at [localhost:3000/repl?version=local](http://localhost:3000/repl?version=local). Please note that the local REPL only works with `npm run dev` and not when building the site for production usage.
@ -44,7 +35,6 @@ In order for the REPL's GitHub integration to work properly when running locally
GITHUB_CLIENT_SECRET=[your app's Client Secret]
BASEURL=http://localhost:3000
```
## Building the site
To build the website, run `npm run sapper`. The output can be found in `__sapper__/build`.
@ -53,26 +43,6 @@ To build the website, run `npm run sapper`. The output can be found in `__sapper
Tests can be run using `npm run test`.
## Linking `@sveltejs/site-kit` and `@sveltejs/site-repl`
This site depends on `@sveltejs/site-kit`, a collection of styles, components and icons used in common by *.svelte.dev websites, and `@sveltejs/site-repl`.
In order to work on features that depend on those packages, you need to [link](https://docs.npmjs.com/cli/link) their repositories:
- `cd <somewhere>`
- `git clone https://github.com/sveltejs/site-kit`
- `git clone https://github.com/sveltejs/svelte-repl`
- `cd <somewhere>/site-kit`
- `npm link`
- `cd <somewhere>/svelte-repl`
- `npm link`
- `cd <svelte-repo>/site`
- `npm link @sveltejs/site-kit`
- `npm link @sveltejs/svelte-repl`
## Translating the API docs
Anchors are automatically generated using headings in the documentation and by default (for the english language) they are latinised to make sure the URL is always conforming to RFC3986.

@ -30,7 +30,7 @@ Given that, what if the framework *didn't actually run in the browser*? What if,
Svelte is a new framework that does exactly that. You write your components using HTML, CSS and JavaScript (plus a few extra bits you can [learn in under 5 minutes](https://v2.svelte.dev/guide)), and during your build process Svelte compiles them into tiny standalone JavaScript modules. By statically analysing the component template, we can make sure that the browser does as little work as possible.
The [Svelte implementation of TodoMVC](https://svelte-todomvc.surge.sh/) weighs 3.6kb zipped. For comparison, React plus ReactDOM *without any app code* weighs about 45kb zipped. It takes about 10x as long for the browser just to evaluate React as it does for Svelte to be up and running with an interactive TodoMVC.
The [Svelte implementation of TodoMVC](http://svelte-todomvc.surge.sh/) weighs 3.6kb zipped. For comparison, React plus ReactDOM *without any app code* weighs about 45kb zipped. It takes about 10x as long for the browser just to evaluate React as it does for Svelte to be up and running with an interactive TodoMVC.
And once your app *is* up and running, according to [js-framework-benchmark](https://github.com/krausest/js-framework-benchmark) **Svelte is fast as heck**. It's faster than React. It's faster than Vue. It's faster than Angular, or Ember, or Ractive, or Preact, or Riot, or Mithril. It's competitive with Inferno, which is probably the fastest UI framework in the world, for now, because [Dominic Gannaway](https://twitter.com/trueadm) is a wizard. (Svelte is slower at removing elements. We're [working on it](https://github.com/sveltejs/svelte/issues/26).)

@ -5,7 +5,7 @@ author: Rich Harris
authorURL: https://twitter.com/Rich_Harris
---
> Quickstart for the impatient: [the Sapper docs](https://sapper.svelte.dev), and the [starter template](https://github.com/sveltejs/sapper-template)
> Quickstart for the impatient: [the Sapper docs](https://sapper.svelte.technology), and the [starter template](https://github.com/sveltejs/sapper-template)
If you had to list the characteristics of the perfect Node.js web application framework, you'd probably come up with something like this:
@ -47,9 +47,9 @@ What happens if we use the new model as a starting point?
## Introducing Sapper
<aside><p>The <a href="https://sapper.svelte.dev/docs#Why_the_name">name comes from</a> the term for combat engineers, and is also short for Svelte app maker</p></aside>
<aside><p>The <a href="https://sapper.svelte.technology/docs#why-the-name-">name comes from</a> the term for combat engineers, and is also short for Svelte app maker</p></aside>
[Sapper](https://sapper.svelte.dev) is the answer to that question. **Sapper is a Next.js-style framework that aims to meet the eleven criteria at the top of this article while dramatically reducing the amount of code that gets sent to the browser.** It's implemented as Express-compatible middleware, meaning it's easy to understand and customise.
[Sapper](https://sapper.svelte.technology) is the answer to that question. **Sapper is a Next.js-style framework that aims to meet the eleven criteria at the top of this article while dramatically reducing the amount of code that gets sent to the browser.** It's implemented as Express-compatible middleware, meaning it's easy to understand and customise.
The same 'hello world' app that took 204kb with React and Next weighs just 7kb with Sapper. That number is likely to fall further in the future as we explore the space of optimisation possibilities, such as not shipping any JavaScript *at all* for pages that aren't interactive, beyond the tiny Sapper runtime that handles client-side routing.
@ -57,7 +57,7 @@ What about a more 'real world' example? Conveniently, the [RealWorld](https://gi
<aside><p>Code-splitting isn't free — if the reference implementation used code-splitting, it would be larger still</p></aside>
The entire app costs 132.7kb (39.9kb zipped), which is significantly smaller than the reference React/Redux implementation at 327kb (85.7kb), but even if it was as large it would *feel* faster because of code-splitting. And that's a crucial point. We're told we need to code-split our apps, but if your app uses a traditional framework like React or Vue then there's a hard lower bound on the size of your initial code-split chunk — the framework itself, which is likely to be a significant portion of your total app size. With the Svelte approach, that's no longer the case.
The entire app costs 132.7kb (39.9kb zipped), which is significantly smaller than the reference React/Redux implementation at 327kb (85.7kb), but even if was as large it would *feel* faster because of code-splitting. And that's a crucial point. We're told we need to code-split our apps, but if your app uses a traditional framework like React or Vue then there's a hard lower bound on the size of your initial code-split chunk — the framework itself, which is likely to be a significant portion of your total app size. With the Svelte approach, that's no longer the case.
But size is only part of the story. Svelte apps are also extremely performant and memory-efficient, and the framework includes powerful features that you would sacrifice if you chose a 'minimal' or 'simple' UI library.

@ -51,7 +51,7 @@ Once installed, you'll have access to three new commands:
## Installing a text editor
To write code, you need a good editor. The most popular choice is [Visual Studio Code](https://code.visualstudio.com/) or VSCode, and justifiably so — it's well-designed and fully-featured, and has a wealth of extensions ([including one for Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode), which provides syntax highlighting and diagnostic messages when you're writing components).
To write code, you need a good editor. The most popular choice is [Visual Studio Code](https://code.visualstudio.com/) or VSCode, and justifiably so — it's well-designed and fully-featured, and has a wealth of extensions ([including one for Svelte](https://marketplace.visualstudio.com/items?itemName=JamesBirtles.svelte-vscode), which provides syntax highlighting and diagnostic messages when you're writing components).
## Creating a project
@ -74,6 +74,8 @@ This creates a new directory, `my-svelte-project`, adds files from the [sveltejs
In the `package.json` file, there is a section called `"scripts"`. These scripts define shortcuts for working with your application — `dev`, `build` and `start`. To launch your app in development mode, type the following:
> TODO update the template, it needs... some work
```bash
npm run dev
```

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

@ -121,9 +121,6 @@ An element or component can have multiple spread attributes, interspersed with r
<input {...$$restProps}>
```
> The `value` attribute of an `input` element or its children `option` elements must not be set with spread attributes when using `bind:group` or `bind:checked`. Svelte needs to be able to see the element's `value` directly in the markup in these cases so that it can link it to the bound variable.
---
### Text expressions
@ -544,21 +541,6 @@ Numeric input values are coerced; even though `input.value` is a string as far a
<input type="range" bind:value={num}>
```
---
On `<input>` elements with `type="file"`, you can use `bind:files` to get the [`FileList` of selected files](https://developer.mozilla.org/en-US/docs/Web/API/FileList).
```sv
<label for="avatar">Upload a picture:</label>
<input
accept="image/png, image/jpeg"
bind:files
id="avatar"
name="avatar"
type="file"
/>
```
##### Binding `<select>` value
@ -616,18 +598,18 @@ Media elements (`<audio>` and `<video>`) have their own set of bindings — six
* `duration` (readonly) — the total duration of the video, in seconds
* `buffered` (readonly) — an array of `{start, end}` objects
* `played` (readonly) — ditto
* `seekable` (readonly) — ditto
* `played` (readonly) — ditto
* `seeking` (readonly) — boolean
* `ended` (readonly) — boolean
...and five *two-way* bindings:
* `currentTime` — the current playback time in the video, in seconds
* `playbackRate` — how fast or slow to play the video, where 1 is 'normal'
* `currentTime` — the current point in the video, in seconds
* `playbackRate` — how fast to play the video, where 1 is 'normal'
* `paused` — this one should be self-explanatory
* `volume` — a value between 0 and 1
* `muted` — a boolean value where `true` is muted
* `muted` — a boolean value where true is muted
Videos additionally have readonly `videoWidth` and `videoHeight` bindings.
@ -636,12 +618,11 @@ Videos additionally have readonly `videoWidth` and `videoHeight` bindings.
src={clip}
bind:duration
bind:buffered
bind:played
bind:seekable
bind:seeking
bind:played
bind:ended
bind:currentTime
bind:playbackRate
bind:paused
bind:volume
bind:muted
@ -788,7 +769,7 @@ Actions are functions that are called when an element is created. They can retur
---
An action can have a parameter. If the returned value has an `update` method, it will be called whenever that parameter changes, immediately after Svelte has applied updates to the markup.
An action can have parameters. If the returned value has an `update` method, it will be called whenever those parameters change, immediately after Svelte has applied updates to the markup.
> Don't worry about the fact that we're redeclaring the `foo` function for every component instance — Svelte will hoist any functions that don't depend on local state out of the component definition.

@ -50,8 +50,6 @@ If a function is returned from `onMount`, it will be called when the component i
</script>
```
> This behaviour will only work when the function passed to `onMount` *synchronously* returns a value. `async` functions always return a `Promise`, and as such cannot *synchronously* return a function.
#### `beforeUpdate`
```js
@ -289,9 +287,7 @@ The second argument to `readable` is the same as the second argument to `writabl
```js
import { readable } from 'svelte/store';
const time = readable(null, set => {
set(new Date());
const time = readable(new Date(), set => {
const interval = setInterval(() => {
set(new Date());
}, 1000);
@ -525,7 +521,7 @@ $: $size = big ? 100 : 10;
### `svelte/transition`
The `svelte/transition` module exports seven functions: `fade`, `blur`, `fly`, `slide`, `scale`, `draw` and `crossfade`. They are for use with Svelte [`transitions`](docs#transition_fn).
The `svelte/transition` module exports six functions: `fade`, `fly`, `slide`, `scale`, `draw` and `crossfade`. They are for use with Svelte [`transitions`](docs#transition_fn).
#### `fade`

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

@ -16,10 +16,16 @@
$: remaining = todos.filter(t => !t.done).length;
</script>
<style>
.done {
opacity: 0.4;
}
</style>
<h1>Todos</h1>
{#each todos as todo}
<div>
<div class:done={todo.done}>
<input
type=checkbox
bind:checked={todo.done}
@ -28,7 +34,6 @@
<input
placeholder="What needs to be done?"
bind:value={todo.text}
disabled={todo.done}
>
</div>
{/each}

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

@ -20,7 +20,7 @@
const t = window.performance.now();
const r = 64 + (128 * x / canvas.width) + (64 * Math.sin(t / 1000));
const g = 64 + (128 * y / canvas.height) + (64 * Math.cos(t / 1400));
const g = 64 + (128 * y / canvas.height) + (64 * Math.cos(t / 1000));
const b = 128;
imageData.data[p + 0] = r;

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

@ -2,11 +2,7 @@
question: Are there any video courses?
---
Rich Harris, the creator of Svelte, taught a course:
- [Frontend Masters](https://frontendmasters.com/courses/svelte/)
There are also a couple of third-party courses:
There are no official ones, but here are a couple of third-part ones that we know of.
- [Egghead](https://egghead.io/playlists/getting-started-with-svelte-3-05a8541a)
- [Udemy](https://www.udemy.com/sveltejs-the-complete-guide/)

@ -0,0 +1,5 @@
---
question: Is svelte.dev down?
---
Probably not, but it's possible. If you can't seem to access any `.dev` sites, check out [this SuperUser question and answer](https://superuser.com/q/1413402).

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

@ -1,32 +0,0 @@
---
question: How do I document my components?
---
In editors which use the Svelte Language Server you can document Components, functions and exports using specially formatted comments.
````svelte
<script>
/** What should we call the user? */
export let name = 'world';
</script>
<!--
@component
Here's some documentation for this component.
It will show up on hover.
- You can use markdown here.
- You can also use code blocks here.
- Usage:
```tsx
<main name="Arethra">
```
-->
<main>
<h1>
Hello, {name}
</h1>
</main>
````
Note: The `@component` is necessary in the HTML comment which describes your component.

@ -1,20 +1,5 @@
---
question: What about TypeScript support?
question: What about Typescript support?
---
You need to install a preprocessor such as [svelte-preprocess](https://github.com/sveltejs/svelte-preprocess). You can run type checking from the command line with [svelte-check](https://www.npmjs.com/package/svelte-check).
To declare the type of a reactive variable in a Svelte template, you should use the following syntax:
```
let x: number;
$: x = count + 1;
```
To import a type or interface make sure to use [TypeScript's `type` modifier](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export):
```
import type { SomeInterface } from './SomeFile';
```
You must use the `type` modifier because `svelte-preprocess` doesn't know whether an import is a type or a value — it only transpiles one file at a time without knowledge of the other files and therefore can't safely erase imports which only contain types without this modifier present.
You need to install a [community supported preprocessor](https://github.com/sveltejs/integrations#preprocessors) such as [svelte-preprocess](https://github.com/kaisermann/svelte-preprocess). Work is ongoing to improve [IDE support](https://github.com/sveltejs/language-tools/issues/83) and build [additional CLI tooling](https://github.com/sveltejs/language-tools/issues/68)

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

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

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

@ -1,10 +1,10 @@
import 'dotenv/config';
import babel from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import replace from '@rollup/plugin-replace';
import resolve from '@rollup/plugin-node-resolve';
import resolve from 'rollup-plugin-node-resolve';
import replace from 'rollup-plugin-replace';
import commonjs from 'rollup-plugin-commonjs';
import svelte from 'rollup-plugin-svelte';
import babel from 'rollup-plugin-babel';
import json from 'rollup-plugin-json';
import { terser } from 'rollup-plugin-terser';
import config from 'sapper/config/rollup.js';
import pkg from './package.json';
@ -13,10 +13,6 @@ const mode = process.env.NODE_ENV;
const dev = mode === 'development';
const legacy = !!process.env.SAPPER_LEGACY_BUILD;
if (!dev && !process.env.MAPBOX_ACCESS_TOKEN) {
throw new Error('MAPBOX_ACCESS_TOKEN is missing. Please add the token in the .env file before generating the production build.');
}
const onwarn = (warning, onwarn) => (warning.code === 'CIRCULAR_DEPENDENCY' && /[/\\]@sapper[/\\]/.test(warning.message)) || onwarn(warning);
const dedupe = importee => importee === 'svelte' || importee.startsWith('svelte/');
@ -44,7 +40,7 @@ export default {
legacy && babel({
extensions: ['.js', '.mjs', '.html', '.svelte'],
babelHelpers: 'runtime',
runtimeHelpers: true,
exclude: ['node_modules/@babel/**'],
presets: [
['@babel/preset-env', {
@ -63,8 +59,6 @@ export default {
module: true
})
],
preserveEntrySignatures: false,
onwarn
},
@ -93,8 +87,6 @@ export default {
require('module').builtinModules || Object.keys(process.binding('natives'))
)
],
preserveEntrySignatures: 'strict',
onwarn
},
@ -109,9 +101,6 @@ export default {
}),
commonjs(),
!dev && terser()
],
preserveEntrySignatures: false,
onwarn
]
}
};

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

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

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

@ -62,7 +62,6 @@
<style>
main {
height: 100%;
position: relative;
margin: 0 auto;
/* padding: var(--nav-h) var(--side-nav) 0 var(--side-nav); */

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

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

@ -85,7 +85,7 @@ export default function() {
renderer.heading = (text, level, rawtext) => {
let slug;
const match = /<a href="([^"]+)"[^>]*>(.+)<\/a>/.exec(text);
const match = /<a href="([^"]+)">(.+)<\/a>/.exec(text);
if (match) {
slug = match[1];
text = match[2];

@ -227,8 +227,6 @@ export default app;` });
padding: .6rem var(--side-nav);
background-color: var(--second);
color: white;
white-space: nowrap;
flex: 0;
}
.icon {

@ -117,7 +117,7 @@
<style>
.repl-outer {
position: relative;
height: 100%;
height: calc(100vh - var(--nav-h));
--app-controls-h: 5.6rem;
--pane-controls-h: 4.2rem;
overflow: hidden;
@ -125,8 +125,6 @@
padding: var(--app-controls-h) 0 0 0;
/* margin: 0 calc(var(--side-nav) * -1); */
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.viewport {
@ -138,7 +136,6 @@
width: 200%;
height: calc(100% - 42px);
transition: transform 0.3s;
flex: 1;
}
.mobile .offset {

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

@ -64,7 +64,7 @@
</style>
<nav>
<a rel="prefetch" aria-label="Previous tutorial step" class="no-underline" href="tutorial/{(selected.prev || selected).slug}" class:disabled={!selected.prev}>
<a rel="prefetch" class="no-underline" href="tutorial/{(selected.prev || selected).slug}" class:disabled={!selected.prev}>
<Icon name="arrow-left" />
</a>
@ -88,7 +88,7 @@
</select>
</div>
<a rel="prefetch" aria-label="Next tutorial step" class="no-underline" href="tutorial/{(selected.next || selected).slug}" class:disabled={!selected.next}>
<a rel="prefetch" class="no-underline" href="tutorial/{(selected.next || selected).slug}" class:disabled={!selected.next}>
<Icon name="arrow-right" />
</a>
</nav>

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 KiB

@ -8,7 +8,7 @@ import {
create_scopes,
extract_names,
Scope,
extract_identifiers
extract_identifiers,
} from './utils/scope';
import Stylesheet from './css/Stylesheet';
import { test } from '../config';
@ -155,7 +155,7 @@ export default class Component {
) || { start: 0, end: 0 };
this.warn(svelteOptions, {
code: 'custom-element-no-tag',
message: `No custom element 'tag' option was specified. To automatically register a custom element, specify a name with a hyphen in it, e.g. <svelte:options tag="my-thing"/>. To hide this warning, use <svelte:options tag={null}/>`
message: `No custom element 'tag' option was specified. To automatically register a custom element, specify a name with a hyphen in it, e.g. <svelte:options tag="my-thing"/>. To hide this warning, use <svelte:options tag={null}/>`,
});
}
this.tag = this.component_options.tag || compile_options.tag;
@ -190,7 +190,7 @@ export default class Component {
this.add_var({
name,
injected: true,
referenced: true
referenced: true,
});
} else if (name[0] === '$') {
this.add_var({
@ -198,7 +198,7 @@ export default class Component {
injected: true,
referenced: true,
mutated: true,
writable: true
writable: true,
});
const subscribable_name = name.slice(1);
@ -289,7 +289,7 @@ export default class Component {
}
const imported_helpers = Array.from(this.helpers, ([name, alias]) => ({
name,
alias
alias,
}));
create_module(
@ -305,7 +305,7 @@ export default class Component {
.filter(variable => variable.module && variable.export_name)
.map(variable => ({
name: variable.name,
as: variable.export_name
as: variable.export_name,
}))
);
@ -342,9 +342,9 @@ export default class Component {
reassigned: v.reassigned || false,
referenced: v.referenced || false,
writable: v.writable || false,
referenced_from_script: v.referenced_from_script || false
referenced_from_script: v.referenced_from_script || false,
})),
stats: this.stats.render()
stats: this.stats.render(),
};
}
@ -409,7 +409,7 @@ export default class Component {
source: this.source,
start: pos.start,
end: pos.end,
filename: this.compile_options.filename
filename: this.compile_options.filename,
});
}
@ -441,7 +441,7 @@ export default class Component {
pos: pos.start,
filename: this.compile_options.filename,
toString: () =>
`${warning.message} (${start.line}:${start.column})\n${frame}`
`${warning.message} (${start.line}:${start.column})\n${frame}`,
});
}
@ -453,7 +453,7 @@ export default class Component {
if (node.type === 'ExportDefaultDeclaration') {
this.error(node, {
code: `default-export`,
message: `A component cannot have a default export`
message: `A component cannot have a default export`,
});
}
@ -461,7 +461,7 @@ export default class Component {
if (node.source) {
this.error(node, {
code: `not-implemented`,
message: `A component currently cannot have an export ... from`
message: `A component currently cannot have an export ... from`,
});
}
if (node.declaration) {
@ -531,10 +531,10 @@ export default class Component {
if (node.type === 'LabeledStatement' && node.label.name === '$') {
component.warn(node as any, {
code: 'module-script-reactive-declaration',
message: '$: has no effect in a module script'
message: '$: has no effect in a module script',
});
}
}
},
});
const { scope, globals } = create_scopes(script.content);
@ -544,7 +544,7 @@ export default class Component {
if (name[0] === '$') {
this.error(node as any, {
code: 'illegal-declaration',
message: `The $ prefix is reserved, and cannot be used for variable and import names`
message: `The $ prefix is reserved, and cannot be used for variable and import names`,
});
}
@ -562,7 +562,7 @@ export default class Component {
if (name[0] === '$') {
this.error(node as any, {
code: 'illegal-subscription',
message: `Cannot reference store value inside <script context="module">`
message: `Cannot reference store value inside <script context="module">`,
});
} else {
this.add_var({
@ -623,7 +623,7 @@ export default class Component {
if (name[0] === '$') {
this.error(node as any, {
code: 'illegal-declaration',
message: `The $ prefix is reserved, and cannot be used for variable and import names`
message: `The $ prefix is reserved, and cannot be used for variable and import names`,
});
}
@ -647,12 +647,12 @@ export default class Component {
injected: true,
writable: true,
reassigned: true,
initialised: true
initialised: true,
});
} else if (is_reserved_keyword(name)) {
this.add_var({
name,
injected: true
injected: true,
});
} else if (name[0] === '$') {
if (name === '$' || name[1] === '$') {
@ -666,7 +666,7 @@ export default class Component {
name,
injected: true,
mutated: true,
writable: true
writable: true,
});
this.add_reference(name.slice(1));
@ -764,7 +764,7 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
}
},
});
for (const [parent, prop, index] of to_remove) {
@ -832,11 +832,11 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
}
},
});
}
warn_on_undefined_store_value_references(node, parent, scope: Scope) {
warn_on_undefined_store_value_references(node, parent, scope) {
if (
node.type === 'LabeledStatement' &&
node.label.name === '$' &&
@ -844,7 +844,7 @@ export default class Component {
) {
this.warn(node as any, {
code: 'non-top-level-reactive-declaration',
message: '$: has no effect outside of the top-level'
message: '$: has no effect outside of the top-level',
});
}
@ -852,17 +852,8 @@ export default class Component {
const object = get_object(node);
const { name } = object;
if (name[0] === '$') {
if (!scope.has(name)) {
this.warn_if_undefined(name, object, null);
}
if (name[1] !== '$' && scope.has(name.slice(1)) && scope.find_owner(name.slice(1)) !== this.instance_scope) {
this.error(node, {
code: `contextual-store`,
message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
});
}
if (name[0] === '$' && !scope.has(name)) {
this.warn_if_undefined(name, object, null);
}
}
}
@ -881,7 +872,7 @@ export default class Component {
if (node.body.type !== 'BlockStatement') {
node.body = {
type: 'BlockStatement',
body: [node.body]
body: [node.body],
};
}
node.body.body.push(inside[0]);
@ -890,8 +881,8 @@ export default class Component {
type: 'BlockStatement',
body: [
before[0],
node
]
node,
],
};
}
return null;
@ -927,7 +918,7 @@ export default class Component {
// TODO is this still true post-#3539?
component.error(declarator as any, {
code: 'destructured-prop',
message: `Cannot declare props in destructured declaration`
message: `Cannot declare props in destructured declaration`,
});
}
@ -990,7 +981,7 @@ export default class Component {
if (node.type === 'ExportNamedDeclaration' && node.declaration) {
(parent as Program).body[index] = node.declaration;
}
}
},
});
}
@ -1004,7 +995,7 @@ export default class Component {
hoistable_nodes,
var_lookup,
injected_reactive_declaration_vars,
imports
imports,
} = this;
const top_level_function_declarations = new Map();
@ -1136,7 +1127,7 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
}
},
});
checked.add(fn_declaration);
@ -1161,9 +1152,7 @@ export default class Component {
for (const specifier of specifiers) {
const variable = var_lookup.get(specifier.local.name);
if (!variable.mutated || variable.subscribable) {
variable.hoistable = true;
}
if (!variable.mutated) variable.hoistable = true;
}
}
}
@ -1229,7 +1218,7 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
}
},
});
const { expression } = node.body as ExpressionStatement;
@ -1239,7 +1228,7 @@ export default class Component {
assignees,
dependencies,
node,
declaration
declaration,
});
}
});
@ -1320,7 +1309,7 @@ export default class Component {
this.warn(node, {
code: 'missing-declaration',
message
message,
});
}
@ -1343,7 +1332,7 @@ function process_component_options(component: Component, nodes) {
'accessors' in component.compile_options
? component.compile_options.accessors
: !!component.compile_options.customElement,
preserveWhitespace: !!component.compile_options.preserveWhitespace
preserveWhitespace: !!component.compile_options.preserveWhitespace,
};
const node = nodes.find(node => node.name === 'svelte:options');
@ -1384,7 +1373,7 @@ function process_component_options(component: Component, nodes) {
if (tag && !/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) {
component.error(attribute, {
code: `invalid-tag-property`,
message: `tag name must be two or more words joined by the '-' character`
message: `tag name must be two or more words joined by the '-' character`,
});
}
@ -1412,12 +1401,12 @@ function process_component_options(component: Component, nodes) {
if (match) {
component.error(attribute, {
code: `invalid-namespace-property`,
message: `Invalid namespace '${ns}' (did you mean '${match}'?)`
message: `Invalid namespace '${ns}' (did you mean '${match}'?)`,
});
} else {
component.error(attribute, {
code: `invalid-namespace-property`,
message: `Invalid namespace '${ns}'`
message: `Invalid namespace '${ns}'`,
});
}
}
@ -1443,13 +1432,13 @@ function process_component_options(component: Component, nodes) {
default:
component.error(attribute, {
code: `invalid-options-attribute`,
message: `<svelte:options> unknown attribute`
message: `<svelte:options> unknown attribute`,
});
}
} else {
component.error(attribute, {
code: `invalid-options-attribute`,
message: `<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes`
message: `<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes`,
});
}
});

@ -435,7 +435,7 @@ export default class Stylesheet {
child.warn_on_unused_selector((selector: Selector) => {
component.warn(selector.node, {
code: `css-unused-selector`,
message: `Unused CSS selector "${this.source.slice(selector.node.start, selector.node.end)}"`
message: `Unused CSS selector`
});
});
});

@ -52,7 +52,7 @@ function validate_options(options: CompileOptions, warnings: Warning[]) {
code: `options-lowercase-name`,
message,
filename,
toString: () => message
toString: () => message,
});
}
@ -62,7 +62,7 @@ function validate_options(options: CompileOptions, warnings: Warning[]) {
code: `options-loop-guard-timeout`,
message,
filename,
toString: () => message
toString: () => message,
});
}
}

@ -41,8 +41,7 @@ export default class Binding extends Node {
this.raw_expression = JSON.parse(JSON.stringify(info.expression));
const { name } = get_object(this.expression.node);
this.is_contextual = Array.from(this.expression.references).some(name => scope.names.has(name));
this.is_contextual = scope.names.has(name);
// make sure we track this as a mutable ref
if (scope.is_let(name)) {
@ -50,7 +49,7 @@ export default class Binding extends Node {
code: 'invalid-binding',
message: 'Cannot bind to a variable declared with the let: directive'
});
} else if (scope.names.has(name)) {
} else if (this.is_contextual) {
if (scope.is_await(name)) {
component.error(this, {
code: 'invalid-binding',
@ -61,7 +60,7 @@ export default class Binding extends Node {
scope.dependencies_for_name.get(name).forEach(name => {
const variable = component.var_lookup.get(name);
if (variable) {
variable.mutated = true;
variable[this.expression.node.type === 'MemberExpression' ? 'mutated' : 'reassigned'] = true;
}
});
} else {
@ -76,7 +75,7 @@ export default class Binding extends Node {
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'
message: 'Cannot bind to a variable which is not writable',
});
}

@ -21,7 +21,6 @@ export default class EachBlock extends AbstractBlock {
contexts: Context[];
has_animation: boolean;
has_binding = false;
has_index_binding = false;
else?: ElseBlock;

@ -61,17 +61,6 @@ const a11y_no_onchange = new Set([
'option'
]);
const a11y_labelable = new Set([
"button",
"input",
"keygen",
"meter",
"output",
"progress",
"select",
"textarea"
]);
const invisible_elements = new Set(['meta', 'html', 'script', 'style']);
const valid_modifiers = new Set([
@ -399,7 +388,7 @@ export default class Element extends Node {
if (/(^[0-9-.])|[\^$@%&#?!|()[\]{}^*+~;]/.test(name)) {
component.error(attribute, {
code: `illegal-attribute`,
message: `'${name}' is not a valid attribute name`
message: `'${name}' is not a valid attribute name`,
});
}
@ -423,7 +412,7 @@ export default class Element extends Node {
if (!(parent.type === 'InlineComponent' || within_custom_element(parent))) {
component.error(attribute, {
code: `invalid-slotted-content`,
message: `Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`
message: `Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`,
});
}
}
@ -518,35 +507,6 @@ export default class Element extends Node {
}
}
if (this.name === 'label') {
const has_input_child = this.children.some(i => (i instanceof Element && a11y_labelable.has(i.name) ));
if (!attribute_map.has('for') && !has_input_child) {
component.warn(this, {
code: `a11y-label-has-associated-control`,
message: `A11y: A form label must be associated with a control.`
});
}
}
if (this.is_media_node()) {
if (attribute_map.has('muted')) {
return;
}
let has_caption;
const track = this.children.find((i: Element) => i.name === 'track');
if (track) {
has_caption = track.attributes.find(a => a.name === 'kind' && a.get_static_value() === 'captions');
}
if (!has_caption) {
component.warn(this, {
code: `a11y-media-has-caption`,
message: `A11y: Media elements must have a <track kind="captions">`
});
}
}
if (a11y_no_onchange.has(this.name)) {
if (handlers_map.has('change') && !handlers_map.has('blur')) {
component.warn(this, {
@ -746,10 +706,6 @@ export default class Element extends Node {
validate_content() {
if (!a11y_required_content.has(this.name)) return;
if (
this.bindings
.some((binding) => ['textContent', 'innerHTML'].includes(binding.name))
) return;
if (this.children.length === 0) {
this.component.warn(this, {

@ -12,7 +12,7 @@ const elements_without_text = new Set([
'dl',
'optgroup',
'select',
'video'
'video',
]);
export default class Text extends Node {

@ -1,5 +1,5 @@
import { x } from 'code-red';
import { Node, Identifier } from 'estree';
import { Node, Identifier, RestElement, Property } from 'estree';
export interface Context {
key: Identifier;
@ -34,10 +34,12 @@ export function unpack_destructuring(contexts: Context[], node: Node, modifier:
const used_properties = [];
node.properties.forEach((property) => {
if (property.type === 'RestElement') {
const props: (RestElement | Property) = (property as any);
if (props.type === 'RestElement') {
unpack_destructuring(
contexts,
property.argument,
props.argument,
node => x`@object_without_properties(${modifier(node)}, [${used_properties}])` as Node
);
} else {

@ -14,8 +14,6 @@ import { invalidate } from '../../render_dom/invalidate';
import { Node, FunctionExpression, Identifier } from 'estree';
import { TemplateNode } from '../../../interfaces';
import { is_reserved_keyword } from '../../utils/reserved_keywords';
import replace_object from '../../utils/replace_object';
import EachBlock from '../EachBlock';
type Owner = Wrapper | TemplateNode;
@ -24,7 +22,7 @@ export default class Expression {
component: Component;
owner: Owner;
node: any;
references: Set<string> = new Set();
references: Set<string>;
dependencies: Set<string> = new Set();
contextual_dependencies: Set<string> = new Set();
@ -50,7 +48,7 @@ export default class Expression {
this.template_scope = template_scope;
this.owner = owner;
const { dependencies, contextual_dependencies, references } = this;
const { dependencies, contextual_dependencies } = this;
let { map, scope } = create_scopes(info);
this.scope = scope;
@ -75,18 +73,14 @@ export default class Expression {
if (is_reference(node, parent)) {
const { name, nodes } = flatten_reference(node);
references.add(name);
if (scope.has(name)) return;
if (name[0] === '$') {
const store_name = name.slice(1);
if (template_scope.names.has(store_name) || scope.has(store_name)) {
component.error(node, {
code: `contextual-store`,
message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
});
}
if (name[0] === '$' && template_scope.names.has(name.slice(1))) {
component.error(node, {
code: `contextual-store`,
message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
});
}
if (template_scope.is_let(name)) {
@ -124,9 +118,12 @@ export default class Expression {
if (function_expression) {
if (node.type === 'AssignmentExpression') {
deep = node.left.type === 'MemberExpression';
names = extract_names(deep ? get_object(node.left) : node.left);
names = deep
? [get_object(node.left).name]
: extract_names(node.left);
} else if (node.type === 'UpdateExpression') {
names = extract_names(get_object(node.argument));
const { name } = get_object(node.argument);
names = [name];
}
}
@ -137,8 +134,6 @@ export default class Expression {
const variable = component.var_lookup.get(name);
if (variable) variable[deep ? 'mutated' : 'reassigned'] = true;
});
const each_block = template_scope.get_owner(name);
(each_block as EachBlock).has_binding = true;
} else {
component.add_reference(name);
@ -202,7 +197,7 @@ export default class Expression {
scope = map.get(node);
}
if (node.type === 'Identifier' && is_reference(node, parent)) {
if (is_reference(node, parent)) {
const { name } = flatten_reference(node);
if (scope.has(name)) return;
@ -316,10 +311,6 @@ export default class Expression {
if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
const object_name = get_object(assignee).name;
if (scope.has(object_name)) return;
// normally (`a = 1`, `b.c = 2`), there'll be a single name
// (a or b). In destructuring cases (`[d, e] = [e, d]`) there
// may be more, in which case we need to tack the extra ones
@ -336,23 +327,6 @@ export default class Expression {
}
});
const context = block.bindings.get(object_name);
if (context) {
// for `{#each array as item}`
// replace `item = 1` to `each_array[each_index] = 1`, this allow us to mutate the array
// rather than mutating the local `item` variable
const { snippet, object, property } = context;
const replaced: any = replace_object(assignee, snippet);
if (node.type === 'AssignmentExpression') {
node.left = replaced;
} else {
node.argument = replaced;
}
contextual_dependencies.add(object.name);
contextual_dependencies.add(property.name);
}
this.replace(invalidate(block.renderer, scope, node, traced));
}
}

@ -4,15 +4,6 @@ import { b, x } from 'code-red';
import { Node, Identifier, ArrayPattern } from 'estree';
import { is_head } from './wrappers/shared/is_head';
export interface Bindings {
object: Identifier;
property: Identifier;
snippet: Node;
store: string;
tail: Node;
modifier: (node: Node) => Node;
}
export interface BlockOptions {
parent?: Block;
name: Identifier;
@ -20,7 +11,14 @@ export interface BlockOptions {
renderer?: Renderer;
comment?: string;
key?: Identifier;
bindings?: Map<string, Bindings>;
bindings?: Map<string, {
object: Identifier;
property: Identifier;
snippet: Node;
store: string;
tail: Node;
modifier: (node: Node) => Node;
}>;
dependencies?: Set<string>;
}
@ -38,7 +36,14 @@ export default class Block {
dependencies: Set<string> = new Set();
bindings: Map<string, Bindings>;
bindings: Map<string, {
object: Identifier;
property: Identifier;
snippet: Node;
store: string;
tail: Node;
modifier: (node: Node) => Node;
}>;
chunks: {
declarations: Array<Node | Node[]>;
@ -101,7 +106,7 @@ export default class Block {
intro: [],
update: [],
outro: [],
destroy: []
destroy: [],
};
this.has_animation = false;
@ -294,7 +299,7 @@ export default class Block {
${this.chunks.mount}
}`;
} else {
properties.mount = x`function #mount(#target, #anchor) {
properties.mount = x`function #mount(#target, #anchor, #remount) {
${this.chunks.mount}
}`;
}
@ -447,9 +452,6 @@ export default class Block {
render_listeners(chunk: string = '') {
if (this.event_listeners.length > 0) {
this.add_variable({ type: 'Identifier', name: '#mounted' });
this.chunks.destroy.push(b`#mounted = false`);
const dispose: Identifier = {
type: 'Identifier',
name: `#dispose${chunk}`
@ -460,10 +462,8 @@ export default class Block {
if (this.event_listeners.length === 1) {
this.chunks.mount.push(
b`
if (!#mounted) {
${dispose} = ${this.event_listeners[0]};
#mounted = true;
}
if (#remount) ${dispose}();
${dispose} = ${this.event_listeners[0]};
`
);
@ -472,12 +472,10 @@ export default class Block {
);
} else {
this.chunks.mount.push(b`
if (!#mounted) {
${dispose} = [
${this.event_listeners}
];
#mounted = true;
}
if (#remount) @run_all(${dispose});
${dispose} = [
${this.event_listeners}
];
`);
this.chunks.destroy.push(

@ -26,13 +26,12 @@ export default class Renderer {
options: CompileOptions;
context: ContextMember[] = [];
initial_context: ContextMember[] = [];
context_lookup: Map<string, ContextMember> = new Map();
context_overflow: boolean;
blocks: Array<Block | Node | Node[]> = [];
readonly: Set<string> = new Set();
meta_bindings: Array<Node | Node[]> = []; // initial values for e.g. window.innerWidth, if there's a <svelte:window> meta tag
binding_groups: Map<string, { binding_group: (to_reference?: boolean) => Node; is_context: boolean; contexts: string[]; index: number }> = new Map();
binding_groups: string[] = [];
block: Block;
fragment: FragmentWrapper;
@ -60,10 +59,10 @@ export default class Renderer {
if (component.slots.size > 0) {
this.add_to_context('$$scope');
this.add_to_context('#slots');
this.add_to_context('$$slots');
}
if (this.binding_groups.size > 0) {
if (this.binding_groups.length > 0) {
this.add_to_context('$$binding_groups');
}
@ -76,7 +75,7 @@ export default class Renderer {
bindings: new Map(),
dependencies: new Set()
dependencies: new Set(),
});
this.block.has_update_method = true;
@ -111,12 +110,8 @@ export default class Renderer {
// these determine whether variable is included in initial context
// array, so must have the highest priority
if (variable.export_name) member.priority += 16;
if (variable.referenced) member.priority += 32;
} else if (member.is_non_contextual) {
// determine whether variable is included in initial context
// array, so must have the highest priority
member.priority += 8;
if (variable.export_name) member.priority += 8;
if (variable.referenced) member.priority += 16;
}
if (!member.is_contextual) {
@ -126,17 +121,6 @@ export default class Renderer {
this.context.sort((a, b) => (b.priority - a.priority) || ((a.index.value as number) - (b.index.value as number)));
this.context.forEach((member, i) => member.index.value = i);
let i = this.context.length;
while (i--) {
const member = this.context[i];
if (member.variable) {
if (member.variable.referenced || member.variable.export_name) break;
} else if (member.is_non_contextual) {
break;
}
}
this.initial_context = this.context.slice(0, i + 1);
}
add_to_context(name: string, contextual = false) {
@ -160,7 +144,8 @@ export default class Renderer {
member.is_contextual = true;
} else {
member.is_non_contextual = true;
member.variable = this.component.var_lookup.get(name);
const variable = this.component.var_lookup.get(name);
member.variable = variable;
}
return member;

@ -70,15 +70,6 @@ export default function dom(
);
}
const uses_slots = component.var_lookup.has('$$slots');
let compute_slots;
if (uses_slots) {
compute_slots = b`
const $$slots = @compute_slots(#slots);
`;
}
const uses_props = component.var_lookup.has('$$props');
const uses_rest = component.var_lookup.has('$$restProps');
const $$props = uses_props || uses_rest ? `$$new_props` : `$$props`;
@ -302,20 +293,32 @@ export default function dom(
const variable = component.var_lookup.get(prop.name);
if (variable.hoistable) return false;
return prop.name[0] !== '$';
if (prop.name[0] === '$') return false;
return true;
});
const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
const instance_javascript = component.extract_javascript(component.ast.instance);
let i = renderer.context.length;
while (i--) {
const member = renderer.context[i];
if (member.variable) {
if (member.variable.referenced || member.variable.export_name) break;
} else if (member.is_non_contextual) {
break;
}
}
const initial_context = renderer.context.slice(0, i + 1);
const has_definition = (
component.compile_options.dev ||
(instance_javascript && instance_javascript.length > 0) ||
filtered_props.length > 0 ||
uses_props ||
component.partly_hoisted.length > 0 ||
renderer.initial_context.length > 0 ||
initial_context.length > 0 ||
component.reactive_declarations.length > 0 ||
capture_state ||
inject_state
@ -401,7 +404,7 @@ export default function dom(
const return_value = {
type: 'ArrayExpression',
elements: renderer.initial_context.map(member => ({
elements: initial_context.map(member => ({
type: 'Identifier',
name: member.name
}) as Expression)
@ -417,19 +420,18 @@ export default function dom(
${resubscribable_reactive_store_unsubscribers}
${component.slots.size || component.compile_options.dev || uses_slots ? b`let { $$slots: #slots = {}, $$scope } = $$props;` : null}
${component.compile_options.dev && b`@validate_slots('${component.tag}', #slots, [${[...component.slots.keys()].map(key => `'${key}'`).join(',')}]);`}
${compute_slots}
${instance_javascript}
${unknown_props_check}
${renderer.binding_groups.size > 0 && b`const $$binding_groups = [${[...renderer.binding_groups.keys()].map(_ => x`[]`)}];`}
${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`[]`)}];`}
${component.partly_hoisted}
${set && b`$$self.$$set = ${set};`}
${set && b`$$self.$set = ${set};`}
${capture_state && b`$$self.$capture_state = ${capture_state};`}

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

@ -7,7 +7,6 @@ import FragmentWrapper from './Fragment';
import { b, x } from 'code-red';
import ElseBlock from '../../nodes/ElseBlock';
import { Identifier, Node } from 'estree';
import get_object from '../../utils/get_object';
export class ElseBlockWrapper extends Wrapper {
node: ElseBlock;
@ -140,8 +139,11 @@ export default class EachBlockWrapper extends Wrapper {
view_length: fixed_length === null ? x`${iterations}.length` : fixed_length
};
const object = get_object(node.expression.node);
const store = object.type === 'Identifier' && object.name[0] === '$' ? object.name.slice(1) : null;
const store =
node.expression.node.type === 'Identifier' &&
node.expression.node.name[0] === '$'
? node.expression.node.name.slice(1)
: null;
node.contexts.forEach(prop => {
this.block.bindings.set(prop.key.name, {
@ -199,7 +201,7 @@ export default class EachBlockWrapper extends Wrapper {
this.context_props = this.node.contexts.map(prop => b`child_ctx[${renderer.context_lookup.get(prop.key.name).index}] = ${prop.modifier(x`list[i]`)};`);
if (this.node.has_binding) this.context_props.push(b`child_ctx[${renderer.context_lookup.get(this.vars.each_block_value.name).index}] = list;`);
if (this.node.has_binding || this.node.has_index_binding || this.node.index) this.context_props.push(b`child_ctx[${renderer.context_lookup.get(this.index_name.name).index}] = i;`);
if (this.node.has_binding || this.node.index) this.context_props.push(b`child_ctx[${renderer.context_lookup.get(this.index_name.name).index}] = i;`);
const snippet = this.node.expression.manipulate(block);
@ -296,19 +298,6 @@ export default class EachBlockWrapper extends Wrapper {
}
`);
const has_transitions = !!(this.else.block.has_intro_method || this.else.block.has_outro_method);
const destroy_block_else = this.else.block.has_outro_method
? b`
@group_outros();
@transition_out(${each_block_else}, 1, 1, () => {
${each_block_else} = null;
});
@check_outros();`
: b`
${each_block_else}.d(1);
${each_block_else} = null;`;
if (this.else.block.has_update_method) {
this.updates.push(b`
if (!${this.vars.data_length} && ${each_block_else}) {
@ -316,22 +305,22 @@ export default class EachBlockWrapper extends Wrapper {
} else if (!${this.vars.data_length}) {
${each_block_else} = ${this.else.block.name}(#ctx);
${each_block_else}.c();
${has_transitions && b`@transition_in(${each_block_else}, 1);`}
${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
} else if (${each_block_else}) {
${destroy_block_else};
${each_block_else}.d(1);
${each_block_else} = null;
}
`);
} else {
this.updates.push(b`
if (${this.vars.data_length}) {
if (${each_block_else}) {
${destroy_block_else};
${each_block_else}.d(1);
${each_block_else} = null;
}
} else if (!${each_block_else}) {
${each_block_else} = ${this.else.block.name}(#ctx);
${each_block_else}.c();
${has_transitions && b`@transition_in(${each_block_else}, 1);`}
${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
}
`);

@ -6,10 +6,8 @@ import { string_literal } from '../../../utils/stringify';
import { b, x } from 'code-red';
import Expression from '../../../nodes/shared/Expression';
import Text from '../../../nodes/Text';
import handle_select_value_binding from './handle_select_value_binding';
import { Identifier, Node } from 'estree';
export class BaseAttributeWrapper {
export default class AttributeWrapper {
node: Attribute;
parent: ElementWrapper;
@ -22,29 +20,7 @@ export class BaseAttributeWrapper {
parent.not_static_content();
block.add_dependencies(node.dependencies);
}
}
render(_block: Block) {}
}
export default class AttributeWrapper extends BaseAttributeWrapper {
node: Attribute;
parent: ElementWrapper;
metadata: any;
name: string;
property_name: string;
is_indirectly_bound_value: boolean;
is_src: boolean;
is_select_value_attribute: boolean;
is_input_value: boolean;
should_cache: boolean;
last: Identifier;
constructor(parent: ElementWrapper, block: Block, node: Attribute) {
super(parent, block, node);
if (node.dependencies.size > 0) {
// special case — <option value={foo}> — see below
if (this.parent.node.name === 'option' && node.name === 'value') {
let select: ElementWrapper = this.parent;
@ -60,27 +36,32 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
});
}
}
if (node.name === 'value') {
handle_select_value_binding(this, node.dependencies);
}
}
}
this.name = fix_attribute_casing(this.node.name);
this.metadata = this.get_metadata();
this.is_indirectly_bound_value = is_indirectly_bound_value(this);
this.property_name = this.is_indirectly_bound_value
? '__value'
: this.metadata && this.metadata.property_name;
this.is_src = this.name === 'src'; // TODO retire this exception in favour of https://github.com/sveltejs/svelte/issues/3750
this.is_select_value_attribute = this.name === 'value' && this.parent.node.name === 'select';
this.is_input_value = this.name === 'value' && this.parent.node.name === 'input';
this.should_cache = should_cache(this);
is_indirectly_bound_value() {
const element = this.parent;
const name = fix_attribute_casing(this.node.name);
return name === 'value' &&
(element.node.name === 'option' || // TODO check it's actually bound
(element.node.name === 'input' &&
element.node.bindings.some(
(binding) =>
/checked|group/.test(binding.name)
)));
}
render(block: Block) {
const element = this.parent;
const { name, property_name, should_cache, is_indirectly_bound_value } = this;
const name = fix_attribute_casing(this.node.name);
const metadata = this.get_metadata();
const is_indirectly_bound_value = this.is_indirectly_bound_value();
const property_name = is_indirectly_bound_value
? '__value'
: metadata && metadata.property_name;
// xlink is a special case... we could maybe extend this to generic
// namespaced attributes but I'm not sure that's applicable in
@ -93,61 +74,97 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
const is_legacy_input_type = element.renderer.component.compile_options.legacy && name === 'type' && this.parent.node.name === 'input';
const dependencies = this.get_dependencies();
const dependencies = this.node.get_dependencies();
const value = this.get_value(block);
const is_src = this.node.name === 'src'; // TODO retire this exception in favour of https://github.com/sveltejs/svelte/issues/3750
const is_select_value_attribute =
name === 'value' && element.node.name === 'select';
const is_input_value = name === 'value' && element.node.name === 'input';
const should_cache = is_src || this.node.should_cache() || is_select_value_attribute; // TODO is this necessary?
const last = should_cache && block.get_unique_name(
`${element.var.name}_${name.replace(/[^a-zA-Z_$]/g, '_')}_value`
);
if (should_cache) block.add_variable(last);
let updater;
const init = this.get_init(block, value);
const init = should_cache ? x`${last} = ${value}` : value;
if (is_legacy_input_type) {
block.chunks.hydrate.push(
b`@set_input_type(${element.var}, ${init});`
);
updater = b`@set_input_type(${element.var}, ${should_cache ? this.last : value});`;
} else if (this.is_select_value_attribute) {
updater = b`@set_input_type(${element.var}, ${should_cache ? last : value});`;
} else if (is_select_value_attribute) {
// annoying special case
const is_multiple_select = element.node.get_static_attribute_value('multiple');
const i = block.get_unique_name('i');
const option = block.get_unique_name('option');
const if_statement = is_multiple_select
? b`
${option}.selected = ~${last}.indexOf(${option}.__value);`
: b`
if (${option}.__value === ${last}) {
${option}.selected = true;
${{ type: 'BreakStatement' }};
}`; // TODO the BreakStatement is gross, but it's unsyntactic otherwise...
if (is_multiple_select) {
updater = b`@select_options(${element.var}, ${value});`;
} else {
updater = b`@select_option(${element.var}, ${value});`;
}
updater = b`
for (var ${i} = 0; ${i} < ${element.var}.options.length; ${i} += 1) {
var ${option} = ${element.var}.options[${i}];
${if_statement}
}
`;
block.chunks.mount.push(b`
${last} = ${value};
${updater}
`);
} else if (this.is_src) {
} else if (is_src) {
block.chunks.hydrate.push(
b`if (${element.var}.src !== ${init}) ${method}(${element.var}, "${name}", ${this.last});`
b`if (${element.var}.src !== ${init}) ${method}(${element.var}, "${name}", ${last});`
);
updater = b`${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
updater = b`${method}(${element.var}, "${name}", ${should_cache ? last : value});`;
} else if (property_name) {
block.chunks.hydrate.push(
b`${element.var}.${property_name} = ${init};`
);
updater = block.renderer.options.dev
? b`@prop_dev(${element.var}, "${property_name}", ${should_cache ? this.last : value});`
: b`${element.var}.${property_name} = ${should_cache ? this.last : value};`;
? b`@prop_dev(${element.var}, "${property_name}", ${should_cache ? last : value});`
: b`${element.var}.${property_name} = ${should_cache ? last : value};`;
} else {
block.chunks.hydrate.push(
b`${method}(${element.var}, "${name}", ${init});`
);
updater = b`${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
updater = b`${method}(${element.var}, "${name}", ${should_cache ? last : value});`;
}
if (is_indirectly_bound_value) {
const update_value = b`${element.var}.value = ${element.var}.__value;`;
block.chunks.hydrate.push(update_value);
if (dependencies.length > 0) {
let condition = block.renderer.dirty(dependencies);
updater = b`
${updater}
${update_value};
`;
}
if (should_cache) {
condition = is_src
? x`${condition} && (${element.var}.src !== (${last} = ${value}))`
: x`${condition} && (${last} !== (${last} = ${value}))`;
}
if (dependencies.length > 0) {
const condition = this.get_dom_update_conditions(block, block.renderer.dirty(dependencies));
if (is_input_value) {
const type = element.node.get_static_attribute_value('type');
if (type === null || type === "" || type === "text" || type === "email" || type === "password") {
condition = x`${condition} && ${element.var}.${property_name} !== ${should_cache ? last : value}`;
}
}
if (block.has_outros) {
condition = x`!#current || ${condition}`;
}
block.chunks.update.push(b`
if (${condition}) {
@ -159,72 +176,26 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
if (this.node.is_true && name === 'autofocus') {
block.autofocus = element.var;
}
}
get_init(block: Block, value) {
this.last = this.should_cache && block.get_unique_name(
`${this.parent.var.name}_${this.name.replace(/[^a-zA-Z_$]/g, '_')}_value`
);
if (this.should_cache) block.add_variable(this.last);
return this.should_cache ? x`${this.last} = ${value}` : value;
}
get_dom_update_conditions(block: Block, dependency_condition: Node) {
const { property_name, should_cache, last } = this;
const element = this.parent;
const value = this.get_value(block);
let condition = dependency_condition;
if (should_cache) {
condition = this.is_src
? x`${condition} && (${element.var}.src !== (${last} = ${value}))`
: x`${condition} && (${last} !== (${last} = ${value}))`;
}
if (this.is_input_value) {
const type = element.node.get_static_attribute_value('type');
if (type === null || type === "" || type === "text" || type === "email" || type === "password") {
condition = x`${condition} && ${element.var}.${property_name} !== ${should_cache ? last : value}`;
}
}
if (is_indirectly_bound_value) {
const update_value = b`${element.var}.value = ${element.var}.__value;`;
if (block.has_outros) {
condition = x`!#current || ${condition}`;
block.chunks.hydrate.push(update_value);
if (this.node.get_dependencies().length > 0) block.chunks.update.push(update_value);
}
return condition;
}
get_dependencies() {
const node_dependencies = this.node.get_dependencies();
const dependencies = new Set(node_dependencies);
node_dependencies.forEach((prop: string) => {
const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(prop);
if (indirect_dependencies) {
indirect_dependencies.forEach(indirect_dependency => {
dependencies.add(indirect_dependency);
});
}
});
return Array.from(dependencies);
}
get_metadata() {
if (this.parent.node.namespace) return null;
const metadata = attribute_lookup[this.name];
const metadata = attribute_lookup[fix_attribute_casing(this.node.name)];
if (metadata && metadata.applies_to && !metadata.applies_to.includes(this.parent.node.name)) return null;
return metadata;
}
get_value(block) {
if (this.node.is_true) {
if (this.metadata && boolean_attribute.has(this.metadata.property_name.toLowerCase())) {
const metadata = this.get_metadata();
if (metadata && boolean_attribute.has(metadata.property_name.toLowerCase())) {
return x`true`;
}
return x`""`;
@ -307,8 +278,8 @@ const attribute_lookup = {
'optgroup',
'option',
'select',
'textarea'
]
'textarea',
],
},
formnovalidate: { property_name: 'formNoValidate', applies_to: ['button', 'input'] },
hidden: {},
@ -335,9 +306,9 @@ const attribute_lookup = {
'progress',
'param',
'select',
'textarea'
]
}
'textarea',
],
},
};
Object.keys(attribute_lookup).forEach(name => {
@ -372,19 +343,4 @@ const boolean_attribute = new Set([
'required',
'reversed',
'selected'
]);
function should_cache(attribute: AttributeWrapper) {
return attribute.is_src || attribute.node.should_cache();
}
function is_indirectly_bound_value(attribute: AttributeWrapper) {
const element = attribute.parent;
return attribute.name === 'value' &&
(element.node.name === 'option' || // TODO check it's actually bound
(element.node.name === 'input' &&
element.node.bindings.some(
(binding) =>
/checked|group/.test(binding.name)
)));
}
]);

@ -1,33 +1,29 @@
import { b, x } from 'code-red';
import Binding from '../../../nodes/Binding';
import ElementWrapper from '../Element';
import InlineComponentWrapper from '../InlineComponent';
import get_object from '../../../utils/get_object';
import replace_object from '../../../utils/replace_object';
import Block from '../../Block';
import Renderer from '../../Renderer';
import flatten_reference from '../../../utils/flatten_reference';
import EachBlock from '../../../nodes/EachBlock';
import { Node, Identifier } from 'estree';
import add_to_set from '../../../utils/add_to_set';
import mark_each_block_bindings from '../shared/mark_each_block_bindings';
import handle_select_value_binding from './handle_select_value_binding';
export default class BindingWrapper {
node: Binding;
parent: ElementWrapper | InlineComponentWrapper;
parent: ElementWrapper;
object: string;
handler: {
uses_context: boolean;
mutation: (Node | Node[]);
contextual_dependencies: Set<string>;
lhs?: Node;
snippet?: Node;
};
snippet: Node;
is_readonly: boolean;
needs_lock: boolean;
constructor(block: Block, node: Binding, parent: ElementWrapper | InlineComponentWrapper) {
constructor(block: Block, node: Binding, parent: ElementWrapper) {
this.node = node;
this.parent = parent;
@ -36,11 +32,20 @@ export default class BindingWrapper {
block.add_dependencies(dependencies);
// TODO does this also apply to e.g. `<input type='checkbox' bind:group='foo'>`?
handle_select_value_binding(this, dependencies);
if (parent.node.name === 'select') {
parent.select_binding_dependencies = dependencies;
dependencies.forEach((prop: string) => {
parent.renderer.component.indirect_dependencies.set(prop, new Set());
});
}
if (node.is_contextual) {
mark_each_block_bindings(this.parent, this.node);
// we need to ensure that the each block creates a context including
// the list and the index, if they're not otherwise referenced
const { name } = get_object(this.node.expression.node);
const each_block = this.parent.node.scope.get_owner(name);
(each_block as EachBlock).has_binding = true;
}
this.object = get_object(this.node.expression.node).name;
@ -82,7 +87,7 @@ export default class BindingWrapper {
const update_conditions: any[] = this.needs_lock ? [x`!${lock}`] : [];
const mount_conditions: any[] = [];
const dependency_array = Array.from(this.get_dependencies());
const dependency_array = [...this.node.expression.dependencies];
if (dependency_array.length > 0) {
update_conditions.push(block.renderer.dirty(dependency_array));
@ -116,31 +121,17 @@ export default class BindingWrapper {
switch (this.node.name) {
case 'group':
{
const { binding_group, is_context, contexts, index } = get_binding_group(parent.renderer, this.node, block);
const binding_group = get_binding_group(parent.renderer, this.node.expression.node);
block.renderer.add_to_context(`$$binding_groups`);
if (is_context) {
if (contexts.length > 1) {
let binding_group = x`${block.renderer.reference('$$binding_groups')}[${index}]`;
for (const name of contexts.slice(0, -1)) {
binding_group = x`${binding_group}[${block.renderer.reference(name)}]`;
block.chunks.init.push(
b`${binding_group} = ${binding_group} || [];`
);
}
}
block.chunks.init.push(
b`${binding_group(true)} = [];`
);
}
const reference = block.renderer.reference(`$$binding_groups`);
block.chunks.hydrate.push(
b`${binding_group(true)}.push(${parent.var});`
b`${reference}[${binding_group}].push(${parent.var});`
);
block.chunks.destroy.push(
b`${binding_group(true)}.splice(${binding_group(true)}.indexOf(${parent.var}), 1);`
b`${reference}[${binding_group}].splice(${reference}[${binding_group}].indexOf(${parent.var}), 1);`
);
break;
}
@ -216,7 +207,7 @@ export default class BindingWrapper {
}
function get_dom_updater(
element: ElementWrapper | InlineComponentWrapper,
element: ElementWrapper,
binding: BindingWrapper
) {
const { node } = element;
@ -252,61 +243,19 @@ function get_dom_updater(
return b`${element.var}.${binding.node.name} = ${binding.snippet};`;
}
function get_binding_group(renderer: Renderer, value: Binding, block: Block) {
const { parts } = flatten_reference(value.raw_expression);
let keypath = parts.join('.');
const contexts = [];
for (const dep of value.expression.contextual_dependencies) {
const context = block.bindings.get(dep);
let key;
let name;
if (context) {
key = context.object.name;
name = context.property.name;
} else {
key = dep;
name = dep;
}
keypath = `${key}@${keypath}`;
contexts.push(name);
}
if (!renderer.binding_groups.has(keypath)) {
const index = renderer.binding_groups.size;
contexts.forEach(context => {
renderer.add_to_context(context, true);
});
renderer.binding_groups.set(keypath, {
binding_group: (to_reference: boolean = false) => {
let binding_group = '$$binding_groups';
let _secondary_indexes = contexts;
function get_binding_group(renderer: Renderer, value: Node) {
const { parts } = flatten_reference(value); // TODO handle cases involving computed member expressions
const keypath = parts.join('.');
if (to_reference) {
binding_group = block.renderer.reference(binding_group);
_secondary_indexes = _secondary_indexes.map(name => block.renderer.reference(name));
}
if (_secondary_indexes.length > 0) {
let obj = x`${binding_group}[${index}]`;
_secondary_indexes.forEach(secondary_index => {
obj = x`${obj}[${secondary_index}]`;
});
return obj;
} else {
return x`${binding_group}[${index}]`;
}
},
is_context: contexts.length > 0,
contexts,
index
});
// TODO handle contextual bindings — `keypath` should include unique ID of
// each block that provides context
let index = renderer.binding_groups.indexOf(keypath);
if (index === -1) {
index = renderer.binding_groups.length;
renderer.binding_groups.push(keypath);
}
return renderer.binding_groups.get(keypath);
return index;
}
function get_event_handler(
@ -321,17 +270,21 @@ function get_event_handler(
contextual_dependencies: Set<string>;
lhs?: Node;
} {
const contextual_dependencies = new Set<string>(binding.node.expression.contextual_dependencies);
const value = get_value_from_dom(renderer, binding.parent, binding);
const contextual_dependencies = new Set(binding.node.expression.contextual_dependencies);
const context = block.bindings.get(name);
let set_store;
if (context) {
const { object, property, store, snippet } = context;
lhs = replace_object(lhs, snippet);
contextual_dependencies.add(object.name);
contextual_dependencies.add(property.name);
contextual_dependencies.delete(name);
const { object, property, modifier, store } = context;
if (lhs.type === 'Identifier') {
lhs = modifier(x`${object}[${property}]`);
contextual_dependencies.add(object.name);
contextual_dependencies.add(property.name);
}
if (store) {
set_store = b`${store}.set(${`$${store}`});`;
@ -344,8 +297,6 @@ function get_event_handler(
}
}
const value = get_value_from_dom(renderer, binding.parent, binding, block, contextual_dependencies);
const mutation = b`
${lhs} = ${value};
${set_store}
@ -354,23 +305,20 @@ function get_event_handler(
return {
uses_context: binding.node.is_contextual || binding.node.expression.uses_context, // TODO this is messy
mutation,
contextual_dependencies,
lhs
contextual_dependencies
};
}
function get_value_from_dom(
renderer: Renderer,
element: ElementWrapper | InlineComponentWrapper,
binding: BindingWrapper,
block: Block,
contextual_dependencies: Set<string>
element: ElementWrapper,
binding: BindingWrapper
) {
const { node } = element;
const { name } = binding.node;
if (name === 'this') {
return x`$$value`;
return x`$$node`;
}
// <select bind:value='selected>
@ -384,10 +332,9 @@ function get_value_from_dom(
// <input type='checkbox' bind:group='foo'>
if (name === 'group') {
const binding_group = get_binding_group(renderer, binding.node.expression.node);
if (type === 'checkbox') {
const { binding_group, contexts } = get_binding_group(renderer, binding.node, block);
add_to_set(contextual_dependencies, contexts);
return x`@get_binding_group_value(${binding_group()}, this.__value, this.checked)`;
return x`@get_binding_group_value($$binding_groups[${binding_group}])`;
}
return x`this.__value`;

@ -1,3 +0,0 @@
import { BaseAttributeWrapper } from "./Attribute";
export default class SpreadAttributeWrapper extends BaseAttributeWrapper {}

@ -1,16 +0,0 @@
import AttributeWrapper from "./Attribute";
import BindingWrapper from "./Binding";
import ElementWrapper from "./index";
export default function handle_select_value_binding(
attr: AttributeWrapper | BindingWrapper,
dependencies: Set<string>
) {
const { parent } = attr;
if (parent.node.name === "select") {
(parent as ElementWrapper).select_binding_dependencies = dependencies;
dependencies.forEach((prop: string) => {
parent.renderer.component.indirect_dependencies.set(prop, new Set());
});
}
}

@ -6,12 +6,12 @@ import { is_void, sanitize } from '../../../../utils/names';
import FragmentWrapper from '../Fragment';
import { escape_html, string_literal } from '../../../utils/stringify';
import TextWrapper from '../Text';
import TagWrapper from '../shared/Tag';
import fix_attribute_casing from './fix_attribute_casing';
import { b, x, p } from 'code-red';
import { namespaces } from '../../../../utils/namespaces';
import AttributeWrapper from './Attribute';
import StyleAttributeWrapper from './StyleAttribute';
import SpreadAttributeWrapper from './SpreadAttribute';
import { dimensions } from '../../../../utils/patterns';
import Binding from './Binding';
import InlineComponentWrapper from '../InlineComponent';
@ -26,13 +26,6 @@ import { Identifier } from 'estree';
import EventHandler from './EventHandler';
import { extract_names } from 'periscopic';
import Action from '../../../nodes/Action';
import MustacheTagWrapper from '../MustacheTag';
import RawMustacheTagWrapper from '../RawMustacheTag';
interface BindingGroup {
events: string[];
bindings: Binding[];
}
const events = [
{
@ -132,13 +125,13 @@ const events = [
event_names: ['toggle'],
filter: (node: Element, _name: string) =>
node.name === 'details'
}
},
];
export default class ElementWrapper extends Wrapper {
node: Element;
fragment: FragmentWrapper;
attributes: Array<AttributeWrapper | StyleAttributeWrapper | SpreadAttributeWrapper>;
attributes: AttributeWrapper[];
bindings: Binding[];
event_handlers: EventHandler[];
class_dependencies: string[];
@ -222,9 +215,6 @@ export default class ElementWrapper extends Wrapper {
if (attribute.name === 'style') {
return new StyleAttributeWrapper(this, block, attribute);
}
if (attribute.type === 'Spread') {
return new SpreadAttributeWrapper(this, block, attribute);
}
return new AttributeWrapper(this, block, attribute);
});
@ -342,7 +332,8 @@ export default class ElementWrapper extends Wrapper {
if (!this.node.namespace && (this.can_use_innerhtml || can_use_textcontent) && this.fragment.nodes.length > 0) {
if (this.fragment.nodes.length === 1 && this.fragment.nodes[0].node.type === 'Text') {
block.chunks.create.push(
b`${node}.textContent = ${string_literal((this.fragment.nodes[0] as TextWrapper).data)};`
// @ts-ignore todo: should it be this.fragment.nodes[0].node.data instead?
b`${node}.textContent = ${string_literal(this.fragment.nodes[0].data)};`
);
} else {
const state = {
@ -414,7 +405,7 @@ export default class ElementWrapper extends Wrapper {
get_render_statement(block: Block) {
const { name, namespace } = this.node;
if (namespace === namespaces.svg) {
if (namespace === 'http://www.w3.org/2000/svg') {
return x`@svg_element("${name}")`;
}
@ -422,7 +413,7 @@ export default class ElementWrapper extends Wrapper {
return x`@_document.createElementNS("${namespace}", "${name}")`;
}
const is: AttributeWrapper = this.attributes.find(attr => attr.node.name === 'is') as any;
const is = this.attributes.find(attr => attr.node.name === 'is');
if (is) {
return x`@element_is("${name}", ${is.render_chunks(block).reduce((lhs, rhs) => x`${lhs} + ${rhs}`)})`;
}
@ -445,9 +436,14 @@ export default class ElementWrapper extends Wrapper {
}
add_directives_in_order (block: Block) {
interface BindingGroup {
events: string[];
bindings: Binding[];
}
type OrderedAttribute = EventHandler | BindingGroup | Binding | Action;
const binding_groups = events
const bindingGroups = events
.map(event => ({
events: event.event_names,
bindings: this.bindings
@ -471,7 +467,7 @@ export default class ElementWrapper extends Wrapper {
}
([
...binding_groups,
...bindingGroups,
...this.event_handlers,
this_binding,
...this.node.actions
@ -491,140 +487,143 @@ export default class ElementWrapper extends Wrapper {
});
}
add_bindings(block: Block, binding_group: BindingGroup) {
add_bindings(block: Block, bindingGroup) {
const { renderer } = this;
if (binding_group.bindings.length === 0) return;
if (bindingGroup.bindings.length === 0) return;
renderer.component.has_reactive_assignments = true;
const lock = binding_group.bindings.some(binding => binding.needs_lock) ?
const lock = bindingGroup.bindings.some(binding => binding.needs_lock) ?
block.get_unique_name(`${this.var.name}_updating`) :
null;
if (lock) block.add_variable(lock, x`false`);
const handler = renderer.component.get_unique_name(`${this.var.name}_${binding_group.events.join('_')}_handler`);
renderer.add_to_context(handler.name);
[bindingGroup].forEach(group => {
const handler = renderer.component.get_unique_name(`${this.var.name}_${group.events.join('_')}_handler`);
renderer.add_to_context(handler.name);
// TODO figure out how to handle locks
const needs_lock = binding_group.bindings.some(binding => binding.needs_lock);
// TODO figure out how to handle locks
const needs_lock = group.bindings.some(binding => binding.needs_lock);
const dependencies: Set<string> = new Set();
const contextual_dependencies: Set<string> = new Set();
const dependencies: Set<string> = new Set();
const contextual_dependencies: Set<string> = new Set();
binding_group.bindings.forEach(binding => {
// TODO this is a mess
add_to_set(dependencies, binding.get_dependencies());
add_to_set(contextual_dependencies, binding.handler.contextual_dependencies);
group.bindings.forEach(binding => {
// TODO this is a mess
add_to_set(dependencies, binding.get_dependencies());
add_to_set(contextual_dependencies, binding.node.expression.contextual_dependencies);
add_to_set(contextual_dependencies, binding.handler.contextual_dependencies);
binding.render(block, lock);
});
binding.render(block, lock);
});
// media bindings — awkward special case. The native timeupdate events
// fire too infrequently, so we need to take matters into our
// own hands
let animation_frame;
if (binding_group.events[0] === 'timeupdate') {
animation_frame = block.get_unique_name(`${this.var.name}_animationframe`);
block.add_variable(animation_frame);
}
// media bindings — awkward special case. The native timeupdate events
// fire too infrequently, so we need to take matters into our
// own hands
let animation_frame;
if (group.events[0] === 'timeupdate') {
animation_frame = block.get_unique_name(`${this.var.name}_animationframe`);
block.add_variable(animation_frame);
}
const has_local_function = contextual_dependencies.size > 0 || needs_lock || animation_frame;
const has_local_function = contextual_dependencies.size > 0 || needs_lock || animation_frame;
let callee = renderer.reference(handler);
let callee = renderer.reference(handler);
// TODO dry this out — similar code for event handlers and component bindings
if (has_local_function) {
const args = Array.from(contextual_dependencies).map(name => renderer.reference(name));
// TODO dry this out — similar code for event handlers and component bindings
if (has_local_function) {
const args = Array.from(contextual_dependencies).map(name => renderer.reference(name));
// need to create a block-local function that calls an instance-level function
if (animation_frame) {
block.chunks.init.push(b`
function ${handler}() {
@_cancelAnimationFrame(${animation_frame});
if (!${this.var}.paused) {
${animation_frame} = @raf(${handler});
// need to create a block-local function that calls an instance-level function
if (animation_frame) {
block.chunks.init.push(b`
function ${handler}() {
@_cancelAnimationFrame(${animation_frame});
if (!${this.var}.paused) {
${animation_frame} = @raf(${handler});
${needs_lock && b`${lock} = true;`}
}
${callee}.call(${this.var}, ${args});
}
`);
} else {
block.chunks.init.push(b`
function ${handler}() {
${needs_lock && b`${lock} = true;`}
${callee}.call(${this.var}, ${args});
}
${callee}.call(${this.var}, ${args});
}
`);
} else {
block.chunks.init.push(b`
function ${handler}() {
${needs_lock && b`${lock} = true;`}
${callee}.call(${this.var}, ${args});
}
`);
`);
}
callee = handler;
}
callee = handler;
}
const params = Array.from(contextual_dependencies).map(name => ({
type: 'Identifier',
name
}));
this.renderer.component.partly_hoisted.push(b`
function ${handler}(${params}) {
${group.bindings.map(b => b.handler.mutation)}
${Array.from(dependencies)
.filter(dep => dep[0] !== '$')
.filter(dep => !contextual_dependencies.has(dep))
.map(dep => b`${this.renderer.invalidate(dep)};`)}
}
`);
const params = Array.from(contextual_dependencies).map(name => ({
type: 'Identifier',
name
}));
this.renderer.component.partly_hoisted.push(b`
function ${handler}(${params}) {
${binding_group.bindings.map(b => b.handler.mutation)}
${Array.from(dependencies)
.filter(dep => dep[0] !== '$')
.filter(dep => !contextual_dependencies.has(dep))
.map(dep => b`${this.renderer.invalidate(dep)};`)}
}
`);
group.events.forEach(name => {
if (name === 'elementresize') {
// special case
const resize_listener = block.get_unique_name(`${this.var.name}_resize_listener`);
block.add_variable(resize_listener);
binding_group.events.forEach(name => {
if (name === 'elementresize') {
// special case
const resize_listener = block.get_unique_name(`${this.var.name}_resize_listener`);
block.add_variable(resize_listener);
block.chunks.mount.push(
b`${resize_listener} = @add_resize_listener(${this.var}, ${callee}.bind(${this.var}));`
);
block.chunks.mount.push(
b`${resize_listener} = @add_resize_listener(${this.var}, ${callee}.bind(${this.var}));`
);
block.chunks.destroy.push(
b`${resize_listener}();`
);
} else {
block.event_listeners.push(
x`@listen(${this.var}, "${name}", ${callee})`
);
}
});
block.chunks.destroy.push(
b`${resize_listener}();`
);
} else {
block.event_listeners.push(
x`@listen(${this.var}, "${name}", ${callee})`
const some_initial_state_is_undefined = group.bindings
.map(binding => x`${binding.snippet} === void 0`)
.reduce((lhs, rhs) => x`${lhs} || ${rhs}`);
const should_initialise = (
this.node.name === 'select' ||
group.bindings.find(binding => {
return (
binding.node.name === 'indeterminate' ||
binding.node.name === 'textContent' ||
binding.node.name === 'innerHTML' ||
binding.is_readonly_media_attribute()
);
})
);
if (should_initialise) {
const callback = has_local_function ? handler : x`() => ${callee}.call(${this.var})`;
block.chunks.hydrate.push(
b`if (${some_initial_state_is_undefined}) @add_render_callback(${callback});`
);
}
});
const some_initial_state_is_undefined = binding_group.bindings
.map(binding => x`${binding.snippet} === void 0`)
.reduce((lhs, rhs) => x`${lhs} || ${rhs}`);
const should_initialise = (
this.node.name === 'select' ||
binding_group.bindings.find(binding => {
return (
binding.node.name === 'indeterminate' ||
binding.node.name === 'textContent' ||
binding.node.name === 'innerHTML' ||
binding.is_readonly_media_attribute()
if (group.events[0] === 'elementresize') {
block.chunks.hydrate.push(
b`@add_render_callback(() => ${callee}.call(${this.var}));`
);
})
);
if (should_initialise) {
const callback = has_local_function ? handler : x`() => ${callee}.call(${this.var})`;
block.chunks.hydrate.push(
b`if (${some_initial_state_is_undefined}) @add_render_callback(${callback});`
);
}
if (binding_group.events[0] === 'elementresize') {
block.chunks.hydrate.push(
b`@add_render_callback(() => ${callee}.call(${this.var}));`
);
}
}
});
if (lock) {
block.chunks.update.push(b`${lock} = false;`);
@ -636,7 +635,7 @@ export default class ElementWrapper extends Wrapper {
renderer.component.has_reactive_assignments = true;
const binding_callback = bind_this(renderer.component, block, this_binding, this.var);
const binding_callback = bind_this(renderer.component, block, this_binding.node, this.var);
block.chunks.mount.push(binding_callback);
}
@ -668,24 +667,25 @@ export default class ElementWrapper extends Wrapper {
this.attributes
.forEach(attr => {
const dependencies = attr.node.get_dependencies();
const condition = dependencies.length > 0
? block.renderer.dirty(dependencies)
const condition = attr.node.dependencies.size > 0
? block.renderer.dirty(Array.from(attr.node.dependencies))
: null;
if (attr instanceof SpreadAttributeWrapper) {
if (attr.node.is_spread) {
const snippet = attr.node.expression.manipulate(block);
initial_props.push(snippet);
updates.push(condition ? x`${condition} && ${snippet}` : snippet);
} else {
const name = attr.property_name || attr.name;
initial_props.push(x`{ ${name}: ${attr.get_init(block, attr.get_value(block))} }`);
const snippet = x`{ ${name}: ${attr.should_cache ? attr.last : attr.get_value(block)} }`;
const metadata = attr.get_metadata();
const name = attr.is_indirectly_bound_value()
? '__value'
: (metadata && metadata.property_name) || fix_attribute_casing(attr.node.name);
const snippet = x`{ ${name}: ${attr.get_value(block)} }`;
initial_props.push(snippet);
updates.push(condition ? x`${attr.get_dom_update_conditions(block, condition)} && ${snippet}` : snippet);
updates.push(condition ? x`${condition} && ${snippet}` : snippet);
}
});
@ -705,39 +705,10 @@ export default class ElementWrapper extends Wrapper {
);
block.chunks.update.push(b`
${fn}(${this.var}, ${data} = @get_spread_update(${levels}, [
${fn}(${this.var}, @get_spread_update(${levels}, [
${updates}
]));
`);
// handle edge cases for elements
if (this.node.name === 'select') {
const dependencies = new Set();
for (const attr of this.attributes) {
for (const dep of attr.node.dependencies) {
dependencies.add(dep);
}
}
block.chunks.mount.push(b`
if (${data}.multiple) @select_options(${this.var}, ${data}.value);
`);
block.chunks.update.push(b`
if (${block.renderer.dirty(Array.from(dependencies))} && ${data}.multiple) @select_options(${this.var}, ${data}.value);
`);
} else if (this.node.name === 'input' && this.attributes.find(attr => attr.node.name === 'value')) {
const type = this.node.get_static_attribute_value('type');
if (type === null || type === "" || type === "text" || type === "email" || type === "password") {
block.chunks.mount.push(b`
${this.var}.value = ${data}.value;
`);
block.chunks.update.push(b`
if ('value' in ${data}) {
${this.var}.value = ${data}.value;
}
`);
}
}
}
add_transitions(
@ -941,9 +912,9 @@ export default class ElementWrapper extends Wrapper {
}
}
function to_html(wrappers: Array<ElementWrapper | TextWrapper | MustacheTagWrapper | RawMustacheTagWrapper>, block: Block, literal: any, state: any, can_use_raw_text?: boolean) {
function to_html(wrappers: Array<ElementWrapper | TextWrapper | TagWrapper>, block: Block, literal: any, state: any, can_use_raw_text?: boolean) {
wrappers.forEach(wrapper => {
if (wrapper instanceof TextWrapper) {
if (wrapper.node.type === 'Text') {
if ((wrapper as TextWrapper).use_space()) state.quasi.value.raw += ' ';
const parent = wrapper.node.parent as Element;
@ -954,13 +925,13 @@ function to_html(wrappers: Array<ElementWrapper | TextWrapper | MustacheTagWrapp
can_use_raw_text
);
state.quasi.value.raw += (raw ? wrapper.data : escape_html(wrapper.data))
state.quasi.value.raw += (raw ? wrapper.node.data : escape_html(wrapper.node.data))
.replace(/\\/g, '\\\\')
.replace(/`/g, '\\`')
.replace(/\$/g, '\\$');
}
else if (wrapper instanceof MustacheTagWrapper || wrapper instanceof RawMustacheTagWrapper) {
else if (wrapper.node.type === 'MustacheTag' || wrapper.node.type === 'RawMustacheTag' ) {
literal.quasis.push(state.quasi);
literal.expressions.push(wrapper.node.expression.manipulate(block));
state.quasi = {
@ -999,8 +970,8 @@ function to_html(wrappers: Array<ElementWrapper | TextWrapper | MustacheTagWrapp
state.quasi.value.raw += '>';
if (!wrapper.void) {
to_html(wrapper.fragment.nodes as Array<ElementWrapper | TextWrapper>, block, literal, state);
if (!(wrapper as ElementWrapper).void) {
to_html((wrapper as ElementWrapper).fragment.nodes as Array<ElementWrapper | TextWrapper>, block, literal, state);
state.quasi.value.raw += `</${wrapper.node.name}>`;
}

@ -603,7 +603,7 @@ export default class IfBlockWrapper extends Wrapper {
// as -1
operator: val.operator,
prefix: val.prefix,
argument: val.argument
argument: val.argument,
};
}
}

@ -1,5 +1,4 @@
import Wrapper from '../shared/Wrapper';
import BindingWrapper from '../Element/Binding';
import Renderer from '../../Renderer';
import Block from '../../Block';
import InlineComponent from '../../../nodes/InlineComponent';
@ -8,16 +7,16 @@ import { sanitize } from '../../../../utils/names';
import add_to_set from '../../../utils/add_to_set';
import { b, x, p } from 'code-red';
import Attribute from '../../../nodes/Attribute';
import get_object from '../../../utils/get_object';
import create_debugging_comment from '../shared/create_debugging_comment';
import { get_slot_definition } from '../shared/get_slot_definition';
import EachBlock from '../../../nodes/EachBlock';
import TemplateScope from '../../../nodes/shared/TemplateScope';
import is_dynamic from '../shared/is_dynamic';
import bind_this from '../shared/bind_this';
import { Node, Identifier, ObjectExpression } from 'estree';
import EventHandler from '../Element/EventHandler';
import { extract_names } from 'periscopic';
import mark_each_block_bindings from '../shared/mark_each_block_bindings';
import { string_to_member_expression } from '../../../utils/string_to_member_expression';
export default class InlineComponentWrapper extends Wrapper {
var: Identifier;
@ -48,7 +47,12 @@ export default class InlineComponentWrapper extends Wrapper {
this.node.bindings.forEach(binding => {
if (binding.is_contextual) {
mark_each_block_bindings(this, binding);
// we need to ensure that the each block creates a context including
// the list and the index, if they're not otherwise referenced
const { name } = get_object(binding.expression.node);
const each_block = this.node.scope.get_owner(name);
(each_block as EachBlock).has_binding = true;
}
block.add_dependencies(binding.expression.dependencies);
@ -112,7 +116,7 @@ export default class InlineComponentWrapper extends Wrapper {
if (variable.reassigned || variable.export_name || variable.is_reactive_dependency) {
this.renderer.component.warn(this.node, {
code: 'reactive-component',
message: `<${name}/> will not be reactive if ${name} changes. Use <svelte:component this={${name}}/> if you want this reactivity.`
message: `<${name}/> will not be reactive if ${name} changes. Use <svelte:component this={${name}}/> if you want this reactivity.`,
});
}
}
@ -128,7 +132,6 @@ export default class InlineComponentWrapper extends Wrapper {
const { component } = renderer;
const name = this.var;
block.add_variable(name);
const component_opts = x`{}` as ObjectExpression;
@ -306,7 +309,7 @@ export default class InlineComponentWrapper extends Wrapper {
component.has_reactive_assignments = true;
if (binding.name === 'this') {
return bind_this(component, block, new BindingWrapper(block, binding, this), this.var);
return bind_this(component, block, binding, this.var);
}
const id = component.get_unique_name(`${this.var.name}_${binding.name}_binding`);
@ -413,7 +416,7 @@ export default class InlineComponentWrapper extends Wrapper {
}
if (${switch_value}) {
${name} = new ${switch_value}(${switch_props}(#ctx));
var ${name} = new ${switch_value}(${switch_props}(#ctx));
${munged_bindings}
${munged_handlers}
@ -469,7 +472,7 @@ export default class InlineComponentWrapper extends Wrapper {
${name} = null;
}
} else if (${switch_value}) {
${updates.length > 0 && b`${name}.$set(${name_changes});`}
${updates.length && b`${name}.$set(${name_changes});`}
}
`);
@ -485,13 +488,13 @@ export default class InlineComponentWrapper extends Wrapper {
} else {
const expression = this.node.name === 'svelte:self'
? component.name
: this.renderer.reference(string_to_member_expression(this.node.name));
: this.renderer.reference(this.node.name);
block.chunks.init.push(b`
${(this.node.attributes.length > 0 || this.node.bindings.length > 0) && b`
${props && b`let ${props} = ${attribute_object};`}`}
${statements}
${name} = new ${expression}(${component_opts});
const ${name} = new ${expression}(${component_opts});
${munged_bindings}
${munged_handlers}

@ -39,7 +39,7 @@ export default class RawMustacheTagWrapper extends Tag {
}
else {
const needs_anchor = in_head || (this.next ? !this.next.is_dom_node() : (!this.parent || !this.parent.is_dom_node()));
const needs_anchor = in_head || (this.next && !this.next.is_dom_node());
const html_tag = block.get_unique_name('html_tag');
const html_anchor = needs_anchor && block.get_unique_name('html_anchor');
@ -51,10 +51,10 @@ export default class RawMustacheTagWrapper extends Tag {
content => x`${html_tag}.p(${content})`
);
const update_anchor = needs_anchor ? html_anchor : this.next ? this.next.var : 'null';
const update_anchor = in_head ? 'null' : needs_anchor ? html_anchor : this.next ? this.next.var : 'null';
block.chunks.hydrate.push(b`${html_tag} = new @HtmlTag(${update_anchor});`);
block.chunks.mount.push(b`${html_tag}.m(${init}, ${parent_node || '#target'}, ${parent_node ? null : '#anchor'});`);
block.chunks.hydrate.push(b`${html_tag} = new @HtmlTag(${init}, ${update_anchor});`);
block.chunks.mount.push(b`${html_tag}.m(${parent_node || '#target'}, ${parent_node ? null : '#anchor'});`);
if (needs_anchor) {
block.add_element(html_anchor, x`@empty()`, x`@empty()`, parent_node);

@ -7,7 +7,6 @@ import { b, p, x } from 'code-red';
import { sanitize } from '../../../utils/names';
import add_to_set from '../../utils/add_to_set';
import get_slot_data from '../../utils/get_slot_data';
import { is_reserved_keyword } from '../../utils/reserved_keywords';
import Expression from '../../nodes/shared/Expression';
import is_dynamic from './shared/is_dynamic';
import { Identifier, ObjectExpression } from 'estree';
@ -95,7 +94,11 @@ export default class SlotWrapper extends Wrapper {
}
});
const dynamic_dependencies = Array.from(attribute.dependencies).filter((name) => this.is_dependency_dynamic(name));
const dynamic_dependencies = Array.from(attribute.dependencies).filter(name => {
if (this.node.scope.is_let(name)) return true;
const variable = renderer.component.var_lookup.get(name);
return is_dynamic(variable);
});
if (dynamic_dependencies.length > 0) {
changes.properties.push(p`${attribute.name}: ${renderer.dirty(dynamic_dependencies)}`);
@ -125,7 +128,7 @@ export default class SlotWrapper extends Wrapper {
const slot_or_fallback = has_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_definition} = ${renderer.reference('$$slots')}.${slot_name};
const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn});
${has_fallback ? b`const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null}
`);
@ -154,10 +157,17 @@ export default class SlotWrapper extends Wrapper {
b`@transition_out(${slot_or_fallback}, #local);`
);
const dynamic_dependencies = Array.from(this.dependencies).filter((name) => this.is_dependency_dynamic(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 = has_fallback
? Array.from(this.fallback.dependencies).filter((name) => this.is_dependency_dynamic(name))
? Array.from(this.fallback.dependencies).filter(is_dependency_dynamic)
: [];
const slot_update = b`
@ -191,12 +201,4 @@ export default class SlotWrapper extends Wrapper {
b`if (${slot_or_fallback}) ${slot_or_fallback}.d(detaching);`
);
}
is_dependency_dynamic(name: string) {
if (name === '$$scope') return true;
if (this.node.scope.is_let(name)) return true;
if (is_reserved_keyword(name)) return true;
const variable = this.renderer.component.var_lookup.get(name);
return is_dynamic(variable);
}
}

@ -16,7 +16,7 @@ const associated_events = {
outerHeight: 'resize',
scrollX: 'scroll',
scrollY: 'scroll'
scrollY: 'scroll',
};
const properties = {
@ -29,7 +29,7 @@ const readonly = new Set([
'innerHeight',
'outerWidth',
'outerHeight',
'online'
'online',
]);
export default class WindowWrapper extends Wrapper {

@ -1,60 +1,64 @@
import flatten_reference from '../../../utils/flatten_reference';
import { b, x } from 'code-red';
import Component from '../../../Component';
import Block from '../../Block';
import BindingWrapper from '../Element/Binding';
import Binding from '../../../nodes/Binding';
import { Identifier } from 'estree';
import { compare_node } from '../../../utils/compare_node';
export default function bind_this(component: Component, block: Block, binding: BindingWrapper, variable: Identifier) {
export default function bind_this(component: Component, block: Block, binding: Binding, variable: Identifier) {
const fn = component.get_unique_name(`${variable.name}_binding`);
block.renderer.add_to_context(fn.name);
const callee = block.renderer.reference(fn.name);
const { contextual_dependencies, mutation } = binding.handler;
const dependencies = binding.get_dependencies();
const body = b`
${mutation}
${Array.from(dependencies)
.filter(dep => dep[0] !== '$')
.filter(dep => !contextual_dependencies.has(dep))
.map(dep => b`${block.renderer.invalidate(dep)};`)}
`;
if (contextual_dependencies.size) {
const params: Identifier[] = Array.from(contextual_dependencies).map(name => ({
type: 'Identifier',
name
}));
let lhs;
let object;
let body;
if (binding.is_contextual && binding.raw_expression.type === 'Identifier') {
// bind:x={y} — we can't just do `y = x`, we need to
// to `array[index] = x;
const { name } = binding.raw_expression;
const { snippet } = block.bindings.get(name);
lhs = snippet;
body = b`${lhs} = $$value`; // TODO we need to invalidate... something
} else {
object = flatten_reference(binding.raw_expression).name;
lhs = binding.raw_expression;
body = binding.raw_expression.type === 'Identifier'
? b`
${block.renderer.invalidate(object, x`${lhs} = $$value`)};
`
: b`
${lhs} = $$value;
${block.renderer.invalidate(object)};
`;
}
const contextual_dependencies: Identifier[] = Array.from(binding.expression.contextual_dependencies).map(name => ({
type: 'Identifier',
name
}));
if (contextual_dependencies.length) {
component.partly_hoisted.push(b`
function ${fn}($$value, ${params}) {
function ${fn}($$value, ${contextual_dependencies}) {
if (${lhs} === $$value) return;
@binding_callbacks[$$value ? 'unshift' : 'push'](() => {
${body}
});
}
`);
const alias_map = new Map();
const args = [];
for (let id of params) {
const value = block.renderer.reference(id.name);
let found = false;
if (block.variables.has(id.name)) {
let alias = id.name;
for (
let i = 1;
block.variables.has(alias) && !compare_node(block.variables.get(alias).init, value);
alias = `${id.name}_${i++}`
);
alias_map.set(alias, id.name);
id = { type: 'Identifier', name: alias };
found = block.variables.has(alias);
}
for (const id of contextual_dependencies) {
args.push(id);
if (!found) {
block.add_variable(id, value);
if (block.variables.has(id.name)) {
if (block.renderer.context_lookup.get(id.name).is_contextual) continue;
}
block.add_variable(id, block.renderer.reference(id.name));
}
const assign = block.get_unique_name(`assign_${variable.name}`);
@ -65,8 +69,8 @@ export default function bind_this(component: Component, block: Block, binding: B
const ${unassign} = () => ${callee}(null, ${args});
`);
const condition = Array.from(args)
.map(name => x`${name} !== ${block.renderer.reference(alias_map.get(name.name) || name.name)}`)
const condition = Array.from(contextual_dependencies)
.map(name => x`${name} !== ${block.renderer.reference(name.name)}`)
.reduce((lhs, rhs) => x`${lhs} || ${rhs}`);
// we push unassign and unshift assign so that references are
@ -75,7 +79,7 @@ export default function bind_this(component: Component, block: Block, binding: B
block.chunks.update.push(b`
if (${condition}) {
${unassign}();
${args.map(a => b`${a} = ${block.renderer.reference(alias_map.get(a.name) || a.name)}`)};
${args.map(a => b`${a} = ${block.renderer.reference(a.name)}`)};
${assign}();
}`
);

@ -34,13 +34,13 @@ export function get_slot_definition(block: Block, scope: TemplateScope, lets: Le
type: 'Property',
kind: 'init',
key: l.name,
value
value,
});
});
const changes_input = {
type: 'ObjectPattern',
properties
properties,
};
const names: Set<string> = new Set();

@ -1,26 +0,0 @@
import EachBlock from "../../../nodes/EachBlock";
import InlineComponentWrapper from "../InlineComponent";
import ElementWrapper from "../Element";
import Binding from "../../../nodes/Binding";
export default function mark_each_block_bindings(
parent: ElementWrapper | InlineComponentWrapper,
binding: Binding
) {
// we need to ensure that the each block creates a context including
// the list and the index, if they're not otherwise referenced
binding.expression.references.forEach(name => {
const each_block = parent.node.scope.get_owner(name);
if (each_block) {
(each_block as EachBlock).has_binding = true;
}
});
if (binding.name === "group") {
// for `<input bind:group={} >`, we make sure that all the each blocks creates context with `index`
for (const name of binding.expression.contextual_dependencies) {
const each_block = parent.node.scope.get_owner(name);
(each_block as EachBlock).has_index_binding = true;
}
}
}

@ -11,8 +11,8 @@ export default function(node: Slot, renderer: Renderer, options: RenderOptions)
const result = renderer.pop();
renderer.add_expression(x`
#slots.${node.slot_name}
? #slots.${node.slot_name}(${slot_data})
$$slots.${node.slot_name}
? $$slots.${node.slot_name}(${slot_data})
: ${result}
`);
}

@ -5,7 +5,8 @@ import { string_literal } from '../utils/stringify';
import Renderer from './Renderer';
import { INode as TemplateNode } from '../nodes/interfaces'; // TODO
import Text from '../nodes/Text';
import { LabeledStatement, Statement, Node } from 'estree';
import { extract_names } from '../utils/scope';
import { LabeledStatement, Statement, ExpressionStatement, AssignmentExpression, Node } from 'estree';
export default function ssr(
component: Component,
@ -34,9 +35,6 @@ export default function ssr(
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 uses_slots = component.var_lookup.has('$$slots');
const slots = uses_slots ? b`let $$slots = @compute_slots(#slots);` : null;
const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
const reactive_store_values = reactive_stores
.map(({ name }) => {
@ -74,17 +72,37 @@ export default function ssr(
})
: [];
const injected = Array.from(component.injected_reactive_declaration_vars).filter(name => {
const variable = component.var_lookup.get(name);
return variable.injected;
});
const reactive_declarations = component.reactive_declarations.map(d => {
const body: Statement = (d.node as LabeledStatement).body;
let statement = b`${body}`;
if (!d.declaration) { // TODO do not add label if it's not referenced
if (d.declaration) {
const declared = extract_names(d.declaration);
const injected = declared.filter(name => {
return name[0] !== '$' && component.var_lookup.get(name).injected;
});
const self_dependencies = injected.filter(name => d.dependencies.has(name));
if (injected.length) {
// in some cases we need to do `let foo; [expression]`, in
// others we can do `let [expression]`
const separate = (
self_dependencies.length > 0 ||
declared.length > injected.length
);
const { left, right } = (body as ExpressionStatement).expression as AssignmentExpression;
statement = separate
? b`
${injected.map(name => b`let ${name};`)}
${statement}`
: b`
let ${left} = ${right}`;
}
} else { // TODO do not add label if it's not referenced
statement = b`$: { ${statement} }`;
}
@ -101,8 +119,6 @@ export default function ssr(
${reactive_store_values}
${injected.map(name => b`let ${name};`)}
${reactive_declarations}
$$rendered = ${literal};
@ -113,15 +129,12 @@ export default function ssr(
: b`
${reactive_store_values}
${injected.map(name => b`let ${name};`)}
${reactive_declarations}
return ${literal};`;
const blocks = [
rest,
slots,
...reactive_stores.map(({ name }) => {
const store_name = name.slice(1);
const store = component.var_lookup.get(store_name);
@ -149,7 +162,7 @@ export default function ssr(
${component.fully_hoisted}
const ${name} = @create_ssr_component(($$result, $$props, $$bindings, #slots) => {
const ${name} = @create_ssr_component(($$result, $$props, $$bindings, $$slots) => {
${blocks}
});
`;

@ -1,19 +0,0 @@
import { Node, Literal, Identifier, MemberExpression } from "estree";
export function compare_node(a: Node | void, b: Node | void) {
if (a === b) return true;
if (!a || !b) return false;
if (a.type !== b.type) return false;
switch (a.type) {
case "Identifier":
return a.name === (b as Identifier).name;
case "MemberExpression":
return (
compare_node(a.object, (b as MemberExpression).object) &&
compare_node(a.property, (b as MemberExpression).property) &&
a.computed === (b as MemberExpression).computed
);
case 'Literal':
return a.value === (b as Literal).value;
}
}

@ -3,18 +3,14 @@ import { Node, Identifier } from 'estree';
export default function flatten_reference(node: Node) {
const nodes = [];
const parts = [];
while (node.type === 'MemberExpression') {
nodes.unshift(node.property);
if (!node.computed) {
parts.unshift((node.property as Identifier).name);
} else {
const computed_property = to_string(node.property);
if (computed_property) {
parts.unshift(`[${computed_property}]`);
}
}
node = node.object;
}
@ -24,16 +20,9 @@ export default function flatten_reference(node: Node) {
nodes.unshift(node);
parts.unshift(name);
if (!(node as any).computed) {
parts.unshift(name);
}
return { name, nodes, parts };
}
function to_string(node: Node) {
switch (node.type) {
case 'Literal':
return String(node.value);
case 'Identifier':
return node.name;
}
}

@ -1,6 +1,5 @@
// https://github.com/darkskyapp/string-hash/blob/master/index.js
export default function hash(str: string): string {
str = str.replace(/\r/g, "");
let hash = 5381;
let i = str.length;

@ -1,14 +0,0 @@
import { Node } from 'estree';
export default function replace_object(node: Node, replacement: Node) {
if (node.type === 'Identifier') return replacement;
const ancestor = node;
let parent;
while (node.type === 'MemberExpression') {
parent = node;
node = node.object;
}
parent.object = replacement;
return ancestor;
}

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

@ -1,17 +0,0 @@
import { MemberExpression, Identifier } from "estree";
export function string_to_member_expression(name: string) {
const parts = name.split(".");
let node: MemberExpression | Identifier = {
type: "Identifier",
name: parts[0]
};
for (let i = 1; i < parts.length; i++) {
node = {
type: "MemberExpression",
object: node,
property: { type: "Identifier", name: parts[i] }
} as MemberExpression;
}
return node;
}

@ -16,7 +16,7 @@ const escaped = {
"'": '&#39;',
'&': '&amp;',
'<': '&lt;',
'>': '&gt;'
'>': '&gt;',
};
export function escape_html(html) {

@ -108,7 +108,7 @@ export interface CompileOptions {
format?: ModuleFormat;
name?: string;
filename?: string;
generate?: 'dom' | 'ssr' | false;
generate?: string | false;
outputFilename?: string;
cssOutputFilename?: string;
@ -166,4 +166,4 @@ export interface Var {
export interface CssResult {
code: string;
map: SourceMap;
}
}

@ -8,12 +8,6 @@ import error from '../utils/error';
type ParserState = (parser: Parser) => (ParserState | void);
interface LastAutoClosedTag {
tag: string;
reason: string;
depth: number;
}
export class Parser {
readonly template: string;
readonly filename?: string;
@ -26,7 +20,6 @@ export class Parser {
css: Style[] = [];
js: Script[] = [];
meta_tags = {};
last_auto_closed_tag?: LastAutoClosedTag;
constructor(template: string, options: ParserOptions) {
if (typeof template !== 'string') {
@ -41,7 +34,7 @@ export class Parser {
start: null,
end: null,
type: 'Fragment',
children: []
children: [],
};
this.stack.push(this.html);

@ -57,6 +57,6 @@ export default function read_script(parser: Parser, start: number, attributes: N
start,
end: parser.index,
context: get_context(parser, attributes, start),
content: ast
content: ast,
};
}

@ -14,7 +14,7 @@ export default function read_style(parser: Parser, start: number, attributes: No
try {
ast = parse(styles, {
positions: true,
offset: content_start
offset: content_start,
});
} catch (err) {
if (err.name === 'CssSyntaxError') {
@ -54,13 +54,6 @@ export default function read_style(parser: Parser, start: number, attributes: No
}, node.start);
}
if (node.type === 'PseudoClassSelector' && node.name === 'global' && node.children === null) {
parser.error({
code: `css-syntax-error`,
message: `:global() must contain a selector`
}, node.loc.start.offset);
}
if (node.loc) {
node.start = node.loc.start.offset;
node.end = node.loc.end.offset;
@ -94,4 +87,4 @@ function is_ref_selector(a: any, b: any) { // TODO add CSS node types
a.name === 'ref' &&
b.type === 'PseudoClassSelector'
);
}
}

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

Loading…
Cancel
Save