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..f87b3610df 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.1.0", + "version": "3.4.2", "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 1472ff3d6c..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 diff --git a/site/content/docs/02-template-syntax.md b/site/content/docs/02-template-syntax.md index c6fd5c8b2d..167d1fa3a2 100644 --- a/site/content/docs/02-template-syntax.md +++ b/site/content/docs/02-template-syntax.md @@ -351,6 +351,24 @@ If the `on:` directive is used without a value, the component will *forward* the ``` +--- + +It's possible to have multiple event listeners for the same event: + +```html + + + +``` ### Component events @@ -1261,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/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 e8637c98c3..faba1dd062 100644 --- a/site/content/examples/10-animations/00-animate/App.svelte +++ b/site/content/examples/10-animations/00-animate/App.svelte @@ -1,6 +1,6 @@
- +

todo

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/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 138639ad28..d9de5a217e 100644 --- a/site/package.json +++ b/site/package.json @@ -38,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", @@ -48,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", @@ -56,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 dd41a0a645..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,7 +760,7 @@ export default class Component { }); } - if (is_reference(node, parent)) { + if (is_reference(node as ESTreeNode, parent as ESTreeNode)) { const object = get_object(node); const { name } = object; @@ -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); } @@ -1265,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/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 3359e981ed..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,7 +17,7 @@ export default class InlineComponent extends Node { bindings: Binding[] = []; handlers: EventHandler[] = []; lets: Let[] = []; - children: Node[]; + children: INode[]; scope: TemplateScope; constructor(component: Component, parent, scope, info) { 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/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 fc188e9673..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; @@ -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 —