Merge branch 'master' into onmount_triggers_in_reverse_order_for_siblings

* master: (66 commits)
  -> v3.4.3
  always add raw property to text nodes
  flesh out in/out transition tutorial chapter (#2792)
  code style
  fix test
  fix tests
  Fix CRUD example to allow changing input values.
  Fixes #2714
  treat requestAnimationFrame as a noop on the server
  site: actions tutorial: destroy is not required (#2776)
  Allow binding of <details> open
  site: add /faq redirect to GitHub wiki FAQ
  fix case sensitive import name, improve tsconfig
  type declarations for bundled files
  convert everything to TypeScript
  check for unknown props when creating component
  cleanup, improve comments
  typecheck npm script
  workarond for estree-walker related typings conflict
  compile/render-dom and other remaining typings
  ...
pull/2752/head
Colin Casey 6 years ago
commit 135f7b6493

18
.gitignore vendored

@ -1,16 +1,17 @@
.idea
.DS_Store .DS_Store
.nyc_output .nyc_output
node_modules node_modules
*.map *.map
/src/compile/internal-exports.ts /src/compile/internal-exports.ts
/compiler.js /compiler.*js
/index.js /index.*js
/internal.* /internal.*js
/store.js /store.*js
/easing.js /easing.*js
/motion.* /motion.*js
/transition.js /transition.*js
/animate.js /animate.*js
/scratch/ /scratch/
/coverage/ /coverage/
/coverage.lcov/ /coverage.lcov/
@ -20,6 +21,7 @@ node_modules
/test/sourcemaps/samples/*/output.css.map /test/sourcemaps/samples/*/output.css.map
/yarn-error.log /yarn-error.log
_actual*.* _actual*.*
/dist
/site/cypress/screenshots/ /site/cypress/screenshots/
/site/__sapper__/ /site/__sapper__/

@ -1,5 +1,40 @@
# Svelte changelog # Svelte changelog
## 3.4.3
* Add type declaration files for everything ([#2842](https://github.com/sveltejs/svelte/pull/2842))
* Prevent `svelte/store` being bundled ([#2786](https://github.com/sveltejs/svelte/issues/2786))
* Warn on unknown props in dev mode ([#2840](https://github.com/sveltejs/svelte/pull/2840))
* Treat `requestAnimationFrame` as a no-op on the server ([#2856](https://github.com/sveltejs/svelte/pull/2856))
* Add `raw` property to AST's `Text` nodes ([#2714](https://github.com/sveltejs/svelte/issues/2714))
* Add `<details bind:open>` ([#2854](https://github.com/sveltejs/svelte/issues/2854))
## 3.4.2
* Use empty string for empty data attributes ([#2804](https://github.com/sveltejs/svelte/pull/2804))
* Support `customElement: true` with no `<svelte:options>` ([#2821](https://github.com/sveltejs/svelte/issues/2821))
* Add docstrings to `svelte/store` ([#2795](https://github.com/sveltejs/svelte/pull/2795))
## 3.4.1
* Handle non-falsy non-function return values from derivers ([#2780](https://github.com/sveltejs/svelte/issues/2780))
* Allow `spring` to work server-side ([#2773](https://github.com/sveltejs/svelte/issues/2773))
## 3.4.0
* Allow custom element to be defined without a `tag` ([#2417](https://github.com/sveltejs/svelte/issues/2417))
* Fix parsing of quote marks inside attribute values ([#2715](https://github.com/sveltejs/svelte/pull/2754))
* Convert `svelte/store` to TypeScript ([#2733](https://github.com/sveltejs/svelte/pull/2733))
* Allow `debug` tags to include hoisted values ([#2764](https://github.com/sveltejs/svelte/issues/2764))
* Parse error if attribute name is missing `=` ([#1513](https://github.com/sveltejs/svelte/pull/2770))
* Allow reactive declarations to depend on mutated `const` values ([#2728](https://github.com/sveltejs/svelte/issues/2728))
## 3.3.0
* Allow multiple event listeners on a single node ([#2688](https://github.com/sveltejs/svelte/issues/2688))
* Allow derivers to return a cleanup function ([#2553](https://github.com/sveltejs/svelte/issues/2553))
* Support namespaced components (`<Foo.Bar/>`) ([#2743](https://github.com/sveltejs/svelte/pull/2743))
## 3.2.2 ## 3.2.2
* Add `window` and `document` to expected globals ([#2722](https://github.com/sveltejs/svelte/pull/2722)) * Add `window` and `document` to expected globals ([#2722](https://github.com/sveltejs/svelte/pull/2722))

@ -2,7 +2,7 @@
<a href="https://svelte.dev"> <a href="https://svelte.dev">
<img alt="Cybernetically enhanced web apps: Svelte" src="https://svelte-assets.surge.sh/banner.png"> <img alt="Cybernetically enhanced web apps: Svelte" src="https://svelte-assets.surge.sh/banner.png">
</a> </a>
<a href="https://www.npmjs.com/package/svelte"> <a href="https://www.npmjs.com/package/svelte">
<img src="https://img.shields.io/npm/v/svelte.svg" alt="npm version"> <img src="https://img.shields.io/npm/v/svelte.svg" alt="npm version">
</a> </a>
@ -16,7 +16,7 @@
alt="build status"> alt="build status">
</a> </a>
<a href="https://github.com/svelte/svelte/blob/master/LICENSE.md"> <a href="https://github.com/sveltejs/svelte/blob/master/LICENSE">
<img src="https://img.shields.io/npm/l/svelte.svg" alt="license"> <img src="https://img.shields.io/npm/l/svelte.svg" alt="license">
</a> </a>
</p> </p>
@ -36,7 +36,7 @@ Pull requests are encouraged and always welcome. [Pick an issue](https://github.
To install and work on Svelte locally: To install and work on Svelte locally:
```bash ```bash
git clone git@github.com:sveltejs/svelte.git git clone https://github.com/sveltejs/svelte.git
cd svelte cd svelte
npm install npm install
``` ```

1
animate.d.ts vendored

@ -0,0 +1 @@
export * from './dist/animate';

1
compiler.d.ts vendored

@ -0,0 +1 @@
export * from './dist/compiler';

1
easing.d.ts vendored

@ -0,0 +1 @@
export * from './dist/easing';

1
index.d.ts vendored

@ -0,0 +1 @@
export * from './dist/index';

@ -1,10 +0,0 @@
export {
onMount,
onDestroy,
beforeUpdate,
afterUpdate,
setContext,
getContext,
tick,
createEventDispatcher
} from './internal';

1
internal.d.ts vendored

@ -0,0 +1 @@
export * from './dist/internal';

1
motion.d.ts vendored

@ -0,0 +1 @@
export * from './dist/motion';

51
package-lock.json generated

@ -1,6 +1,6 @@
{ {
"name": "svelte", "name": "svelte",
"version": "3.1.0", "version": "3.4.2",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -246,15 +246,6 @@
"integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
"dev": true "dev": true
}, },
"async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz",
"integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==",
"dev": true,
"requires": {
"lodash": "^4.17.11"
}
},
"async-limiter": { "async-limiter": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
@ -1550,12 +1541,12 @@
"dev": true "dev": true
}, },
"handlebars": { "handlebars": {
"version": "4.1.0", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.0.tgz", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz",
"integrity": "sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w==", "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==",
"dev": true, "dev": true,
"requires": { "requires": {
"async": "^2.5.0", "neo-async": "^2.6.0",
"optimist": "^0.6.1", "optimist": "^0.6.1",
"source-map": "^0.6.1", "source-map": "^0.6.1",
"uglify-js": "^3.1.4" "uglify-js": "^3.1.4"
@ -1996,9 +1987,9 @@
"dev": true "dev": true
}, },
"js-yaml": { "js-yaml": {
"version": "3.12.1", "version": "3.13.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
"integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
"dev": true, "dev": true,
"requires": { "requires": {
"argparse": "^1.0.7", "argparse": "^1.0.7",
@ -2448,6 +2439,12 @@
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
"dev": true "dev": true
}, },
"neo-async": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
"integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
"dev": true
},
"nice-try": { "nice-try": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
@ -4182,26 +4179,26 @@
"dev": true "dev": true
}, },
"typescript": { "typescript": {
"version": "3.2.4", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.5.tgz",
"integrity": "sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg==", "integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==",
"dev": true "dev": true
}, },
"uglify-js": { "uglify-js": {
"version": "3.4.9", "version": "3.5.12",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.12.tgz",
"integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", "integrity": "sha512-KeQesOpPiZNgVwJj8Ge3P4JYbQHUdZzpx6Fahy6eKAYRSV4zhVmLXoC+JtOeYxcHCHTve8RG1ZGdTvpeOUM26Q==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
"commander": "~2.17.1", "commander": "~2.20.0",
"source-map": "~0.6.1" "source-map": "~0.6.1"
}, },
"dependencies": { "dependencies": {
"commander": { "commander": {
"version": "2.17.1", "version": "2.20.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
"integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
"dev": true, "dev": true,
"optional": true "optional": true
} }

@ -1,6 +1,6 @@
{ {
"name": "svelte", "name": "svelte",
"version": "3.2.2", "version": "3.4.3",
"description": "Cybernetically enhanced web apps", "description": "Cybernetically enhanced web apps",
"module": "index.mjs", "module": "index.mjs",
"main": "index", "main": "index",
@ -27,11 +27,13 @@
"precodecov": "npm run coverage", "precodecov": "npm run coverage",
"lint": "eslint src test/*.js", "lint": "eslint src test/*.js",
"build": "rollup -c", "build": "rollup -c",
"prepare": "npm run build", "prepare": "npm run build && npm run tsd",
"dev": "rollup -cw", "dev": "rollup -cw",
"pretest": "npm run build", "pretest": "npm run build",
"posttest": "agadoo src/internal/index.js", "posttest": "agadoo internal.mjs",
"prepublishOnly": "export PUBLISH=true && npm run lint && npm test" "prepublishOnly": "export PUBLISH=true && npm run lint && npm test",
"tsd": "tsc -p . --emitDeclarationOnly",
"typecheck": "tsc -p . --noEmit"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -83,7 +85,7 @@
"tiny-glob": "^0.2.1", "tiny-glob": "^0.2.1",
"ts-node": "^8.0.2", "ts-node": "^8.0.2",
"tslib": "^1.8.0", "tslib": "^1.8.0",
"typescript": "^3.0.1" "typescript": "^3.4.0"
}, },
"nyc": { "nyc": {
"include": [ "include": [

@ -9,10 +9,19 @@ import pkg from './package.json';
const is_publish = !!process.env.PUBLISH; const is_publish = !!process.env.PUBLISH;
const tsPlugin = is_publish
? typescript({
include: 'src/**',
typescript: require('typescript')
})
: sucrase({
transforms: ['typescript']
});
export default [ export default [
/* internal.[m]js */ /* internal.[m]js */
{ {
input: `src/internal/index.js`, input: `src/internal/index.ts`,
output: [ output: [
{ {
file: `internal.mjs`, file: `internal.mjs`,
@ -26,19 +35,22 @@ export default [
} }
], ],
external: id => id.startsWith('svelte/'), external: id => id.startsWith('svelte/'),
plugins: [{
generateBundle(options, bundle) { plugins: [
const mod = bundle['internal.mjs']; tsPlugin,
if (mod) { {
fs.writeFileSync('src/compile/internal-exports.ts', `// This file is automatically generated\nexport default new Set(${JSON.stringify(mod.exports)});`); generateBundle(options, bundle) {
const mod = bundle['internal.mjs'];
if (mod) {
fs.writeFileSync('src/compile/internal-exports.ts', `// This file is automatically generated\nexport default new Set(${JSON.stringify(mod.exports)});`);
}
} }
} }]
}]
}, },
/* compiler.js */ /* compiler.js */
{ {
input: 'src/index.ts', input: 'src/compiler.ts',
plugins: [ plugins: [
replace({ replace({
__VERSION__: pkg.version __VERSION__: pkg.version
@ -48,15 +60,7 @@ export default [
include: ['node_modules/**'] include: ['node_modules/**']
}), }),
json(), json(),
is_publish tsPlugin
? typescript({
include: 'src/**',
exclude: 'src/internal/**',
typescript: require('typescript')
})
: sucrase({
transforms: ['typescript']
})
], ],
output: { output: {
file: 'compiler.js', file: 'compiler.js',
@ -71,7 +75,7 @@ export default [
/* motion.mjs */ /* motion.mjs */
{ {
input: `src/motion/index.js`, input: `src/motion/index.ts`,
output: [ output: [
{ {
file: `motion.mjs`, file: `motion.mjs`,
@ -84,17 +88,30 @@ export default [
paths: id => id.startsWith('svelte/') && id.replace('svelte', '.') paths: id => id.startsWith('svelte/') && id.replace('svelte', '.')
} }
], ],
plugins: [
tsPlugin
],
external: id => id.startsWith('svelte/') external: id => id.startsWith('svelte/')
}, },
// everything else // everything else
...['index', 'store', 'easing', 'transition', 'animate'].map(name => ({ ...['index', 'easing', 'transition', 'animate', 'store'].map(name => ({
input: `${name}.mjs`, input: `src/${name}.ts`,
output: { output: [
file: `${name}.js`, {
format: 'cjs', file: `${name}.mjs`,
paths: id => id.startsWith('svelte/') && id.replace('svelte', '.') format: 'esm',
}, paths: id => id.startsWith('svelte/') && id.replace('svelte', '.')
external: id => id !== `${name}.mjs` },
{
file: `${name}.js`,
format: 'cjs',
paths: id => id.startsWith('svelte/') && id.replace('svelte', '.')
}
],
plugins: [
tsPlugin
],
external: id => id.startsWith('svelte/')
})) }))
]; ];

@ -13,7 +13,11 @@ Start the server with `npm run dev`, and navigate to [localhost:3000](http://loc
## Using a 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. To use the local copy of the compiler and runtime from this repo, you can navigate to [localhost:3000/repl?version=local](http://localhost:3000/repl?version=local). To produce the proper browser-compatible UMD build, you will need to run `npm run build` with the `PUBLISH` environment variable set (to any non-empty string). 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.
Then visit the REPL at [localhost:3000/repl?version=local](http://localhost:3000/repl?version=local).
## REPL GitHub integration ## REPL GitHub integration

@ -44,9 +44,11 @@ In the terminal, you can instantly create a new project like so:
npx degit sveltejs/template my-svelte-project npx degit sveltejs/template my-svelte-project
cd my-svelte-project cd my-svelte-project
npm install npm install
npm run dev & open http://localhost:5000 npm run dev
``` ```
This will create a new project in the `my-svelte-project` directory, install its dependencies, and start a server on http://localhost:5000.
Once you've tinkered a bit and understood how everything fits together, you can fork [sveltejs/template](https://github.com/sveltejs/template) and start doing this instead: Once you've tinkered a bit and understood how everything fits together, you can fork [sveltejs/template](https://github.com/sveltejs/template) and start doing this instead:
```bash ```bash

@ -47,11 +47,14 @@ Svelte uses the `export` keyword to mark a variable declaration as a *property*
// Values that are passed in as props // Values that are passed in as props
// are immediately available // are immediately available
console.log(foo, bar); console.log(foo, bar);
// function declarations cannot be set externally, // Function expressions can also be props
// but can be accessed from outside export let format = (number) => (number.toFixed(2));
export function instanceMethod() {
alert(foo); // Function declarations are added as methods
// on the component, rather than props
export function greetMethod() {
alert(`I'm a <${this.constructor.name}>!`);
} }
// you can also use export { ... as ... } to have // you can also use export { ... as ... } to have

@ -351,6 +351,24 @@ If the `on:` directive is used without a value, the component will *forward* the
</button> </button>
``` ```
---
It's possible to have multiple event listeners for the same event:
```html
<script>
let counter = 0;
function increment() {
counter = counter + 1;
}
function track(event) {
trackEvent(event)
}
</script>
<button on:click={increment} on:click={track}>Click me!</button>
```
### Component events ### Component events
@ -1261,3 +1279,50 @@ The `<svelte:options>` element provides a place to specify per-component compile
```html ```html
<svelte:options tag="my-custom-element"/> <svelte:options tag="my-custom-element"/>
``` ```
### @debug
```sv
{@debug}
```
```sv
{@debug var1, var2, ..., varN}
```
---
The `{@debug ...}` tag offers an alternative to `console.log(...)`. It logs the values of specific variables whenever they change, and pauses code execution if you have devtools open.
It accepts a comma-separated list of variable names (not arbitrary expressions).
```html
<script>
let user = {
firstname: 'Ada',
lastname: 'Lovelace'
};
</script>
{@debug user}
<h1>Hello {user.firstname}!</h1>
```
---
`{@debug ...}` accepts a comma-separated list of variable names (not arbitrary expressions).
```html
<!-- Compiles -->
{@debug user}
{@debug user1, user2, user3}
<!-- WON'T compile -->
{@debug user.firstname}
{@debug myArray[0]}
{@debug !isReady}
{@debug typeof user === 'object'}
```
The `{@debug}` tag without any arguments will insert a `debugger` statement that gets triggered when *any* state changes, as opposed to the specified variables.

@ -308,8 +308,8 @@ const { code } = svelte.preprocess(source, [
```js ```js
walk(ast: Node, { walk(ast: Node, {
enter(node: Node, parent: Node)?: void, enter(node: Node, parent: Node, prop: string, index: number)?: void,
leave(node: Node, parent: Node)?: void leave(node: Node, parent: Node, prop: string, index: number)?: void
}) })
``` ```
@ -323,13 +323,13 @@ The walker takes an abstract syntax tree to walk and an object with two optional
```js ```js
const svelte = require('svelte/compiler'); const svelte = require('svelte/compiler');
svelte.walk(ast, { svelte.walk(ast, {
enter(node, parent) { enter(node, parent, prop, index) {
do_something(node); do_something(node);
if (should_skip_children(node)) { if (should_skip_children(node)) {
this.skip(); this.skip();
} }
}, },
leave(node, parent) { leave(node, parent, prop, index) {
do_something_else(node); do_something_else(node);
} }
}); });

@ -1,6 +1,6 @@
<script> <script>
import { quintOut } from 'svelte/easing'; import { quintOut } from 'svelte/easing';
import { crossfade } from 'svelte/transition'; import { crossfade } from 'svelte/transition';
import { flip } from 'svelte/animate'; import { flip } from 'svelte/animate';
const [send, receive] = crossfade({ const [send, receive] = crossfade({
@ -44,12 +44,6 @@
function remove(todo) { function remove(todo) {
todos = todos.filter(t => t !== todo); todos = todos.filter(t => t !== todo);
} }
function handleKeydown(event) {
if (event.which === 13) {
addTodo(event.target);
}
}
</script> </script>
<style> <style>
@ -115,7 +109,7 @@
</style> </style>
<div class='board'> <div class='board'>
<input class="new-todo" placeholder="what needs to be done?" on:enter={add}> <input class="new-todo" placeholder="what needs to be done?" on:keydown="{event => event.which === 13 && add(this)}">
<div class='left'> <div class='left'>
<h2>todo</h2> <h2>todo</h2>

@ -30,10 +30,7 @@
$: selected = filteredPeople[i]; $: selected = filteredPeople[i];
$: { $: reset_inputs(selected);
first = selected ? selected.first : '';
last = selected ? selected.last : '';
}
function create() { function create() {
people = people.concat({ first, last }); people = people.concat({ first, last });
@ -53,7 +50,8 @@
} }
function reset_inputs(person) { function reset_inputs(person) {
({ first, last } = person); first = person ? person.first : '';
last = person ? person.last : '';
} }
</script> </script>

@ -1,11 +1,13 @@
export default function flash(element) { export default function flash(element) {
element.style.transition = 'none'; requestAnimationFrame(() => {
element.style.color = 'rgba(255,62,0,1)'; element.style.transition = 'none';
element.style.backgroundColor = 'rgba(255,62,0,0.2)'; element.style.color = 'rgba(255,62,0,1)';
element.style.backgroundColor = 'rgba(255,62,0,0.2)';
setTimeout(() => { setTimeout(() => {
element.style.transition = 'color 1s, background 1s'; element.style.transition = 'color 1s, background 1s';
element.style.color = ''; element.style.color = '';
element.style.backgroundColor = ''; element.style.backgroundColor = '';
});
}); });
} }

@ -2,7 +2,13 @@
title: In and out title: In and out
--- ---
Instead of the `transition` directive, an element can have an `in` or an `out` directive, or both together: Instead of the `transition` directive, an element can have an `in` or an `out` directive, or both together. Import `fade` alongside `fly`...
```js
import { fade, fly } from 'svelte/transition';
```
...then replace the `transition` directive with separate `in` and `out` directives:
```html ```html
<p in:fly="{{ y: 200, duration: 2000 }}" out:fade> <p in:fly="{{ y: 200, duration: 2000 }}" out:fade>

@ -27,7 +27,7 @@ import { pannable } from './pannable.js';
></div> ></div>
``` ```
Open the `pannable.js` file. Like transition functions, an action function receives a `node` and some optional parameters, and returns an action object. That object must have a `destroy` function, which is called when the element is unmounted. Open the `pannable.js` file. Like transition functions, an action function receives a `node` and some optional parameters, and returns an action object. That object can have a `destroy` function, which is called when the element is unmounted.
We want to fire `panstart` event when the user mouses down on the element, `panmove` events (with `dx` and `dy` properties showing how far the mouse moved) when they drag it, and `panend` events when they mouse up. One possible implementation looks like this: We want to fire `panstart` event when the user mouses down on the element, `panmove` events (with `dx` and `dy` properties showing how far the mouse moved) when they drag it, and `panend` events when they mouse up. One possible implementation looks like this:
@ -84,4 +84,3 @@ export function pannable(node) {
Update the `pannable` function and try moving the box around. Update the `pannable` function and try moving the box around.
> This implementation is for demonstration purposes — a more complete one would also consider touch events. > This implementation is for demonstration purposes — a more complete one would also consider touch events.

@ -1,11 +1,13 @@
export default function flash(element) { export default function flash(element) {
element.style.transition = 'none'; requestAnimationFrame(() => {
element.style.color = 'rgba(255,62,0,1)'; element.style.transition = 'none';
element.style.backgroundColor = 'rgba(255,62,0,0.2)'; element.style.color = 'rgba(255,62,0,1)';
element.style.backgroundColor = 'rgba(255,62,0,0.2)';
setTimeout(() => { setTimeout(() => {
element.style.transition = 'color 1s, background 1s'; element.style.transition = 'color 1s, background 1s';
element.style.color = ''; element.style.color = '';
element.style.backgroundColor = ''; element.style.backgroundColor = '';
});
}); });
} }

@ -1,11 +1,13 @@
export default function flash(element) { export default function flash(element) {
element.style.transition = 'none'; requestAnimationFrame(() => {
element.style.color = 'rgba(255,62,0,1)'; element.style.transition = 'none';
element.style.backgroundColor = 'rgba(255,62,0,0.2)'; element.style.color = 'rgba(255,62,0,1)';
element.style.backgroundColor = 'rgba(255,62,0,0.2)';
setTimeout(() => { setTimeout(() => {
element.style.transition = 'color 1s, background 1s'; element.style.transition = 'color 1s, background 1s';
element.style.color = ''; element.style.color = '';
element.style.backgroundColor = ''; element.style.backgroundColor = '';
});
}); });
} }

@ -33,23 +33,6 @@
"resolve": "^1.3.2", "resolve": "^1.3.2",
"semver": "^5.4.1", "semver": "^5.4.1",
"source-map": "^0.5.0" "source-map": "^0.5.0"
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true
}
} }
}, },
"@babel/generator": { "@babel/generator": {
@ -808,23 +791,6 @@
"debug": "^4.1.0", "debug": "^4.1.0",
"globals": "^11.1.0", "globals": "^11.1.0",
"lodash": "^4.17.11" "lodash": "^4.17.11"
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true
}
} }
}, },
"@babel/types": { "@babel/types": {
@ -1366,14 +1332,14 @@
"integrity": "sha512-ym6ooqMr09+cV+y52p5kszJ0jYcX+nJfm8POrQb7QYowvpPPuneZ71EclHrQSB7a50lcytgR/xtL6AUFdvyEkg==" "integrity": "sha512-ym6ooqMr09+cV+y52p5kszJ0jYcX+nJfm8POrQb7QYowvpPPuneZ71EclHrQSB7a50lcytgR/xtL6AUFdvyEkg=="
}, },
"@polka/send": { "@polka/send": {
"version": "1.0.0-next.2", "version": "1.0.0-next.3",
"resolved": "https://registry.npmjs.org/@polka/send/-/send-1.0.0-next.2.tgz", "resolved": "https://registry.npmjs.org/@polka/send/-/send-1.0.0-next.3.tgz",
"integrity": "sha512-eq8gUzykpYPuOMrnyAzsL4KunhQXZKFiNsbThAwh19PrBAz2v8mECsj3YnxjYYifbB1w1vhR74nsXQWDi80oAg==" "integrity": "sha512-54ftOGSZQMx8Xh8pnPgAj4499wppAEHQ892A7WacYOJ7ySuCWVgFmpODmXC2hU7qD9Scbi0iAu8rZls3ld+Eyg=="
}, },
"@polka/url": { "@polka/url": {
"version": "1.0.0-next.1", "version": "1.0.0-next.3",
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.1.tgz", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.3.tgz",
"integrity": "sha512-6d8YbKW4hjJMnU6ZJSDLtALWiB4J//OIPaP885ruf5U8MLZHigocDxhjgvLwbV6bGkikhllgTjD9eWioKWAQdA==" "integrity": "sha512-Uom7l6OeP6vcf85lMImelYu5WKVWjXyhkpi9WsRdRzlJFJFPVhjBtBCktgDUj7dk1N5FURUdegSZ5XOjxf8JZg=="
}, },
"@sindresorhus/slugify": { "@sindresorhus/slugify": {
"version": "0.9.1", "version": "0.9.1",
@ -1396,9 +1362,9 @@
} }
}, },
"@sveltejs/svelte-repl": { "@sveltejs/svelte-repl": {
"version": "0.0.10", "version": "0.0.11",
"resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.0.10.tgz", "resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.0.11.tgz",
"integrity": "sha512-PYXCN8OC2q3WzwtMcbFinLGzFI7RlD3cHqjkUuQWDaIMHriKYuALun4H/FxP8w3B3hNe9OBprgGmBzlkPuGEJw==", "integrity": "sha512-F284f8qaUs1rp8akqWXcB6oovlaso7qmsUz1rqm80FwUKLffjYIWy2a1p6+Yo1kRy6Q+fW8kj21JLEqv7pjOwA==",
"dev": true, "dev": true,
"requires": { "requires": {
"codemirror": "^5.45.0", "codemirror": "^5.45.0",
@ -1412,9 +1378,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "11.13.8", "version": "12.0.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.8.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.2.tgz",
"integrity": "sha512-szA3x/3miL90ZJxUCzx9haNbK5/zmPieGraZEe4WI+3srN0eGLiT22NXeMHmyhNEopn+IrxqMc7wdVwvPl8meg==", "integrity": "sha512-5tabW/i+9mhrfEOUcLDu2xBPsHJ+X5Orqy9FKpale3SjDA17j5AEpYq5vfy3oAeAHGcvANRCO3NV3d2D6q3NiA==",
"dev": true "dev": true
}, },
"@types/pg": { "@types/pg": {
@ -1660,14 +1626,14 @@
"dev": true "dev": true
}, },
"browserslist": { "browserslist": {
"version": "4.5.6", "version": "4.6.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.6.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.0.tgz",
"integrity": "sha512-o/hPOtbU9oX507lIqon+UvPYqpx3mHc8cV3QemSBTXwkG8gSQSK6UKvXcE/DcleU3+A59XTUHyCvZ5qGy8xVAg==", "integrity": "sha512-Jk0YFwXBuMOOol8n6FhgkDzn3mY9PYLYGk29zybF05SbRTsMgPqmTNeQQhOghCxq5oFqAXE3u4sYddr4C0uRhg==",
"dev": true, "dev": true,
"requires": { "requires": {
"caniuse-lite": "^1.0.30000963", "caniuse-lite": "^1.0.30000967",
"electron-to-chromium": "^1.3.127", "electron-to-chromium": "^1.3.133",
"node-releases": "^1.1.17" "node-releases": "^1.1.19"
} }
}, },
"buffer": { "buffer": {
@ -1742,9 +1708,9 @@
"dev": true "dev": true
}, },
"caniuse-lite": { "caniuse-lite": {
"version": "1.0.30000963", "version": "1.0.30000967",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000963.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000967.tgz",
"integrity": "sha512-n4HUiullc7Lw0LyzpeLa2ffP8KxFBGdxqD/8G3bSL6oB758hZ2UE2CVK+tQN958tJIi0/tfpjAc67aAtoHgnrQ==", "integrity": "sha512-rUBIbap+VJfxTzrM4akJ00lkvVb5/n5v3EGXfWzSH5zT8aJmGzjA8HWhJ4U6kCpzxozUSnB+yvAYDRPY6mRpgQ==",
"dev": true "dev": true
}, },
"chalk": { "chalk": {
@ -1970,12 +1936,12 @@
} }
}, },
"debug": { "debug": {
"version": "2.6.9", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true, "dev": true,
"requires": { "requires": {
"ms": "2.0.0" "ms": "^2.1.1"
} }
}, },
"decamelize": { "decamelize": {
@ -2096,9 +2062,9 @@
} }
}, },
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.3.129", "version": "1.3.134",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.129.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.134.tgz",
"integrity": "sha512-puirJsgZnedlFEmRa7WEUIaS8ZgHHn7d7inph+RiapCc0x80hdoDyEEpR9z3aRUSZy4fGxOTOFcxnGmySlrmhA==", "integrity": "sha512-C3uK2SrtWg/gSWaluLHWSHjyebVZCe4ZC0NVgTAoTq8tCR9FareRK5T7R7AS/nPZShtlEcjVMX1kQ8wi4nU68w==",
"dev": true "dev": true
}, },
"emoji-regex": { "emoji-regex": {
@ -2157,9 +2123,9 @@
"dev": true "dev": true
}, },
"eslint-plugin-svelte3": { "eslint-plugin-svelte3": {
"version": "1.0.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-svelte3/-/eslint-plugin-svelte3-1.0.0.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-svelte3/-/eslint-plugin-svelte3-1.2.0.tgz",
"integrity": "sha512-lsKUKPrzsjB4JAwmGhfg/Xssc/+L4KU8oL5WNZ0q/D3DkYkIVE4XpT/j8TY6oEFLd31Sznm7itw8Q7RsK6g0cA==", "integrity": "sha512-7tuYh8YdwE9PP96U9qNJUSVMaxxUS/HZEZtEDlNGSAe0g40xd12pJo6lrc5wGxOmXpR6adGy5DnkSSF1UXGDKg==",
"dev": true "dev": true
}, },
"esm": { "esm": {
@ -2222,6 +2188,15 @@
"to-regex": "^3.0.1" "to-regex": "^3.0.1"
}, },
"dependencies": { "dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"requires": {
"ms": "2.0.0"
}
},
"define-property": { "define-property": {
"version": "0.2.5", "version": "0.2.5",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
@ -2239,6 +2214,12 @@
"requires": { "requires": {
"is-extendable": "^0.1.0" "is-extendable": "^0.1.0"
} }
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
} }
} }
}, },
@ -2373,14 +2354,6 @@
"dev": true, "dev": true,
"requires": { "requires": {
"is-buffer": "~2.0.3" "is-buffer": "~2.0.3"
},
"dependencies": {
"is-buffer": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
"integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==",
"dev": true
}
} }
}, },
"for-each": { "for-each": {
@ -2408,9 +2381,9 @@
} }
}, },
"fs-minipass": { "fs-minipass": {
"version": "1.2.5", "version": "1.2.6",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.6.tgz",
"integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "integrity": "sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"minipass": "^2.2.1" "minipass": "^2.2.1"
@ -2450,9 +2423,9 @@
"dev": true "dev": true
}, },
"glob": { "glob": {
"version": "7.1.3", "version": "7.1.4",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
"dev": true, "dev": true,
"requires": { "requires": {
"fs.realpath": "^1.0.0", "fs.realpath": "^1.0.0",
@ -2547,6 +2520,12 @@
"kind-of": "^4.0.0" "kind-of": "^4.0.0"
}, },
"dependencies": { "dependencies": {
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
},
"kind-of": { "kind-of": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
@ -2577,26 +2556,18 @@
"dev": true "dev": true
}, },
"html-minifier": { "html-minifier": {
"version": "3.5.21", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz",
"integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==",
"dev": true, "dev": true,
"requires": { "requires": {
"camel-case": "3.0.x", "camel-case": "^3.0.0",
"clean-css": "4.2.x", "clean-css": "^4.2.1",
"commander": "2.17.x", "commander": "^2.19.0",
"he": "1.2.x", "he": "^1.2.0",
"param-case": "2.1.x", "param-case": "^2.1.1",
"relateurl": "0.2.x", "relateurl": "^0.2.7",
"uglify-js": "3.4.x" "uglify-js": "^3.5.1"
},
"dependencies": {
"commander": {
"version": "2.17.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
"integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
"dev": true
}
} }
}, },
"http-link-header": { "http-link-header": {
@ -2606,9 +2577,9 @@
"dev": true "dev": true
}, },
"httpie": { "httpie": {
"version": "1.1.1", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/httpie/-/httpie-1.1.1.tgz", "resolved": "https://registry.npmjs.org/httpie/-/httpie-1.1.2.tgz",
"integrity": "sha512-KYgUXOhxVPo5mYuFPqnKW14fP5goMGkLc9CRz0WD6b1TCED9nl9wzj4jqr+8LY+AhPJQ/LdCQLRfF2JrBEja5Q==" "integrity": "sha512-VQ82oXG95oY1fQw/XecHuvcFBA+lZQ9Vwj1RfLcO8a7HpDd4cc2ukwpJt+TUlFaLUAzZErylxWu6wclJ1rUhUQ=="
}, },
"ieee754": { "ieee754": {
"version": "1.1.13", "version": "1.1.13",
@ -2662,6 +2633,12 @@
"kind-of": "^3.0.2" "kind-of": "^3.0.2"
}, },
"dependencies": { "dependencies": {
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
},
"kind-of": { "kind-of": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@ -2680,9 +2657,9 @@
"dev": true "dev": true
}, },
"is-buffer": { "is-buffer": {
"version": "1.1.6", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==",
"dev": true "dev": true
}, },
"is-callable": { "is-callable": {
@ -2700,6 +2677,12 @@
"kind-of": "^3.0.2" "kind-of": "^3.0.2"
}, },
"dependencies": { "dependencies": {
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
},
"kind-of": { "kind-of": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@ -2769,6 +2752,12 @@
"kind-of": "^3.0.2" "kind-of": "^3.0.2"
}, },
"dependencies": { "dependencies": {
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
},
"kind-of": { "kind-of": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@ -2949,13 +2938,6 @@
"lodash.once": "^4.0.0", "lodash.once": "^4.0.0",
"ms": "^2.1.1", "ms": "^2.1.1",
"semver": "^5.6.0" "semver": "^5.6.0"
},
"dependencies": {
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
}
} }
}, },
"jwa": { "jwa": {
@ -3195,9 +3177,9 @@
} }
}, },
"mime": { "mime": {
"version": "2.4.2", "version": "2.4.3",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.2.tgz", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.3.tgz",
"integrity": "sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg==" "integrity": "sha512-QgrPRJfE+riq5TPZMcHZOtm8c6K/yYrMbKIoRfapfiGLxS8OTeIfRhUGW5LU7MlRa52KOAGCfUNruqLrIBvWZw=="
}, },
"mimic-fn": { "mimic-fn": {
"version": "2.1.0", "version": "2.1.0",
@ -3326,11 +3308,19 @@
"ms": "^2.1.1" "ms": "^2.1.1"
} }
}, },
"ms": { "glob": {
"version": "2.1.1", "version": "7.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"dev": true "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"
}
}, },
"supports-color": { "supports-color": {
"version": "6.0.0", "version": "6.0.0",
@ -3356,10 +3346,9 @@
"dev": true "dev": true
}, },
"ms": { "ms": {
"version": "2.0.0", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
"dev": true
}, },
"nanomatch": { "nanomatch": {
"version": "1.2.13", "version": "1.2.13",
@ -3412,9 +3401,9 @@
"dev": true "dev": true
}, },
"node-pg-migrate": { "node-pg-migrate": {
"version": "3.19.0", "version": "3.20.0",
"resolved": "https://registry.npmjs.org/node-pg-migrate/-/node-pg-migrate-3.19.0.tgz", "resolved": "https://registry.npmjs.org/node-pg-migrate/-/node-pg-migrate-3.20.0.tgz",
"integrity": "sha512-IIiiP6oHR9JDOqlIpaRFTnIedPIMXsYiMOkCPCSCGA2e+ZuDn/VS07CbDwVwKA+sBfwR0g5KIBx7QZGAS6sesQ==", "integrity": "sha512-7crNxFNueGgLVYw74FIi0MFowbXlVVpK2ZVM0RvJkhlA0da0Gt+pLmQYFkAuCl2cdfcvK72yUEvtXiw0Uei5CQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/pg": "^7.4.0", "@types/pg": "^7.4.0",
@ -3426,9 +3415,9 @@
} }
}, },
"node-releases": { "node-releases": {
"version": "1.1.17", "version": "1.1.19",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.17.tgz", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.19.tgz",
"integrity": "sha512-/SCjetyta1m7YXLgtACZGDYJdCSIBAWorDWkGCGZlydP2Ll7J48l7j/JxNYZ+xsgSPbWfdulVS/aY+GdjUsQ7Q==", "integrity": "sha512-SH/B4WwovHbulIALsQllAVwqZZD1kPmKCqrhGfR29dXjLAVZMHvBjD3S6nL9D/J9QkmZ1R92/0wCMDKXUUvyyA==",
"dev": true, "dev": true,
"requires": { "requires": {
"semver": "^5.3.0" "semver": "^5.3.0"
@ -3498,6 +3487,12 @@
"is-descriptor": "^0.1.0" "is-descriptor": "^0.1.0"
} }
}, },
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
},
"kind-of": { "kind-of": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@ -3725,9 +3720,9 @@
} }
}, },
"pg": { "pg": {
"version": "7.10.0", "version": "7.11.0",
"resolved": "https://registry.npmjs.org/pg/-/pg-7.10.0.tgz", "resolved": "https://registry.npmjs.org/pg/-/pg-7.11.0.tgz",
"integrity": "sha512-aE6FZomsyn3OeGv1oM50v7Xu5zR75c15LXdOCwA9GGrfjXsQjzwYpbcTS6OwEMhYfZQS6m/FVU/ilPLiPzJDCw==", "integrity": "sha512-YO4V7vCmEMGoF390LJaFaohWNKaA2ayoQOEZmiHVcAUF+YsRThpf/TaKCgSvsSE7cDm37Q/Cy3Gz41xiX/XjTw==",
"requires": { "requires": {
"buffer-writer": "2.0.0", "buffer-writer": "2.0.0",
"packet-reader": "1.0.0", "packet-reader": "1.0.0",
@ -3814,12 +3809,12 @@
"dev": true "dev": true
}, },
"polka": { "polka": {
"version": "1.0.0-next.2", "version": "1.0.0-next.3",
"resolved": "https://registry.npmjs.org/polka/-/polka-1.0.0-next.2.tgz", "resolved": "https://registry.npmjs.org/polka/-/polka-1.0.0-next.3.tgz",
"integrity": "sha512-y82w42/8IA7bc4YwGwAmnbrXj8ZWWDGvnfwq1b0eCtFielZSSSJv7OXUIKQuc/vw5OCCM1hPIgrYsNPzbwDaJw==", "integrity": "sha512-VmCsJK2uAqyjtV8e6ujEhgehibh+lvgdlrIgkTGsL+EKrCS/+BmGq57NV7yvkeGKI4XhsCw/J1YSeejmNfhbig==",
"requires": { "requires": {
"@polka/url": "^1.0.0-next.1", "@polka/url": "^1.0.0-next.3",
"trouter": "^3.0.1" "trouter": "^3.0.2"
} }
}, },
"posix-character-classes": { "posix-character-classes": {
@ -3929,9 +3924,9 @@
"dev": true "dev": true
}, },
"regenerate-unicode-properties": { "regenerate-unicode-properties": {
"version": "8.0.2", "version": "8.1.0",
"resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.0.2.tgz", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz",
"integrity": "sha512-SbA/iNrBUf6Pv2zU8Ekv1Qbhv92yxL4hiDa2siuxs4KKn4oOoMDHXjAf7+Nz9qinUQ46B1LcWEi/PhJfPWpZWQ==", "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==",
"dev": true, "dev": true,
"requires": { "requires": {
"regenerate": "^1.4.0" "regenerate": "^1.4.0"
@ -4047,9 +4042,9 @@
"dev": true "dev": true
}, },
"resolve": { "resolve": {
"version": "1.10.1", "version": "1.11.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz",
"integrity": "sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA==", "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==",
"dev": true, "dev": true,
"requires": { "requires": {
"path-parse": "^1.0.6" "path-parse": "^1.0.6"
@ -4077,9 +4072,9 @@
} }
}, },
"rollup": { "rollup": {
"version": "1.11.2", "version": "1.11.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-1.11.2.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.11.3.tgz",
"integrity": "sha512-H5sS7GZ/Rn0t119Et8mw0QXtg5HTOI/1FL57EKHk5oduRmGaraOf3KcEt6j+dXJ9tXxWQkG+/FBjPS4dzxo6EA==", "integrity": "sha512-81MR7alHcFKxgWzGfG7jSdv+JQxSOIOD/Fa3iNUmpzbd7p+V19e1l9uffqT8/7YAHgGOzmoPGN3Fx3L2ptOf5g==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/estree": "0.0.39", "@types/estree": "0.0.39",
@ -4127,9 +4122,9 @@
} }
}, },
"rollup-plugin-node-resolve": { "rollup-plugin-node-resolve": {
"version": "4.2.3", "version": "4.2.4",
"resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-4.2.3.tgz", "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-4.2.4.tgz",
"integrity": "sha512-r+WaesPzdGEynpLZLALFEDugA4ACa5zn7bc/+LVX4vAXQQ8IgDHv0xfsSvJ8tDXUtprfBtrDtRFg27ifKjcJTg==", "integrity": "sha512-t/64I6l7fZ9BxqD3XlX4ZeO6+5RLKyfpwE2CiPNUKa+GocPlQhf/C208ou8y3AwtNsc6bjSk/8/6y/YAyxCIvw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/resolve": "0.0.8", "@types/resolve": "0.0.8",
@ -4172,9 +4167,9 @@
} }
}, },
"rollup-pluginutils": { "rollup-pluginutils": {
"version": "2.6.0", "version": "2.7.0",
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.6.0.tgz", "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.7.0.tgz",
"integrity": "sha512-aGQwspEF8oPKvg37u3p7h0cYNwmJR1sCBMZGZ5b9qy8HGtETknqjzcxrDRrcAnJNXN18lBH4Q9vZYth/p4n8jQ==", "integrity": "sha512-FoP6L1YnMYTAR06Dpq5LE3jJtMwPE6H4VEOqFU23yoziZnqNRSiWcVy6YgEY5PdQB4G7278+8c4TvB0JKS1csA==",
"dev": true, "dev": true,
"requires": { "requires": {
"estree-walker": "^0.6.0", "estree-walker": "^0.6.0",
@ -4207,24 +4202,16 @@
} }
}, },
"sapper": { "sapper": {
"version": "0.26.0", "version": "0.27.1",
"resolved": "https://registry.npmjs.org/sapper/-/sapper-0.26.0.tgz", "resolved": "https://registry.npmjs.org/sapper/-/sapper-0.27.1.tgz",
"integrity": "sha512-KdouvzoCeCLirGwlf6U1KwT8GDTFNtK9KEQRFV8bQvNJQzwqS7+QyPAK8Z2MnR7gamluo+bDx84cTtnHD9I/mQ==", "integrity": "sha512-RH0K1uQ3zJ1IXvowxr2SuboGXV69q22KaPMhhoM5VNDv9fsUlVHtluZE8WTcGxckiO2L1xFfgM7v/aINkSZpcw==",
"dev": true, "dev": true,
"requires": { "requires": {
"html-minifier": "^3.5.21", "html-minifier": "^4.0.0",
"http-link-header": "^1.0.2", "http-link-header": "^1.0.2",
"shimport": "^1.0.0", "shimport": "^1.0.0",
"sourcemap-codec": "^1.4.4", "sourcemap-codec": "^1.4.4",
"string-hash": "^1.1.3" "string-hash": "^1.1.3"
},
"dependencies": {
"shimport": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/shimport/-/shimport-1.0.0.tgz",
"integrity": "sha512-XKd+39voZT1rFR1ct+pr8sFSYAW6IvM3LeF87FrgcGHc/uSZ4GfOZVA42LE5LXFOpTWgmDC5sS8DNDtiV4Vd4Q==",
"dev": true
}
} }
}, },
"sax": { "sax": {
@ -4317,6 +4304,12 @@
"rechoir": "^0.6.2" "rechoir": "^0.6.2"
} }
}, },
"shimport": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/shimport/-/shimport-1.0.0.tgz",
"integrity": "sha512-XKd+39voZT1rFR1ct+pr8sFSYAW6IvM3LeF87FrgcGHc/uSZ4GfOZVA42LE5LXFOpTWgmDC5sS8DNDtiV4Vd4Q==",
"dev": true
},
"signal-exit": { "signal-exit": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
@ -4324,9 +4317,9 @@
"dev": true "dev": true
}, },
"sirv": { "sirv": {
"version": "0.4.0", "version": "0.4.2",
"resolved": "https://registry.npmjs.org/sirv/-/sirv-0.4.0.tgz", "resolved": "https://registry.npmjs.org/sirv/-/sirv-0.4.2.tgz",
"integrity": "sha512-k/dcRW7Ry2VgERDiLyyq3peGZEnqP2EcTcG5646QjoLwz7lnDA50i20m/3Rn7J4FLtimyoKQsG4E2BItctwjhg==", "integrity": "sha512-dQbZnsMaIiTQPZmbGmktz+c74zt/hyrJEB4tdp2Jj0RNv9J6B/OWR5RyrZEvIn9fyh9Zlg2OlE2XzKz6wMKGAw==",
"requires": { "requires": {
"@polka/url": "^0.5.0", "@polka/url": "^0.5.0",
"mime": "^2.3.1" "mime": "^2.3.1"
@ -4355,6 +4348,15 @@
"use": "^3.1.0" "use": "^3.1.0"
}, },
"dependencies": { "dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"requires": {
"ms": "2.0.0"
}
},
"define-property": { "define-property": {
"version": "0.2.5", "version": "0.2.5",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
@ -4372,6 +4374,12 @@
"requires": { "requires": {
"is-extendable": "^0.1.0" "is-extendable": "^0.1.0"
} }
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
} }
} }
}, },
@ -4435,6 +4443,12 @@
"kind-of": "^3.2.0" "kind-of": "^3.2.0"
}, },
"dependencies": { "dependencies": {
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
},
"kind-of": { "kind-of": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@ -4655,9 +4669,9 @@
} }
}, },
"svelte": { "svelte": {
"version": "3.2.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.2.0.tgz", "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.3.0.tgz",
"integrity": "sha512-i/FSWUcqVw9JBo9bY69/ZI89WCCpyhdWjvAroOroI4qnQboh0WGlgjnFOEKOTvlv1XONd8cVpRGbOYYE3Ec6TQ==", "integrity": "sha512-iJYkIJDvAak1kizEYnE4b4eJ17D25fU0adW7GjDgO0klbjcAFlqtWEGFJa9kpJOlUtNLilcF09k4Y9TDmK/vjg==",
"dev": true "dev": true
}, },
"tar": { "tar": {
@ -4732,6 +4746,12 @@
"kind-of": "^3.0.2" "kind-of": "^3.0.2"
}, },
"dependencies": { "dependencies": {
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
},
"kind-of": { "kind-of": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@ -4772,29 +4792,23 @@
"dev": true "dev": true
}, },
"trouter": { "trouter": {
"version": "3.0.1", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/trouter/-/trouter-3.0.1.tgz", "resolved": "https://registry.npmjs.org/trouter/-/trouter-3.0.2.tgz",
"integrity": "sha512-9IBGrlL5bW65xhWufCCf4AsZyxGVIxv7Jy+PTwNtfPHJo+8hAp4wvt/+ersAHE//0Lgjy7obPROfgasNocoYuA==", "integrity": "sha512-wzUcM3oKmF8Fx5pd+3IxZj5LBugqW+hSQHm6cTHkpiZHL8w6YeZSzo3LPw0UdhlwaGPms3OxT7N4GEOIRTw+jw==",
"requires": { "requires": {
"regexparam": "^1.2.0" "regexparam": "^1.2.0"
} }
}, },
"uglify-js": { "uglify-js": {
"version": "3.4.10", "version": "3.5.14",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.14.tgz",
"integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", "integrity": "sha512-dgyjIw8KFK6AyVl5vm2tEqPewv5TKGEiiVFLI1LbF+oHua/Njd8tZk3lIbF1AWU1rNdEg7scaceADb4zqCcWXg==",
"dev": true, "dev": true,
"requires": { "requires": {
"commander": "~2.19.0", "commander": "~2.20.0",
"source-map": "~0.6.1" "source-map": "~0.6.1"
}, },
"dependencies": { "dependencies": {
"commander": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
"integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
"dev": true
},
"source-map": { "source-map": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",

@ -38,7 +38,7 @@
"@babel/runtime": "^7.4.4", "@babel/runtime": "^7.4.4",
"@sindresorhus/slugify": "^0.9.1", "@sindresorhus/slugify": "^0.9.1",
"@sveltejs/site-kit": "^1.0.4", "@sveltejs/site-kit": "^1.0.4",
"@sveltejs/svelte-repl": "0.0.10", "@sveltejs/svelte-repl": "0.0.11",
"degit": "^2.1.3", "degit": "^2.1.3",
"dotenv": "^8.0.0", "dotenv": "^8.0.0",
"eslint-plugin-svelte3": "^1.0.0", "eslint-plugin-svelte3": "^1.0.0",
@ -48,7 +48,7 @@
"node-fetch": "^2.3.0", "node-fetch": "^2.3.0",
"node-pg-migrate": "^3.18.1", "node-pg-migrate": "^3.18.1",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"rollup": "^1.11.2", "rollup": "^1.11.3",
"rollup-plugin-babel": "^4.3.2", "rollup-plugin-babel": "^4.3.2",
"rollup-plugin-commonjs": "^9.3.4", "rollup-plugin-commonjs": "^9.3.4",
"rollup-plugin-json": "^4.0.0", "rollup-plugin-json": "^4.0.0",
@ -56,7 +56,7 @@
"rollup-plugin-replace": "^2.2.0", "rollup-plugin-replace": "^2.2.0",
"rollup-plugin-svelte": "^5.0.3", "rollup-plugin-svelte": "^5.0.3",
"rollup-plugin-terser": "^4.0.4", "rollup-plugin-terser": "^4.0.4",
"sapper": "^0.26.0", "sapper": "^0.27.1",
"shelljs": "^0.8.3", "shelljs": "^0.8.3",
"svelte": "^3.0.0" "svelte": "^3.0.0"
}, },

@ -1,11 +0,0 @@
const fs = require('fs');
const files = [];
for (const path of process.argv.slice(2)) {
if (!path.includes('/.')) {
files.push({ path: path.slice(19), data: fs.readFileSync(path).toString() });
}
}
fs.writeFileSync('static/svelte-app.json', JSON.stringify(files));

@ -1,7 +1,7 @@
const sh = require('shelljs'); const sh = require('shelljs');
const fs = require('fs'); const fs = require('fs');
sh.cd(__dirname+'/../'); sh.cd(__dirname + '/../');
// fetch svelte app // fetch svelte app
sh.rm('-rf','scripts/svelte-app'); sh.rm('-rf','scripts/svelte-app');
@ -16,7 +16,10 @@ const appPath = 'scripts/svelte-app';
const files = []; const files = [];
for (const path of sh.find(appPath).filter(p => fs.lstatSync(p).isFile()) ) { for (const path of sh.find(appPath).filter(p => fs.lstatSync(p).isFile()) ) {
files.push({ path: path.slice(appPath.length + 1), data: fs.readFileSync(path).toString() }); const bytes = fs.readFileSync(path);
const string = bytes.toString();
const data = bytes.compare(Buffer.from(string)) === 0 ? string : [...bytes];
files.push({ path: path.slice(appPath.length + 1), data });
} }
fs.writeFileSync('static/svelte-app.json', JSON.stringify(files)); fs.writeFileSync('static/svelte-app.json', JSON.stringify(files));

@ -54,5 +54,7 @@
<a target="_blank" rel="noopener" href="https://nytimes.com"><img src="organisations/nyt.svg" alt="The New York Times logo"></a> <a target="_blank" rel="noopener" href="https://nytimes.com"><img src="organisations/nyt.svg" alt="The New York Times logo"></a>
<a target="_blank" rel="noopener" href="https://razorpay.com"><img src="organisations/razorpay.svg" alt="Razorpay logo"></a> <a target="_blank" rel="noopener" href="https://razorpay.com"><img src="organisations/razorpay.svg" alt="Razorpay logo"></a>
<a target="_blank" rel="noopener" href="https://www.stone.co"><img src="organisations/stone.svg" alt="Stone Payments logo"></a> <a target="_blank" rel="noopener" href="https://www.stone.co"><img src="organisations/stone.svg" alt="Stone Payments logo"></a>
<a target="_blank" rel="noopener" href="https://thunderdome.dev"><img src="organisations/thunderdome.svg" alt="Thunderdome logo"></a>
<a target="_blank" rel="noopener" href="https://m.tokopedia.com"><img src="organisations/tokopedia.png" alt="Tokopedia logo"></a>
<a target="_blank" rel="noopener" href="https://github.com/sveltejs/svelte/blob/master/site/src/routes/_components/WhosUsingSvelte.svelte" class="add-yourself"><span>+ your company?</span></a> <a target="_blank" rel="noopener" href="https://github.com/sveltejs/svelte/blob/master/site/src/routes/_components/WhosUsingSvelte.svelte" class="add-yourself"><span>+ your company?</span></a>
</div> </div>

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

@ -89,7 +89,7 @@ npx degit sveltejs/template my-svelte-project
cd my-svelte-project cd my-svelte-project
npm install npm install
npm run dev & open http://localhost:5000 npm run dev
</pre> </pre>
<p style="flex: 1">See the <a href="blog/the-easiest-way-to-get-started">quickstart guide</a> for more information.</p> <p style="flex: 1">See the <a href="blog/the-easiest-way-to-get-started">quickstart guide</a> for more information.</p>

@ -0,0 +1,154 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg1459"
version="1.1"
viewBox="0 0 274.77133 60.298889"
height="60.298889mm"
width="274.77133mm">
<defs
id="defs1453" />
<metadata
id="metadata1456">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(-42.531001,-116.41603)"
id="layer1">
<g
transform="translate(93.750421,-1.9345242)"
id="g997">
<g
id="g958"
transform="matrix(0.45367544,0,0,0.45367544,-70.17869,66.227085)">
<path
d="m 178.30147,211.4295 c 0,0 -41.87399,-81.14294 -120.817617,-67.37697 m -5.94379,67.68201 c 0,0 45.783,-83.2982 122.198207,-66.72283 m -58.28473,-25.96854 v 124.35097 m 45.89507,-84.33553 a 46.124953,39.331358 0 0 1 -46.12495,39.33136 46.124953,39.331358 0 0 1 -46.124947,-39.33136 46.124953,39.331358 0 0 1 46.124947,-39.33135 46.124953,39.331358 0 0 1 46.12495,39.33135 z m 26.30592,22.47508 a 72.482072,61.806418 0 0 1 -72.48207,61.80641 72.482072,61.806418 0 0 1 -72.482077,-61.80641 72.482072,61.806418 0 0 1 72.482077,-61.80643 72.482072,61.806418 0 0 1 72.48207,61.80643 z"
style="fill:none;stroke:#646464;stroke-width:1.80000019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4645-2-8" />
<circle
r="3.9503546"
cy="198.46136"
cx="115.33445"
id="path4563-1-1-5-2"
style="opacity:1;fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:1.80000019;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
r="3.9503546"
cy="179.61028"
cx="154.28223"
id="path4563-1-1-4-0-7"
style="opacity:1;fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:1.80000019;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
r="3.9503546"
cy="211.14809"
cx="178.06921"
id="path4563-1-1-40-7-8"
style="opacity:1;fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:1.80000019;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
r="3.9503546"
cy="242.95314"
cx="115.79539"
id="path4563-1-1-8-5-8"
style="opacity:1;fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:1.80000019;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
r="3.9503546"
cy="211.14809"
cx="52.719795"
id="path4563-1-1-85-6-5"
style="opacity:1;fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:1.80000019;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
r="3.9503546"
cy="142.72708"
cx="157.48947"
id="path4563-1-1-6-5-4"
style="opacity:1;fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:1.80000019;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
r="3.9503546"
cy="151.54697"
cx="115.2609"
id="path4563-1-1-7-4-9"
style="opacity:1;fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:1.80000019;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
r="3.9503546"
cy="119.7419"
cx="115.2609"
id="path4563-1-1-3-7-6"
style="opacity:1;fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:1.80000019;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
r="3.9503546"
cy="142.19254"
cx="73.834099"
id="path4563-1-1-2-7-6"
style="opacity:1;fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:1.80000019;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
r="3.9503546"
cy="178.80847"
cx="76.506798"
id="path4563-1-1-34-5-3"
style="opacity:1;fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:1.80000019;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
aria-label="THUNDERDOME"
transform="matrix(0.22880747,0,0,0.22880747,0.22823691,-38.584587)"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:3.25098467;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="flowRoot4650-39-9">
<path
d="m 99.216,745.60469 -7.296,25.92 h 18.624 v 113.28 h 28.416 v -113.28 h 18.624 l -6.912,-25.92 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:192px;font-family:'American Captain';-inkscape-font-specification:'American Captain';fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:3.25098467;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4889-2" />
<path
d="m 237.135,745.60469 h -28.416 v 59.52 h -15.168 v -59.52 h -28.416 v 139.2 h 28.416 v -55.68 h 15.168 v 55.68 h 28.416 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:192px;font-family:'American Captain';-inkscape-font-specification:'American Captain';fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:3.25098467;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4891-4" />
<path
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:192px;font-family:'American Captain';-inkscape-font-specification:'American Captain';fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:2.68477941;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m -814.90625,747.83984 v 0.0137 h -15.81836 v 97.19726 c 0,12.68484 4.7555,17.75977 17.91602,17.75977 h 23.62695 c 13.16052,0 17.91601,-5.07493 17.91602,-17.75977 v -97.19726 h -16.49805 v -0.0137 l -11.50586,40.55664 h 19.56055 l -29.33985,55.51563 7.76758,-41.70899 h -16.9707 l 14.60742,-54.36328 z"
transform="matrix(1.2108945,0,0,1.2108945,1254.6805,-159.96715)"
id="path4893-9" />
<path
d="m 332.385,884.80469 h 25.728 v -58.176 l 14.976,58.176 h 28.608 v -139.2 h -28.608 v 55.872 l -14.208,-55.872 h -26.496 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:192px;font-family:'American Captain';-inkscape-font-specification:'American Captain';fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:3.25098467;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4895-2" />
<path
d="m 454.281,769.98869 c 1.92,0 2.496,0.96 2.496,2.688 v 84.864 c 0,2.112 -0.384,2.88 -2.688,2.88 h -13.056 v -90.432 z m 30.144,-7.488 c 0,-10.176 -5.568,-16.896 -16.512,-16.896 h -54.528 v 139.2 h 49.344 c 15.936,0 21.696,-6.144 21.696,-21.504 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:192px;font-family:'American Captain';-inkscape-font-specification:'American Captain';fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:3.25098467;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4897-8" />
<path
d="m 495.885,884.80469 h 52.992 l 4.8,-25.92 h -29.184 v -30.336 h 23.04 v -24 h -23.04 v -33.024 h 30.336 l -4.8,-25.92 h -54.144 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:192px;font-family:'American Captain';-inkscape-font-specification:'American Captain';fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:3.25098467;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4899-5" />
<path
d="m 605.982,769.98869 c 1.92,0 2.688,1.152 2.688,2.88 v 42.24 c 0,2.112 -0.576,2.88 -2.688,2.88 H 592.35 v -48 z m 30.144,-6.336 c 0,-10.944 -5.76,-18.048 -18.816,-18.048 h -52.8 v 139.2 h 27.84 v -44.352 h 3.648 l 13.44,44.352 h 28.8 l -14.592,-44.352 c 8.064,0 12.48,-6.144 12.48,-12.288 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:192px;font-family:'American Captain';-inkscape-font-specification:'American Captain';fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:3.25098467;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4901-1" />
<path
d="m 689.031,769.98869 c 1.92,0 2.496,0.96 2.496,2.688 v 84.864 c 0,2.112 -0.384,2.88 -2.688,2.88 h -13.056 v -90.432 z m 30.144,-7.488 c 0,-10.176 -5.568,-16.896 -16.512,-16.896 h -54.528 v 139.2 h 49.344 c 15.936,0 21.696,-6.144 21.696,-21.504 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:192px;font-family:'American Captain';-inkscape-font-specification:'American Captain';fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:3.25098467;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4903-4" />
<path
d="m 772.107,769.98869 c 1.92,0 2.496,0.96 2.496,2.688 v 84.864 c 0,2.112 -0.384,2.88 -2.688,2.88 h -10.56 c -2.304,0 -2.688,-0.768 -2.688,-2.88 v -84.864 c 0,-1.728 0.576,-2.688 2.496,-2.688 z m 30.72,-6.336 c 0,-10.944 -5.76,-18.048 -18.816,-18.048 h -34.56 c -13.056,0 -18.816,7.104 -18.816,18.048 v 101.376 c 0,10.56 4.416,19.776 19.968,19.776 h 32.256 c 15.552,0 19.968,-9.216 19.968,-19.776 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:192px;font-family:'American Captain';-inkscape-font-specification:'American Captain';fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:3.25098467;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4905-7" />
<path
d="m 858.804,874.82069 17.664,-55.68 v 65.664 h 27.072 v -139.2 h -29.568 l -15.168,58.752 -15.168,-58.752 H 814.26 v 139.2 h 27.072 v -65.664 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:192px;font-family:'American Captain';-inkscape-font-specification:'American Captain';fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:3.25098467;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4907-8" />
<path
d="m 915.135,884.80469 h 52.992 l 4.8,-25.92 h -29.184 v -30.336 h 23.04 v -24 h -23.04 v -33.024 h 30.336 l -4.8,-25.92 h -54.144 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:192px;font-family:'American Captain';-inkscape-font-specification:'American Captain';fill:#ffdd57;fill-opacity:1;stroke:#646464;stroke-width:3.25098467;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4909-9" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

@ -1,5 +1,5 @@
import { cubicOut } from './easing'; import { cubicOut } from 'svelte/easing';
import { is_function } from './internal'; import { is_function } from 'svelte/internal';
export function flip(node, animation, params) { export function flip(node, animation, params) {
const style = getComputedStyle(node); const style = getComputedStyle(node);
@ -22,4 +22,4 @@ export function flip(node, animation, params) {
easing, easing,
css: (t, u) => `transform: ${transform} translate(${u * dx}px, ${u * dy}px);` css: (t, u) => `transform: ${transform} translate(${u * dx}px, ${u * dy}px);`
}; };
} }

@ -1,4 +1,5 @@
import MagicString, { Bundle } from 'magic-string'; import MagicString, { Bundle } from 'magic-string';
// @ts-ignore
import { walk, childKeys } from 'estree-walker'; import { walk, childKeys } from 'estree-walker';
import { getLocator } from 'locate-character'; import { getLocator } from 'locate-character';
import Stats from '../Stats'; import Stats from '../Stats';
@ -21,6 +22,7 @@ import { remove_indentation, add_indentation } from '../utils/indentation';
import get_object from './utils/get_object'; import get_object from './utils/get_object';
import unwrap_parens from './utils/unwrap_parens'; import unwrap_parens from './utils/unwrap_parens';
import Slot from './nodes/Slot'; import Slot from './nodes/Slot';
import { Node as ESTreeNode } from 'estree';
type ComponentOptions = { type ComponentOptions = {
namespace?: string; namespace?: string;
@ -152,10 +154,14 @@ export default class Component {
this.namespace = namespaces[this.component_options.namespace] || this.component_options.namespace; this.namespace = namespaces[this.component_options.namespace] || this.component_options.namespace;
if (compile_options.customElement) { if (compile_options.customElement) {
this.tag = this.component_options.tag || compile_options.tag; if (this.component_options.tag === undefined && compile_options.tag === undefined) {
if (!this.tag) { const svelteOptions = ast.html.children.find(child => child.name === 'svelte:options') || { start: 0, end: 0 };
throw new Error(`Cannot compile to a custom element without specifying a tag name via options.tag or <svelte:options>`); 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}/>`
});
} }
this.tag = this.component_options.tag || compile_options.tag;
} else { } else {
this.tag = this.name; this.tag = this.name;
} }
@ -754,7 +760,7 @@ export default class Component {
}); });
} }
if (is_reference(node, parent)) { if (is_reference(node as ESTreeNode, parent as ESTreeNode)) {
const object = get_object(node); const object = get_object(node);
const { name } = object; const { name } = object;
@ -772,7 +778,7 @@ export default class Component {
}); });
} }
invalidate(name, value) { invalidate(name, value?) {
const variable = this.var_lookup.get(name); const variable = this.var_lookup.get(name);
if (variable && (variable.subscribable && variable.reassigned)) { if (variable && (variable.subscribable && variable.reassigned)) {
@ -1018,7 +1024,7 @@ export default class Component {
scope = map.get(node); scope = map.get(node);
} }
if (is_reference(node, parent)) { if (is_reference(node as ESTreeNode, parent as ESTreeNode)) {
const { name } = flatten_reference(node); const { name } = flatten_reference(node);
const owner = scope.find_owner(name); const owner = scope.find_owner(name);
@ -1109,14 +1115,16 @@ export default class Component {
} else if (node.type === 'UpdateExpression') { } else if (node.type === 'UpdateExpression') {
const identifier = get_object(node.argument); const identifier = get_object(node.argument);
assignees.add(identifier.name); assignees.add(identifier.name);
} else if (is_reference(node, parent)) { } else if (is_reference(node as ESTreeNode, parent as ESTreeNode)) {
const identifier = get_object(node); const identifier = get_object(node);
if (!assignee_nodes.has(identifier)) { if (!assignee_nodes.has(identifier)) {
const { name } = identifier; const { name } = identifier;
const owner = scope.find_owner(name); const owner = scope.find_owner(name);
const component_var = component.var_lookup.get(name);
const is_writable_or_mutated = component_var && (component_var.writable || component_var.mutated);
if ( if (
(!owner || owner === component.instance_scope) && (!owner || owner === component.instance_scope) &&
(name[0] === '$' || component.var_lookup.has(name) && component.var_lookup.get(name).writable) (name[0] === '$' || is_writable_or_mutated)
) { ) {
dependencies.add(name); dependencies.add(name);
} }
@ -1265,9 +1273,9 @@ function process_component_options(component: Component, nodes) {
const message = `'tag' must be a string literal`; const message = `'tag' must be a string literal`;
const tag = get_value(attribute, code, message); const tag = get_value(attribute, code, message);
if (typeof tag !== 'string') component.error(attribute, { code, message }); if (typeof tag !== 'string' && tag !== null) component.error(attribute, { code, message });
if (!/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) { if (tag && !/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) {
component.error(attribute, { component.error(attribute, {
code: `invalid-tag-property`, 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`

@ -1,4 +1,4 @@
import { assign } from '../internal'; import { assign } from '../internal/index';
import Stats from '../Stats'; import Stats from '../Stats';
import parse from '../parse/index'; import parse from '../parse/index';
import render_dom from './render-dom/index'; import render_dom from './render-dom/index';
@ -55,7 +55,7 @@ function validate_options(options: CompileOptions, warnings: Warning[]) {
} }
} }
function get_name(filename) { function get_name(filename: string) {
if (!filename) return null; if (!filename) return null;
const parts = filename.split(/[\/\\]/); const parts = filename.split(/[\/\\]/);
@ -105,4 +105,4 @@ export default function compile(source: string, options: CompileOptions = {}) {
: render_dom(component, options); : render_dom(component, options);
return component.generate(js); return component.generate(js);
} }

@ -67,6 +67,7 @@ export default class Attribute extends Node {
this.should_cache = this.is_dynamic this.should_cache = this.is_dynamic
? this.chunks.length === 1 ? this.chunks.length === 1
// @ts-ignore todo: probably error
? this.chunks[0].node.type !== 'Identifier' || scope.names.has(this.chunks[0].node.name) ? this.chunks[0].node.type !== 'Identifier' || scope.names.has(this.chunks[0].node.name)
: true : true
: false; : false;
@ -91,8 +92,10 @@ export default class Attribute extends Node {
if (this.chunks.length === 0) return `""`; if (this.chunks.length === 0) return `""`;
if (this.chunks.length === 1) { if (this.chunks.length === 1) {
return this.chunks[0].type === 'Text' return this.chunks[0].type === 'Text'
? stringify(this.chunks[0].data) ? stringify((this.chunks[0] as Text).data)
// @ts-ignore todo: probably error
: this.chunks[0].render(block); : this.chunks[0].render(block);
} }
@ -102,6 +105,7 @@ export default class Attribute extends Node {
if (chunk.type === 'Text') { if (chunk.type === 'Text') {
return stringify(chunk.data); return stringify(chunk.data);
} else { } else {
// @ts-ignore todo: probably error
return chunk.get_precedence() <= 13 ? `(${chunk.render()})` : chunk.render(); return chunk.get_precedence() <= 13 ? `(${chunk.render()})` : chunk.render();
} }
}) })
@ -114,7 +118,8 @@ export default class Attribute extends Node {
return this.is_true return this.is_true
? true ? true
: this.chunks[0] : this.chunks[0]
? this.chunks[0].data // method should be called only when `is_static = true`
? (this.chunks[0] as Text).data
: ''; : '';
} }
} }

@ -5,6 +5,7 @@ import CatchBlock from './CatchBlock';
import Expression from './shared/Expression'; import Expression from './shared/Expression';
export default class AwaitBlock extends Node { export default class AwaitBlock extends Node {
type: 'AwaitBlock';
expression: Expression; expression: Expression;
value: string; value: string;
error: string; error: string;

@ -5,6 +5,7 @@ import Component from '../Component';
import TemplateScope from './shared/TemplateScope'; import TemplateScope from './shared/TemplateScope';
export default class Binding extends Node { export default class Binding extends Node {
type: 'Binding';
name: string; name: string;
expression: Expression; expression: Expression;
is_contextual: boolean; is_contextual: boolean;

@ -3,6 +3,7 @@ import TemplateScope from './shared/TemplateScope';
import AbstractBlock from './shared/AbstractBlock'; import AbstractBlock from './shared/AbstractBlock';
export default class CatchBlock extends AbstractBlock { export default class CatchBlock extends AbstractBlock {
type: 'CatchBlock';
scope: TemplateScope; scope: TemplateScope;
constructor(component, parent, scope, info) { constructor(component, parent, scope, info) {

@ -2,6 +2,7 @@ import Node from './shared/Node';
import Expression from './shared/Expression'; import Expression from './shared/Expression';
export default class DebugTag extends Node { export default class DebugTag extends Node {
type: 'DebugTag';
expressions: Expression[]; expressions: Expression[];
constructor(component, parent, scope, info) { constructor(component, parent, scope, info) {
@ -11,4 +12,4 @@ export default class DebugTag extends Node {
return new Expression(component, parent, scope, node); return new Expression(component, parent, scope, node);
}); });
} }
} }

@ -6,8 +6,15 @@ import TemplateScope from './shared/TemplateScope';
import AbstractBlock from './shared/AbstractBlock'; import AbstractBlock from './shared/AbstractBlock';
import { Node as INode } from '../../interfaces'; import { Node as INode } from '../../interfaces';
import { new_tail } from '../utils/tail'; import { new_tail } from '../utils/tail';
import Element from './Element';
function unpack_destructuring(contexts: Array<{ name: string, tail: string }>, node: INode, tail: string) { type Context = {
key: INode,
name?: string,
tail: string
};
function unpack_destructuring(contexts: Array<Context>, node: INode, tail: string) {
if (!node) return; if (!node) return;
if (node.type === 'Identifier' || node.type === 'RestIdentifier') { if (node.type === 'Identifier' || node.type === 'RestIdentifier') {
@ -53,7 +60,7 @@ export default class EachBlock extends AbstractBlock {
context: string; context: string;
key: Expression; key: Expression;
scope: TemplateScope; scope: TemplateScope;
contexts: Array<{ name: string, tail: string }>; contexts: Array<Context>;
has_animation: boolean; has_animation: boolean;
has_binding = false; has_binding = false;
@ -82,7 +89,7 @@ export default class EachBlock extends AbstractBlock {
if (this.index) { if (this.index) {
// index can only change if this is a keyed each block // index can only change if this is a keyed each block
const dependencies = this.key ? this.expression.dependencies : []; const dependencies = this.key ? this.expression.dependencies : new Set([]);
this.scope.add(this.index, dependencies, this); this.scope.add(this.index, dependencies, this);
} }
@ -92,8 +99,8 @@ export default class EachBlock extends AbstractBlock {
if (this.has_animation) { if (this.has_animation) {
if (this.children.length !== 1) { if (this.children.length !== 1) {
const child = this.children.find(child => !!child.animation); const child = this.children.find(child => !!(child as Element).animation);
component.error(child.animation, { component.error((child as Element).animation, {
code: `invalid-animation`, code: `invalid-animation`,
message: `An element that use the animate directive must be the sole child of a keyed each block` message: `An element that use the animate directive must be the sole child of a keyed each block`
}); });

@ -15,6 +15,7 @@ import fuzzymatch from '../../utils/fuzzymatch';
import list from '../../utils/list'; import list from '../../utils/list';
import Let from './Let'; import Let from './Let';
import TemplateScope from './shared/TemplateScope'; import TemplateScope from './shared/TemplateScope';
import { INode } from './interfaces';
const svg = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|svg|switch|symbol|text|textPath|tref|tspan|unknown|use|view|vkern)$/; const svg = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|svg|switch|symbol|text|textPath|tref|tspan|unknown|use|view|vkern)$/;
@ -101,7 +102,7 @@ export default class Element extends Node {
intro?: Transition = null; intro?: Transition = null;
outro?: Transition = null; outro?: Transition = null;
animation?: Animation = null; animation?: Animation = null;
children: Node[]; children: INode[];
namespace: string; namespace: string;
constructor(component, parent, scope, info: any) { constructor(component, parent, scope, info: any) {
@ -136,7 +137,7 @@ export default class Element extends Node {
// Special case — treat these the same way: // Special case — treat these the same way:
// <option>{foo}</option> // <option>{foo}</option>
// <option value={foo}>{foo}</option> // <option value={foo}>{foo}</option>
const value_attribute = info.attributes.find((attribute: Node) => attribute.name === 'value'); const value_attribute = info.attributes.find(attribute => attribute.name === 'value');
if (!value_attribute) { if (!value_attribute) {
info.attributes.push({ info.attributes.push({
@ -228,7 +229,7 @@ export default class Element extends Node {
let is_figure_parent = false; let is_figure_parent = false;
while (parent) { while (parent) {
if (parent.name === 'figure') { if ((parent as Element).name === 'figure') {
is_figure_parent = true; is_figure_parent = true;
break; break;
} }
@ -253,7 +254,7 @@ export default class Element extends Node {
return true; return true;
}); });
const index = children.findIndex(child => child.name === 'figcaption'); const index = children.findIndex(child => (child as Element).name === 'figcaption');
if (index !== -1 && (index !== 0 && index !== children.length - 1)) { if (index !== -1 && (index !== 0 && index !== children.length - 1)) {
this.component.warn(children[index], { this.component.warn(children[index], {
@ -320,7 +321,9 @@ export default class Element extends Node {
} }
const value = attribute.get_static_value(); const value = attribute.get_static_value();
// @ts-ignore
if (value && !aria_role_set.has(value)) { if (value && !aria_role_set.has(value)) {
// @ts-ignore
const match = fuzzymatch(value, aria_roles); const match = fuzzymatch(value, aria_roles);
let message = `A11y: Unknown role '${value}'`; let message = `A11y: Unknown role '${value}'`;
if (match) message += ` (did you mean '${match}'?)`; if (match) message += ` (did you mean '${match}'?)`;
@ -359,6 +362,7 @@ export default class Element extends Node {
// tabindex-no-positive // tabindex-no-positive
if (name === 'tabindex') { if (name === 'tabindex') {
const value = attribute.get_static_value(); const value = attribute.get_static_value();
// @ts-ignore todo is tabindex=true correct case?
if (!isNaN(value) && +value > 0) { if (!isNaN(value) && +value > 0) {
component.warn(attribute, { component.warn(attribute, {
code: `a11y-positive-tabindex`, code: `a11y-positive-tabindex`,
@ -544,7 +548,7 @@ export default class Element extends Node {
message: `'group' binding can only be used with <input type="checkbox"> or <input type="radio">` message: `'group' binding can only be used with <input type="checkbox"> or <input type="radio">`
}); });
} }
} else if (name == 'files') { } else if (name === 'files') {
if (this.name !== 'input') { if (this.name !== 'input') {
component.error(binding, { component.error(binding, {
code: `invalid-binding`, code: `invalid-binding`,
@ -560,6 +564,14 @@ export default class Element extends Node {
message: `'files' binding can only be used with <input type="file">` message: `'files' binding can only be used with <input type="file">`
}); });
} }
} else if (name === 'open') {
if (this.name !== 'details') {
component.error(binding, {
code: `invalid-binding`,
message: `'${name}' binding can only be used with <details>`
});
}
} else if ( } else if (
name === 'currentTime' || name === 'currentTime' ||
name === 'duration' || name === 'duration' ||

@ -1,10 +1,11 @@
import map_children from './shared/map_children'; import map_children from './shared/map_children';
import AbstractBlock from './shared/AbstractBlock'; import AbstractBlock from './shared/AbstractBlock';
import Component from '../Component';
export default class ElseBlock extends AbstractBlock { export default class ElseBlock extends AbstractBlock {
type: 'ElseBlock'; type: 'ElseBlock';
constructor(component, parent, scope, info) { constructor(component: Component, parent, scope, info) {
super(component, parent, scope, info); super(component, parent, scope, info);
this.children = map_children(component, this, scope, info.children); this.children = map_children(component, this, scope, info.children);

@ -5,6 +5,7 @@ import deindent from '../utils/deindent';
import Block from '../render-dom/Block'; import Block from '../render-dom/Block';
export default class EventHandler extends Node { export default class EventHandler extends Node {
type: 'EventHandler';
name: string; name: string;
modifiers: Set<string>; modifiers: Set<string>;
expression: Expression; expression: Expression;
@ -65,4 +66,4 @@ export default class EventHandler extends Node {
// this.component.add_reference(this.handler_name); // this.component.add_reference(this.handler_name);
return `ctx.${this.handler_name}`; return `ctx.${this.handler_name}`;
} }
} }

@ -3,10 +3,12 @@ import Component from '../Component';
import map_children from './shared/map_children'; import map_children from './shared/map_children';
import Block from '../render-dom/Block'; import Block from '../render-dom/Block';
import TemplateScope from './shared/TemplateScope'; import TemplateScope from './shared/TemplateScope';
import { INode } from './interfaces';
export default class Fragment extends Node { export default class Fragment extends Node {
type: 'Fragment';
block: Block; block: Block;
children: Node[]; children: INode[];
scope: TemplateScope; scope: TemplateScope;
constructor(component: Component, info: any) { constructor(component: Component, info: any) {
@ -16,4 +18,4 @@ export default class Fragment extends Node {
this.scope = scope; this.scope = scope;
this.children = map_children(component, this, scope, info.children); this.children = map_children(component, this, scope, info.children);
} }
} }

@ -1,5 +1,4 @@
import Node from './shared/Node'; import Node from './shared/Node';
import Block from '../render-dom/Block';
import map_children from './shared/map_children'; import map_children from './shared/map_children';
export default class Head extends Node { export default class Head extends Node {

@ -7,6 +7,7 @@ import Expression from './shared/Expression';
import Component from '../Component'; import Component from '../Component';
import Let from './Let'; import Let from './Let';
import TemplateScope from './shared/TemplateScope'; import TemplateScope from './shared/TemplateScope';
import { INode } from './interfaces';
export default class InlineComponent extends Node { export default class InlineComponent extends Node {
type: 'InlineComponent'; type: 'InlineComponent';
@ -16,7 +17,7 @@ export default class InlineComponent extends Node {
bindings: Binding[] = []; bindings: Binding[] = [];
handlers: EventHandler[] = []; handlers: EventHandler[] = [];
lets: Let[] = []; lets: Let[] = [];
children: Node[]; children: INode[];
scope: TemplateScope; scope: TemplateScope;
constructor(component: Component, parent, scope, info) { constructor(component: Component, parent, scope, info) {

@ -1,3 +1,5 @@
import Tag from './shared/Tag'; import Tag from './shared/Tag';
export default class MustacheTag extends Tag {} export default class MustacheTag extends Tag {
type: 'MustacheTag';
}

@ -2,7 +2,7 @@ import map_children from './shared/map_children';
import AbstractBlock from './shared/AbstractBlock'; import AbstractBlock from './shared/AbstractBlock';
export default class PendingBlock extends AbstractBlock { export default class PendingBlock extends AbstractBlock {
type: 'PendingBlock';
constructor(component, parent, scope, info) { constructor(component, parent, scope, info) {
super(component, parent, scope, info); super(component, parent, scope, info);
this.children = map_children(component, parent, scope, info.children); this.children = map_children(component, parent, scope, info.children);

@ -1,3 +1,5 @@
import Tag from './shared/Tag'; import Tag from './shared/Tag';
export default class RawMustacheTag extends Tag {} export default class RawMustacheTag extends Tag {
type: 'RawMustacheTag'
}

@ -1,17 +1,17 @@
import Node from './shared/Node';
import Element from './Element'; import Element from './Element';
import Attribute from './Attribute'; import Attribute from './Attribute';
import Component from '../Component'; import Component from '../Component';
import TemplateScope from './shared/TemplateScope'; import TemplateScope from './shared/TemplateScope';
import { INode } from './interfaces';
export default class Slot extends Element { export default class Slot extends Element {
type: 'Element'; type: 'Element';
name: string; name: string;
children: Node[]; children: INode[];
slot_name: string; slot_name: string;
values: Map<string, Attribute> = new Map(); values: Map<string, Attribute> = new Map();
constructor(component: Component, parent: Node, scope: TemplateScope, info: any) { constructor(component: Component, parent: INode, scope: TemplateScope, info: any) {
super(component, parent, scope, info); super(component, parent, scope, info);
info.attributes.forEach(attr => { info.attributes.forEach(attr => {
@ -68,4 +68,4 @@ export default class Slot extends Element {
component.slots.set(this.slot_name, this); component.slots.set(this.slot_name, this);
} }
} }

@ -1,13 +1,14 @@
import Node from './shared/Node'; import Node from './shared/Node';
import Component from '../Component'; import Component from '../Component';
import TemplateScope from './shared/TemplateScope'; import TemplateScope from './shared/TemplateScope';
import { INode } from './interfaces';
export default class Text extends Node { export default class Text extends Node {
type: 'Text'; type: 'Text';
data: string; data: string;
use_space = false; use_space = false;
constructor(component: Component, parent: Node, scope: TemplateScope, info: any) { constructor(component: Component, parent: INode, scope: TemplateScope, info: any) {
super(component, parent, scope, info); super(component, parent, scope, info);
this.data = info.data; this.data = info.data;
@ -23,4 +24,4 @@ export default class Text extends Node {
this.use_space = true; this.use_space = true;
} }
} }
} }

@ -3,6 +3,7 @@ import TemplateScope from './shared/TemplateScope';
import AbstractBlock from './shared/AbstractBlock'; import AbstractBlock from './shared/AbstractBlock';
export default class ThenBlock extends AbstractBlock { export default class ThenBlock extends AbstractBlock {
type: 'ThenBlock';
scope: TemplateScope; scope: TemplateScope;
constructor(component, parent, scope, info) { constructor(component, parent, scope, info) {

@ -1,12 +1,13 @@
import Node from './shared/Node'; import Node from './shared/Node';
import map_children from './shared/map_children'; import map_children, { Children } from './shared/map_children';
import Component from '../Component';
export default class Title extends Node { export default class Title extends Node {
type: 'Title'; type: 'Title';
children: any[]; // TODO children: Children;
should_cache: boolean; should_cache: boolean;
constructor(component, parent, scope, info) { constructor(component: Component, parent, scope, info) {
super(component, parent, scope, info); super(component, parent, scope, info);
this.children = map_children(component, parent, scope, info.children); this.children = map_children(component, parent, scope, info.children);
@ -33,4 +34,4 @@ export default class Title extends Node {
) )
: true; : true;
} }
} }

@ -0,0 +1,64 @@
import Tag from './shared/Tag';
import Action from './Action';
import Animation from './Animation';
import Attribute from './Attribute';
import AwaitBlock from './AwaitBlock';
import Binding from './Binding';
import Body from './Body';
import CatchBlock from './CatchBlock';
import Class from './Class';
import Comment from './Comment';
import DebugTag from './DebugTag';
import EachBlock from './EachBlock';
import Element from './Element';
import ElseBlock from './ElseBlock';
import EventHandler from './EventHandler';
import Fragment from './Fragment';
import Head from './Head';
import IfBlock from './IfBlock';
import InlineComponent from './InlineComponent';
import Let from './Let';
import MustacheTag from './MustacheTag';
import Options from './Options';
import PendingBlock from './PendingBlock';
import RawMustacheTag from './RawMustacheTag';
import Slot from './Slot';
import Text from './Text';
import ThenBlock from './ThenBlock';
import Title from './Title';
import Transition from './Transition';
import Window from './Window';
// note: to write less types each of types in union below should have type defined as literal
// https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions
export type INode = Action
| Animation
| Attribute
| AwaitBlock
| Binding
| Body
| CatchBlock
| Class
| Comment
| DebugTag
| EachBlock
| Element
| ElseBlock
| EventHandler
| Fragment
| Head
| IfBlock
| InlineComponent
| Let
| MustacheTag
| Options
| PendingBlock
| RawMustacheTag
| Slot
| Tag
| Text
| ThenBlock
| Title
| Transition
| Window;

@ -1,10 +1,11 @@
import Block from '../../render-dom/Block'; import Block from '../../render-dom/Block';
import Component from './../../Component'; import Component from './../../Component';
import Node from './Node'; import Node from './Node';
import { INode } from '../interfaces';
export default class AbstractBlock extends Node { export default class AbstractBlock extends Node {
block: Block; block: Block;
children: Node[]; children: INode[];
constructor(component: Component, parent, scope, info: any) { constructor(component: Component, parent, scope, info: any) {
super(component, parent, scope, info); super(component, parent, scope, info);

@ -12,6 +12,7 @@ import TemplateScope from './TemplateScope';
import get_object from '../../utils/get_object'; import get_object from '../../utils/get_object';
import { nodes_match } from '../../../utils/nodes_match'; import { nodes_match } from '../../../utils/nodes_match';
import Block from '../../render-dom/Block'; import Block from '../../render-dom/Block';
import { INode } from '../interfaces';
const binary_operators: Record<string, number> = { const binary_operators: Record<string, number> = {
'**': 15, '**': 15,
@ -61,10 +62,12 @@ const precedence: Record<string, (node?: Node) => number> = {
SequenceExpression: () => 0 SequenceExpression: () => 0
}; };
type Owner = Wrapper | INode;
export default class Expression { export default class Expression {
type = 'Expression'; type: 'Expression' = 'Expression';
component: Component; component: Component;
owner: Wrapper; owner: Owner;
node: any; node: any;
snippet: string; snippet: string;
references: Set<string>; references: Set<string>;
@ -81,7 +84,8 @@ export default class Expression {
rendered: string; rendered: string;
constructor(component: Component, owner: Wrapper, template_scope: TemplateScope, info) { // todo: owner type
constructor(component: Component, owner: Owner, template_scope: TemplateScope, info) {
// TODO revert to direct property access in prod? // TODO revert to direct property access in prod?
Object.defineProperties(this, { Object.defineProperties(this, {
component: { component: {
@ -92,6 +96,7 @@ export default class Expression {
this.node = info; this.node = info;
this.template_scope = template_scope; this.template_scope = template_scope;
this.owner = owner; this.owner = owner;
// @ts-ignore
this.is_synthetic = owner.is_synthetic; this.is_synthetic = owner.is_synthetic;
const { dependencies, contextual_dependencies } = this; const { dependencies, contextual_dependencies } = this;
@ -218,7 +223,7 @@ export default class Expression {
} }
// TODO move this into a render-dom wrapper? // TODO move this into a render-dom wrapper?
render(block: Block) { render(block?: Block) {
if (this.rendered) return this.rendered; if (this.rendered) return this.rendered;
const { const {
@ -510,4 +515,4 @@ function is_contextual(component: Component, scope: TemplateScope, name: string)
// assume contextual // assume contextual
return true; return true;
} }

@ -1,15 +1,17 @@
import Attribute from './../Attribute'; import Attribute from './../Attribute';
import Component from './../../Component'; import Component from './../../Component';
import { INode } from '../interfaces';
import Text from '../Text';
export default class Node { export default class Node {
readonly start: number; readonly start: number;
readonly end: number; readonly end: number;
readonly component: Component; readonly component: Component;
readonly parent: Node; readonly parent: INode;
readonly type: string; readonly type: string;
prev?: Node; prev?: INode;
next?: Node; next?: INode;
can_use_innerhtml: boolean; can_use_innerhtml: boolean;
var: string; var: string;
@ -55,7 +57,7 @@ export default class Node {
if (attribute.chunks.length === 0) return ''; if (attribute.chunks.length === 0) return '';
if (attribute.chunks.length === 1 && attribute.chunks[0].type === 'Text') { if (attribute.chunks.length === 1 && attribute.chunks[0].type === 'Text') {
return attribute.chunks[0].data; return (attribute.chunks[0] as Text).data;
} }
return null; return null;

@ -2,6 +2,7 @@ import Node from './Node';
import Expression from './Expression'; import Expression from './Expression';
export default class Tag extends Node { export default class Tag extends Node {
type: 'MustacheTag' | 'RawMustacheTag';
expression: Expression; expression: Expression;
should_cache: boolean; should_cache: boolean;
@ -14,4 +15,4 @@ export default class Tag extends Node {
(this.expression.dependencies.size && scope.names.has(info.expression.name)) (this.expression.dependencies.size && scope.names.has(info.expression.name))
); );
} }
} }

@ -2,6 +2,7 @@ import EachBlock from '../EachBlock';
import ThenBlock from '../ThenBlock'; import ThenBlock from '../ThenBlock';
import CatchBlock from '../CatchBlock'; import CatchBlock from '../CatchBlock';
import InlineComponent from '../InlineComponent'; import InlineComponent from '../InlineComponent';
import Element from '../Element';
type NodeWithScope = EachBlock | ThenBlock | CatchBlock | InlineComponent | Element; type NodeWithScope = EachBlock | ThenBlock | CatchBlock | InlineComponent | Element;
@ -41,4 +42,4 @@ export default class TemplateScope {
const owner = this.get_owner(name); const owner = this.get_owner(name);
return owner && (owner.type === 'Element' || owner.type === 'InlineComponent'); return owner && (owner.type === 'Element' || owner.type === 'InlineComponent');
} }
} }

@ -14,9 +14,11 @@ import Slot from '../Slot';
import Text from '../Text'; import Text from '../Text';
import Title from '../Title'; import Title from '../Title';
import Window from '../Window'; import Window from '../Window';
import Node from './Node'; import { Node } from '../../../interfaces';
function get_constructor(type): typeof Node { export type Children = ReturnType<typeof map_children>;
function get_constructor(type) {
switch (type) { switch (type) {
case 'AwaitBlock': return AwaitBlock; case 'AwaitBlock': return AwaitBlock;
case 'Body': return Body; case 'Body': return Body;
@ -38,7 +40,7 @@ function get_constructor(type): typeof Node {
} }
} }
export default function map_children(component, parent, scope, children: any[]) { export default function map_children(component, parent, scope, children: Node[]) {
let last = null; let last = null;
return children.map(child => { return children.map(child => {
const constructor = get_constructor(child.type); const constructor = get_constructor(child.type);

@ -9,7 +9,7 @@ export interface BlockOptions {
renderer?: Renderer; renderer?: Renderer;
comment?: string; comment?: string;
key?: string; key?: string;
bindings?: Map<string, () => { object: string, property: string, snippet: string }>; bindings?: Map<string, { object: string, property: string, snippet: string }>;
dependencies?: Set<string>; dependencies?: Set<string>;
} }

@ -3,7 +3,6 @@ import { CompileOptions } from '../../interfaces';
import Component from '../Component'; import Component from '../Component';
import FragmentWrapper from './wrappers/Fragment'; import FragmentWrapper from './wrappers/Fragment';
import CodeBuilder from '../utils/CodeBuilder'; import CodeBuilder from '../utils/CodeBuilder';
import SlotWrapper from './wrappers/Slot';
export default class Renderer { export default class Renderer {
component: Component; // TODO Maybe Renderer shouldn't know about Component? component: Component; // TODO Maybe Renderer shouldn't know about Component?
@ -18,6 +17,7 @@ export default class Renderer {
fragment: FragmentWrapper; fragment: FragmentWrapper;
file_var: string; file_var: string;
locate: (c: number) => { line: number; column: number; };
constructor(component: Component, options: CompileOptions) { constructor(component: Component, options: CompileOptions) {
this.component = component; this.component = component;
@ -58,4 +58,4 @@ export default class Renderer {
this.fragment.render(this.block, null, 'nodes'); this.fragment.render(this.block, null, 'nodes');
} }
} }

@ -134,7 +134,6 @@ export default function dom(
}); });
if (component.compile_options.dev) { if (component.compile_options.dev) {
// TODO check no uunexpected props were passed, as well as
// checking that expected ones were passed // checking that expected ones were passed
const expected = props.filter(prop => !prop.initialised); const expected = props.filter(prop => !prop.initialised);
@ -364,7 +363,7 @@ export default function dom(
} }
const variable = component.var_lookup.get(n); const variable = component.var_lookup.get(n);
return variable && variable.writable; return variable && (variable.writable || variable.mutated);
}) })
.map(n => `$$dirty.${n}`).join(' || '); .map(n => `$$dirty.${n}`).join(' || ');
@ -395,6 +394,16 @@ export default function dom(
return $name; return $name;
}); });
let unknown_props_check;
if (component.compile_options.dev && writable_props.length) {
unknown_props_check = deindent`
const writable_props = [${writable_props.map(prop => `'${prop.export_name}'`).join(', ')}];
Object.keys($$props).forEach(key => {
if (!writable_props.includes(key)) console.warn(\`<${component.tag}> was created with unknown prop '\${key}'\`);
});
`;
}
builder.add_block(deindent` builder.add_block(deindent`
function ${definition}(${args.join(', ')}) { function ${definition}(${args.join(', ')}) {
${reactive_store_declarations.length > 0 && `let ${reactive_store_declarations.join(', ')};`} ${reactive_store_declarations.length > 0 && `let ${reactive_store_declarations.join(', ')};`}
@ -405,6 +414,8 @@ export default function dom(
${component.javascript} ${component.javascript}
${unknown_props_check}
${component.slots.size && `let { $$slots = {}, $$scope } = $$props;`} ${component.slots.size && `let { $$slots = {}, $$scope } = $$props;`}
${renderer.binding_groups.length > 0 && `const $$binding_groups = [${renderer.binding_groups.map(_ => `[]`).join(', ')}];`} ${renderer.binding_groups.length > 0 && `const $$binding_groups = [${renderer.binding_groups.map(_ => `[]`).join(', ')}];`}
@ -462,9 +473,13 @@ export default function dom(
${body.length > 0 && body.join('\n\n')} ${body.length > 0 && body.join('\n\n')}
} }
customElements.define("${component.tag}", ${name});
`); `);
if (component.tag != null) {
builder.add_block(deindent`
customElements.define("${component.tag}", ${name});
`);
}
} else { } else {
const superclass = options.dev ? 'SvelteComponentDev' : 'SvelteComponent'; const superclass = options.dev ? 'SvelteComponentDev' : 'SvelteComponent';

@ -25,7 +25,7 @@ export default class DebugTagWrapper extends Wrapper {
if (!renderer.options.dev) return; if (!renderer.options.dev) return;
const { code } = component; const { code, var_lookup } = component;
if (this.node.expressions.length === 0) { if (this.node.expressions.length === 0) {
// Debug all // Debug all
@ -50,23 +50,30 @@ export default class DebugTagWrapper extends Wrapper {
const condition = Array.from(dependencies).map(d => `changed.${d}`).join(' || '); const condition = Array.from(dependencies).map(d => `changed.${d}`).join(' || ');
const identifiers = this.node.expressions.map(e => e.node.name).join(', '); const ctx_identifiers = this.node.expressions
.filter(e => {
const looked_up_var = var_lookup.get(e.node.name);
return !(looked_up_var && looked_up_var.hoistable);
})
.map(e => e.node.name)
.join(', ');
const logged_identifiers = this.node.expressions.map(e => e.node.name).join(', ');
block.builders.update.add_block(deindent` block.builders.update.add_block(deindent`
if (${condition}) { if (${condition}) {
const { ${identifiers} } = ctx; const { ${ctx_identifiers} } = ctx;
console.${log}({ ${identifiers} }); console.${log}({ ${logged_identifiers} });
debugger; debugger;
} }
`); `);
block.builders.create.add_block(deindent` block.builders.create.add_block(deindent`
{ {
const { ${identifiers} } = ctx; const { ${ctx_identifiers} } = ctx;
console.${log}({ ${identifiers} }); console.${log}({ ${logged_identifiers} });
debugger; debugger;
} }
`); `);
} }
} }
} }

@ -8,7 +8,7 @@ import deindent from '../../utils/deindent';
import ElseBlock from '../../nodes/ElseBlock'; import ElseBlock from '../../nodes/ElseBlock';
import { attach_head } from '../../utils/tail'; import { attach_head } from '../../utils/tail';
class ElseBlockWrapper extends Wrapper { export class ElseBlockWrapper extends Wrapper {
node: ElseBlock; node: ElseBlock;
block: Block; block: Block;
fragment: FragmentWrapper; fragment: FragmentWrapper;
@ -83,6 +83,7 @@ export default class EachBlockWrapper extends Wrapper {
this.block = block.child({ this.block = block.child({
comment: create_debugging_comment(this.node, this.renderer.component), comment: create_debugging_comment(this.node, this.renderer.component),
name: renderer.component.get_unique_name('create_each_block'), name: renderer.component.get_unique_name('create_each_block'),
// @ts-ignore todo: probably error
key: node.key as string, key: node.key as string,
bindings: new Map(block.bindings) bindings: new Map(block.bindings)
@ -310,7 +311,9 @@ export default class EachBlockWrapper extends Wrapper {
} }
block.builders.init.add_block(deindent` block.builders.init.add_block(deindent`
const ${get_key} = ctx => ${this.node.key.render()}; const ${get_key} = ctx => ${
// @ts-ignore todo: probably error
this.node.key.render()};
for (var #i = 0; #i < ${this.vars.each_block_value}.${length}; #i += 1) { for (var #i = 0; #i < ${this.vars.each_block_value}.${length}; #i += 1) {
let child_ctx = ${this.vars.get_each_context}(ctx, ${this.vars.each_block_value}, #i); let child_ctx = ${this.vars.get_each_context}(ctx, ${this.vars.each_block_value}, #i);

@ -4,6 +4,7 @@ import fix_attribute_casing from './fix_attribute_casing';
import ElementWrapper from './index'; import ElementWrapper from './index';
import { stringify } from '../../../utils/stringify'; import { stringify } from '../../../utils/stringify';
import deindent from '../../../utils/deindent'; import deindent from '../../../utils/deindent';
import Expression from '../../../nodes/shared/Expression';
export default class AttributeWrapper { export default class AttributeWrapper {
node: Attribute; node: Attribute;
@ -21,7 +22,9 @@ export default class AttributeWrapper {
// special case — <option value={foo}> — see below // special case — <option value={foo}> — see below
if (this.parent.node.name === 'option' && node.name === 'value') { if (this.parent.node.name === 'option' && node.name === 'value') {
let select: ElementWrapper = this.parent; let select: ElementWrapper = this.parent;
while (select && (select.node.type !== 'Element' || select.node.name !== 'select')) select = select.parent; while (select && (select.node.type !== 'Element' || select.node.name !== 'select'))
// @ts-ignore todo: doublecheck this, but looks to be correct
select = select.parent;
if (select && select.select_binding_dependencies) { if (select && select.select_binding_dependencies) {
select.select_binding_dependencies.forEach(prop => { select.select_binding_dependencies.forEach(prop => {
@ -47,7 +50,7 @@ export default class AttributeWrapper {
(element.node.name === 'option' || // TODO check it's actually bound (element.node.name === 'option' || // TODO check it's actually bound
(element.node.name === 'input' && (element.node.name === 'input' &&
element.node.bindings.find( element.node.bindings.find(
(binding: Binding) => (binding) =>
/checked|group/.test(binding.name) /checked|group/.test(binding.name)
))); )));
@ -78,13 +81,13 @@ export default class AttributeWrapper {
// DRY it out if that's possible without introducing crazy indirection // DRY it out if that's possible without introducing crazy indirection
if (this.node.chunks.length === 1) { if (this.node.chunks.length === 1) {
// single {tag} — may be a non-string // single {tag} — may be a non-string
value = this.node.chunks[0].render(block); value = (this.node.chunks[0] as Expression).render(block);
} else { } else {
// '{foo} {bar}' — treat as string concatenation // '{foo} {bar}' — treat as string concatenation
value = value =
(this.node.chunks[0].type === 'Text' ? '' : `"" + `) + (this.node.chunks[0].type === 'Text' ? '' : `"" + `) +
this.node.chunks this.node.chunks
.map((chunk: Node) => { .map((chunk) => {
if (chunk.type === 'Text') { if (chunk.type === 'Text') {
return stringify(chunk.data); return stringify(chunk.data);
} else { } else {
@ -187,7 +190,7 @@ export default class AttributeWrapper {
: property_name : property_name
? `${element.var}.${property_name} = ${value};` ? `${element.var}.${property_name} = ${value};`
: is_dataset : is_dataset
? `${element.var}.dataset.${camel_case_name} = ${value};` ? `${element.var}.dataset.${camel_case_name} = ${value === true ? '""' : value};`
: `${method}(${element.var}, "${name}", ${value === true ? '""' : value});` : `${method}(${element.var}, "${name}", ${value === true ? '""' : value});`
); );

@ -1,14 +1,15 @@
import Attribute from '../../../nodes/Attribute'; import Attribute from '../../../nodes/Attribute';
import Block from '../../Block'; import Block from '../../Block';
import AttributeWrapper from './Attribute'; import AttributeWrapper from './Attribute';
import Node from '../../../nodes/shared/Node';
import ElementWrapper from '.'; import ElementWrapper from '.';
import { stringify } from '../../../utils/stringify'; import { stringify } from '../../../utils/stringify';
import add_to_set from '../../../utils/add_to_set'; import add_to_set from '../../../utils/add_to_set';
import Expression from '../../../nodes/shared/Expression';
import Text from '../../../nodes/Text';
export interface StyleProp { export interface StyleProp {
key: string; key: string;
value: Node[]; value: (Text|Expression)[];
} }
export default class StyleAttributeWrapper extends AttributeWrapper { export default class StyleAttributeWrapper extends AttributeWrapper {
@ -28,7 +29,7 @@ export default class StyleAttributeWrapper extends AttributeWrapper {
value = value =
((prop.value.length === 1 || prop.value[0].type === 'Text') ? '' : `"" + `) + ((prop.value.length === 1 || prop.value[0].type === 'Text') ? '' : `"" + `) +
prop.value prop.value
.map((chunk: Node) => { .map((chunk) => {
if (chunk.type === 'Text') { if (chunk.type === 'Text') {
return stringify(chunk.data); return stringify(chunk.data);
} else { } else {
@ -54,7 +55,7 @@ export default class StyleAttributeWrapper extends AttributeWrapper {
); );
} }
} else { } else {
value = stringify(prop.value[0].data); value = stringify((prop.value[0] as Text).data);
} }
block.builders.hydrate.add_line( block.builders.hydrate.add_line(
@ -64,8 +65,8 @@ export default class StyleAttributeWrapper extends AttributeWrapper {
} }
} }
function optimize_style(value: Node[]) { function optimize_style(value: (Text|Expression)[]) {
const props: { key: string, value: Node[] }[] = []; const props: StyleProp[] = [];
let chunks = value.slice(); let chunks = value.slice();
while (chunks.length) { while (chunks.length) {
@ -87,13 +88,12 @@ function optimize_style(value: Node[]) {
end: chunk.end, end: chunk.end,
type: 'Text', type: 'Text',
data: remaining_data data: remaining_data
}; } as Text;
} else { } else {
chunks.shift(); chunks.shift();
} }
const result = get_style_value(chunks); const result = get_style_value(chunks);
if (!result) return null;
props.push({ key, value: result.value }); props.push({ key, value: result.value });
chunks = result.chunks; chunks = result.chunks;
@ -102,8 +102,8 @@ function optimize_style(value: Node[]) {
return props; return props;
} }
function get_style_value(chunks: Node[]) { function get_style_value(chunks: (Text | Expression)[]) {
const value: Node[] = []; const value: (Text|Expression)[] = [];
let in_url = false; let in_url = false;
let quote_mark = null; let quote_mark = null;
@ -122,7 +122,7 @@ function get_style_value(chunks: Node[]) {
} else if (char === '\\') { } else if (char === '\\') {
escaped = true; escaped = true;
} else if (char === quote_mark) { } else if (char === quote_mark) {
quote_mark === null; quote_mark = null;
} else if (char === '"' || char === "'") { } else if (char === '"' || char === "'") {
quote_mark = char; quote_mark = char;
} else if (char === ')' && in_url) { } else if (char === ')' && in_url) {
@ -142,7 +142,7 @@ function get_style_value(chunks: Node[]) {
start: chunk.start, start: chunk.start,
end: chunk.start + c, end: chunk.start + c,
data: chunk.data.slice(0, c) data: chunk.data.slice(0, c)
}); } as Text);
} }
while (/[;\s]/.test(chunk.data[c])) c += 1; while (/[;\s]/.test(chunk.data[c])) c += 1;
@ -154,7 +154,7 @@ function get_style_value(chunks: Node[]) {
end: chunk.end, end: chunk.end,
type: 'Text', type: 'Text',
data: remaining_data data: remaining_data
}); } as Text);
break; break;
} }
@ -171,6 +171,6 @@ function get_style_value(chunks: Node[]) {
}; };
} }
function is_dynamic(value: Node[]) { function is_dynamic(value: (Text|Expression)[]) {
return value.length > 1 || value[0].type !== 'Text'; return value.length > 1 || value[0].type !== 'Text';
} }

@ -20,20 +20,19 @@ import add_event_handlers from '../shared/add_event_handlers';
import add_actions from '../shared/add_actions'; import add_actions from '../shared/add_actions';
import create_debugging_comment from '../shared/create_debugging_comment'; import create_debugging_comment from '../shared/create_debugging_comment';
import { get_context_merger } from '../shared/get_context_merger'; import { get_context_merger } from '../shared/get_context_merger';
import Slot from '../../../nodes/Slot';
const events = [ const events = [
{ {
event_names: ['input'], event_names: ['input'],
filter: (node: Element, name: string) => filter: (node: Element, name: string) =>
node.name === 'textarea' || node.name === 'textarea' ||
node.name === 'input' && !/radio|checkbox|range/.test(node.get_static_attribute_value('type')) node.name === 'input' && !/radio|checkbox|range/.test(node.get_static_attribute_value('type') as string)
}, },
{ {
event_names: ['change'], event_names: ['change'],
filter: (node: Element, name: string) => filter: (node: Element, name: string) =>
node.name === 'select' || node.name === 'select' ||
node.name === 'input' && /radio|checkbox/.test(node.get_static_attribute_value('type')) node.name === 'input' && /radio|checkbox/.test(node.get_static_attribute_value('type') as string)
}, },
{ {
event_names: ['change', 'input'], event_names: ['change', 'input'],
@ -91,6 +90,12 @@ const events = [
name === 'playbackRate' name === 'playbackRate'
}, },
// details event
{
event_names: ['toggle'],
filter: (node: Element, name: string) =>
node.name === 'details'
},
]; ];
export default class ElementWrapper extends Wrapper { export default class ElementWrapper extends Wrapper {
@ -135,7 +140,7 @@ export default class ElementWrapper extends Wrapper {
} }
if (owner && owner.node.type === 'InlineComponent') { if (owner && owner.node.type === 'InlineComponent') {
const name = attribute.get_static_value(); const name = attribute.get_static_value() as string;
if (!(owner as InlineComponentWrapper).slots.has(name)) { if (!(owner as InlineComponentWrapper).slots.has(name)) {
const child_block = block.child({ const child_block = block.child({
@ -275,6 +280,7 @@ export default class ElementWrapper extends Wrapper {
if (!this.node.namespace && this.can_use_innerhtml && this.fragment.nodes.length > 0) { if (!this.node.namespace && this.can_use_innerhtml && this.fragment.nodes.length > 0) {
if (this.fragment.nodes.length === 1 && this.fragment.nodes[0].node.type === 'Text') { if (this.fragment.nodes.length === 1 && this.fragment.nodes[0].node.type === 'Text') {
block.builders.create.add_line( block.builders.create.add_line(
// @ts-ignore todo: should it be this.fragment.nodes[0].node.data instead?
`${node}.textContent = ${stringify(this.fragment.nodes[0].data)};` `${node}.textContent = ${stringify(this.fragment.nodes[0].data)};`
); );
} else { } else {
@ -324,7 +330,7 @@ export default class ElementWrapper extends Wrapper {
function to_html(wrapper: ElementWrapper | TextWrapper) { function to_html(wrapper: ElementWrapper | TextWrapper) {
if (wrapper.node.type === 'Text') { if (wrapper.node.type === 'Text') {
const { parent } = wrapper.node; const parent = wrapper.node.parent as Element;
const raw = parent && ( const raw = parent && (
parent.name === 'script' || parent.name === 'script' ||
@ -349,7 +355,7 @@ export default class ElementWrapper extends Wrapper {
if (is_void(wrapper.node.name)) return open + '>'; if (is_void(wrapper.node.name)) return open + '>';
return `${open}>${wrapper.fragment.nodes.map(to_html).join('')}</${wrapper.node.name}>`; return `${open}>${(wrapper as ElementWrapper).fragment.nodes.map(to_html).join('')}</${wrapper.node.name}>`;
} }
if (renderer.options.dev) { if (renderer.options.dev) {
@ -376,8 +382,8 @@ export default class ElementWrapper extends Wrapper {
get_claim_statement(nodes: string) { get_claim_statement(nodes: string) {
const attributes = this.node.attributes const attributes = this.node.attributes
.filter((attr: Node) => attr.type === 'Attribute') .filter((attr) => attr.type === 'Attribute')
.map((attr: Node) => `${quote_name_if_necessary(attr.name)}: true`) .map((attr) => `${quote_name_if_necessary(attr.name)}: true`)
.join(', '); .join(', ');
const name = this.node.namespace const name = this.node.namespace
@ -455,7 +461,7 @@ export default class ElementWrapper extends Wrapper {
function ${handler}() { function ${handler}() {
${animation_frame && deindent` ${animation_frame && deindent`
cancelAnimationFrame(${animation_frame}); cancelAnimationFrame(${animation_frame});
if (!${this.var}.paused) ${animation_frame} = requestAnimationFrame(${handler});`} if (!${this.var}.paused) ${animation_frame} = @raf(${handler});`}
${needs_lock && `${lock} = true;`} ${needs_lock && `${lock} = true;`}
ctx.${handler}.call(${this.var}${contextual_dependencies.size > 0 ? ', ctx' : ''}); ctx.${handler}.call(${this.var}${contextual_dependencies.size > 0 ? ', ctx' : ''});
} }
@ -553,12 +559,13 @@ export default class ElementWrapper extends Wrapper {
} }
add_attributes(block: Block) { add_attributes(block: Block) {
// @ts-ignore todo:
if (this.node.attributes.find(attr => attr.type === 'Spread')) { if (this.node.attributes.find(attr => attr.type === 'Spread')) {
this.add_spread_attributes(block); this.add_spread_attributes(block);
return; return;
} }
this.attributes.forEach((attribute: Attribute) => { this.attributes.forEach((attribute) => {
if (attribute.node.name === 'class' && attribute.node.is_dynamic) { if (attribute.node.name === 'class' && attribute.node.is_dynamic) {
this.class_dependencies.push(...attribute.node.dependencies); this.class_dependencies.push(...attribute.node.dependencies);
} }
@ -814,27 +821,28 @@ export default class ElementWrapper extends Wrapper {
}); });
} }
add_css_class(class_name = this.component.stylesheet.id) { // todo: looks to be dead code copypasted from Element.add_css_class in src/compile/nodes/Element.ts
const class_attribute = this.attributes.find(a => a.name === 'class'); // add_css_class(class_name = this.component.stylesheet.id) {
if (class_attribute && !class_attribute.is_true) { // const class_attribute = this.attributes.find(a => a.name === 'class');
if (class_attribute.chunks.length === 1 && class_attribute.chunks[0].type === 'Text') { // if (class_attribute && !class_attribute.is_true) {
(class_attribute.chunks[0] as Text).data += ` ${class_name}`; // if (class_attribute.chunks.length === 1 && class_attribute.chunks[0].type === 'Text') {
} else { // (class_attribute.chunks[0] as Text).data += ` ${class_name}`;
(class_attribute.chunks as Node[]).push( // } else {
new Text(this.component, this, this.scope, { // (class_attribute.chunks as Node[]).push(
type: 'Text', // new Text(this.component, this, this.scope, {
data: ` ${class_name}` // type: 'Text',
}) // data: ` ${class_name}`
); // })
} // );
} else { // }
this.attributes.push( // } else {
new Attribute(this.component, this, this.scope, { // this.attributes.push(
type: 'Attribute', // new Attribute(this.component, this, this.scope, {
name: 'class', // type: 'Attribute',
value: [{ type: 'Text', data: class_name }] // name: 'class',
}) // value: [{ type: 'Text', data: class_name }]
); // })
} // );
} // }
// }
} }

@ -13,7 +13,7 @@ import Slot from './Slot';
import Text from './Text'; import Text from './Text';
import Title from './Title'; import Title from './Title';
import Window from './Window'; import Window from './Window';
import Node from '../../nodes/shared/Node'; import { INode } from '../../nodes/interfaces';
import TextWrapper from './Text'; import TextWrapper from './Text';
import Renderer from '../Renderer'; import Renderer from '../Renderer';
import Block from '../Block'; import Block from '../Block';
@ -49,7 +49,7 @@ export default class FragmentWrapper {
constructor( constructor(
renderer: Renderer, renderer: Renderer,
block: Block, block: Block,
nodes: Node[], nodes: INode[],
parent: Wrapper, parent: Wrapper,
strip_whitespace: boolean, strip_whitespace: boolean,
next_sibling: Wrapper next_sibling: Wrapper
@ -85,6 +85,7 @@ export default class FragmentWrapper {
// *unless* there is no whitespace between this node and its next sibling // *unless* there is no whitespace between this node and its next sibling
if (this.nodes.length === 0) { if (this.nodes.length === 0) {
const should_trim = ( const should_trim = (
// @ts-ignore todo: probably error, should it be next_sibling.node.data?
next_sibling ? (next_sibling.node.type === 'Text' && /^\s/.test(next_sibling.data)) : !child.has_ancestor('EachBlock') next_sibling ? (next_sibling.node.type === 'Text' && /^\s/.test(next_sibling.data)) : !child.has_ancestor('EachBlock')
); );
@ -96,6 +97,7 @@ export default class FragmentWrapper {
// glue text nodes (which could e.g. be separated by comments) together // glue text nodes (which could e.g. be separated by comments) together
if (last_child && last_child.node.type === 'Text') { if (last_child && last_child.node.type === 'Text') {
// @ts-ignore todo: probably error, should it be last_child.node.data?
last_child.data = data + last_child.data; last_child.data = data + last_child.data;
continue; continue;
} }

@ -96,7 +96,7 @@ export default class IfBlockWrapper extends Wrapper {
if (branch.block.has_outros) has_outros = true; if (branch.block.has_outros) has_outros = true;
if (is_else_if(node.else)) { if (is_else_if(node.else)) {
create_branches(node.else.children[0]); create_branches(node.else.children[0] as IfBlock);
} else if (node.else) { } else if (node.else) {
const branch = new IfBlockBranch( const branch = new IfBlockBranch(
renderer, renderer,
@ -452,4 +452,4 @@ export default class IfBlockWrapper extends Wrapper {
block.builders.destroy.add_line(`${if_name}${name}.d(${parent_node ? '' : 'detaching'});`); block.builders.destroy.add_line(`${if_name}${name}.d(${parent_node ? '' : 'detaching'});`);
} }
} }

@ -142,7 +142,7 @@ export default class InlineComponentWrapper extends Wrapper {
if (this.fragment) { if (this.fragment) {
const default_slot = this.slots.get('default'); const default_slot = this.slots.get('default');
this.fragment.nodes.forEach((child: Wrapper) => { this.fragment.nodes.forEach((child) => {
child.render(default_slot.block, null, 'nodes'); child.render(default_slot.block, null, 'nodes');
}); });
} }
@ -505,4 +505,4 @@ export default class InlineComponentWrapper extends Wrapper {
); );
} }
} }
} }

@ -1,13 +1,14 @@
import Renderer from '../Renderer'; import Renderer from '../Renderer';
import Block from '../Block'; import Block from '../Block';
import Node from '../../nodes/shared/Node';
import Tag from './shared/Tag'; import Tag from './shared/Tag';
import Wrapper from './shared/Wrapper'; import Wrapper from './shared/Wrapper';
import MustacheTag from '../../nodes/MustacheTag';
import RawMustacheTag from '../../nodes/RawMustacheTag';
export default class MustacheTagWrapper extends Tag { export default class MustacheTagWrapper extends Tag {
var = 't'; var = 't';
constructor(renderer: Renderer, block: Block, parent: Wrapper, node: Node) { constructor(renderer: Renderer, block: Block, parent: Wrapper, node: MustacheTag | RawMustacheTag) {
super(renderer, block, parent, node); super(renderer, block, parent, node);
this.cannot_use_innerhtml(); this.cannot_use_innerhtml();
} }
@ -25,4 +26,4 @@ export default class MustacheTagWrapper extends Tag {
parent_node parent_node
); );
} }
} }

@ -1,9 +1,10 @@
import Renderer from '../Renderer'; import Renderer from '../Renderer';
import Block from '../Block'; import Block from '../Block';
import Node from '../../nodes/shared/Node';
import Tag from './shared/Tag'; import Tag from './shared/Tag';
import Wrapper from './shared/wrapper'; import Wrapper from './shared/Wrapper';
import deindent from '../../utils/deindent'; import deindent from '../../utils/deindent';
import MustacheTag from '../../nodes/MustacheTag';
import RawMustacheTag from '../../nodes/RawMustacheTag';
export default class RawMustacheTagWrapper extends Tag { export default class RawMustacheTagWrapper extends Tag {
var = 'raw'; var = 'raw';
@ -12,7 +13,7 @@ export default class RawMustacheTagWrapper extends Tag {
renderer: Renderer, renderer: Renderer,
block: Block, block: Block,
parent: Wrapper, parent: Wrapper,
node: Node node: MustacheTag | RawMustacheTag
) { ) {
super(renderer, block, parent, node); super(renderer, block, parent, node);
this.cannot_use_innerhtml(); this.cannot_use_innerhtml();
@ -100,4 +101,4 @@ export default class RawMustacheTagWrapper extends Tag {
add_anchor_after(); add_anchor_after();
} }
} }
} }

@ -9,7 +9,6 @@ import add_to_set from '../../utils/add_to_set';
import get_slot_data from '../../utils/get_slot_data'; import get_slot_data from '../../utils/get_slot_data';
import { stringify_props } from '../../utils/stringify_props'; import { stringify_props } from '../../utils/stringify_props';
import Expression from '../../nodes/shared/Expression'; import Expression from '../../nodes/shared/Expression';
import Attribute from '../../nodes/Attribute';
export default class SlotWrapper extends Wrapper { export default class SlotWrapper extends Wrapper {
node: Slot; node: Slot;

@ -4,6 +4,7 @@ import Block from '../Block';
import Title from '../../nodes/Title'; import Title from '../../nodes/Title';
import { stringify } from '../../utils/stringify'; import { stringify } from '../../utils/stringify';
import add_to_set from '../../utils/add_to_set'; import add_to_set from '../../utils/add_to_set';
import Text from '../../nodes/Text';
export default class TitleWrapper extends Wrapper { export default class TitleWrapper extends Wrapper {
node: Title; node: Title;
@ -31,6 +32,7 @@ export default class TitleWrapper extends Wrapper {
// DRY it out if that's possible without introducing crazy indirection // DRY it out if that's possible without introducing crazy indirection
if (this.node.children.length === 1) { if (this.node.children.length === 1) {
// single {tag} — may be a non-string // single {tag} — may be a non-string
// @ts-ignore todo: check this
const { expression } = this.node.children[0]; const { expression } = this.node.children[0];
value = expression.render(block); value = expression.render(block);
add_to_set(all_dependencies, expression.dependencies); add_to_set(all_dependencies, expression.dependencies);
@ -39,16 +41,18 @@ export default class TitleWrapper extends Wrapper {
value = value =
(this.node.children[0].type === 'Text' ? '' : `"" + `) + (this.node.children[0].type === 'Text' ? '' : `"" + `) +
this.node.children this.node.children
.map((chunk: Node) => { .map((chunk) => {
if (chunk.type === 'Text') { if (chunk.type === 'Text') {
return stringify(chunk.data); return stringify(chunk.data);
} else { } else {
// @ts-ignore todo: check this
const snippet = chunk.expression.render(block); const snippet = chunk.expression.render(block);
// @ts-ignore todo: check this
chunk.expression.dependencies.forEach(d => { chunk.expression.dependencies.forEach(d => {
all_dependencies.add(d); all_dependencies.add(d);
}); });
// @ts-ignore todo: check this
return chunk.expression.get_precedence() <= 13 ? `(${snippet})` : snippet; return chunk.expression.get_precedence() <= 13 ? `(${snippet})` : snippet;
} }
}) })
@ -88,8 +92,8 @@ export default class TitleWrapper extends Wrapper {
); );
} }
} else { } else {
const value = stringify(this.node.children[0].data); const value = stringify((this.node.children[0] as Text).data);
block.builders.hydrate.add_line(`document.title = ${value};`); block.builders.hydrate.add_line(`document.title = ${value};`);
} }
} }
} }

@ -6,6 +6,7 @@ import deindent from '../../utils/deindent';
import add_event_handlers from './shared/add_event_handlers'; import add_event_handlers from './shared/add_event_handlers';
import Window from '../../nodes/Window'; import Window from '../../nodes/Window';
import add_actions from './shared/add_actions'; import add_actions from './shared/add_actions';
import { INode } from '../../nodes/interfaces';
const associated_events = { const associated_events = {
innerWidth: 'resize', innerWidth: 'resize',
@ -33,7 +34,7 @@ const readonly = new Set([
export default class WindowWrapper extends Wrapper { export default class WindowWrapper extends Wrapper {
node: Window; node: Window;
constructor(renderer: Renderer, block: Block, parent: Wrapper, node: Node) { constructor(renderer: Renderer, block: Block, parent: Wrapper, node: INode) {
super(renderer, block, parent, node); super(renderer, block, parent, node);
} }

@ -1,11 +1,11 @@
import Renderer from '../../Renderer'; import Renderer from '../../Renderer';
import Node from '../../../nodes/shared/Node';
import Block from '../../Block'; import Block from '../../Block';
import { INode } from '../../../nodes/interfaces';
export default class Wrapper { export default class Wrapper {
renderer: Renderer; renderer: Renderer;
parent: Wrapper; parent: Wrapper;
node: Node; node: INode;
prev: Wrapper | null; prev: Wrapper | null;
next: Wrapper | null; next: Wrapper | null;
@ -17,7 +17,7 @@ export default class Wrapper {
renderer: Renderer, renderer: Renderer,
block: Block, block: Block,
parent: Wrapper, parent: Wrapper,
node: Node node: INode
) { ) {
this.node = node; this.node = node;
@ -75,4 +75,8 @@ export default class Wrapper {
this.node.type === 'MustacheTag' this.node.type === 'MustacheTag'
); );
} }
}
render(block: Block, parent_node: string, parent_nodes: string){
throw Error('Wrapper class is not renderable');
}
}

@ -1,8 +1,8 @@
import Component from '../../../Component'; import Component from '../../../Component';
import { Node } from '../../../../interfaces'; import { INode } from '../../../nodes/interfaces';
export default function create_debugging_comment( export default function create_debugging_comment(
node: Node, node: INode,
component: Component component: Component
) { ) {
const { locate, source } = component; const { locate, source } = component;
@ -19,6 +19,7 @@ export default function create_debugging_comment(
d = node.children.length ? node.children[0].start : node.start; d = node.children.length ? node.children[0].start : node.start;
while (source[d - 1] !== '>') d -= 1; while (source[d - 1] !== '>') d -= 1;
} else { } else {
// @ts-ignore
d = node.expression ? node.expression.node.end : c; d = node.expression ? node.expression.node.end : c;
while (source[d] !== '}') d += 1; while (source[d] !== '}') d += 1;
while (source[d] === '}') d += 1; while (source[d] === '}') d += 1;

@ -12,6 +12,7 @@ import Tag from './handlers/Tag';
import Text from './handlers/Text'; import Text from './handlers/Text';
import Title from './handlers/Title'; import Title from './handlers/Title';
import { AppendTarget, CompileOptions } from '../../interfaces'; import { AppendTarget, CompileOptions } from '../../interfaces';
import { INode } from '../nodes/interfaces';
type Handler = (node: any, renderer: Renderer, options: CompileOptions) => void; type Handler = (node: any, renderer: Renderer, options: CompileOptions) => void;
@ -36,6 +37,10 @@ const handlers: Record<string, Handler> = {
Window: noop Window: noop
}; };
export interface RenderOptions extends CompileOptions{
locate: (c: number) => { line: number; column: number; };
};
export default class Renderer { export default class Renderer {
has_bindings = false; has_bindings = false;
code = ''; code = '';
@ -51,7 +56,7 @@ export default class Renderer {
} }
} }
render(nodes, options) { render(nodes: INode[], options: RenderOptions) {
nodes.forEach(node => { nodes.forEach(node => {
const handler = handlers[node.type]; const handler = handlers[node.type];

@ -1,8 +1,8 @@
import Renderer from '../Renderer'; import Renderer, { RenderOptions } from '../Renderer';
import { CompileOptions } from '../../../interfaces';
import { snip } from '../../utils/snip'; import { snip } from '../../utils/snip';
import AwaitBlock from '../../nodes/AwaitBlock';
export default function(node, renderer: Renderer, options: CompileOptions) { export default function(node: AwaitBlock, renderer: Renderer, options: RenderOptions) {
renderer.append('${(function(__value) { if(@is_promise(__value)) return `'); renderer.append('${(function(__value) { if(@is_promise(__value)) return `');
renderer.render(node.pending.children, options); renderer.render(node.pending.children, options);
@ -13,4 +13,4 @@ export default function(node, renderer: Renderer, options: CompileOptions) {
const snippet = snip(node.expression); const snippet = snip(node.expression);
renderer.append(`\`;}(__value);}(${snippet})) }`); renderer.append(`\`;}(__value);}(${snippet})) }`);
} }

@ -1,8 +1,8 @@
import Renderer from '../Renderer'; import Renderer, { RenderOptions } from '../Renderer';
import { CompileOptions } from '../../../interfaces'; import Comment from '../../nodes/Comment';
export default function(node, renderer: Renderer, options: CompileOptions) { export default function(node: Comment, renderer: Renderer, options: RenderOptions) {
if (options.preserveComments) { if (options.preserveComments) {
renderer.append(`<!--${node.data}-->`); renderer.append(`<!--${node.data}-->`);
} }
} }

@ -1,9 +1,10 @@
import { stringify } from '../../utils/stringify'; import { stringify } from '../../utils/stringify';
import DebugTag from '../../nodes/DebugTag';
export default function(node, renderer, options) { import Renderer, { RenderOptions } from '../Renderer';
export default function(node: DebugTag, renderer: Renderer, options: RenderOptions) {
if (!options.dev) return; if (!options.dev) return;
const filename = options.file || null; const filename = options.filename || null;
const { line, column } = options.locate(node.start + 1); const { line, column } = options.locate(node.start + 1);
const obj = node.expressions.length === 0 const obj = node.expressions.length === 0
@ -15,4 +16,4 @@ export default function(node, renderer, options) {
const str = '${@debug(' + `${filename && stringify(filename)}, ${line}, ${column}, ${obj})}`; const str = '${@debug(' + `${filename && stringify(filename)}, ${line}, ${column}, ${obj})}`;
renderer.append(str); renderer.append(str);
} }

@ -1,6 +1,8 @@
import { snip } from '../../utils/snip'; import { snip } from '../../utils/snip';
import Renderer, { RenderOptions } from '../Renderer';
import EachBlock from '../../nodes/EachBlock';
export default function(node, renderer, options) { export default function(node: EachBlock, renderer: Renderer, options: RenderOptions) {
const snippet = snip(node.expression); const snippet = snip(node.expression);
const { start, end } = node.context_node; const { start, end } = node.context_node;
@ -24,4 +26,4 @@ export default function(node, renderer, options) {
} }
renderer.append('}'); renderer.append('}');
} }

@ -5,6 +5,9 @@ import Node from '../../nodes/shared/Node';
import { snip } from '../../utils/snip'; import { snip } from '../../utils/snip';
import { stringify_attribute } from '../../utils/stringify_attribute'; import { stringify_attribute } from '../../utils/stringify_attribute';
import { get_slot_scope } from './shared/get_slot_scope'; import { get_slot_scope } from './shared/get_slot_scope';
import Renderer, { RenderOptions } from '../Renderer';
import Element from '../../nodes/Element';
import Text from '../../nodes/Text';
// source: https://gist.github.com/ArjanSchouten/0b8574a6ad7f5065a5e7 // source: https://gist.github.com/ArjanSchouten/0b8574a6ad7f5065a5e7
const boolean_attributes = new Set([ const boolean_attributes = new Set([
@ -47,15 +50,17 @@ const boolean_attributes = new Set([
'translate' 'translate'
]); ]);
export default function(node, renderer, options) { export default function(node: Element, renderer: Renderer, options: RenderOptions & {
slot_scopes: Map<any, any>;
}) {
let opening_tag = `<${node.name}`; let opening_tag = `<${node.name}`;
let textarea_contents; // awkward special case let textarea_contents; // awkward special case
const slot = node.get_static_attribute_value('slot'); const slot = node.get_static_attribute_value('slot');
const component = node.find_nearest(/InlineComponent/); const component = node.find_nearest(/InlineComponent/);
if (slot && component) { if (slot && component) {
const slot = node.attributes.find((attribute: Node) => attribute.name === 'slot'); const slot = node.attributes.find((attribute) => attribute.name === 'slot');
const slot_name = slot.chunks[0].data; const slot_name = (slot.chunks[0] as Text).data;
const target = renderer.targets[renderer.targets.length - 1]; const target = renderer.targets[renderer.targets.length - 1];
target.slot_stack.push(slot_name); target.slot_stack.push(slot_name);
target.slots[slot_name] = ''; target.slots[slot_name] = '';
@ -160,4 +165,4 @@ export default function(node, renderer, options) {
if (!is_void(node.name)) { if (!is_void(node.name)) {
renderer.append(`</${node.name}>`); renderer.append(`</${node.name}>`);
} }
} }

@ -1,7 +1,10 @@
export default function(node, renderer, options) { import Renderer, { RenderOptions } from '../Renderer';
import Head from '../../nodes/Head';
export default function(node: Head, renderer: Renderer, options: RenderOptions) {
renderer.append('${($$result.head += `'); renderer.append('${($$result.head += `');
renderer.render(node.children, options); renderer.render(node.children, options);
renderer.append('`, "")}'); renderer.append('`, "")}');
} }

@ -1,5 +1,7 @@
import { snip } from '../../utils/snip'; import { snip } from '../../utils/snip';
import Renderer, { RenderOptions } from '../Renderer';
import RawMustacheTag from '../../nodes/RawMustacheTag';
export default function(node, renderer, options) { export default function(node: RawMustacheTag, renderer: Renderer, options: RenderOptions) {
renderer.append('${' + snip(node.expression) + '}'); renderer.append('${' + snip(node.expression) + '}');
} }

@ -1,6 +1,7 @@
import { snip } from '../../utils/snip'; import { snip } from '../../utils/snip';
import IfBlock from '../../nodes/IfBlock';
export default function(node, renderer, options) { import Renderer, { RenderOptions } from '../Renderer';
export default function(node: IfBlock, renderer: Renderer, options: RenderOptions) {
const snippet = snip(node.expression); const snippet = snip(node.expression);
renderer.append('${ ' + snippet + ' ? `'); renderer.append('${ ' + snippet + ' ? `');
@ -14,4 +15,4 @@ export default function(node, renderer, options) {
} }
renderer.append('` }'); renderer.append('` }');
} }

@ -1,14 +1,17 @@
import { escape, escape_template, stringify } from '../../utils/stringify'; import { escape, escape_template, stringify } from '../../utils/stringify';
import { quote_name_if_necessary } from '../../../utils/names'; import { quote_name_if_necessary } from '../../../utils/names';
import { snip } from '../../utils/snip'; import { snip } from '../../utils/snip';
import Renderer from '../Renderer'; import Renderer, { RenderOptions } from '../Renderer';
import { stringify_props } from '../../utils/stringify_props'; import { stringify_props } from '../../utils/stringify_props';
import { get_slot_scope } from './shared/get_slot_scope'; import { get_slot_scope } from './shared/get_slot_scope';
import { AppendTarget } from '../../../interfaces'; import { AppendTarget } from '../../../interfaces';
import InlineComponent from '../../nodes/InlineComponent';
import { INode } from '../../nodes/interfaces';
import Text from '../../nodes/Text';
function stringify_attribute(chunk: Node) { function stringify_attribute(chunk: INode) {
if (chunk.type === 'Text') { if (chunk.type === 'Text') {
return escape_template(escape(chunk.data)); return escape_template(escape((chunk as Text).data));
} }
return '${@escape(' + snip(chunk) + ')}'; return '${@escape(' + snip(chunk) + ')}';
@ -30,7 +33,7 @@ function get_attribute_value(attribute) {
return '`' + attribute.chunks.map(stringify_attribute).join('') + '`'; return '`' + attribute.chunks.map(stringify_attribute).join('') + '`';
} }
export default function(node, renderer: Renderer, options) { export default function(node: InlineComponent, renderer: Renderer, options: RenderOptions) {
const binding_props = []; const binding_props = [];
const binding_fns = []; const binding_fns = [];

@ -1,7 +1,9 @@
import { quote_prop_if_necessary } from '../../../utils/names'; import { quote_prop_if_necessary } from '../../../utils/names';
import get_slot_data from '../../utils/get_slot_data'; import get_slot_data from '../../utils/get_slot_data';
import Renderer, { RenderOptions } from '../Renderer';
import Slot from '../../nodes/Slot';
export default function(node, renderer, options) { export default function(node: Slot, renderer: Renderer, options: RenderOptions) {
const prop = quote_prop_if_necessary(node.slot_name); const prop = quote_prop_if_necessary(node.slot_name);
const slot_data = get_slot_data(node.values, true); const slot_data = get_slot_data(node.values, true);
@ -13,4 +15,4 @@ export default function(node, renderer, options) {
renderer.render(node.children, options); renderer.render(node.children, options);
renderer.append(`\`}`); renderer.append(`\`}`);
} }

@ -1,6 +1,6 @@
import { snip } from '../../utils/snip'; import { snip } from '../../utils/snip';
import Renderer, { RenderOptions } from '../Renderer';
export default function(node, renderer, options) { export default function(node, renderer: Renderer, options: RenderOptions) {
const snippet = snip(node.expression); const snippet = snip(node.expression);
renderer.append( renderer.append(
@ -10,4 +10,4 @@ export default function(node, renderer, options) {
? '${' + snippet + '}' ? '${' + snippet + '}'
: '${@escape(' + snippet + ')}' : '${@escape(' + snippet + ')}'
); );
} }

@ -1,14 +1,17 @@
import { escape_html, escape_template, escape } from '../../utils/stringify'; import { escape_html, escape_template, escape } from '../../utils/stringify';
import Renderer, { RenderOptions } from '../Renderer';
import Text from '../../nodes/Text';
import Element from '../../nodes/Element';
export default function(node, renderer, options) { export default function(node: Text, renderer: Renderer, options: RenderOptions) {
let text = node.data; let text = node.data;
if ( if (
!node.parent || !node.parent ||
node.parent.type !== 'Element' || node.parent.type !== 'Element' ||
(node.parent.name !== 'script' && node.parent.name !== 'style') ((node.parent as Element).name !== 'script' && (node.parent as Element).name !== 'style')
) { ) {
// unless this Text node is inside a <script> or <style> element, escape &,<,> // unless this Text node is inside a <script> or <style> element, escape &,<,>
text = escape_html(text); text = escape_html(text);
} }
renderer.append(escape(escape_template(text))); renderer.append(escape(escape_template(text)));
} }

@ -1,7 +1,10 @@
export default function(node, renderer, options) { import Renderer, { RenderOptions } from '../Renderer';
import Title from '../../nodes/Title';
export default function(node: Title, renderer: Renderer, options: RenderOptions) {
renderer.append(`<title>`); renderer.append(`<title>`);
renderer.render(node.children, options); renderer.render(node.children, options);
renderer.append(`</title>`); renderer.append(`</title>`);
} }

@ -4,6 +4,8 @@ import { CompileOptions } from '../../interfaces';
import { stringify } from '../utils/stringify'; import { stringify } from '../utils/stringify';
import Renderer from './Renderer'; import Renderer from './Renderer';
import { extract_names } from '../utils/scope'; import { extract_names } from '../utils/scope';
import { INode } from '../nodes/interfaces';
import Text from '../nodes/Text';
export default function ssr( export default function ssr(
component: Component, component: Component,
@ -151,10 +153,10 @@ export default function ssr(
`).trim(); `).trim();
} }
function trim(nodes) { function trim(nodes: INode[]) {
let start = 0; let start = 0;
for (; start < nodes.length; start += 1) { for (; start < nodes.length; start += 1) {
const node = nodes[start]; const node = nodes[start] as Text;
if (node.type !== 'Text') break; if (node.type !== 'Text') break;
node.data = node.data.replace(/^\s+/, ''); node.data = node.data.replace(/^\s+/, '');
@ -163,7 +165,7 @@ function trim(nodes) {
let end = nodes.length; let end = nodes.length;
for (; end > start; end -= 1) { for (; end > start; end -= 1) {
const node = nodes[end - 1]; const node = nodes[end - 1] as Text;
if (node.type !== 'Text') break; if (node.type !== 'Text') break;
node.data = node.data.replace(/\s+$/, ''); node.data = node.data.replace(/\s+$/, '');

@ -1,5 +1,6 @@
export default function add_to_set(a: Set<any>, b: Set<any>) { export default function add_to_set<T>(a: Set<T>, b: Set<T> | Array<T>) {
// @ts-ignore
b.forEach(item => { b.forEach(item => {
a.add(item); a.add(item);
}); });
} }

@ -1,6 +1,7 @@
import { walk } from 'estree-walker'; import { walk } from 'estree-walker';
import is_reference from 'is-reference'; import is_reference from 'is-reference';
import { Node } from '../../interfaces'; import { Node } from '../../interfaces';
import { Node as ESTreeNode } from 'estree';
export function create_scopes(expression: Node) { export function create_scopes(expression: Node) {
const map = new WeakMap(); const map = new WeakMap();
@ -9,7 +10,7 @@ export function create_scopes(expression: Node) {
let scope = new Scope(null, false); let scope = new Scope(null, false);
walk(expression, { walk(expression, {
enter(node: Node, parent: Node) { enter(node, parent) {
if (node.type === 'ImportDeclaration') { if (node.type === 'ImportDeclaration') {
node.specifiers.forEach(specifier => { node.specifiers.forEach(specifier => {
scope.declarations.set(specifier.local.name, specifier); scope.declarations.set(specifier.local.name, specifier);
@ -25,7 +26,7 @@ export function create_scopes(expression: Node) {
if (node.id) scope.declarations.set(node.id.name, node); if (node.id) scope.declarations.set(node.id.name, node);
} }
node.params.forEach((param: Node) => { node.params.forEach((param) => {
extract_names(param).forEach(name => { extract_names(param).forEach(name => {
scope.declarations.set(name, node); scope.declarations.set(name, node);
}); });
@ -38,7 +39,7 @@ export function create_scopes(expression: Node) {
map.set(node, scope); map.set(node, scope);
} else if (/(Class|Variable)Declaration/.test(node.type)) { } else if (/(Class|Variable)Declaration/.test(node.type)) {
scope.add_declaration(node); scope.add_declaration(node);
} else if (node.type === 'Identifier' && is_reference(node, parent)) { } else if (node.type === 'Identifier' && is_reference(node as ESTreeNode, parent as ESTreeNode)) {
if (!scope.has(node.name) && !globals.has(node.name)) { if (!scope.has(node.name) && !globals.has(node.name)) {
globals.set(node.name, node); globals.set(node.name, node);
} }

@ -1,11 +1,10 @@
import Attribute from '../nodes/Attribute'; import Attribute from '../nodes/Attribute';
import Node from '../nodes/shared/Node';
import { escape_template, escape } from './stringify'; import { escape_template, escape } from './stringify';
import { snip } from './snip'; import { snip } from './snip';
export function stringify_attribute(attribute: Attribute, is_ssr: boolean) { export function stringify_attribute(attribute: Attribute, is_ssr: boolean) {
return attribute.chunks return attribute.chunks
.map((chunk: Node) => { .map((chunk) => {
if (chunk.type === 'Text') { if (chunk.type === 'Text') {
return escape_template(escape(chunk.data).replace(/"/g, '&quot;')); return escape_template(escape(chunk.data).replace(/"/g, '&quot;'));
} }
@ -15,4 +14,4 @@ export function stringify_attribute(attribute: Attribute, is_ssr: boolean) {
: '${' + snip(chunk) + '}'; : '${' + snip(chunk) + '}';
}) })
.join(''); .join('');
} }

@ -0,0 +1,6 @@
export { default as compile } from './compile/index';
export { default as parse } from './parse/index';
export { default as preprocess } from './preprocess/index';
export { walk } from 'estree-walker';
export const VERSION = '__VERSION__';

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

Loading…
Cancel
Save