diff --git a/.gitignore b/.gitignore index 06671edc2b..35888493fa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,17 @@ +.idea .DS_Store .nyc_output node_modules *.map /src/compile/internal-exports.ts -/compiler.js -/index.js -/internal.* -/store.js -/easing.js -/motion.* -/transition.js -/animate.js +/compiler.*js +/index.*js +/internal.*js +/store.*js +/easing.*js +/motion.*js +/transition.*js +/animate.*js /scratch/ /coverage/ /coverage.lcov/ @@ -20,6 +21,7 @@ node_modules /test/sourcemaps/samples/*/output.css.map /yarn-error.log _actual*.* +/dist /site/cypress/screenshots/ /site/__sapper__/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 239f2d28e3..4981ca096b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,40 @@ # 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 `
` ([#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 `` ([#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 (``) ([#2743](https://github.com/sveltejs/svelte/pull/2743)) + ## 3.2.2 * Add `window` and `document` to expected globals ([#2722](https://github.com/sveltejs/svelte/pull/2722)) diff --git a/README.md b/README.md index ac0e4ff366..7d0af8ac2e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Cybernetically enhanced web apps: Svelte - + npm version @@ -16,7 +16,7 @@ alt="build status"> - + license

@@ -36,7 +36,7 @@ Pull requests are encouraged and always welcome. [Pick an issue](https://github. To install and work on Svelte locally: ```bash -git clone git@github.com:sveltejs/svelte.git +git clone https://github.com/sveltejs/svelte.git cd svelte npm install ``` diff --git a/animate.d.ts b/animate.d.ts new file mode 100644 index 0000000000..3284bfd8c0 --- /dev/null +++ b/animate.d.ts @@ -0,0 +1 @@ +export * from './dist/animate'; diff --git a/compiler.d.ts b/compiler.d.ts new file mode 100644 index 0000000000..977efefb6d --- /dev/null +++ b/compiler.d.ts @@ -0,0 +1 @@ +export * from './dist/compiler'; diff --git a/easing.d.ts b/easing.d.ts new file mode 100644 index 0000000000..c07764f4f0 --- /dev/null +++ b/easing.d.ts @@ -0,0 +1 @@ +export * from './dist/easing'; diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000000..e4ddc9027e --- /dev/null +++ b/index.d.ts @@ -0,0 +1 @@ +export * from './dist/index'; diff --git a/index.mjs b/index.mjs deleted file mode 100644 index ee5b575171..0000000000 --- a/index.mjs +++ /dev/null @@ -1,10 +0,0 @@ -export { - onMount, - onDestroy, - beforeUpdate, - afterUpdate, - setContext, - getContext, - tick, - createEventDispatcher -} from './internal'; diff --git a/internal.d.ts b/internal.d.ts new file mode 100644 index 0000000000..be034cd88a --- /dev/null +++ b/internal.d.ts @@ -0,0 +1 @@ +export * from './dist/internal'; diff --git a/motion.d.ts b/motion.d.ts new file mode 100644 index 0000000000..2fdaa86c4e --- /dev/null +++ b/motion.d.ts @@ -0,0 +1 @@ +export * from './dist/motion'; diff --git a/package-lock.json b/package-lock.json index 7c7363db2e..0ab3d0bfd6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.1.0", + "version": "3.4.3", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -246,15 +246,6 @@ "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "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": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", @@ -1550,12 +1541,12 @@ "dev": true }, "handlebars": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.0.tgz", - "integrity": "sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", "dev": true, "requires": { - "async": "^2.5.0", + "neo-async": "^2.6.0", "optimist": "^0.6.1", "source-map": "^0.6.1", "uglify-js": "^3.1.4" @@ -1996,9 +1987,9 @@ "dev": true }, "js-yaml": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", - "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -2448,6 +2439,12 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "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": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -4182,26 +4179,26 @@ "dev": true }, "typescript": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.4.tgz", - "integrity": "sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg==", + "version": "3.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.5.tgz", + "integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==", "dev": true }, "uglify-js": { - "version": "3.4.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", - "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.12.tgz", + "integrity": "sha512-KeQesOpPiZNgVwJj8Ge3P4JYbQHUdZzpx6Fahy6eKAYRSV4zhVmLXoC+JtOeYxcHCHTve8RG1ZGdTvpeOUM26Q==", "dev": true, "optional": true, "requires": { - "commander": "~2.17.1", + "commander": "~2.20.0", "source-map": "~0.6.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==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", "dev": true, "optional": true } diff --git a/package.json b/package.json index ccbedde168..b7214c9254 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.2.2", + "version": "3.4.3", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", @@ -27,11 +27,13 @@ "precodecov": "npm run coverage", "lint": "eslint src test/*.js", "build": "rollup -c", - "prepare": "npm run build", + "prepare": "npm run build && npm run tsd", "dev": "rollup -cw", "pretest": "npm run build", - "posttest": "agadoo src/internal/index.js", - "prepublishOnly": "export PUBLISH=true && npm run lint && npm test" + "posttest": "agadoo internal.mjs", + "prepublishOnly": "export PUBLISH=true && npm run lint && npm test", + "tsd": "tsc -p . --emitDeclarationOnly", + "typecheck": "tsc -p . --noEmit" }, "repository": { "type": "git", @@ -83,7 +85,7 @@ "tiny-glob": "^0.2.1", "ts-node": "^8.0.2", "tslib": "^1.8.0", - "typescript": "^3.0.1" + "typescript": "^3.4.0" }, "nyc": { "include": [ diff --git a/rollup.config.js b/rollup.config.js index f7b2d07d4b..9fd49f3e8f 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -9,10 +9,19 @@ import pkg from './package.json'; const is_publish = !!process.env.PUBLISH; +const tsPlugin = is_publish + ? typescript({ + include: 'src/**', + typescript: require('typescript') + }) + : sucrase({ + transforms: ['typescript'] + }); + export default [ /* internal.[m]js */ { - input: `src/internal/index.js`, + input: `src/internal/index.ts`, output: [ { file: `internal.mjs`, @@ -26,19 +35,22 @@ export default [ } ], external: id => id.startsWith('svelte/'), - plugins: [{ - 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)});`); + + plugins: [ + tsPlugin, + { + 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 */ { - input: 'src/index.ts', + input: 'src/compiler.ts', plugins: [ replace({ __VERSION__: pkg.version @@ -48,15 +60,7 @@ export default [ include: ['node_modules/**'] }), json(), - is_publish - ? typescript({ - include: 'src/**', - exclude: 'src/internal/**', - typescript: require('typescript') - }) - : sucrase({ - transforms: ['typescript'] - }) + tsPlugin ], output: { file: 'compiler.js', @@ -71,7 +75,7 @@ export default [ /* motion.mjs */ { - input: `src/motion/index.js`, + input: `src/motion/index.ts`, output: [ { file: `motion.mjs`, @@ -84,17 +88,30 @@ export default [ paths: id => id.startsWith('svelte/') && id.replace('svelte', '.') } ], + plugins: [ + tsPlugin + ], external: id => id.startsWith('svelte/') }, // everything else - ...['index', 'store', 'easing', 'transition', 'animate'].map(name => ({ - input: `${name}.mjs`, - output: { - file: `${name}.js`, - format: 'cjs', - paths: id => id.startsWith('svelte/') && id.replace('svelte', '.') - }, - external: id => id !== `${name}.mjs` + ...['index', 'easing', 'transition', 'animate', 'store'].map(name => ({ + input: `src/${name}.ts`, + output: [ + { + file: `${name}.mjs`, + format: 'esm', + paths: id => id.startsWith('svelte/') && id.replace('svelte', '.') + }, + { + file: `${name}.js`, + format: 'cjs', + paths: id => id.startsWith('svelte/') && id.replace('svelte', '.') + } + ], + plugins: [ + tsPlugin + ], + external: id => id.startsWith('svelte/') })) ]; diff --git a/site/README.md b/site/README.md index c438bda5ca..59380feffc 100644 --- a/site/README.md +++ b/site/README.md @@ -13,7 +13,11 @@ Start the server with `npm run dev`, and navigate to [localhost:3000](http://loc ## 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 diff --git a/site/content/blog/2017-08-07-the-easiest-way-to-get-started.md b/site/content/blog/2017-08-07-the-easiest-way-to-get-started.md index 596c469433..9d4c661615 100644 --- a/site/content/blog/2017-08-07-the-easiest-way-to-get-started.md +++ b/site/content/blog/2017-08-07-the-easiest-way-to-get-started.md @@ -44,9 +44,11 @@ In the terminal, you can instantly create a new project like so: npx degit sveltejs/template my-svelte-project cd my-svelte-project 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: ```bash diff --git a/site/content/docs/01-component-format.md b/site/content/docs/01-component-format.md index 356fa1170d..ddd2667075 100644 --- a/site/content/docs/01-component-format.md +++ b/site/content/docs/01-component-format.md @@ -47,11 +47,14 @@ Svelte uses the `export` keyword to mark a variable declaration as a *property* // Values that are passed in as props // are immediately available console.log(foo, bar); - - // function declarations cannot be set externally, - // but can be accessed from outside - export function instanceMethod() { - alert(foo); + + // Function expressions can also be props + export let format = (number) => (number.toFixed(2)); + + // 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 @@ -89,7 +92,7 @@ Because Svelte's reactivity is based on assignments, using array methods like `. --- -Any top-level statement (i.e. not inside a block or a function) can be made reactive by prefixing it with the `$:` label. Reactive statements run immediately before the component updates, whenever the values that they depend on have changed. +Any top-level statement (i.e. not inside a block or a function) can be made reactive by prefixing it with the `$:` [JS label syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label). Reactive statements run immediately before the component updates, whenever the values that they depend on have changed. ```html + + +``` ### Component events @@ -895,7 +913,138 @@ Local transitions only play when the block they belong to is created or destroye ### Animations -TODO i can't remember how any of this works +```sv +animate:name +``` + +```sv +animate:name={params} +``` + +```js +animation = (node: HTMLElement, { from: DOMRect, to: DOMRect } , params: any) => { + delay?: number, + duration?: number, + easing?: (t: number) => number, + css?: (t: number, u: number) => string, + tick?: (t: number, u: number) => void +} +``` + +```js +DOMRect { + bottom: number, + height: number, + ​​left: number, + right: number, + ​top: number, + width: number, + x: number, + y:number +} +``` + +--- + +An animation is triggered when the contents of a [keyed each block](docs#Each_blocks) are re-ordered. Animations do not run when an element is removed, only when the each block's data is reordered. Animate directives must be on an element that is an *immediate* child of a keyed each block. + +Animations can be used with Svelte's [built-in animation functions](docs#svelte_animate) or [custom animation functions](docs#Custom_animation_functions). + +```html + +{#each list as item, index (item)} +
  • {item}
  • +{/each} +``` + +#### Animation Parameters + +--- + +As with actions and transitions, animations can have parameters. + +(The double `{{curlies}}` aren't a special syntax; this is an object literal inside an expression tag.) + +```html +{#each list as item, index (item)} +
  • {item}
  • +{/each} +``` + +#### Custom animation functions + +--- + +Animations can use custom functions that provide the `node`, an `animation` object and any `paramaters` as arguments. The `animation` parameter is an object containing `from` and `to` properties each containing a [DOMRect](https://developer.mozilla.org/en-US/docs/Web/API/DOMRect#Properties) describing the geometry of the element in its `start` and `end` positions. The `from` property is the DOMRect of the element in its starting position, the `to` property is the DOMRect of the element in its final position after the list has been reordered and the DOM updated. + +If the returned object has a `css` method, Svelte will create a CSS animation that plays on the element. + +The `t` argument passed to `css` is a value that goes from `0` and `1` after the `easing` function has been applied. The `u` argument is equal to `1 - t`. + +The function is called repeatedly *before* the animation begins, with different `t` and `u` arguments. + + +```html + + +{#each list as item, index (item)} +
    {item}
    +{/each} +``` + +--- + + +A custom animation function can also return a `tick` function, which is called *during* the animation with the same `t` and `u` arguments. + +> If it's possible to use `css` instead of `tick`, do so — CSS animations can run off the main thread, preventing jank on slower devices. + +```html + + +{#each list as item, index (item)} +
    {item}
    +{/each} +``` + ### Slots @@ -1130,3 +1279,50 @@ The `` element provides a place to specify per-component compile ```html ``` + + +### @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 + + +{@debug user} + +

    Hello {user.firstname}!

    +``` + +--- + +`{@debug ...}` accepts a comma-separated list of variable names (not arbitrary expressions). + +```html + +{@debug user} +{@debug user1, user2, user3} + + +{@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. \ No newline at end of file diff --git a/site/content/docs/03-run-time.md b/site/content/docs/03-run-time.md index dfb270dc97..1beacc4169 100644 --- a/site/content/docs/03-run-time.md +++ b/site/content/docs/03-run-time.md @@ -324,13 +324,13 @@ const time = readable(new Date(), set => { store = derived(a, callback: (a: any) => any) ``` ```js -store = derived(a, callback: (a: any, set: (value: any) => void) => void, initial_value: any) +store = derived(a, callback: (a: any, set: (value: any) => void) => void | () => void, initial_value: any) ``` ```js store = derived([a, ...b], callback: ([a: any, ...b: any[]]) => any) ``` ```js -store = derived([a, ...b], callback: ([a: any, ...b: any[]], set: (value: any) => void) => void, initial_value: any) +store = derived([a, ...b], callback: ([a: any, ...b: any[]], set: (value: any) => void) => void | () => void, initial_value: any) ``` --- @@ -359,6 +359,20 @@ const delayed = derived(a, ($a, set) => { }, 'one moment...'); ``` +If you return a function from the callback, it will be called when a) the callback runs again, or b) the last subscriber unsubscribes: + +```js +import { derived } from 'svelte/store'; + +const tick = derived(frequency, ($frequency, set) => { + const interval = setInterval(() => set(Date.now()), 1000 / frequency); + + return () => { + clearInterval(interval); + } +}, 'one moment...'); +``` + --- In both cases, an array of arguments can be passed as the first argument instead of a single store. @@ -503,10 +517,204 @@ Both `set` and `update` can take a second argument — an object with `hard` or ### `svelte/transition` -TODO +The `svelte/transition` module exports six functions: `fade`, `fly`, `slide`, `scale`, `draw` and `crossfade`. They are for use with svelte [`transitions`](docs#Transitions). + +#### `fade` + +```sv +transition:fade={params} +``` +```sv +in:fade={params} +``` +```sv +out:fade={params} +``` + +--- + +Animates the opacity of an element from 0 to the current opacity for `in` transitions and from the current opacity to 0 for `out` transitions. + +`fade` accepts the following parameters: + +* `delay` (`number`, default 0) — milliseconds before starting +* `duration` (`number`, default 400) — milliseconds the transition lasts + +You can see the `fade` transition in action in the [transition tutorial](tutorial/transition). + +```html + + +{#if condition} +
    + fades in and out +
    +{/if} +``` + +#### `fly` + +```sv +transition:fly={params} +``` +```sv +in:fly={params} +``` +```sv +out:fly={params} +``` + +--- + +Animates the x and y positions and the opacity of an element. `in` transitions animate from an element's current (default) values to the provided values, passed as parameters. `out` transitions animate from the provided values to an element's default values. + +`fly` accepts the following parameters: + +* `delay` (`number`, default 0) — milliseconds before starting +* `duration` (`number`, default 400) — milliseconds the transition lasts +* `easing` (`function`, default `cubicOut`) — an [easing function](docs#svelte_easing) +* `x` (`number`, default 0) - the x offset to animate out to and in from +* `y` (`number`, default 0) - the y offset to animate out to and in from +* `opacity` (`number`, default 0) - the opacity value to animate out to and in from + +You can see the `fly` transition in action in the [transition tutorial](tutorial/adding-parameters-to-transitions). + +```html + + +{#if condition} +
    + flies in and out +
    +{/if} +``` + +#### `slide` + +```sv +transition:slide={params} +``` +```sv +in:slide={params} +``` +```sv +out:slide={params} +``` + +--- + +Slides an element in and out. + +`slide` accepts the following parameters: + +* `delay` (`number`, default 0) — milliseconds before starting +* `duration` (`number`, default 400) — milliseconds the transition lasts +* `easing` (`function`, default `cubicOut`) — an [easing function](docs#svelte_easing) + +```html + + +{#if condition} +
    + flies in and out +
    +{/if} +``` + +#### `scale` + +```sv +transition:scale={params} +``` +```sv +in:scale={params} +``` +```sv +out:scale={params} +``` + +--- + +Animates the opacity and scale of an element. `in` transitions animate from an element's current (default) values to the provided values, passed as parameters. `out` transitions animate from the provided values to an element's default values. + +`scale` accepts the following parameters: + +* `delay` (`number`, default 0) — milliseconds before starting +* `duration` (`number`, default 400) — milliseconds the transition lasts +* `easing` (`function`, default `cubicOut`) — an [easing function](docs#svelte_easing) +* `start` (`number`, default 0) - the scale value to animate out to and in from +* `opacity` (`number`, default 0) - the opacity value to animate out to and in from + +```html + + +{#if condition} +
    + scales in and out +
    +{/if} +``` + +#### `draw` + +```sv +transition:draw={params} +``` +```sv +in:draw={params} +``` +```sv +out:draw={params} +``` + +--- + +Animates the stroke of an SVG element, like a snake in a tube. `in` transitions begin with the path invisible and draw the path to the screen over time. `out` transitions start in a visible state and gradually erase the path. `draw` only works with elements that have a `getTotalLength` method, like `` and ``. + +`scale` accepts the following parameters: + +* `delay` (`number`, default 0) — milliseconds before starting +* `speed` (`number`, default undefined) - the speed of the animation, see below. +* `duration` (`number` | `function`, default 800) — milliseconds the transition lasts +* `easing` (`function`, default `cubicInOut`) — an [easing function](docs#svelte_easing) + +The `speed` parameter is a means of setting the duration of the transition relative to the path's length. It is modifier that is applied to the length of the path: `duration = length / speed`. A path that is 1000 pixels with a speed of 1 will have a duration of `1000ms`, setting the speed to `0.5` will halve that duration and setting it to `2` will double it. + +```html + + + + {#if condition} + + {/if} + + +``` + + + + -* fade, fly, slide, scale, draw -* crossfade... ### `svelte/animate` diff --git a/site/content/docs/04-compile-time.md b/site/content/docs/04-compile-time.md index b019b9437b..c219bae497 100644 --- a/site/content/docs/04-compile-time.md +++ b/site/content/docs/04-compile-time.md @@ -308,8 +308,8 @@ const { code } = svelte.preprocess(source, [ ```js walk(ast: Node, { - enter(node: Node, parent: Node)?: void, - leave(node: Node, parent: Node)?: void + enter(node: Node, parent: Node, prop: string, index: number)?: 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 const svelte = require('svelte/compiler'); svelte.walk(ast, { - enter(node, parent) { + enter(node, parent, prop, index) { do_something(node); if (should_skip_children(node)) { this.skip(); } }, - leave(node, parent) { + leave(node, parent, prop, index) { do_something_else(node); } }); diff --git a/site/content/examples/10-animations/00-animate/App.svelte b/site/content/examples/10-animations/00-animate/App.svelte index c46096c204..faba1dd062 100644 --- a/site/content/examples/10-animations/00-animate/App.svelte +++ b/site/content/examples/10-animations/00-animate/App.svelte @@ -1,8 +1,9 @@
    - +

    todo

    @@ -122,6 +117,7 @@
    -
    \ No newline at end of file + diff --git a/site/content/examples/10-animations/00-animate/crossfade.js b/site/content/examples/10-animations/00-animate/crossfade.js deleted file mode 100644 index e11e18b60e..0000000000 --- a/site/content/examples/10-animations/00-animate/crossfade.js +++ /dev/null @@ -1,65 +0,0 @@ -import { quintOut } from 'svelte/easing'; - -export default function crossfade({ send, receive, fallback }) { - let requested = new Map(); - let provided = new Map(); - - function crossfade(from, node) { - const to = node.getBoundingClientRect(); - const dx = from.left - to.left; - const dy = from.top - to.top; - - const style = getComputedStyle(node); - const transform = style.transform === 'none' ? '' : style.transform; - - return { - duration: 400, - easing: quintOut, - css: (t, u) => ` - opacity: ${t}; - transform: ${transform} translate(${u * dx}px,${u * dy}px); - ` - }; - } - - return { - send(node, params) { - provided.set(params.key, { - rect: node.getBoundingClientRect() - }); - - return () => { - if (requested.has(params.key)) { - const { rect } = requested.get(params.key); - requested.delete(params.key); - - return crossfade(rect, node); - } - - // if the node is disappearing altogether - // (i.e. wasn't claimed by the other list) - // then we need to supply an outro - provided.delete(params.key); - return fallback(node, params); - }; - }, - - receive(node, params) { - requested.set(params.key, { - rect: node.getBoundingClientRect() - }); - - return () => { - if (provided.has(params.key)) { - const { rect } = provided.get(params.key); - provided.delete(params.key); - - return crossfade(rect, node); - } - - requested.delete(params.key); - return fallback(node, params); - }; - } - }; -} \ No newline at end of file diff --git a/site/content/examples/19-7guis/05-7guis-crud/App.svelte b/site/content/examples/19-7guis/05-7guis-crud/App.svelte index 1f39fe6642..a0d6ef7f3e 100644 --- a/site/content/examples/19-7guis/05-7guis-crud/App.svelte +++ b/site/content/examples/19-7guis/05-7guis-crud/App.svelte @@ -30,10 +30,7 @@ $: selected = filteredPeople[i]; - $: { - first = selected ? selected.first : ''; - last = selected ? selected.last : ''; - } + $: reset_inputs(selected); function create() { people = people.concat({ first, last }); @@ -53,7 +50,8 @@ } function reset_inputs(person) { - ({ first, last } = person); + first = person ? person.first : ''; + last = person ? person.last : ''; } diff --git a/site/content/examples/20-miscellaneous/02-immutable-data/flash.js b/site/content/examples/20-miscellaneous/02-immutable-data/flash.js index 8dff9cbe2f..c788cc6d35 100644 --- a/site/content/examples/20-miscellaneous/02-immutable-data/flash.js +++ b/site/content/examples/20-miscellaneous/02-immutable-data/flash.js @@ -1,11 +1,13 @@ export default function flash(element) { - element.style.transition = 'none'; - element.style.color = 'rgba(255,62,0,1)'; - element.style.backgroundColor = 'rgba(255,62,0,0.2)'; + requestAnimationFrame(() => { + element.style.transition = 'none'; + element.style.color = 'rgba(255,62,0,1)'; + element.style.backgroundColor = 'rgba(255,62,0,0.2)'; - setTimeout(() => { - element.style.transition = 'color 1s, background 1s'; - element.style.color = ''; - element.style.backgroundColor = ''; + setTimeout(() => { + element.style.transition = 'color 1s, background 1s'; + element.style.color = ''; + element.style.backgroundColor = ''; + }); }); } \ No newline at end of file diff --git a/site/content/tutorial/01-introduction/03-dynamic-attributes/text.md b/site/content/tutorial/01-introduction/03-dynamic-attributes/text.md index 6deaad5837..1fd6774b8a 100644 --- a/site/content/tutorial/01-introduction/03-dynamic-attributes/text.md +++ b/site/content/tutorial/01-introduction/03-dynamic-attributes/text.md @@ -16,7 +16,7 @@ That's better. But Svelte is giving us a warning: When building web apps, it's important to make sure that they're *accessible* to the broadest possible userbase, including people with (for example) impaired vision or motion, or people without powerful hardware or good internet connections. Accessibility (shortened to a11y) isn't always easy to get right, but Svelte will help by warning you if you write inaccessible markup. -In this case, we're missing the `alt` tag that describes the image for people using screenreaders, or people with slow or flaky internet connections that can't download the image. Let's add one: +In this case, we're missing the `alt` attribute that describes the image for people using screenreaders, or people with slow or flaky internet connections that can't download the image. Let's add one: ```html A man dancing diff --git a/site/content/tutorial/06-bindings/01-text-inputs/text.md b/site/content/tutorial/06-bindings/01-text-inputs/text.md index 0082586133..7bcbc96fa6 100644 --- a/site/content/tutorial/06-bindings/01-text-inputs/text.md +++ b/site/content/tutorial/06-bindings/01-text-inputs/text.md @@ -4,7 +4,7 @@ title: Text inputs As a general rule, data flow in Svelte is *top down* — a parent component can set props on a child component, and a component can set attributes on an element, but not the other way around. -Sometimes it's useful to break that rule. Take the case of the `` element in this component — we *could* add an `on:input` event handler that set the value of `name` to `event.target.value`, but it's a bit... boilerplatey. It gets even worse with other kinds of form element, as we'll see. +Sometimes it's useful to break that rule. Take the case of the `` element in this component — we *could* add an `on:input` event handler that set the value of `name` to `event.target.value`, but it's a bit... boilerplatey. It gets even worse with other form elements, as we'll see. Instead, we can use the `bind:value` directive: @@ -12,4 +12,4 @@ Instead, we can use the `bind:value` directive: ``` -This means that not only will changes to the value of `name` update the input value, but changes to the input value will update `name`. \ No newline at end of file +This means that not only will changes to the value of `name` update the input value, but changes to the input value will update `name`. diff --git a/site/content/tutorial/10-transitions/03-in-and-out/text.md b/site/content/tutorial/10-transitions/03-in-and-out/text.md index 21cb221342..1f1ac2c80b 100644 --- a/site/content/tutorial/10-transitions/03-in-and-out/text.md +++ b/site/content/tutorial/10-transitions/03-in-and-out/text.md @@ -2,7 +2,13 @@ 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

    diff --git a/site/content/tutorial/12-actions/01-actions/text.md b/site/content/tutorial/12-actions/01-actions/text.md index 279dc3123f..38de8f9a65 100644 --- a/site/content/tutorial/12-actions/01-actions/text.md +++ b/site/content/tutorial/12-actions/01-actions/text.md @@ -27,7 +27,7 @@ import { pannable } from './pannable.js'; > ``` -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: @@ -84,4 +84,3 @@ export function pannable(node) { 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. - diff --git a/site/content/tutorial/16-special-elements/07-svelte-options/app-a/flash.js b/site/content/tutorial/16-special-elements/07-svelte-options/app-a/flash.js index 8dff9cbe2f..c788cc6d35 100644 --- a/site/content/tutorial/16-special-elements/07-svelte-options/app-a/flash.js +++ b/site/content/tutorial/16-special-elements/07-svelte-options/app-a/flash.js @@ -1,11 +1,13 @@ export default function flash(element) { - element.style.transition = 'none'; - element.style.color = 'rgba(255,62,0,1)'; - element.style.backgroundColor = 'rgba(255,62,0,0.2)'; + requestAnimationFrame(() => { + element.style.transition = 'none'; + element.style.color = 'rgba(255,62,0,1)'; + element.style.backgroundColor = 'rgba(255,62,0,0.2)'; - setTimeout(() => { - element.style.transition = 'color 1s, background 1s'; - element.style.color = ''; - element.style.backgroundColor = ''; + setTimeout(() => { + element.style.transition = 'color 1s, background 1s'; + element.style.color = ''; + element.style.backgroundColor = ''; + }); }); } \ No newline at end of file diff --git a/site/content/tutorial/16-special-elements/07-svelte-options/app-b/flash.js b/site/content/tutorial/16-special-elements/07-svelte-options/app-b/flash.js index 8dff9cbe2f..c788cc6d35 100644 --- a/site/content/tutorial/16-special-elements/07-svelte-options/app-b/flash.js +++ b/site/content/tutorial/16-special-elements/07-svelte-options/app-b/flash.js @@ -1,11 +1,13 @@ export default function flash(element) { - element.style.transition = 'none'; - element.style.color = 'rgba(255,62,0,1)'; - element.style.backgroundColor = 'rgba(255,62,0,0.2)'; + requestAnimationFrame(() => { + element.style.transition = 'none'; + element.style.color = 'rgba(255,62,0,1)'; + element.style.backgroundColor = 'rgba(255,62,0,0.2)'; - setTimeout(() => { - element.style.transition = 'color 1s, background 1s'; - element.style.color = ''; - element.style.backgroundColor = ''; + setTimeout(() => { + element.style.transition = 'color 1s, background 1s'; + element.style.color = ''; + element.style.backgroundColor = ''; + }); }); } \ No newline at end of file diff --git a/site/package-lock.json b/site/package-lock.json index b0899b1779..b61cee722e 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -33,23 +33,6 @@ "resolve": "^1.3.2", "semver": "^5.4.1", "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": { @@ -808,23 +791,6 @@ "debug": "^4.1.0", "globals": "^11.1.0", "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": { @@ -1366,14 +1332,14 @@ "integrity": "sha512-ym6ooqMr09+cV+y52p5kszJ0jYcX+nJfm8POrQb7QYowvpPPuneZ71EclHrQSB7a50lcytgR/xtL6AUFdvyEkg==" }, "@polka/send": { - "version": "1.0.0-next.2", - "resolved": "https://registry.npmjs.org/@polka/send/-/send-1.0.0-next.2.tgz", - "integrity": "sha512-eq8gUzykpYPuOMrnyAzsL4KunhQXZKFiNsbThAwh19PrBAz2v8mECsj3YnxjYYifbB1w1vhR74nsXQWDi80oAg==" + "version": "1.0.0-next.3", + "resolved": "https://registry.npmjs.org/@polka/send/-/send-1.0.0-next.3.tgz", + "integrity": "sha512-54ftOGSZQMx8Xh8pnPgAj4499wppAEHQ892A7WacYOJ7ySuCWVgFmpODmXC2hU7qD9Scbi0iAu8rZls3ld+Eyg==" }, "@polka/url": { - "version": "1.0.0-next.1", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.1.tgz", - "integrity": "sha512-6d8YbKW4hjJMnU6ZJSDLtALWiB4J//OIPaP885ruf5U8MLZHigocDxhjgvLwbV6bGkikhllgTjD9eWioKWAQdA==" + "version": "1.0.0-next.3", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.3.tgz", + "integrity": "sha512-Uom7l6OeP6vcf85lMImelYu5WKVWjXyhkpi9WsRdRzlJFJFPVhjBtBCktgDUj7dk1N5FURUdegSZ5XOjxf8JZg==" }, "@sindresorhus/slugify": { "version": "0.9.1", @@ -1396,9 +1362,9 @@ } }, "@sveltejs/svelte-repl": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.0.10.tgz", - "integrity": "sha512-PYXCN8OC2q3WzwtMcbFinLGzFI7RlD3cHqjkUuQWDaIMHriKYuALun4H/FxP8w3B3hNe9OBprgGmBzlkPuGEJw==", + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.0.11.tgz", + "integrity": "sha512-F284f8qaUs1rp8akqWXcB6oovlaso7qmsUz1rqm80FwUKLffjYIWy2a1p6+Yo1kRy6Q+fW8kj21JLEqv7pjOwA==", "dev": true, "requires": { "codemirror": "^5.45.0", @@ -1412,9 +1378,9 @@ "dev": true }, "@types/node": { - "version": "11.13.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.8.tgz", - "integrity": "sha512-szA3x/3miL90ZJxUCzx9haNbK5/zmPieGraZEe4WI+3srN0eGLiT22NXeMHmyhNEopn+IrxqMc7wdVwvPl8meg==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.2.tgz", + "integrity": "sha512-5tabW/i+9mhrfEOUcLDu2xBPsHJ+X5Orqy9FKpale3SjDA17j5AEpYq5vfy3oAeAHGcvANRCO3NV3d2D6q3NiA==", "dev": true }, "@types/pg": { @@ -1660,14 +1626,14 @@ "dev": true }, "browserslist": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.6.tgz", - "integrity": "sha512-o/hPOtbU9oX507lIqon+UvPYqpx3mHc8cV3QemSBTXwkG8gSQSK6UKvXcE/DcleU3+A59XTUHyCvZ5qGy8xVAg==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.0.tgz", + "integrity": "sha512-Jk0YFwXBuMOOol8n6FhgkDzn3mY9PYLYGk29zybF05SbRTsMgPqmTNeQQhOghCxq5oFqAXE3u4sYddr4C0uRhg==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000963", - "electron-to-chromium": "^1.3.127", - "node-releases": "^1.1.17" + "caniuse-lite": "^1.0.30000967", + "electron-to-chromium": "^1.3.133", + "node-releases": "^1.1.19" } }, "buffer": { @@ -1742,9 +1708,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30000963", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000963.tgz", - "integrity": "sha512-n4HUiullc7Lw0LyzpeLa2ffP8KxFBGdxqD/8G3bSL6oB758hZ2UE2CVK+tQN958tJIi0/tfpjAc67aAtoHgnrQ==", + "version": "1.0.30000967", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000967.tgz", + "integrity": "sha512-rUBIbap+VJfxTzrM4akJ00lkvVb5/n5v3EGXfWzSH5zT8aJmGzjA8HWhJ4U6kCpzxozUSnB+yvAYDRPY6mRpgQ==", "dev": true }, "chalk": { @@ -1970,12 +1936,12 @@ } }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "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.0.0" + "ms": "^2.1.1" } }, "decamelize": { @@ -2096,9 +2062,9 @@ } }, "electron-to-chromium": { - "version": "1.3.129", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.129.tgz", - "integrity": "sha512-puirJsgZnedlFEmRa7WEUIaS8ZgHHn7d7inph+RiapCc0x80hdoDyEEpR9z3aRUSZy4fGxOTOFcxnGmySlrmhA==", + "version": "1.3.134", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.134.tgz", + "integrity": "sha512-C3uK2SrtWg/gSWaluLHWSHjyebVZCe4ZC0NVgTAoTq8tCR9FareRK5T7R7AS/nPZShtlEcjVMX1kQ8wi4nU68w==", "dev": true }, "emoji-regex": { @@ -2157,9 +2123,9 @@ "dev": true }, "eslint-plugin-svelte3": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte3/-/eslint-plugin-svelte3-1.0.0.tgz", - "integrity": "sha512-lsKUKPrzsjB4JAwmGhfg/Xssc/+L4KU8oL5WNZ0q/D3DkYkIVE4XpT/j8TY6oEFLd31Sznm7itw8Q7RsK6g0cA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-svelte3/-/eslint-plugin-svelte3-1.2.0.tgz", + "integrity": "sha512-7tuYh8YdwE9PP96U9qNJUSVMaxxUS/HZEZtEDlNGSAe0g40xd12pJo6lrc5wGxOmXpR6adGy5DnkSSF1UXGDKg==", "dev": true }, "esm": { @@ -2222,6 +2188,15 @@ "to-regex": "^3.0.1" }, "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": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", @@ -2239,6 +2214,12 @@ "requires": { "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, "requires": { "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": { @@ -2408,9 +2381,9 @@ } }, "fs-minipass": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.6.tgz", + "integrity": "sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==", "dev": true, "requires": { "minipass": "^2.2.1" @@ -2450,9 +2423,9 @@ "dev": true }, "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -2547,6 +2520,12 @@ "kind-of": "^4.0.0" }, "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": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", @@ -2577,26 +2556,18 @@ "dev": true }, "html-minifier": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", - "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", - "dev": true, - "requires": { - "camel-case": "3.0.x", - "clean-css": "4.2.x", - "commander": "2.17.x", - "he": "1.2.x", - "param-case": "2.1.x", - "relateurl": "0.2.x", - "uglify-js": "3.4.x" - }, - "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 - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz", + "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==", + "dev": true, + "requires": { + "camel-case": "^3.0.0", + "clean-css": "^4.2.1", + "commander": "^2.19.0", + "he": "^1.2.0", + "param-case": "^2.1.1", + "relateurl": "^0.2.7", + "uglify-js": "^3.5.1" } }, "http-link-header": { @@ -2606,9 +2577,9 @@ "dev": true }, "httpie": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/httpie/-/httpie-1.1.1.tgz", - "integrity": "sha512-KYgUXOhxVPo5mYuFPqnKW14fP5goMGkLc9CRz0WD6b1TCED9nl9wzj4jqr+8LY+AhPJQ/LdCQLRfF2JrBEja5Q==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/httpie/-/httpie-1.1.2.tgz", + "integrity": "sha512-VQ82oXG95oY1fQw/XecHuvcFBA+lZQ9Vwj1RfLcO8a7HpDd4cc2ukwpJt+TUlFaLUAzZErylxWu6wclJ1rUhUQ==" }, "ieee754": { "version": "1.1.13", @@ -2662,6 +2633,12 @@ "kind-of": "^3.0.2" }, "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": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -2680,9 +2657,9 @@ "dev": true }, "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", "dev": true }, "is-callable": { @@ -2700,6 +2677,12 @@ "kind-of": "^3.0.2" }, "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": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -2769,6 +2752,12 @@ "kind-of": "^3.0.2" }, "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": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -2949,13 +2938,6 @@ "lodash.once": "^4.0.0", "ms": "^2.1.1", "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": { @@ -3195,9 +3177,9 @@ } }, "mime": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.2.tgz", - "integrity": "sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg==" + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.3.tgz", + "integrity": "sha512-QgrPRJfE+riq5TPZMcHZOtm8c6K/yYrMbKIoRfapfiGLxS8OTeIfRhUGW5LU7MlRa52KOAGCfUNruqLrIBvWZw==" }, "mimic-fn": { "version": "2.1.0", @@ -3326,11 +3308,19 @@ "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 + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "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": { "version": "6.0.0", @@ -3356,10 +3346,9 @@ "dev": true }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" }, "nanomatch": { "version": "1.2.13", @@ -3412,9 +3401,9 @@ "dev": true }, "node-pg-migrate": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/node-pg-migrate/-/node-pg-migrate-3.19.0.tgz", - "integrity": "sha512-IIiiP6oHR9JDOqlIpaRFTnIedPIMXsYiMOkCPCSCGA2e+ZuDn/VS07CbDwVwKA+sBfwR0g5KIBx7QZGAS6sesQ==", + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/node-pg-migrate/-/node-pg-migrate-3.20.0.tgz", + "integrity": "sha512-7crNxFNueGgLVYw74FIi0MFowbXlVVpK2ZVM0RvJkhlA0da0Gt+pLmQYFkAuCl2cdfcvK72yUEvtXiw0Uei5CQ==", "dev": true, "requires": { "@types/pg": "^7.4.0", @@ -3426,9 +3415,9 @@ } }, "node-releases": { - "version": "1.1.17", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.17.tgz", - "integrity": "sha512-/SCjetyta1m7YXLgtACZGDYJdCSIBAWorDWkGCGZlydP2Ll7J48l7j/JxNYZ+xsgSPbWfdulVS/aY+GdjUsQ7Q==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.19.tgz", + "integrity": "sha512-SH/B4WwovHbulIALsQllAVwqZZD1kPmKCqrhGfR29dXjLAVZMHvBjD3S6nL9D/J9QkmZ1R92/0wCMDKXUUvyyA==", "dev": true, "requires": { "semver": "^5.3.0" @@ -3498,6 +3487,12 @@ "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": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -3725,9 +3720,9 @@ } }, "pg": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-7.10.0.tgz", - "integrity": "sha512-aE6FZomsyn3OeGv1oM50v7Xu5zR75c15LXdOCwA9GGrfjXsQjzwYpbcTS6OwEMhYfZQS6m/FVU/ilPLiPzJDCw==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-7.11.0.tgz", + "integrity": "sha512-YO4V7vCmEMGoF390LJaFaohWNKaA2ayoQOEZmiHVcAUF+YsRThpf/TaKCgSvsSE7cDm37Q/Cy3Gz41xiX/XjTw==", "requires": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", @@ -3814,12 +3809,12 @@ "dev": true }, "polka": { - "version": "1.0.0-next.2", - "resolved": "https://registry.npmjs.org/polka/-/polka-1.0.0-next.2.tgz", - "integrity": "sha512-y82w42/8IA7bc4YwGwAmnbrXj8ZWWDGvnfwq1b0eCtFielZSSSJv7OXUIKQuc/vw5OCCM1hPIgrYsNPzbwDaJw==", + "version": "1.0.0-next.3", + "resolved": "https://registry.npmjs.org/polka/-/polka-1.0.0-next.3.tgz", + "integrity": "sha512-VmCsJK2uAqyjtV8e6ujEhgehibh+lvgdlrIgkTGsL+EKrCS/+BmGq57NV7yvkeGKI4XhsCw/J1YSeejmNfhbig==", "requires": { - "@polka/url": "^1.0.0-next.1", - "trouter": "^3.0.1" + "@polka/url": "^1.0.0-next.3", + "trouter": "^3.0.2" } }, "posix-character-classes": { @@ -3929,9 +3924,9 @@ "dev": true }, "regenerate-unicode-properties": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.0.2.tgz", - "integrity": "sha512-SbA/iNrBUf6Pv2zU8Ekv1Qbhv92yxL4hiDa2siuxs4KKn4oOoMDHXjAf7+Nz9qinUQ46B1LcWEi/PhJfPWpZWQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", + "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", "dev": true, "requires": { "regenerate": "^1.4.0" @@ -4047,9 +4042,9 @@ "dev": true }, "resolve": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz", - "integrity": "sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", + "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -4077,9 +4072,9 @@ } }, "rollup": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.11.2.tgz", - "integrity": "sha512-H5sS7GZ/Rn0t119Et8mw0QXtg5HTOI/1FL57EKHk5oduRmGaraOf3KcEt6j+dXJ9tXxWQkG+/FBjPS4dzxo6EA==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.11.3.tgz", + "integrity": "sha512-81MR7alHcFKxgWzGfG7jSdv+JQxSOIOD/Fa3iNUmpzbd7p+V19e1l9uffqT8/7YAHgGOzmoPGN3Fx3L2ptOf5g==", "dev": true, "requires": { "@types/estree": "0.0.39", @@ -4127,9 +4122,9 @@ } }, "rollup-plugin-node-resolve": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-4.2.3.tgz", - "integrity": "sha512-r+WaesPzdGEynpLZLALFEDugA4ACa5zn7bc/+LVX4vAXQQ8IgDHv0xfsSvJ8tDXUtprfBtrDtRFg27ifKjcJTg==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-4.2.4.tgz", + "integrity": "sha512-t/64I6l7fZ9BxqD3XlX4ZeO6+5RLKyfpwE2CiPNUKa+GocPlQhf/C208ou8y3AwtNsc6bjSk/8/6y/YAyxCIvw==", "dev": true, "requires": { "@types/resolve": "0.0.8", @@ -4172,9 +4167,9 @@ } }, "rollup-pluginutils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.6.0.tgz", - "integrity": "sha512-aGQwspEF8oPKvg37u3p7h0cYNwmJR1sCBMZGZ5b9qy8HGtETknqjzcxrDRrcAnJNXN18lBH4Q9vZYth/p4n8jQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.7.0.tgz", + "integrity": "sha512-FoP6L1YnMYTAR06Dpq5LE3jJtMwPE6H4VEOqFU23yoziZnqNRSiWcVy6YgEY5PdQB4G7278+8c4TvB0JKS1csA==", "dev": true, "requires": { "estree-walker": "^0.6.0", @@ -4207,24 +4202,16 @@ } }, "sapper": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/sapper/-/sapper-0.26.0.tgz", - "integrity": "sha512-KdouvzoCeCLirGwlf6U1KwT8GDTFNtK9KEQRFV8bQvNJQzwqS7+QyPAK8Z2MnR7gamluo+bDx84cTtnHD9I/mQ==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/sapper/-/sapper-0.27.1.tgz", + "integrity": "sha512-RH0K1uQ3zJ1IXvowxr2SuboGXV69q22KaPMhhoM5VNDv9fsUlVHtluZE8WTcGxckiO2L1xFfgM7v/aINkSZpcw==", "dev": true, "requires": { - "html-minifier": "^3.5.21", + "html-minifier": "^4.0.0", "http-link-header": "^1.0.2", "shimport": "^1.0.0", "sourcemap-codec": "^1.4.4", "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": { @@ -4317,6 +4304,12 @@ "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": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -4324,9 +4317,9 @@ "dev": true }, "sirv": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-0.4.0.tgz", - "integrity": "sha512-k/dcRW7Ry2VgERDiLyyq3peGZEnqP2EcTcG5646QjoLwz7lnDA50i20m/3Rn7J4FLtimyoKQsG4E2BItctwjhg==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-0.4.2.tgz", + "integrity": "sha512-dQbZnsMaIiTQPZmbGmktz+c74zt/hyrJEB4tdp2Jj0RNv9J6B/OWR5RyrZEvIn9fyh9Zlg2OlE2XzKz6wMKGAw==", "requires": { "@polka/url": "^0.5.0", "mime": "^2.3.1" @@ -4355,6 +4348,15 @@ "use": "^3.1.0" }, "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": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", @@ -4372,6 +4374,12 @@ "requires": { "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" }, "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": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -4655,9 +4669,9 @@ } }, "svelte": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.2.0.tgz", - "integrity": "sha512-i/FSWUcqVw9JBo9bY69/ZI89WCCpyhdWjvAroOroI4qnQboh0WGlgjnFOEKOTvlv1XONd8cVpRGbOYYE3Ec6TQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.3.0.tgz", + "integrity": "sha512-iJYkIJDvAak1kizEYnE4b4eJ17D25fU0adW7GjDgO0klbjcAFlqtWEGFJa9kpJOlUtNLilcF09k4Y9TDmK/vjg==", "dev": true }, "tar": { @@ -4732,6 +4746,12 @@ "kind-of": "^3.0.2" }, "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": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -4772,29 +4792,23 @@ "dev": true }, "trouter": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trouter/-/trouter-3.0.1.tgz", - "integrity": "sha512-9IBGrlL5bW65xhWufCCf4AsZyxGVIxv7Jy+PTwNtfPHJo+8hAp4wvt/+ersAHE//0Lgjy7obPROfgasNocoYuA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/trouter/-/trouter-3.0.2.tgz", + "integrity": "sha512-wzUcM3oKmF8Fx5pd+3IxZj5LBugqW+hSQHm6cTHkpiZHL8w6YeZSzo3LPw0UdhlwaGPms3OxT7N4GEOIRTw+jw==", "requires": { "regexparam": "^1.2.0" } }, "uglify-js": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", - "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.14.tgz", + "integrity": "sha512-dgyjIw8KFK6AyVl5vm2tEqPewv5TKGEiiVFLI1LbF+oHua/Njd8tZk3lIbF1AWU1rNdEg7scaceADb4zqCcWXg==", "dev": true, "requires": { - "commander": "~2.19.0", + "commander": "~2.20.0", "source-map": "~0.6.1" }, "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": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", diff --git a/site/package.json b/site/package.json index cc593634da..d9de5a217e 100644 --- a/site/package.json +++ b/site/package.json @@ -12,7 +12,8 @@ "cy:run": "cypress run", "cy:open": "cypress open", "test": "run-p --race dev cy:run", - "testsrc": "mocha -r esm test/**" + "testsrc": "mocha -r esm test/**", + "deploy": "make deploy" }, "dependencies": { "@polka/redirect": "^1.0.0-next.0", @@ -37,7 +38,7 @@ "@babel/runtime": "^7.4.4", "@sindresorhus/slugify": "^0.9.1", "@sveltejs/site-kit": "^1.0.4", - "@sveltejs/svelte-repl": "0.0.10", + "@sveltejs/svelte-repl": "0.0.11", "degit": "^2.1.3", "dotenv": "^8.0.0", "eslint-plugin-svelte3": "^1.0.0", @@ -47,7 +48,7 @@ "node-fetch": "^2.3.0", "node-pg-migrate": "^3.18.1", "npm-run-all": "^4.1.5", - "rollup": "^1.11.2", + "rollup": "^1.11.3", "rollup-plugin-babel": "^4.3.2", "rollup-plugin-commonjs": "^9.3.4", "rollup-plugin-json": "^4.0.0", @@ -55,7 +56,7 @@ "rollup-plugin-replace": "^2.2.0", "rollup-plugin-svelte": "^5.0.3", "rollup-plugin-terser": "^4.0.4", - "sapper": "^0.26.0", + "sapper": "^0.27.1", "shelljs": "^0.8.3", "svelte": "^3.0.0" }, diff --git a/site/scripts/build-svelte-app-json.js b/site/scripts/build-svelte-app-json.js deleted file mode 100644 index 59a4b4a07b..0000000000 --- a/site/scripts/build-svelte-app-json.js +++ /dev/null @@ -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)); diff --git a/site/scripts/update_template.js b/site/scripts/update_template.js index 814d402f5e..9d897c064f 100644 --- a/site/scripts/update_template.js +++ b/site/scripts/update_template.js @@ -1,7 +1,7 @@ const sh = require('shelljs'); const fs = require('fs'); -sh.cd(__dirname+'/../'); +sh.cd(__dirname + '/../'); // fetch svelte app sh.rm('-rf','scripts/svelte-app'); @@ -16,7 +16,10 @@ const appPath = 'scripts/svelte-app'; const files = []; 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)); \ No newline at end of file diff --git a/site/src/routes/_components/WhosUsingSvelte.svelte b/site/src/routes/_components/WhosUsingSvelte.svelte index 1700312055..65d818a8bb 100644 --- a/site/src/routes/_components/WhosUsingSvelte.svelte +++ b/site/src/routes/_components/WhosUsingSvelte.svelte @@ -54,5 +54,7 @@ The New York Times logo Razorpay logo Stone Payments logo + Thunderdome logo + Tokopedia logo + your company? diff --git a/site/src/routes/faq.js b/site/src/routes/faq.js new file mode 100644 index 0000000000..6263494a4c --- /dev/null +++ b/site/src/routes/faq.js @@ -0,0 +1,4 @@ +export function get(req, res) { + res.writeHead(302, { Location: 'https://github.com/sveltejs/svelte/wiki/FAQ' }); + res.end(); +} \ No newline at end of file diff --git a/site/src/routes/index.svelte b/site/src/routes/index.svelte index 539f522b4e..cbbdf43e95 100644 --- a/site/src/routes/index.svelte +++ b/site/src/routes/index.svelte @@ -89,7 +89,7 @@ npx degit sveltejs/template my-svelte-project cd my-svelte-project npm install -npm run dev & open http://localhost:5000 +npm run dev

    See the quickstart guide for more information.

    diff --git a/site/static/organisations/thunderdome.svg b/site/static/organisations/thunderdome.svg new file mode 100644 index 0000000000..c8cbdaf039 --- /dev/null +++ b/site/static/organisations/thunderdome.svg @@ -0,0 +1,154 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/site/static/organisations/tokopedia.png b/site/static/organisations/tokopedia.png new file mode 100644 index 0000000000..bc5231cd5a Binary files /dev/null and b/site/static/organisations/tokopedia.png differ diff --git a/animate.mjs b/src/animate.ts similarity index 86% rename from animate.mjs rename to src/animate.ts index f22fabe401..cf64cd060a 100644 --- a/animate.mjs +++ b/src/animate.ts @@ -1,5 +1,5 @@ -import { cubicOut } from './easing'; -import { is_function } from './internal'; +import { cubicOut } from 'svelte/easing'; +import { is_function } from 'svelte/internal'; export function flip(node, animation, params) { const style = getComputedStyle(node); @@ -22,4 +22,4 @@ export function flip(node, animation, params) { easing, css: (t, u) => `transform: ${transform} translate(${u * dx}px, ${u * dy}px);` }; -} \ No newline at end of file +} diff --git a/src/compile/Component.ts b/src/compile/Component.ts index aad5e98413..a8145e6b2c 100644 --- a/src/compile/Component.ts +++ b/src/compile/Component.ts @@ -1,4 +1,5 @@ import MagicString, { Bundle } from 'magic-string'; +// @ts-ignore import { walk, childKeys } from 'estree-walker'; import { getLocator } from 'locate-character'; import Stats from '../Stats'; @@ -21,6 +22,7 @@ import { remove_indentation, add_indentation } from '../utils/indentation'; import get_object from './utils/get_object'; import unwrap_parens from './utils/unwrap_parens'; import Slot from './nodes/Slot'; +import { Node as ESTreeNode } from 'estree'; type ComponentOptions = { namespace?: string; @@ -152,10 +154,14 @@ export default class Component { this.namespace = namespaces[this.component_options.namespace] || this.component_options.namespace; if (compile_options.customElement) { - this.tag = this.component_options.tag || compile_options.tag; - if (!this.tag) { - throw new Error(`Cannot compile to a custom element without specifying a tag name via options.tag or `); + if (this.component_options.tag === undefined && compile_options.tag === undefined) { + const svelteOptions = ast.html.children.find(child => child.name === 'svelte:options') || { start: 0, end: 0 }; + this.warn(svelteOptions, { + code: 'custom-element-no-tag', + message: `No custom element 'tag' option was specified. To automatically register a custom element, specify a name with a hyphen in it, e.g. . To hide this warning, use ` + }); } + this.tag = this.component_options.tag || compile_options.tag; } else { this.tag = this.name; } @@ -754,12 +760,12 @@ export default class Component { }); } - if (is_reference(node, parent)) { + if (is_reference(node as ESTreeNode, parent as ESTreeNode)) { const object = get_object(node); const { name } = object; if (name[0] === '$' && !scope.has(name)) { - component.warn_if_undefined(object, null); + component.warn_if_undefined(name, object, null); } } }, @@ -772,7 +778,7 @@ export default class Component { }); } - invalidate(name, value) { + invalidate(name, value?) { const variable = this.var_lookup.get(name); if (variable && (variable.subscribable && variable.reassigned)) { @@ -1018,7 +1024,7 @@ export default class Component { scope = map.get(node); } - if (is_reference(node, parent)) { + if (is_reference(node as ESTreeNode, parent as ESTreeNode)) { const { name } = flatten_reference(node); const owner = scope.find_owner(name); @@ -1109,14 +1115,16 @@ export default class Component { } else if (node.type === 'UpdateExpression') { const identifier = get_object(node.argument); 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); if (!assignee_nodes.has(identifier)) { const { name } = identifier; 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 ( (!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); } @@ -1202,9 +1210,7 @@ export default class Component { return `ctx.${name}`; } - warn_if_undefined(node, template_scope: TemplateScope) { - let { name } = node; - + warn_if_undefined(name: string, node, template_scope: TemplateScope) { if (name[0] === '$') { name = name.slice(1); this.has_reactive_assignments = true; // TODO does this belong here? @@ -1267,9 +1273,9 @@ function process_component_options(component: Component, nodes) { const message = `'tag' must be a string literal`; 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, { code: `invalid-tag-property`, message: `tag name must be two or more words joined by the '-' character` diff --git a/src/compile/index.ts b/src/compile/index.ts index e80a937932..dac75f23e0 100644 --- a/src/compile/index.ts +++ b/src/compile/index.ts @@ -1,4 +1,4 @@ -import { assign } from '../internal'; +import { assign } from '../internal/index'; import Stats from '../Stats'; import parse from '../parse/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; const parts = filename.split(/[\/\\]/); @@ -105,4 +105,4 @@ export default function compile(source: string, options: CompileOptions = {}) { : render_dom(component, options); return component.generate(js); -} \ No newline at end of file +} diff --git a/src/compile/nodes/Action.ts b/src/compile/nodes/Action.ts index feec3fada8..77b9e3c846 100644 --- a/src/compile/nodes/Action.ts +++ b/src/compile/nodes/Action.ts @@ -11,7 +11,7 @@ export default class Action extends Node { constructor(component: Component, parent, scope, info) { super(component, parent, scope, info); - component.warn_if_undefined(info, scope); + component.warn_if_undefined(info.name, info, scope); this.name = info.name; component.qualify(info.name); diff --git a/src/compile/nodes/Animation.ts b/src/compile/nodes/Animation.ts index 638a88b169..6ccdbb0803 100644 --- a/src/compile/nodes/Animation.ts +++ b/src/compile/nodes/Animation.ts @@ -10,7 +10,7 @@ export default class Animation extends Node { constructor(component: Component, parent, scope, info) { super(component, parent, scope, info); - component.warn_if_undefined(info, scope); + component.warn_if_undefined(info.name, info, scope); this.name = info.name; component.qualify(info.name); diff --git a/src/compile/nodes/Attribute.ts b/src/compile/nodes/Attribute.ts index c07960ce47..0b2d3a3700 100644 --- a/src/compile/nodes/Attribute.ts +++ b/src/compile/nodes/Attribute.ts @@ -67,6 +67,7 @@ export default class Attribute extends Node { this.should_cache = this.is_dynamic ? this.chunks.length === 1 + // @ts-ignore todo: probably error ? this.chunks[0].node.type !== 'Identifier' || scope.names.has(this.chunks[0].node.name) : true : false; @@ -91,8 +92,10 @@ export default class Attribute extends Node { if (this.chunks.length === 0) return `""`; if (this.chunks.length === 1) { + 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); } @@ -102,6 +105,7 @@ export default class Attribute extends Node { if (chunk.type === 'Text') { return stringify(chunk.data); } else { + // @ts-ignore todo: probably error return chunk.get_precedence() <= 13 ? `(${chunk.render()})` : chunk.render(); } }) @@ -114,7 +118,8 @@ export default class Attribute extends Node { return this.is_true ? true : this.chunks[0] - ? this.chunks[0].data + // method should be called only when `is_static = true` + ? (this.chunks[0] as Text).data : ''; } } diff --git a/src/compile/nodes/AwaitBlock.ts b/src/compile/nodes/AwaitBlock.ts index f8e6896b5d..cd57750d29 100644 --- a/src/compile/nodes/AwaitBlock.ts +++ b/src/compile/nodes/AwaitBlock.ts @@ -5,6 +5,7 @@ import CatchBlock from './CatchBlock'; import Expression from './shared/Expression'; export default class AwaitBlock extends Node { + type: 'AwaitBlock'; expression: Expression; value: string; error: string; diff --git a/src/compile/nodes/Binding.ts b/src/compile/nodes/Binding.ts index b03eba0c36..0d666a543f 100644 --- a/src/compile/nodes/Binding.ts +++ b/src/compile/nodes/Binding.ts @@ -5,6 +5,7 @@ import Component from '../Component'; import TemplateScope from './shared/TemplateScope'; export default class Binding extends Node { + type: 'Binding'; name: string; expression: Expression; is_contextual: boolean; diff --git a/src/compile/nodes/CatchBlock.ts b/src/compile/nodes/CatchBlock.ts index 23c08a494c..0edc0f76d8 100644 --- a/src/compile/nodes/CatchBlock.ts +++ b/src/compile/nodes/CatchBlock.ts @@ -3,6 +3,7 @@ import TemplateScope from './shared/TemplateScope'; import AbstractBlock from './shared/AbstractBlock'; export default class CatchBlock extends AbstractBlock { + type: 'CatchBlock'; scope: TemplateScope; constructor(component, parent, scope, info) { diff --git a/src/compile/nodes/DebugTag.ts b/src/compile/nodes/DebugTag.ts index 4d2c3f6ae4..0fbfa592ad 100644 --- a/src/compile/nodes/DebugTag.ts +++ b/src/compile/nodes/DebugTag.ts @@ -2,6 +2,7 @@ import Node from './shared/Node'; import Expression from './shared/Expression'; export default class DebugTag extends Node { + type: 'DebugTag'; expressions: Expression[]; constructor(component, parent, scope, info) { @@ -11,4 +12,4 @@ export default class DebugTag extends Node { return new Expression(component, parent, scope, node); }); } -} \ No newline at end of file +} diff --git a/src/compile/nodes/EachBlock.ts b/src/compile/nodes/EachBlock.ts index b58c023ac9..2f18373137 100644 --- a/src/compile/nodes/EachBlock.ts +++ b/src/compile/nodes/EachBlock.ts @@ -6,8 +6,15 @@ import TemplateScope from './shared/TemplateScope'; import AbstractBlock from './shared/AbstractBlock'; import { Node as INode } from '../../interfaces'; 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, node: INode, tail: string) { if (!node) return; if (node.type === 'Identifier' || node.type === 'RestIdentifier') { @@ -53,7 +60,7 @@ export default class EachBlock extends AbstractBlock { context: string; key: Expression; scope: TemplateScope; - contexts: Array<{ name: string, tail: string }>; + contexts: Array; has_animation: boolean; has_binding = false; @@ -82,7 +89,7 @@ export default class EachBlock extends AbstractBlock { if (this.index) { // 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); } @@ -92,8 +99,8 @@ export default class EachBlock extends AbstractBlock { if (this.has_animation) { if (this.children.length !== 1) { - const child = this.children.find(child => !!child.animation); - component.error(child.animation, { + const child = this.children.find(child => !!(child as Element).animation); + component.error((child as Element).animation, { code: `invalid-animation`, message: `An element that use the animate directive must be the sole child of a keyed each block` }); diff --git a/src/compile/nodes/Element.ts b/src/compile/nodes/Element.ts index ac2b81b3e7..1b2d82188c 100644 --- a/src/compile/nodes/Element.ts +++ b/src/compile/nodes/Element.ts @@ -15,6 +15,7 @@ import fuzzymatch from '../../utils/fuzzymatch'; import list from '../../utils/list'; import Let from './Let'; 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)$/; @@ -101,7 +102,7 @@ export default class Element extends Node { intro?: Transition = null; outro?: Transition = null; animation?: Animation = null; - children: Node[]; + children: INode[]; namespace: string; constructor(component, parent, scope, info: any) { @@ -136,7 +137,7 @@ export default class Element extends Node { // Special case — treat these the same way: // // - const value_attribute = info.attributes.find((attribute: Node) => attribute.name === 'value'); + const value_attribute = info.attributes.find(attribute => attribute.name === 'value'); if (!value_attribute) { info.attributes.push({ @@ -228,7 +229,7 @@ export default class Element extends Node { let is_figure_parent = false; while (parent) { - if (parent.name === 'figure') { + if ((parent as Element).name === 'figure') { is_figure_parent = true; break; } @@ -253,7 +254,7 @@ export default class Element extends Node { 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)) { this.component.warn(children[index], { @@ -320,7 +321,9 @@ export default class Element extends Node { } const value = attribute.get_static_value(); + // @ts-ignore if (value && !aria_role_set.has(value)) { + // @ts-ignore const match = fuzzymatch(value, aria_roles); let message = `A11y: Unknown role '${value}'`; if (match) message += ` (did you mean '${match}'?)`; @@ -359,6 +362,7 @@ export default class Element extends Node { // tabindex-no-positive if (name === 'tabindex') { const value = attribute.get_static_value(); + // @ts-ignore todo is tabindex=true correct case? if (!isNaN(value) && +value > 0) { component.warn(attribute, { code: `a11y-positive-tabindex`, @@ -544,7 +548,7 @@ export default class Element extends Node { message: `'group' binding can only be used with or ` }); } - } else if (name == 'files') { + } else if (name === 'files') { if (this.name !== 'input') { component.error(binding, { code: `invalid-binding`, @@ -560,6 +564,14 @@ export default class Element extends Node { message: `'files' binding can only be used with ` }); } + + } else if (name === 'open') { + if (this.name !== 'details') { + component.error(binding, { + code: `invalid-binding`, + message: `'${name}' binding can only be used with
    ` + }); + } } else if ( name === 'currentTime' || name === 'duration' || diff --git a/src/compile/nodes/ElseBlock.ts b/src/compile/nodes/ElseBlock.ts index 61c1aa5455..5f3aa29529 100644 --- a/src/compile/nodes/ElseBlock.ts +++ b/src/compile/nodes/ElseBlock.ts @@ -1,10 +1,11 @@ import map_children from './shared/map_children'; import AbstractBlock from './shared/AbstractBlock'; +import Component from '../Component'; export default class ElseBlock extends AbstractBlock { type: 'ElseBlock'; - constructor(component, parent, scope, info) { + constructor(component: Component, parent, scope, info) { super(component, parent, scope, info); this.children = map_children(component, this, scope, info.children); diff --git a/src/compile/nodes/EventHandler.ts b/src/compile/nodes/EventHandler.ts index f5e7e0e898..dab60858d5 100644 --- a/src/compile/nodes/EventHandler.ts +++ b/src/compile/nodes/EventHandler.ts @@ -5,6 +5,7 @@ import deindent from '../utils/deindent'; import Block from '../render-dom/Block'; export default class EventHandler extends Node { + type: 'EventHandler'; name: string; modifiers: Set; expression: Expression; @@ -65,4 +66,4 @@ export default class EventHandler extends Node { // this.component.add_reference(this.handler_name); return `ctx.${this.handler_name}`; } -} \ No newline at end of file +} diff --git a/src/compile/nodes/Fragment.ts b/src/compile/nodes/Fragment.ts index ec25d41a1c..6025b036a6 100644 --- a/src/compile/nodes/Fragment.ts +++ b/src/compile/nodes/Fragment.ts @@ -3,10 +3,12 @@ import Component from '../Component'; import map_children from './shared/map_children'; import Block from '../render-dom/Block'; import TemplateScope from './shared/TemplateScope'; +import { INode } from './interfaces'; export default class Fragment extends Node { + type: 'Fragment'; block: Block; - children: Node[]; + children: INode[]; scope: TemplateScope; constructor(component: Component, info: any) { @@ -16,4 +18,4 @@ export default class Fragment extends Node { this.scope = scope; this.children = map_children(component, this, scope, info.children); } -} \ No newline at end of file +} diff --git a/src/compile/nodes/Head.ts b/src/compile/nodes/Head.ts index bc6e9bde40..2c08dcd595 100644 --- a/src/compile/nodes/Head.ts +++ b/src/compile/nodes/Head.ts @@ -1,5 +1,4 @@ import Node from './shared/Node'; -import Block from '../render-dom/Block'; import map_children from './shared/map_children'; export default class Head extends Node { diff --git a/src/compile/nodes/InlineComponent.ts b/src/compile/nodes/InlineComponent.ts index 0d8801aad1..8b6cd77282 100644 --- a/src/compile/nodes/InlineComponent.ts +++ b/src/compile/nodes/InlineComponent.ts @@ -7,6 +7,7 @@ import Expression from './shared/Expression'; import Component from '../Component'; import Let from './Let'; import TemplateScope from './shared/TemplateScope'; +import { INode } from './interfaces'; export default class InlineComponent extends Node { type: 'InlineComponent'; @@ -16,15 +17,16 @@ export default class InlineComponent extends Node { bindings: Binding[] = []; handlers: EventHandler[] = []; lets: Let[] = []; - children: Node[]; + children: INode[]; scope: TemplateScope; constructor(component: Component, parent, scope, info) { super(component, parent, scope, info); if (info.name !== 'svelte:component' && info.name !== 'svelte:self') { - component.warn_if_undefined(info, scope); - component.add_reference(info.name); + const name = info.name.split('.')[0]; // accommodate namespaces + component.warn_if_undefined(name, info, scope); + component.add_reference(name); } this.name = info.name; diff --git a/src/compile/nodes/MustacheTag.ts b/src/compile/nodes/MustacheTag.ts index e668987a9c..ac6688d503 100644 --- a/src/compile/nodes/MustacheTag.ts +++ b/src/compile/nodes/MustacheTag.ts @@ -1,3 +1,5 @@ import Tag from './shared/Tag'; -export default class MustacheTag extends Tag {} \ No newline at end of file +export default class MustacheTag extends Tag { + type: 'MustacheTag'; +} diff --git a/src/compile/nodes/PendingBlock.ts b/src/compile/nodes/PendingBlock.ts index 0fd71c0221..5ff7352558 100644 --- a/src/compile/nodes/PendingBlock.ts +++ b/src/compile/nodes/PendingBlock.ts @@ -2,7 +2,7 @@ import map_children from './shared/map_children'; import AbstractBlock from './shared/AbstractBlock'; export default class PendingBlock extends AbstractBlock { - + type: 'PendingBlock'; constructor(component, parent, scope, info) { super(component, parent, scope, info); this.children = map_children(component, parent, scope, info.children); diff --git a/src/compile/nodes/RawMustacheTag.ts b/src/compile/nodes/RawMustacheTag.ts index ada3123410..fc63885942 100644 --- a/src/compile/nodes/RawMustacheTag.ts +++ b/src/compile/nodes/RawMustacheTag.ts @@ -1,3 +1,5 @@ import Tag from './shared/Tag'; -export default class RawMustacheTag extends Tag {} \ No newline at end of file +export default class RawMustacheTag extends Tag { + type: 'RawMustacheTag' +} diff --git a/src/compile/nodes/Slot.ts b/src/compile/nodes/Slot.ts index dbb502b41a..a03fe8c026 100644 --- a/src/compile/nodes/Slot.ts +++ b/src/compile/nodes/Slot.ts @@ -1,17 +1,17 @@ -import Node from './shared/Node'; import Element from './Element'; import Attribute from './Attribute'; import Component from '../Component'; import TemplateScope from './shared/TemplateScope'; +import { INode } from './interfaces'; export default class Slot extends Element { type: 'Element'; name: string; - children: Node[]; + children: INode[]; slot_name: string; values: Map = 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); info.attributes.forEach(attr => { @@ -68,4 +68,4 @@ export default class Slot extends Element { component.slots.set(this.slot_name, this); } -} \ No newline at end of file +} diff --git a/src/compile/nodes/Text.ts b/src/compile/nodes/Text.ts index 1c31c9d83d..7500f5ff30 100644 --- a/src/compile/nodes/Text.ts +++ b/src/compile/nodes/Text.ts @@ -1,13 +1,14 @@ import Node from './shared/Node'; import Component from '../Component'; import TemplateScope from './shared/TemplateScope'; +import { INode } from './interfaces'; export default class Text extends Node { type: 'Text'; data: string; 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); this.data = info.data; @@ -23,4 +24,4 @@ export default class Text extends Node { this.use_space = true; } } -} \ No newline at end of file +} diff --git a/src/compile/nodes/ThenBlock.ts b/src/compile/nodes/ThenBlock.ts index 7e4ed0e5da..7f9bbde0f0 100644 --- a/src/compile/nodes/ThenBlock.ts +++ b/src/compile/nodes/ThenBlock.ts @@ -3,6 +3,7 @@ import TemplateScope from './shared/TemplateScope'; import AbstractBlock from './shared/AbstractBlock'; export default class ThenBlock extends AbstractBlock { + type: 'ThenBlock'; scope: TemplateScope; constructor(component, parent, scope, info) { diff --git a/src/compile/nodes/Title.ts b/src/compile/nodes/Title.ts index fd58d3043d..6ac0848053 100644 --- a/src/compile/nodes/Title.ts +++ b/src/compile/nodes/Title.ts @@ -1,12 +1,13 @@ 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 { type: 'Title'; - children: any[]; // TODO + children: Children; should_cache: boolean; - constructor(component, parent, scope, info) { + constructor(component: Component, parent, scope, info) { super(component, parent, scope, info); this.children = map_children(component, parent, scope, info.children); @@ -33,4 +34,4 @@ export default class Title extends Node { ) : true; } -} \ No newline at end of file +} diff --git a/src/compile/nodes/Transition.ts b/src/compile/nodes/Transition.ts index c3f22d888e..82eb578f0f 100644 --- a/src/compile/nodes/Transition.ts +++ b/src/compile/nodes/Transition.ts @@ -12,7 +12,7 @@ export default class Transition extends Node { constructor(component: Component, parent, scope, info) { super(component, parent, scope, info); - component.warn_if_undefined(info, scope); + component.warn_if_undefined(info.name, info, scope); this.name = info.name; component.qualify(info.name); diff --git a/src/compile/nodes/interfaces.ts b/src/compile/nodes/interfaces.ts new file mode 100644 index 0000000000..434b09e5aa --- /dev/null +++ b/src/compile/nodes/interfaces.ts @@ -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; diff --git a/src/compile/nodes/shared/AbstractBlock.ts b/src/compile/nodes/shared/AbstractBlock.ts index 1dfebd51f0..e1104e4928 100644 --- a/src/compile/nodes/shared/AbstractBlock.ts +++ b/src/compile/nodes/shared/AbstractBlock.ts @@ -1,10 +1,11 @@ import Block from '../../render-dom/Block'; import Component from './../../Component'; import Node from './Node'; +import { INode } from '../interfaces'; export default class AbstractBlock extends Node { block: Block; - children: Node[]; + children: INode[]; constructor(component: Component, parent, scope, info: any) { super(component, parent, scope, info); diff --git a/src/compile/nodes/shared/Expression.ts b/src/compile/nodes/shared/Expression.ts index 22cb403f75..e7c63dfec2 100644 --- a/src/compile/nodes/shared/Expression.ts +++ b/src/compile/nodes/shared/Expression.ts @@ -12,6 +12,7 @@ import TemplateScope from './TemplateScope'; import get_object from '../../utils/get_object'; import { nodes_match } from '../../../utils/nodes_match'; import Block from '../../render-dom/Block'; +import { INode } from '../interfaces'; const binary_operators: Record = { '**': 15, @@ -61,10 +62,12 @@ const precedence: Record number> = { SequenceExpression: () => 0 }; +type Owner = Wrapper | INode; + export default class Expression { - type = 'Expression'; + type: 'Expression' = 'Expression'; component: Component; - owner: Wrapper; + owner: Owner; node: any; snippet: string; references: Set; @@ -81,7 +84,8 @@ export default class Expression { 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? Object.defineProperties(this, { component: { @@ -92,6 +96,7 @@ export default class Expression { this.node = info; this.template_scope = template_scope; this.owner = owner; + // @ts-ignore this.is_synthetic = owner.is_synthetic; const { dependencies, contextual_dependencies } = this; @@ -149,7 +154,7 @@ export default class Expression { } component.add_reference(name); - component.warn_if_undefined(nodes[0], template_scope); + component.warn_if_undefined(name, nodes[0], template_scope); } this.skip(); @@ -218,7 +223,7 @@ export default class Expression { } // TODO move this into a render-dom wrapper? - render(block: Block) { + render(block?: Block) { if (this.rendered) return this.rendered; const { @@ -510,4 +515,4 @@ function is_contextual(component: Component, scope: TemplateScope, name: string) // assume contextual return true; -} \ No newline at end of file +} diff --git a/src/compile/nodes/shared/Node.ts b/src/compile/nodes/shared/Node.ts index b6eaf9965d..b647e3a158 100644 --- a/src/compile/nodes/shared/Node.ts +++ b/src/compile/nodes/shared/Node.ts @@ -1,15 +1,17 @@ import Attribute from './../Attribute'; import Component from './../../Component'; +import { INode } from '../interfaces'; +import Text from '../Text'; export default class Node { readonly start: number; readonly end: number; readonly component: Component; - readonly parent: Node; + readonly parent: INode; readonly type: string; - prev?: Node; - next?: Node; + prev?: INode; + next?: INode; can_use_innerhtml: boolean; var: string; @@ -55,7 +57,7 @@ export default class Node { if (attribute.chunks.length === 0) return ''; if (attribute.chunks.length === 1 && attribute.chunks[0].type === 'Text') { - return attribute.chunks[0].data; + return (attribute.chunks[0] as Text).data; } return null; diff --git a/src/compile/nodes/shared/Tag.ts b/src/compile/nodes/shared/Tag.ts index 94971bef11..bc826458d9 100644 --- a/src/compile/nodes/shared/Tag.ts +++ b/src/compile/nodes/shared/Tag.ts @@ -2,6 +2,7 @@ import Node from './Node'; import Expression from './Expression'; export default class Tag extends Node { + type: 'MustacheTag' | 'RawMustacheTag'; expression: Expression; should_cache: boolean; @@ -14,4 +15,4 @@ export default class Tag extends Node { (this.expression.dependencies.size && scope.names.has(info.expression.name)) ); } -} \ No newline at end of file +} diff --git a/src/compile/nodes/shared/TemplateScope.ts b/src/compile/nodes/shared/TemplateScope.ts index abd366642e..5f30d0c883 100644 --- a/src/compile/nodes/shared/TemplateScope.ts +++ b/src/compile/nodes/shared/TemplateScope.ts @@ -2,6 +2,7 @@ import EachBlock from '../EachBlock'; import ThenBlock from '../ThenBlock'; import CatchBlock from '../CatchBlock'; import InlineComponent from '../InlineComponent'; +import Element from '../Element'; type NodeWithScope = EachBlock | ThenBlock | CatchBlock | InlineComponent | Element; @@ -41,4 +42,4 @@ export default class TemplateScope { const owner = this.get_owner(name); return owner && (owner.type === 'Element' || owner.type === 'InlineComponent'); } -} \ No newline at end of file +} diff --git a/src/compile/nodes/shared/map_children.ts b/src/compile/nodes/shared/map_children.ts index b903853016..71d764a889 100644 --- a/src/compile/nodes/shared/map_children.ts +++ b/src/compile/nodes/shared/map_children.ts @@ -14,9 +14,11 @@ import Slot from '../Slot'; import Text from '../Text'; import Title from '../Title'; import Window from '../Window'; -import Node from './Node'; +import { Node } from '../../../interfaces'; -function get_constructor(type): typeof Node { +export type Children = ReturnType; + +function get_constructor(type) { switch (type) { case 'AwaitBlock': return AwaitBlock; 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; return children.map(child => { const constructor = get_constructor(child.type); diff --git a/src/compile/render-dom/Block.ts b/src/compile/render-dom/Block.ts index e40b3ceb55..531826edcb 100644 --- a/src/compile/render-dom/Block.ts +++ b/src/compile/render-dom/Block.ts @@ -9,7 +9,7 @@ export interface BlockOptions { renderer?: Renderer; comment?: string; key?: string; - bindings?: Map { object: string, property: string, snippet: string }>; + bindings?: Map; dependencies?: Set; } diff --git a/src/compile/render-dom/Renderer.ts b/src/compile/render-dom/Renderer.ts index 1d766c6345..ea07c1544f 100644 --- a/src/compile/render-dom/Renderer.ts +++ b/src/compile/render-dom/Renderer.ts @@ -3,7 +3,6 @@ import { CompileOptions } from '../../interfaces'; import Component from '../Component'; import FragmentWrapper from './wrappers/Fragment'; import CodeBuilder from '../utils/CodeBuilder'; -import SlotWrapper from './wrappers/Slot'; export default class Renderer { component: Component; // TODO Maybe Renderer shouldn't know about Component? @@ -18,6 +17,7 @@ export default class Renderer { fragment: FragmentWrapper; file_var: string; + locate: (c: number) => { line: number; column: number; }; constructor(component: Component, options: CompileOptions) { this.component = component; @@ -58,4 +58,4 @@ export default class Renderer { this.fragment.render(this.block, null, 'nodes'); } -} \ No newline at end of file +} diff --git a/src/compile/render-dom/index.ts b/src/compile/render-dom/index.ts index 0a0743b2a0..1432813e9d 100644 --- a/src/compile/render-dom/index.ts +++ b/src/compile/render-dom/index.ts @@ -134,7 +134,6 @@ export default function dom( }); if (component.compile_options.dev) { - // TODO check no uunexpected props were passed, as well as // checking that expected ones were passed const expected = props.filter(prop => !prop.initialised); @@ -364,7 +363,7 @@ export default function dom( } const variable = component.var_lookup.get(n); - return variable && variable.writable; + return variable && (variable.writable || variable.mutated); }) .map(n => `$$dirty.${n}`).join(' || '); @@ -395,6 +394,16 @@ export default function dom( 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` function ${definition}(${args.join(', ')}) { ${reactive_store_declarations.length > 0 && `let ${reactive_store_declarations.join(', ')};`} @@ -405,6 +414,8 @@ export default function dom( ${component.javascript} + ${unknown_props_check} + ${component.slots.size && `let { $$slots = {}, $$scope } = $$props;`} ${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')} } - - customElements.define("${component.tag}", ${name}); `); + + if (component.tag != null) { + builder.add_block(deindent` + customElements.define("${component.tag}", ${name}); + `); + } } else { const superclass = options.dev ? 'SvelteComponentDev' : 'SvelteComponent'; diff --git a/src/compile/render-dom/wrappers/DebugTag.ts b/src/compile/render-dom/wrappers/DebugTag.ts index 06fef90a62..bdad6d2493 100644 --- a/src/compile/render-dom/wrappers/DebugTag.ts +++ b/src/compile/render-dom/wrappers/DebugTag.ts @@ -25,7 +25,7 @@ export default class DebugTagWrapper extends Wrapper { if (!renderer.options.dev) return; - const { code } = component; + const { code, var_lookup } = component; if (this.node.expressions.length === 0) { // Debug all @@ -50,23 +50,30 @@ export default class DebugTagWrapper extends Wrapper { 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` if (${condition}) { - const { ${identifiers} } = ctx; - console.${log}({ ${identifiers} }); + const { ${ctx_identifiers} } = ctx; + console.${log}({ ${logged_identifiers} }); debugger; } `); block.builders.create.add_block(deindent` { - const { ${identifiers} } = ctx; - console.${log}({ ${identifiers} }); + const { ${ctx_identifiers} } = ctx; + console.${log}({ ${logged_identifiers} }); debugger; } `); } } -} \ No newline at end of file +} diff --git a/src/compile/render-dom/wrappers/EachBlock.ts b/src/compile/render-dom/wrappers/EachBlock.ts index fe5d5746e5..9208c838ad 100644 --- a/src/compile/render-dom/wrappers/EachBlock.ts +++ b/src/compile/render-dom/wrappers/EachBlock.ts @@ -8,7 +8,7 @@ import deindent from '../../utils/deindent'; import ElseBlock from '../../nodes/ElseBlock'; import { attach_head } from '../../utils/tail'; -class ElseBlockWrapper extends Wrapper { +export class ElseBlockWrapper extends Wrapper { node: ElseBlock; block: Block; fragment: FragmentWrapper; @@ -83,6 +83,7 @@ export default class EachBlockWrapper extends Wrapper { this.block = block.child({ comment: create_debugging_comment(this.node, this.renderer.component), name: renderer.component.get_unique_name('create_each_block'), + // @ts-ignore todo: probably error key: node.key as string, bindings: new Map(block.bindings) @@ -310,7 +311,9 @@ export default class EachBlockWrapper extends Wrapper { } 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) { let child_ctx = ${this.vars.get_each_context}(ctx, ${this.vars.each_block_value}, #i); diff --git a/src/compile/render-dom/wrappers/Element/Attribute.ts b/src/compile/render-dom/wrappers/Element/Attribute.ts index 9841f4e85d..876496e2f6 100644 --- a/src/compile/render-dom/wrappers/Element/Attribute.ts +++ b/src/compile/render-dom/wrappers/Element/Attribute.ts @@ -4,6 +4,7 @@ import fix_attribute_casing from './fix_attribute_casing'; import ElementWrapper from './index'; import { stringify } from '../../../utils/stringify'; import deindent from '../../../utils/deindent'; +import Expression from '../../../nodes/shared/Expression'; export default class AttributeWrapper { node: Attribute; @@ -21,7 +22,9 @@ export default class AttributeWrapper { // special case —