diff --git a/.flowconfig b/.flowconfig deleted file mode 100644 index c1961b7a6b..0000000000 --- a/.flowconfig +++ /dev/null @@ -1,9 +0,0 @@ -[ignore] -/types/.* - -[include] - -[libs] - -[options] -strip_root=true diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index eb49e78156..0000000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.svelte linguist-language=HTML diff --git a/.gitignore b/.gitignore index 4d7bbc7ac3..923dd5901e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ node_modules *.map /src/compiler/compile/internal-exports.ts +/compiler.d.ts /compiler.*js /index.*js /internal diff --git a/appveyor.yml b/appveyor.yml index 249f61abf4..23a3ac3505 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,12 +9,13 @@ init: environment: matrix: - # node.js + - nodejs_version: 8 - nodejs_version: 10 + - nodejs_version: 12 install: - - ps: Install-Product node $env:nodejs_version - - npm install + - ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) + - npm ci || npm install build: off diff --git a/compiler.d.ts b/compiler.d.ts deleted file mode 100644 index e2a3820bc5..0000000000 --- a/compiler.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './types/compiler'; diff --git a/package-lock.json b/package-lock.json index f1e8bf1d32..aea08689b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.4.4", + "version": "3.5.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -30,16 +30,6 @@ "integrity": "sha512-UdVB1rSL7H8TS8674fH02p5lRbhfIqQ18YKLxLKEnHFztHUH6bhMqjebMxgSTmWVrs5raS5JSLJIKKHFT4WfPg==", "dev": true }, - "@sveltejs/svelte-repl": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.0.5.tgz", - "integrity": "sha512-SKSX4xkqwH0XcUHQozwTNm3OCqatk66CXYZnqOW9Jf4E1B6opyQUb9f96KwAxh7ghZMbeePRv51oOWsw6n0Yww==", - "dev": true, - "requires": { - "codemirror": "^5.45.0", - "yootils": "0.0.15" - } - }, "@types/estree": { "version": "0.0.39", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", @@ -59,9 +49,9 @@ "dev": true }, "@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==", + "version": "8.10.49", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.49.tgz", + "integrity": "sha512-YX30JVx0PvSmJ3Eqr74fYLGeBxD+C7vIL20ek+GGGLJeUbVYRUW3EzyAXpIRA0K8c8o0UWqR/GwEFYiFoz1T8w==", "dev": true }, "@typescript-eslint/eslint-plugin": { @@ -650,12 +640,6 @@ "urlgrey": "^0.4.4" } }, - "codemirror": { - "version": "5.45.0", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.45.0.tgz", - "integrity": "sha512-c19j644usCE8gQaXa0jqn2B/HN9MnB2u6qPIrrhrMkB+QAP42y8G4QnTwuwbVSoUS1jEl7JU9HZMGhCDL0nsAw==", - "dev": true - }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -4750,12 +4734,6 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.0.0.tgz", "integrity": "sha512-+Wo/p5VRfxUgBUGy2j/6KX2mj9AYJWOHuhMjMcbBFc3y54o9/4buK1ksBvuiK01C3kby8DH9lSmJdSxw+4G/2Q==", "dev": true - }, - "yootils": { - "version": "0.0.15", - "resolved": "https://registry.npmjs.org/yootils/-/yootils-0.0.15.tgz", - "integrity": "sha512-GvGLuJ7XHJPGEUQ52vh8fh+vPjfikuGcu7yBswfrsNsHqnAoytOVuSb69eM0j8wQIjMz0U3kY3YsfwMhJgfG9w==", - "dev": true } } } diff --git a/package.json b/package.json index 48f2c41d85..37bd6f75e7 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,10 @@ "engines": { "node": ">= 8" }, - "types": "types/runtime", + "types": "types/runtime/index.d.ts", "scripts": { "test": "mocha --opts mocha.opts", - "test:unit": "mocha --require sucrase/register --recursive ./**/__test__.ts", + "test:unit": "mocha --require sucrase/register --recursive src/**/__test__.ts", "quicktest": "mocha --opts mocha.opts", "precoverage": "c8 mocha --opts mocha.coverage.opts", "coverage": "c8 report --reporter=text-lcov > coverage.lcov && c8 report --reporter=html", @@ -35,10 +35,8 @@ "dev": "rollup -cw", "pretest": "npm run build", "posttest": "agadoo internal/index.mjs", - "prepublishOnly": "export PUBLISH=true && npm test && npm run create-stubs", - "create-stubs": "node scripts/create-stubs.js", - "tsd": "tsc -p . --emitDeclarationOnly", - "typecheck": "tsc -p . --noEmit", + "prepublishOnly": "PUBLISH=true npm test", + "tsd": "tsc -p src/compiler --emitDeclarationOnly && tsc -p src/runtime --emitDeclarationOnly", "lint": "eslint \"{src,test}/**/*.{ts,js}\"" }, "repository": { @@ -58,9 +56,8 @@ }, "homepage": "https://github.com/sveltejs/svelte#README", "devDependencies": { - "@sveltejs/svelte-repl": "0.0.5", "@types/mocha": "^5.2.0", - "@types/node": "^10.5.5", + "@types/node": "=8", "@typescript-eslint/eslint-plugin": "^1.9.0", "@typescript-eslint/parser": "^1.9.0", "acorn": "^6.1.1", diff --git a/rollup.config.js b/rollup.config.js index 8907ae4e6c..fb329534a2 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -20,6 +20,8 @@ const ts_plugin = is_publish const external = id => id.startsWith('svelte/'); +fs.writeFileSync(`./compiler.d.ts`, `export * from './types/compiler/index';`); + export default [ /* runtime */ { @@ -59,12 +61,22 @@ export default [ external, plugins: [ ts_plugin, - dir === 'internal' && { - generateBundle(options, bundle) { - const mod = bundle['index.mjs']; - if (mod) { - fs.writeFileSync('src/compiler/compile/internal-exports.ts', `// This file is automatically generated\nexport default new Set(${JSON.stringify(mod.exports)});`); + { + writeBundle(bundle) { + if (dir === 'internal') { + const mod = bundle['index.mjs']; + if (mod) { + fs.writeFileSync('src/compiler/compile/internal-exports.ts', `// This file is automatically generated\nexport default new Set(${JSON.stringify(mod.exports)});`); + } } + + fs.writeFileSync(`${dir}/package.json`, JSON.stringify({ + main: './index', + module: './index.mjs', + types: './index.d.ts' + }, null, ' ')); + + fs.writeFileSync(`${dir}/index.d.ts`, `export * from '../types/runtime/${dir}/index';`); } } ] diff --git a/scripts/create-stubs.js b/scripts/create-stubs.js deleted file mode 100644 index e69e3f5e20..0000000000 --- a/scripts/create-stubs.js +++ /dev/null @@ -1,12 +0,0 @@ -const fs = require('fs'); - -fs.readdirSync('src/runtime') - .filter(dir => fs.statSync(`src/runtime/${dir}`).isDirectory()) - .forEach(dir => { - fs.writeFileSync(`${dir}/package.json`, JSON.stringify({ - main: './index', - module: './index.mjs' - }, null, ' ')); - - fs.writeFileSync(`${dir}/index.d.ts`, `export * from '../types/runtime/${dir}/index.d.ts';`); - }); \ No newline at end of file diff --git a/site/content/docs/02-template-syntax.md b/site/content/docs/02-template-syntax.md index aad7e3fc19..a6e17f8bc2 100644 --- a/site/content/docs/02-template-syntax.md +++ b/site/content/docs/02-template-syntax.md @@ -101,27 +101,7 @@ Text can also contain JavaScript expressions: ``` -### HTML expressions - -```sv -{@html expression} -``` - ---- - -In a text expression, characters like `<` and `>` are escaped. With HTML expressions, they're not. - -> Svelte does not sanitize expressions before injecting HTML. If the data comes from an untrusted source, you must sanitize it, or you are exposing your users to an XSS vulnerability. - -```html -
-

{post.title}

- {@html post.content} -
-``` - - -### If blocks +### {#if ...} ```sv {#if expression}...{/if} @@ -158,7 +138,7 @@ Additional conditions can be added with `{:else if expression}`, optionally endi ``` -### Each blocks +### {#each ...} ```sv {#each expression as name}...{/each} @@ -229,7 +209,7 @@ An each block can also have an `{:else}` clause, which is rendered if the list i ``` -### Await blocks +### {#await ...} ```sv {#await expression}...{:then name}...{:catch name}...{/await} @@ -283,7 +263,80 @@ If you don't care about the pending state, you can also omit the initial block. ``` -### DOM events +### {@html ...} + +```sv +{@html expression} +``` + +--- + +In a text expression, characters like `<` and `>` are escaped. With HTML expressions, they're not. + +> Svelte does not sanitize expressions before injecting HTML. If the data comes from an untrusted source, you must sanitize it, or you are exposing your users to an XSS vulnerability. + +```html +
+

{post.title}

+ {@html post.content} +
+``` + + +### {@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. + + + +### Element directives + +As well as attributes, elements can have *directives*, which control the element's behaviour in some way. + + +#### [on:*eventname*](on_component_event) ```sv on:eventname={handler} @@ -324,6 +377,13 @@ Handlers can be declared inline with no performance penalty. As with attributes, Add *modifiers* to DOM events with the `|` character. +```html +
+ +
+``` + The following modifiers are available: * `preventDefault` — calls `event.preventDefault()` before running the handler @@ -334,13 +394,6 @@ The following modifiers are available: Modifiers can be chained together, e.g. `on:click|once|capture={...}`. -```html -
- -
-``` - --- If the `on:` directive is used without a value, the component will *forward* the event, meaning that a consumer of the component can listen for it. @@ -370,39 +423,11 @@ It's possible to have multiple event listeners for the same event: ``` -### Component events - -```sv -on:eventname={handler} -``` - ---- - -Components can emit events using [createEventDispatcher](docs#createEventDispatcher), or by forwarding DOM events. Listening for component events looks the same as listening for DOM events: - -```html - -``` - ---- - -As with DOM events, if the `on:` directive is used without a value, the component will *forward* the event, meaning that a consumer of the component can listen for it. - -```html - -``` - -### Element bindings +#### [bind:*property*](bind_element_property) ```sv bind:property={variable} ``` -```sv -bind:group={variable} -``` -```sv -bind:this={dom_node} -``` --- @@ -436,31 +461,8 @@ Numeric input values are coerced; even though `input.value` is a string as far a ``` -#### Binding related elements ---- - -Inputs that work together can use `bind:group`. - -```html - - - - - - - - - - - - -``` - -#### Binding `` value --- @@ -500,7 +502,7 @@ When the value of an `